diff --git a/Makefile b/Makefile index d8dfe2f2..142cf02b 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,8 @@ SIM_SERV_DIRS = \ ${TRICK_HOME}/trick_source/sim_services/SimTime \ ${TRICK_HOME}/trick_source/sim_services/ThreadBase \ ${TRICK_HOME}/trick_source/sim_services/Timer \ - ${TRICK_HOME}/trick_source/sim_services/Units \ + ${TRICK_HOME}/trick_source/sim_services/UdUnits \ + ${TRICK_HOME}/trick_source/sim_services/UnitsMap \ ${TRICK_HOME}/trick_source/sim_services/VariableServer \ ${TRICK_HOME}/trick_source/sim_services/Zeroconf \ ${TRICK_HOME}/trick_source/sim_services/include \ diff --git a/include/trick/UdUnits.hh b/include/trick/UdUnits.hh new file mode 100644 index 00000000..8f73fc5c --- /dev/null +++ b/include/trick/UdUnits.hh @@ -0,0 +1,21 @@ + +#ifndef UDUNITS_HH +#define UDUNITS_HH + +#include +#include + +namespace Trick { + +class UdUnits { + public: + static ut_system * get_u_system() ; + int read_default_xml() ; + int read_user_xml(std::string) ; + + protected: + static ut_system * u_system ; // ** system of units +} ; + +} +#endif diff --git a/include/trick/files_to_ICG.hh b/include/trick/files_to_ICG.hh index 9ec09805..0bf71d6e 100644 --- a/include/trick/files_to_ICG.hh +++ b/include/trick/files_to_ICG.hh @@ -82,6 +82,7 @@ #include "trick/StripChart.hh" #include "trick/RtiStager.hh" #include "trick/RtiExec.hh" +#include "trick/UdUnits.hh" #include "trick/UnitsMap.hh" #include "trick/Zeroconf.hh" #include "trick/Flag.h" diff --git a/include/trick/swig/swig_class_typedef.i b/include/trick/swig/swig_class_typedef.i index 3273623b..de549175 100644 --- a/include/trick/swig/swig_class_typedef.i +++ b/include/trick/swig/swig_class_typedef.i @@ -41,7 +41,7 @@ t->ref.num_index_left = 1 ; t->ref.ref_type = REF_ADDRESS ; - t->ref.attr->units = strdup("--") ; + t->ref.attr->units = strdup("1") ; //cout << "returning a structured swig_ref" << std::endl ; $result = SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIG_TypeQuery("_p_swig_ref"), SWIG_POINTER_OWN); @@ -101,7 +101,7 @@ t->ref.attr->num_index = 2 ; t->ref.attr->index[0].size = $1_dim0 ; t->ref.attr->index[1].size = 0 ; - t->ref.attr->units = strdup("--") ; + t->ref.attr->units = strdup("1") ; t->ref.create_add_path = 0 ; t->ref.num_index = 0 ; @@ -140,7 +140,7 @@ t->ref.num_index_left = 2 ; t->ref.ref_type = REF_ADDRESS ; - t->ref.attr->units = strdup("--") ; + t->ref.attr->units = strdup("1") ; $result = SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIG_TypeQuery("_p_swig_ref"), SWIG_POINTER_OWN); } @@ -179,7 +179,7 @@ t->ref.num_index_left = 2 ; t->ref.ref_type = REF_ADDRESS ; - t->ref.attr->units = strdup("--") ; + t->ref.attr->units = strdup("1") ; //cout << "returning a structured swig_ref" << std::endl ; $result = SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIG_TypeQuery("_p_swig_ref"), SWIG_POINTER_OWN); diff --git a/include/trick/swig/swig_int_templates.hh b/include/trick/swig/swig_int_templates.hh index cdf8a83d..eae4402e 100644 --- a/include/trick/swig/swig_int_templates.hh +++ b/include/trick/swig/swig_int_templates.hh @@ -6,18 +6,32 @@ #ifndef SWIG_INT_TEMPLATES_HH #define SWIG_INT_TEMPLATES_HH +#include "trick/UdUnits.hh" +#include + template< class S , typename T > static int convert_and_set( T & output , void * my_argp , std::string to_units ) { int ret = 0 ; S * temp_m = reinterpret_cast< S * >(my_argp) ; - if ( temp_m->units.compare("--") ) { - try { - Unit converter(temp_m->units.c_str()) ; - output = (T)converter.Convert_to( temp_m->value , to_units.c_str()) ; + if ( temp_m->units.compare("1") ) { + ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), temp_m->units.c_str(), UT_ASCII) ; + if ( !from ) { + PyErr_SetString(PyExc_AttributeError,(std::string("could not covert from units "+temp_m->units).c_str())); + return -1 ; } - catch (Unit::CONVERSION_ERROR & ce_err ) { - PyErr_SetString(PyExc_TypeError,"Units conversion error"); - ret = -1; + ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), to_units.c_str(), UT_ASCII) ; + if ( !to ) { + PyErr_SetString(PyExc_AttributeError,(std::string("could not covert to units "+to_units).c_str())); + return -1 ; + } + + cv_converter * converter = ut_get_converter(from,to) ; + if ( converter ) { + output = (T)cv_convert_double(converter, temp_m->value ) ; + cv_free(converter) ; + } else { + PyErr_SetString(PyExc_AttributeError,"Units conversion Error"); + return -1 ; } } else { output = (T)temp_m->value ; diff --git a/include/trick/swig/units_attach.i b/include/trick/swig/units_attach.i index bede4d08..286d8c5a 100644 --- a/include/trick/swig/units_attach.i +++ b/include/trick/swig/units_attach.i @@ -5,8 +5,12 @@ #define UNITS_ATTACH_I %inline %{ -#include "trick/Unit.hh" +#include +#include #include "trick/swig/swig_double.hh" + +std::string map_trick_units_to_udunits( std::string orig_units ) ; + %} %inline %{ @@ -19,6 +23,19 @@ PyObject * attach_units(PyObject * in_units_obj , PyObject * in_object) { if ( PyString_Check(in_units_obj) ) { in_units = PyString_AsString(in_units_obj) ; + std::string new_units = map_trick_units_to_udunits(in_units) ; + if ( in_units.compare(new_units) ) { + PyThreadState *tstate = PyThreadState_GET(); + std::string file_name ; + int line_no = 0 ; + if (NULL != tstate && NULL != tstate->frame) { + file_name = PyString_AsString(tstate->frame->f_code->co_filename); + line_no = PyFrame_GetLineNumber(tstate->frame) ; + } + std::cout << "\033[31mUnits converted from [" << in_units << "] to [" << new_units << "] " + << file_name << ":" << line_no << "\033[0m" << std::endl ; + in_units = new_units ; + } } if ( PyList_Check(in_object)) { @@ -32,19 +49,62 @@ PyObject * attach_units(PyObject * in_units_obj , PyObject * in_object) { result_obj = SWIG_NewPointerObj(SWIG_as_voidptr(container), SWIG_TypeQuery("swig_double *") , SWIG_POINTER_OWN); } else if ( SWIG_IsOK(SWIG_ConvertPtr(in_object, &my_argp,SWIG_TypeQuery("swig_double *"), 0 ))) { swig_double * temp_m = reinterpret_cast< swig_double * >(my_argp) ; - if ( temp_m->units.compare("--") ) { - try { - Unit converter(temp_m->units.c_str()) ; - temp_m->value = converter.Convert_to( temp_m->value , in_units.c_str()) ; + if ( temp_m->units.compare("1") ) { + ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), temp_m->units.c_str(), UT_ASCII) ; + if ( !from ) { + PyErr_SetString(PyExc_AttributeError,(std::string("could not covert from units "+temp_m->units).c_str())); + return NULL ; + } + ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), in_units.c_str(), UT_ASCII) ; + if ( !to ) { + PyErr_SetString(PyExc_AttributeError,(std::string("could not covert to units "+in_units).c_str())); + return NULL ; + } + + cv_converter * converter = ut_get_converter(from,to) ; + if ( converter ) { + temp_m->value = cv_convert_double(converter, temp_m->value ) ; temp_m->units = in_units ; + cv_free(converter) ; + } else { + PyErr_SetString(PyExc_AttributeError,"Units conversion Error"); + return NULL ; } - catch (Unit::CONVERSION_ERROR & ce_err ) { - PyErr_SetString(PyExc_TypeError,"improper units conversion"); - return NULL; - } + ut_free(from) ; + ut_free(to) ; + } else { + temp_m->units = in_units ; } result_obj = SWIG_NewPointerObj(SWIG_as_voidptr(new swig_double(*temp_m)), SWIG_TypeQuery("swig_double *") , SWIG_POINTER_OWN); + } else if ( SWIG_IsOK(SWIG_ConvertPtr(in_object, &my_argp,SWIG_TypeQuery("swig_int *"), 0 ))) { + swig_int * temp_m = reinterpret_cast< swig_int * >(my_argp) ; + if ( temp_m->units.compare("1") ) { + ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), temp_m->units.c_str(), UT_ASCII) ; + if ( !from ) { + PyErr_SetString(PyExc_AttributeError,(std::string("could not covert from units "+temp_m->units).c_str())); + return NULL ; + } + ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), in_units.c_str(), UT_ASCII) ; + if ( !to ) { + PyErr_SetString(PyExc_AttributeError,(std::string("could not covert to units "+in_units).c_str())); + return NULL ; + } + cv_converter * converter = ut_get_converter(from,to) ; + if ( converter ) { + temp_m->value = (long long)cv_convert_double(converter, (double)temp_m->value ) ; + temp_m->units = in_units ; + cv_free(converter) ; + } else { + PyErr_SetString(PyExc_AttributeError,"Units conversion Error"); + return NULL ; + } + ut_free(from) ; + ut_free(to) ; + } else { + temp_m->units = in_units ; + } + result_obj = SWIG_NewPointerObj(SWIG_as_voidptr(new swig_int(*temp_m)), SWIG_TypeQuery("swig_int *") , SWIG_POINTER_OWN); } else if ( PyTuple_Check(in_object)) { unsigned int size = PyTuple_Size(in_object) ; result_obj = PyTuple_New(size) ; diff --git a/libexec/trick/pm/gte.pm b/libexec/trick/pm/gte.pm index 3e9ed4e9..36a40b31 100644 --- a/libexec/trick/pm/gte.pm +++ b/libexec/trick/pm/gte.pm @@ -87,6 +87,7 @@ sub gte (@) { $def{"TRICK_GTE_EXT"} = "" ; $def{"TRICK_HOME"} = "$trick_home" ; $def{"TRICK_HOST_CPU_USER_SUFFIX"} = "" ; + $def{"TRICK_ICGFLAGS"} = "" ; $def{"TRICK_ICG_NOCOMMENT"} = "" ; $def{"TRICK_ICG_EXCLUDE"} = "" ; $def{"TRICK_SWIG_EXCLUDE"} = "" ; diff --git a/share/trick/makefiles/Makefile.common b/share/trick/makefiles/Makefile.common index 7b74b363..8682b211 100644 --- a/share/trick/makefiles/Makefile.common +++ b/share/trick/makefiles/Makefile.common @@ -39,7 +39,7 @@ export TRICK_SWIG_EXCLUDE export TRICK_EXT_LIB_DIRS export TRICK_GTE_EXT export TRICK_HOST_CPU := $(shell export TRICK_CC=$(TRICK_CC) && $(TRICK_HOME)/bin/trick-gte TRICK_HOST_CPU) -export TRICK_EXEC_LINK_LIBS = ${PTHREAD_LIBS} $(PYTHON_LIB) $(PLATFORM_LIBS) -lm -ldl -lz +export TRICK_EXEC_LINK_LIBS = ${PTHREAD_LIBS} $(PYTHON_LIB) $(PLATFORM_LIBS) -lm -ldl -lz -ludunits2 export TRICK_LIBS = ${RPATH} -L${TRICK_LIB_DIR} -ltrick -ltrick_pyip -ltrick_comm -ltrick_math -ltrick_units -ltrick_mm export TRICK_SYSTEM_CFLAGS export TRICK_SYSTEM_CXXFLAGS diff --git a/share/trick/makefiles/Makefile.sim b/share/trick/makefiles/Makefile.sim index 849cfa32..5f8b82e3 100644 --- a/share/trick/makefiles/Makefile.sim +++ b/share/trick/makefiles/Makefile.sim @@ -52,15 +52,15 @@ S_source.hh $(CURDIR)/build/S_define.lib_deps : S_define | build # Automatic and manual ICG rules $(CURDIR)/build/Makefile_io_src : | S_source.hh $(PRINT_ICG) - $(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -m ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} S_source.hh + $(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -m ${TRICK_ICGFLAGS} ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} S_source.hh ICG: $(PRINT_ICG) - $(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -m ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} S_source.hh + $(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -m ${TRICK_ICGFLAGS} ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} S_source.hh force_ICG: $(PRINT_ICG) - $(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -f -m ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} S_source.hh + $(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -f -m ${TRICK_ICGFLAGS} ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} S_source.hh # Build dependencies for recreating S_source.hh $(CURDIR)/build/S_define.deps : diff --git a/share/trick/sim_objects/default_trick_sys.sm b/share/trick/sim_objects/default_trick_sys.sm index b08ce079..c541d048 100644 --- a/share/trick/sim_objects/default_trick_sys.sm +++ b/share/trick/sim_objects/default_trick_sys.sm @@ -92,6 +92,7 @@ a replacement SimObject will create an uncompilable sim. ##include "trick/Zeroconf.hh" ##include "trick/RtiStager.hh" ##include "trick/RtiExec.hh" +##include "trick/UdUnits.hh" // This is a user header block. Code here is copied without processing to S_source.hh %header{ @@ -787,6 +788,18 @@ class UnitTestSimObject : public Trick::SimObject { UnitTestSimObject trick_utest ; #endif +#ifndef TRICK_NO_UDUNITS +class UdUnitsSimObject : public Trick::SimObject { + public: + Trick::UdUnits udunits ; + UdUnitsSimObject() { + P65535 ("default_data") udunits.read_default_xml() ; + } +} ; + +UdUnitsSimObject trick_udunits; +#endif + // Include optional external clocks #include "sim_objects/TPROClock.sm" #include "sim_objects/BC635Clock.sm" diff --git a/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp b/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp index e498dd9b..26ae31c6 100644 --- a/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp +++ b/trick_source/codegen/Interface_Code_Gen/FieldDescription.cpp @@ -12,7 +12,26 @@ #include "Utilities.hh" // Provides units check capability. -#include "trick/units_conv.h" +std::string map_trick_units_to_udunits( std::string orig_units ) ; + +extern llvm::cl::opt< bool > units_truth_is_scary ; + +static ut_system * get_u_system() { + + ut_system * u_system ; + + /* Initialize the udunits-2 library */ + ut_set_error_message_handler(ut_ignore) ; + if( (u_system = ut_read_xml( NULL )) == NULL ) { + std::cout << "Error initializing udunits-2 unit system" << std::endl ; + exit(-1); + } + ut_set_error_message_handler(ut_write_to_stderr) ; + + return u_system ; +} + +ut_system * FieldDescription::u_system = get_u_system() ; FieldDescription::FieldDescription( std::string in_container_class ) : @@ -20,7 +39,7 @@ FieldDescription::FieldDescription( field_offset(0) , field_width(0) , inherited(false) , - units("--") , + units("1") , line_no(0) , io(3) , type_enum_string("TRICK_VOID") , @@ -133,14 +152,45 @@ void FieldDescription::parseComment(std::string comment) { get_regex_field(comment , "@?trick_io[\\({]([^\\)}]+)[\\)}](.*)" , 2) ; } - //std::cout << "4. " << comment << std::endl ; - ret_str = get_regex_field(comment , "@?trick_units[\\({]([^\\)}]+)[\\)}]" , 1) ; - if ( ! ret_str.empty()) { - units = ret_str ; - //std::cout << "go for trick_units " << units << std::endl ; - units_found = true ; - comment = get_regex_field(comment , "(.*)@?trick_units[\\({]([^\\)}]+)[\\)}]" , 1) + - get_regex_field(comment , "@?trick_units[\\({]([^\\)}]+)[\\)}](.*)" , 2) ; + /* + Units can include parenthesis now. We need to match the parenthesis in + trick_units() to get the whole units string. + */ + std::size_t tu_string = comment.find("trick_units") ; + if ( tu_string != std::string::npos ) { + std::size_t ustart = tu_string + std::string("trick_units").length() ; + std::size_t uend = ustart + 1 ; + std::stack parens ; + parens.push( comment[ustart]); + while ( ! parens.empty() and (uend < comment.length())) { + switch ( comment[uend] ) { + case '(': + parens.push('(') ; + break ; + case ')': + if (parens.top() == '(') { + parens.pop() ; + } + break ; + case '}': + if (parens.top() == '{') { + parens.pop() ; + } + break ; + } + uend++ ; + } + if ( parens.empty() ) { + units = comment.substr(ustart + 1 , uend - ustart - 2) ; + units_found = true ; + // If we have "@trick_units" include the "@" sign for erasure. + if ( tu_string > 0 and comment[tu_string-1] == '@' ) { + tu_string -= 1 ; + } + comment.erase(tu_string , uend - tu_string) ; + } else { + std::cout << "unmatched parenthesis for trick_units" << std::endl ; + } } if ( ! io_found ) { @@ -174,19 +224,33 @@ void FieldDescription::parseComment(std::string comment) { } } + // Test if we have valid units. We need to have found a units string and an io spec not zero // Possible todo is to create a map of valid units so we don't have to retest each string. if ( units_found and io != 0 and (valid_units.find(units) == valid_units.end())) { - Units_t * test_units = new_units(units.c_str()) ; - if ( test_units == NULL ) { - // If the units are invalid write an error message and change the units to "--" - std::cout << "\033[31mBad units specification (" << units << "): " << file_name << ":" << line_no - << "\033[0m" << std::endl ; - units = "--" ; + if ( !units.compare("--") ) { + units = "1" ; } else { - // If the units are valid, free the memory allocated by new_units. - CONV_FREE(test_units) ; - valid_units.insert(units) ; + // map old unit names to new names + std::string new_units = map_trick_units_to_udunits(units) ; + if ( units.compare(new_units) ) { + if ( ! units_truth_is_scary ) { + std::cout << "\033[31mUnits converted from [" << units << "] to [" << new_units << "] " + << file_name << ":" << line_no << "\033[0m" << std::endl ; + } + units = new_units ; + } + ut_unit * test_units = ut_parse(u_system, units.c_str() , UT_ASCII) ; + if ( test_units == NULL ) { + // If the units are invalid write an error message and change the units to "1" + std::cout << "\033[31mBad units specification [" << units << "] " << file_name << ":" << line_no + << "\033[0m" << std::endl ; + units = "1" ; + } else { + // If the units are valid, free the memory allocated by new_units. + ut_free(test_units) ; + valid_units.insert(units) ; + } } } diff --git a/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh b/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh index 754ade40..097b8e96 100644 --- a/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh +++ b/trick_source/codegen/Interface_Code_Gen/FieldDescription.hh @@ -6,6 +6,8 @@ #include #include +#include + #include "ConstructValues.hh" #include "clang/Basic/Specifiers.h" @@ -166,6 +168,7 @@ class FieldDescription : public ConstructValues { /** Internal function to execute regular expression */ std::string get_regex_field(std::string input , const char * expr , unsigned int index) ; + static ut_system * u_system ; } ; #endif diff --git a/trick_source/codegen/Interface_Code_Gen/PrintFileContentsBase.cpp b/trick_source/codegen/Interface_Code_Gen/PrintFileContentsBase.cpp index 63f2a752..8095c4e8 100644 --- a/trick_source/codegen/Interface_Code_Gen/PrintFileContentsBase.cpp +++ b/trick_source/codegen/Interface_Code_Gen/PrintFileContentsBase.cpp @@ -39,7 +39,7 @@ void PrintFileContentsBase::print_units_map(std::ofstream & outfile, ClassValues outfile << " Trick::UnitsMap * units_map_ptr __attribute__((unused)) = Trick::UnitsMap::units_map() ;\n" ; for ( fit = cv->field_begin() ; fit != cv->field_end() ; fit++ ) { - if ( determinePrintAttr(cv , *fit) and (*fit)->getUnits().compare("--")) { + if ( determinePrintAttr(cv , *fit) and (*fit)->getUnits().compare("1")) { FieldDescription * fdes = *fit ; outfile << " units_map_ptr->add_param(\"" ; printContainerClasses( outfile, cv , "__" ) ; diff --git a/trick_source/codegen/Interface_Code_Gen/main.cpp b/trick_source/codegen/Interface_Code_Gen/main.cpp index 71be82e6..59106127 100644 --- a/trick_source/codegen/Interface_Code_Gen/main.cpp +++ b/trick_source/codegen/Interface_Code_Gen/main.cpp @@ -25,13 +25,12 @@ #include "PrintAttributesFactory.hh" #include "Utilities.hh" -#include "trick/units_conv.h" - /* Command line arguments. These work better as globals, as suggested in llvm/CommandLine documentation */ llvm::cl::list< std::string > include_dirs("I", llvm::cl::Prefix, llvm::cl::desc("Include directory"), llvm::cl::value_desc("directory")) ; llvm::cl::list< std::string > defines("D", llvm::cl::Prefix, llvm::cl::desc("Defines"), llvm::cl::value_desc("define")) ; +llvm::cl::opt< bool > units_truth_is_scary ("units-truth-is-scary", llvm::cl::desc("Don't print units conversion messages")) ; llvm::cl::opt< bool > sim_services_flag ("s", llvm::cl::desc("Gernerate io_src for Trick core headers")) ; llvm::cl::opt< bool > force ("f", llvm::cl::desc("Force all io_src files to be generated")) ; llvm::cl::opt< int > attr_version ("v", llvm::cl::desc("Select version of attributes to produce. 10 and 13 are valid"), llvm::cl::init(10)) ; @@ -44,7 +43,7 @@ llvm::cl::list< std::string > input_file_names(llvm::cl::Positional, llvm::cl::d llvm::cl::list< std::string > sink(llvm::cl::Sink, llvm::cl::ZeroOrMore) ; llvm::cl::list< std::string > pre_compiled_headers("include", llvm::cl::Prefix, llvm::cl::desc("pre-compiled headers"), llvm::cl::value_desc("pre_compiled_headers")) ; -llvm::cl::opt< bool > show_units ("u", llvm::cl::desc("List recognized units")) ; +//llvm::cl::opt< bool > show_units ("u", llvm::cl::desc("List recognized units")) ; void ICG_version() { std::cout << "Trick Interface Code Generator (ICG) 13.dev" << std::endl ; @@ -83,10 +82,12 @@ int main( int argc , char * argv[] ) { return -1 ; } +/* if ( show_units ) { list_units() ; return 0 ; } +*/ if ( input_file_names.empty() ) { std::cerr << "No header file specified" << std::endl ; diff --git a/trick_source/codegen/Interface_Code_Gen/makefile b/trick_source/codegen/Interface_Code_Gen/makefile index 48901f2e..e50f840b 100644 --- a/trick_source/codegen/Interface_Code_Gen/makefile +++ b/trick_source/codegen/Interface_Code_Gen/makefile @@ -8,7 +8,7 @@ CXXFLAGS := -g -I$(shell $(LLVM_HOME)/bin/llvm-config --includedir) -D__STDC_CON CLANG_MINOR_GTEQ5 := $(shell expr `$(LLVM_HOME)/bin/llvm-config --version | cut -f2 -d. ` \>= 5 ) -LLVMLDFLAGS := $(shell $(LLVM_HOME)/bin/llvm-config --ldflags) +LLVMLDFLAGS := $(shell $(LLVM_HOME)/bin/llvm-config --ldflags) -ludunits2 OBJ_DIR := object_$(TRICK_HOST_CPU) @@ -21,10 +21,8 @@ ICG := ${TRICK_HOME}/bin/trick-ICG SOURCES = $(wildcard *.cpp) OBJECTS = $(addprefix $(OBJ_DIR)/, $(subst .cpp,.o,$(SOURCES))) -# Include the units conversion source from trick_utils. -UNITS_CONV_SRC = ${TRICK_HOME}/trick_source/trick_utils/units/src/units_conv.c -UNITS_CONV_INCLUDE = -I${TRICK_HOME}/include -UNITS_CONV_OBJ = $(OBJ_DIR)/units_conv.o +UDUNITS_OBJS = \ + $(OBJ_DIR)/map_trick_units_to_udunits.o CLANGLIBS = \ -lclangFrontend \ @@ -55,8 +53,8 @@ endif all: $(ICG) -$(ICG): $(OBJECTS) $(UNITS_CONV_OBJ) - $(CXX) -o $@ $(OBJECTS) $(UNITS_CONV_OBJ) $(LLVMLDFLAGS) $(CLANGLIBS) +$(ICG): $(OBJECTS) $(UDUNITS_OBJS) + $(CXX) -o $@ $(OBJECTS) $(UNITS_CONV_OBJ) $(UDUNITS_OBJS) $(LLVMLDFLAGS) $(CLANGLIBS) # Only FieldDescription.cpp includes the units conversion header. $(OBJ_DIR)/FieldDescription.o : CXXFLAGS += $(UNITS_CONV_INCLUDE) @@ -66,8 +64,8 @@ $(OBJ_DIR)/main.o : CXXFLAGS += $(UNITS_CONV_INCLUDE) $(OBJECTS): $(OBJ_DIR)/%.o : %.cpp $(CXX) $(CXXFLAGS) -c $< -o $@ -$(UNITS_CONV_OBJ): $(UNITS_CONV_SRC) - $(CC) $(UNITS_CONV_INCLUDE) -c $< -o $@ +$(UDUNITS_OBJS): $(OBJ_DIR)/%.o : ${TRICK_HOME}/trick_source/sim_services/UdUnits/%.cpp + $(CXX) -c $< -o $@ $(OBJECTS) $(UNITS_CONV_OBJ) : | $(OBJ_DIR) diff --git a/trick_source/sim_services/UdUnits/Makefile b/trick_source/sim_services/UdUnits/Makefile new file mode 100644 index 00000000..a181cedf --- /dev/null +++ b/trick_source/sim_services/UdUnits/Makefile @@ -0,0 +1,5 @@ + +include ${TRICK_HOME}/share/trick/makefiles/Makefile.common +include ${TRICK_HOME}/share/trick/makefiles/Makefile.tricklib +-include Makefile_deps + diff --git a/trick_source/sim_services/UdUnits/UdUnits.cpp b/trick_source/sim_services/UdUnits/UdUnits.cpp new file mode 100644 index 00000000..856bef63 --- /dev/null +++ b/trick_source/sim_services/UdUnits/UdUnits.cpp @@ -0,0 +1,27 @@ + +#include + +#include "trick/UdUnits.hh" + +ut_system * Trick::UdUnits::u_system = NULL ; + +ut_system * Trick::UdUnits::get_u_system() { + return u_system ; +} +int Trick::UdUnits::read_default_xml() { + /* Initialize the udunits-2 library */ + ut_set_error_message_handler(ut_ignore) ; + if( (u_system = ut_read_xml( NULL )) == NULL ) { + std::cerr << "Error initializing udunits-2 unit system" << std::endl ; + return -1 ; + } + ut_set_error_message_handler(ut_write_to_stderr) ; + + return 0 ; +} + +int Trick::UdUnits::read_user_xml(std::string file_name) { + return 0 ; +} + + diff --git a/trick_source/sim_services/UdUnits/map_trick_units_to_udunits.cpp b/trick_source/sim_services/UdUnits/map_trick_units_to_udunits.cpp new file mode 100644 index 00000000..93ef040b --- /dev/null +++ b/trick_source/sim_services/UdUnits/map_trick_units_to_udunits.cpp @@ -0,0 +1,96 @@ + +#include +#include +#include +#include +#include + +static std::map< std::string, std::string> init_map_old_to_ud() { + std::map< std::string, std::string> init_map ; + init_map["r"] = "rad" ; + init_map["d"] = "degree" ; + init_map["as"] = "arcsecond" ; + init_map["am"] = "arcminute" ; + init_map["rev"] = "revolution" ; + init_map["M"] = "m" ; // really? people still using this? (yes) + init_map["n.m."] = "nmile" ; + init_map["sl"] = "slug" ; + init_map["mt"] = "t" ; + init_map["lbm"] = "lb" ; + init_map["oz"] = "ozf" ; + init_map["v"] = "V" ; + init_map["F"] = "degF" ; + init_map["C"] = "degC" ; + init_map["R"] = "degR" ; + init_map["TNT"] = "ton_TNT" ; + init_map["Wh"] = "(W*h)" ; + init_map["kWh"] = "(kW*h)" ; + init_map["gal"] = "gallon" ; + init_map["one"] = "1" ; + init_map["cnt"] = "count" ; + + return init_map ; +} + +static std::map< std::string, std::string> old_to_ud = init_map_old_to_ud() ; + +static void tokenize_units(const std::string& str, + std::vector& tokens, + const std::string& delimiters = " ") +{ + // Skip delimiters at beginning. + std::string::size_type lastPos = str.find_first_not_of(delimiters, 0); + + if ( lastPos != 0 ) { + tokens.push_back(str.substr(0, lastPos)); + } + + // Find first "non-delimiter". + std::string::size_type pos = str.find_first_of(delimiters, lastPos); + + while (std::string::npos != pos || std::string::npos != lastPos) { + // Found a token, add it to the vector. + tokens.push_back(str.substr(lastPos, pos - lastPos)); + // Find end of delimiters. Note the "not_of" + lastPos = str.find_first_not_of(delimiters, pos); + // Push the delimiters + if ( lastPos != std::string::npos ) { + tokens.push_back(str.substr(pos, lastPos - pos)); + } else if ( pos != std::string::npos ) { + tokens.push_back(str.substr(pos)); + } + // Find next "non-delimiter" + pos = str.find_first_of(delimiters, lastPos); + } + +} + +// This routine (partially) tokenizes a units string. It substitutes +// units that need their names changed to conform to the new units system. +std::string map_trick_units_to_udunits( std::string orig_units ) { + std::vector tokens ; + std::vector::iterator it ; + tokenize_units(orig_units, tokens, "*/^()") ; + for( it = tokens.begin() ; it != tokens.end() ; it++ ) { + std::string power ; + char last_char = *((*it).rbegin()) ; + // tokens can end in powers of 2 or 3 in the old system. + // save the power if it is the last character + if(last_char == '2' || last_char == '3') { + (*it).erase((*it).length() -1) ; + } + // look up the unit to see if it needs to be converted. + std::map< std::string, std::string>::iterator mit ; + mit = old_to_ud.find(*it) ; + if ( mit != old_to_ud.end() ) { + *it = mit->second ; + } + // put back the power after the base unit has been tested + if ((last_char == '2' || last_char == '3')) { + *it += last_char ; + } + //std::cout << " " << *it << std::endl ; + } + std::string new_units = std::accumulate( tokens.begin(),tokens.end(), std::string("") ); + return new_units ; +} diff --git a/trick_source/sim_services/UnitsMap/UnitsMap.cpp b/trick_source/sim_services/UnitsMap/UnitsMap.cpp index ef066d90..b9617956 100644 --- a/trick_source/sim_services/UnitsMap/UnitsMap.cpp +++ b/trick_source/sim_services/UnitsMap/UnitsMap.cpp @@ -43,11 +43,11 @@ std::string Trick::UnitsMap::get_units( std::string param ) { /** * @par Design Details: * @li Finds the specified variable in the map and returns the units of the found variable. - * If the variable can not be found, returns "--" (unitless). + * If the variable can not be found, returns "1" (unitless). */ if ( param_units.find(param) != param_units.end() ) { return(std::string(param_units[param])) ; } else { - return(std::string("--")) ; + return(std::string("1")) ; } } diff --git a/trick_source/trick_swig/sim_services.i b/trick_source/trick_swig/sim_services.i index dd00718b..44133baa 100644 --- a/trick_source/trick_swig/sim_services.i +++ b/trick_source/trick_swig/sim_services.i @@ -136,6 +136,7 @@ #include "trick/vval.h" #include "trick/Flag.h" #include "trick/Unit.hh" +#include "trick/UdUnits.hh" #ifdef USE_ER7_UTILS_INTEGRATORS #include "er7_utils/integration/core/include/integrator_constructor_factory.hh" diff --git a/trick_source/trick_swig/swig_convert_units.cpp b/trick_source/trick_swig/swig_convert_units.cpp index bece8394..6e1f4782 100644 --- a/trick_source/trick_swig/swig_convert_units.cpp +++ b/trick_source/trick_swig/swig_convert_units.cpp @@ -1,80 +1,73 @@ #include #include +#include #include "trick/Unit.hh" +#include "trick/UdUnits.hh" int convert_united_value( std::string & to_units , std::string & from_units , long long * val ) { - - if ( from_units.compare("--") ) { - try { - Unit converter(from_units.c_str()) ; - *val = (long long)converter.Convert_to( (double)(* val) , to_units.c_str()) ; + if ( from_units.compare("1") ) { + ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), from_units.c_str(), UT_ASCII) ; + if ( !from ) { + PyErr_SetString(PyExc_AttributeError,(std::string("could not covert from units "+from_units).c_str())); + return -1 ; } - catch (Unit::CONVERSION_ERROR & ce_err ) { + ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), to_units.c_str(), UT_ASCII) ; + if ( !to ) { + PyErr_SetString(PyExc_AttributeError,(std::string("could not covert to units "+to_units).c_str())); + return -1 ; + } + + cv_converter * converter = ut_get_converter(from,to) ; + if ( converter ) { + *val = (long long)cv_convert_double(converter, (double)*val ) ; + cv_free(converter) ; + } else { PyErr_SetString(PyExc_AttributeError,"Units conversion Error"); return -1 ; } + + ut_free(from) ; + ut_free(to) ; } return 0 ; } int convert_united_value( std::string & to_units , std::string & from_units , double * val ) { - if ( from_units.compare("--") ) { - try { - Unit converter(from_units.c_str()) ; - *val = converter.Convert_to( *val , to_units.c_str()) ; + if ( from_units.compare("1") ) { + ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), from_units.c_str(), UT_ASCII) ; + if ( !from ) { + PyErr_SetString(PyExc_AttributeError,(std::string("could not covert from units "+from_units).c_str())); + return -1 ; } - catch (Unit::CONVERSION_ERROR & ce_err ) { + ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), to_units.c_str(), UT_ASCII) ; + if ( !to ) { + PyErr_SetString(PyExc_AttributeError,(std::string("could not covert to units "+to_units).c_str())); + return -1 ; + } + + cv_converter * converter = ut_get_converter(from,to) ; + if ( converter ) { + *val = cv_convert_double(converter, *val ) ; + cv_free(converter) ; + } else { PyErr_SetString(PyExc_AttributeError,"Units conversion Error"); return -1 ; } + + ut_free(from) ; + ut_free(to) ; } return 0 ; } int scale_united_value( std::string & to_units , std::string & from_units , long long * val ) { - - if ( from_units.compare("--") ) { - try { - Units_t * from = new_units(from_units.c_str()) ; - Units_t * to = new_units(to_units.c_str()) ; - UnitsConvFn_t conv_fn; - if (conv_fn_u(from, to, &conv_fn) != CONV_OK) { - throw Unit::CONVERSION_ERROR(); - } - *val = (long long)(conv_fn.C[1] * (*val)) ; - free(from) ; - free(to) ; - } - catch (Unit::CONVERSION_ERROR & ce_err ) { - PyErr_SetString(PyExc_AttributeError,"Units conversion Error"); - return -1 ; - } - } - return 0 ; + return convert_united_value(to_units, from_units, val) ; } int scale_united_value( std::string & to_units , std::string & from_units , double * val ) { - - if ( from_units.compare("--") ) { - try { - Units_t * from = new_units(from_units.c_str()) ; - Units_t * to = new_units(to_units.c_str()) ; - UnitsConvFn_t conv_fn; - if (conv_fn_u(from, to, &conv_fn) != CONV_OK) { - throw Unit::CONVERSION_ERROR(); - } - *val = conv_fn.C[1] * (*val) ; - free(from) ; - free(to) ; - } - catch (Unit::CONVERSION_ERROR & ce_err ) { - PyErr_SetString(PyExc_AttributeError,"Units conversion Error"); - return -1 ; - } - } - return 0 ; + return convert_united_value(to_units, from_units, val) ; } diff --git a/trick_source/trick_swig/swig_double.cpp b/trick_source/trick_swig/swig_double.cpp index 0429ffe0..54f3822f 100644 --- a/trick_source/trick_swig/swig_double.cpp +++ b/trick_source/trick_swig/swig_double.cpp @@ -11,11 +11,11 @@ char swig_double::str_output[32] ; swig_double::swig_double() { value = 0 ; - units = "--" ; + units = "1" ; } char * swig_double::__str__() { - if ( ! units.empty() && units.compare("--") ) { + if ( ! units.empty() && units.compare("1") ) { sprintf(str_output , "%g %s", value , units.c_str()) ; } else { sprintf(str_output , "%g", value ) ; @@ -67,7 +67,7 @@ PyObject * swig_double::__add__( PyObject * obj1 ) { result->units = units ; ret = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIG_TypeQuery("swig_double *"), SWIG_POINTER_OWN); - + return ret ; } @@ -107,7 +107,7 @@ PyObject * swig_double::__sub__( PyObject * obj1 ) { result->units = units ; ret = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIG_TypeQuery("swig_double *"), SWIG_POINTER_OWN); - + return ret ; } @@ -123,35 +123,19 @@ PyObject * swig_double::__mul__( PyObject * obj1 ) { result->units = units ; } else if (SWIG_IsOK(SWIG_ConvertPtr(obj1, &argp2,SWIG_TypeQuery("swig_int *"), 0 ))) { swig_int * temp_m = reinterpret_cast< swig_int * >(argp2) ; - if ( !temp_m->units.compare("--")) { - result->value = value * temp_m->value ; - result->units = units ; - } else if ( !units.compare("--")) { - result->value = value * temp_m->value ; - result->units = temp_m->units ; - } else { - PyErr_SetString(PyExc_TypeError,"Operation must contain at least one unit-less value. Cannot create new unit-ed type."); - return NULL ; - } + result->value = value * temp_m->value ; + result->units = units + "*(" + temp_m->units + ")"; } else if (SWIG_IsOK(SWIG_ConvertPtr(obj1, &argp2,SWIG_TypeQuery("swig_double *"), 0 ))) { swig_double * temp_m = reinterpret_cast< swig_double * >(argp2) ; - if ( !temp_m->units.compare("--")) { - result->value = value * temp_m->value ; - result->units = units ; - } else if ( !units.compare("--")) { - result->value = value * temp_m->value ; - result->units = temp_m->units ; - } else { - PyErr_SetString(PyExc_TypeError,"Operation must contain at least one unit-less value. Cannot create new unit-ed type."); - return NULL ; - } + result->value = value * temp_m->value ; + result->units = units + "*(" + temp_m->units + ")"; } else if ( PyInt_Check(obj1) ) { result->value = value * PyInt_AsLong(obj1) ; result->units = units ; } ret = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIG_TypeQuery("swig_double *"), SWIG_POINTER_OWN); - + return ret ; } @@ -166,27 +150,17 @@ PyObject * swig_double::__div__( PyObject * obj1 ) { result->value = value / PyFloat_AsDouble(obj1) ; } else if (SWIG_IsOK(SWIG_ConvertPtr(obj1, &argp2,SWIG_TypeQuery("swig_int *"), 0 ))) { swig_int * temp_m = reinterpret_cast< swig_int * >(argp2) ; - if ( !temp_m->units.compare("--")) { - result->value = value / temp_m->value ; - } else { - PyErr_SetString(PyExc_TypeError,"Divisor must be unitless. Cannot create new unit-ed type."); - return NULL ; - } + result->value = value / temp_m->value ; + result->units = units ; + result->units = units + "/(" + temp_m->units + ")"; } else if (SWIG_IsOK(SWIG_ConvertPtr(obj1, &argp2,SWIG_TypeQuery("swig_double *"), 0 ))) { swig_double * temp_m = reinterpret_cast< swig_double * >(argp2) ; - if ( !temp_m->units.compare("--")) { - result->value = value / temp_m->value ; - } else { - PyErr_SetString(PyExc_TypeError,"Divisor must be unitless. Cannot create new unit-ed type."); - return NULL ; - } + result->value = value / temp_m->value ; + result->units = units + "/(" + temp_m->units + ")"; } else if ( PyInt_Check(obj1) ) { result->value = value / PyInt_AsLong(obj1) ; } - result->units = units ; - ret = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIG_TypeQuery("swig_double *"), SWIG_POINTER_OWN); - return ret ; } diff --git a/trick_source/trick_swig/swig_int.cpp b/trick_source/trick_swig/swig_int.cpp index e2e6ae85..88de5915 100644 --- a/trick_source/trick_swig/swig_int.cpp +++ b/trick_source/trick_swig/swig_int.cpp @@ -11,11 +11,11 @@ char swig_int::str_output[32] ; swig_int::swig_int() { value = 0 ; - units = "--" ; + units = "1" ; } char * swig_int::__str__() { - if ( ! units.empty() && units.compare("--") ) { + if ( ! units.empty() && units.compare("1") ) { sprintf(str_output , "%lld %s", value , units.c_str()) ; } else { sprintf(str_output , "%lld", value ) ;