diff --git a/CMakeLists.txt b/CMakeLists.txt index de07747ab..ddb5c681c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,9 @@ OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON) # build static libs by default OPTION(BUILD_STATIC_LIBS "Build static libraries" OFF) +OPTION(PYTHON_GENERATOR "Compile fedex_plus_python" ON) +OPTION(CPP_GENERATOR "Compile fedex_plus" ON) + # Set version SET(SCL_VERSION_MAJOR "3") SET(SCL_VERSION_MINOR "2") @@ -258,6 +261,7 @@ include_directories( ADD_SUBDIRECTORY(src/express) ADD_SUBDIRECTORY(src/exppp) ADD_SUBDIRECTORY(src/fedex_plus) +ADD_SUBDIRECTORY(src/fedex_python) ADD_SUBDIRECTORY(src/clstepcore) ADD_SUBDIRECTORY(src/cleditor) ADD_SUBDIRECTORY(src/cldai) diff --git a/include/express/type.h b/include/express/type.h index c399e13ae..f6bf3b11b 100644 --- a/include/express/type.h +++ b/include/express/type.h @@ -235,6 +235,8 @@ GLOBAL SCL_EXPRESS_EXPORT Error ERROR_corrupted_type INITIALLY( ERROR_none ); #define TYPEis_identifier(t) ((t)->u.type->body->type == identifier_) #define TYPEis_logical(t) ((t)->u.type->body->type == logical_) #define TYPEis_boolean(t) ((t)->u.type->body->type == boolean_) +#define TYPEis_real(t) ((t)->u.type->body->type == real_) +#define TYPEis_integer(t) ((t)->u.type->body->type == integer_) #define TYPEis_string(t) ((t)->u.type->body->type == string_) #define TYPEis_expression(t) ((t)->u.type->body->type == op_) #define TYPEis_oneof(t) ((t)->u.type->body->type == oneof_) diff --git a/src/fedex_python/CMakeLists.txt b/src/fedex_python/CMakeLists.txt new file mode 100644 index 000000000..a434ad25a --- /dev/null +++ b/src/fedex_python/CMakeLists.txt @@ -0,0 +1,44 @@ +if(PYTHON_GENERATOR) + +include_directories( + ${SCL_SOURCE_DIR}/include + ${SCL_SOURCE_DIR}/include/exppp + ${SCL_SOURCE_DIR}/include/express + ${SCL_SOURCE_DIR}/src/fedex_plus +) + +add_definitions( -DHAVE_CONFIG_H ) + +IF(MSVC) +set(fedex_plus_MSVC_SOURCES + ${SCL_SOURCE_DIR}/src/fedex_plus/xgetopt.cc +) +add_definitions( -DSCL_EXPRESS_DLL_IMPORTS ) +add_definitions( -DSCL_EXPPP_DLL_IMPORTS ) +ENDIF(MSVC) + +set(fedex_python_SOURCES + src/classes_misc_python.c + ${SCL_SOURCE_DIR}/src/express/fedex.c + src/fedex_main_python.c + src/classes_wrapper_python.cc + src/classes_python.c + src/selects_python.c + src/multpass_python.c + ${SCL_SOURCE_DIR}/src/fedex_plus/collect.cc + ${SCL_SOURCE_DIR}/src/fedex_plus/complexlist.cc + ${SCL_SOURCE_DIR}/src/fedex_plus/entlist.cc + ${SCL_SOURCE_DIR}/src/fedex_plus/multlist.cc + ${SCL_SOURCE_DIR}/src/fedex_plus/orlist.cc + ${SCL_SOURCE_DIR}/src/fedex_plus/entnode.cc + ${SCL_SOURCE_DIR}/src/fedex_plus/expressbuild.cc + ${SCL_SOURCE_DIR}/src/fedex_plus/non-ors.cc + ${SCL_SOURCE_DIR}/src/fedex_plus/match-ors.cc + ${SCL_SOURCE_DIR}/src/fedex_plus/trynext.cc + ${SCL_SOURCE_DIR}/src/fedex_plus/write.cc + ${SCL_SOURCE_DIR}/src/fedex_plus/print.cc +) +SCL_ADDEXEC(fedex_python "${fedex_python_SOURCES} ${fedex_plus_MSVC_SOURCES}" "libexppp express") + +add_dependencies( fedex_python version_string ) +endif(PYTHON_GENERATOR) diff --git a/src/fedex_python/REAMDE.md b/src/fedex_python/REAMDE.md new file mode 100644 index 000000000..64e7179c7 --- /dev/null +++ b/src/fedex_python/REAMDE.md @@ -0,0 +1 @@ +Howto diff --git a/src/fedex_python/examples/unitary_schemas/gcc_incomplete_type.py b/src/fedex_python/examples/unitary_schemas/gcc_incomplete_type.py new file mode 100644 index 000000000..72cec4b23 --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/gcc_incomplete_type.py @@ -0,0 +1,19 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * +maths_number = NUMBER +# SELECT TYPE atom_based_value_ +if (not 'maths_number' in globals().keys()): + maths_number = 'maths_number' +if (not 'atom_based_tuple' in globals().keys()): + atom_based_tuple = 'atom_based_tuple' +atom_based_value = SELECT( + 'maths_number', + 'atom_based_tuple') +atom_based_tuple = LIST(0,None,'atom_based_value') diff --git a/src/fedex_python/examples/unitary_schemas/generate_schemas_modules.py b/src/fedex_python/examples/unitary_schemas/generate_schemas_modules.py new file mode 100644 index 000000000..86f6b3b51 --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/generate_schemas_modules.py @@ -0,0 +1,13 @@ +__doc__= ''' This script runs fedex_python over each EXPRESS schema in the test/unitary_schemas folder''' + +unitary_schemas_path = '../../../../test/unitary_schemas' +fedex_python_path = '../../../../cmake-build/bin/fedex_python' + +import subprocess +import glob +import os + +unitary_schemas = glob.glob(os.path.join(unitary_schemas_path,'*.exp')) + +for unitary_schema in unitary_schemas: + subprocess.call([fedex_python_path,unitary_schema]) \ No newline at end of file diff --git a/src/fedex_python/examples/unitary_schemas/index_attribute.py b/src/fedex_python/examples/unitary_schemas/index_attribute.py new file mode 100644 index 000000000..4b1e36826 --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/index_attribute.py @@ -0,0 +1,117 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * +common_datum_list = LIST(1,None,'datum_reference_element') +label = STRING +# SELECT TYPE datum_or_common_datum_ +if (not 'common_datum_list' in globals().keys()): + common_datum_list = 'common_datum_list' +if (not 'datum' in globals().keys()): + datum = 'datum' +datum_or_common_datum = SELECT( + 'common_datum_list', + 'datum') + +#################### + # ENTITY shape_aspect # +#################### +class shape_aspect(BaseEntityClass): + '''Entity shape_aspect definition. + + :param name + :type name:STRING + + :param of_shape + :type of_shape:product_definition_shape + ''' + def __init__( self , name,of_shape, ): + self.name = name + self.of_shape = of_shape + + @apply + def name(): + def fget( self ): + return self._name + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument name is mantatory and can not be set to None') + if not check_type(value,STRING): + self._name = STRING(value) + else: + self._name = value + return property(**locals()) + + @apply + def of_shape(): + def fget( self ): + return self._of_shape + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument of_shape is mantatory and can not be set to None') + if not check_type(value,product_definition_shape): + self._of_shape = product_definition_shape(value) + else: + self._of_shape = value + return property(**locals()) + +#################### + # ENTITY general_datum_reference # +#################### +class general_datum_reference(shape_aspect): + '''Entity general_datum_reference definition. + + :param base + :type base:datum_or_common_datum + ''' + def __init__( self , shape_aspect__name , shape_aspect__of_shape , base, ): + shape_aspect.__init__(self , shape_aspect__name , shape_aspect__of_shape , ) + self.base = base + + @apply + def base(): + def fget( self ): + return self._base + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument base is mantatory and can not be set to None') + if not check_type(value,datum_or_common_datum): + self._base = datum_or_common_datum(value) + else: + self._base = value + return property(**locals()) + +#################### + # ENTITY product_definition_shape # +#################### +class product_definition_shape(BaseEntityClass): + '''Entity product_definition_shape definition. + ''' + # This class does not define any attribute. + pass + +#################### + # ENTITY datum_reference_element # +#################### +class datum_reference_element(general_datum_reference): + '''Entity datum_reference_element definition. + ''' + def __init__( self , general_datum_reference__base , ): + general_datum_reference.__init__(self , general_datum_reference__base , ) + +#################### + # ENTITY datum # +#################### +class datum(shape_aspect): + '''Entity datum definition. + ''' + def __init__( self , shape_aspect__name , shape_aspect__of_shape , ): + shape_aspect.__init__(self , shape_aspect__name , shape_aspect__of_shape , ) diff --git a/src/fedex_python/examples/unitary_schemas/multiple_rep.py b/src/fedex_python/examples/unitary_schemas/multiple_rep.py new file mode 100644 index 000000000..c0df05dd3 --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/multiple_rep.py @@ -0,0 +1,264 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * +text = STRING +representation_context = STRING +identifier = STRING +shape_definition = STRING +transformation = STRING +representation_item = STRING +characterized_product_definition = STRING +# SELECT TYPE characterized_definition_ +if (not 'characterized_object' in globals().keys()): + characterized_object = 'characterized_object' +if (not 'characterized_product_definition' in globals().keys()): + characterized_product_definition = 'characterized_product_definition' +if (not 'shape_definition' in globals().keys()): + shape_definition = 'shape_definition' +characterized_definition = SELECT( + 'characterized_object', + 'characterized_product_definition', + 'shape_definition') +label = STRING +characterized_object = STRING + +#################### + # ENTITY representation_relationship # +#################### +class representation_relationship(BaseEntityClass): + '''Entity representation_relationship definition. + + :param name + :type name:STRING + + :param rep_1 + :type rep_1:representation + + :param rep_2 + :type rep_2:representation + ''' + def __init__( self , name,rep_1,rep_2, ): + self.name = name + self.rep_1 = rep_1 + self.rep_2 = rep_2 + + @apply + def name(): + def fget( self ): + return self._name + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument name is mantatory and can not be set to None') + if not check_type(value,STRING): + self._name = STRING(value) + else: + self._name = value + return property(**locals()) + + @apply + def rep_1(): + def fget( self ): + return self._rep_1 + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument rep_1 is mantatory and can not be set to None') + if not check_type(value,representation): + self._rep_1 = representation(value) + else: + self._rep_1 = value + return property(**locals()) + + @apply + def rep_2(): + def fget( self ): + return self._rep_2 + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument rep_2 is mantatory and can not be set to None') + if not check_type(value,representation): + self._rep_2 = representation(value) + else: + self._rep_2 = value + return property(**locals()) + +#################### + # ENTITY shape_representation_relationship # +#################### +class shape_representation_relationship(representation_relationship): + '''Entity shape_representation_relationship definition. + ''' + def __init__( self , representation_relationship__name , representation_relationship__rep_1 , representation_relationship__rep_2 , ): + representation_relationship.__init__(self , representation_relationship__name , representation_relationship__rep_1 , representation_relationship__rep_2 , ) + +#################### + # ENTITY representation # +#################### +class representation(BaseEntityClass): + '''Entity representation definition. + + :param name + :type name:STRING + + :param items + :type items:SET(1,None,'STRING') + + :param context_of_items + :type context_of_items:STRING + ''' + def __init__( self , name,items,context_of_items, ): + self.name = name + self.items = items + self.context_of_items = context_of_items + + @apply + def name(): + def fget( self ): + return self._name + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument name is mantatory and can not be set to None') + if not check_type(value,STRING): + self._name = STRING(value) + else: + self._name = value + return property(**locals()) + + @apply + def items(): + def fget( self ): + return self._items + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument items is mantatory and can not be set to None') + if not check_type(value,SET(1,None,'STRING')): + self._items = SET(value) + else: + self._items = value + return property(**locals()) + + @apply + def context_of_items(): + def fget( self ): + return self._context_of_items + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument context_of_items is mantatory and can not be set to None') + if not check_type(value,STRING): + self._context_of_items = STRING(value) + else: + self._context_of_items = value + return property(**locals()) + +#################### + # ENTITY property_definition # +#################### +class property_definition(BaseEntityClass): + '''Entity property_definition definition. + + :param name + :type name:STRING + + :param definition + :type definition:characterized_definition + ''' + def __init__( self , name,definition, ): + self.name = name + self.definition = definition + + @apply + def name(): + def fget( self ): + return self._name + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument name is mantatory and can not be set to None') + if not check_type(value,STRING): + self._name = STRING(value) + else: + self._name = value + return property(**locals()) + + @apply + def definition(): + def fget( self ): + return self._definition + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument definition is mantatory and can not be set to None') + if not check_type(value,characterized_definition): + self._definition = characterized_definition(value) + else: + self._definition = value + return property(**locals()) + +#################### + # ENTITY context_dependent_shape_representation # +#################### +class context_dependent_shape_representation(BaseEntityClass): + '''Entity context_dependent_shape_representation definition. + + :param representation_relation + :type representation_relation:shape_representation_relationship + ''' + def __init__( self , representation_relation, ): + self.representation_relation = representation_relation + + @apply + def representation_relation(): + def fget( self ): + return self._representation_relation + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument representation_relation is mantatory and can not be set to None') + if not check_type(value,shape_representation_relationship): + self._representation_relation = shape_representation_relationship(value) + else: + self._representation_relation = value + return property(**locals()) + +#################### + # ENTITY definitional_representation_relationship # +#################### +class definitional_representation_relationship(representation_relationship): + '''Entity definitional_representation_relationship definition. + ''' + def __init__( self , representation_relationship__name , representation_relationship__rep_1 , representation_relationship__rep_2 , ): + representation_relationship.__init__(self , representation_relationship__name , representation_relationship__rep_1 , representation_relationship__rep_2 , ) + +#################### + # ENTITY component_2d_location # +#################### +class component_2d_location(context_dependent_shape_representation,shape_representation_relationship,definitional_representation_relationship): + '''Entity component_2d_location definition. + + :param context_dependent_shape_representation_representation_relation + :type context_dependent_shape_representation_representation_relation:component_2d_location + ''' + def __init__( self , context_dependent_shape_representation__representation_relation , ): + context_dependent_shape_representation.__init__(self , context_dependent_shape_representation__representation_relation , ) + shape_representation_relationship.__init__(self , ) + definitional_representation_relationship.__init__(self , ) + + @apply + def context_dependent_shape_representation_representation_relation(): + def fget( self ): + return EvalDerivedAttribute(self,'''SELF''') + def fset( self, value ): + # DERIVED argument + raise AssertionError('Argument context_dependent_shape_representation_representation_relation is DERIVED. It is computed and can not be set to any value') + return property(**locals()) diff --git a/src/fedex_python/examples/unitary_schemas/test_array.py b/src/fedex_python/examples/unitary_schemas/test_array.py new file mode 100644 index 000000000..cdfca5461 --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/test_array.py @@ -0,0 +1,35 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * + +#################### + # ENTITY point # +#################### +class point(BaseEntityClass): + '''Entity point definition. + + :param coords + :type coords:ARRAY(1,3,'REAL') + ''' + def __init__( self , coords, ): + self.coords = coords + + @apply + def coords(): + def fget( self ): + return self._coords + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument coords is mantatory and can not be set to None') + if not check_type(value,ARRAY(1,3,'REAL')): + self._coords = ARRAY(value) + else: + self._coords = value + return property(**locals()) diff --git a/src/fedex_python/examples/unitary_schemas/test_array_of_simple_types.py b/src/fedex_python/examples/unitary_schemas/test_array_of_simple_types.py new file mode 100644 index 000000000..808e00d79 --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/test_array_of_simple_types.py @@ -0,0 +1,71 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * + +#################### + # ENTITY point # +#################### +class point(BaseEntityClass): + '''Entity point definition. + + :param arr_real + :type arr_real:ARRAY(1,3,'REAL') + + :param arr_string + :type arr_string:ARRAY(1,3,'STRING') + + :param arr_integer + :type arr_integer:ARRAY(1,None,'INTEGER') + ''' + def __init__( self , arr_real,arr_string,arr_integer, ): + self.arr_real = arr_real + self.arr_string = arr_string + self.arr_integer = arr_integer + + @apply + def arr_real(): + def fget( self ): + return self._arr_real + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument arr_real is mantatory and can not be set to None') + if not check_type(value,ARRAY(1,3,'REAL')): + self._arr_real = ARRAY(value) + else: + self._arr_real = value + return property(**locals()) + + @apply + def arr_string(): + def fget( self ): + return self._arr_string + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument arr_string is mantatory and can not be set to None') + if not check_type(value,ARRAY(1,3,'STRING')): + self._arr_string = ARRAY(value) + else: + self._arr_string = value + return property(**locals()) + + @apply + def arr_integer(): + def fget( self ): + return self._arr_integer + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument arr_integer is mantatory and can not be set to None') + if not check_type(value,ARRAY(1,None,'INTEGER')): + self._arr_integer = ARRAY(value) + else: + self._arr_integer = value + return property(**locals()) diff --git a/src/fedex_python/examples/unitary_schemas/test_derived_attribute.py b/src/fedex_python/examples/unitary_schemas/test_derived_attribute.py new file mode 100644 index 000000000..083b03609 --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/test_derived_attribute.py @@ -0,0 +1,113 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * + +#################### + # ENTITY vector # +#################### +class vector(BaseEntityClass): + '''Entity vector definition. + ''' + # This class does not define any attribute. + pass + +#################### + # ENTITY circle # +#################### +class circle(BaseEntityClass): + '''Entity circle definition. + + :param centre + :type centre:point + + :param radius + :type radius:REAL + + :param axis + :type axis:vector + + :param area + :type area:REAL + + :param perimeter + :type perimeter:REAL + ''' + def __init__( self , centre,radius,axis, ): + self.centre = centre + self.radius = radius + self.axis = axis + + @apply + def centre(): + def fget( self ): + return self._centre + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument centre is mantatory and can not be set to None') + if not check_type(value,point): + self._centre = point(value) + else: + self._centre = value + return property(**locals()) + + @apply + def radius(): + def fget( self ): + return self._radius + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument radius is mantatory and can not be set to None') + if not check_type(value,REAL): + self._radius = REAL(value) + else: + self._radius = value + return property(**locals()) + + @apply + def axis(): + def fget( self ): + return self._axis + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument axis is mantatory and can not be set to None') + if not check_type(value,vector): + self._axis = vector(value) + else: + self._axis = value + return property(**locals()) + + @apply + def area(): + def fget( self ): + return EvalDerivedAttribute(self,'''PI * (radius ** 2)''') + def fset( self, value ): + # DERIVED argument + raise AssertionError('Argument area is DERIVED. It is computed and can not be set to any value') + return property(**locals()) + + @apply + def perimeter(): + def fget( self ): + return EvalDerivedAttribute(self,'''2 * PI * radius''') + def fset( self, value ): + # DERIVED argument + raise AssertionError('Argument perimeter is DERIVED. It is computed and can not be set to any value') + return property(**locals()) + +#################### + # ENTITY point # +#################### +class point(BaseEntityClass): + '''Entity point definition. + ''' + # This class does not define any attribute. + pass diff --git a/src/fedex_python/examples/unitary_schemas/test_enum_entity_name.py b/src/fedex_python/examples/unitary_schemas/test_enum_entity_name.py new file mode 100644 index 000000000..d914e73c6 --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/test_enum_entity_name.py @@ -0,0 +1,28 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * + +# ENUMERATION TYPE simple_datum_reference_modifier +if (not 'line' in globals().keys()): + line = 'line' +if (not 'translation' in globals().keys()): + translation = 'translation' +simple_datum_reference_modifier = ENUMERATION( + 'line', + 'translation', + ) + +#################### + # ENTITY line # +#################### +class line(BaseEntityClass): + '''Entity line definition. + ''' + # This class does not define any attribute. + pass diff --git a/src/fedex_python/examples/unitary_schemas/test_enums_same_name.py b/src/fedex_python/examples/unitary_schemas/test_enums_same_name.py new file mode 100644 index 000000000..254760893 --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/test_enums_same_name.py @@ -0,0 +1,29 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * + +# ENUMERATION TYPE hair_color +if (not 'bald' in globals().keys()): + bald = 'bald' +if (not 'red' in globals().keys()): + red = 'red' +hair_color = ENUMERATION( + 'bald', + 'red', + ) + +# ENUMERATION TYPE favorite_color +if (not 'clear' in globals().keys()): + clear = 'clear' +if (not 'red' in globals().keys()): + red = 'red' +favorite_color = ENUMERATION( + 'clear', + 'red', + ) diff --git a/src/fedex_python/examples/unitary_schemas/test_multiple_inheritance.py b/src/fedex_python/examples/unitary_schemas/test_multiple_inheritance.py new file mode 100644 index 000000000..c8d111fc5 --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/test_multiple_inheritance.py @@ -0,0 +1,516 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * +# SELECT TYPE classification_item_ +if (not 'person_and_organization_address' in globals().keys()): + person_and_organization_address = 'person_and_organization_address' +if (not 'address' in globals().keys()): + address = 'address' +classification_item = SELECT( + 'person_and_organization_address', + 'address') +text = STRING +identifier = STRING +label = STRING + +#################### + # ENTITY address # +#################### +class address(BaseEntityClass): + '''Entity address definition. + + :param internal_location + :type internal_location:STRING + + :param street_number + :type street_number:STRING + + :param street + :type street:STRING + + :param postal_box + :type postal_box:STRING + + :param town + :type town:STRING + + :param region + :type region:STRING + + :param postal_code + :type postal_code:STRING + + :param country + :type country:STRING + + :param facsimile_number + :type facsimile_number:STRING + + :param telephone_number + :type telephone_number:STRING + + :param electronic_mail_address + :type electronic_mail_address:STRING + + :param telex_number + :type telex_number:STRING + ''' + def __init__( self , internal_location,street_number,street,postal_box,town,region,postal_code,country,facsimile_number,telephone_number,electronic_mail_address,telex_number, ): + self.internal_location = internal_location + self.street_number = street_number + self.street = street + self.postal_box = postal_box + self.town = town + self.region = region + self.postal_code = postal_code + self.country = country + self.facsimile_number = facsimile_number + self.telephone_number = telephone_number + self.electronic_mail_address = electronic_mail_address + self.telex_number = telex_number + + @apply + def internal_location(): + def fget( self ): + return self._internal_location + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._internal_location = STRING(value) + else: + self._internal_location = value + return property(**locals()) + + @apply + def street_number(): + def fget( self ): + return self._street_number + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._street_number = STRING(value) + else: + self._street_number = value + return property(**locals()) + + @apply + def street(): + def fget( self ): + return self._street + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._street = STRING(value) + else: + self._street = value + return property(**locals()) + + @apply + def postal_box(): + def fget( self ): + return self._postal_box + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._postal_box = STRING(value) + else: + self._postal_box = value + return property(**locals()) + + @apply + def town(): + def fget( self ): + return self._town + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._town = STRING(value) + else: + self._town = value + return property(**locals()) + + @apply + def region(): + def fget( self ): + return self._region + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._region = STRING(value) + else: + self._region = value + return property(**locals()) + + @apply + def postal_code(): + def fget( self ): + return self._postal_code + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._postal_code = STRING(value) + else: + self._postal_code = value + return property(**locals()) + + @apply + def country(): + def fget( self ): + return self._country + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._country = STRING(value) + else: + self._country = value + return property(**locals()) + + @apply + def facsimile_number(): + def fget( self ): + return self._facsimile_number + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._facsimile_number = STRING(value) + else: + self._facsimile_number = value + return property(**locals()) + + @apply + def telephone_number(): + def fget( self ): + return self._telephone_number + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._telephone_number = STRING(value) + else: + self._telephone_number = value + return property(**locals()) + + @apply + def electronic_mail_address(): + def fget( self ): + return self._electronic_mail_address + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._electronic_mail_address = STRING(value) + else: + self._electronic_mail_address = value + return property(**locals()) + + @apply + def telex_number(): + def fget( self ): + return self._telex_number + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._telex_number = STRING(value) + else: + self._telex_number = value + return property(**locals()) + +#################### + # ENTITY personal_address # +#################### +class personal_address(address): + '''Entity personal_address definition. + + :param people + :type people:SET(1,None,'person') + + :param description + :type description:STRING + ''' + def __init__( self , address__internal_location , address__street_number , address__street , address__postal_box , address__town , address__region , address__postal_code , address__country , address__facsimile_number , address__telephone_number , address__electronic_mail_address , address__telex_number , people,description, ): + address.__init__(self , address__internal_location , address__street_number , address__street , address__postal_box , address__town , address__region , address__postal_code , address__country , address__facsimile_number , address__telephone_number , address__electronic_mail_address , address__telex_number , ) + self.people = people + self.description = description + + @apply + def people(): + def fget( self ): + return self._people + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument people is mantatory and can not be set to None') + if not check_type(value,SET(1,None,'person')): + self._people = SET(value) + else: + self._people = value + return property(**locals()) + + @apply + def description(): + def fget( self ): + return self._description + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._description = STRING(value) + else: + self._description = value + return property(**locals()) + +#################### + # ENTITY organizational_address # +#################### +class organizational_address(address): + '''Entity organizational_address definition. + + :param organizations + :type organizations:SET(1,None,'organization') + + :param description + :type description:STRING + ''' + def __init__( self , address__internal_location , address__street_number , address__street , address__postal_box , address__town , address__region , address__postal_code , address__country , address__facsimile_number , address__telephone_number , address__electronic_mail_address , address__telex_number , organizations,description, ): + address.__init__(self , address__internal_location , address__street_number , address__street , address__postal_box , address__town , address__region , address__postal_code , address__country , address__facsimile_number , address__telephone_number , address__electronic_mail_address , address__telex_number , ) + self.organizations = organizations + self.description = description + + @apply + def organizations(): + def fget( self ): + return self._organizations + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument organizations is mantatory and can not be set to None') + if not check_type(value,SET(1,None,'organization')): + self._organizations = SET(value) + else: + self._organizations = value + return property(**locals()) + + @apply + def description(): + def fget( self ): + return self._description + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._description = STRING(value) + else: + self._description = value + return property(**locals()) + +#################### + # ENTITY person # +#################### +class person(BaseEntityClass): + '''Entity person definition. + + :param id + :type id:STRING + + :param last_name + :type last_name:STRING + + :param first_name + :type first_name:STRING + + :param middle_names + :type middle_names:LIST(1,None,'STRING') + + :param prefix_titles + :type prefix_titles:LIST(1,None,'STRING') + + :param suffix_titles + :type suffix_titles:LIST(1,None,'STRING') + ''' + def __init__( self , id,last_name,first_name,middle_names,prefix_titles,suffix_titles, ): + self.id = id + self.last_name = last_name + self.first_name = first_name + self.middle_names = middle_names + self.prefix_titles = prefix_titles + self.suffix_titles = suffix_titles + + @apply + def id(): + def fget( self ): + return self._id + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument id is mantatory and can not be set to None') + if not check_type(value,STRING): + self._id = STRING(value) + else: + self._id = value + return property(**locals()) + + @apply + def last_name(): + def fget( self ): + return self._last_name + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._last_name = STRING(value) + else: + self._last_name = value + return property(**locals()) + + @apply + def first_name(): + def fget( self ): + return self._first_name + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._first_name = STRING(value) + else: + self._first_name = value + return property(**locals()) + + @apply + def middle_names(): + def fget( self ): + return self._middle_names + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,LIST(1,None,'STRING')): + self._middle_names = LIST(value) + else: + self._middle_names = value + return property(**locals()) + + @apply + def prefix_titles(): + def fget( self ): + return self._prefix_titles + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,LIST(1,None,'STRING')): + self._prefix_titles = LIST(value) + else: + self._prefix_titles = value + return property(**locals()) + + @apply + def suffix_titles(): + def fget( self ): + return self._suffix_titles + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,LIST(1,None,'STRING')): + self._suffix_titles = LIST(value) + else: + self._suffix_titles = value + return property(**locals()) + +#################### + # ENTITY organization # +#################### +class organization(BaseEntityClass): + '''Entity organization definition. + + :param id + :type id:STRING + + :param name + :type name:STRING + + :param description + :type description:STRING + ''' + def __init__( self , id,name,description, ): + self.id = id + self.name = name + self.description = description + + @apply + def id(): + def fget( self ): + return self._id + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._id = STRING(value) + else: + self._id = value + return property(**locals()) + + @apply + def name(): + def fget( self ): + return self._name + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument name is mantatory and can not be set to None') + if not check_type(value,STRING): + self._name = STRING(value) + else: + self._name = value + return property(**locals()) + + @apply + def description(): + def fget( self ): + return self._description + def fset( self, value ): + if value != None: # OPTIONAL attribute + if not check_type(value,STRING): + self._description = STRING(value) + else: + self._description = value + return property(**locals()) + +#################### + # ENTITY person_and_organization_address # +#################### +class person_and_organization_address(organizational_address,personal_address): + '''Entity person_and_organization_address definition. + + :param organizational_address_organizations + :type organizational_address_organizations:SET(1,1,'organization') + + :param personal_address_people + :type personal_address_people:SET(1,1,'person') + ''' + def __init__( self , organizational_address__organizations , organizational_address__description , personal_address__people , personal_address__description , organizational_address_organizations,personal_address_people, ): + organizational_address.__init__(self , organizational_address__organizations , organizational_address__description , ) + personal_address.__init__(self , personal_address__people , personal_address__description , ) + self.organizational_address_organizations = organizational_address_organizations + self.personal_address_people = personal_address_people + + @apply + def organizational_address_organizations(): + def fget( self ): + return self._organizational_address_organizations + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument organizational_address_organizations is mantatory and can not be set to None') + if not check_type(value,SET(1,1,'organization')): + self._organizational_address_organizations = SET(value) + else: + self._organizational_address_organizations = value + return property(**locals()) + + @apply + def personal_address_people(): + def fget( self ): + return self._personal_address_people + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument personal_address_people is mantatory and can not be set to None') + if not check_type(value,SET(1,1,'person')): + self._personal_address_people = SET(value) + else: + self._personal_address_people = value + return property(**locals()) diff --git a/src/fedex_python/examples/unitary_schemas/test_named_type.py b/src/fedex_python/examples/unitary_schemas/test_named_type.py new file mode 100644 index 000000000..5020f9b0c --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/test_named_type.py @@ -0,0 +1,37 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * +measure = REAL +type2 = INTEGER + +#################### + # ENTITY line # +#################### +class line(BaseEntityClass): + '''Entity line definition. + + :param line_length + :type line_length:REAL + ''' + def __init__( self , line_length, ): + self.line_length = line_length + + @apply + def line_length(): + def fget( self ): + return self._line_length + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument line_length is mantatory and can not be set to None') + if not check_type(value,REAL): + self._line_length = REAL(value) + else: + self._line_length = value + return property(**locals()) diff --git a/src/fedex_python/examples/unitary_schemas/test_select_data_type.py b/src/fedex_python/examples/unitary_schemas/test_select_data_type.py new file mode 100644 index 000000000..81652a777 --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/test_select_data_type.py @@ -0,0 +1,253 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * +# SELECT TYPE permanent_attachment_ +if (not 'glue' in globals().keys()): + glue = 'glue' +if (not 'weld' in globals().keys()): + weld = 'weld' +permanent_attachment = SELECT( + 'glue', + 'weld') +# SELECT TYPE temporary_attachment_ +if (not 'nail' in globals().keys()): + nail = 'nail' +if (not 'screw' in globals().keys()): + screw = 'screw' +temporary_attachment = SELECT( + 'nail', + 'screw') +# SELECT TYPE attachment_method_ +if (not 'permanent_attachment' in globals().keys()): + permanent_attachment = 'permanent_attachment' +if (not 'temporary_attachment' in globals().keys()): + temporary_attachment = 'temporary_attachment' +attachment_method = SELECT( + 'permanent_attachment', + 'temporary_attachment') + +#################### + # ENTITY weld # +#################### +class weld(BaseEntityClass): + '''Entity weld definition. + + :param composition + :type composition:STRING + ''' + def __init__( self , composition, ): + self.composition = composition + + @apply + def composition(): + def fget( self ): + return self._composition + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument composition is mantatory and can not be set to None') + if not check_type(value,STRING): + self._composition = STRING(value) + else: + self._composition = value + return property(**locals()) + +#################### + # ENTITY glue # +#################### +class glue(BaseEntityClass): + '''Entity glue definition. + + :param composition + :type composition:STRING + + :param solvent + :type solvent:STRING + ''' + def __init__( self , composition,solvent, ): + self.composition = composition + self.solvent = solvent + + @apply + def composition(): + def fget( self ): + return self._composition + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument composition is mantatory and can not be set to None') + if not check_type(value,STRING): + self._composition = STRING(value) + else: + self._composition = value + return property(**locals()) + + @apply + def solvent(): + def fget( self ): + return self._solvent + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument solvent is mantatory and can not be set to None') + if not check_type(value,STRING): + self._solvent = STRING(value) + else: + self._solvent = value + return property(**locals()) + +#################### + # ENTITY wall_mounting # +#################### +class wall_mounting(BaseEntityClass): + '''Entity wall_mounting definition. + + :param mounting + :type mounting:STRING + + :param on + :type on:STRING + + :param using + :type using:attachment_method + ''' + def __init__( self , mounting,on,using, ): + self.mounting = mounting + self.on = on + self.using = using + + @apply + def mounting(): + def fget( self ): + return self._mounting + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument mounting is mantatory and can not be set to None') + if not check_type(value,STRING): + self._mounting = STRING(value) + else: + self._mounting = value + return property(**locals()) + + @apply + def on(): + def fget( self ): + return self._on + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument on is mantatory and can not be set to None') + if not check_type(value,STRING): + self._on = STRING(value) + else: + self._on = value + return property(**locals()) + + @apply + def using(): + def fget( self ): + return self._using + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument using is mantatory and can not be set to None') + if not check_type(value,attachment_method): + self._using = attachment_method(value) + else: + self._using = value + return property(**locals()) + +#################### + # ENTITY screw # +#################### +class screw(BaseEntityClass): + '''Entity screw definition. + + :param body_length + :type body_length:REAL + + :param pitch + :type pitch:REAL + ''' + def __init__( self , body_length,pitch, ): + self.body_length = body_length + self.pitch = pitch + + @apply + def body_length(): + def fget( self ): + return self._body_length + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument body_length is mantatory and can not be set to None') + if not check_type(value,REAL): + self._body_length = REAL(value) + else: + self._body_length = value + return property(**locals()) + + @apply + def pitch(): + def fget( self ): + return self._pitch + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument pitch is mantatory and can not be set to None') + if not check_type(value,REAL): + self._pitch = REAL(value) + else: + self._pitch = value + return property(**locals()) + +#################### + # ENTITY nail # +#################### +class nail(BaseEntityClass): + '''Entity nail definition. + + :param body_length + :type body_length:REAL + + :param head_area + :type head_area:REAL + ''' + def __init__( self , body_length,head_area, ): + self.body_length = body_length + self.head_area = head_area + + @apply + def body_length(): + def fget( self ): + return self._body_length + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument body_length is mantatory and can not be set to None') + if not check_type(value,REAL): + self._body_length = REAL(value) + else: + self._body_length = value + return property(**locals()) + + @apply + def head_area(): + def fget( self ): + return self._head_area + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument head_area is mantatory and can not be set to None') + if not check_type(value,REAL): + self._head_area = REAL(value) + else: + self._head_area = value + return property(**locals()) diff --git a/src/fedex_python/examples/unitary_schemas/test_single_inheritance.py b/src/fedex_python/examples/unitary_schemas/test_single_inheritance.py new file mode 100644 index 000000000..b7873a7fa --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/test_single_inheritance.py @@ -0,0 +1,101 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * +length_measure = REAL +label = STRING +point = REAL + +#################### + # ENTITY shape # +#################### +class shape(BaseEntityClass): + '''Entity shape definition. + + :param item_name + :type item_name:STRING + + :param number_of_sides + :type number_of_sides:INTEGER + ''' + def __init__( self , item_name,number_of_sides, ): + self.item_name = item_name + self.number_of_sides = number_of_sides + + @apply + def item_name(): + def fget( self ): + return self._item_name + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument item_name is mantatory and can not be set to None') + if not check_type(value,STRING): + self._item_name = STRING(value) + else: + self._item_name = value + return property(**locals()) + + @apply + def number_of_sides(): + def fget( self ): + return self._number_of_sides + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument number_of_sides is mantatory and can not be set to None') + if not check_type(value,INTEGER): + self._number_of_sides = INTEGER(value) + else: + self._number_of_sides = value + return property(**locals()) + +#################### + # ENTITY rectangle # +#################### +class rectangle(shape): + '''Entity rectangle definition. + + :param height + :type height:REAL + + :param width + :type width:REAL + ''' + def __init__( self , shape__item_name , shape__number_of_sides , height,width, ): + shape.__init__(self , shape__item_name , shape__number_of_sides , ) + self.height = height + self.width = width + + @apply + def height(): + def fget( self ): + return self._height + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument height is mantatory and can not be set to None') + if not check_type(value,REAL): + self._height = REAL(value) + else: + self._height = value + return property(**locals()) + + @apply + def width(): + def fget( self ): + return self._width + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument width is mantatory and can not be set to None') + if not check_type(value,REAL): + self._width = REAL(value) + else: + self._width = value + return property(**locals()) diff --git a/src/fedex_python/examples/unitary_schemas/test_single_inheritance_multi_level.py b/src/fedex_python/examples/unitary_schemas/test_single_inheritance_multi_level.py new file mode 100644 index 000000000..b241d55ec --- /dev/null +++ b/src/fedex_python/examples/unitary_schemas/test_single_inheritance_multi_level.py @@ -0,0 +1,110 @@ +# This file was generated by fedex_python. You probably don't want to edit +# it since your modifications will be lost if fedex_plus is used to +# regenerate it. +from SCL.SCLBase import * +from SCL.SimpleDataTypes import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * +from SCL.TypeChecker import check_type +from SCL.Expr import * +length_measure = REAL +label = STRING +point = REAL + +#################### + # ENTITY shape # +#################### +class shape(BaseEntityClass): + '''Entity shape definition. + + :param item_name + :type item_name:STRING + + :param number_of_sides + :type number_of_sides:INTEGER + ''' + def __init__( self , item_name,number_of_sides, ): + self.item_name = item_name + self.number_of_sides = number_of_sides + + @apply + def item_name(): + def fget( self ): + return self._item_name + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument item_name is mantatory and can not be set to None') + if not check_type(value,STRING): + self._item_name = STRING(value) + else: + self._item_name = value + return property(**locals()) + + @apply + def number_of_sides(): + def fget( self ): + return self._number_of_sides + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument number_of_sides is mantatory and can not be set to None') + if not check_type(value,INTEGER): + self._number_of_sides = INTEGER(value) + else: + self._number_of_sides = value + return property(**locals()) + +#################### + # ENTITY subshape # +#################### +class subshape(shape): + '''Entity subshape definition. + ''' + def __init__( self , shape__item_name , shape__number_of_sides , ): + shape.__init__(self , shape__item_name , shape__number_of_sides , ) + +#################### + # ENTITY rectangle # +#################### +class rectangle(subshape): + '''Entity rectangle definition. + + :param height + :type height:REAL + + :param width + :type width:REAL + ''' + def __init__( self , height,width, ): + subshape.__init__(self , ) + self.height = height + self.width = width + + @apply + def height(): + def fget( self ): + return self._height + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument height is mantatory and can not be set to None') + if not check_type(value,REAL): + self._height = REAL(value) + else: + self._height = value + return property(**locals()) + + @apply + def width(): + def fget( self ): + return self._width + def fset( self, value ): + # Mandatory argument + if value==None: + raise AssertionError('Argument width is mantatory and can not be set to None') + if not check_type(value,REAL): + self._width = REAL(value) + else: + self._width = value + return property(**locals()) diff --git a/src/fedex_python/python/SCL/AggregationDataTypes.py b/src/fedex_python/python/SCL/AggregationDataTypes.py new file mode 100644 index 000000000..ec77152e1 --- /dev/null +++ b/src/fedex_python/python/SCL/AggregationDataTypes.py @@ -0,0 +1,265 @@ +# Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) +# All rights reserved. + +# This file is part of the StepClassLibrary (SCL). +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of the nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from SimpleDataTypes import * +from TypeChecker import * + +class BaseAggregate(object): + """ A class that define common properties to ARRAY, LIST, SET and BAG. + """ + def __init__( self , bound1 , bound2 , base_type ): + # check that bound1bound2: + raise AssertionError("bound1 shall be less than or equal to bound2") + self._bound1 = bound1 + self._bound2 = bound2 + self._base_type = base_type + + def __getitem__(self, index): + if indexself._bound2): + raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound2,index)) + else: + return list.__getitem__(self,index) + + def __setitem__(self,index,value): + if indexself._bound2): + raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound2,index)) + elif not isinstance(value,self._base_type): + raise TypeError("%s type expected, passed %s."%(self._base_type, type(value))) + else: + # first find the length of the list, and extend it if ever + # the index is + list.__setitem__(self,index,value) + +class ARRAY(object): + """An array data type has as its domain indexed, fixed-size collections of like elements. The lower + and upper bounds, which are integer-valued expressions, define the range of index values, and + thus the size of each array collection. + An array data type definition may optionally specify + that an array value cannot contain duplicate elements. + It may also specify that an array value + need not contain an element at every index position. + + Given that m is the lower bound and n is the upper bound, there are exactly n-m+1 elements + in the array. These elements are indexed by subscripts from m to n, inclusive (see 12.6.1). + NOTE 1 { The bounds may be positive, negative or zero, but may not be indeterminate (?) (see + 14.2). + """ + def __init__( self , bound_1 , bound_2 , base_type , UNIQUE = False, OPTIONAL=False): + if not type(bound_1)==int: + raise TypeError("ARRAY lower bound must be an integer") + if not type(bound_2)==int: + raise TypeError("ARRAY upper bound must be an integer") + if not (bound_1 <= bound_2): + raise AssertionError("ARRAY lower bound must be less than or equal to upper bound") + # the base type can be either a type or a string that defines a type + if type(base_type)==str: + if globals().has_key(base_type): + self._base_type = globals()[base_type] + else: + raise TypeError("%s does not name a type"%base_type) + else: + self._base_type = base_type + # set up class attributes + self._bound_1 = bound_1 + self._bound_2 = bound_2 + self._unique = UNIQUE + self._optional = OPTIONAL + # preallocate list elements + list_size = bound_2 - bound_1 + 1 + self._container = list_size*[None] + + def bound_1(self): + return self._bound_1 + + def bound_2(self): + return self._bound_2 + + def __getitem__(self, index): + if indexself._bound_2): + raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound_2,index)) + else: + value = self._container[index-self._bound_1] + if not self._optional and value==None: + raise AssertionError("Not OPTIONAL prevent the value with index %i from being None (default). Please set the value first."%index) + return value + + def __setitem__(self, index, value): + if indexself._bound_2): + raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound_2,index)) + else: + # first check the type of the value + check_type(value,self._base_type) + # then check if the value is already in the array + if self._unique: + if value in self._container: + raise AssertionError("UNIQUE keyword prevent inserting this instance.") + self._container[index-self._bound_1] = value + +class LIST(object): + """A list data type has as its domain sequences of like elements. The optional lower and upper + bounds, which are integer-valued expressions, define the minimum and maximum number of + elements that can be held in the collection defined by a list data type. + A list data type + definition may optionally specify that a list value cannot contain duplicate elements. + """ + def __init__( self , bound_1 , bound_2 , base_type , UNIQUE = False): + if not type(bound_1)==int: + raise TypeError("LIST lower bound must be an integer") + # bound_2 can be set to None + self._unbounded = False + if bound_2 == None: + self._unbounded = True + elif not type(bound_2)==int: + raise TypeError("LIST upper bound must be an integer") + if not bound_1>=0: + raise AssertionError("LIST lower bound must be greater of equal to 0") + if (type(bound_2)==int and not (bound_1 <= bound_2)): + raise AssertionError("ARRAY lower bound must be less than or equal to upper bound") + # set up class attributes + self._bound_1 = bound_1 + self._bound_2 = bound_2 + self._base_type = base_type + self._unique = UNIQUE + # preallocate list elements if bounds are both integers + if not self._unbounded: + list_size = bound_2 - bound_1 + 1 + self._container = list_size*[None] + # for unbounded list, this will come after + else: + self._container = [None] + + def bound_1(self): + return self._bound_1 + + def bound_2(self): + return self._bound_2 + + def __getitem__(self, index): + # case bounded + if not self._unbounded: + if indexself._bound_2): + raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound_2,index)) + else: + value = self._container[index-self._bound_1] + if value == None: + raise AssertionError("Value with index %i not defined. Please set the value first."%index) + return value + #case unbounded + else: + if index-self._bound_1>len(self._container): + raise AssertionError("Value with index %i not defined. Please set the value first."%index) + else: + value = self._container[index-self._bound_1] + if value == None: + raise AssertionError("Value with index %i not defined. Please set the value first."%index) + return value + + def __setitem__(self, index, value): + # case bounded + if not self._unbounded: + if indexself._bound_2): + raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound_2,index)) + else: + # first check the type of the value + check_type(value,self._base_type) + # then check if the value is already in the array + if self._unique: + if value in self._container: + raise AssertionError("UNIQUE keyword prevent inserting this instance.") + self._container[index-self._bound_1] = value + # case unbounded + else: + if index nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import sys + +def type_is_defined(type_str): + """ Look for the type definition in the global scope from the type string. + @TODO: find a better implementation than testing all modules! + """ + modules = sys.modules + for module in modules.values(): + if (module is not None) and (not '__' in module.__name__): + module_variables = vars(module) + if module_variables.has_key(type_str): + typ = module_variables[type_str] + return True, vars(module)[type_str] + return False,None + +class ENUMERATION(object): + """ EXPRESS definition : An ENUMERATION data type has as its domain an ordered set of names. The names represent + values of the enumeration data type. + + Python implementation: + An enumeration is initialized from strings defining the types. + For instance, some EXPRESS definition: + TYPE ahead_or_behind = ENUMERATION OF + (ahead, + behind); + END_TYPE; -- ahead_or_behind + + is implemented in python with the line: + ahead_of_behind = ENUMERATION('ahead','behind') + + The ENUMERATION definition takes python strings because of the resolution ordre + that could be an issue. + + When getting the authorized types but the ENUMERATION, python looks for the object + definition from the globals() dictionary. + """ + + def __init__(self,*kargs): + self._base_types = list(kargs) + + def get_allowed_types(self): + _auth_types = [] + for typ in self._base_types: + if type(typ)==str: + res,value = type_is_defined(typ) + if not res: + raise TypeError("'%s' does not name a type"%typ) + else: + _auth_types.append(value) + else: + _auth_types.append(ty) + return _auth_types + + def get_allowed_basic_types(self): + ''' if a select contains some subselect, goes down through the different + sublayers untill there is no more ''' + b = [] + _auth_types = self.get_allowed_types() + for _auth_type in _auth_types: + if isinstance(_auth_type,SELECT) or isinstance(_auth_type,ENUMERATION): + h = _auth_type.get_allowed_types() + b.extend(h) + return b + +class SELECT(object): + """ A select data type has as its domain the union of the domains of the named data types in + its select list. The select data type is a generalization of each of the named data types in its + select list. + """ + def __init__(self,*kargs): + self._base_types = list(kargs) + + def get_allowed_types(self): + _auth_types = [] + for typ in self._base_types: + if type(typ)==str: + res,value = type_is_defined(typ) + if not res: + raise TypeError("'%s' does not name a type"%typ) + else: + _auth_types.append(value) + else: + _auth_types.append(ty) + return _auth_types + + def get_allowed_basic_types(self): + ''' if a select contains some subselect, goes down through the different + sublayers untill there is no more ''' + b = [] + _auth_types = self.get_allowed_types() + for _auth_type in _auth_types: + if isinstance(_auth_type,SELECT) or isinstance(_auth_type,ENUMERATION): + h = _auth_type.get_allowed_types() + b.extend(h) + return b + +if __name__=='__main__': + class line: + pass + class point: + pass + a = ENUMERATION('line','point') + print a.get_allowed_types() + \ No newline at end of file diff --git a/src/fedex_python/python/SCL/Expr.py b/src/fedex_python/python/SCL/Expr.py new file mode 100644 index 000000000..068242c0b --- /dev/null +++ b/src/fedex_python/python/SCL/Expr.py @@ -0,0 +1,71 @@ +# Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) +# All rights reserved. + +# This file is part of the StepClassLibrary (SCL). +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of the nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from math import * +PI = pi #in EXPRESS, PI is uppercase + +def EvalDerivedAttribute(class_instance, str_expr): + ''' + This functions tries to evaluate EXPRESS math expr. + For instance in the following example: + == + ENTITY circle; + centre : point; + radius : REAL; + axis : vector; + DERIVE + area : REAL := PI*radius**2; + perimeter : REAL := 2.0*PI*radius; + + END_ENTITY; + == + The following string should be passed to EvalExpr: + 'PI*radius**2' + ''' + # first, try to find class paramters + # in the previous example, we should replace radius with self.radius before eval'ing expr + props = [] + for prop in dir(class_instance): + if not prop.startswith("_"): #means prop is an item that might be considered + props.append(prop) + for item in props: + str_expr = str_expr.replace(item,"class_instance.%s"%item) + # after that step, the expression should be: + # PI*class_instance.radius*class_instance.radius + # this can be evaluated with the eval function + # CAREFUL: eval is known to be unsafe. This should be changed in the future + # (using a parser, or simpy for instance) + try: + return eval(str_expr.lower()) + except: + print 'Error evaluating expression' + return None + diff --git a/src/fedex_python/python/SCL/Model.py b/src/fedex_python/python/SCL/Model.py new file mode 100644 index 000000000..9a3f0e87b --- /dev/null +++ b/src/fedex_python/python/SCL/Model.py @@ -0,0 +1,55 @@ +# Copyright (c) 2011-2012, Thomas Paviot (tpaviot@gmail.com) +# All rights reserved. + +# This file is part of the StepClassLibrary (SCL). +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of the nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +class Model(objet): + """ The container for entity instances + """ + def __init_(self): + print "Model initialized" + self._instances = [] + + def add_instance(self, entity_instance): + self._instances.append(entity_instance) + + def remove_instance(self, entity_instance): + self._instances.remove(entity_instance) + + def get_instances(self): + return self._instances + + def export_to_p21file(self, filename): + raise AssertionError("Not implemented") + + def export_to_p28file(self, filename): + raise AssertionError("Not implemented") + + + diff --git a/src/fedex_python/python/SCL/Part21.py b/src/fedex_python/python/SCL/Part21.py new file mode 100644 index 000000000..41223d2f2 --- /dev/null +++ b/src/fedex_python/python/SCL/Part21.py @@ -0,0 +1,207 @@ +# Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) +# All rights reserved. + +# This file is part of the StepClassLibrary (SCL). +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of the nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import re +import Utils + +INSTANCE_DEFINITION_RE = re.compile("#(\d+)[^\S\n]?=[^\S\n]?(.*?)\((.*)\)[^\S\n]?;[\\r]?$") + +def map_string_to_num(stri): + """ Take a string, check wether it is an integer, a float or not + """ + if ('.' in stri) or ('E' in stri): #it's definitely a float + return REAL(stri) + else: + return INTEGER(stri) + +class Model: + """ + A model contains a list of instances + """ + def __init__(self,name): + self._name = name + # a dict of instances + # each time an instance is added to the model, count is incremented + self._instances = {} + self._number_of_instances = 0 + + def add_instance(self, instance): + ''' + Adds an instance to the model + ''' + self._number_of_instances += 1 + self._instances[self._number_of_instances-1] = instance + + def print_instances(self): + ''' + Dump instances to stdout + ''' + for idx in range(self._number_of_instances): + "==========" + print "Instance #%i"%(idx+1) + print self._instances[idx] + +class Part21EntityInstance: + """ + A class to represent a Part21 instance as defined in one Part21 file + A Part21EntityInstance is defined by the following arguments: + entity_name: a string + entity_attributes: a list of strings to represent an attribute. + For instance, the following expression: + #4 = PRODUCT_DEFINITION_SHAPE('$','$',#5); + will result in : + entity : + entity_instance_attributes: ['$','$','#5'] + """ + def __init__(self,entity_name,attributes): + self._entity + self._attributes_definition = attributes + print self._entity_name + print self._attributes_definition + + +class Part21Parser: + """ + Loads all instances definition of a Part21 file into memory. + Two dicts are created: + self._instance_definition : stores attibutes, key is the instance integer id + self._number_of_ancestors : stores the number of ancestors of entity id. This enables + to define the order of instances creation. + """ + def __init__(self, filename): + self._filename = filename + # the schema + self._schema_name = "" + # the dict self._instances contain instance definition + self._instances_definition = {} + # this dict contains lists of 0 ancestors, 1 ancestor, etc. + # initializes this dict + self._number_of_ancestors = {} + for i in range(2000): + self._number_of_ancestors[i]=[] + self.parse_file() + # reduce number_of_ancestors dict + for item in self._number_of_ancestors.keys(): + if len(self._number_of_ancestors[item])==0: + del self._number_of_ancestors[item] + + def get_schema_name(self): + return self._schema_name + print schema_name + + def get_number_of_instances(self): + return len(self._instances_definition.keys()) + + def parse_file(self): + init_time = time.time() + print "Parsing file %s..."%self._filename, + fp = open(self._filename) + while True: + line = fp.readline() + if not line: + break + # there may be a multline definition. In this case, we read lines untill we found + # a ; + #while (not line.endswith(";\r\n")): #its a multiline + # line = line.replace("\r\n","") + fp.readline() + # parse line + match_instance_definition = INSTANCE_DEFINITION_RE.search(line) # id,name,attrs + if match_instance_definition: + instance_id, entity_name, entity_attrs = match_instance_definition.groups() + instance_int_id = int(instance_id) + # find number of ancestors + number_of_ancestors = entity_attrs.count('#') + # fill number of ancestors dict + self._number_of_ancestors[number_of_ancestors].append(instance_int_id) + # parse attributes string + entity_attrs_list, str_len = Utils.process_nested_parent_str(entity_attrs) + # then finally append this instance to the disct instance + self._instances_definition[instance_int_id] = (entity_name,entity_attrs_list) + else: #does not match with entity instance definition, parse the header + if line.startswith('FILE_SCHEMA'): + #identify the schema name + self._schema_name = line.split("'")[1].split("'")[0].split(" ")[0].lower() + fp.close() + print 'done in %fs.'%(time.time()-init_time) + print 'schema: - %s entities %i'%(self._schema_name,len(self._instances_definition.keys())) + +class EntityInstancesFactory(object): + ''' + This class creates entity instances from the str definition + For instance, the definition: + 20: ('CARTESIAN_POINT', ["''", '(5.,125.,20.)']) + will result in: + p = ARRAY(1,3,REAL) + p.[1] = REAL(5) + p.[2] = REAL(125) + p.[3] = REAL(20) + new_instance = cartesian_point(STRING(''),p) + ''' + def __init__(self, schema_name, instance_definition): + # First try to import the schema module + pass + +class Part21Population(object): + def __init__(self, part21_loader): + """ Take a part21_loader a tries to create entities + """ + self._part21_loader = part21_loader + self._aggregate_scope = [] + self._aggr_scope = False + self.create_entity_instances() + + def create_entity_instances(self): + """ Starts entity instances creation + """ + for number_of_ancestor in self._part21_loader._number_of_ancestors.keys(): + for entity_definition_id in self._part21_loader._number_of_ancestors[number_of_ancestor]: + self.create_entity_instance(entity_definition_id) + + def create_entity_instance(self, instance_id): + instance_definition = self._part21_loader._instances_definition[instance_id] + print "Instance definition to process",instance_definition + # first find class name + class_name = instance_definition[0].lower() + print "Class name:%s"%class_name + object_ = globals()[class_name] + # then attributes + #print object_.__doc__ + instance_attributes = instance_definition[1] + print "instance_attributes:",instance_attributes + a = object_(*instance_attributes) + +if __name__ == "__main__": + import time + import sys + from config_control_design import * + p21loader = Part21Parser("gasket1.p21") + print "Creating instances" + p21population = Part21Population(p21loader) diff --git a/src/fedex_python/python/SCL/SCLBase.py b/src/fedex_python/python/SCL/SCLBase.py new file mode 100644 index 000000000..617c816ad --- /dev/null +++ b/src/fedex_python/python/SCL/SCLBase.py @@ -0,0 +1,44 @@ +# Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) +# All rights reserved. + +# This file is part of the StepClassLibrary (SCL). +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of the nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +class BaseEntityClass(object): + """ A class that allows advanced __repr__ features for entity instances + """ + def __repr__(self): + """ Displays attribute with their values + """ + doc_string = "# %s class description:\n%s\n# Instance attributes:\n"%(self.__class__,self.__doc__) + # write each argument with its value + properties = dir(self) + for elem in properties: + if not elem.startswith("_"): + doc_string += "\t%s:%s\n"%(elem,self.__getattribute__(elem)) + return doc_string diff --git a/src/fedex_python/python/SCL/SimpleDataTypes.py b/src/fedex_python/python/SCL/SimpleDataTypes.py new file mode 100644 index 000000000..c0a37d4e9 --- /dev/null +++ b/src/fedex_python/python/SCL/SimpleDataTypes.py @@ -0,0 +1,186 @@ +# Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) +# All rights reserved. + +# This file is part of the StepClassLibrary (SCL). +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of the nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +Docstrings are courtesy of ISO 10303-11:1994(E) +""" + +class NUMBER: + """ + The number data type has as its domain all numeric values in the language. The number data + type shall be used when a more specific numeric representation is not important. + + Python mapping: cannot be mapped to a builtin python type. The constructor only checks that + the parameter passed at initialization is a number. + """ + def __init__(self,value): + # should test the type of value (float, or integer) + pass + +class REAL(float): + """ + The real data type has as its domain all rational, irrational and scientfic real numbers. It is + a specialization of the number data type. + Syntax: + 265 real_type = REAL [ '(' precision_spec ')' ] . + 255 precision_spec = numeric_expression . + Rational and irrational numbers have infnite resolution and are exact. Scientific numbers rep- + resent quantities which are known only to a specified precision. The precision_spec is stated + in terms of significant digits. + A real number literal is represented by a mantissa and optional exponent. The number of digits + making up the mantissa when all leading zeros have been removed is the number of significant + digits. The known precision of a value is the number of leading digits that are necessary to the + application. + Rules and restrictions: + a) The precision_spec gives the minimum number of digits of resolution that are re- + quired. This expression shall evaluate to a positive integer value. + b) When no resolution specification is given the precision of the real number is uncon- + strained. + + Python mapping: REAL is mapped to 'float' type + """ + pass + +class INTEGER(int): + """ + The integer data type has as its domain all integer numbers. It is a specialization of the real + data type. + + Python mapping: INTEGER is mapped to 'int' type""" + pass + +class STRING(str): + """ + The string data type has as its domain sequences of characters. The characters which are + permitted to form part of a string value are de ned in ISO 10646. + Syntax: + 293 string_type = STRING [ width_spec ] . + 318 width_spec = '(' width ')' [ FIXED ] . + 317 width = numeric_expression . + A string data type may be de ned as either xed or varying width (number of characters). If + it is not specfically defined as fixed width (by using the fixed reserved word in the dfinition) + the string has varying width. + + The domain of a xed width string data type is the set of all character sequences of exactly + the width speci ed in the type de nition. + The domain of a varying width string data type is the set of all character sequences of width + less than or equal to the maximum width speci ed in the type de nition. + If no width is speci ed, the domain is the set of all character sequences, with no constraint on + the width of these sequences. + Substrings and individual characters may be addressed using subscripts as described in 12.5. + The case (upper or lower) of letters within a string is signi cant. + + Python mapping: INTEGER is mapped the 'str' type. An additional width_spec parameter can be passed + to handle the FIXED length constraint + """ + pass + +class LOGICAL: + """ + The logical data type has as its domain the three literals true, false and unknown. + Syntax: + 243 logical_type = LOGICAL . + The following ordering holds for the values of the logical data type: false < unknown < + true. The logical data type is compatible with the boolean data type, except that the value + unknown cannot be assigned to a boolean variable. + """ + pass +Unknown = LOGICAL() + +# +#The boolean data type has as its domain the two literals true and false. The boolean data +#type is a specialization of the logical data type. +# +#Python mapping: BOOLEAN is mapped to 'bool' type +# +# The bool data type can't however be subclassed in Python (see +# See http://mail.python.org/pipermail/python-dev/2002-March/020822.html) +# so it is just set to bool +BOOLEAN = bool + +class BINARY(str): + """ + The binary data type has as its domain sequences of bits, each bit being represented by 0 or 1. + Syntax: + 172 binary_type = BINARY [ width_spec ] . + 318 width_spec = '(' width ')' [ FIXED ] . + 317 width = numeric_expression . + A binary data type may be defined as either fixed or varying width (number of bits). If it is + not specifically defined as fixed width (by using the fixed reserved word in the definition) the + binary data type has varying width. + The domain of a fixed width binary data type is the set of all bit sequences of exactly the width + speci ed in the type definition. + The domain of a varying width binary data type is the set of all bit sequences of width less + than or equal to the maximum width speci ed in the type de nition. If no width is specified, + the domain is the set of all bit sequences, with no constraint on the width of these sequences. + Subbinaries and individual bits may be addressed using subscripts as described in 12.3. + + Python mapping: BINARY is mapped to the 'str' type. A check is performed to validate it is a binary + string representing a number. + """ + def __new__(self, value, width=-1, fixed=False): + return str.__new__(self, value) + + def __init__(self, value, width=-1, fixed=False): + """ By default, lenght is set to None""" + self._specified_width = width + self._fixed = fixed + # Check implicit width + if (width!=-1) and not fixed: + raise ValueError("The 'width' parameter is passed but 'fixed' is still false. Please explicitely set 'fixed' to True to avoid implicit declaration") + # First check the string length if 'fixed' is set to True + if fixed: + if len(value) != width: + raise ValueError("The BINARY width %i is not consistent with the 'width' declaration(%i)"%(len(value),width)) + # Check that the value passed is actually a binary + try: + int(value,2) + except ValueError: + raise ValueError("%s is not a binary"%value) + + +if __name__=="__main__": + print "Creating REAL from float value" + a = REAL(1.5) + print a*2 + print "Creating REAL from string value" + a = REAL("1.2") + print a*3 + print "Creating INTEGER from int value" + b = INTEGER(2) + c = INTEGER(3) + print b+c + print "Creating INTEGER from string value" + e = INTEGER("5") + f = INTEGER("8") + print e*f + + \ No newline at end of file diff --git a/src/fedex_python/python/SCL/TypeChecker.py b/src/fedex_python/python/SCL/TypeChecker.py new file mode 100644 index 000000000..7c6db89bd --- /dev/null +++ b/src/fedex_python/python/SCL/TypeChecker.py @@ -0,0 +1,73 @@ +# Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) +# All rights reserved. + +# This file is part of the StepClassLibrary (SCL). +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of the nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from ConstructedDataTypes import ENUMERATION, SELECT + +RAISE_EXCEPTION_IF_TYPE_DOES_NOT_MATCH = True + +def cast_python_object_to_aggregate(obj, aggregate): + """ This function casts a python object to an aggregate type. For instance: + [1.,2.,3.]-> ARRAY(1,3,REAL)""" + aggregate_lower_bound = aggregate.bound_1() + aggregate_upper_bound = aggregate.bound_2() + if type(obj)==list: + for idx in range(aggregate_lower_bound,aggregate_upper_bound+1): + aggregate[idx] = obj[idx-aggregate_lower_bound] + return aggregate + +def check_type(instance, expected_type): + """ This function checks wether an object is an instance of a given class + returns False or True + """ + type_match = False #by default, will be set to True if any match + # in the case of an enumeration, we have to check if the instance is in the list + if (isinstance(expected_type,SELECT) or isinstance(expected_type,ENUMERATION)): + # we check if the instance is of the type of any of the types that are in the SELECT + allowed_types = expected_type.get_allowed_basic_types() + #if instance in allowed_types: + for allowed_type in allowed_types: + if isinstance(instance,allowed_type): + type_match = True + if not type_match: + if RAISE_EXCEPTION_IF_TYPE_DOES_NOT_MATCH: + raise TypeError('Argument type must be %s (you passed %s)'%(allowed_types,type(instance))) + else: + print "WARNING: expected '%s' but passed a '%s', casting from python value to EXPRESS type"%(allowed_types, type(instance)) + return False + else: + type_match = isinstance(instance,expected_type) + if not type_match: + if RAISE_EXCEPTION_IF_TYPE_DOES_NOT_MATCH: + raise TypeError('Argument type must be %s (you passed %s)'%(expected_type,type(instance))) + else: + print "WARNING: expected '%s' but passed a '%s', casting from python value to EXPRESS type"%(expected_type, type(instance)) + return False + return True diff --git a/src/fedex_python/python/SCL/Utils.py b/src/fedex_python/python/SCL/Utils.py new file mode 100644 index 000000000..7cce22494 --- /dev/null +++ b/src/fedex_python/python/SCL/Utils.py @@ -0,0 +1,70 @@ +# Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) +# All rights reserved. + +# This file is part of the StepClassLibrary (SCL). +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of the nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +''' This module provide string utils''' + +def process_nested_parent_str(attr_str,idx=0): + ''' + The first letter should be a parenthesis + input string: "(1,4,(5,6),7)" + output: ['1','4',['5','6'],'7'] + ''' + params = [] + current_param = '' + k = 0 + while (k nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest + +from SCL.SimpleDataTypes import * +from SCL.TypeChecker import * +from SCL.ConstructedDataTypes import * +from SCL.AggregationDataTypes import * + +# +# Simple data types +# +class TestINTEGER(unittest.TestCase): + ''' + INTEGER test + ''' + def test_create_from_int(self): + a = INTEGER(1) + self.assertEqual(a,1) + b = REAL(0) + self.assertEqual(b,0) + + def test_create_from_string(self): + a = REAL("10") + self.assertEqual(a,10) + b = REAL("0") + self.assertEqual(b,0) + + def test_type(self): + a = INTEGER(5) + self.assertTrue(type(a) == INTEGER) + + def test_INTEGER_ops(self): + a = INTEGER(2) + b = INTEGER(3) + c = a*b + self.assertEqual(c,6) + self.assertTrue(type(c) == int) + + def test_create_from_string_exception(self): + ''' + INT cannot be constructed from an ascii string + ''' + try: + INTEGER("c") + except ValueError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + +class TestREAL(unittest.TestCase): + ''' + REAL test + ''' + def test_create_from_float(self): + a = REAL(1.5) + self.assertEqual(a,1.5) + b = REAL(0) + self.assertEqual(b,0) + + def test_create_from_string(self): + a = REAL("1.5") + self.assertEqual(a,1.5) + b = REAL("0") + self.assertEqual(b,0) + + def test_type(self): + a = REAL(5) + self.assertTrue(type(a) == REAL) + + def test_REAL_ops(self): + a = REAL(1.5) + b = REAL(2) + c = a*b + self.assertEqual(c,3) + self.assertTrue(type(c) == float) + + def test_REAL_INTEGER_ops(self): + a = REAL(5.5) + b = INTEGER(3) + self.assertEqual(a+b,8.5) + self.assertTrue(type(a+b) == float) + + def test_create_from_string_exception(self): + ''' + REAL cannot be constructed from an ascii string + ''' + try: + REAL("c") + except ValueError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + +class TestBOOLEAN(unittest.TestCase): + ''' + BOOLEAN test + ''' + def test_create_from_bool(self): + a = BOOLEAN(True) + self.assertTrue(a) + b = BOOLEAN(False) + self.assertFalse(b) + +# +# AggregationDataTypeSimple +# +class TestARRAY(unittest.TestCase): + ''' + ARRAY test + ''' + def test_create_array(self): + ARRAY(1,7,REAL) + #upper and lower bounds can be negative + ARRAY(-1,5,INTEGER) + ARRAY(-4,-3,INTEGER) + # they even can be both 0 + ARRAY(0,0,REAL) + ARRAY(1,1,BOOLEAN) + # lower bound should be less or equal than upper bound + try: + ARRAY(3,2,REAL) + except AssertionError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + + def test_array_bounds(self): + a = ARRAY(3,8,REAL) + try: + a[2] + except IndexError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + try: + a[9] + except IndexError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + + def test_array_unique(self): + # if UNIQUE is not set to True (False by default), + # the array may contain the same instance at different + # positions + a = ARRAY(1,4,REAL) + a[3] = REAL(4) + a[4] = REAL(4) + # however, if UNIQUE, then every instances in the + # array must be different + a = ARRAY(1,4,REAL,UNIQUE=True) + a[3] = REAL(4) + try: + a[3] = REAL(4) + except AssertionError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + + def test_array_optional(self): + # if OPTIONAL is not set explicitely to True + # then each value must be set + a = ARRAY(1,3,REAL) + try: + a[1] + except AssertionError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + # if OPTIONAL is set to True, then values + # can be indeterminated + b = ARRAY(1,3,REAL,OPTIONAL=True) + b[2] = REAL(5) + b[3] = REAL(5) + +# +# AggregationDataTypeSimple +# +class TestLIST(unittest.TestCase): + ''' + LIST test + ''' + def test_create_bounded_list(self): + LIST(1,7,REAL) + #upper and lower bounds can be negative + LIST(1,5,INTEGER) + # they even can be both 0 + LIST(0,0,REAL) + LIST(1,1,BOOLEAN) + # lower bound should be less or equal than upper bound + try: + LIST(3,2,REAL) + except AssertionError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + # lower bound should be greater or equal than zero + try: + LIST(-1,2,REAL) + except AssertionError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + + def test_create_unbounded_list(self): + a = LIST(0,None,REAL) + a[6] = REAL(6) + self.assertEqual(a[6],6) + b = LIST(10,None,REAL) + a[10] = REAL(7) + self.assertEqual(a[10],7) + + def test_list_bounds(self): + a = LIST(3,8,REAL) + try: + a[2] + except IndexError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + try: + a[9] + except IndexError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + + def test_list_unique(self): + # if UNIQUE is not set to True (False by default), + # the array may contain the same instance at different + # positions + a = LIST(1,4,REAL) + a[3] = REAL(4) + a[4] = REAL(4) + # however, if UNIQUE, then every instances in the + # array must be different + a = LIST(1,4,REAL,UNIQUE=True) + a[3] = REAL(4) + try: + a[3] = REAL(4) + except AssertionError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + +# +# TypeChecker +# +class TestTypeChecker(unittest.TestCase): + def test_match_type(self): + class P: + pass + p = P() + match_type = check_type(p,P) #should return True + self.assertTrue(match_type) + + def test_type_dontmatch(self): + class P: + pass + p = P() + try: + check_type(3,P) + except TypeError: + pass + except e: + self.fail('Unexpected exception thrown:', e) + else: + self.fail('ExpectedException not thrown') + + def test_check_enum_type(self): + enum = ENUMERATION(["my","string"]) + +unittest.main() + diff --git a/src/fedex_python/python/setup.py b/src/fedex_python/python/setup.py new file mode 100644 index 000000000..bda974879 --- /dev/null +++ b/src/fedex_python/python/setup.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +# Copyright (c) 2011, Thomas Paviot (tpaviot@gmail.com) +# All rights reserved. + +# This file is part StepClassLibrary (SCL). +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of the nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from distutils.core import setup + +setup(name='SCL', + version='0.5', + description='Python STEP Class Library', + author='Thomas Paviot', + author_email='tpaviot@gmail.com', + url='https://github.com/mpictor/StepClassLibrary', + packages=['SCL'], + ) \ No newline at end of file diff --git a/src/fedex_python/src/classes_misc_python.c b/src/fedex_python/src/classes_misc_python.c new file mode 100644 index 000000000..8032f60ce --- /dev/null +++ b/src/fedex_python/src/classes_misc_python.c @@ -0,0 +1,654 @@ +#define CLASSES_MISC_C +#include +#include "classes.h" +/******************************************************************* +** FedEx parser output module for generating C++ class definitions +** December 5, 1989 +** release 2 17-Feb-1992 +** release 3 March 1993 +** release 4 December 1993 +** K. C. Morris +** +** Development of FedEx was funded by the United States Government, +** and is not subject to copyright. + +******************************************************************* +The conventions used in this binding follow the proposed specification +for the STEP Standard Data Access Interface as defined in document +N350 ( August 31, 1993 ) of ISO 10303 TC184/SC4/WG7. +*******************************************************************/ + +extern int multiple_inheritance; +/*extern int corba_binding; */ + +/****************************************************************** +** The following functions will be used *** +*** through out the the program fedex_plus ***/ + + +/****************************************************************** + ** Procedure: CheckWord + ** Description: if word is a reserved word, it is capitalized + ** Parameters: word -- string to be checked + ** Returns: altered word if word is reserved; otherwise the original word + ** Side Effects: the word is altered in memory + ** Status: started 12/1 + ******************************************************************/ +const char * +CheckWord( const char * word ) { +#ifdef NOT_USING_SDAI_BINDING + /* obsolete with proposed c++ binding */ + + static char * reserved_words [] = { + "application_marker", "asm", "attributes", "auto", + "break", "case", "char", "class", "const", "continue", + "default", "delete", "do", "double", + "else", "enum", "extern", + "float", "for", "friend", "goto", "handle", + "if", "inline", "instance_id", "int", "long", + "new", "nullable", "opcode", "operator", "overload", + "private", "protected", "public", "register", "return", + "shared", "short", "sizeof", "static", "struct", "switch", + "this", "template", "type", "typedef", "type_name", + "union", "unsigned", + "val", "virtual", "void", "volatile" + }; + int nwords = ( sizeof reserved_words / sizeof reserved_words[0] ); + int cond, + i, + low = 0, + high = nwords - 1; + + /* word is obviously not in list, if it is longer than any of the words in the list */ + if( strlen( word ) > 12 ) { + return ( word ); + } + + while( low <= high ) { + i = ( low + high ) / 2; + if( ( cond = strcmp( word, reserved_words [i] ) ) < 0 ) { + high = i - 1; + } else if( cond > 0 ) { + low = i + 1; + } else { /* word is a reserved word, capitalize it */ + printf( "** warning: reserved word %s ", word ); + *( word + 0 ) = toupper( *( word + 0 ) ); + printf( "is changed to %s **\n", word ); + + } + } +#endif + return ( word ); + +} + +/****************************************************************** + ** Procedure: string functions + ** Description: These functions take a character or a string and return + ** a temporary copy of the string with the function applied to it. + ** Parameters: + ** Returns: temporary copy of characters + ** Side Effects: character or string returned persists until the + ** next invocation of the function + ** Status: complete + ******************************************************************/ + +char +ToLower( char c ) { + if( isupper( c ) ) { + return ( tolower( c ) ); + } else { + return ( c ); + } + +} + +char +ToUpper( char c ) { + if( islower( c ) ) { + return ( toupper( c ) ); + } else { + return ( c ); + } +} + +const char * +StrToLower( const char * word ) { + static char newword [MAX_LEN]; + int i = 0; + if( !word ) { + return 0; + } + while( word [i] != '\0' ) { + newword [i] = ToLower( word [i] ); + ++i; + } + newword [i] = '\0'; + return ( newword ) ; + +} + +const char * +StrToUpper( const char * word ) { + static char newword [MAX_LEN]; + int i = 0; + char ToUpper( char c ); + + while( word [i] != '\0' ) { + newword [i] = ToUpper( word [i] ); + ++i; + + } + newword [i] = '\0'; + return ( newword ); +} + +const char * +StrToConstant( const char * word ) { + static char newword [MAX_LEN]; + int i = 0; + + while( word [i] != '\0' ) { + if( word [i] == '/' || word [i] == '.' ) { + newword [i] = '_'; + } else { + newword [i] = ToUpper( word [i] ); + } + ++i; + + } + newword [i] = '\0'; + return ( newword ); +} + +/****************************************************************** + ** Procedure: FILEcreate + ** Description: creates a file for c++ with header definitions + ** Parameters: filename + ** Returns: FILE* pointer to file created or NULL + ** Side Effects: creates a file with name filename + ** Status: complete + ******************************************************************/ + +FILE * +FILEcreate( const char * filename ) { + FILE * file; + //const char * fn; + + if( ( file = fopen( filename, "w" ) ) == NULL ) { + printf( "**Error in SCHEMAprint: unable to create file %s ** \n", filename ); + return ( NULL ); + } + + //fprintf( file, "#ifndef %s\n", fn = StrToConstant( filename ) ); + //fprintf( file, "#define %s\n", fn ); + + fprintf( file, "# This file was generated by fedex_python. You probably don't want to edit\n" ); + fprintf( file, "# it since your modifications will be lost if fedex_plus is used to\n" ); + fprintf( file, "# regenerate it.\n" ); + return ( file ); + +} + +/****************************************************************** + ** Procedure: FILEclose + ** Description: closes a file opened with FILEcreate + ** Parameters: FILE* file -- pointer to file to close + ** Returns: + ** Side Effects: + ** Status: complete + ******************************************************************/ + +void +FILEclose( FILE * file ) { + fclose( file ); +} + + +/****************************************************************** + ** Procedure: isAggregate + ** Parameters: Attribute a + ** Returns: int indicates whether the attribute is an aggregate + ** Description: indicates whether the attribute is an aggregate + ** Side Effects: none + ** Status: complete 1/15/91 + ******************************************************************/ + +int +isAggregate( Variable a ) { + return( TYPEinherits_from( VARget_type( a ), aggregate_ ) ); +} + +int +isAggregateType( const Type t ) { + return( TYPEinherits_from( t, aggregate_ ) ); +} + + + +/****************************************************************** + ** Procedure: TypeName + ** Parameters: Type t + ** Returns: name of type as defined in SDAI C++ binding 4-Nov-1993 + ** Status: 4-Nov-1993 + ******************************************************************/ +const char * +TypeName( Type t ) { +} + +/****************************************************************** + ** Procedure: ClassName + ** Parameters: const char * oldname + ** Returns: temporary copy of name suitable for use as a class name + ** Side Effects: erases the name created by a previous call to this function + ** Status: complete + ******************************************************************/ + +const char * +ClassName( const char * oldname ) { + int i = 0, j = 0; + static char newname [BUFSIZ]; + if( !oldname ) { + return ( "" ); + } + + + strcpy( newname, ENTITYCLASS_PREFIX ) ; + j = strlen( ENTITYCLASS_PREFIX ) ; + newname [j] = ToUpper( oldname [i] ); + ++i; + ++j; + while( oldname [i] != '\0' ) { + newname [j] = ToLower( oldname [i] ); + /* if (oldname [i] == '_') */ + /* character is '_' */ + /* newname [++j] = ToUpper (oldname [++i]);*/ + ++i; + ++j; + } + newname [j] = '\0'; + return ( newname ); +} + +const char * +ENTITYget_CORBAname( Entity ent ) { + static char newname [BUFSIZ]; + strcpy( newname, ENTITYget_name( ent ) ); + newname[0] = ToUpper( newname [0] ); + return newname; +} + +/****************************************************************** + ** Procedure: ENTITYget_classname + ** Parameters: Entity ent + ** Returns: the name of the c++ class representing the entity + ** Status: complete + ******************************************************************/ + +const char * +ENTITYget_classname( Entity ent ) { + const char * oldname = ENTITYget_name( ent ); + return ( ClassName( oldname ) ); +} + +/****************************************************************** + ** Procedure: PrettyTmpName (char * oldname) + ** Procedure: PrettyNewName (char * oldname) + ** Parameters: oldname + ** Returns: a new capitalized name + ** Description: creates a new name with first character's in caps + ** Side Effects: PrettyNewName allocates memory for the new name + ** Status: OK 7-Oct-1992 kcm + ******************************************************************/ +const char * +PrettyTmpName( const char * oldname ) { + int i = 0; + static char newname [BUFSIZ]; + newname [0] = '\0'; + while( ( oldname [i] != '\0' ) && ( i < BUFSIZ ) ) { + newname [i] = ToLower( oldname [i] ); + if( oldname [i] == '_' ) { /* character is '_' */ + ++i; + newname [i] = ToUpper( oldname [i] ); + } + if( oldname [i] != '\0' ) { + ++i; + } + } + + newname [0] = ToUpper( oldname [0] ); + newname [i] = '\0'; + return newname; +} + +/* This function is out of date DAS */ +const char * +EnumName( const char * oldname ) { + int j = 0; + static char newname [MAX_LEN]; + if( !oldname ) { + return ( "" ); + } + + strcpy( newname, ENUM_PREFIX ) ; + j = strlen( ENUM_PREFIX ) ; + newname [j] = ToUpper( oldname [0] ); + strncpy( newname + j + 1, StrToLower( oldname + 1 ), MAX_LEN - j ); + j = strlen( newname ); + newname [j] = '\0'; + return ( newname ); +} + +const char * +SelectName( const char * oldname ) { + int j = 0; + static char newname [MAX_LEN]; + if( !oldname ) { + return ( "" ); + } + + strcpy( newname, TYPE_PREFIX ); + newname [0] = ToUpper( newname [0] ); + j = strlen( TYPE_PREFIX ); + newname [j] = ToUpper( oldname [0] ); + strncpy( newname + j + 1, StrToLower( oldname + 1 ), MAX_LEN - j ); + j = strlen( newname ); + newname [j] = '\0'; + return ( newname ); +} + +const char * +FirstToUpper( const char * word ) { + static char newword [MAX_LEN]; + + strncpy( newword, word, MAX_LEN ); + newword[0] = ToUpper( newword[0] ); + return ( newword ); +} + +/* return fundamental type but as the string which corresponds to */ +/* the appropriate type descriptor */ +/* if report_reftypes is true, report REFERENCE_TYPE when appropriate */ +char * +FundamentalType( const Type t, int report_reftypes ) { + if( report_reftypes && TYPEget_head( t ) ) { + return( "REFERENCE_TYPE" ); + } + switch( TYPEget_body( t )->type ) { + case integer_: + return( "INTEGER" ); + case real_: + return( "REAL" ); + case string_: + return( "STRING" ); + case binary_: + return( "BINARY" ); + case boolean_: + return( "BOOLEAN" ); + case logical_: + return( "LOGICAL" ); + case number_: + return( "NUMBER" ); + case generic_: + return( "GENERIC_TYPE" ); + case aggregate_: + return( "AGGREGATE_" ); + case array_: + return( "ARRAY_TYPE" ); + case bag_: + return( "BAG_TYPE" ); + case set_: + return( "'SET_TYPE not implemented'" ); + case list_: + return( "'LIST TYPE Not implemented'" ); + case entity_: + return( "INSTANCE" ); + case enumeration_: + return( "ENUMERATION" ); + case select_: + return ( "SELECT" ); + default: + return( "UNKNOWN_TYPE" ); + } +} + +/* this actually gets you the name of the variable that will be generated to + be a TypeDescriptor or subtype of TypeDescriptor to represent Type t in + the dictionary. */ + +const char * +TypeDescriptorName( Type t ) { + static char b [BUFSIZ]; + Schema parent = t->superscope; + /* NOTE - I corrected a prev bug here in which the *current* schema was + ** passed to this function. Now we take "parent" - the schema in which + ** Type t was defined - which was actually used to create t's name. DAR */ + + if( !parent ) { + parent = TYPEget_body( t )->entity->superscope; + /* This works in certain cases that don't work otherwise (basically a + ** kludge). For some reason types which are really entity choices of + ** a select have no superscope value, but their super may be tracked + ** by following through the entity they reference, as above. */ + } + + sprintf( b, "%s%s%s", SCHEMAget_name( parent ), TYPEprefix( t ), + TYPEget_name( t ) ); + return b; +} + +/* this gets you the name of the type of TypeDescriptor (or subtype) that a + variable generated to represent Type t would be an instance of. */ + +const char * +GetTypeDescriptorName( Type t ) { + switch( TYPEget_body( t )->type ) { + case aggregate_: + return "AggrTypeDescriptor"; + + case list_: + return "ListTypeDescriptor"; + + case set_: + return "SetTypeDescriptor"; + + case bag_: + return "BagTypeDescriptor"; + + case array_: + return "ArrayTypeDescriptor"; + + case select_: + return "SelectTypeDescriptor"; + + case boolean_: + case logical_: + case enumeration_: + return "EnumTypeDescriptor"; + + case entity_: + return "EntityDescriptor"; + + case integer_: + case real_: + case string_: + case binary_: + case number_: + case generic_: + return "TypeDescriptor"; + default: + printf( "Error in %s, line %d: type %d not handled by switch statement.", __FILE__, __LINE__, TYPEget_body( t )->type ); + abort(); + } +} + +int +ENTITYhas_explicit_attributes( Entity e ) { + Linked_List l = ENTITYget_attributes( e ); + int cnt = 0; + LISTdo( l, a, Variable ) + if( VARget_initializer( a ) == EXPRESSION_NULL ) { + ++cnt; + } + LISTod; + return cnt; + +} + +Entity +ENTITYput_superclass( Entity entity ) { +#define ENTITYget_type(e) ((e)->u.entity->type) + + Linked_List l = ENTITYget_supertypes( entity ); + Entity super = 0; + Entity ignore = 0; + int super_cnt = 0; + EntityTag tag; + + Linked_List list = 0; + + if( ! LISTempty( l ) ) { + + if( multiple_inheritance ) { + list = ENTITYget_supertypes( entity ); + if( ! LISTempty( list ) ) { + /* assign superclass to be the first one on the list of parents */ + super = ( Entity )LISTpeek_first( list ); + } + } else { + /* find the first parent that has attributes (in the parent or any of its + ancestors). Make super point at that parent and print warnings for + all the rest of the parents. DAS */ + LISTdo( l, e, Entity ) + /* if there's no super class yet, + or if the entity super class [the variable] super is pointing at + doesn't have any attributes: make super point at the current parent. + As soon as the parent pointed to by super has attributes, stop + assigning super and print ignore messages for the remaining parents. + */ + if( ( ! super ) || ( ! ENTITYhas_explicit_attributes( super ) ) ) { + ignore = super; + super = e; + ++ super_cnt; + } else { + ignore = e; + } + if( ignore ) { + printf( "WARNING: multiple inheritance not implemented.\n" ); + printf( "\tin ENTITY %s\n\tSUPERTYPE %s IGNORED.\n\n", + ENTITYget_name( entity ), ENTITYget_name( e ) ); + } + LISTod; + } + + tag = ( EntityTag ) malloc( sizeof( struct EntityTag_ ) ); + tag -> superclass = super; + TYPEput_clientData( ENTITYget_type( entity ), tag ); + return super; + } + return 0; +} + +Entity +ENTITYget_superclass( Entity entity ) { + EntityTag tag; + tag = TYPEget_clientData( ENTITYget_type( entity ) ); + return ( tag ? tag -> superclass : 0 ); +} + +void ENTITYget_first_attribs( Entity entity, Linked_List result ) { + Linked_List supers; + + LISTdo( ENTITYget_attributes( entity ), attr, Generic ) + LISTadd_last( result, attr ); + LISTod; + supers = ENTITYget_supertypes( entity ); + if( supers ) { + ENTITYget_first_attribs( ( Entity )LISTget_first( supers ), result ); + } +} + +/* Attributes are divided into four categories: +** these are not exclusive as far as I can tell! I added defs below DAS +** +** . simple explicit +** . type shifters // not DERIVEd - redefines type in ancestor +** // VARget_initializer(v) returns null +** +** . simple derived // DERIVEd - is calculated - VARget_initializer(v) +** // returns non-zero, VARis_derived(v) is non-zero +** +** . overriding // includes type shifters and derived +** +** All of them are added to the dictionary. +** Only type shifters generate a new STEPattribute. +** Type shifters generate access functions and data members, for now. +** Overriding generate access functions and data members, for now. ???? DAS + +** // type shifting attributes +** // ------------------------ +** // before printing new STEPattribute +** // check to see if it\'s already printed in supertype +** // still add new access function +** +** // overriding attributes +** // --------------------- +** // go through derived attributes +** // if STEPattribute found with same name +** // tell it to be * for reading and writing +**/ + +Variable +VARis_type_shifter( Variable a ) { + char * temp; + + if( VARis_derived( a ) || VARget_inverse( a ) ) { + return 0; + } + + temp = EXPRto_string( VARget_name( a ) ); + if( ! strncmp( StrToLower( temp ), "self\\", 5 ) ) { + /* a is a type shifter */ + free( temp ); + return a; + } + free( temp ); + return 0; +} + +Variable +VARis_overrider( Entity e, Variable a ) { + + Variable other; + char * tmp; + + tmp = VARget_simple_name( a ); + + LISTdo( ENTITYget_supertypes( e ), s, Entity ) + if( ( other = ENTITYget_named_attribute( s, tmp ) ) + && other != a ) { + return other; + } + LISTod; + return 0; +} + +Type +TYPEget_ancestor( Type t ) +/* + * For a renamed type, returns the original (ancestor) type from which t + * descends. Return NULL if t is top level. + */ +{ + Type i = t; + + if( !TYPEget_head( i ) ) { + return NULL; + } + + while( TYPEget_head( i ) ) { + i = TYPEget_head( i ); + } + + return i; +} diff --git a/src/fedex_python/src/classes_python.c b/src/fedex_python/src/classes_python.c new file mode 100644 index 000000000..7419e962c --- /dev/null +++ b/src/fedex_python/src/classes_python.c @@ -0,0 +1,1320 @@ +/* +** Fed-x parser output module for generating C++ class definitions +** December 5, 1989 +** release 2 17-Feb-1992 +** release 3 March 1993 +** release 4 December 1993 +** K. C. Morris +** +** Development of Fed-x was funded by the United States Government, +** and is not subject to copyright. + +******************************************************************* +The conventions used in this binding follow the proposed specification +for the STEP Standard Data Access Interface as defined in document +N350 ( August 31, 1993 ) of ISO 10303 TC184/SC4/WG7. +*******************************************************************/ + +/****************************************************************** +*** The functions in this file generate the C++ code for ENTITY ** +*** classes, TYPEs, and TypeDescriptors. *** + ** **/ + + +/* this is used to add new dictionary calls */ +/* #define NEWDICT */ + +#include +#include "classes.h" + +int isAggregateType( const Type t ); +int isAggregate( Variable a ); +Variable VARis_type_shifter( Variable a ); +const char * ENTITYget_CORBAname( Entity ent ); +const char * GetTypeDescriptorName( Type t ); + +char * FundamentalType( const Type t, int report_reftypes ); + +int multiple_inheritance = 1; +int print_logging = 0; +int corba_binding = 0; +int old_accessors = 0; + +/* several classes use attr_count for naming attr dictionary entry + variables. All but the last function generating code for a particular + entity increment a copy of it for naming each attr in the entity. + Here are the functions: + ENTITYhead_print (Entity entity, FILE* file,Schema schema) + LIBdescribe_entity (Entity entity, FILE* file, Schema schema) + LIBcopy_constructor (Entity ent, FILE* file) + LIBstructor_print (Entity entity, FILE* file, Schema schema) + LIBstructor_print_w_args (Entity entity, FILE* file, Schema schema) + ENTITYincode_print (Entity entity, FILE* file,Schema schema) + DAS + */ +static int attr_count; /* number each attr to avoid inter-entity clashes */ +static int type_count; /* number each temporary type for same reason above */ + +extern int any_duplicates_in_select( const Linked_List list ); +extern int unique_types( const Linked_List list ); +extern char * non_unique_types_string( const Type type ); +static void printEnumCreateHdr( FILE *, const Type ); +static void printEnumCreateBody( FILE *, const Type ); +static void printEnumAggrCrHdr( FILE *, const Type ); +static void printEnumAggrCrBody( FILE *, const Type ); +void printAccessHookFriend( FILE *, const char * ); +void printAccessHookHdr( FILE *, const char * ); +int TYPEget_RefTypeVarNm( const Type t, char * buf, Schema schema ); +void TypeBody_Description( TypeBody body, char * buf ); + +/* +Turn the string into a new string that will be printed the same as the +original string. That is, turn backslash into a quoted backslash and +turn \n into "\n" (i.e. 2 chars). +*/ + +char * format_for_stringout( char * orig_buf, char * return_buf ) { + char * optr = orig_buf; + char * rptr = return_buf; + while( *optr ) { + if( *optr == '\n' ) { + *rptr = '\\'; + rptr++; + *rptr = 'n'; + } else if( *optr == '\\' ) { + *rptr = '\\'; + rptr++; + *rptr = '\\'; + } else { + *rptr = *optr; + } + rptr++; + optr++; + } + *rptr = '\0'; + return return_buf; +} + +void +USEREFout( Schema schema, Dictionary refdict, Linked_List reflist, char * type, FILE * file ) { + Dictionary dict; + DictionaryEntry de; + struct Rename * r; + Linked_List list; + char td_name[BUFSIZ]; + char sch_name[BUFSIZ]; + + strncpy( sch_name, PrettyTmpName( SCHEMAget_name( schema ) ), BUFSIZ ); + + LISTdo( reflist, s, Schema ) { + fprintf( file, "\t// %s FROM %s; (all objects)\n", type, s->symbol.name ); + fprintf( file, "\tis = new Interface_spec(\"%s\",\"%s\");\n", sch_name, PrettyTmpName( s->symbol.name ) ); + fprintf( file, "\tis->all_objects_(1);\n" ); + if( !strcmp( type, "USE" ) ) { + fprintf( file, "\t%s%s->use_interface_list_()->Append(is);\n", SCHEMA_PREFIX, SCHEMAget_name( schema ) ); + } else { + fprintf( file, "\t%s%s->ref_interface_list_()->Append(is);\n", SCHEMA_PREFIX, SCHEMAget_name( schema ) ); + } + } + LISTod + + if( !refdict ) { + return; + } + dict = DICTcreate( 10 ); + + /* sort each list by schema */ + + /* step 1: for each entry, store it in a schema-specific list */ + DICTdo_init( refdict, &de ); + while( 0 != ( r = ( struct Rename * )DICTdo( &de ) ) ) { + Linked_List list; + + list = ( Linked_List )DICTlookup( dict, r->schema->symbol.name ); + if( !list ) { + list = LISTcreate(); + DICTdefine( dict, r->schema->symbol.name, list, + ( Symbol * )0, OBJ_UNKNOWN ); + } + LISTadd( list, r ); + } + + /* step 2: for each list, print out the renames */ + DICTdo_init( dict, &de ); + while( 0 != ( list = ( Linked_List )DICTdo( &de ) ) ) { + bool first_time = true; + LISTdo( list, r, struct Rename * ) + + /* + Interface_spec_ptr is; + Used_item_ptr ui; + is = new Interface_spec(const char * cur_sch_id); + schemadescriptor->use_interface_list_()->Append(is); + ui = new Used_item(TypeDescriptor *ld, const char *oi, const char *ni) ; + is->_explicit_items->Append(ui); + */ + + /* note: SCHEMAget_name(r->schema) equals r->schema->symbol.name) */ + if( first_time ) { + fprintf( file, "\t// %s FROM %s (selected objects)\n", type, r->schema->symbol.name ); + fprintf( file, "\tis = new Interface_spec(\"%s\",\"%s\");\n", sch_name, PrettyTmpName( r->schema->symbol.name ) ); + if( !strcmp( type, "USE" ) ) { + fprintf( file, "\t%s%s->use_interface_list_()->Append(is);\n", SCHEMA_PREFIX, SCHEMAget_name( schema ) ); + } else { + fprintf( file, "\t%s%s->ref_interface_list_()->Append(is);\n", SCHEMA_PREFIX, SCHEMAget_name( schema ) ); + } + } + + if( first_time ) { + first_time = false; + } + if( r->type == OBJ_TYPE ) { + sprintf( td_name, "%s", TYPEtd_name( ( Type )r->object ) ); + } else if( r->type == OBJ_FUNCTION ) { + sprintf( td_name, "/* Function not implemented */ 0" ); + } else if( r->type == OBJ_PROCEDURE ) { + sprintf( td_name, "/* Procedure not implemented */ 0" ); + } else if( r->type == OBJ_RULE ) { + sprintf( td_name, "/* Rule not implemented */ 0" ); + } else if( r->type == OBJ_ENTITY ) { + sprintf( td_name, "%s%s%s", + SCOPEget_name( ( ( Entity )r->object )->superscope ), + ENT_PREFIX, ENTITYget_name( ( Entity )r->object ) ); + } else { + sprintf( td_name, "/* %c from OBJ_? in expbasic.h not implemented */ 0", r->type ); + } + if( r->old != r->nnew ) { + fprintf( file, "\t// object %s AS %s\n", r->old->name, + r->nnew->name ); + if( !strcmp( type, "USE" ) ) { + fprintf( file, "\tui = new Used_item(\"%s\", %s, \"%s\", \"%s\");\n", r->schema->symbol.name, td_name, r->old->name, r->nnew->name ); + fprintf( file, "\tis->explicit_items_()->Append(ui);\n" ); + fprintf( file, "\t%s%s->interface_().explicit_items_()->Append(ui);\n", SCHEMA_PREFIX, SCHEMAget_name( schema ) ); + } else { + fprintf( file, "\tri = new Referenced_item(\"%s\", %s, \"%s\", \"%s\");\n", r->schema->symbol.name, td_name, r->old->name, r->nnew->name ); + fprintf( file, "\tis->explicit_items_()->Append(ri);\n" ); + fprintf( file, "\t%s%s->interface_().explicit_items_()->Append(ri);\n", SCHEMA_PREFIX, SCHEMAget_name( schema ) ); + } + } else { + fprintf( file, "\t// object %s\n", r->old->name ); + if( !strcmp( type, "USE" ) ) { + fprintf( file, "\tui = new Used_item(\"%s\", %s, \"\", \"%s\");\n", r->schema->symbol.name, td_name, r->nnew->name ); + fprintf( file, "\tis->explicit_items_()->Append(ui);\n" ); + fprintf( file, "\t%s%s->interface_().explicit_items_()->Append(ui);\n", SCHEMA_PREFIX, SCHEMAget_name( schema ) ); + } else { + fprintf( file, "\tri = new Referenced_item(\"%s\", %s, \"\", \"%s\");\n", r->schema->symbol.name, td_name, r->nnew->name ); + fprintf( file, "\tis->explicit_items_()->Append(ri);\n" ); + fprintf( file, "\t%s%s->interface_().explicit_items_()->Append(ri);\n", SCHEMA_PREFIX, SCHEMAget_name( schema ) ); + } + } + LISTod + } + HASHdestroy( dict ); +} + +const char * +IdlEntityTypeName( Type t ) { +} + + +int Handle_FedPlus_Args( int i, char * arg ) { + if( ( ( char )i == 's' ) || ( ( char )i == 'S' ) ) { + multiple_inheritance = 0; + } + if( ( ( char )i == 'a' ) || ( ( char )i == 'A' ) ) { + old_accessors = 1; + } + if( ( char )i == 'L' ) { + print_logging = 1; + } + if( ( ( char )i == 'c' ) || ( ( char )i == 'C' ) ) { + corba_binding = 1; + } + return 0; +} + + +bool is_python_keyword(char * word) { + bool python_keyword = false; + if (strcmp(word,"class")==0) python_keyword = true; + return python_keyword; +} + +/****************************************************************** + ** Procedure: generate_attribute_name + ** Parameters: Variable a, an Express attribute; char *out, the C++ name + ** Description: converts an Express name into the corresponding C++ name + ** see relation to generate_dict_attr_name() DAS + ** Side Effects: + ** Status: complete 8/5/93 + ******************************************************************/ +char * +generate_attribute_name( Variable a, char * out ) { + char * temp, *p, *q; + int j; + temp = EXPRto_string( VARget_name( a ) ); + p = temp; + if( ! strncmp( StrToLower( p ), "self\\", 5 ) ) { + p = p + 5; + } + /* copy p to out */ + /* DAR - fixed so that '\n's removed */ + for( j = 0, q = out; j < BUFSIZ; p++ ) { + /* copy p to out, 1 char at time. Skip \n's and spaces, convert */ + /* '.' to '_', and convert to lowercase. */ + if( ( *p != '\n' ) && ( *p != ' ' ) ) { + if( *p == '.' ) { + *q = '_'; + } else { + *q = tolower( *p ); + } + j++; + q++; + } + } + free(temp); + // python generator : we should prevend an attr name to be a python reserved keyword + if (is_python_keyword(out)) strcat(out,"_"); + return out; +} + +char * +generate_attribute_func_name( Variable a, char * out ) { + generate_attribute_name( a, out ); + strncpy( out, CheckWord( StrToLower( out ) ), BUFSIZ ); + if( old_accessors ) { + out[0] = toupper( out[0] ); + } else { + out[strlen( out )] = '_'; + } + return out; +} + +/****************************************************************** + ** Procedure: generate_dict_attr_name + ** Parameters: Variable a, an Express attribute; char *out, the C++ name + ** Description: converts an Express name into the corresponding SCL + ** dictionary name. The difference between this and the + ** generate_attribute_name() function is that for derived + ** attributes the name will have the form . + ** where is the name of the parent containing the + ** attribute being derived and is the name of the + ** derived attribute. Both and may + ** contain underscores but and will be + ** separated by a period. generate_attribute_name() generates + ** the same name except and will be + ** separated by an underscore since it is illegal to have a + ** period in a variable name. This function is used for the + ** dictionary name (a string) and generate_attribute_name() + ** will be used for variable and access function names. + ** Side Effects: + ** Status: complete 8/5/93 + ******************************************************************/ +char * +generate_dict_attr_name( Variable a, char * out ) { + char * temp, *p, *q; + int j; + + temp = EXPRto_string( VARget_name( a ) ); + p = temp; + if( ! strncmp( StrToLower( p ), "self\\", 5 ) ) { + p = p + 5; + } + /* copy p to out */ + strncpy( out, StrToLower( p ), BUFSIZ ); + /* DAR - fixed so that '\n's removed */ + for( j = 0, q = out; j < BUFSIZ; p++ ) { + /* copy p to out, 1 char at time. Skip \n's, and convert to lc. */ + if( *p != '\n' ) { + *q = tolower( *p ); + j++; + q++; + } + } + + free( temp ); + return out; +} + +/****************************************************************** +** Entity Generation */ + +/****************************************************************** + ** Procedure: ENTITYhead_print + ** Parameters: const Entity entity + ** FILE* file -- file being written to + ** Returns: + ** Description: prints the beginning of the entity class definition for the + ** c++ code and the declaration of extern attr descriptors for + ** the registry. In the .h file + ** Side Effects: generates c++ code + ** Status: good 1/15/91 + ** added registry things 12-Apr-1993 + ******************************************************************/ + +void +ENTITYhead_print( Entity entity, FILE * file, Schema schema ) { + char entnm [BUFSIZ]; + char attrnm [BUFSIZ]; + Linked_List list; + int attr_count_tmp = attr_count; + Entity super = 0; + + strncpy( entnm, ENTITYget_classname( entity ), BUFSIZ ); + + /* DAS print all the attr descriptors and inverse attr descriptors for an + entity as extern defs in the .h file. */ + LISTdo( ENTITYget_attributes( entity ), v, Variable ) + generate_attribute_name( v, attrnm ); + fprintf( file, "extern %s *%s%d%s%s;\n", + ( VARget_inverse( v ) ? "Inverse_attribute" : ( VARis_derived( v ) ? "Derived_attribute" : "AttrDescriptor" ) ), + ATTR_PREFIX, attr_count_tmp++, + ( VARis_derived( v ) ? "D" : ( VARis_type_shifter( v ) ? "R" : ( VARget_inverse( v ) ? "I" : "" ) ) ), + attrnm ); + + /* **** testing the functions **** */ + /* + if( !(VARis_derived(v) && + VARget_initializer(v) && + VARis_type_shifter(v) && + VARis_overrider(entity, v)) ) + fprintf(file,"// %s Attr is not derived, a type shifter, overrider, no initializer.\n",attrnm); + + if(VARis_derived (v)) + fprintf(file,"// %s Attr is derived\n",attrnm); + if (VARget_initializer (v)) + fprintf(file,"// %s Attr has an initializer\n",attrnm); + if(VARis_type_shifter (v)) + fprintf(file,"// %s Attr is a type shifter\n",attrnm); + if(VARis_overrider (entity, v)) + fprintf(file,"// %s Attr is an overrider\n",attrnm); + */ + /* ****** */ + + LISTod + + fprintf( file, "\nclass %s : ", entnm ); + + /* inherit from either supertype entity class or root class of + all - i.e. SCLP23(Application_instance) */ + + if( multiple_inheritance ) { + list = ENTITYget_supertypes( entity ); + if( ! LISTempty( list ) ) { + super = ( Entity )LISTpeek_first( list ); + } + } else { /* the old way */ + super = ENTITYput_superclass( entity ); + } + + if( super ) { + fprintf( file, " public %s {\n ", ENTITYget_classname( super ) ); + } else { + fprintf( file, " public SCLP23(Application_instance) {\n" ); + } + + +} + +/****************************************************************** + ** Procedure: DataMemberPrint + ** Parameters: const Entity entity -- entity being processed + ** FILE* file -- file being written to + ** Returns: + ** Description: prints out the data members for an entity's c++ class + ** definition + ** Side Effects: generates c++ code + ** Status: ok 1/15/91 + ******************************************************************/ + +void +DataMemberPrint( Entity entity, FILE * file, Schema schema ) { +} + +/****************************************************************** + ** Procedure: MemberFunctionSign + ** Parameters: Entity *entity -- entity being processed + ** FILE* file -- file being written to + ** Returns: + ** Description: prints the signature for member functions + of an entity's class definition + ** DAS prints the end of the entity class def and the creation + ** function that the EntityTypeDescriptor uses. + ** Side Effects: prints c++ code to a file + ** Status: ok 1/1/5/91 + ** updated 17-Feb-1992 to print only the signature + and not the function definitions + ******************************************************************/ + +void +MemberFunctionSign( Entity entity, FILE * file ) { + +} + +/****************************************************************** + ** Procedure: LIBdescribe_entity (entity, file, schema) + ** Parameters: Entity entity -- entity being processed + ** FILE* file -- file being written to + ** Schema schema -- schema being processed + ** Returns: + ** Description: declares the global pointer to the EntityDescriptor + representing a particular entity + ** DAS also prints the attr descs and inverse attr descs + ** This function creates the storage space for the externs defs + ** that were defined in the .h file. These global vars go in + ** the .cc file. + ** Side Effects: prints c++ code to a file + ** Status: ok 12-Apr-1993 + ******************************************************************/ +char * +GetAttrTypeName(Type t) { + char * attr_type; + if (TYPEis_string(t)) + { + attr_type = "STRING"; + } + else if (TYPEis_logical(t)) + { + attr_type = "LOGICAL"; + } + else if (TYPEis_boolean(t)) + { + attr_type = "BOOLEAN"; + } + else if (TYPEis_real(t)) + { + attr_type = "REAL"; + } + else if (TYPEis_integer(t)) + { + attr_type = "INTEGER"; + } + else + { + attr_type = TYPEget_name(t); + } + return attr_type; +} + +/* +* +* A function that prints BAG, ARRAY, SET or LIST to the file +* +*/ + +void +print_aggregate_type(FILE *file, Type t) { + switch(TYPEget_body( t )->type) { + case array_: + fprintf(file,"ARRAY"); + break; + case bag_: + fprintf(file,"BAG"); + break; + case set_: + fprintf(file,"SET"); + break; + case list_: + fprintf(file,"LIST"); + break; + default: + break; + } +} + +/* +* +* A recursive function to export aggregate to python +* +*/ +void +process_aggregate (FILE *file, Type t) { + Expression lower = AGGR_TYPEget_lower_limit(t); + char *lower_str = EXPRto_string(lower); + Expression upper = AGGR_TYPEget_upper_limit(t); + char *upper_str = NULL; + if (upper == LITERAL_INFINITY) { + upper_str = "None"; + } + else { + upper_str = EXPRto_string(upper); + } + switch(TYPEget_body( t )->type) { + case array_: + fprintf(file,"ARRAY"); + break; + case bag_: + fprintf(file,"BAG"); + break; + case set_: + fprintf(file,"SET"); + break; + case list_: + fprintf(file,"LIST"); + break; + default: + break; + } + fprintf(file,"(%s,%s,",lower_str,upper_str); + //write base type + Type base_type = TYPEget_base_type(t); + if (TYPEis_aggregate(base_type)) { + process_aggregate(file,base_type); + fprintf(file,")"); //close parenthesis + } + else { + char * array_base_type = GetAttrTypeName(TYPEget_base_type(t)); + //fprintf(file,"%s)",array_base_type); + fprintf(file,"'%s')",array_base_type); + } + +} + +void +LIBdescribe_entity( Entity entity, FILE * file, Schema schema ) { + int attr_count_tmp = attr_count; + char attrnm [BUFSIZ], parent_attrnm[BUFSIZ]; + char * attr_type; + bool generate_constructor = true; //by default, generates a python constructor + bool inheritance = false; + Type t; + /* class name + need to use new-style classes for properties to work correctly + so class must inherit from object */ + if (is_python_keyword(ENTITYget_name(entity))) {fprintf(file,"class %s_(",ENTITYget_name(entity));} + else {fprintf(file,"class %s(",ENTITYget_name(entity));} + + /* + * Look for inheritance and super classes + */ + Linked_List list; + list = ENTITYget_supertypes( entity ); + int num_parent = 0; + if( ! LISTempty( list ) ) { + inheritance = true; + LISTdo( list, e, Entity ) + /* if there\'s no super class yet, + or the super class doesn\'t have any attributes + */ + if (num_parent > 0) fprintf(file,","); //separator for parent classes names + if (is_python_keyword(ENTITYget_name(e))) {fprintf(file,"%s_",ENTITYget_name(e));} + else {fprintf(file,"%s",ENTITYget_name(e));} + num_parent++; + LISTod; + } + else { + //inherit from BaeEntityClass by default, in order to enable decorators + // as well as advanced __repr__ feature + fprintf(file,"BaseEntityClass"); + } + fprintf(file,"):\n"); + /* + * Write docstrings in a Sphinx compliant manner + */ + fprintf(file,"\t'''Entity %s definition.\n",ENTITYget_name(entity)); + LISTdo(ENTITYget_attributes( entity ), v, Variable) + generate_attribute_name( v, attrnm ); + t = VARget_type( v ); + fprintf(file,"\n\t:param %s\n",attrnm); + fprintf(file,"\t:type %s:",attrnm); + if( TYPEis_aggregate( t ) ) { + process_aggregate(file,t); + fprintf(file,"\n"); + } + else { + fprintf(file,"%s\n",GetAttrTypeName(t)); + } + attr_count_tmp++; + LISTod + fprintf(file,"\t'''\n"); + /* + * Before writing constructor, check if this entity has any attribute + * other wise just a 'pass' statement is enough + */ + attr_count_tmp = 0; + int num_derived_inverse_attr = 0; + LISTdo(ENTITYget_attributes( entity ), v, Variable) + if (VARis_derived(v) || VARget_inverse(v)) { + num_derived_inverse_attr++; + } + else { + attr_count_tmp++; + } + LISTod + if ((attr_count_tmp == 0) && !inheritance) { + fprintf(file,"\t# This class does not define any attribute.\n"); + fprintf(file,"\tpass\n"); + generate_constructor = false; + } + if (false) {} + else { + /* + * write class constructor + */ + if (generate_constructor) { + fprintf(file,"\tdef __init__( self , "); + } + // if inheritance, first write the inherited parameters + list = ENTITYget_supertypes( entity ); + int num_parent = 0, index_attribute = 0; + if( ! LISTempty( list ) ) { + LISTdo( list, e, Entity ) + /* search attribute names for superclass */ + LISTdo(ENTITYget_attributes( e ), v2, Variable) + generate_attribute_name( v2, parent_attrnm ); + fprintf(file,"%s__%s , ",ENTITYget_name(e),parent_attrnm); + index_attribute++; + LISTod + num_parent++; + LISTod; + } + LISTdo(ENTITYget_attributes( entity ), v, Variable) + generate_attribute_name( v, attrnm ); + if (!VARis_derived(v) && !VARget_inverse(v)) { + fprintf(file,"%s,",attrnm); + } + LISTod + // close constructor method + if (generate_constructor) fprintf(file," ):\n"); + /** if inheritance, first init base class **/ + list = ENTITYget_supertypes( entity ); + if( ! LISTempty( list ) ) { + LISTdo( list, e, Entity ) + fprintf(file,"\t\t%s.__init__(self , ",ENTITYget_name(e)); + /* search and write attribute names for superclass */ + LISTdo(ENTITYget_attributes( e ), v2, Variable) + generate_attribute_name( v2, parent_attrnm ); + fprintf(file,"%s__%s , ",ENTITYget_name(e),parent_attrnm); + LISTod + fprintf(file,")\n"); //separator for parent classes names + LISTod; + } + // init variables in constructor + LISTdo(ENTITYget_attributes( entity ), v, Variable) + generate_attribute_name( v, attrnm ); + if (!VARis_derived(v) && !VARget_inverse(v)) fprintf(file,"\t\tself.%s = %s\n",attrnm,attrnm); + //attr_count_tmp++; + LISTod + /* + * write attributes as python properties + */ + LISTdo( ENTITYget_attributes( entity ), v, Variable ) + generate_attribute_name( v, attrnm ); + fprintf(file,"\n\t@apply\n"); + fprintf(file,"\tdef %s():\n",attrnm); + // fget + fprintf(file,"\t\tdef fget( self ):\n"); + if (!VARis_derived(v)) { + fprintf(file,"\t\t\treturn self._%s\n",attrnm); + } + else { + // expression initializer + char * expression_string = EXPRto_string( v->initializer ); + fprintf(file,"\t\t\treturn EvalDerivedAttribute(self,'''%s''')\n",expression_string); + free( expression_string ); + } + // fset + fprintf(file,"\t\tdef fset( self, value ):\n"); + t = VARget_type( v ); + + attr_type = GetAttrTypeName(t); + + if (!VARis_derived(v) && !VARget_inverse(v)) { + // if the argument is not optional + if (!VARget_optional(v)) { + fprintf(file, "\t\t# Mandatory argument\n"); + fprintf(file,"\t\t\tif value==None:\n"); + fprintf(file,"\t\t\t\traise AssertionError('Argument %s is mantatory and can not be set to None')\n",attrnm); + fprintf(file,"\t\t\tif not check_type(value,"); + if( TYPEis_aggregate( t ) ) { + process_aggregate(file,t); + fprintf(file,"):\n"); + } + else { + fprintf(file,"%s):\n",attr_type); + } + } + else { + fprintf(file,"\t\t\tif value != None: # OPTIONAL attribute\n\t"); + fprintf(file,"\t\t\tif not check_type(value,"); + if( TYPEis_aggregate( t ) ) { + process_aggregate(file,t); + fprintf(file,"):\n\t"); + } + else { + fprintf(file,"%s):\n\t",attr_type); + } + } + // check wether attr_type is aggr or explicit + if( TYPEis_aggregate( t ) ) { + fprintf(file, "\t\t\t\tself._%s = ",attrnm); + print_aggregate_type(file,t); + fprintf(file,"(value)\n"); + fprintf(file, "\t\t\telse:\n\t"); + } + else { + fprintf(file, "\t\t\t\tself._%s = %s(value)\n",attrnm,attr_type); + fprintf(file, "\t\t\telse:\n\t"); + } + fprintf(file,"\t\t\tself._%s = value\n",attrnm); + } + // if the attribute is derived, prevent fset to attribute to be set + else if (VARis_derived(v)){ + fprintf(file,"\t\t# DERIVED argument\n"); + fprintf(file,"\t\t\traise AssertionError('Argument %s is DERIVED. It is computed and can not be set to any value')\n",attrnm); + } + else if (VARget_inverse(v)) { + fprintf(file,"\t\t# INVERSE argument\n"); + fprintf(file,"\t\t\traise AssertionError('Argument %s is INVERSE. It is computed and can not be set to any value')\n",attrnm); + } + fprintf(file,"\t\treturn property(**locals())\n"); + LISTod + } +} + +int +get_local_attribute_number( Entity entity ) { + int i = 0; + Linked_List local = ENTITYget_attributes( entity ); + LISTdo( local, a, Variable ) + /* go to the child's first explicit attribute */ + if( ( ! VARget_inverse( a ) ) && ( ! VARis_derived( a ) ) ) ++i; + LISTod; + return i; +} + +int +get_attribute_number( Entity entity ) { + int i = 0; + int found = 0; + Linked_List local, complete; + complete = ENTITYget_all_attributes( entity ); + local = ENTITYget_attributes( entity ); + + LISTdo( local, a, Variable ) + /* go to the child's first explicit attribute */ + if( ( ! VARget_inverse( a ) ) && ( ! VARis_derived( a ) ) ) { + LISTdo( complete, p, Variable ) + /* cycle through all the explicit attributes until the + child's attribute is found */ + if( !found && ( ! VARget_inverse( p ) ) && ( ! VARis_derived( p ) ) ) { + if( p != a ) { + ++i; + } else { + found = 1; + } + } + LISTod; + if( found ) { + return i; + } else printf( "Internal error: %s:%d\n" + "Attribute %s not found. \n" + /* In this case, a is a Variable - so macro VARget_name (a) expands * + * to an Expression. The first element of an Expression is a Symbol. * + * The first element of a Symbol is char * name. */ + , __FILE__, __LINE__, VARget_name( a )->symbol.name ); + } + + LISTod; + return -1; +} + +void +LIBstructor_print( Entity entity, FILE * file, Schema schema ) { +} + +/********************/ +/* print the constructor that accepts a SCLP23(Application_instance) as an argument used + when building multiply inherited entities. +*/ + +void +LIBstructor_print_w_args( Entity entity, FILE * file, Schema schema ) { +} + +/****************************************************************** + ** Procedure: ENTITYlib_print + ** Parameters: Entity *entity -- entity being processed + ** FILE* file -- file being written to + ** Returns: + ** Description: drives the printing of the code for the class library + ** additional member functions can be generated by writing a routine + ** to generate the code and calling that routine from this procedure + ** Side Effects: generates code segment for c++ library file + ** Status: ok 1/15/91 + ******************************************************************/ +void +ENTITYlib_print( Entity entity, FILE * file, Schema schema ) { + LIBdescribe_entity( entity, file, schema ); +} + +//FIXME should return bool +/* return 1 if types are predefined by us */ +int +TYPEis_builtin( const Type t ) { + switch( TYPEget_body( t )->type ) { /* dunno if correct*/ + case integer_: + case real_: + case string_: + case binary_: + case boolean_: + case number_: + case logical_: + return 1; + break; + default: + break; + } + return 0; +} + + +void +print_typechain( FILE * f, const Type t, char * buf, Schema schema ) { +} + +void +ENTITYincode_print( Entity entity, FILE * file, Schema schema ) { +} + +/****************************************************************** + ** Procedure: ENTITYPrint + ** Parameters: Entity *entity -- entity being processed + ** FILE* file -- file being written to + ** Returns: + ** Description: drives the functions for printing out code in lib, + ** include, and initialization files for a specific entity class + ** Side Effects: generates code in 3 files + ** Status: complete 1/15/91 + ******************************************************************/ + + +void +ENTITYPrint( Entity entity, FILES * files, Schema schema ) { + char * n = ENTITYget_name( entity ); + DEBUG( "Entering ENTITYPrint for %s\n", n ); + fprintf( files->lib, "\n####################\n # ENTITY %s #\n####################\n", n ); + ENTITYlib_print( entity, files -> lib, schema ); + DEBUG( "DONE ENTITYPrint\n" ) ; +} + +void +MODELPrintConstructorBody( Entity entity, FILES * files, Schema schema + /*, int index*/ ) { +} + +void +MODELPrint( Entity entity, FILES * files, Schema schema, int index ) { +} + +void +ENTITYprint_new( Entity entity, FILES * files, Schema schema, int externMap ) { +} + +void +MODELprint_new( Entity entity, FILES * files, Schema schema ) { +} + +/****************************************************************** + ** TYPE GENERATION **/ + + +/****************************************************************** + ** Procedure: TYPEprint_enum + ** Parameters: const Type type - type to print + ** FILE* f - file on which to print + ** Returns: + ** Requires: TYPEget_class(type) == TYPE_ENUM + ** Description: prints code to represent an enumerated type in c++ + ** Side Effects: prints to header file + ** Status: ok 1/15/91 + ** Changes: Modified to check for appropiate key words as described + ** in "SDAI C++ Binding for PDES, Inc. Prototyping" by + ** Stephen Clark. + ** - Changed to match CD2 Part 23, 1/14/97 DAS + ** Change Date: 5/22/91 CD + ******************************************************************/ +const char * +EnumCElementName( Type type, Expression expr ) { +} + +char * +CheckEnumSymbol( char * s ) { +} + +void +TYPEenum_lib_print( const Type type, FILE * f ) { + DictionaryEntry de; + Expression expr; + char c_enum_ele [BUFSIZ]; + // begin the new enum type + if (is_python_keyword(TYPEget_name( type ))) { + fprintf( f, "\n# ENUMERATION TYPE %s_\n", TYPEget_name( type ) ); + } + else { + fprintf( f, "\n# ENUMERATION TYPE %s\n", TYPEget_name( type ) ); + } + // first write all the values of the enum + DICTdo_type_init( ENUM_TYPEget_items( type ), &de, OBJ_ENUM ); + while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) { + strncpy( c_enum_ele, EnumCElementName( type, expr ), BUFSIZ ); + fprintf(f,"if (not '%s' in globals().keys()):\n",EXPget_name(expr)); + if (is_python_keyword(EXPget_name(expr))) { + fprintf(f,"\t%s_ = '%s_'\n",EXPget_name(expr),EXPget_name(expr)); + } + else { + fprintf(f,"\t%s = '%s'\n",EXPget_name(expr),EXPget_name(expr)); + } + } + // then outputs the enum + if (is_python_keyword(TYPEget_name( type ))) { + fprintf(f,"%s_ = ENUMERATION(",TYPEget_name( type )); + } + else { + fprintf(f,"%s = ENUMERATION(",TYPEget_name( type )); + } + /* set up the dictionary info */ + + //fprintf( f, "const char * \n%s::element_at (int n) const {\n", n ); + //fprintf( f, " switch (n) {\n" ); + DICTdo_type_init( ENUM_TYPEget_items( type ), &de, OBJ_ENUM ); + while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) { + strncpy( c_enum_ele, EnumCElementName( type, expr ), BUFSIZ ); + if (is_python_keyword(EXPget_name(expr))) { + fprintf(f,"\n\'%s_',",EXPget_name(expr)); + } + else { + fprintf(f,"\n\t'%s',",EXPget_name(expr)); + } + } + fprintf(f,"\n\t)\n"); +} + + +void Type_Description( const Type, char * ); + +/* return printable version of entire type definition */ +/* return it in static buffer */ +char * +TypeDescription( const Type t ) { + static char buf[4000]; + + buf[0] = '\0'; + + if( TYPEget_head( t ) ) { + Type_Description( TYPEget_head( t ), buf ); + } else { + TypeBody_Description( TYPEget_body( t ), buf ); + } + + /* should also print out where clause here */ + + return buf + 1; +} + +void strcat_expr( Expression e, char * buf ) { + if( e == LITERAL_INFINITY ) { + strcat( buf, "?" ); + } else if( e == LITERAL_PI ) { + strcat( buf, "PI" ); + } else if( e == LITERAL_E ) { + strcat( buf, "E" ); + } else if( e == LITERAL_ZERO ) { + strcat( buf, "0" ); + } else if( e == LITERAL_ONE ) { + strcat( buf, "1" ); + } else if( TYPEget_name( e ) ) { + strcat( buf, TYPEget_name( e ) ); + } else if( TYPEget_body( e->type )->type == integer_ ) { + char tmpbuf[30]; + sprintf( tmpbuf, "%d", e->u.integer ); + strcat( buf, tmpbuf ); + } else { + strcat( buf, "??" ); + } +} + +/* print t's bounds to end of buf */ +void +strcat_bounds( TypeBody b, char * buf ) { + if( !b->upper ) { + return; + } + + strcat( buf, " [" ); + strcat_expr( b->lower, buf ); + strcat( buf, ":" ); + strcat_expr( b->upper, buf ); + strcat( buf, "]" ); +} + +void +TypeBody_Description( TypeBody body, char * buf ) { + char * s; + + switch( body->type ) { + case integer_: + strcat( buf, " INTEGER" ); + break; + case real_: + strcat( buf, " REAL" ); + break; + case string_: + strcat( buf, " STRING" ); + break; + case binary_: + strcat( buf, " BINARY" ); + break; + case boolean_: + strcat( buf, " BOOLEAN" ); + break; + case logical_: + strcat( buf, " LOGICAL" ); + break; + case number_: + strcat( buf, " NUMBER" ); + break; + case entity_: + strcat( buf, " " ); + strcat( buf, PrettyTmpName( TYPEget_name( body->entity ) ) ); + break; + case aggregate_: + case array_: + case bag_: + case set_: + case list_: + switch( body->type ) { + /* ignore the aggregate bounds for now */ + case aggregate_: + strcat( buf, " AGGREGATE OF" ); + break; + case array_: + strcat( buf, " ARRAY" ); + strcat_bounds( body, buf ); + strcat( buf, " OF" ); + if( body->flags.optional ) { + strcat( buf, " OPTIONAL" ); + } + if( body->flags.unique ) { + strcat( buf, " UNIQUE" ); + } + break; + case bag_: + strcat( buf, " BAG" ); + strcat_bounds( body, buf ); + strcat( buf, " OF" ); + break; + case set_: + strcat( buf, " SET" ); + strcat_bounds( body, buf ); + strcat( buf, " OF" ); + break; + case list_: + strcat( buf, " LIST" ); + strcat_bounds( body, buf ); + strcat( buf, " OF" ); + if( body->flags.unique ) { + strcat( buf, " UNIQUE" ); + } + break; + default: + printf( "Error in %s, line %d: type %d not handled by switch statement.", __FILE__, __LINE__, body->type ); + abort(); + } + + Type_Description( body->base, buf ); + break; + case enumeration_: + strcat( buf, " ENUMERATION of (" ); + LISTdo( body->list, e, Expression ) + strcat( buf, ENUMget_name( e ) ); + strcat( buf, ", " ); + LISTod + /* find last comma and replace with ')' */ + s = strrchr( buf, ',' ); + if( s ) { + strcpy( s, ")" ); + } + break; + + case select_: + strcat( buf, " SELECT (" ); + LISTdo( body->list, t, Type ) + strcat( buf, PrettyTmpName( TYPEget_name( t ) ) ); + strcat( buf, ", " ); + LISTod + /* find last comma and replace with ')' */ + s = strrchr( buf, ',' ); + if( s ) { + strcpy( s, ")" ); + } + break; + default: + strcat( buf, " UNKNOWN" ); + } + + if( body->precision ) { + strcat( buf, " (" ); + strcat_expr( body->precision, buf ); + strcat( buf, ")" ); + } + if( body->flags.fixed ) { + strcat( buf, " FIXED" ); + } +} + +void +Type_Description( const Type t, char * buf ) { + if( TYPEget_name( t ) ) { + strcat( buf, " " ); + strcat( buf, TYPEget_name( t ) ); + /* strcat(buf,PrettyTmpName (TYPEget_name(t)));*/ + } else { + TypeBody_Description( TYPEget_body( t ), buf ); + } +} + +void +TYPEprint_typedefs( Type t, FILE * classes ) { +} + +/* return 1 if it is a multidimensional aggregate at the level passed in + otherwise return 0; If it refers to a type that is a multidimensional + aggregate 0 is still returned. */ +int +isMultiDimAggregateType( const Type t ) { + if( TYPEget_body( t )->base ) + if( isAggregateType( TYPEget_body( t )->base ) ) { + return 1; + } + return 0; +} + +/* Get the TypeDescriptor variable name that t's TypeDescriptor references (if + possible). + pass space in through buf, buff will be filled in with the name of the + TypeDescriptor (TD) that needs to be referenced by the TD that is + generated for Type t. Return 1 if buf has been filled in with the name + of a TD. Return 0 if it hasn't for these reasons: Enumeration TDs don't + reference another TD, select TDs reference several TDs and are handled + separately, Multidimensional aggregates generate unique intermediate TD + variables that are referenced - when these don't have an Express related + name this function can't know about them - e.g. + TYPE listSetAggr = LIST OF SET OF STRING; This function won't fill in the + name that listSetAggr's ListTypeDescriptor will reference. + TYPE arrListSetAggr = ARRAY [1:4] of listSetAggr; This function will + return the name of the TD that arrlistSetAggr's ArrayTypeDescriptor should + reference since it has an Express name associated with it. +*/ +int TYPEget_RefTypeVarNm( const Type t, char * buf, Schema schema ) { +} + + +/***** + print stuff for types that are declared in Express TYPE statements... i.e. + extern descriptor declaration in .h file - MOVED BY DAR to TYPEprint_type- + defs - in order to print all the Sdaiclasses.h stuff in fedex_plus's + first pass through each schema. + descriptor definition in the .cc file + initialize it in the .init.cc file (DAR - all initialization done in fn + TYPEprint_init() (below) which is done in fedex_plus's 1st pass only.) +*****/ + +void +TYPEprint_descriptions( const Type type, FILES * files, Schema schema ) { + char tdnm [BUFSIZ], + typename_buf [MAX_LEN], + base [BUFSIZ], + nm [BUFSIZ]; + Type i; + + strncpy( tdnm, TYPEtd_name( type ), BUFSIZ ); + + if( TYPEis_enumeration( type ) && ( i = TYPEget_ancestor( type ) ) != NULL ) { + /* If we're a renamed enum type, just print a few typedef's to the + // original and some specialized create functions: */ + strncpy( base, StrToLower(EnumName( TYPEget_name( i ) )), BUFSIZ ); + strncpy( nm, StrToLower(EnumName( TYPEget_name( type ) )), BUFSIZ ); + fprintf( files->lib, "%s = %s\n",nm,base ); + return; + } + + if( TYPEget_RefTypeVarNm( type, typename_buf, schema ) ) + { + char * output = FundamentalType(type,0); + if( TYPEis_aggregate( type ) ) { + fprintf(files->lib, "%s = ",TYPEget_name(type)); + process_aggregate(files->lib,type); + fprintf(files->lib,"\n"); + } + else if(TYPEis_select(type)) { + TYPEselect_lib_print( type, files -> lib ); + } + else { + fprintf(files->lib, "%s = ",TYPEget_name(type)); + fprintf(files->lib,"%s\n",output); + } + } + else { + switch( TYPEget_body( type )->type ) { + case enumeration_: + TYPEenum_lib_print( type, files -> lib ); + break; + case select_: + break; + default: + break; + } + } +} + + +static void +printEnumCreateHdr( FILE * inc, const Type type ) +/* + * Prints a bunch of lines for enumeration creation functions (i.e., "cre- + * ate_SdaiEnum1()"). Since this is done both for an enum and for "copies" + * of it (when "TYPE enum2 = enum1"), I placed this code in a separate fn. + */ +{ + +} + +static void +printEnumCreateBody( FILE * lib, const Type type ) +/* + * See header comment above by printEnumCreateHdr. + */ +{ +} + +static void +printEnumAggrCrHdr( FILE * inc, const Type type ) +/* + * Similar to printEnumCreateHdr above for the enum aggregate. + */ +{ +} + +static void +printEnumAggrCrBody( FILE * lib, const Type type ) { +} + +void +TYPEprint_init( const Type type, FILE * ifile, Schema schema ) { +} + +/* print name, fundamental type, and description initialization function + calls */ + +void +TYPEprint_nm_ft_desc( Schema schema, const Type type, FILE * f, char * endChars ) { +} + + +/* new space for a variable of type TypeDescriptor (or subtype). This + function is called for Types that have an Express name. */ + +void +TYPEprint_new( const Type type, FILE * create, Schema schema ) { +} diff --git a/src/fedex_python/src/classes_wrapper_python.cc b/src/fedex_python/src/classes_wrapper_python.cc new file mode 100644 index 000000000..4bf3d4411 --- /dev/null +++ b/src/fedex_python/src/classes_wrapper_python.cc @@ -0,0 +1,544 @@ +#include +#include +#include + +#include "complexSupport.h" +extern int corba_binding; + +void use_ref( Schema, Express, FILES * ); + +void +create_builtin_type_decl( FILES * files, char * name ) { + //fprintf( files->incall, "extern TypeDescriptor *%s%s_TYPE;\n", + // TD_PREFIX, name ); +} + +void +create_builtin_type_defn( FILES * files, char * name ) { + //fprintf( files->initall, "\t%s%s_TYPE = TypeDescriptor (", + // TD_PREFIX, name ); + //fprintf( files->initall, "\"%s\", %s_TYPE, \"%s\");\n", + // PrettyTmpName( name ), StrToUpper( name ), StrToLower( name ) ); +} + +/****************************************************************** + ** Procedure: print_file_header + ** Parameters: const Schema schema - top-level schema being printed + ** FILE* file - file on which to print header + ** Returns: + ** Description: handles file related tasks that need to be done once + ** at the beginning of processing. + ** In this case the file schema.h is initiated + ** Status: ok 1/15/91 + ******************************************************************/ + +void +print_file_header( Express express, FILES * files ) { + //files -> incall = FILEcreate( "schema.h" ); + + /* prevent RCS from expanding this! */ + //fprintf( files->incall, "import sdai\n" ); + //fprintf( files->incall, "import Registry\n" ); + + //fprintf( files->incall, "\n#include \n" ); + //fprintf( files->incall, "\n#include \n" ); + //fprintf( files->incall, "\n#include \n" ); + //fprintf( files->incall, "\n#include \n" ); + + //fprintf( files->incall, "\n#include \n" ); + //fprintf( files->incall, "import Sdaiclasses\n" ); + //fprintf( files->incall, "extern void SchemaInit (Registry &);\n" ); + //fprintf( files->incall, "extern void InitSchemasAndEnts (Registry &);\n" ); + + //files -> initall = FILEcreate( "schema.py" ); + //fprintf( files->initall, "/* %cId$ */ \n", '\044' ); + //fprintf( files->initall, "#include \n" ); + //fprintf( files->initall, "import schema\n" ); + //fprintf( files-> initall, "class Registry:\n" ); + + //fprintf( files->initall, "\tdef SchemaInit (Registry reg)\n{\n" ); + //fprintf( files->initall, "\t extern void InitSchemasAndEnts " ); + //fprintf( files->initall, "(Registry & r);\n" ); + //fprintf( files->initall, "\t InitSchemasAndEnts (reg);\n" ); + + // This file will contain instantiation statements for all the schemas and + // entities in the express file. (They must all be in separate function + // called first by SchemaInit() so that all entities will exist + //files -> create = FILEcreate( "SdaiAll.py" ); + //fprintf( files->create, "/* %cId$ */ \n", '\044' ); + //fprintf( files->create, "#include \n" ); + //fprintf( files->create, "import schema" ); + //fprintf( files->create, "\nvoid\nInitSchemasAndEnts (Registry & reg)\n{\n" ); + + // This file declares all entity classes as incomplete types. This will + // allow all the .h files to reference all .h's. We can then have e.g., + // entX from schemaA have attribute attr1 = entY from schemaB. + //files -> classes = FILEcreate( "Sdaiclasses.h" ); + //fprintf( files->classes, "/* %cId$ */ \n", '$' ); + //fprintf( files->classes, "#include \n" ); + + /* create built-in types */ + /* no need to generate + create_builtin_type_decl(files,"INTEGER"); + create_builtin_type_decl(files,"REAL"); + create_builtin_type_decl(files,"STRING"); + create_builtin_type_decl(files,"BINARY"); + create_builtin_type_decl(files,"BOOLEAN"); + create_builtin_type_decl(files,"LOGICAL"); + create_builtin_type_decl(files,"NUMBER"); + create_builtin_type_decl(files,"GENERIC"); + */ + /* create built-in types */ + /* no need to generate + create_builtin_type_defn(files,"INTEGER"); + create_builtin_type_defn(files,"REAL"); + create_builtin_type_defn(files,"STRING"); + create_builtin_type_defn(files,"BINARY"); + create_builtin_type_defn(files,"BOOLEAN"); + create_builtin_type_defn(files,"LOGICAL"); + create_builtin_type_defn(files,"NUMBER"); + create_builtin_type_defn(files,"GENERIC"); + */ + +} + +/****************************************************************** + ** Procedure: print_file_trailer + ** Parameters: const Schema schema - top-level schema printed + ** FILE* file - file on which to print trailer + ** Returns: + ** Description: handles cleaning up things at end of processing + ** Status: ok 1/15/91 + ******************************************************************/ + +/*ARGSUSED*/ +void +print_file_trailer( Express express, FILES * files ) { + //FILEclose( files->incall ); + //FILEclose( files->initall ); + //fprintf( files->create, "}\n\n" ); + //FILEclose( files->create ); + //fprintf( files->classes, "\n" ); + //FILEclose( files->classes ); +} + +/****************************************************************** + ** SCHEMA SECTION **/ + +/****************************************************************** + ** Procedure: SCOPEPrint + ** Parameters: const Scope scope - scope to print + ** FILE* file - file on which to print + ** Returns: + ** Description: cycles through the scopes of the input Express schema + ** Side Effects: calls functions for processing entities and types + ** Status: working 1/15/91 + ** -- it's still not clear how include files should be organized + ** and what the relationship is between this organization and the + ** organization of the schemas in the input Express + ******************************************************************/ + +void +SCOPEPrint( Scope scope, FILES * files, Schema schema, Express model, + ComplexCollect * col, int cnt ) { + Linked_List list = SCOPEget_entities_superclass_order( scope ); + DictionaryEntry de; + Type i; + int redefs = 0;// index = 0; + + /* fill in the values for the type descriptors */ + /* and print the enumerations */ + //fprintf( files -> inc, "\n/*\t************** TYPES \t*/\n" ); + //fprintf( files -> lib, "\n/*\t************** TYPES \t*/\n" ); + SCOPEdo_types( scope, t, de ) + // First check for one exception: Say enumeration type B is defined + // to be a rename of enum A. If A is in this schema but has not been + // processed yet, we must wait till it's processed first. The reason + // is because B will basically be defined with a couple of typedefs to + // the classes which represent A. (To simplify, we wait even if A is + // in another schema, so long as it's been processed.) + if( ( t->search_id == CANPROCESS ) + && ( TYPEis_enumeration( t ) ) + && ( ( i = TYPEget_ancestor( t ) ) != NULL ) + && ( i->search_id >= CANPROCESS ) ) { + redefs = 1; + } + SCOPEod + + SCOPEdo_types( scope, t, de ) + // Do the non-redefined enumerations: + if( ( t->search_id == CANPROCESS ) + && !( TYPEis_enumeration( t ) && TYPEget_head( t ) ) ) { + TYPEprint_descriptions( t, files, schema ); + if( !TYPEis_select( t ) ) { + // Selects have a lot more processing and are done below. + t->search_id = PROCESSED; + } + } + SCOPEod; + + // process redifined enumerations + if( redefs ) { + SCOPEdo_types( scope, t, de ) + if( t->search_id == CANPROCESS && TYPEis_enumeration( t ) ) { + TYPEprint_descriptions( t, files, schema ); + t->search_id = PROCESSED; + } + SCOPEod; + } + + /* do the select definitions next, since they depend on the others */ + //fprintf( files->inc, "\n//\t***** Build the SELECT Types \t\n" ); + // Note - say we have sel B, rename of sel A (as above by enum's). Here + // we don't have to worry about printing B before A. This is checked in + // TYPEselect_print(). + SCOPEdo_types( scope, t, de ) + if( t->search_id == CANPROCESS ) { + // Only selects haven't been processed yet and may still be set to + // CANPROCESS. + TYPEselect_print( t, files, schema ); + t->search_id = PROCESSED; + } + SCOPEod; + + // process each entity. This must be done *before* typedefs are defined + LISTdo( list, e, Entity ); + if( e->search_id == CANPROCESS ) { + ENTITYPrint( e, files, schema ); + e->search_id = PROCESSED; + } + LISTod; + + LISTfree( list ); +} + + +void +PrintModelContentsSchema( Scope scope, FILES * files, Schema schema, + Express model ) { + Linked_List list; + char nm[BUFSIZ]; + DictionaryEntry de; + + //fprintf( files -> inc, "\n/*\t************** TYPES \t*/\n" ); + // Types should be exported to schema_name.DefinedDataTypes + //fprintf( files -> lib, "\n/*\t************** TYPES \t*/\n" ); + //fprintf( files -> init, "\n/*\t************** TYPES \t*/\n" ); + + /* do \'new\'s for types descriptors */ + SCOPEdo_types( scope, t, de ) + //TYPEprint_new( t, files->create, schema ); + SCOPEod; + + /* do \'new\'s for entity descriptors */ + list = SCOPEget_entities_superclass_order( scope ); + //fprintf( files->init, "\n\t//\t***** Describe the Entities \t*/\n" ); + fprintf( files->inc, "\n//\t***** Describe the Entities \t\n" ); + LISTdo( list, e, Entity ); + ENTITYput_superclass( e ); /* find supertype to use for single */ + ENTITYprint_new( e, files, schema, 0 ); /* inheritance */ + LISTod; + + // Print Entity Classes + LISTdo( list, e, Entity ); + ENTITYPrint( e, files, schema ); + LISTod; + /* fill in the values for the type descriptors */ + /* and print the enumerations */ + //fprintf(files->lib,"register_defined_types():\n"); + fprintf( files->inc, "\n//\t***** Describe the Other Types \t\n" ); + SCOPEdo_types( scope, t, de ) + TYPEprint_descriptions( t, files, schema ); + if( TYPEis_select( t ) ) { + /* do the select aggregates here */ + strncpy( nm, SelectName( TYPEget_name( t ) ), BUFSIZ ); + fprintf( files->inc, "class %s;\ntypedef %s * %sH;\n", nm, nm, nm ); + fprintf( files->inc, + "typedef %s * %s_ptr;\ntypedef %s_ptr %s_var;\n\n", + nm, nm, nm, nm ); + fprintf( files->inc, "class %ss;\ntypedef %ss * %ssH;\n", nm, nm, nm ); + fprintf( files->inc, + "typedef %ss * %ss_ptr;\ntypedef %ss_ptr %ss_var;\n\n", + nm, nm, nm, nm ); + } + SCOPEod; + + /* build the typedefs */ + SCOPEdo_types( scope, t, de ) + if( !( TYPEis_select( t ) ) ) { + TYPEprint_typedefs( t, files ->inc ); + } + SCOPEod; + + /* do the select definitions next, since they depend on the others */ + fprintf( files->inc, "\n//\t***** Build the SELECT Types \t\n" ); + //fprintf( files->init, "\n//\t***** Add the TypeDescriptor's to the" + // " SELECT Types \t\n" ); + SCOPEdo_types( scope, t, de ) + if( TYPEis_select( t ) ) { + TYPEselect_print( t, files, schema ); + } + SCOPEod; + +LISTfree( list ); +} + + + +/****************************************************************** + ** Procedure: SCHEMAprint + ** Parameters: const Schema schema - schema to print + ** FILES *file - file on which to print + ** Express model - fedex rep of entire EXPRESS file + ** ComplexCollect col - all the complex entity info pertaining + ** to this EXPRESS file + ** int suffix - suffix to use for generated cc files + ** Returns: + ** Description: handles initialization of files specific to schemas + ** Side Effects: + ** Status: + ******************************************************************/ + +void +SCHEMAprint( Schema schema, FILES * files, Express model, void * complexCol, + int suffix ) { + char schnm[MAX_LEN], sufnm[MAX_LEN], fnm[MAX_LEN], *np; + /* sufnm = schema name + suffix */ + FILE * libfile, + //*incfile, + //*schemafile = files->incall, + // *schemainit = files->initall, + *initfile + // *createall = files->create + ; + Rule r; + Function f; + Procedure p; + DictionaryEntry de; + char * tmpstr = 0; + unsigned int tmpstr_size = 0; + /********** create files based on name of schema ***********/ + /* return if failure */ + /* 1. header file */ + //sprintf( schnm, "%s%s", SCHEMA_FILE_PREFIX, + // StrToUpper( SCHEMAget_name( schema ) ) ); + sprintf( schnm, "%s", SCHEMAget_name( schema ) ); + if( suffix == 0 ) { + sprintf( sufnm, "%s", schnm ); + } else { + sprintf( sufnm, "%s_%d", schnm, suffix ); + } + sprintf( fnm, "%s.h", sufnm ); + + np = fnm + strlen( fnm ) - 1; /* point to end of constant part of string */ + + /* 2. class source file */ + sprintf( np, "py" ); + if( !( libfile = ( files -> lib ) = FILEcreate( fnm ) ) ) { + return; + } + //fprintf( libfile, "/* %cId$ */ \n", '$' ); + fprintf(libfile,"from SCL.SCLBase import *\n"); + fprintf(libfile,"from SCL.SimpleDataTypes import *\n"); + fprintf(libfile,"from SCL.ConstructedDataTypes import *\n"); + fprintf(libfile,"from SCL.AggregationDataTypes import *\n"); + fprintf(libfile,"from SCL.TypeChecker import check_type\n"); + fprintf(libfile,"from SCL.Expr import *\n"); + + /********** do the schemas ***********/ + + /* really, create calls for entity constructors */ + SCOPEPrint( schema, files, schema, model, ( ComplexCollect * )complexCol, + suffix ); + + /********** close the files ***********/ + FILEclose( libfile ); + //FILEclose( incfile ); + //if( schema->search_id == PROCESSED ) { + // fprintf( initfile, "\n}\n" ); + // FILEclose( initfile ); + //} else { + // fclose( initfile ); + //} +} + +/****************************************************************** + ** Procedure: getMCPrint + ** Parameters: + Express express - in memory representation of an express model + FILE* schema_h - generated schema.h file + FILE* schema_cc - schema.cc file + ** Returns: + ** Description: drives functions to generate code for all the schemas + ** in an Express model into one set of files -- works with + ** print_schemas_combined + ** Side Effects: generates code + ** Status: 24-Feb-1992 new -kcm + ******************************************************************/ +void +getMCPrint( Express express, FILE * schema_h, FILE * schema_cc ) { + DictionaryEntry de; + Schema schema; + + fprintf( schema_h, + "\nSCLP23(Model_contents_ptr) GetModelContents(char *schemaName);\n" ); + fprintf( schema_cc, "%s%s%s%s", + "// Generate a function to be called by Model to help it\n", + "// create the necessary Model_contents without the\n", + "// dictionary (Registry) handle since it doesn't have a\n", + "// predetermined way to access to the handle.\n" ); + fprintf( schema_cc, + "\nSCLP23(Model_contents_ptr) GetModelContents(char *schemaName)\n{\n" ); + DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA ); + schema = ( Scope )DICTdo( &de ); + fprintf( schema_cc, + " if(!strcmp(schemaName, \"%s\"))\n", + SCHEMAget_name( schema ) ); + fprintf( schema_cc, + " return (SCLP23(Model_contents_ptr)) new SdaiModel_contents_%s; \n", + SCHEMAget_name( schema ) ); + while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) { + fprintf( schema_cc, + " else if(!strcmp(schemaName, \"%s\"))\n", + SCHEMAget_name( schema ) ); + fprintf( schema_cc, + " return (SCLP23(Model_contents_ptr)) new SdaiModel_contents_%s; \n", + SCHEMAget_name( schema ) ); + } + fprintf( schema_cc, "}\n" ); +} + +/****************************************************************** + ** Procedure: EXPRESSPrint + ** Parameters: + Express express -- in memory representation of an express model + FILES* files -- set of output files to print to + ** Returns: + ** Description: drives functions to generate code for all the schemas + ** in an Express model into one set of files -- works with + ** print_schemas_combined + ** Side Effects: generates code + ** Status: 24-Feb-1992 new -kcm + ******************************************************************/ +void +EXPRESSPrint( Express express, ComplexCollect & col, FILES * files ) { + char fnm [MAX_LEN], *np; + const char * schnm; /* schnm is really "express name" */ + FILE * libfile; + //FILE * incfile; + //FILE * schemafile = files -> incall; + //FILE * schemainit = files -> initall; + FILE * initfile; + /* new */ + Schema schema; + DictionaryEntry de; + + + /********** create files based on name of schema ***********/ + /* return if failure */ + /* 1. header file */ + sprintf( fnm, "%s.h", schnm = ClassName( EXPRESSget_basename( express ) ) ); + //if( !( incfile = ( files -> inc ) = FILEcreate( fnm ) ) ) { + // return; + //} + //fprintf( incfile, "/* %cId$ */\n", '$' ); + + //fprintf( incfile, "#ifdef __O3DB__\n" ); + //fprintf( incfile, "#include \n" ); + //fprintf( incfile, "#endif\n\n" ); + //fprintf( incfile, "#include \n" ); + /* fprintf (incfile, "#include \n");*/ + /* fprintf (incfile, "extern void %sInit (Registry & r);\n", schnm);*/ + + //np = fnm + strlen( fnm ) - 1; /* point to end of constant part of string */ + + /* 2. class source file */ + //sprintf( np, "cc" ); + if( !( libfile = ( files -> lib ) = FILEcreate( fnm ) ) ) { + return; + } + //fprintf( libfile, "/* %cId$ */\n", '$' ); + //fprintf( libfile, "#include <%s.h> n", schnm ); + + /* 3. source code to initialize entity registry */ + /* prints header of file for input function */ + + //sprintf( np, "init.cc" ); + //if( !( initfile = ( files -> init ) = FILEcreate( fnm ) ) ) { + // return; + //} + //fprintf( initfile, "/* $Id%d */\n", '$' ); + //fprintf( initfile, "#include <%s.h>\n\n", schnm ); + //fprintf( initfile, "void \n%sInit (Registry& reg)\n{\n", schnm ); + + /********** record in files relating to entire input ***********/ + + /* add to schema's include and initialization file */ + //fprintf( schemafile, "#include <%s.h>\n\n", schnm ); + //fprintf( schemafile, "extern void %sInit (Registry & r);\n", schnm ); + //fprintf( schemainit, "\t extern void %sInit (Registry & r);\n", schnm ); + //fprintf( schemainit, "\t %sInit (reg);\n", schnm ); + + /********** do all schemas ***********/ + DICTdo_init( express->symbol_table, &de ); + while( 0 != ( schema = ( Scope )DICTdo( &de ) ) ) { + SCOPEPrint( schema, files, schema, express, &col, 0 ); + } + + + /********** close the files ***********/ + FILEclose( libfile ); + //FILEclose( incfile ); + //fprintf( initfile, "\n}\n" ); + //FILEclose( initfile ); + +} + +/****************************************************************** + ** Procedure: print_schemas_combined + ** Parameters: + Express express -- in memory representation of an express model + FILES* files -- set of output files to print to + ** Returns: + ** Description: drives functions to generate code for all the schemas + ** in an Express model into one set of files -- works with EXPRESSPrint + ** Side Effects: generates code + ** Status: 24-Feb-1992 new -kcm + ******************************************************************/ + +void +print_schemas_combined( Express express, ComplexCollect & col, FILES * files ) { + + EXPRESSPrint( express, col, files ); +} + +/* +** Procedure: print_file +** Parameters: const Schema schema - top-level schema to print +** FILE* file - file on which to print +** Returns: void +** Description: this function calls one of two different functions +** depending on whether the output should be combined into a single +** set of files or a separate set for each schema +** +*/ + +void +print_file( Express express ) { + extern void RESOLUTIONsucceed( void ); + int separate_schemas = 1; + ComplexCollect col( express ); + + File_holder files; + + resolution_success(); + + print_file_header( express, &files ); + if( separate_schemas ) { + print_schemas_separate( express, ( void * )&col, &files ); + } else { + print_schemas_combined( express, col, &files ); + } + print_file_trailer( express, &files ); + //print_complex( col, ( const char * )"compstructs.cc" ); +} diff --git a/src/fedex_python/src/fedex_main_python.c b/src/fedex_python/src/fedex_main_python.c new file mode 100644 index 000000000..11e73c77a --- /dev/null +++ b/src/fedex_python/src/fedex_main_python.c @@ -0,0 +1,134 @@ + +/************************************************************************ +** Driver for Fed-X Express parser. +************************************************************************/ + +/* + * This software was developed by U.S. Government employees as part of + * their official duties and is not subject to copyright. + * + * $Log: fedex_main.c,v $ + * Revision 3.0.1.3 1997/11/05 23:12:18 sauderd + * Adding a new state DP3.1 and associated revision + * + * Revision 3.0.1.2 1997/09/26 15:59:10 sauderd + * Finished implementing the -a option (changed from -e) to generate the early + * bound access functions the old way. Implemented the change to generate them + * the new correct way by default. + * + * Revision 3.0.1.1 1997/09/18 21:18:41 sauderd + * Added a -e or -E option to generate attribute get and put functions the old + * way (without an underscore). It sets the variable old_accessors. This doesn't + * currently do anything. It needs to be implemented to generate attr funcs + * correctly. + * + * Revision 3.0.1.0 1997/04/16 19:29:03 dar + * Setting the first branch + * + * Revision 3.0 1997/04/16 19:29:02 dar + * STEP Class Library Pre Release 3.0 + * + * Revision 2.1.0.5 1997/03/11 15:33:59 sauderd + * Changed code so that if fedex_plus is passed the -c or -C option it would + * generate implementation objects for Orbix (CORBA). Look for code that is + * inside stmts such as if(corba_binding) + * + * Revision 2.1.0.4 1996/09/25 22:56:55 sauderd + * Added a command line argument for logging SCL use. The option added is -l or + * -L. It also says the option in the usage stmt when you run fedex_plus without + * an argument. Added the options to the EXPRESSgetopt_options string. + * + * Revision 2.1.0.3 1996/06/18 18:14:17 sauderd + * Changed the line that gets printed when you run fedex_plus with no + * arguments to include the option for single inheritance. + * + * Revision 2.1.0.2 1995/05/19 22:40:03 sauderd + * Added a command line argument -s or -S for generating code based on the old + * method as opposed to the new method of multiple inheritance. + * + * Revision 2.1.0.1 1995/05/16 19:52:18 lubell + * setting state to dp21 + * + * Revision 2.1.0.0 1995/05/12 18:53:48 lubell + * setting branch + * + * Revision 2.1 1995/05/12 18:53:47 lubell + * changing version to 2.1 + * + * Revision 1.7 1995/03/16 20:58:50 sauderd + * ? changes. + * + * Revision 1.6 1992/09/29 15:46:55 libes + * added messages for KC + * + * Revision 1.5 1992/08/27 23:28:52 libes + * moved Descriptor "new"s to precede assignments + * punted SELECT type + * + * Revision 1.4 1992/08/19 18:49:59 libes + * registry support + * + * Revision 1.3 1992/06/05 19:55:28 libes + * Added * to typedefs. Replaced warning kludges with ERRORoption. + */ + +#include +#include +#include "../express/express.h" +#include "../express/resolve.h" + +extern void print_fedex_version( void ); + +static void fedex_plus_usage( void ) { + fprintf( stderr, "usage: %s [-v] [-d # | -d 9 -l nnn -u nnn] [-n] [-p ] {-w|-i } express_file\n", EXPRESSprogram_name ); + //fprintf( stderr, "where\t-s or -S uses only single inheritance in the generated C++ classes\n" ); + //fprintf( stderr, "\t-a or -A generates the early bound access functions for entity classes the old way (without an underscore)\n" ); + //fprintf( stderr, "\t-c or -C generates C++ classes for use with CORBA (Orbix)\n" ); + //fprintf( stderr, "\t-L prints logging code in the generated C++ classes\n" ); + fprintf( stderr, "\t-v produces the version description below\n" ); + fprintf( stderr, "\t-d turns on debugging (\"-d 0\" describes this further\n" ); + //fprintf( stderr, "\t-p turns on printing when processing certain objects (see below)\n" ); + //fprintf( stderr, "\t-n do not pause for internal errors (useful with delta script)\n" ); + fprintf( stderr, "\t-w warning enable\n" ); + fprintf( stderr, "\t-i warning ignore\n" ); + fprintf( stderr, "and is one of:\n" ); + fprintf( stderr, "\tnone\n\tall\n" ); + LISTdo( ERRORwarnings, opt, Error_Warning ) + fprintf( stderr, "\t%s\n", opt->name ); + LISTod + fprintf( stderr, "and is one or more of:\n" ); + fprintf( stderr, " e entity\n" ); + fprintf( stderr, " p procedure\n" ); + fprintf( stderr, " r rule\n" ); + fprintf( stderr, " f function\n" ); + fprintf( stderr, " t type\n" ); + fprintf( stderr, " s schema or file\n" ); + fprintf( stderr, " # pass #\n" ); + fprintf( stderr, " E everything (all of the above)\n" ); + print_fedex_version(); + exit( 2 ); +} + +int Handle_FedPlus_Args( int, char * ); +void print_file( Express ); + +void resolution_success( void ) { + printf( "Resolution successful.\nWriting python module..." ); +} + +int success( Express model ) { + printf( "Done.\n" ); + return( 0 ); +} + +/* This function is called from main() which is part of the NIST Express + Toolkit. It assigns 2 pointers to functions which are called in main() */ +void EXPRESSinit_init() { + EXPRESSbackend = print_file; + EXPRESSsucceed = success; + EXPRESSgetopt = Handle_FedPlus_Args; + /* so the function getopt (see man 3 getopt) will not report an error */ + strcat( EXPRESSgetopt_options, "sSLcCaA" ); + ERRORusage_function = fedex_plus_usage; +} + diff --git a/src/fedex_python/src/multpass_python.c b/src/fedex_python/src/multpass_python.c new file mode 100644 index 000000000..bd1cdb4c5 --- /dev/null +++ b/src/fedex_python/src/multpass_python.c @@ -0,0 +1,703 @@ +/***************************************************************************** + * multpass.c * + * * + * Description: * + * Adds multi-schema support enhancement to fedex_plus parser. Allows the * + * generation of C++ representations for multiple EXPRESS schemas without * + * creating conflicting header files. Previously, fedex_plus would gene- * + * rate a single set of files (.h, .cc, .init.cc) for each schema found in * + * the processed EXPRESS file. A number of problem situations occurred: * + * * + * (1) Two schemas which USE or REFERENCE entities from one another. If * + * e.g. schema A USEs entity 1 from schema B and defines ent 2 subtype * + * of 1, and schema B USEs ent 2 from A and defines ents 1 and 3 sub- * + * type of 2, neither include file could be compiled first. * + * (2) An entity which has a select or enumeration attribute which is de- * + * fined in another schema. * + * (3) A select type which has a select or enum member item which is de- * + * fined in another schema. + * (4) An enumeration type which is a redefinition of an enum defined in * + * another schema. * + * * + * The functions in multpass.c provide for the processing of each schema * + * in multiple passes. At each pass, only entities and types which are * + * not dependent on undefined objects are processed. With each pass, more * + * entities and types become defined and more dependent entities and types * + * will become processable. At each state of processing, a separate set * + * of C++ files is generated. Lastly, multpass processes certain aggre- * + * gate and redefined objects after all the fundamental types are defined. * + * * + * Created by: David Rosenfeld * + * Date: 04/09/97 * + *****************************************************************************/ + +#include +#include "classes.h" + +#define FALSE 0 +#define TRUE 1 + +int isAggregateType( const Type t ); + +/* Local function prototypes: */ +static void initializeMarks( Express ); +static void unsetObjs( Schema ); +static int checkTypes( Schema ); +static int checkEnts( Schema ); +static void markDescs( Entity ); +static int checkItem( Type, Scope, Schema, int *, int ); +static int ENUMcanBeProcessed( Type, Schema ); +static int inSchema( Scope, Scope ); +static void addRenameTypedefs( Schema, FILE * ); +static void addAggrTypedefs( Schema , FILE * ); +static void addUseRefNames( Schema, FILE * ); + +void print_schemas_separate( Express express, void * complexCol, FILES * files ) +/* + * Generates the C++ files corresponding to a list of schemas. Does so in + * multiple passes through the schemas. In each pass it checks for enti- + * ties which are subtypes of entites in other schemas which have not yet + * been processed. Such entities cannot be processed in that pass until + * their supertypes have been defined. It also checks for entities which + * have enum or select attributes which have not been processed, and for + * select types which have enum or select items (or entities containing + * enums) which have not been processed. + */ +{ + int complete = FALSE, val1, val2, suffix; + DictionaryEntry de; + Schema schema; + + /* First set all marks we'll be using to UNPROCESSED/NOTKNOWN: */ + initializeMarks( express ); + //FIXME SdaiAll.cc:12:24: warning: unused variable ‘is’ [-Wunused-variable] (also for ui & ri) + //fprintf( files->create, " Interface_spec_ptr is;\n Used_item_ptr ui;\n Referenced_item_ptr ri;\n Uniqueness_rule_ptr ur;\n Where_rule_ptr wr;\n Global_rule_ptr gr;\n" ); + while( !complete ) { + complete = TRUE; + DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA ); + while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) { + if( schema->search_id == UNPROCESSED ) { + /* i.e., if the schema has more ents/types to process in it */ + unsetObjs( schema ); + /* Unset the ones which had search_id = CANTPROCESS. We're + // going to check that again since things may have changed by + // this pass. The ones with search_id = PROCESSED do not + // change since we're done with them. */ + schema->search_id = PROCESSED; + /* We assume this is the case unless something goes wrong. */ + val1 = checkTypes( schema ); + val2 = checkEnts( schema ); + /* The check functions recheck all the ents, types, USEd, and + // REFs which are still NOTKNOWN to see if we can process any + // more this pass. If any returns TRUE, we'll process again + // this round. */ + if( val1 || val2 ) { + if( schema->search_id == UNPROCESSED || + *( int * )schema->clientData > 0 ) { + /* What we're trying to determine here is if we will + // need to print multiple files for this schema. If + // we're already beyond a first file (2nd condition) + // or we're at the first but there are more entities + // which couldn't be processed yet (and thus search_id + // was still set to UNPROCESSED), this schema will be + // printed in multiple files. If so, SCHEMAprint() + // will create files with the suffixes "_1", "_2", etc. + // If not, no file suffix will be added. */ + suffix = ++*( int * )schema->clientData; + SCHEMAprint( schema, files, express, complexCol, + suffix ); + } else { + SCHEMAprint( schema, files, express, complexCol, 0 ); + } + } + complete = complete && ( schema->search_id == PROCESSED ); + /* Job's not complete so long as schema still has entities it + // had to skip. */ + } + } + } + + /******************* + *******************/ + + DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA ); + while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) { + //fprintf( files->create, + // "\t//////////////// USE statements\n" ); + //USEREFout( schema, schema->u.schema->usedict, schema->u.schema->use_schemas, "USE", files->create ); + + //fprintf( files->create, + // "\t//////////////// REFERENCE statements\n" ); + //USEREFout( schema, schema->u.schema->refdict, schema->u.schema->ref_schemas, "REFERENCE", files->create ); + } + /***************** + *****************/ + /* Before closing, we have three more situations to deal with (i.e., three + // types of declarations etc. which could only be printed at the end). + // Each is explained in the header section of its respective function. */ + DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA ); + while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) { + /* (These two tasks are totally unrelated but are done in the same loop + // for efficiency.) */ + addRenameTypedefs( schema, files->classes ); + addUseRefNames( schema, files->create ); + } + /* Third situation: (Must be dealt with after first, see header comments + // of addAggrTypedefs.) */ + DICTdo_type_init( express->symbol_table, &de, OBJ_SCHEMA ); + while( ( schema = ( Scope )DICTdo( &de ) ) != 0 ) { + //addAggrTypedefs( schema, files->classes ); + addAggrTypedefs( schema, files->lib ); + } + + /* On our way out, print the necessary statements to add support for + // complex entities. (The 1st line below is a part of SchemaInit(), + // which hasn't been closed yet. (That's done on 2nd line below.)) */ + //fprintf( files->initall, "\t reg.SetCompCollect( gencomplex() );\n" ); + //fprintf( files->initall, "}\n\n" ); + //fprintf( files->incall, "\n#include \n" ); + //fprintf( files->incall, "ComplexCollect *gencomplex();\n" ); + + /* Function GetModelContents() is printed at the end of the schema.xx + // files. This is done in a separate loop through the schemas, in function + // below. */ + //getMCPrint( express, files->incall, files->initall ); +} + +static void initializeMarks( Express express ) +/* + * Set all schema->search_id's to UNPROCESSED, meaning we haven't processed + * all the ents and types in it yet. Also, put an int=0 in each schema's + * clientData field. We'll use it to record what # file we're generating + * for each schema. Set all entity and type search_id's to NOTKNOWN mean- + * we don't know if we can process it yet. (An ent & select type may have + * an attribute/item which comes from another schema. All other types can + * be processed the first time, but that will be caught in checkTypes().) + */ +{ + DictionaryEntry de_sch, de_ent, de_type; + Schema schema; + + DICTdo_type_init( express->symbol_table, &de_sch, OBJ_SCHEMA ); + while( ( schema = ( Scope )DICTdo( &de_sch ) ) != 0 ) { + schema->search_id = UNPROCESSED; + schema->clientData = ( int * )malloc( sizeof( int ) ); + *( int * )schema->clientData = 0; + SCOPEdo_entities( schema, ent, de_ent ) + ent->search_id = NOTKNOWN; + SCOPEod + SCOPEdo_types( schema, t, de_type ) + t->search_id = NOTKNOWN; + SCOPEod + } +} + +static void unsetObjs( Schema schema ) +/* + * Resets all the ents & types of schema which had been set to CANTPROCRSS + * to NOTKNOWN. This function is called every time print_schemas_separate + * iterates through the schemas, printing to file what can be printed. At + * each pass we re-examine what ents/types can be processed. Ones which + * couldn't be processed at the last pass may be processable now. Ents/ + * types which have already been marked PROCESSED will not have to be + * revisited, and are not changed. + */ +{ + DictionaryEntry de; + + SCOPEdo_types( schema, t, de ) + if( t->search_id == CANTPROCESS ) { + t->search_id = NOTKNOWN; + } + SCOPEod + SCOPEdo_entities( schema, ent, de ) + if( ent->search_id == CANTPROCESS ) { + ent->search_id = NOTKNOWN; + } + SCOPEod +} + +static int checkTypes( Schema schema ) +/* + * Goes through the types contained in this schema checking for ones which + * can't be processed. This may be the case if: (1) We have a select type + * which has enumeration or select items which have not yet been defined + * (are defined in a different schema we haven't processed yet). (2) We + * have a select which has an entity item which contains unprocessed enums. + * (Unproc'ed selects, however, do not pose a problem here for reasons + * beyond the scope.) (3) We have an enum type which is a redefinition of + * an enum not yet defined. If we find any such type, we set its mark to + * CANTPROCESS. If some types in schema *can* be processed now, we return + * TRUE. (See relevant header comments of checkEnts() below.) + */ +{ + DictionaryEntry de; + int retval = FALSE, unknowncnt; + Type i; + Entity ent; + Linked_List attribs; + + do { + unknowncnt = 0; + SCOPEdo_types( schema, type, de ) + if( type->search_id != NOTKNOWN ) { + continue; + } + /* We're only interested in the ones which haven't been processed + // already or accepted (set to CANPROCESS in a previous pass thru + // the do loop) already. */ + type->search_id = CANPROCESS; + /* Assume this until disproven. */ + + if( TYPEis_enumeration( type ) && TYPEget_head( type ) ) { + i = TYPEget_ancestor( type ); + if( !sameSchema( i, type ) && i->search_id != PROCESSED ) { + /* Note - if, however, i is in same schema, we're safe: We + // know it'll be processed this pass because enum's are + // always processed on the first pass. (We do have to take + // care to process the original enum before the redefined. + // This is done in SCOPEPrint, in classes_wrapper.cc.) */ + type->search_id = CANTPROCESS; + schema->search_id = UNPROCESSED; + } + } else if( TYPEis_select( type ) ) { + LISTdo( SEL_TYPEget_items( type ), i, Type ) + if( !TYPEis_entity( i ) ) { + if( checkItem( i, type, schema, &unknowncnt, 0 ) ) { + break; + } + /* checkItem does most of the work of determining if + // an item of a select will make the select type un- + // processable. It checks for conditions which would + // make this true and sets values in type, schema, and + // unknowncnt accordingly. (See checkItem's commenting + // below.) It also return TRUE if i has made type un- + // processable. If so, we break - there's no point + // checking the other items of type any more. */ + } else { + /* Check if our select has an entity item which itself + // has unprocessed selects or enums. */ + ent = ENT_TYPEget_entity( i ); + if( ent->search_id == PROCESSED ) { + continue; + } + /* If entity has been processed already, things must be + // okay. (Note - but if it hasn't been processed yet we + // may still be able to process type. This is because + // a sel type will only contain a pointer to an entity- + // item (and we can create a pointer to a not-yet-pro- + // cessed object), while it will contain actual objects + // for the enum and select attributes of ent.) */ + attribs = ENTITYget_all_attributes( ent ); + LISTdo( attribs, attr, Variable ) + if( checkItem( attr->type, type, schema, + &unknowncnt, 1 ) ) { + break; + } + LISTod + LISTfree( attribs ); + } + LISTod + /* One more condition - if we're a select which is a rename of + // another select - we must also make sure the original select + // is in this schema or has been processed. Since a rename- + // select is defined with typedef's to the original, we can't + // do that if the original hasn't been defined. */ + if( ( type->search_id == CANPROCESS ) + && ( ( i = TYPEget_ancestor( type ) ) != NULL ) + && ( !sameSchema( i, type ) ) + && ( i->search_id != PROCESSED ) ) { + type->search_id = CANTPROCESS; + schema->search_id = UNPROCESSED; + } + } + + if( type->search_id == CANPROCESS ) { + /* NOTE - This condition will be met if type isn't a select or + // enum at all and above if was never entered (and it's our + // first pass so type hasn't been processed). So for non-enums + // and selects, checkTypes() will simply check the type off and + // go on. */ + retval = TRUE; + } + SCOPEod + } while( unknowncnt > 0 ); + /* We loop to deal with the following situation: Say sel A contains enum B + // as an item, but A appears earlier in the EXPRESS file than B. In such a + // case, we really can process A now since it doesn't depend on anything + // which won't be processed till later. But when we first reach A, item B + // will have value NOTKNOWN, and at the time we won't know if B will be set + // to CANPROCESS when we get to it. To deal with this, checkItem() below + // increments unknowncnt for every item which is in this schema and still + // has search_id = NOTKNOWN. (Not if id = CANTPROCESS, which means we've + // tried already this pass and B still can't be processed.) Here, we keep + // looping until all the unknowns are resolved. (It may take may passes if + // selX has item selY which has item selZ.) (I take all the trouble with + // this so as not to generate mult files in unnecessary cases where e.g. + // the EXPRESS is in a single schema.) */ + + return retval; +} + +static int checkEnts( Schema schema ) +/* + * Goes through the entities contained in this schema checking for ones + * which can't be processed. It checks for two situations: (1) If we find + * an entity which is a subtype of a not-yet-processed entity in another + * schema. (2) If an entity has an attribute which is an enumeration or + * select type (which is implemented by fedex_plus as a C++ class), and the + * enum or select class has not yet been defined. For each entity which + * satisfies one of the above conditions, we set its mark and the marks of + * all its subtype descendents to CANTPROCESS. Later, when C++ files are + * generated for this schema, the ents marked CANTPROCESS will be skipped. + * checkEnts() will return TRUE if there are some ents/types which *can* be + * processed now. This will tell later functions that there are some pro- + * cessable entities at this pass and C++ files should be generated. (Some + * of the inline commenting of checkTypes() is applicable here and is not + * repeated.) + */ +{ + DictionaryEntry de; + int retval = FALSE, ignore = 0; + + /* Loop through schema's entities: */ + SCOPEdo_entities( schema, ent, de ) + if( ent->search_id != NOTKNOWN ) { + continue; + } + /* ent->search_id may = CANTPROCESS signifying we've already determined + // that this ent is dependent on an undefined external one. (It got + // its mark already because it was the descendent of a parent entity we + // already checked and rejected.) ent->search_id may = PROCESSED. In + // such a case there of course is also nothing to check now. */ + ent->search_id = CANPROCESS; + + /* First traverse ent's supertypes. If any is from a different schema + // and is not yet defined, ent will have to wait. */ + LISTdo( ENTITYget_supertypes( ent ), super, Entity ) + if( ( !sameSchema( ent, super ) ) + && ( super->search_id != PROCESSED ) ) { + markDescs( ent ); + schema->search_id = UNPROCESSED; + break; + /* Exit the LISTdo loop. Since we found an unprocessed + // parent, we're done with this entity. */ + } + LISTod + + /* Next traverse ent's attributes, looking for attributes which are + // not yet defined (more explanation in checkItem()). */ + if( ent->search_id == CANPROCESS ) { + /* Only do next test if ent hasn't already failed the 1st. */ + LISTdo( ENTITYget_attributes( ent ), attr, Variable ) + if( checkItem( attr->type, ent, schema, &ignore, 0 ) ) { + markDescs( ent ); + break; + } + LISTod + } + + if( ent->search_id == CANPROCESS ) { + /* If ent's mark still = CANPROCESS and not CANTPROCESS, it + // must still be processable. Set retval to TRUE signifying + // that there are ent's we'll be able to process. */ + retval = TRUE; + } + SCOPEod + /* NOTE - We don't have to loop here as in checkTypes() (see long comment + // there). It was necessary there because we may have processed type + // sel1 before its member enum1. Whereas here, since all types are done + // before selects (checkTypes() is called before checkEnts()), there is + // no such concern. */ + + return retval; +} + +static void markDescs( Entity ent ) +/* + * Sets the mark value of ent and all its subtypes to CANTPROCESS. This + * function is called if we've determined that ent is a subtype of an + * entity defined in a different schema which has not yet been processed. + */ +{ + ent->search_id = CANTPROCESS; + LISTdo( ENTITYget_subtypes( ent ), sub, Entity ) + markDescs( sub ); + LISTod +} + +static int checkItem( Type t, Scope parent, Schema schema, int * unknowncnt, + int noSel ) +/* + * Function with a lot of side effects: Checks if type t, a member of + * `parent' makes parent unprocessable. parent may be an entity and t is + * its attribute. parent may be a select type and t is one of its items. + * parent may be a select type and t an attribute of one of its entity + * items. Lastly, parent may be an aggregate and t its base type. t will + * make parent unprocessable if it is an enum or sel which hasn't been + * processed yet, see inline commenting. If so, parent->search_id is set + * to CANTPROCESS, and schema->search_id is set to UNPROCESSED (i.e., we're + * not done yet). Also, if one of parent's items is still NOTKNOWN (caused + * if it's in our schema and we haven't gotten to it yet - see comment, end + * of checkTypes()), parent is set to NOTKNOWN and unknowncnt is incremen- + * ted to tell us that we'll have to try parent again after its item has + * been processed (i.e., we have to repeat the do-loop in checkTypes()). + * checkItem returns TRUE if parent became unprocessable; FALSE otherwise. + * + * NOTE: noSel deals with the following: Say selA has member entX. If + * entX has attribute enumP, it creates a problem, while if entX has attr + * selB, it is not. When using checkItem for an ent member of a select, + * noSel is set to 1 to tell it to worry about t if it's an enum but not + * if it's a select. + */ +{ + Type i = t; + + if( isAggregateType( t ) ) { + i = TYPEget_base_type( t ); + /* NOTE - If t is a 2D aggregate or higher, we do not go down to its + // lowest base type. An item which is a higher dimension aggregates + // does not make its parent unprocessable. All an e.g. entity needs + // defined to have a 2D aggr attribute is GenericAggregate (built in) + // and a typedef for a pointer to the type name, which is declared in + // Sdaiclasses.h. */ + } + + if( TYPEis_enumeration( i ) && !ENUMcanBeProcessed( i, schema ) ) { + /* Enum's are usually processed on the first try. ENUMcanBeProcessed() + // checks for cases of renamed enum's, which must wait for the enum i + // is a rename of. */ + if( parent->search_id == NOTKNOWN ) { + /* We had thought parent's val was going to be NOTKNOWN - i.e., + // dependent on other selects in this schema which haven't been + // processed. When we set it to NOTKNOWN we also incremented + // unknowncnt. Now we see it's not going to be unknown so we + // decrement the count: */ + ( *unknowncnt )--; + } + parent->search_id = CANTPROCESS; + schema->search_id = UNPROCESSED; + return TRUE; + } else if( TYPEis_select( i ) && !noSel ) { + if( !sameSchema( i, parent ) ) { + if( i->search_id != PROCESSED ) { + if( parent->search_id == NOTKNOWN ) { + ( *unknowncnt )--; + } + parent->search_id = CANTPROCESS; + schema->search_id = UNPROCESSED; + return TRUE; + } + } else { + /* We have another sel in the same schema. This gets complicated - + // it may be processable but we just haven't gotten to it yet. So + // we may have to wait on parent. */ + if( i->search_id == CANTPROCESS ) { + /* We *have* checked i already and it can't be processed. */ + if( parent->search_id == NOTKNOWN ) { + ( *unknowncnt )--; + } + parent->search_id = CANTPROCESS; + schema->search_id = UNPROCESSED; + return TRUE; + } else if( i->search_id == NOTKNOWN ) { + /* We haven't processed i this pass. */ + if( parent->search_id != NOTKNOWN ) { + parent->search_id = NOTKNOWN; + /* We lower parent's value. But don't return TRUE. That + // would tell checkTypes() that there's nothing more to + // check. But checkTypes should keep looping thru the re- + // maining items of parent - maybe one of them will tell us + // that parent definitely can't be processed this pass. */ + ( *unknowncnt )++; + } + } + } + } + return FALSE; +} + +static int ENUMcanBeProcessed( Type e, Schema s ) +/* + * Tells us if an enumeration type has been processed already, or if not + * will be processed this pass through schema s. As always, I take great + * pains to avoid breaking up a schema into >1 file unnecessarily. In + * cases where a user is building a library based on a single schema, we + * shouldn't cause him to suffer side-effects of the mult schema support, + * because of a case that "looks like" it may require multiple files. + */ +{ + Type a; + + if( !inSchema( e, s ) ) { + /* If e is not in s - the schema we're processing now - things are + // fairly simple. Nothing is going to change by the time we finish + // with this schema. Base the return val on whether or not e *was* + // processed already. */ + return ( e->search_id == PROCESSED ); + } + + if( e->search_id != NOTKNOWN ) { + /* Next case: e is in our schema, but either it's been processed + // already, or we've determined that it can or can't be processed. + // This case is also relatively simple - we have nothing more to + // figure out here. */ + return ( e->search_id >= CANPROCESS ); + /* PROC/CANPROC - TRUE; UNPROC'ED/CANTPROC - FALSE */ + } + + /* Remaining case: e is in our schema and still = NOTKNOWN. I.e., we + // haven't gotten to e this pass and don't yet know whether it'll be + // processable. Figure that out now: */ + if( ( a = TYPEget_ancestor( e ) ) == NULL ) { + /* If e is not a rename of anything, it should be processed now. */ + return TRUE; + } + if( inSchema( a, s ) || a->search_id == PROCESSED ) { + /* If e's ancestor (the one it's a rename of) is in our schema it will + // be processed now. If not, it must have been processed already. */ + return TRUE; + } + return FALSE; +} + +int sameSchema( Scope sc1, Scope sc2 ) +/* + * Checks if sc1 and sc2 are in the same superscope. Normally called for + * two types to see if they're in the same schema. + */ +{ + return ( !strcmp( SCOPEget_name( sc1->superscope ), + SCOPEget_name( sc2->superscope ) ) ); +} + +static int inSchema( Scope scope, Scope super ) +/* + * Checks if scope is contained in super's scope. + */ +{ + return ( !strcmp( SCOPEget_name( scope->superscope ), + SCOPEget_name( super ) ) ); +} + +static void addRenameTypedefs( Schema schema, FILE * classes ) +/* + * Prints typedefs at the end of Sdaiclasses.h for enumeration or select + * types which are renamed from other enum/sel's. Since the original e/s + * may be in any schema, this must be done at the end of all the schemas. + * (Actually, for the enum only the aggregate class name is written in + * Sdaiclasses.h (needs to have forward declarations here).) + */ +{ +} + +static void addAggrTypedefs( Schema schema, FILE * classes ) +/* + * Print typedefs at the end of Sdiaclasses.h for aggregates of enum's and + * selects. Since the underlying enum/sel may appear in any schema, this + * must be done at the end of all the schemas. Note that this function is + * called after addRenameTypedefs() since an aggregate may also be based on + * one of the renamed enum/sel's defined there. + */ +{ + DictionaryEntry de; + Type i; + static int firsttime = TRUE; + char nm[BUFSIZ]; + + SCOPEdo_types( schema, t, de ) + if( TYPEis_aggregate( t ) ) { + i = TYPEget_base_type( t ); + if( TYPEis_enumeration( i ) || TYPEis_select( i ) ) { + /* This if will pass if t was a 1D aggregate only. They are + // the only types which had to wait for their underlying type. + // 2D aggr's and higher only need type GenericAggr defined + // which is built-in. */ + printf("in addAggrTypedefs. %s is enum or select.\n",TYPEget_name(t)); + //strncpy( nm, ClassName( TYPEget_name( t ) ), BUFSIZ ); + //printf("%s;%s",nm,TYPEget_ctype( t )); + //if( firsttime ) { + // fprintf( classes, "The first TIME\n" ); + // firsttime = FALSE; + //} + //fprintf(classes,"in addAggrTypedefs. %s is enum or select.\n",TYPEget_name(t)); + //strncpy( nm, ClassName( TYPEget_name( t ) ), BUFSIZ ); + //fprintf( classes, "typedef %s\t%s;\n", + // TYPEget_ctype( t ), nm ); + //fprintf( classes, "typedef %s *\t%sH;\n", nm, nm ); + //fprintf( classes, "typedef %s *\t%s_ptr;\n", nm, nm ); + } + } + SCOPEod +} + +static void addUseRefNames( Schema schema, FILE * create ) +/* + * Checks the USE and REFERENCE dicts contained in schema. If either dict + * contains items (types or entities) which are renamed in this schema, + * code is written to add another member to the "altNames" list of the + * corresponding TypeDescriptor or EntityDescriptor object in the SCL. The + * list will be used in the SCL to use the correct name of this type or + * entity when reading and writing files. + */ +{ + Dictionary useRefDict; + DictionaryEntry de; + Rename * rnm; + char * oldnm, schNm[BUFSIZ]; + static int firsttime = TRUE; + + if( ( useRefDict = schema->u.schema->usedict ) != NULL ) { + DICTdo_init( useRefDict, &de ); + while( ( rnm = ( Rename * )DICTdo( &de ) ) != 0 ) { + oldnm = ( ( Scope )rnm->object )->symbol.name; + if( ( strcmp( oldnm, rnm->nnew->name ) ) ) { + /* strcmp != 0, so old and new names different. + // Note: can't just check if nnew != old. That wouldn't + // catch following: schema C USEs obj Y from schema B + // (not renamed). B USEd it from schema A and renamed it + // from X. nnew would = old, but name would not be same + // as rnm->object's name. */ + if( firsttime ) { + fprintf( create, "\t// Alternate names for types and " ); + fprintf( create, "entities when used in other schemas:\n" ); + firsttime = FALSE; + } + if( rnm->type == OBJ_TYPE ) { + fprintf( create, "\t%s", TYPEtd_name( ( Type )rnm->object ) ); + } else { + /* must be an entity */ + fprintf( create, "\t%s%s%s", + SCOPEget_name( ( ( Entity )rnm->object )->superscope ), + ENT_PREFIX, ENTITYget_name( ( Entity )rnm->object ) ); + } + strcpy( schNm, PrettyTmpName( SCHEMAget_name( schema ) ) ); + fprintf( create, "->addAltName( \"%s\", \"%s\" );\n", + schNm, PrettyTmpName( rnm->nnew->name ) ); + } + } + } + if( ( useRefDict = schema->u.schema->refdict ) != NULL ) { + DICTdo_init( useRefDict, &de ); + while( ( rnm = ( Rename * )DICTdo( &de ) ) != 0 ) { + oldnm = ( ( Scope )rnm->object )->symbol.name; + if( ( strcmp( oldnm, rnm->nnew->name ) ) ) { + if( firsttime ) { + fprintf( create, "\t// Alternate names for types and " ); + fprintf( create, "entities when used in other schemas:\n" ); + firsttime = FALSE; + } + if( rnm->type == OBJ_TYPE ) { + fprintf( create, "\t%s", TYPEtd_name( ( Type )rnm->object ) ); + } else { + fprintf( create, "\t%s%s%s", + SCOPEget_name( ( ( Entity )rnm->object )->superscope ), + ENT_PREFIX, ENTITYget_name( ( Entity )rnm->object ) ); + } + strcpy( schNm, PrettyTmpName( SCHEMAget_name( schema ) ) ); + fprintf( create, "->addAltName( \"%s\", \"%s\" );\n", + schNm, PrettyTmpName( rnm->nnew->name ) ); + } + } + } +} diff --git a/src/fedex_python/src/selects_python.c b/src/fedex_python/src/selects_python.c new file mode 100644 index 000000000..4b901c1ec --- /dev/null +++ b/src/fedex_python/src/selects_python.c @@ -0,0 +1,742 @@ +/******************************************************************* +** FedEx parser output module for generating C++ class definitions +** December 5, 1989 +** release 2 17-Feb-1992 +** release 3 March 1993 +** release 4 December 1993 +** K. C. Morris +** +** Development of FedEx was funded by the United States Government, +** and is not subject to copyright. + +******************************************************************* +The conventions used in this binding follow the proposed specification +for the STEP Standard Data Access Interface as defined in document +N350 ( August 31, 1993 ) of ISO 10303 TC184/SC4/WG7. +*******************************************************************/ + +extern int multiple_inheritance; + +/************************************************************************** +******** The functions in this file generate C++ code for representing +******** EXPRESS SELECT types. +**************************************************************************/ +#include +#include "classes.h" + +int isAggregateType( const Type t ); +char * generate_attribute_name( Variable a, char * out ); +char * FundamentalType( const Type t, int report_reftypes ); +void ATTRsign_access_methods( Variable a, FILE * file ); +char * generate_attribute_func_name( Variable a, char * out ); +void ATTRprint_access_methods_get_head( const char * classnm, Variable a, FILE * file ); +void ATTRprint_access_methods_put_head( const char * entnm, Variable a, FILE * file ); + +#define BASE_SELECT "SCLP23(Select)" + +#define TYPEis_primitive(t) ( !( TYPEis_entity(t) || \ + TYPEis_select (t) || \ + TYPEis_aggregate(t) ) ) + +#define TYPEis_numeric(t) ( ((t)->u.type->body->type == real_) || \ + ((t)->u.type->body->type == integer_) || \ + ((t)->u.type->body->type == number_) ) +#define PRINT_BUG_REPORT \ + fprintf( f, " std::cerr << __FILE__ << \":\" << __LINE__ << \": ERROR" \ + " in schema library: \\n\" \n\t<< _POC_ << \"\\n\\n\";\n"); + +#define PRINT_SELECTBUG_WARNING(f) \ + fprintf( (f), "\n severity( SEVERITY_WARNING );\n" ); \ + fprintf( (f), " std::cerr << __FILE__ << \":\" << __LINE__ << \": "); \ + fprintf( (f), "WARNING: possible misuse of\"\n << \" SELECT "); \ + fprintf( (f), "TYPE from schema library.\\n\";\n"); \ + fprintf( (f), " Error( \"Mismatch in underlying type.\" );\n" ); + +#define print_error_msg() \ + fprintf( f, "\n severity( SEVERITY_BUG );\n" ); \ + PRINT_BUG_REPORT \ + fprintf( f, " Error( \"This 'argument' is of the incorrect type\" );\n" ); + +#define TRUE 1 +#define FALSE 0 + +static void initSelItems( const Type, FILE * ); + +const char * +SEL_ITEMget_enumtype( Type t ) { + return StrToUpper( TYPEget_name( t ) ); +} + + +/****************************************************************** + ** Procedure: TYPEget_utype + ** Parameters: Type t + ** Returns: type used to represent the underlying type in a select class + ** Description: + ** Side Effects: + ** Status: + ******************************************************************/ + +const char * +TYPEget_utype( Type t ) { +} + +/******************* +LISTmember + +determines if the given entity is a member of the list. +RETURNS the member if it is a member; otherwise 0 is returned. +*******************/ +Generic +LISTmember( const Linked_List list, Generic e ) { + Link node; + for( node = list->mark->next; node != list->mark; node = node->next ) + if( e == node -> data ) { + return e; + } + return ( 0 ); +} + +/******************* + compareOrigTypes + + Specialized function to catch if two enumerations, two selects, or two aggrs + of either, are of the same type. The issue is that e.g. select B may be a + rename of sel A (i.e., TYPE B = A;). Such renamed types are implemented by + fedex_plus with typedefs, so that they are in fact the same type. TYPEget_- + ctype() is used for most type comparisons and does not consider renamed types + equivalent. This function is called in instances when they should be consi- + dered equivalent. One such case is the generation of duplicate lists. + *******************/ +static int +compareOrigTypes( Type a, Type b ) { + Type t, u; + + if( ( TYPEis_select( a ) && TYPEis_select( b ) ) + || ( TYPEis_enumeration( a ) && TYPEis_enumeration( b ) ) ) { + t = a; + u = b; + } else if( TYPEis_aggregate( a ) && TYPEis_aggregate( b ) ) { + t = TYPEget_base_type( a ); + u = TYPEget_base_type( b ); + if( !( ( TYPEis_select( t ) && TYPEis_select( u ) ) + || ( TYPEis_enumeration( t ) && TYPEis_enumeration( u ) ) ) ) { + return FALSE; + /* Only go further with 1D aggregates of sels or enums. Note that + // for 2D aggrs and higher we do not continue. These are all recog- + // nized to be the same type ("GenericAggregate") by TYPEget_ctype(), + // and do not have to be handled specially here. */ + } + } else { + return FALSE; + } + + if( TYPEget_head( t ) ) { + t = TYPEget_ancestor( t ); + } + if( TYPEget_head( u ) ) { + u = TYPEget_ancestor( u ); + } + return ( !strcmp( TYPEget_name( t ), TYPEget_name( u ) ) ); +} + +/******************* + utype_member + + determines if the given "link's" underlying type is a member of the list. + RETURNS the underlying type if it is a member; otherwise 0 is returned. + + If "rename" is TRUE, we also consider check to match in certain cases where + list already has an item that check is a renaming of (see header comments to + compareOrigTypes() above). + *******************/ +const char * +utype_member( const Linked_List list, const Type check, int rename ) { + static char r [BUFSIZ]; + + LISTdo( list, t, Type ) + strncpy( r, TYPEget_utype( t ), BUFSIZ ); + if( strcmp( r, TYPEget_utype( check ) ) == 0 ) { + return r; + } + if( rename && compareOrigTypes( check, t ) ) { + return r; + } + LISTod; + return 0; +} + +/** +*** SELgetnew_dmlist (const Type type) +*** Returns a list of types which have unique underlying types +*** The returned list includes all the types which have a data members +*** in the select type. +*** +*** The list that is returned needs to be freed by the caller. +***/ + + +Linked_List +SELgetnew_dmlist( const Type type ) { + Linked_List complete = SEL_TYPEget_items( type ); + Linked_List newlist = LISTcreate(); + + LISTdo( complete, t, Type ) + + /* if t\'s underlying type is not already in newlist, */ + if( ! utype_member( newlist, t, 0 ) ) { + LISTadd_last( newlist, t ); + } + + LISTod; + + return newlist; + +} + +const char * +SEL_ITEMget_dmtype( Type t, const Linked_List l ) { + const char * r = utype_member( l, t, 0 ); + return StrToLower( r ? r : TYPEget_utype( t ) ); + +} + + +/******************* +duplicate_in_express_list + +determines if the given "link's" underlying type is a multiple member +of the list. + RETURNS 1 if true, else 0. +*******************/ +int +duplicate_in_express_list( const Linked_List list, const Type check ) { + if( TYPEis_entity( check ) ) { + return FALSE; + } + /* entities are never the same */ + + LISTdo( list, t, Type ) + if( t == check ) { + ; /* don\'t compare check to itself */ + } else { + return TRUE; /* other things in the list conflict */ + } + LISTod; + return FALSE; +} + +/******************* +unique_types ( const Linked_List list ) + +determines if any of the types in a select type resolve to the same +underlying Express type. +RETURNS 1 if true, else 0. +*******************/ +int +unique_types( const Linked_List list ) { + LISTdo( list, t, Type ) + if( duplicate_in_express_list( list, t ) ) { + return FALSE; + } + LISTod; + return TRUE; +} + + +/******************* +duplicate_utype_member + +determines if the given "link's" C++ representation is used again in the list. + RETURNS 1 if true, else 0. +*******************/ +int +duplicate_utype_member( const Linked_List list, const Type check ) { + char b [BUFSIZ]; + + if( TYPEis_entity( check ) ) { + return FALSE; + } + /* entities are never the same */ + + LISTdo( list, t, Type ) + if( t == check ) { + ; + } + /* don\'t compare check to itself */ + else { /* continue looking */ + strncpy( b, TYPEget_utype( t ), BUFSIZ ); + if( ( !strcmp( b, TYPEget_utype( check ) ) ) + || ( compareOrigTypes( t, check ) ) ) + /* if the underlying types are the same */ + { + return TRUE; + } + if( ! strcmp( b, "SCLP23(Integer)" ) && + ( ! strcmp( TYPEget_utype( check ), "SCLP23(Real)" ) ) ) + /* integer\'s and real\'s are not unique */ + { + return TRUE; + } + } + LISTod; + return FALSE; +} + +/******************* +any_duplicates_in_select + +determines if any of the types in a select type resolve to the same +C++ representation for the underlying Express type. +RETURNS 1 if true, else 0. +*******************/ +int +any_duplicates_in_select( const Linked_List list ) { + LISTdo( list, t, Type ) + if( duplicate_utype_member( list, t ) ) { + return TRUE; + } + LISTod; + return FALSE; +} + +/******************* +find_duplicate_list + +finds an instance of each kind of duplicate type found in the given list. +This list is returned as dup_list. If a duplicate exists, the function +returns TRUE, else FALSE. +list should be unbound before calling, and freed afterwards. +*******************/ +int +find_duplicate_list( const Type type, Linked_List * duplicate_list ) { + Linked_List temp; /** temporary list for comparison **/ + + *duplicate_list = LISTcreate(); + if( any_duplicates_in_select( SEL_TYPEget_items( type ) ) ) { + /** if there is a dup somewhere **/ + temp = LISTcreate(); + LISTdo( SEL_TYPEget_items( type ), u, Type ) + if( !utype_member( *duplicate_list, u, 1 ) ) { + /** if not already a duplicate **/ + if( utype_member( temp, u, 1 ) ) { + LISTadd_first( *duplicate_list, u ); + } else { + LISTadd_first( temp, u ); + } + } + LISTod; + LISTfree( temp ); + return TRUE; + } + return FALSE; +} + +/******************* +non_unique_types_string ( const Type type ) + +returns a string containing the non-unique EXPRESS types deriveable +from a select. the returned string is in the form (TYPE | TYPE |...) +*******************/ +/* In the functions below, we use a vector of ints to count paths in the + select-graph to base types. The names in this enum correspond to the + indices in the vector, i.e., tvec[treal] == tvec[1], and contains the + number of paths to REAL in the graph +*/ + +enum __types { + tint = 0, /* INTEGER */ + treal, /* REAL */ + tstring, /* STRING */ + tbinary, /* BINARY */ + tenum, /* ENUMERATION, also LOGICAL, BOOLEAN */ + tselect, /* SELECT */ + tentity, /* ENTITY */ + taggr, /* AGGREGATE, also ARRAY, BAG, SET, LIST */ + tnumber /* NUMBER */ +}; + +/* This function gets called recursively, to follow a select-graph to its + leaves. It passes around the vector described above, to track paths to + the leaf nodes. +*/ +void +non_unique_types_vector( const Type type, int * tvec ) { + LISTdo( SEL_TYPEget_items( type ), t, Type ) + switch( TYPEget_body( t )->type ) { + case integer_: + tvec[tint]++; + break; + case real_: + tvec[treal]++; + break; + case string_: + tvec[tstring]++; + break; + case binary_: + tvec[tbinary]++; + break; + case enumeration_: + case logical_: + case boolean_: + tvec[tenum]++; + break; + case select_: + /* SELECT, ergo recurse! */ + non_unique_types_vector( t, tvec ); + break; + case entity_: + tvec[tentity]++; + break; + case aggregate_: + case array_: + case list_: + case bag_: + case set_: + tvec[taggr]++; + break; + case number_: + tvec[tnumber]++; + break; + default: + printf( "Error in %s, line %d: type %d not handled by switch statement.", __FILE__, __LINE__, TYPEget_body( t )->type ); + abort(); + } + LISTod; +} + +/* Uses non_unique_types_vector on the select to get a vector of base-type + reference counts, then uses that to make a string of types, of the form + (FOO_TYPE | BAR_TYPE | BAZ_TYPE), where FOO, BAR, and BAZ are EXPRESS + types. If all types are unique, the string (0) is generated. +*/ +char * +non_unique_types_string( const Type type ) { + int tvec[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + char * typestr; + int first = 1; + int i; + + non_unique_types_vector( type, tvec ); + + /* build type string from vector */ + typestr = ( char * )malloc( BUFSIZ ); + typestr[0] = '\0'; + strcat( typestr, ( char * )"(" ); + for( i = 0; i <= tnumber; i++ ) { + if( tvec[i] < 2 ) { + continue; /* skip, this one is unique */ + } + + if( !first ) { + strcat( typestr, ( char * )" | " ); + } else { + first = 0; + } + switch( i ) { + case tint : + strcat( typestr, ( char * )"sdaiINTEGER" ); + break; + case treal : + strcat( typestr, ( char * )"sdaiREAL" ); + break; + case tstring: + strcat( typestr, ( char * )"sdaiSTRING" ); + break; + case tbinary: + strcat( typestr, ( char * )"sdaiBINARY" ); + break; + case tenum : + strcat( typestr, ( char * )"sdaiENUMERATION" ); + break; + case tentity: + strcat( typestr, ( char * )"sdaiINSTANCE" ); + break; + case taggr : + strcat( typestr, ( char * )"sdaiAGGR" ); + break; + case tnumber: + strcat( typestr, ( char * )"sdaiNUMBER" ); + break; + } + } + if( first ) { + strcat( typestr, ( char * )"0" ); + } + strcat( typestr, ( char * )")" ); + return typestr; +} + + + +/****************************************************************** + ** Procedure: ATTR_LISTmember + ** Parameters: Linked_List l, Variable check + ** Returns: the attribute if an attribute with the same name as "check" + ** is on the list, 0 otherwise + ** Description: checks to see if an attribute is a member of the list + ** Side Effects: + ** Status: 26-Oct-1993 done + ******************************************************************/ + +Variable +ATTR_LISTmember( Linked_List l, Variable check ) { + char nm [BUFSIZ]; + char cur [BUFSIZ]; + + generate_attribute_name( check, nm ); + LISTdo( l, a, Variable ) + generate_attribute_name( a, cur ); + if( ! strcmp( nm, cur ) ) { + return check; + } + LISTod; + return ( 0 ); +} + + +/****************************************************************** + ** Procedure: SEL_TYPEgetnew_attribute_list + ** Parameters: const Type type + ** Returns: Returns a list of all the attributes for a select type. + ** The list is the union of all the attributes of the underlying types. + ** Description: + ** Side Effects: +*** The list that is returned needs to be freed by the caller. + ** Status: + ******************************************************************/ + +Linked_List +SEL_TYPEgetnew_attribute_list( const Type type ) { + Linked_List complete = SEL_TYPEget_items( type ); + Linked_List newlist = LISTcreate(); + Linked_List attrs; + Entity cur; + + LISTdo( complete, t, Type ) + if( TYPEis_entity( t ) ) { + cur = ENT_TYPEget_entity( t ); + attrs = ENTITYget_all_attributes( cur ); + LISTdo( attrs, a, Variable ) + if( ! ATTR_LISTmember( newlist, a ) ) { + LISTadd_first( newlist, a ); + } + LISTod; + } + LISTod; + return newlist; +} + +/******************* +TYPEselect_inc_print_vars prints the class 'definition', that is, the objects + and the constructor(s)/destructor for a select class. +********************/ +void +TYPEselect_inc_print_vars( const Type type, FILE * f, Linked_List dups ) { + +} + +/******************* +TYPEselect_inc_print prints the class member function declarations of a select +class. +*******************/ +void +TYPEselect_inc_print( const Type type, FILE * f ) { + } + + +/******************* +TYPEselect_lib_print_part_one prints constructor(s)/destructor of a select +class. +*******************/ +void +TYPEselect_lib_print_part_one( const Type type, FILE * f, Schema schema, + Linked_List dups, char * n ) { +} + +static void +initSelItems( const Type type, FILE * f ) +/* + * Creates initialization functions for the select items of a select. The + * selects must have their typedescriptors set properly. If a select is a + * renaming of another select ("TYPE selB = selA") its td would default to + * selA's, so it must be set specifically. + */ +{ +} + +Linked_List +ENTITYget_expanded_entities( Entity e, Linked_List l ) { + Linked_List supers; + int super_cnt = 0; + Entity super; + + if( ! LISTmember( l, e ) ) { + LISTadd_first( l, e ); + } + + if( multiple_inheritance ) { + supers = ENTITYget_supertypes( e ); + LISTdo( supers, s, Entity ) + /* ignore the more than one supertype + since multiple inheritance isn\'t implemented */ + if( super_cnt == 0 ) { + ENTITYget_expanded_entities( s, l ); + } + ++ super_cnt; + LISTod; + } else { + /* ignore the more than one supertype + since multiple inheritance isn\'t implemented */ + super = ENTITYget_superclass( e ); + ENTITYget_expanded_entities( super, l ); + } + return l; +} + +Linked_List +SELget_entity_itemlist( const Type type ) { + Linked_List complete = SEL_TYPEget_items( type ); + Linked_List newlist = LISTcreate(); + Entity cur; + + LISTdo( complete, t, Type ) + if( TYPEis_entity( t ) ) { + cur = ENT_TYPEget_entity( t ); + ENTITYget_expanded_entities( cur, newlist ); + } + LISTod; + return newlist; + +} + +static int +memberOfEntPrimary( Entity ent, Variable uattr ) +/* + * Specialized function used in function TYPEselect_lib_print_part_three + * below. Calls a function to check if an attribute of an entity belongs + * to its primary path (is its own attr, that of its first super, that of + * its first super's first super etc), and does necessary housekeeping. + */ +{ + Linked_List attrlist = LISTcreate(); + int result; + + ENTITYget_first_attribs( ent, attrlist ); + result = ( LISTmember( attrlist, uattr ) != 0 ); + LIST_destroy( attrlist ); + return result; +} + +/******************* +TYPEselect_lib_print_part_three prints part 3) of the SDAI C++ binding for +a select class -- access functions for the data members of underlying entity +types. +*******************/ +void +TYPEselect_lib_print_part_three( const Type type, FILE * f, Schema schema, + char * classnm ) { +} + +/******************* +TYPEselect_lib_print_part_four prints part 4 of the SDAI document of a select +class. +*******************/ +void +TYPEselect_lib_print_part_four( const Type type, FILE * f, Schema schema, + Linked_List dups, char * n ) { + } + + +/******************* +TYPEselect_init_print prints the types that belong to the select type +*******************/ + +void +TYPEselect_init_print( const Type type, FILE * f, Schema schema ) { +#define schema_name SCHEMAget_name(schema) + LISTdo( SEL_TYPEget_items( type ), t, Type ) + + fprintf( f, "\t%s -> Elements ().AddNode", + TYPEtd_name( type ) ); + fprintf( f, " (%s);\n", + TYPEtd_name( t ) ); + LISTod; +#undef schema_name +} + +void +TYPEselect_lib_part21( const Type type, FILE * f, Schema schema ) { +} + + +void +TYPEselect_lib_StrToVal( const Type type, FILE * f, Schema schema ) { +} + +void +TYPEselect_lib_virtual( const Type type, FILE * f, Schema schema ) { + TYPEselect_lib_part21( type, f, schema ); + TYPEselect_lib_StrToVal( type, f, schema ); +} + +void +SELlib_print_protected( const Type type, FILE * f, const Schema schema ) { +} + +/******************* +TYPEselect_lib_print prints the member functions (definitions) of a select +class. +*******************/ +void +TYPEselect_lib_print( const Type type, FILE * f, Schema schema ) { + fprintf( f, "# SELECT TYPE %s_\n", TYPEget_name(type) ); + // writes the variable with strings + LISTdo( SEL_TYPEget_items( type ), t, Type ) + if (is_python_keyword(TYPEget_name(t))) { + fprintf(f,"if (not '%s_' in globals().keys()):\n",TYPEget_name(t)); + fprintf( f, "%s_ = '%s_'\n",TYPEget_name(t),TYPEget_name(t)); + } + else { + fprintf(f,"if (not '%s' in globals().keys()):\n",TYPEget_name(t)); + fprintf( f, "\t%s = '%s'\n",TYPEget_name(t),TYPEget_name(t)); + } + LISTod; + + // create the SELECT + if (is_python_keyword(TYPEget_name(type))) { + fprintf( f, "%s_ = SELECT(",TYPEget_name(type)); + } + else { + fprintf( f, "%s = SELECT(",TYPEget_name(type)); + } + + // first compute the number of types (necessary to insert commas) + int nbr_select = 0; + LISTdo( SEL_TYPEget_items( type ), t, Type ) + nbr_select++; + LISTod; + // then write types + int num = 0; + LISTdo( SEL_TYPEget_items( type ), t, Type ) + if (is_python_keyword(TYPEget_name(t))) { + fprintf( f, "\n\t'%s_'",TYPEget_name(t)); + } + else { + fprintf( f, "\n\t'%s'",TYPEget_name(t)); + } + if (num < nbr_select -1 ) fprintf(f,","); + num++; + LISTod; + fprintf(f,")\n"); +} + +void +TYPEselect_print( Type t, FILES * files, Schema schema ) { +} +#undef BASE_SELECT + + +/************************************************************************** +******** END of SELECT TYPE +**************************************************************************/