From 495bcd6926d6ce06e7dd06300ee4763235bacf89 Mon Sep 17 00:00:00 2001 From: Peter Clifton Date: Sun, 19 Apr 2015 03:30:01 +0100 Subject: [PATCH 1/8] Fix use-after free of various fundamental types which are effectively singletons. We should not delete these in the Registry destructor, as other registry classes may still need them. A better fix would be tostatically initialise them, as suggested by Mark Pictor. Fixes: https://github.com/stepcode/stepcode/issues/327 --- src/clstepcore/Registry.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/clstepcore/Registry.cc b/src/clstepcore/Registry.cc index 4501f89e5..d61d4030b 100644 --- a/src/clstepcore/Registry.cc +++ b/src/clstepcore/Registry.cc @@ -81,6 +81,10 @@ Registry::~Registry() { SC_HASHdestroy( active_types ); delete col; +/* NB: These are implemented as singletons, so we MUST NOT DELETE THEM! + * Other registry objects may be relying on their continued existance + */ +#if 0 if( t_sdaiINTEGER ) { delete t_sdaiINTEGER; t_sdaiINTEGER = NULL; @@ -109,6 +113,7 @@ Registry::~Registry() { delete t_sdaiNUMBER; t_sdaiNUMBER = NULL; } +#endif } void Registry::DeleteContents() { From 208f3effbd604a0d61a0bae0af1bcd6635bd29f1 Mon Sep 17 00:00:00 2001 From: Peter Clifton Date: Sun, 19 Apr 2015 03:30:01 +0100 Subject: [PATCH 2/8] Fix assigning an Entity reference attribute with the late bound API If the (SDAI_Application_instance * ) pointer already exists, it may well have been assigned by the early-bound class initialiser to point into an instance of its class type. We should not delete that pointer, rather just alter its contents. --- src/clstepcore/STEPattribute.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/clstepcore/STEPattribute.cc b/src/clstepcore/STEPattribute.cc index 251beb445..f8a3ff3c2 100644 --- a/src/clstepcore/STEPattribute.cc +++ b/src/clstepcore/STEPattribute.cc @@ -958,10 +958,9 @@ void STEPattribute::Binary( SDAI_Binary * bin ) { void STEPattribute::Entity( SDAI_Application_instance * ent ) { assert( NonRefType() == ENTITY_TYPE ); - if( ptr.c ) { - delete ptr.c; + if( ptr.c == NULL ) { + ptr.c = new (SDAI_Application_instance * ); } - ptr.c = new (SDAI_Application_instance * ); *( ptr.c ) = ent; } From f444958fce76831336231a7ca8a188046d54b8d5 Mon Sep 17 00:00:00 2001 From: Peter Clifton Date: Sun, 19 Apr 2015 03:30:01 +0100 Subject: [PATCH 3/8] Fixup AP214 schema ENTITY conversion_based_unit The schema currently in use for AP214e3 contains a change that turned out to be a mistake causing breakage of old files, and was subsequently reverted prior to publication of the standard The published schema doesn't appear to have been corrected, so in the mean time, this fix corrects things to match the ammended section from Part 42. (This change removes DERIVED rule for dimensions attribute, and replaces it with a WHERE clause checking the explict attribute matches the intended derivation.) --- data/ap214e3/AP214E3_2010.exp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/data/ap214e3/AP214E3_2010.exp b/data/ap214e3/AP214E3_2010.exp index 28d88fc90..cb2b65583 100644 --- a/data/ap214e3/AP214E3_2010.exp +++ b/data/ap214e3/AP214E3_2010.exp @@ -3475,13 +3475,11 @@ ENTITY contract_type; END_ENTITY; -- 10303-41: contract_schema ENTITY conversion_based_unit -SUBTYPE OF (named_unit); - name : label; - conversion_factor : measure_with_unit; -DERIVE - SELF\named_unit.dimensions : dimensional_exponents := - derive_dimensional_exponents(conversion_factor\measure_with_unit. - unit_component); + SUBTYPE OF (named_unit); + name : label; + conversion_factor : measure_with_unit; +WHERE + WR1: SELF\named_unit.dimensions = derive_dimensional_exponents(conversion_factor\measure_with_unit.unit_component); END_ENTITY; -- 10303-41: measure_schema ENTITY coordinated_universal_time_offset; From 5afbfaef06a7215b0db3f40fa116eb4ec9c752fb Mon Sep 17 00:00:00 2001 From: Peter Clifton Date: Sun, 19 Apr 2015 03:30:01 +0100 Subject: [PATCH 4/8] Fix inconsistent sort order compared to ISO-10303-21 standard This manifested in incorrect complex entity ordering in some cases. For example, a complex containing a BOUNDED_SURFACE and B_SPLINE_SURFACE entity would emit them in the incorrect order. (This was picked up upon loading SCL created files in the IDA-step viewer). Fixes: https://github.com/stepcode/stepcode/issues/330 --- src/clstepcore/complexSupport.h | 8 +-- src/clstepcore/complexlist.cc | 2 +- src/clstepcore/entlist.cc | 4 +- src/clstepcore/entnode.cc | 2 +- src/clstepcore/non-ors.cc | 2 +- src/clstepcore/schRename.h | 2 +- src/clutils/Str.cc | 92 ++++++++++++++++++++++++ src/clutils/Str.h | 1 + src/exp2cxx/CMakeLists.txt | 1 + src/exp2cxx/Str.cc | 105 ++++++++++++++++++++++++++++ src/exp2cxx/Str.h | 18 +++++ src/exp2cxx/complexSupport.h | 10 +-- src/exp2cxx/complexlist.cc | 2 +- src/exp2cxx/entlist.cc | 2 +- src/exp2cxx/entnode.cc | 2 +- src/exp2cxx/non-ors.cc | 2 +- src/exp2python/CMakeLists.txt | 1 + src/exp2python/src/complexSupport.h | 10 +-- 18 files changed, 244 insertions(+), 22 deletions(-) create mode 100644 src/exp2cxx/Str.cc create mode 100644 src/exp2cxx/Str.h diff --git a/src/clstepcore/complexSupport.h b/src/clstepcore/complexSupport.h index 46b673b46..9ba62472a 100644 --- a/src/clstepcore/complexSupport.h +++ b/src/clstepcore/complexSupport.h @@ -96,10 +96,10 @@ class SC_CORE_EXPORT EntNode { return ( strcmp( name, ent.name ) == 0 ); } bool operator< ( EntNode & ent ) { - return ( strcmp( name, ent.name ) < 0 ); + return ( entity_name_cmp( name, ent.name ) < 0 ); } bool operator> ( EntNode & ent ) { - return ( strcmp( name, ent.name ) > 0 ); + return ( entity_name_cmp( name, ent.name ) > 0 ); } EntNode & operator= ( EntNode & ent ); void Name( const char * nm ) { @@ -363,10 +363,10 @@ class SC_CORE_EXPORT ComplexList { void buildList(); void remove(); int operator< ( ComplexList & c ) { - return ( strcmp( supertype(), c.supertype() ) < 0 ); + return ( entity_name_cmp( supertype(), c.supertype() ) < 0 ); } int operator< ( char * name ) { - return ( strcmp( supertype(), name ) < 0 ); + return ( entity_name_cmp( supertype(), name ) < 0 ); } int operator== ( char * name ) { return ( strcmp( supertype(), name ) == 0 ); diff --git a/src/clstepcore/complexlist.cc b/src/clstepcore/complexlist.cc index 52eb0a372..f1ee90715 100644 --- a/src/clstepcore/complexlist.cc +++ b/src/clstepcore/complexlist.cc @@ -106,7 +106,7 @@ void ComplexList::addChildren( EntList * ent ) { } } else { nm = ( dynamic_cast(ent) )->name; - while( prev != NULL && ( comp = strcmp( prev->name, nm ) ) < 0 ) { + while( prev != NULL && ( comp = entity_name_cmp( prev->name, nm ) ) < 0 ) { prev2 = prev; prev = prev->next; } diff --git a/src/clstepcore/entlist.cc b/src/clstepcore/entlist.cc index 0dd35803a..7a542313f 100644 --- a/src/clstepcore/entlist.cc +++ b/src/clstepcore/entlist.cc @@ -93,7 +93,7 @@ void SimpleList::unmarkAll( EntNode * ents ) { return; } - while( eptr != NULL && ( comp = strcmp( eptr->name, name ) ) < 0 ) { + while( eptr != NULL && ( comp = entity_name_cmp( eptr->name, name ) ) < 0 ) { eptr = eptr->next; } // (We assume we have a match now since viable >= MATCHSOME.) @@ -117,7 +117,7 @@ bool SimpleList::acceptChoice( EntNode * ents ) { int comp; while( eptr != NULL ) { - if( ( comp = strcmp( name, eptr->name ) ) == 0 ) { + if( ( comp = entity_name_cmp( name, eptr->name ) ) == 0 ) { if( ! eptr->marked() ) { eptr->setmark( ORMARK ); I_marked = ORMARK; diff --git a/src/clstepcore/entnode.cc b/src/clstepcore/entnode.cc index 792489e4b..9c50913e5 100644 --- a/src/clstepcore/entnode.cc +++ b/src/clstepcore/entnode.cc @@ -32,7 +32,7 @@ EntNode::EntNode( const char ** names ) { while( names[j] && *names[j] != '*' ) { nm = names[j]; - while( prev != NULL && ( comp = StrCmpIns( prev->name, nm ) ) < 0 ) { + while( prev != NULL && ( comp = entity_name_cmp( prev->name, nm ) ) < 0 ) { prev2 = prev; prev = prev->next; } diff --git a/src/clstepcore/non-ors.cc b/src/clstepcore/non-ors.cc index 14607f606..fc97e7efd 100644 --- a/src/clstepcore/non-ors.cc +++ b/src/clstepcore/non-ors.cc @@ -24,7 +24,7 @@ MatchType SimpleList::matchNonORs( EntNode * ents ) { int comp; while( eptr != NULL ) { - if( ( comp = strcmp( name, eptr->name ) ) == 0 ) { + if( ( comp = entity_name_cmp( name, eptr->name ) ) == 0 ) { if( ! eptr->marked( MARK ) ) { // NOTE - this cond also returns true if eptr did have an OR- // MARK. We don't want to remark now (since we're also trying diff --git a/src/clstepcore/schRename.h b/src/clstepcore/schRename.h index a0403a5d8..6b89ebb51 100644 --- a/src/clstepcore/schRename.h +++ b/src/clstepcore/schRename.h @@ -32,7 +32,7 @@ class SC_CORE_EXPORT SchRename { return newName; } int operator< ( SchRename & schrnm ) { - return ( strcmp( schName, schrnm.schName ) < 0 ); + return ( entity_name_cmp( schName, schrnm.schName ) < 0 ); /* ??? SHOULD THIS BE entity_name_cmp ??? */ } bool choice( const char * nm ) const; // is nm one of our possible choices? diff --git a/src/clutils/Str.cc b/src/clutils/Str.cc index ba36cd610..ee78e61bb 100644 --- a/src/clutils/Str.cc +++ b/src/clutils/Str.cc @@ -112,6 +112,98 @@ int StrCmpIns( const char * str1, const char * str2 ) { return c1 - c2; } +static int contiguous_block_number( unsigned char c ) +{ + if (c == 0) /* \0 */ + return 0; + if (c == 32) /* SPACE */ + return 1; + if (48 <= c && c <= 57) /* 0-9 */ + return 2; + if (97 <= c && c <= 122) /* a-z */ + return 3; + if (65 <= c && c <= 90) /* A-Z */ + return 4; + if (c == 95) /* _ */ + return 5; + if (33 <= c && c <= 34) /* !" */ + return 6; + if (c == 42) /* * */ + return 7; + if (36 <= c && c <= 38) /* $%& */ + return 8; + if (c == 46) /* . */ + return 9; + if (c == 35) /* # */ + return 10; + if (43 <= c && c <= 45) /* +,- */ + return 11; + if (40 <= c && c <= 41) /* () */ + return 12; + if (c == 63) /* ? */ + return 13; + if (c == 47) /* / */ + return 14; + if (58 <= c && c <= 62) /* :<=> */ + return 15; + if (c == 64) /* @ */ + return 16; + if (c == 91) /* [ */ + return 17; + if (c == 93) /* ] */ + return 18; + if (123 <= c && c <= 125) /* {|} */ + return 19; + if (c == 94) /* ^ */ + return 20; + if (c == 96) /* ` */ + return 21; + if (c == 126) /* ~ */ + return 22; + if (c == 92) /* \ */ + return 23; + if (c == 39) /* ' */ + return 24; + + return 25; +} + +static int entity_char_cmp( unsigned char c1, unsigned char c2 ) +{ + int block1 = contiguous_block_number( c1 ); + int block2 = contiguous_block_number( c2 ); + + if (block1 != block2) + return block1 - block2; + + return c1 - c2; +} + +/**************************************************************//** + ** \fn entity_name_cmp (const char * str1, const char * str2) + ** \returns Comparison result + ** Compares two strings according to P21 entity naming rules + ** Returns < 0 when str1 less then str2 + ** == 0 when str1 equals str2 + ** > 0 when str1 greater then str2 + ******************************************************************/ +int entity_name_cmp( const char *str1, const char *str2 ) +{ + const unsigned char *s1 = ( const unsigned char * ) str1; + const unsigned char *s2 = ( const unsigned char * ) str2; + unsigned char c1, c2; + + do { + c1 = ( unsigned char ) *s1++; + c2 = ( unsigned char ) *s2++; + if( c1 == '\0' ) + return c1 - c2; /* 0 if both c1 and c2 are \0, otherwise returns -ve for c1 terminating first */ + } while( c1 == c2 ); + + return entity_char_cmp( c1, c2 ); +} + + /** * Test if a string ends with the given suffix. */ diff --git a/src/clutils/Str.h b/src/clutils/Str.h index f605bfdda..a9d50f1a4 100644 --- a/src/clutils/Str.h +++ b/src/clutils/Str.h @@ -32,6 +32,7 @@ SC_UTILS_EXPORT const char * StrToLower( const char * word, std::string & s ); SC_UTILS_EXPORT const char * StrToUpper( const char * word, std::string & s ); SC_UTILS_EXPORT const char * StrToConstant( const char * word, std::string & s ); SC_UTILS_EXPORT int StrCmpIns( const char * str1, const char * str2 ); +SC_UTILS_EXPORT int entity_name_cmp ( const char * str1, const char * str2 ); SC_UTILS_EXPORT const char * PrettyTmpName( const char * oldname ); SC_UTILS_EXPORT char * PrettyNewName( const char * oldname ); SC_UTILS_EXPORT char * EntityClassName( char * oldname ); diff --git a/src/exp2cxx/CMakeLists.txt b/src/exp2cxx/CMakeLists.txt index 04fdfb1ac..636cfd6cb 100644 --- a/src/exp2cxx/CMakeLists.txt +++ b/src/exp2cxx/CMakeLists.txt @@ -27,6 +27,7 @@ set(exp2cxx_SOURCES trynext.cc write.cc print.cc + Str.cc genCxxFilenames.c ) diff --git a/src/exp2cxx/Str.cc b/src/exp2cxx/Str.cc new file mode 100644 index 000000000..67decfd7d --- /dev/null +++ b/src/exp2cxx/Str.cc @@ -0,0 +1,105 @@ +/* +* NIST Utils Class Library +* clutils/Str.cc +* April 1997 +* K. C. Morris +* David Sauder + +* Development of this software was funded by the United States Government, +* and is not subject to copyright. +*/ + +#include "Str.h" +#include +#include + +static int contiguous_block_number( unsigned char c ) +{ + if (c == 0) /* \0 */ + return 0; + if (c == 32) /* SPACE */ + return 1; + if (48 <= c && c <= 57) /* 0-9 */ + return 2; + if (97 <= c && c <= 122) /* a-z */ + return 3; + if (65 <= c && c <= 90) /* A-Z */ + return 4; + if (c == 95) /* _ */ + return 5; + if (33 <= c && c <= 34) /* !" */ + return 6; + if (c == 42) /* * */ + return 7; + if (36 <= c && c <= 38) /* $%& */ + return 8; + if (c == 46) /* . */ + return 9; + if (c == 35) /* # */ + return 10; + if (43 <= c && c <= 45) /* +,- */ + return 11; + if (40 <= c && c <= 41) /* () */ + return 12; + if (c == 63) /* ? */ + return 13; + if (c == 47) /* / */ + return 14; + if (58 <= c && c <= 62) /* :<=> */ + return 15; + if (c == 64) /* @ */ + return 16; + if (c == 91) /* [ */ + return 17; + if (c == 93) /* ] */ + return 18; + if (123 <= c && c <= 125) /* {|} */ + return 19; + if (c == 94) /* ^ */ + return 20; + if (c == 96) /* ` */ + return 21; + if (c == 126) /* ~ */ + return 22; + if (c == 92) /* \ */ + return 23; + if (c == 39) /* ' */ + return 24; + + return 25; +} + +static int entity_char_cmp( unsigned char c1, unsigned char c2 ) +{ + int block1 = contiguous_block_number( c1 ); + int block2 = contiguous_block_number( c2 ); + + if (block1 != block2) + return block1 - block2; + + return c1 - c2; +} + +/**************************************************************//** + ** \fn entity_name_cmp (const char * str1, const char * str2) + ** \returns Comparison result + ** Compares two strings according to P21 entity naming rules + ** Returns < 0 when str1 less then str2 + ** == 0 when str1 equals str2 + ** > 0 when str1 greater then str2 + ******************************************************************/ +int entity_name_cmp( const char *str1, const char *str2 ) +{ + const unsigned char *s1 = ( const unsigned char * ) str1; + const unsigned char *s2 = ( const unsigned char * ) str2; + unsigned char c1, c2; + + do { + c1 = ( unsigned char ) *s1++; + c2 = ( unsigned char ) *s2++; + if( c1 == '\0' ) + return c1 - c2; /* 0 if both c1 and c2 are \0, otherwise returns -ve for c1 terminating first */ + } while( c1 == c2 ); + + return entity_char_cmp( c1, c2 ); +} diff --git a/src/exp2cxx/Str.h b/src/exp2cxx/Str.h new file mode 100644 index 000000000..a5d48e321 --- /dev/null +++ b/src/exp2cxx/Str.h @@ -0,0 +1,18 @@ + +#ifndef STR_H +#define STR_H + +/* +* NIST Utils Class Library +* clutils/Str.h +* April 1997 +* K. C. Morris +* David Sauder + +* Development of this software was funded by the United States Government, +* and is not subject to copyright. +*/ + +int entity_name_cmp ( const char * str1, const char * str2 ); + +#endif diff --git a/src/exp2cxx/complexSupport.h b/src/exp2cxx/complexSupport.h index 8277a03fa..22181e732 100644 --- a/src/exp2cxx/complexSupport.h +++ b/src/exp2cxx/complexSupport.h @@ -5,6 +5,8 @@ #include using namespace std; +#include "Str.h" + extern "C" { #include @@ -88,10 +90,10 @@ class EntNode { return ( strcmp( name, ent.name ) == 0 ); } int operator< ( EntNode & ent ) { - return ( strcmp( name, ent.name ) < 0 ); + return ( entity_name_cmp( name, ent.name ) < 0 ); } int operator> ( EntNode & ent ) { - return ( strcmp( name, ent.name ) > 0 ); + return ( entity_name_cmp( name, ent.name ) > 0 ); } void setmark( MarkType stamp = MARK ) { mark = stamp; @@ -353,10 +355,10 @@ class ComplexList { void buildList(); void remove(); int operator< ( ComplexList & c ) { - return ( strcmp( supertype(), c.supertype() ) < 0 ); + return ( entity_name_cmp( supertype(), c.supertype() ) < 0 ); } int operator< ( char * name ) { - return ( strcmp( supertype(), name ) < 0 ); + return ( entity_name_cmp( supertype(), name ) < 0 ); } int operator== ( char * name ) { return ( strcmp( supertype(), name ) == 0 ); diff --git a/src/exp2cxx/complexlist.cc b/src/exp2cxx/complexlist.cc index 84acd5a20..c658e71b7 100644 --- a/src/exp2cxx/complexlist.cc +++ b/src/exp2cxx/complexlist.cc @@ -112,7 +112,7 @@ void ComplexList::addChildren( EntList * ent ) } } else { nm = ( dynamic_cast< SimpleList * >(ent) )->name; - while( prev != NULL && ( comp = strcmp( prev->name, nm ) ) < 0 ) { + while( prev != NULL && ( comp = entity_name_cmp( prev->name, nm ) ) < 0 ) { prev2 = prev; prev = prev->next; } diff --git a/src/exp2cxx/entlist.cc b/src/exp2cxx/entlist.cc index e27114294..1cc8bc78c 100644 --- a/src/exp2cxx/entlist.cc +++ b/src/exp2cxx/entlist.cc @@ -111,7 +111,7 @@ void SimpleList::unmarkAll( EntNode * ents ) return; } - while( eptr != NULL && ( comp = strcmp( eptr->name, name ) ) < 0 ) { + while( eptr != NULL && ( comp = entity_name_cmp( eptr->name, name ) ) < 0 ) { eptr = eptr->next; } // (We assume we have a match now since viable >= MATCHSOME.) diff --git a/src/exp2cxx/entnode.cc b/src/exp2cxx/entnode.cc index 50f3a8659..bcaf5832f 100644 --- a/src/exp2cxx/entnode.cc +++ b/src/exp2cxx/entnode.cc @@ -42,7 +42,7 @@ EntNode::EntNode( char * namelist[] ) while( *namelist[j] != '*' ) { nm = namelist[j]; - while( prev != NULL && ( comp = strcmp( prev->name, nm ) ) < 0 ) { + while( prev != NULL && ( comp = entity_name_cmp( prev->name, nm ) ) < 0 ) { prev2 = prev; prev = prev->next; } diff --git a/src/exp2cxx/non-ors.cc b/src/exp2cxx/non-ors.cc index 2ef5dd803..f89654b6a 100644 --- a/src/exp2cxx/non-ors.cc +++ b/src/exp2cxx/non-ors.cc @@ -25,7 +25,7 @@ MatchType SimpleList::matchNonORs( EntNode * ents ) int comp; while( eptr != NULL ) { - if( ( comp = strcmp( name, eptr->name ) ) == 0 ) { + if( ( comp = entity_name_cmp( name, eptr->name ) ) == 0 ) { if( ! eptr->marked( MARK ) ) { // NOTE - this cond also returns TRUE if eptr did have an OR- // MARK. We don't want to remark now (since we're also trying diff --git a/src/exp2python/CMakeLists.txt b/src/exp2python/CMakeLists.txt index d67632ff6..c1ba7b682 100644 --- a/src/exp2python/CMakeLists.txt +++ b/src/exp2python/CMakeLists.txt @@ -28,6 +28,7 @@ if(SC_PYTHON_GENERATOR) ../exp2cxx/trynext.cc ../exp2cxx/write.cc ../exp2cxx/print.cc + ../exp2cxx/Str.cc ) SC_ADDEXEC(exp2python "${exp2python_SOURCES}" "express;base") diff --git a/src/exp2python/src/complexSupport.h b/src/exp2python/src/complexSupport.h index 7cd781a37..5070ea805 100644 --- a/src/exp2python/src/complexSupport.h +++ b/src/exp2python/src/complexSupport.h @@ -5,6 +5,8 @@ #include using namespace std; +#include "../exp2cxx/Str.h" + extern "C" { #include @@ -88,10 +90,10 @@ class EntNode { return ( strcmp( name, ent.name ) == 0 ); } int operator< ( EntNode & ent ) { - return ( strcmp( name, ent.name ) < 0 ); + return ( entity_name_cmp( name, ent.name ) < 0 ); } int operator> ( EntNode & ent ) { - return ( strcmp( name, ent.name ) > 0 ); + return ( entity_name_cmp( name, ent.name ) > 0 ); } void setmark( MarkType stamp = MARK ) { mark = stamp; @@ -353,10 +355,10 @@ class ComplexList { void buildList(); void remove(); int operator< ( ComplexList & c ) { - return ( strcmp( supertype(), c.supertype() ) < 0 ); + return ( entity_name_cmp( supertype(), c.supertype() ) < 0 ); } int operator< ( char * name ) { - return ( strcmp( supertype(), name ) < 0 ); + return ( entity_name_cmp( supertype(), name ) < 0 ); } int operator== ( char * name ) { return ( strcmp( supertype(), name ) == 0 ); From c6a0ab045e2ad699f18ec76824b1f7d12aa0812b Mon Sep 17 00:00:00 2001 From: Peter Clifton Date: Sun, 19 Apr 2015 03:30:01 +0100 Subject: [PATCH 5/8] Fix potential buffer overrun in PrettyTmpName --- src/clutils/Str.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/clutils/Str.cc b/src/clutils/Str.cc index ee78e61bb..12add4fac 100644 --- a/src/clutils/Str.cc +++ b/src/clutils/Str.cc @@ -273,10 +273,12 @@ const char * PrettyTmpName( const char * oldname ) { int i = 0; static char newname [BUFSIZ]; newname [0] = '\0'; - while( ( oldname [i] != '\0' ) && ( i < BUFSIZ ) ) { + while( ( oldname [i] != '\0' ) && ( i < BUFSIZ - 1 ) ) { newname [i] = ToLower( oldname [i] ); if( oldname [i] == '_' ) { /* character is '_' */ ++i; + if (oldname [i] == '\0' || i >= BUFSIZ - 1) + break; newname [i] = ToUpper( oldname [i] ); } if( oldname [i] != '\0' ) { From f47a4336db22262d47ded981e1c0782de8c209e3 Mon Sep 17 00:00:00 2001 From: Peter Clifton Date: Sun, 19 Apr 2015 03:30:01 +0100 Subject: [PATCH 6/8] Correct an erroneous comment regarding removal of _ characters by PrettyTmptName --- src/clutils/Str.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clutils/Str.cc b/src/clutils/Str.cc index 12add4fac..5b2d232ff 100644 --- a/src/clutils/Str.cc +++ b/src/clutils/Str.cc @@ -266,7 +266,7 @@ std::string GetLiteralStr( istream & in, ErrorDescriptor * err ) { /**************************************************************//** ** \fn PrettyTmpName (char * oldname) ** \returns a new capitalized name in a static buffer - ** Capitalizes first char of word, rest is lowercase. Removes '_'. + ** Capitalizes first char of word, rest is lowercase. ** Status: OK 7-Oct-1992 kcm ******************************************************************/ const char * PrettyTmpName( const char * oldname ) { From 17aaffc8ebf2f7eb6c84d80c38a2a2edee7ce01a Mon Sep 17 00:00:00 2001 From: Peter Clifton Date: Sun, 19 Apr 2015 03:30:01 +0100 Subject: [PATCH 7/8] Fix offsetting of entity name references in multi-dimensional aggregates Multi-dimensional aggregates are not fully implemented in SCL, and instead are read as strings. (In SCLundefined classes). Augment the parsing code to pick out '#' characters indicating an entity reference, and special-case read these WITH the correct file-offset. Fixes reading entities with LIST of LIST of ENTITY type attributes at non-zero file-offset. In particular, fixes reading of B_SPLINE_SURFACE attribute "control_points_list". Fixes: https://github.com/stepcode/stepcode/issues/331 --- src/clstepcore/STEPaggrGeneric.cc | 153 ++++++++++++++++++++++++++++-- src/clstepcore/STEPaggrGeneric.h | 24 ++++- src/clstepcore/STEPattribute.h | 4 +- src/clstepcore/STEPundefined.cc | 33 +++++-- src/clstepcore/STEPundefined.h | 18 +++- src/clstepcore/read_func.cc | 19 +++- 6 files changed, 223 insertions(+), 28 deletions(-) diff --git a/src/clstepcore/STEPaggrGeneric.cc b/src/clstepcore/STEPaggrGeneric.cc index 899d6c656..9c6d7d0b3 100644 --- a/src/clstepcore/STEPaggrGeneric.cc +++ b/src/clstepcore/STEPaggrGeneric.cc @@ -1,4 +1,5 @@ #include "STEPaggrGeneric.h" +#include "typeDescriptor.h" #include /** \file STEPaggrGeneric.cc @@ -35,6 +36,134 @@ STEPaggregate & GenericAggregate::ShallowCopy( const STEPaggregate & a ) { } +/* XXX: GenericAggregate::ReadValue is almost exact copy of the STEPaggregate::ReadValue function. + * + * The only differences are: + * + * - STEPNode * item = 0; + * + GenericAggrNode * item = 0; + * + * if( exchangeFileFormat ) { + * - item->STEPread( in, &errdesc ); + * + item->STEPread( in, &errdesc, elem_type, insts, addFileId ); + * } else { + * - item->StrToVal( in, &errdesc ); + * + item->StrToVal( in, &errdesc, elem_type, insts, addFileId ); + * } + * + * Can we change the signature of STEPnode::STEPread and STEPnode::StrToVal + * to take an elem_type, insts and addFileId field instead of doing this? + */ + +/// if exchangeFileFormat == 1 then paren delims are required. + +Severity GenericAggregate::ReadValue( istream & in, ErrorDescriptor * err, + const TypeDescriptor * elem_type, InstMgrBase * insts, + int addFileId, int assignVal, int exchangeFileFormat, + const char * ) { + (void) insts; //not used in ReadValue() for this class + (void) addFileId; //not used in ReadValue() for this class + + ErrorDescriptor errdesc; + char errmsg[BUFSIZ]; + int value_cnt = 0; + std::string buf; + + if( assignVal ) { + Empty(); // read new values and discard existing ones + } + + char c; + + in >> ws; // skip white space + + c = in.peek(); // does not advance input + + if( in.eof() || c == '$' ) { + _null = 1; + err->GreaterSeverity( SEVERITY_INCOMPLETE ); + return SEVERITY_INCOMPLETE; + } + + if( c == '(' ) { + in.get( c ); + } else if( exchangeFileFormat ) { + // error did not find opening delim + // cannot recover so give up and let STEPattribute recover + err->GreaterSeverity( SEVERITY_INPUT_ERROR ); + return SEVERITY_INPUT_ERROR; + } else if( !in.good() ) { + // this should actually have been caught by skipping white space above + err->GreaterSeverity( SEVERITY_INCOMPLETE ); + return SEVERITY_INCOMPLETE; + } + + GenericAggrNode * item = 0; + + in >> ws; + // take a peek to see if there are any elements before committing to an + // element + c = in.peek(); // does not advance input + if( c == ')' ) { + in.get( c ); + } + // if not assigning values only need one node. So only one node is created. + // It is used to read the values + else if( !assignVal ) { + item = ( GenericAggrNode * )NewNode(); + } + + // ')' is the end of the aggregate + while( in.good() && ( c != ')' ) ) { + value_cnt++; + if( assignVal ) { // create a new node each time through the loop + item = ( GenericAggrNode * )NewNode(); + } + + errdesc.ClearErrorMsg(); + + if( exchangeFileFormat ) { + item->STEPread( in, &errdesc, elem_type, insts, addFileId ); + } else { + item->StrToVal( in, &errdesc, elem_type, insts, addFileId ); + } + + elem_type->AttrTypeName( buf ); + // read up to the next delimiter and set errors if garbage is + // found before specified delims (i.e. comma and quote) + CheckRemainingInput( in, &errdesc, buf, ",)" ); + + if( errdesc.severity() < SEVERITY_INCOMPLETE ) { + sprintf( errmsg, " index: %d\n", value_cnt ); + errdesc.PrependToDetailMsg( errmsg ); + err->AppendFromErrorArg( &errdesc ); + } + if( assignVal ) { // pass the node to STEPaggregate + AddNode( item ); + } + + in >> ws; // skip white space (although should already be skipped) + in.get( c ); // read delim + + // CheckRemainingInput should have left the input right at the delim + // so that it would be read in in.get() above. Since it did not find + // the delim this does not know how to find it either! + if( ( c != ',' ) && ( c != ')' ) ) { + // cannot recover so give up and let STEPattribute recover + err->GreaterSeverity( SEVERITY_INPUT_ERROR ); + return SEVERITY_INPUT_ERROR; + } + } + if( c == ')' ) { + _null = 0; + } else { // expectation for end paren delim has not been met + err->GreaterSeverity( SEVERITY_INPUT_ERROR ); + err->AppendToUserMsg( "Missing close paren for aggregate value" ); + return SEVERITY_INPUT_ERROR; + } + return err->severity(); +} + GenericAggrNode::GenericAggrNode( const char * str ) { value = str; } @@ -53,22 +182,30 @@ SingleLinkNode * GenericAggrNode::NewNode() { return new GenericAggrNode(); } -Severity GenericAggrNode::StrToVal( const char * s, ErrorDescriptor * err ) { - return value.STEPread( s, err ); +Severity GenericAggrNode::StrToVal( const char * s, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId ) { + return value.STEPread( s, err, elem_type, insts, addFileId ); } //TODO -Severity GenericAggrNode::StrToVal( istream & in, ErrorDescriptor * err ) { - return value.STEPread( in, err ); +Severity GenericAggrNode::StrToVal( istream & in, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId ) { + return value.STEPread( in, err, elem_type, insts, addFileId ); } -Severity GenericAggrNode::STEPread( const char * s, ErrorDescriptor * err ) { +Severity GenericAggrNode::STEPread( const char * s, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId ) { istringstream in( ( char * ) s ); - return value.STEPread( in, err ); + return value.STEPread( in, err, elem_type, insts, addFileId ); } -Severity GenericAggrNode::STEPread( istream & in, ErrorDescriptor * err ) { - return value.STEPread( in, err ); +Severity GenericAggrNode::STEPread( istream & in, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId ) { + return value.STEPread( in, err, elem_type, insts, addFileId ); } const char * GenericAggrNode::asStr( std::string & s ) { diff --git a/src/clstepcore/STEPaggrGeneric.h b/src/clstepcore/STEPaggrGeneric.h index 76190406e..4d37c8b6a 100644 --- a/src/clstepcore/STEPaggrGeneric.h +++ b/src/clstepcore/STEPaggrGeneric.h @@ -15,6 +15,14 @@ */ class SC_CORE_EXPORT GenericAggregate : public STEPaggregate { public: +#if 1 /* Could we avoid adding this by extending the STEPnode instead */ + virtual Severity ReadValue( istream & in, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId = 0, + int assignVal = 1, int ExchangeFileFormat = 1, + const char * currSch = 0 ); +#endif + virtual SingleLinkNode * NewNode(); virtual STEPaggregate & ShallowCopy( const STEPaggregate & ); @@ -33,11 +41,19 @@ class SC_CORE_EXPORT GenericAggrNode : public STEPnode { public: SCLundefined value; // INPUT - virtual Severity StrToVal( const char * s, ErrorDescriptor * err ); - virtual Severity StrToVal( istream & in, ErrorDescriptor * err ); + virtual Severity StrToVal( const char * s, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId = 0 ); + virtual Severity StrToVal( istream & in, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId = 0 ); - virtual Severity STEPread( const char * s, ErrorDescriptor * err ); - virtual Severity STEPread( istream & in, ErrorDescriptor * err ); + virtual Severity STEPread( const char * s, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId = 0 ); + virtual Severity STEPread( istream & in, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId = 0 ); // OUTPUT virtual const char * asStr( std::string & s ); diff --git a/src/clstepcore/STEPattribute.h b/src/clstepcore/STEPattribute.h index b352dbe94..0d4c22e2a 100644 --- a/src/clstepcore/STEPattribute.h +++ b/src/clstepcore/STEPattribute.h @@ -68,7 +68,9 @@ extern SC_CORE_EXPORT void AppendChar( char c, int & index, char *& s, int & sSi extern SC_CORE_EXPORT void PushPastString( istream & in, std::string & s, ErrorDescriptor * err ); -extern SC_CORE_EXPORT void PushPastImbedAggr( istream & in, std::string & s, ErrorDescriptor * err ); +extern SC_CORE_EXPORT void PushPastEntityRef( istream & in, std::string & s, ErrorDescriptor * err, InstMgrBase *instances, int addFileId ); + +extern SC_CORE_EXPORT void PushPastImbedAggr( istream & in, std::string & s, ErrorDescriptor * err, InstMgrBase *instances, int addFileId ); extern SC_CORE_EXPORT void PushPastAggr1Dim( istream & in, std::string & s, ErrorDescriptor * err ); diff --git a/src/clstepcore/STEPundefined.cc b/src/clstepcore/STEPundefined.cc index 6ca378099..4a19f0bab 100644 --- a/src/clstepcore/STEPundefined.cc +++ b/src/clstepcore/STEPundefined.cc @@ -19,22 +19,35 @@ ** helper functions for reading unknown types */ -Severity SCLundefined::StrToVal( const char * s, ErrorDescriptor * err ) { +Severity SCLundefined::StrToVal( const char * s, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId ) { (void) err; //unused + (void) elem_type; // unused + (void) insts; // unused + (void) addFileId; // unused val = s; return SEVERITY_NULL; +// XXX: SHOULD WE PUSH THE STRING INTO A STREAM AND FEED TO STEPread??? } -Severity SCLundefined::StrToVal( istream & in, ErrorDescriptor * err ) { - return STEPread( in, err ); +Severity SCLundefined::StrToVal( istream & in, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId ) { + return STEPread( in, err, elem_type, insts, addFileId ); } -Severity SCLundefined::STEPread( const char * s, ErrorDescriptor * err ) { +Severity SCLundefined::STEPread( const char * s, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId ) { istringstream in( ( char * ) s ); - return STEPread( in, err ); + return STEPread( in, err, elem_type, insts, addFileId ); } -Severity SCLundefined::STEPread( istream & in, ErrorDescriptor * err ) { +Severity SCLundefined::STEPread( istream & in, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId ) { + (void) elem_type; // unused char c = '\0'; ostringstream ss; std::string str; @@ -56,7 +69,7 @@ Severity SCLundefined::STEPread( istream & in, ErrorDescriptor * err ) { case '(': in.putback( c ); - PushPastImbedAggr( in, str, err ); + PushPastImbedAggr( in, str, err, insts, addFileId ); ss << str; break; @@ -83,6 +96,12 @@ Severity SCLundefined::STEPread( istream & in, ErrorDescriptor * err ) { terminal = 1; // found a valid delimiter break; + case '#': + in.putback( c ); + PushPastEntityRef( in, str, err, insts, addFileId ); + ss << str; + break; + default: ss.put( c ); break; diff --git a/src/clstepcore/STEPundefined.h b/src/clstepcore/STEPundefined.h index 88abe110f..b876619f5 100644 --- a/src/clstepcore/STEPundefined.h +++ b/src/clstepcore/STEPundefined.h @@ -23,11 +23,19 @@ class SC_CORE_EXPORT SCLundefined { public: // INPUT - virtual Severity StrToVal( const char * s, ErrorDescriptor * err ); - virtual Severity StrToVal( istream & in, ErrorDescriptor * err ); - - virtual Severity STEPread( const char * s, ErrorDescriptor * err ); - virtual Severity STEPread( istream & in, ErrorDescriptor * err ); + virtual Severity StrToVal( const char * s, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId ); + virtual Severity StrToVal( istream & in, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId ); + + virtual Severity STEPread( const char * s, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId ); + virtual Severity STEPread( istream & in, ErrorDescriptor * err, + const TypeDescriptor * elem_type, + InstMgrBase * insts, int addFileId ); // OUTPUT virtual const char * asStr( std::string & s ) const; diff --git a/src/clstepcore/read_func.cc b/src/clstepcore/read_func.cc index 395e52cfd..2a88f1950 100644 --- a/src/clstepcore/read_func.cc +++ b/src/clstepcore/read_func.cc @@ -462,11 +462,21 @@ void PushPastString( istream & in, std::string & s, ErrorDescriptor * err ) { s += GetLiteralStr( in, err ); } +// Kludge to adjust read in an entity reference whilst adjusting for file offset +void PushPastEntityRef( istream & in, std::string & s, ErrorDescriptor * err, InstMgrBase *insts, int addFileId ) { + SDAI_Application_instance *se = ReadEntityRef( in, err, ",)", insts, addFileId ); + + stringstream ss; + ss << "#" << se->StepFileId(); + + s += ss.str(); +} + /** * assign 's' so that it contains an exchange file format aggregate read from 'in'. * This is used to read aggregates that are part of multidimensional aggregates. */ -void PushPastImbedAggr( istream & in, std::string & s, ErrorDescriptor * err ) { +void PushPastImbedAggr( istream & in, std::string & s, ErrorDescriptor * err, InstMgrBase *instances, int addFileId ) { char messageBuf[BUFSIZ]; messageBuf[0] = '\0'; @@ -480,10 +490,13 @@ void PushPastImbedAggr( istream & in, std::string & s, ErrorDescriptor * err ) { while( in.good() && ( c != ')' ) ) { if( c == '(' ) { in.putback( c ); - PushPastImbedAggr( in, s, err ); + PushPastImbedAggr( in, s, err, instances, addFileId ); } else if( c == STRING_DELIM ) { in.putback( c ); PushPastString( in, s, err ); + } else if( c == '#' && instances != NULL) { /* XXX: Hack to skip whilst inside SkipSimpleRecord */ + in.putback( c ); + PushPastEntityRef( in, s, err, instances, addFileId ); } else { s += c; } @@ -631,7 +644,7 @@ const char * SkipSimpleRecord( istream & in, std::string & buf, ErrorDescriptor } else if( c == '(' ) { in.putback( c ); s.clear(); - PushPastImbedAggr( in, s, err ); + PushPastImbedAggr( in, s, err, NULL, 0 ); /* XXX: DUMMY BUFFER ASSUMED, SO addFileId UNIMPORTANT */ buf.append( s.c_str() ); } else { buf += c; From 50991f77759872aeb9eeddbb5c749fc3feb72aee Mon Sep 17 00:00:00 2001 From: Peter Clifton Date: Sun, 19 Apr 2015 03:30:02 +0100 Subject: [PATCH 8/8] Local changes, including fun test program --- example/ap203min/CMakeLists.txt | 25 +- example/ap203min/ap214peter.cpp | 1224 +++++++++++++++++++++++++++++++ 2 files changed, 1243 insertions(+), 6 deletions(-) create mode 100644 example/ap203min/ap214peter.cpp diff --git a/example/ap203min/CMakeLists.txt b/example/ap203min/CMakeLists.txt index 3765fa48a..35a12f051 100644 --- a/example/ap203min/CMakeLists.txt +++ b/example/ap203min/CMakeLists.txt @@ -31,13 +31,16 @@ set(SC_IS_SUBBUILD TRUE) if(NOT DEFINED CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug) endif(NOT DEFINED CMAKE_BUILD_TYPE) -set(SC_BUILD_TYPE ${CMAKE_BUILD_TYPE}) +#set(SC_BUILD_TYPE ${CMAKE_BUILD_TYPE}) +set(CMAKE_BUILD_TYPE Debug) +set(SC_BUILD_TYPE Debug) # Path to STEPcode set(STEPCODE_BUILD_DIR ${CMAKE_BINARY_DIR}/sc CACHE PATH "STEPcode build subdir") # STEP schema to build and link against. -set(SCHEMA ap203) +#set(SCHEMA ap203) +set(SCHEMA ap214e3) set(SC_BUILD_SCHEMAS ${SCHEMA} CACHE INTERNAL "Schema, internal, immutable" FORCE) # Parse out schema name and library. @@ -50,7 +53,8 @@ endif(NOT EXISTS ${SCHEMA_FILE}) get_filename_component(SCHEMA_SN ${SCHEMA_FILE} NAME) -string(REGEX REPLACE "\(.*\).[Ee][Xx][Pp]" "sdai_\\1" SCHEMA_LINK_NAME ${SCHEMA_SN}) +#string(REGEX REPLACE "\(.*\).[Ee][Xx][Pp]" "sdai_\\1" SCHEMA_LINK_NAME ${SCHEMA_SN}) +set(SCHEMA_LINK_NAME "sdai_ap214e3") set(STEPCODE_LIBRARIES base stepcore stepeditor stepdai steputils ${SCHEMA_LINK_NAME}) # Add STEPCode project to CMake build. @@ -77,14 +81,23 @@ include_directories( ${STEPCODE_INCLUDE_DIR} ) +## Application sources and headers +#set(SRCS ap203min.cpp) +# +#set(HDRS ) +# +#add_executable(${PROJECT_NAME} ${SRCS} ${HDRS}) +# +#target_link_libraries(${PROJECT_NAME} ${STEPCODE_LIBRARIES}) + # Application sources and headers -set(SRCS ap203min.cpp) +set(SRCS ap214peter.cpp) set(HDRS ) -add_executable(${PROJECT_NAME} ${SRCS} ${HDRS}) +add_executable("petertest" ${SRCS} ${HDRS}) -target_link_libraries(${PROJECT_NAME} ${STEPCODE_LIBRARIES}) +target_link_libraries("petertest" ${STEPCODE_LIBRARIES}) # Local Variables: # tab-width: 8 diff --git a/example/ap203min/ap214peter.cpp b/example/ap203min/ap214peter.cpp new file mode 100644 index 000000000..660db6713 --- /dev/null +++ b/example/ap203min/ap214peter.cpp @@ -0,0 +1,1224 @@ +//***************************************************************************** +// AP203 Minimum +// +// This program is intended to serve as a tutorial example for programmers +// interested in learning about ISO 10303 (STEP), the STEPcode project, and +// the AP203 portion of STEP. +// +// This program creates and connects the minimum set of entities required +// to form a valid AP203 STEP file. Inspiration for this program came from +// Appendix B of 'Recommended Practices for AP 203' released to the public +// domain in 1998 by PDES Inc. The recommended practices document is +// available online at: +// +// http://www.steptools.com/support/stdev_docs/express/ap203/recprac203v8.pdf +// +// The recommended practices document states: +// +// "This document has been developed by the PDES, Inc. Industry +// consortium to aid in accelerating the implementation of the +// STEP standard. It has not been copyrighted to allow for the +// free exchange of the information. PDES, Inc. Requests that +// anyone using this information provide acknowledgment that +// PDES, Inc. was the original author." +// +// In the same spirit, this program is released to the public domain. Any +// part of this program may be freely copied in part or in full for any +// purpose. No acknowledgment is required for the use of this code. +// +// This program was written by Rob McDonald in October 2013. Since that +// time, it has been maintained by the STEPcode project. +// +//****************************************************************************/ + + +// This program uses CMake to build Makefiles or other project files. It +// includes a CMakeLists.txt program that also builds STEPcode as a sub-build. +// To compile, you must tell CMake where your STEPcode source tree is located +// by setting STEPCODE_ROOT_DIR. To compile: +// +// $ pwd +// .../stepcode/example/ap203min +// $ mkdir build +// $ cd build +// $ cmake .. -DSTEPCODE_ROOT_DIR=../../.. +// $ make +// $ cd bin +// $ ls +// AP203Minimum +// $./AP203Minimum +// AP203Minimum outfile.step + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "schema.h" + +#include + +//#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#if 0 +# define DEBUG_PRODUCT_DEFINITION_SEARCH +# define DEBUG_CHILD_REMOVAL +# define DEBUG_PRODUCT_DEFINITION +#else +# undef DEBUG_PRODUCT_DEFINITION_SEARCH +# undef DEBUG_CHILD_REMOVAL +# undef DEBUG_PRODUCT_DEFINITION +#endif + +enum LenEnum { MM, CM, M, IN, FT, YD }; +enum AngEnum { RAD, DEG }; + +STEPcomplex * Geometric_Context( Registry * registry, InstMgr * instance_list, const LenEnum & len, const AngEnum & angle, const char * tolstr ) { + int instance_cnt = 0; + STEPattribute * attr; + STEPcomplex * stepcomplex; + + SdaiDimensional_exponents * dimensional_exp = new SdaiDimensional_exponents(); + dimensional_exp->length_exponent_( 0.0 ); + dimensional_exp->mass_exponent_( 0.0 ); + dimensional_exp->time_exponent_( 0.0 ); + dimensional_exp->electric_current_exponent_( 0.0 ); + dimensional_exp->thermodynamic_temperature_exponent_( 0.0 ); + dimensional_exp->amount_of_substance_exponent_( 0.0 ); + dimensional_exp->luminous_intensity_exponent_( 0.0 ); + instance_list->Append( ( SDAI_Application_instance * ) dimensional_exp, completeSE ); + instance_cnt++; + + STEPcomplex * ua_length; + // First set up metric units if appropriate. Default to mm. + // If imperial units, set up mm to be used as base to define imperial units. + Si_prefix pfx = Si_prefix__milli; + switch( len ) { + case CM: + pfx = Si_prefix__centi; + break; + case M: + pfx = Si_prefix_unset; + break; + } + + const char * ua_length_types[4] = { "length_unit", "named_unit", "si_unit", "*" }; + ua_length = new STEPcomplex( registry, ( const char ** ) ua_length_types, instance_cnt ); + stepcomplex = ua_length->head; + while( stepcomplex ) { + if (stepcomplex->EntityName() == NULL) + { + std::cout << "ERROR: Creating geometric context failed" << std::endl; + return NULL; + } + if( !strcmp( stepcomplex->EntityName(), "Si_Unit" ) ) { + stepcomplex->ResetAttributes(); + while( ( attr = stepcomplex->NextAttribute() ) != NULL ) { + if( !strcmp( attr->Name(), "prefix" ) ) { + attr->Enum( new SdaiSi_prefix_var( pfx ) ); + } + if( !strcmp( attr->Name(), "name" ) ) { + attr->Enum( new SdaiSi_unit_name_var( Si_unit_name__metre ) ); + } + } + } + stepcomplex = stepcomplex->sc; + } + instance_list->Append( ( SDAI_Application_instance * ) ua_length, completeSE ); + instance_cnt++; + + // If imperial, create conversion based unit. + if( len >= IN ) { + STEPcomplex * len_mm = ua_length; + + char lenname[10]; + double lenconv; + + switch( len ) { + case IN: + strcat( lenname, "'INCH'\0" ); + lenconv = 25.4; + break; + case FT: + strcat( lenname, "'FOOT'\0" ); + lenconv = 25.4 * 12.0; + break; + case YD: + strcat( lenname, "'YARD'\0" ); + lenconv = 25.4 * 36.0; + break; + } + + SdaiUnit * len_unit = new SdaiUnit( ( SdaiNamed_unit * ) len_mm ); + + SdaiMeasure_value * len_measure_value = new SdaiMeasure_value( lenconv, automotive_design::t_measure_value ); + len_measure_value->SetUnderlyingType( automotive_design::t_length_measure ); + + SdaiLength_measure_with_unit * len_measure_with_unit = new SdaiLength_measure_with_unit(); + len_measure_with_unit->value_component_( len_measure_value ); + len_measure_with_unit->unit_component_( len_unit ); + instance_list->Append( ( SDAI_Application_instance * ) len_measure_with_unit, completeSE ); + instance_cnt++; + + SdaiDimensional_exponents * dimensional_exp_len = new SdaiDimensional_exponents(); + dimensional_exp_len->length_exponent_( 1.0 ); + dimensional_exp_len->mass_exponent_( 0.0 ); + dimensional_exp_len->time_exponent_( 0.0 ); + dimensional_exp_len->electric_current_exponent_( 0.0 ); + dimensional_exp_len->thermodynamic_temperature_exponent_( 0.0 ); + dimensional_exp_len->amount_of_substance_exponent_( 0.0 ); + dimensional_exp_len->luminous_intensity_exponent_( 0.0 ); + instance_list->Append( ( SDAI_Application_instance * ) dimensional_exp_len, completeSE ); + instance_cnt++; + + const char * ua_conv_len_types[4] = { "conversion_based_unit", "named_unit", "length_unit", "*" }; + ua_length = new STEPcomplex( registry, ( const char ** ) ua_conv_len_types, instance_cnt ); + stepcomplex = ua_length->head; + while( stepcomplex ) { + if (stepcomplex->EntityName() == NULL) + { + std::cout << "ERROR: Creating geometric context failed" << std::endl; + return NULL; + } + if( !strcmp( stepcomplex->EntityName(), "Conversion_Based_Unit" ) ) { + stepcomplex->ResetAttributes(); + while( ( attr = stepcomplex->NextAttribute() ) != NULL ) { + if( !strcmp( attr->Name(), "name" ) ) { + attr->StrToVal( lenname ); + } + if( !strcmp( attr->Name(), "conversion_factor" ) ) { + attr->Entity( ( STEPentity * )( len_measure_with_unit ) ); + } + } + } + if( !strcmp( stepcomplex->EntityName(), "Named_Unit" ) ) { + stepcomplex->ResetAttributes(); + while( ( attr = stepcomplex->NextAttribute() ) != NULL ) { + if( !strcmp( attr->Name(), "dimensions" ) ) { + attr->Entity( ( STEPentity * )( dimensional_exp_len ) ); + } + } + } + stepcomplex = stepcomplex->sc; + } + + instance_list->Append( ( SDAI_Application_instance * ) ua_length, completeSE ); + instance_cnt++; + } + + SdaiUncertainty_measure_with_unit * uncertainty = ( SdaiUncertainty_measure_with_unit * )registry->ObjCreate( "UNCERTAINTY_MEASURE_WITH_UNIT" ); + uncertainty->name_( "'DISTANCE_ACCURACY_VALUE'" ); + uncertainty->description_( "'Threshold below which geometry imperfections (such as overlaps) are not considered errors.'" ); + SdaiUnit * tol_unit = new SdaiUnit( ( SdaiNamed_unit * ) ua_length ); + uncertainty->ResetAttributes(); + { + while( ( attr = uncertainty->NextAttribute() ) != NULL ) { + if( !strcmp( attr->Name(), "unit_component" ) ) { + attr->Select( tol_unit ); + } + if( !strcmp( attr->Name(), "value_component" ) ) { + attr->StrToVal( tolstr ); + } + } + } + instance_list->Append( ( SDAI_Application_instance * ) uncertainty, completeSE ); + instance_cnt++; + + // First set up radians as base angle unit. + const char * ua_plane_angle_types[4] = { "named_unit", "plane_angle_unit", "si_unit", "*" }; + STEPcomplex * ua_plane_angle = new STEPcomplex( registry, ( const char ** ) ua_plane_angle_types, instance_cnt ); + stepcomplex = ua_plane_angle->head; + while( stepcomplex ) { + if (stepcomplex->EntityName() == NULL) + { + std::cout << "ERROR: Creating geometric context failed" << std::endl; + return NULL; + } + if( !strcmp( stepcomplex->EntityName(), "Si_Unit" ) ) { + stepcomplex->ResetAttributes(); + while( ( attr = stepcomplex->NextAttribute() ) != NULL ) { + if( !strcmp( attr->Name(), "name" ) ) { + attr->Enum( new SdaiSi_unit_name_var( Si_unit_name__radian ) ); + } + } + } + stepcomplex = stepcomplex->sc; + } + instance_list->Append( ( SDAI_Application_instance * ) ua_plane_angle, completeSE ); + instance_cnt++; + +#if 0 + // If degrees, create conversion based unit. + if( angle == DEG ) { + STEPcomplex * ang_rad = ua_plane_angle; + + const double angconv = ( 3.14159265358979323846264338327950 / 180.0 ); + + SdaiUnit * p_ang_unit = new SdaiUnit( ( SdaiNamed_unit * ) ang_rad ); + + SdaiMeasure_value * p_ang_measure_value = new SdaiMeasure_value( angconv, automotive_design::t_measure_value ); + p_ang_measure_value->SetUnderlyingType( automotive_design::t_plane_angle_measure ); + + SdaiPlane_angle_measure_with_unit * p_ang_measure_with_unit = new SdaiPlane_angle_measure_with_unit(); + p_ang_measure_with_unit->value_component_( p_ang_measure_value ); + p_ang_measure_with_unit->unit_component_( p_ang_unit ); + instance_list->Append( ( SDAI_Application_instance * ) p_ang_measure_with_unit, completeSE ); + instance_cnt++; + + const char * ua_conv_angle_types[4] = { "conversion_based_unit", "named_unit", "plane_angle_unit", "*" }; + ua_plane_angle = new STEPcomplex( registry, ( const char ** ) ua_conv_angle_types, instance_cnt ); + stepcomplex = ua_plane_angle->head; + while( stepcomplex ) { + if( !strcmp( stepcomplex->EntityName(), "Conversion_Based_Unit" ) ) { + stepcomplex->ResetAttributes(); + while( ( attr = stepcomplex->NextAttribute() ) != NULL ) { + if( !strcmp( attr->Name(), "name" ) ) { + attr->StrToVal( "'DEGREES'" ); + } + if( !strcmp( attr->Name(), "conversion_factor" ) ) { + attr->Entity( ( STEPentity * )( p_ang_measure_with_unit ) ); + } + } + } + if( !strcmp( stepcomplex->EntityName(), "Named_Unit" ) ) { + stepcomplex->ResetAttributes(); + while( ( attr = stepcomplex->NextAttribute() ) != NULL ) { + if( !strcmp( attr->Name(), "dimensions" ) ) { + //attr->Entity( ( STEPentity * )( dimensional_exp ) ); + //attr->set_null(); + attr->Entity( dimensional_exp ); + } + } + } + stepcomplex = stepcomplex->sc; + } + instance_list->Append( ( SDAI_Application_instance * ) ua_plane_angle, completeSE ); + instance_cnt++; + } +#endif + + const char * ua_solid_angle_types[4] = { "named_unit", "si_unit", "solid_angle_unit", "*" }; + STEPcomplex * ua_solid_angle = new STEPcomplex( registry, ( const char ** ) ua_solid_angle_types, instance_cnt ); + stepcomplex = ua_solid_angle->head; + while( stepcomplex ) { + if (stepcomplex->EntityName() == NULL) + { + std::cout << "ERROR: Creating geometric context failed" << std::endl; + return NULL; + } + if( !strcmp( stepcomplex->EntityName(), "Si_Unit" ) ) { + stepcomplex->ResetAttributes(); + while( ( attr = stepcomplex->NextAttribute() ) != NULL ) { + if( !strcmp( attr->Name(), "name" ) ) { + attr->Enum( new SdaiSi_unit_name_var( Si_unit_name__steradian ) ); + } + } + } + stepcomplex = stepcomplex->sc; + } + instance_list->Append( ( SDAI_Application_instance * ) ua_solid_angle, completeSE ); + instance_cnt++; + + // All units set up, stored in: ua_length, ua_plane_angle, ua_solid_angle + const char * entNmArr[5] = { "geometric_representation_context", "global_uncertainty_assigned_context", "global_unit_assigned_context", "representation_context", "*" }; + STEPcomplex * complex_entity = new STEPcomplex( registry, ( const char ** ) entNmArr, instance_cnt ); + stepcomplex = complex_entity->head; + + while( stepcomplex ) { + if (stepcomplex->EntityName() == NULL) + { + std::cout << "ERROR: Creating geometric context failed" << std::endl; + return NULL; + } + + if( !strcmp( stepcomplex->EntityName(), "Geometric_Representation_Context" ) ) { + stepcomplex->ResetAttributes(); + while( ( attr = stepcomplex->NextAttribute() ) != NULL ) { + if( !strcmp( attr->Name(), "coordinate_space_dimension" ) ) { + attr->StrToVal( "3" ); + } + } + } + + if( !strcmp( stepcomplex->EntityName(), "Global_Uncertainty_Assigned_Context" ) ) { + stepcomplex->ResetAttributes(); + while( ( attr = stepcomplex->NextAttribute() ) != NULL ) { + if( !strcmp( attr->Name(), "uncertainty" ) ) { + EntityAggregate * unc_agg = new EntityAggregate(); + unc_agg->AddNode( new EntityNode( ( SDAI_Application_instance * ) uncertainty ) ); + attr->Aggregate( unc_agg ); + } + } + + } + + if( !strcmp( stepcomplex->EntityName(), "Global_Unit_Assigned_Context" ) ) { + stepcomplex->ResetAttributes(); + while( ( attr = stepcomplex->NextAttribute() ) != NULL ) { + std::string attrval; + if( !strcmp( attr->Name(), "units" ) ) { + EntityAggregate * unit_assigned_agg = new EntityAggregate(); + unit_assigned_agg->AddNode( new EntityNode( ( SDAI_Application_instance * ) ua_length ) ); + unit_assigned_agg->AddNode( new EntityNode( ( SDAI_Application_instance * ) ua_plane_angle ) ); + unit_assigned_agg->AddNode( new EntityNode( ( SDAI_Application_instance * ) ua_solid_angle ) ); + attr->Aggregate( unit_assigned_agg ); + } + } + } + + if( !strcmp( stepcomplex->EntityName(), "Representation_Context" ) ) { + stepcomplex->ResetAttributes(); + while( ( attr = stepcomplex->NextAttribute() ) != NULL ) { + if( !strcmp( attr->Name(), "context_identifier" ) ) { + attr->StrToVal( "'STANDARD'" ); + } + if( !strcmp( attr->Name(), "context_type" ) ) { + attr->StrToVal( "'3D'" ); + } + } + } + stepcomplex = stepcomplex->sc; + } + instance_list->Append( ( SDAI_Application_instance * ) complex_entity, completeSE ); + instance_cnt++; + + return complex_entity; +} + + +SdaiCartesian_point * +MakePoint (Registry *registry, InstMgr *instance_list, + const double &x, const double &y, const double &z) +{ + SdaiCartesian_point * pnt = (SdaiCartesian_point *) registry->ObjCreate ("CARTESIAN_POINT"); + pnt->name_ ("''"); + + RealAggregate * coords = pnt->coordinates_ (); + + RealNode * xnode = new RealNode (); + xnode->value = x; + coords->AddNode (xnode); + + RealNode * ynode = new RealNode (); + ynode->value = y; + coords->AddNode (ynode); + + RealNode * znode = new RealNode (); + znode->value = z; + coords->AddNode (znode); + + instance_list->Append ((SDAI_Application_instance *)pnt, completeSE); + + return pnt; +} + + +SdaiDirection * +MakeDirection (Registry *registry, InstMgr *instance_list, + const double &x, const double &y, const double &z) +{ + SdaiDirection * dir = (SdaiDirection *) registry->ObjCreate ("DIRECTION"); + dir->name_ ("''"); + + RealAggregate * components = dir->direction_ratios_ (); + + RealNode * xnode = new RealNode (); + xnode->value = x; + components->AddNode (xnode); + + RealNode * ynode = new RealNode (); + ynode->value = y; + components->AddNode (ynode); + + RealNode * znode = new RealNode (); + znode->value = z; + components->AddNode (znode); + + instance_list->Append ((SDAI_Application_instance *) dir, completeSE); + + return dir; +} + + +SdaiAxis2_placement_3d * +MakeAxis (Registry *registry, InstMgr *instance_list, + const double &px, const double &py, const double & pz, + const double &ax, const double &ay, const double & az, + const double &rx, const double &ry, const double & rz) +{ + SdaiCartesian_point * pnt = MakePoint (registry, instance_list, px, py, pz); + SdaiDirection * axis = MakeDirection (registry, instance_list, ax, ay, az); + SdaiDirection * refd = MakeDirection (registry, instance_list, rx, ry, rz); + + SdaiAxis2_placement_3d * placement = (SdaiAxis2_placement_3d *) registry->ObjCreate ("AXIS2_PLACEMENT_3D"); + placement->name_ ("''"); + placement->location_ (pnt); + placement->axis_ (axis); + placement->ref_direction_ (refd); + + instance_list->Append ((SDAI_Application_instance *) placement, completeSE); + + return placement; +} + + +SdaiAxis2_placement_3d * +DefaultAxis (Registry *registry, InstMgr *instance_list) +{ + return MakeAxis (registry, instance_list, 0.0, 0.0, 0.0, + 0.0, 0.0, 1.0, + 1.0, 0.0, 0.0); +} + + +typedef std::list pd_list; + + +void +find_all_pd_with_sdr (InstMgr *instance_list, pd_list *pd_list) +{ + int search_index = 0; + + // Loop over the instances of SHAPE_DEFITION_REPRESENTATION in the file + SdaiShape_definition_representation *sdr; + while (ENTITY_NULL != (sdr = (SdaiShape_definition_representation *) + instance_list->GetApplication_instance ("Shape_definition_representation", search_index))) + { + STEPentity *sdr_used_representation = sdr->used_representation_ (); + SdaiRepresented_definition *sdr_definition = sdr->definition_ (); + SdaiProduct_definition_shape *pds = (SdaiProduct_definition_shape *)(SdaiProperty_definition_ptr)(*sdr_definition); + SdaiProduct_definition *pd = *(SdaiCharacterized_product_definition_ptr)(*pds->definition_ ()); + SdaiProduct_definition_formation *pdf = pd->formation_ (); + SdaiProduct *p = pdf->of_product_ (); + + pd_list->push_back (pd); + +#ifdef DEBUG_PRODUCT_DEFINITION_SEARCH + std::cout << "Got a SDR, #" << sdr->StepFileId (); + std::cout << " used_representation (sr or descendant) = #" << sdr_used_representation->StepFileId (); + std::cout << " definition (pds) = #" << pds->StepFileId (); + std::cout << " pds->definition (pd) = #" << pd->StepFileId (); + std::cout << " pd->formation (pdf) = #" << pdf->StepFileId (); + std::cout << " pdf->product (p) = #" << p->StepFileId (); + std::cout << std::endl; + std::cout << "Product id = " << p->id_ ().c_str () << " name = " << p->name_ ().c_str (); + std::cout << std::endl; +#endif + + SdaiShape_representation *sr = (SdaiShape_representation *)sdr_used_representation; + +#ifdef DEBUG_PRODUCT_DEFINITION_SEARCH + std::cout << "SR is actually of type " << ((STEPentity *)sr)->EntityName () << std::endl; + std::cout << std::endl; +#endif + + int id = sdr->StepFileId (); + MgrNode * mnode = instance_list->FindFileId (id); + search_index = instance_list->GetIndex (mnode) + 1; + } +} + +/* entityName should be the name of entity Assembly_component_usage or one of its subtypes + * typically this will be "Assembly_component_usage" or "Next_assembly_usage_occurance" + */ +void +find_and_remove_child_pd (InstMgr *instance_list, pd_list *pd_list, const char *entityName) +{ + int search_index = 0; + + SdaiAssembly_component_usage *acu; + while (ENTITY_NULL != (acu = (SdaiAssembly_component_usage *) + instance_list->GetApplication_instance (entityName, search_index))) + { + SdaiProduct_definition *relating_pd = acu->relating_product_definition_ (); + SdaiProduct_definition *related_pd = acu->related_product_definition_ (); + +#ifdef DEBUG_CHILD_REMOVAL + std::cout << "Product " << related_pd->formation_ ()->of_product_ ()->id_ ().c_str (); + std::cout << " is a child of " << relating_pd->formation_ ()->of_product_ ()->id_ ().c_str (); + std::cout << ".. removing it from list of possible root products"; + std::cout << std::endl; +#endif + + /* Remove related_pd from the list of viable product definitions */ + pd_list->remove (related_pd); + + int id = acu->StepFileId (); + MgrNode * mnode = instance_list->FindFileId (id); + search_index = instance_list->GetIndex (mnode) + 1; + } +#ifdef DEBUG_CHILD_REMOVAL + std::cout << std::endl; +#endif +} + + +SdaiShape_definition_representation * +find_sdr_for_pd (InstMgr *instance_list, SdaiProduct_definition *target_pd) +{ + int search_index = 0; + + // Loop over the instances of SHAPE_DEFITION_REPRESENTATION in the file + SdaiShape_definition_representation *sdr; + while (ENTITY_NULL != (sdr = (SdaiShape_definition_representation *) + instance_list->GetApplication_instance ("Shape_definition_representation", search_index))) + { + SdaiProduct_definition_shape *pds = (SdaiProduct_definition_shape *)(SdaiProperty_definition_ptr)(*sdr->definition_ ()); + SdaiProduct_definition *pd = *(SdaiCharacterized_product_definition_ptr)(*pds->definition_ ()); + + /* Return the SHAPE_REPRESETATION (or subclass) associated with the first SHAPE_DEFINITION_REPRESENTATION for the required PRODUCT_DEFINITION */ + if (pd == target_pd) + return sdr; +// return (SdaiShape_representation *)sdr->used_representation_ (); + + int id = sdr->StepFileId (); + MgrNode * mnode = instance_list->FindFileId (id); + search_index = instance_list->GetIndex (mnode) + 1; + } + + return NULL; +} + + +SdaiShape_representation * +find_sr_for_pd (InstMgr *instance_list, SdaiProduct_definition *target_pd) +{ + SdaiShape_definition_representation *sdr = find_sdr_for_pd (instance_list, target_pd); + return (SdaiShape_representation *)sdr->used_representation_ (); +} + + +SdaiAxis2_placement_3d * +find_axis2_placement_3d_in_sr (SdaiShape_representation *sr) +{ + SingleLinkNode *iter = sr->items_ ()->GetHead (); + + while (iter != NULL) + { + SDAI_Application_instance *node = ((EntityNode *)iter)->node; + + if (strcmp (node->EntityName (), "Axis2_Placement_3d") == 0) + return (SdaiAxis2_placement_3d *)node; + + iter = iter->NextNode (); + } + + return NULL; +} + + +void +write_ap214 (Registry *registry, InstMgr *instance_list, const char *filename) +{ + // STEPfile takes care of reading and writing Part 21 files + STEPfile sfile (*registry, *instance_list, "", false ); + + // Build file header + InstMgr *header_instances = sfile.HeaderInstances (); + + int filename_length = strlen (filename); + char *step_fn = new char[filename_length + 3]; + step_fn[0] = '\''; + strncpy (step_fn + 1, filename, filename_length); + step_fn[filename_length + 1] = '\''; + step_fn[filename_length + 2] = '\0'; + + SdaiFile_name *fn = (SdaiFile_name *)sfile.HeaderDefaultFileName (); + header_instances->Append ((SDAI_Application_instance *) fn, completeSE); + fn->name_ (step_fn); + fn->time_stamp_ ("''"); + fn->author_ ()->AddNode (new StringNode( "''" )); + fn->organization_ ()->AddNode (new StringNode( "''" )); + fn->preprocessor_version_ ("''"); + fn->originating_system_ ("''"); + fn->authorization_ ("''"); + + SdaiFile_description *fd = (SdaiFile_description *)sfile.HeaderDefaultFileDescription (); + header_instances->Append ((SDAI_Application_instance *)fd, completeSE); + fd->description_()->AddNode (new StringNode ("''")); + fd->implementation_level_ ("'1'"); + + SdaiFile_schema *fs = (SdaiFile_schema *) sfile.HeaderDefaultFileSchema (); + header_instances->Append ((SDAI_Application_instance *)fs, completeSE); + fs->schema_identifiers_ ()->AddNode (new StringNode("'AUTOMOTIVE_DESIGN { 1 0 10303 214 3 1 1 }'")); /* XXX: NOT SURE IF THIS IS CORRECT! */ + + //sfile.WriteExchangeFile (filename); + sfile.WriteExchangeFile (filename, false); /* Turn off validation to try and force a save for bad data */ + if (sfile.Error ().severity () < SEVERITY_USERMSG) + { + sfile.Error ().PrintContents (std::cout); + } + + delete [] step_fn; +} + + +STEPcomplex * +MakeRrwtSrr (Registry *registry, + InstMgr *inst_mgr, + const char *description, + const char *name, + SdaiRepresentation_item *rep_1, + SdaiRepresentation_item *rep_2, + SdaiTransformation *transformation_operator) +{ + STEPattribute *attr; + const char * rrwt_srr_types[4] = { "representation_relationship", + "representation_relationship_with_transformation", + "shape_representation_relationship", + "*" }; + + STEPcomplex *rrwt_srr = new STEPcomplex (registry, (const char **) rrwt_srr_types, 0 /* XXX: FileID ??? */); + + STEPcomplex *stepcomplex = rrwt_srr->head; + while (stepcomplex) + { + if (!strcmp( stepcomplex->EntityName (), "Representation_Relationship")) + { + stepcomplex->ResetAttributes(); + while ((attr = stepcomplex->NextAttribute ()) != NULL) + { + if (!strcmp( attr->Name(), "description")) + attr->String (new SDAI_String (description)); + else if( !strcmp( attr->Name(), "name" ) ) + attr->String (new SDAI_String (name)); + else if( !strcmp( attr->Name(), "rep_1" ) ) + attr->Entity (rep_1); + else if( !strcmp( attr->Name(), "rep_2" ) ) + attr->Entity (rep_2); + } + } + else if (!strcmp( stepcomplex->EntityName (), "Representation_Relationship_With_Transformation")) + { + stepcomplex->ResetAttributes(); + while ((attr = stepcomplex->NextAttribute ()) != NULL) + { + if (!strcmp( attr->Name(), "transformation_operator")) + attr->Select (transformation_operator); + } + } + stepcomplex = stepcomplex->sc; + } + + return rrwt_srr; +} + + +SdaiProduct_definition * +create_parent_assembly (Registry *registry, + InstMgr *instance_list) +{ + // Build file data. The entities have been created and added in order such that no entity + // references a later entity. This is not required, but has been done to give a logical + // flow to the source and the resulting STEP file. + + // Global units and tolerance. + STEPcomplex * context = Geometric_Context( registry, instance_list, MM, DEG, "LENGTH_MEASURE(0.0001)" ); + + if (context == NULL) + { + std::cout << "ERROR: Problem creating parent assembly" << std::endl; + return NULL; + } + + // Primary coordinate system. + SdaiAxis2_placement_3d * orig_transform = DefaultAxis( registry, instance_list ); + + // Basic context through product and shape representation + SdaiApplication_context * app_context = ( SdaiApplication_context * ) registry->ObjCreate( "APPLICATION_CONTEXT" ); + instance_list->Append( ( SDAI_Application_instance * ) app_context, completeSE ); + app_context->application_( "'core data for automotive mechanical design processes'" ); + + SdaiProduct_context * prod_context = ( SdaiProduct_context * ) registry->ObjCreate( "PRODUCT_CONTEXT" ); + instance_list->Append( ( SDAI_Application_instance * ) prod_context, completeSE ); + prod_context->name_( "''" ); + prod_context->discipline_type_( "'mechanical'" ); + prod_context->frame_of_reference_( app_context ); + + SdaiApplication_protocol_definition * app_protocol = ( SdaiApplication_protocol_definition * ) registry->ObjCreate( "APPLICATION_PROTOCOL_DEFINITION" ); + instance_list->Append( ( SDAI_Application_instance * ) app_protocol, completeSE ); + app_protocol->status_( "'international standard'" ); + app_protocol->application_protocol_year_( 2010 ); /* XXX: NOT SURE IF THIS IS CORRECT! */ + app_protocol->application_interpreted_model_schema_name_( "'automotive_design'" ); + app_protocol->application_( app_context ); + + SdaiProduct * prod = ( SdaiProduct * ) registry->ObjCreate( "PRODUCT" ); + instance_list->Append( ( SDAI_Application_instance * ) prod, completeSE ); + prod->id_( "''" ); + prod->name_( "'prodname'" ); + prod->description_( "''" ); + prod->frame_of_reference_()->AddNode( new EntityNode( ( SDAI_Application_instance * ) prod_context ) ); + + SdaiProduct_related_product_category * prodcat = ( SdaiProduct_related_product_category * ) registry->ObjCreate( "PRODUCT_RELATED_PRODUCT_CATEGORY" ); + instance_list->Append( ( SDAI_Application_instance * ) prodcat, completeSE ); + prodcat->name_( "'assembly'" ); + prodcat->description_( "''" ); + prodcat->products_()->AddNode( new EntityNode( ( SDAI_Application_instance * ) prod ) ); + + SdaiProduct_definition_formation_with_specified_source * prod_def_form = ( SdaiProduct_definition_formation_with_specified_source * ) registry->ObjCreate( "PRODUCT_DEFINITION_FORMATION_WITH_SPECIFIED_SOURCE" ); + instance_list->Append( ( SDAI_Application_instance * ) prod_def_form, completeSE ); + prod_def_form->id_( "''" ); + prod_def_form->description_( "''" ); + prod_def_form->of_product_( prod ); + prod_def_form->make_or_buy_( Source__made ); + + SdaiProduct_definition_context * prod_def_context = ( SdaiProduct_definition_context * ) registry->ObjCreate( "PRODUCT_DEFINITION_CONTEXT" ); + instance_list->Append( ( SDAI_Application_instance * ) prod_def_context, completeSE ); + prod_def_context->name_( "''" ); + prod_def_context->life_cycle_stage_( "'design'" ); + prod_def_context->frame_of_reference_( app_context ); + + SdaiProduct_definition * prod_def = ( SdaiProduct_definition * ) registry->ObjCreate( "PRODUCT_DEFINITION" ); + instance_list->Append( ( SDAI_Application_instance * ) prod_def, completeSE ); + prod_def->id_( "''" ); + prod_def->description_( "''" ); + prod_def->frame_of_reference_( prod_def_context ); + prod_def->formation_( prod_def_form ); + + SdaiProduct_definition_shape * pshape = ( SdaiProduct_definition_shape * ) registry->ObjCreate( "PRODUCT_DEFINITION_SHAPE" ); + instance_list->Append( ( SDAI_Application_instance * ) pshape, completeSE ); + pshape->name_( "''" ); + pshape->description_( "'ProductShapeDescription'" ); + pshape->definition_( new SdaiCharacterized_definition( new SdaiCharacterized_product_definition( prod_def ) ) ); + + SdaiShape_representation * shape_rep = ( SdaiShape_representation * ) registry->ObjCreate( "SHAPE_REPRESENTATION" ); + instance_list->Append( ( SDAI_Application_instance * ) shape_rep, completeSE ); + shape_rep->name_( "''" ); // Document? + shape_rep->items_()->AddNode( new EntityNode( ( SDAI_Application_instance * ) orig_transform ) ); + shape_rep->context_of_items_( ( SdaiRepresentation_context * ) context ); + + SdaiShape_definition_representation * shape_def_rep = ( SdaiShape_definition_representation * ) registry->ObjCreate( "SHAPE_DEFINITION_REPRESENTATION" ); + instance_list->Append( ( SDAI_Application_instance * ) shape_def_rep, completeSE ); + shape_def_rep->definition_( new SdaiRepresented_definition ( pshape ) ); + shape_def_rep->used_representation_( shape_rep ); + + return prod_def; +} + + +typedef std::list ai_list; + + +static void +find_all_typename_entity_with_id_from (InstMgr *instance_list, ai_list *ai_list, const char *typename_, int from_id) +{ + int search_index = 0; + + // Loop over the instances of SHAPE_DEFITION_REPRESENTATION in the file + SDAI_Application_instance *ai; + while (ENTITY_NULL != (ai = (SDAI_Application_instance *) + instance_list->GetApplication_instance (typename_, search_index))) + { + int id = ai->StepFileId (); + + if (id >= from_id) + { + ai_list->push_back (ai); + + std::cout << "Found a " << typename_ << " instance (#" << id << ") to fixup" << std::endl; + } + + MgrNode * mnode = instance_list->FindFileId (id); + search_index = instance_list->GetIndex (mnode) + 1; + } +} + +static void +find_all_complex_with_member_and_id_from (InstMgr *instance_list, ai_list *ai_list, const char *typename_, int from_id) +{ + MgrNode * node; + SDAI_Application_instance * se; + + int count = instance_list->InstanceCount (); + for (int j = 0; j < count; ++j) + { + node = instance_list->GetMgrNode (j); + se = node->GetApplication_instance (); + if (!se->IsComplex ()) + continue; + + int id = se->StepFileId (); + if (id < from_id) + continue; + + STEPcomplex *stepcomplex = ((STEPcomplex *)se)->head; + while (stepcomplex) + { + if (!StrCmpIns (stepcomplex->EntityName (), typename_)) + { + ai_list->push_back (stepcomplex); + + std::cout << "Found a complex instance (#" << stepcomplex->StepFileId () << ") with " << typename_ << " to fixup" << std::endl; + } + + stepcomplex = stepcomplex->sc; + } + } +} + + +static void +fixup_2d_aggregate_in_b_spline_surface (Registry *registry, InstMgr *instance_list, int file_increment) +{ + const char *entityname = "b_spline_surface"; + ai_list to_fixup; + + find_all_typename_entity_with_id_from (instance_list, &to_fixup, entityname, file_increment); + find_all_complex_with_member_and_id_from (instance_list, &to_fixup, entityname, file_increment); + + /* NB: We need to use late binding APIs to manipulate attributes, as we may be dealing with complex entities */ + /* XXX: TODO: FIXUP THESE ENTITIES */ +} + + +static void +fixup_2d_aggregate_in_rectangular_composite_surface (Registry *registry, InstMgr *instance_list, int file_increment) +{ + const char *entityname = "rectangular_composite_surface"; + ai_list to_fixup; + + find_all_typename_entity_with_id_from (instance_list, &to_fixup, entityname, file_increment); + find_all_complex_with_member_and_id_from (instance_list, &to_fixup, entityname, file_increment); + + /* XXX: TODO: FIXUP THESE ENTITIES */ +} + + +static void +fixup_2d_aggregates (Registry *registry, InstMgr *instance_list, int file_increment) +{ + std::cout << "Checking and fixing up 2D aggregates (not fully implemented in SCL)" << std::endl; + fixup_2d_aggregate_in_b_spline_surface (registry, instance_list, file_increment); + fixup_2d_aggregate_in_rectangular_composite_surface (registry, instance_list, file_increment); + /* NB: THE 2D AGGREGATE in the rational_b_spline_surface ENTITY IS OF REAL TYPE, SO DOESN'T NEED REPAIR */ +} + +SdaiProduct_definition * +append_model_from_file (Registry *registry, + InstMgr *instance_list, + const char *filename) +{ + int max_existing_file_id = instance_list->MaxFileId (); + + /* XXX: The following line is coppied from STEPfile.inline.cc, and we rely on it matching the algorithm there! */ +// int file_increment = ( int )( ( ceil( ( max_existing_file_id + 99.0 ) / 1000.0 ) + 1.0 ) * 1000.0 ); /* XXX: RELYING ON SCL NOT CHANGING */ +// std::cout << "INFO: Expecting a to add " << file_increment << " to entity names" << std::endl; + + STEPfile sfile = STEPfile (*registry, *instance_list, "", false); + + sfile.AppendExchangeFile (filename); + + Severity severity = sfile.Error().severity(); + if (severity != SEVERITY_NULL) + { + sfile.Error().PrintContents (std::cout); + std::cout << "WARNING: Error reading from file '" << filename << "'" << std::endl; +// return NULL; +#warning HANDLE OTHER ERRORS BETTER? + } + + //fixup_2d_aggregates (registry, instance_list, file_increment); + + pd_list all_pd_list; + pd_list pd_list; + + // Find all PRODUCT_DEFINITION entities with a SHAPE_DEFINITION_REPRESETNATION + find_all_pd_with_sdr (instance_list, &all_pd_list); + + // Find and copy over any PRODUCT_DEFINITION in our list which have entity numbers from the append + for (pd_list::iterator iter = all_pd_list.begin(); iter != all_pd_list.end(); iter++) + if ((*iter)->StepFileId () > max_existing_file_id) + pd_list.push_back (*iter); + + /* Try to determine the root product */ + find_and_remove_child_pd (instance_list, &pd_list, "Next_assembly_usage_occurrence"); // Remove any PD which are children of another via NAUO + find_and_remove_child_pd (instance_list, &pd_list, "Assembly_component_usage"); // Remove any PD which are children of another via ACU + +#ifdef DEBUG_PRODUCT_DEFINITION_SEARCH + std::cout << "Hopefully left with the root product definition" << std::endl; + for (pd_list::iterator iter = pd_list.begin(); iter != pd_list.end(); iter++) + std::cout << "Product definition list item #" << (*iter)->StepFileId () << std::endl; + std::cout << std::endl; +#endif + + // If we didn't find a suitable PD, give up now + if (pd_list.size() == 0) + { + std::cout << "ERROR: Did not find a PRODUCT_DEFINITION (with associated SHAPE_DEFINITION_REPRESENTATION)" << std::endl; + return NULL; + } + + if (pd_list.size() > 1) + std::cout << "WARNING: Found more than one PRODUCT_DEFINITION that might be the root" << std::endl; + + // Use the first PD meeting the criterion. Hopefully there should just be one, but if not, we pick the first. + return *pd_list.begin(); +} + + +void +convert_model_to_assy_capable (Registry *registry, + InstMgr *instance_list, + SdaiProduct_definition *pd) +{ + SdaiShape_definition_representation *sdr = find_sdr_for_pd (instance_list, pd); + SdaiShape_representation *sr = (SdaiShape_representation *)sdr->used_representation_ (); + + // If sr is an exact match for the step entity SHAPE_REPRESENTATION (not a subclass), return - we are already in the correct form + if (strcmp (sr->EntityName (), "Shape_Representation") == 0) + return; + + // sr must be a subclass of Shape Representation, not an exact match for "Shape_Representation + // we need to adjust the shape representation structure to insert a SHAPE_REPRESENTATION, then + // relate this to the original shape representation. + +#ifdef DEBUG_PRODUCT_DEFINITION + std::cout << "Going to shoe-horn this into an assembly compatible structure" << std::endl; +#endif + + SdaiAxis2_placement_3d *child_origin = find_axis2_placement_3d_in_sr (sr); + if (child_origin == NULL) + { + std::cout << "WARNING: Could not find AXIS2_PLACEMENT_3D entity in SHAPE_REPRESENTATION - ABORTING CONVERSION TO ASSEMBLY CAPABLE" << std::endl; + return; + } + + SdaiShape_representation *new_sr = (SdaiShape_representation *) registry->ObjCreate ("SHAPE_REPRESENTATION"); + instance_list->Append ((SDAI_Application_instance * ) new_sr, completeSE); + new_sr->name_ ( "''" ); // Document? + new_sr->items_ ()->AddNode (new EntityNode ((SDAI_Application_instance *) child_origin)); + new_sr->context_of_items_ ((SdaiRepresentation_context *) sr->context_of_items_()); + + // Replace the shape representation from the model by our new entity + sdr->used_representation_ (new_sr); + + // NEED SHAPE_REPRESENTATION_RELATIONSHIP linking new_sr and sr + SdaiShape_representation_relationship *new_srr = (SdaiShape_representation_relationship *) registry->ObjCreate ("SHAPE_REPRESENTATION_RELATIONSHIP"); + instance_list->Append ((SDAI_Application_instance * ) new_srr, completeSE); + new_srr->name_ ( "'NONE'" ); + new_srr->description_ ( "'NONE'" ); + new_srr->rep_1_ (new_sr); + new_srr->rep_2_ (sr); +} + + +void +assemble_instance_of_model (Registry *registry, + InstMgr *instance_list, + SdaiProduct_definition *parent_pd, + SdaiProduct_definition *child_pd, + SdaiAxis2_placement_3d *location_in_parent) +{ + SdaiShape_representation *parent_sr = find_sr_for_pd (instance_list, parent_pd); + SdaiShape_representation *child_sr = find_sr_for_pd (instance_list, child_pd); + SdaiAxis2_placement_3d *child_origin = find_axis2_placement_3d_in_sr (child_sr); + + parent_sr->items_ ()->AddNode (new EntityNode (location_in_parent)); + + // NAUO + char *nauo_id = strdup ("'NAUO1'"); // XXX: SHOULD BE UNIQUE! + + SdaiNext_assembly_usage_occurrence *nauo = (SdaiNext_assembly_usage_occurrence *) registry->ObjCreate ("NEXT_ASSEMBLY_USAGE_OCCURRENCE"); + instance_list->Append ((SDAI_Application_instance *)nauo, completeSE); + nauo->description_ ("''"); + nauo->id_ (nauo_id); + nauo->name_ ("''"); + nauo->relating_product_definition_ (parent_pd); + nauo->related_product_definition_ (child_pd); + free (nauo_id); + + // PDS + SdaiProduct_definition_shape *pds = (SdaiProduct_definition_shape *) registry->ObjCreate ("PRODUCT_DEFINITION_SHAPE"); + instance_list->Append ((SDAI_Application_instance *) pds, completeSE); + pds->name_ ("''"); + pds->description_ ("'ProductShapeDescription'"); + pds->definition_ (new SdaiCharacterized_definition (new SdaiCharacterized_product_definition (nauo))); + + // IDT + SdaiItem_defined_transformation *idt = (SdaiItem_defined_transformation *) registry->ObjCreate ("ITEM_DEFINED_TRANSFORMATION"); + instance_list->Append ((SDAI_Application_instance *) idt, completeSE); + idt->description_ ("''"); + idt->name_ ("''"); + idt->transform_item_1_ (location_in_parent); // Axis in the parent shape where the child origin should place + idt->transform_item_2_ (child_origin); // Child origin in the child shape + + // RRWT_SRR COMPLEX + STEPcomplex *rrwt_srr = MakeRrwtSrr (registry, instance_list, + "'NONE'", // RR description + "'NONE'", // RR name + (SdaiRepresentation_item *)parent_sr, // RR rep_1, + (SdaiRepresentation_item *)child_sr, // RR rep_2, + new SdaiTransformation (idt)); // RRWT transformation_operator + instance_list->Append ((SDAI_Application_instance *) rrwt_srr, completeSE); + + // CDSR + SdaiContext_dependent_shape_representation *cdsr = (SdaiContext_dependent_shape_representation *) registry->ObjCreate ("CONTEXT_DEPENDENT_SHAPE_REPRESENTATION"); + instance_list->Append ((SDAI_Application_instance *) cdsr, completeSE); + cdsr->representation_relation_ ((SdaiShape_representation_relationship *)rrwt_srr); + cdsr->represented_product_relation_ (pds); +} + + +void +print_pd_debug (InstMgr *instance_list, SdaiProduct_definition *pd) +{ +#ifdef DEBUG_PRODUCT_DEFINITION + std::cout << "The product we are going to embed is called " << pd->formation_ ()->of_product_ ()->id_ ().c_str () << std::endl; + + SdaiShape_definition_representation *sdr = find_sdr_for_pd (instance_list, pd); + + SdaiShape_representation *sr = find_sr_for_pd (instance_list, pd); + if (sr == NULL) + { + std::cout << "Could not find shape representation for the part!" << std::endl; + return; + } + std::cout << "The shape representation (#" << sr->StepFileId () << ") for the product has type " << sr->EntityName (); + std::cout << std::endl; +#endif +} + + +void +lazy_assemble (Registry *registry, + InstMgr *instance_list, + SdaiProduct_definition *parent_pd, + const char *filename, + const double &px, const double &py, const double & pz, + const double &ax, const double &ay, const double & az, + const double &rx, const double &ry, const double & rz) +{ + SdaiProduct_definition *model_pd = append_model_from_file (registry, instance_list, filename); + if (model_pd == NULL) + return; + SdaiAxis2_placement_3d *child_location = MakeAxis (registry, instance_list, px, py, pz, ax, ay, az, rx, ry, rz); + assemble_instance_of_model (registry, instance_list, parent_pd, model_pd, child_location); +} + + +int +main (void) +{ + // The registry contains information about types present in the current schema; SchemaInit is a function in the schema-specific SDAI library + Registry * registry = new Registry( SchemaInit ); + + // The InstMgr holds instances that have been created or that have been loaded from a file + InstMgr * instance_list = new InstMgr(); + + // Increment FileId so entities start at #1 instead of #0. + instance_list->NextFileId(); + +#if 1 + SdaiProduct_definition *assembly_pd = create_parent_assembly (registry, instance_list); +#endif + SdaiProduct_definition *model_pd; + SdaiAxis2_placement_3d *child_location; + +#if 0 + SdaiProduct_definition *assembly_pd; + model_pd = append_model_from_file (registry, instance_list, "buggy.step"); + assembly_pd = create_parent_assembly (registry, instance_list); + if (assembly_pd == NULL) + { + return -1; + } + if (model_pd != NULL) + { + child_location = MakeAxis (registry, instance_list, 0.0, 0.0, 0.0, // POINT + 0.0, 0.0, 1.0, // AXIS + 1.0, 0.0, 0.0); // REF DIRECTION + assemble_instance_of_model (registry, instance_list, assembly_pd, model_pd, child_location); + } +#endif + +#if 0 + model_pd = append_model_from_file (registry, instance_list, "assy.step"); + if (model_pd != NULL) + { + print_pd_debug (instance_list, model_pd); + convert_model_to_assy_capable (registry, instance_list, model_pd); + + for (int i = -2; i <= 2; i++) + { + // Translation coordinate system. + child_location = MakeAxis (registry, instance_list, i * 50.0, 0.0, 0.0, // POINT + 0.0, 0.0, 1.0, // AXIS + 1.0, 0.0, 0.0); // REF DIRECTION + assemble_instance_of_model (registry, instance_list, assembly_pd, model_pd, child_location); + } + } + + model_pd = append_model_from_file (registry, instance_list, "/home/pcjc2/source/stepcode/example/ap203min/build/bin/part.step"); + if (model_pd != NULL) + { + print_pd_debug (instance_list, model_pd); + convert_model_to_assy_capable (registry, instance_list, model_pd); + + child_location = MakeAxis (registry, instance_list, + 0.0, 0.0, 100.0, + 0.0, 0.0, 1.0, + 1.0, 0.0, 0.0); + + assemble_instance_of_model (registry, instance_list, assembly_pd, model_pd, child_location); + + child_location = MakeAxis (registry, instance_list, + 0.0, 0.0, -100.0, + 0.0, 0.0, 1.0, + 1.0, 0.0, 0.0); + assemble_instance_of_model (registry, instance_list, assembly_pd, model_pd, child_location); + } +#endif + +#if 1 + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/APTOS_RPLJ-11CBEJ-FG_HDRV_Therminal_3-81mmP.step", 000.0, 000.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/BGA121C65P11X11_800X800X143_JEDEC_MO-275-CCBE-1_Freescale_MAPBGA_121.step", 050.0, 000.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/CAPPRD500W60D1250H2000-V-000-300.step", 100.0, 000.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/CAPPRD750W80D1600H2500-HL-000-300-100.step", 150.0, 000.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/CAPRB1000W60L1000T400H1300-180_Vishay_H_Series.step", 200.0, 000.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); // CORRUPTED BY CONVERSION? + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/CAPRR1000W60L1300T400H900_EPCOS_B32921.step", 250.0, 000.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/CAPRR3750W100L4150T2800H4250_EPCOS_B32926.step", 000.0, 050.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/CNC_Tech_3020-14-0100-00_IDC14_V.step", 050.0, 050.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/Degson_DG126-5.0-07P-14_Screw_Terminal.step", 100.0, 050.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); // CORRUPTED BY CONVERSION? + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/DIPS762W51P254L2032H419Q16_DIP_SOCKET_16_.300.step", 150.0, 050.0, 0.0, /**/ 1.0, 0.0, 0.0, /**/ 0.0, 1.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/FCI_67996-440HLF_HDRV40W64P254_2X20_5080X508X838-584-381.step", 200.0, 050.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/FCI_68000-102HLF_HDRV2W64P254_1X2_508X421X839-584-241.step", 250.0, 050.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/HARWIN_M52-040000P1045_HDRV10W46P127_1X10_1270X500X777.step", 000.0, 100.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/Harwin_M52-040000S0545_HDRV_2X5_127mmP_SM.step", 050.0, 100.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/INDRD1143W102D1676H2134-300_Vishay_IHB-1.step", 100.0, 100.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/JEDEC_TO-262_5_LEADS_I2PAK-BL.step", 150.0, 100.0, 0.0, /**/ 0.0, 0.0, -1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/JST_B7PS-VH(LF)(SN)_HDR_3.96mm_Pitch_RA.step", 200.0, 100.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/JST_B7P-VH(LF)(SN)_HDR_TH_3.96mm_pitch_V.step", 250.0, 100.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/Multicomp_2119R5-14G-301523_HDRRA14W40P127_2X7_889X150X340-300-230-200.step", 000.0, 150.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/Multicomp_2119R5-50G-301523_HDRRA50W40P127_2X25_3175X150X340-300-230-200.step", 050.0, 150.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/Multicomp_2206RPA-09G_HDRRA9W46P127_1X9_1143X254X127-285-200-287.step", 100.0, 150.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/MULTICOMP_2217R-02-WH2_HDR_KK_RA.step", 150.0, 150.0, 0.0, /**/ 1.0, 0.0, 0.0, /**/ 0.0, 1.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/MULTICOMP_2217S-03-WH2_HDR_KK_V.step", 200.0, 150.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/OSCCC160X200X050-4_NDK_NX2016SA.step", 250.0, 150.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/PLCC127P1244X1244X457-28N_JEDEC_MO-047AB.step", 000.0, 200.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/QFN50P350X450X80-24_JEDEC_MO-220WFSD.step", 050.0, 200.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); // CORRUPTED BY CONVERSION? + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/QFP80P1400X1400X120-52N_JEDEC_MS-026ADB.step", 100.0, 200.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/RESC1608X50N_EIA_0603_METRIC_1608_157X085X050.step", 150.0, 200.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/SOD9959X265N_JEDEC_DO-215AB.step", 200.0, 200.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/SON40P300X300X80-15N_MAXIM_T1433-1.step", 250.0, 200.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/SOP65P780X200-22N_JEDEC_MO-150AF.step", 000.0, 250.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/TE_1-1634688-4_IDC14_V.step", 050.0, 250.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/TE_1-1634689-0_IDC10_RA.step", 100.0, 250.0, 0.0, /**/ -1.0, 0.0, 0.0, /**/ 0.0, 1.0, 0.0); + lazy_assemble (registry, instance_list, assembly_pd, "pcb-3d/XTAL_RALTRON_HC-49U_3PIN-V.step", 150.0, 250.0, 0.0, /**/ 0.0, 0.0, 1.0, /**/ 1.0, 0.0, 0.0); +#endif + + write_ap214 (registry, instance_list, "outfile.step"); + +// header_instances->DeleteInstances(); + instance_list->DeleteInstances(); + delete registry; + delete instance_list; +}