1 
2 /*
3 * NIST STEP Core Class Library
4 * clstepcore/STEPaggregate.cc
5 * April 1997
6 * K. C. Morris
7 * David Sauder
8 
9 * Development of this software was funded by the United States Government,
10 * and is not subject to copyright.
11 */
12 
13 #include <stdio.h>
14 
15 #include <read_func.h>
16 #include <STEPaggregate.h>
17 #include <STEPattribute.h>
18 #include <instmgr.h>
19 #include <ExpDict.h>
20 #include "sc_memmgr.h"
21 
22 const int Real_Num_Precision = REAL_NUM_PRECISION; // from STEPattribute.h
23 
24 
25 /******************************************************************************
26 **    \file STEPaggregate.cc Functions for manipulating aggregate attributes
27 **  FIXME KNOWN BUGs:
28 **     -- treatment of aggregates of reals or ints is inconsistent with
29 **        other aggregates (there's no classes for these)
30 **     -- no two- dimensional aggregates are implemented
31 **/
32 
33 STEPaggregate NilSTEPaggregate;
34 
35 
STEPaggregate()36 STEPaggregate::STEPaggregate() {
37     _null = 1;
38 }
39 
~STEPaggregate()40 STEPaggregate::~STEPaggregate() {
41     STEPnode * node;
42 
43     node = ( STEPnode * ) head;
44     while( node ) {
45         head = node->NextNode();
46         delete node;
47         node = ( STEPnode * ) head;
48     }
49 }
50 
ShallowCopy(const STEPaggregate & a)51 STEPaggregate & STEPaggregate::ShallowCopy( const STEPaggregate & a ) {
52     (void) a; // unused
53     cerr << "Internal error:  " << __FILE__ << ": " <<  __LINE__
54          << "\n" << _POC_ "\n";
55     cerr << "function:  STEPaggregate::ShallowCopy \n" << "\n";
56     return *this;
57 }
58 
59 /// do not require exchange file format
AggrValidLevel(const char * value,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int optional,char * tokenList,int addFileId,int clearError)60 Severity STEPaggregate::AggrValidLevel( const char * value, ErrorDescriptor * err,
61                                         const TypeDescriptor * elem_type, InstMgrBase * insts,
62                                         int optional, char * tokenList, int addFileId,
63                                         int clearError ) {
64     std::string buf;
65     if( clearError ) {
66         err->ClearErrorMsg();
67     }
68 
69     istringstream in( ( char * )value ); // sz defaults to length of s
70 
71     ReadValue( in, err, elem_type, insts, addFileId, 0, 0 );
72     CheckRemainingInput( in, err, elem_type->AttrTypeName( buf ), tokenList );
73     if( optional && ( err->severity() == SEVERITY_INCOMPLETE ) ) {
74         err->severity( SEVERITY_NULL );
75     }
76     return err->severity();
77 }
78 
79 /// require exchange file format
AggrValidLevel(istream & in,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int optional,char * tokenList,int addFileId,int clearError)80 Severity STEPaggregate::AggrValidLevel( istream & in, ErrorDescriptor * err,
81                                         const TypeDescriptor * elem_type, InstMgrBase * insts,
82                                         int optional, char * tokenList, int addFileId,
83                                         int clearError ) {
84     std::string buf;
85     if( clearError ) {
86         err->ClearErrorMsg();
87     }
88 
89     ReadValue( in, err, elem_type, insts, addFileId, 0, 1 );
90     CheckRemainingInput( in, err, elem_type->AttrTypeName( buf ), tokenList );
91     if( optional && ( err->severity() == SEVERITY_INCOMPLETE ) ) {
92         err->severity( SEVERITY_NULL );
93     }
94     return err->severity();
95 }
96 
97 /// if exchangeFileFormat == 1 then paren delims are required.
98 
ReadValue(istream & in,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId,int assignVal,int exchangeFileFormat,const char *)99 Severity STEPaggregate::ReadValue( istream & in, ErrorDescriptor * err,
100                                    const TypeDescriptor * elem_type, InstMgrBase * insts,
101                                    int addFileId, int assignVal, int exchangeFileFormat,
102                                    const char * ) {
103     (void) insts; //not used in ReadValue() for this class
104     (void) addFileId; //not used in ReadValue() for this class
105 
106     ErrorDescriptor errdesc;
107     char errmsg[BUFSIZ];
108     int value_cnt = 0;
109     std::string buf;
110 
111     if( assignVal ) {
112         Empty();    // read new values and discard existing ones
113     }
114 
115     char c;
116 
117     in >> ws; // skip white space
118 
119     c = in.peek(); // does not advance input
120 
121     if( in.eof() || c == '$' ) {
122         _null = 1;
123         err->GreaterSeverity( SEVERITY_INCOMPLETE );
124         return SEVERITY_INCOMPLETE;
125     }
126 
127     if( c == '(' ) {
128         in.get( c );
129     } else if( exchangeFileFormat ) {
130         // error did not find opening delim
131         // cannot recover so give up and let STEPattribute recover
132         err->GreaterSeverity( SEVERITY_INPUT_ERROR );
133         return SEVERITY_INPUT_ERROR;
134     } else if( !in.good() ) {
135         // this should actually have been caught by skipping white space above
136         err->GreaterSeverity( SEVERITY_INCOMPLETE );
137         return SEVERITY_INCOMPLETE;
138     }
139 
140     STEPnode * item = 0;
141 
142     in >> ws;
143     // take a peek to see if there are any elements before committing to an
144     // element
145     c = in.peek(); // does not advance input
146     if( c == ')' ) {
147         in.get( c );
148     }
149     // if not assigning values only need one node. So only one node is created.
150     // It is used to read the values
151     else if( !assignVal ) {
152         item = ( STEPnode * )NewNode();
153     }
154 
155     // ')' is the end of the aggregate
156     while( in.good() && ( c != ')' ) ) {
157         value_cnt++;
158         if( assignVal ) { // create a new node each time through the loop
159             item = ( STEPnode * )NewNode();
160         }
161 
162         errdesc.ClearErrorMsg();
163 
164         if( exchangeFileFormat ) {
165             item->STEPread( in, &errdesc );
166         } else {
167             item->StrToVal( in, &errdesc );
168         }
169 
170         // read up to the next delimiter and set errors if garbage is
171         // found before specified delims (i.e. comma and quote)
172         CheckRemainingInput( in, &errdesc, elem_type->AttrTypeName( buf ), ",)" );
173 
174         if( errdesc.severity() < SEVERITY_INCOMPLETE ) {
175             sprintf( errmsg, "  index:  %d\n", value_cnt );
176             errdesc.PrependToDetailMsg( errmsg );
177             err->AppendFromErrorArg( &errdesc );
178         }
179         if( assignVal ) { // pass the node to STEPaggregate
180             AddNode( item );
181         }
182 
183         in >> ws; // skip white space (although should already be skipped)
184         in.get( c ); // read delim
185 
186         // CheckRemainingInput should have left the input right at the delim
187         // so that it would be read in in.get() above.  Since it did not find
188         // the delim this does not know how to find it either!
189         if( ( c != ',' ) && ( c != ')' ) ) {
190             // cannot recover so give up and let STEPattribute recover
191             err->GreaterSeverity( SEVERITY_INPUT_ERROR );
192             return SEVERITY_INPUT_ERROR;
193         }
194     }
195     if( c == ')' ) {
196         _null = 0;
197     } else { // expectation for end paren delim has not been met
198         err->GreaterSeverity( SEVERITY_INPUT_ERROR );
199         err->AppendToUserMsg( "Missing close paren for aggregate value" );
200         return SEVERITY_INPUT_ERROR;
201     }
202     return err->severity();
203 }
204 
StrToVal(const char * s,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId)205 Severity STEPaggregate::StrToVal( const char * s, ErrorDescriptor * err,
206                                   const TypeDescriptor * elem_type, InstMgrBase * insts,
207                                   int addFileId ) {
208     istringstream in( ( char * )s );
209     return ReadValue( in, err, elem_type, insts, addFileId, 1, 0 );
210 }
211 
212 ///////////////////////////////////////////////////////////////////////////////
213 
STEPread(istream & in,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId,const char * currSch)214 Severity STEPaggregate::STEPread( istream & in, ErrorDescriptor * err,
215                                   const TypeDescriptor * elem_type, InstMgrBase * insts,
216                                   int addFileId, const char * currSch ) {
217     return ReadValue( in, err, elem_type, insts, addFileId, 1, 1, currSch );
218 }
219 
asStr(std::string & s) const220 const char * STEPaggregate::asStr( std::string & s ) const {
221     s.clear();
222 
223     if( !_null ) {
224         s = "(";
225         STEPnode * n = ( STEPnode * ) head;
226         std::string tmp;
227         while( n ) {
228             s.append( n->STEPwrite( tmp ) );
229             n = ( STEPnode * ) n -> NextNode();
230             if( n ) {
231                 s.append( "," );
232             }
233         }
234         s.append( ")" );
235     }
236     return const_cast<char *>( s.c_str() );
237 }
238 
STEPwrite(ostream & out,const char * currSch) const239 void STEPaggregate::STEPwrite( ostream & out, const char * currSch ) const {
240     if( !_null ) {
241         out << '(';
242         STEPnode * n = ( STEPnode * )head;
243         std::string s;
244         while( n ) {
245             out << n->STEPwrite( s, currSch );
246             n = ( STEPnode * ) n -> NextNode();
247             if( n ) {
248                 out <<  ',';
249             }
250         }
251         out << ')';
252     } else {
253         out << '$';
254     }
255 }
256 
NewNode()257 SingleLinkNode * STEPaggregate::NewNode() {
258     cerr << "Internal error:  " << __FILE__ << ": " <<  __LINE__ << "\n" ;
259     cerr << "function:  STEPaggregate::NewNode \n" << _POC_ << "\n";
260     return 0;
261 }
262 
AddNode(SingleLinkNode * n)263 void STEPaggregate::AddNode( SingleLinkNode * n ) {
264     SingleLinkList::AppendNode( n );
265     _null = 0;
266 }
267 
Empty()268 void STEPaggregate::Empty() {
269     SingleLinkList::Empty();
270     _null = 1;
271 }
272 
273 
274 ///////////////////////////////////////////////////////////////////////////////
275 // STEPnode
276 ///////////////////////////////////////////////////////////////////////////////
277 
StrToVal(const char * s,ErrorDescriptor * err)278 Severity STEPnode::StrToVal( const char * s, ErrorDescriptor * err ) {
279     // defined in subtypes
280     (void) s; //unused
281     cerr << "Internal error:  " << __FILE__ << ": " <<  __LINE__ << "\n" ;
282     err->AppendToDetailMsg(
283         " function: STEPnode::StrToVal() called instead of virtual function.\n"
284     );
285     err->AppendToDetailMsg( "Aggr. attr value: '\n" );
286     err->AppendToDetailMsg( "not assigned.\n" );
287     err->AppendToDetailMsg( _POC_ );
288     err->GreaterSeverity( SEVERITY_BUG );
289     return SEVERITY_BUG;
290 }
291 
StrToVal(istream & in,ErrorDescriptor * err)292 Severity STEPnode::StrToVal( istream & in, ErrorDescriptor * err ) {
293     // defined in subtypes
294     (void) in; //unused
295     cerr << "Internal error:  " << __FILE__ << ": " <<  __LINE__ << "\n" ;
296     err->AppendToDetailMsg(
297         " function: STEPnode::StrToVal() called instead of virtual function.\n"
298     );
299     err->AppendToDetailMsg( "Aggr. attr value: '\n" );
300     err->AppendToDetailMsg( "not assigned.\n" );
301     err->AppendToDetailMsg( _POC_ );
302     err->GreaterSeverity( SEVERITY_BUG );
303     return SEVERITY_BUG;
304 }
305 
STEPread(const char * s,ErrorDescriptor * err)306 Severity STEPnode::STEPread( const char * s, ErrorDescriptor * err ) {
307     //  defined in subclasses
308     (void) s; //unused
309     cerr << "Internal error:  " << __FILE__ << ": " <<  __LINE__ << "\n" ;
310     cerr << "function:  STEPnode::STEPread called instead of virtual function.\n"
311          << _POC_ << "\n";
312 
313     err->AppendToDetailMsg(
314         " function: STEPnode::STEPread() called instead of virtual function.\n"
315     );
316     err->AppendToDetailMsg( _POC_ );
317     err->GreaterSeverity( SEVERITY_BUG );
318 
319     return SEVERITY_BUG;
320 }
321 
STEPread(istream & in,ErrorDescriptor * err)322 Severity STEPnode::STEPread( istream & in, ErrorDescriptor * err ) {
323     (void) in; //unused
324     cerr << "Internal error:  " << __FILE__ << ": " <<  __LINE__ << "\n" ;
325     cerr << "function:  STEPnode::STEPread called instead of virtual function.\n"
326          << _POC_ << "\n";
327 
328     err->AppendToDetailMsg(
329         " function: STEPnode::STEPread() called instead of virtual function.\n"
330     );
331     err->AppendToDetailMsg( _POC_ );
332     err->GreaterSeverity( SEVERITY_BUG );
333     return SEVERITY_BUG;
334 }
335 
asStr(std::string & s)336 const char * STEPnode::asStr( std::string & s ) {
337     //  defined in subclasses
338     (void) s; //unused
339     cerr << "Internal error:  " << __FILE__ << ": " <<  __LINE__ << "\n" ;
340     cerr << "function:  STEPnode::asStr called instead of virtual function.\n"
341          << _POC_ << "\n";
342 
343     return "";
344 }
345 
346 /**
347  * NOTE - second argument will contain name of current schema.  We may need
348  * this if STEPnode belongs to an aggregate of selects.  If so, each node
349  * will be written out by calling STEPwrite on its select, and to write a
350  * select out, the name of its underlying type will be written.  Finally,
351  * the underlying type's name depends on the current schema.  This is be-
352  * cause e.g. type X may be defined in schema A, and may be USEd in schema
353  * B and renamed to Y (i.e., "USE from A (X as Y)").  Thus, if currSch = B,
354  * Y will have to be written out rather than X.  Actually, this concern
355  * only applies for SelectNode.  To accomodate those cases, all the signa-
356  * tures of STEPwrite(std::string) contain currSch.  (As an additional note,
357  * 2D aggregates should make use of currSch in case they are 2D aggrs of
358  * selects.  But since currently (3/27/97) the SCL handles 2D+ aggrs using
359  * SCLundefined's, this is not implemented.)
360  */
STEPwrite(std::string & s,const char * currSch)361 const char * STEPnode::STEPwrite( std::string & s, const char * currSch ) {
362     (void) s; //unused
363     (void) currSch; //unused
364     cerr << "Internal error:  " << __FILE__ << ": " <<  __LINE__ << "\n" ;
365     cerr << "function:  STEPnode::STEPwrite called instead of virtual function.\n"
366          << _POC_ << "\n";
367     return "";
368 }
369 
STEPwrite(ostream & out)370 void STEPnode::STEPwrite( ostream & out ) {
371     (void) out; //unused
372     cerr << "Internal error:  " << __FILE__ << ": " <<  __LINE__ << "\n" ;
373     cerr << "function:  STEPnode::STEPwrite called instead of virtual function.\n"
374          << _POC_ << "\n";
375 }
376 
377 ///////////////////////////////////////////////////////////////////////////////
378 // GenericAggregate
379 ///////////////////////////////////////////////////////////////////////////////
380 
GenericAggregate()381 GenericAggregate::GenericAggregate() {
382 }
383 
~GenericAggregate()384 GenericAggregate::~GenericAggregate() {
385 }
386 
NewNode()387 SingleLinkNode * GenericAggregate::NewNode() {
388     return new GenericAggrNode();
389 }
390 
ShallowCopy(const STEPaggregate & a)391 STEPaggregate & GenericAggregate::ShallowCopy( const STEPaggregate & a ) {
392     Empty();
393 
394     SingleLinkNode * next = a.GetHead();
395     SingleLinkNode * copy;
396 
397     while( next ) {
398         copy = new GenericAggrNode( *( GenericAggrNode * )next );
399         AddNode( copy );
400         next = next->NextNode();
401     }
402     if( head ) {
403         _null = 0;
404     } else {
405         _null = 1;
406     }
407     return *this;
408 
409 }
410 
411 ///////////////////////////////////////////////////////////////////////////////
412 // GenericAggrNode
413 ///////////////////////////////////////////////////////////////////////////////
414 
GenericAggrNode(const char * str)415 GenericAggrNode::GenericAggrNode( const char * str ) {
416     value = str;
417 }
418 
GenericAggrNode(GenericAggrNode & gan)419 GenericAggrNode::GenericAggrNode( GenericAggrNode & gan ) {
420     value = gan.value;
421 }
422 
GenericAggrNode()423 GenericAggrNode::GenericAggrNode() {
424 }
425 
~GenericAggrNode()426 GenericAggrNode::~GenericAggrNode() {
427 }
428 
NewNode()429 SingleLinkNode * GenericAggrNode::NewNode() {
430     return new GenericAggrNode();
431 }
432 
StrToVal(const char * s,ErrorDescriptor * err)433 Severity GenericAggrNode::StrToVal( const char * s, ErrorDescriptor * err ) {
434     return value.STEPread( s, err );
435 }
436 
437 //TODO
StrToVal(istream & in,ErrorDescriptor * err)438 Severity GenericAggrNode::StrToVal( istream & in, ErrorDescriptor * err ) {
439     return value.STEPread( in, err );
440 }
441 
STEPread(const char * s,ErrorDescriptor * err)442 Severity GenericAggrNode::STEPread( const char * s, ErrorDescriptor * err ) {
443     istringstream in( ( char * ) s );
444     return value.STEPread( in, err );
445 }
446 
STEPread(istream & in,ErrorDescriptor * err)447 Severity GenericAggrNode::STEPread( istream & in, ErrorDescriptor * err ) {
448     return value.STEPread( in, err );
449 }
450 
asStr(std::string & s)451 const char * GenericAggrNode::asStr( std::string & s ) {
452     s.clear();
453     value.asStr( s );
454     return const_cast<char *>( s.c_str() );
455 }
456 
STEPwrite(std::string & s,const char * currSch)457 const char * GenericAggrNode::STEPwrite( std::string & s, const char * currSch ) {
458     (void) currSch; //unused
459     return value.STEPwrite( s );
460 }
461 
STEPwrite(ostream & out)462 void GenericAggrNode::STEPwrite( ostream & out ) {
463     value.STEPwrite( out );
464 }
465 
466 ///////////////////////////////////////////////////////////////////////////////
467 // EntityAggregate
468 ///////////////////////////////////////////////////////////////////////////////
469 
EntityAggregate()470 EntityAggregate::EntityAggregate() {
471 }
472 
~EntityAggregate()473 EntityAggregate::~EntityAggregate() {
474 }
475 
476 
477 /// if exchangeFileFormat == 1 then delims are required.
ReadValue(istream & in,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId,int assignVal,int exchangeFileFormat,const char *)478 Severity EntityAggregate::ReadValue( istream & in, ErrorDescriptor * err,
479                                      const TypeDescriptor * elem_type, InstMgrBase * insts,
480                                      int addFileId, int assignVal,
481                                      int exchangeFileFormat, const char * ) {
482     ErrorDescriptor errdesc;
483     char errmsg[BUFSIZ];
484     int value_cnt = 0;
485     std::string buf;
486 
487     if( assignVal ) {
488         Empty();    // read new values and discard existing ones
489     }
490 
491     char c;
492 
493     in >> ws; // skip white space
494 
495     c = in.peek(); // does not advance input
496 
497     if( in.eof() || ( c == '$' ) ) {
498         _null = 1;
499         err->GreaterSeverity( SEVERITY_INCOMPLETE );
500         return SEVERITY_INCOMPLETE;
501     }
502 
503     if( c == '(' ) {
504         in.get( c );
505     } else if( exchangeFileFormat ) {
506         // error did not find opening delim
507         // give up because you do not know where to stop reading.
508         err->GreaterSeverity( SEVERITY_INPUT_ERROR );
509         return SEVERITY_INPUT_ERROR;
510     } else if( !in.good() ) {
511         // this should actually have been caught by skipping white space above
512         err->GreaterSeverity( SEVERITY_INCOMPLETE );
513         return SEVERITY_INCOMPLETE;
514     }
515 
516     EntityNode * item = 0;
517 
518     in >> ws;
519     // take a peek to see if there are any elements before committing to an
520     // element
521     c = in.peek(); // does not advance input
522     if( c == ')' ) {
523         in.get( c );
524     }
525     // if not assigning values only need one node. So only one node is created.
526     // It is used to read the values
527     else if( !assignVal ) {
528         item = new EntityNode();
529     }
530 
531     while( in.good() && ( c != ')' ) ) {
532         value_cnt++;
533         if( assignVal ) { // create a new node each time through the loop
534             item = new EntityNode();
535         }
536 
537         errdesc.ClearErrorMsg();
538 
539         if( exchangeFileFormat ) {
540             item->STEPread( in, &errdesc, elem_type, insts, addFileId );
541         } else {
542             item->StrToVal( in, &errdesc, elem_type, insts, addFileId );
543         }
544 
545         // read up to the next delimiter and set errors if garbage is
546         // found before specified delims (i.e. comma and quote)
547         CheckRemainingInput( in, &errdesc, elem_type->AttrTypeName( buf ), ",)" );
548 
549         if( errdesc.severity() < SEVERITY_INCOMPLETE ) {
550             sprintf( errmsg, "  index:  %d\n", value_cnt );
551             errdesc.PrependToDetailMsg( errmsg );
552             err->AppendFromErrorArg( &errdesc );
553         }
554         if( assignVal ) {
555             AddNode( item );
556         }
557 
558         in >> ws; // skip white space (although should already be skipped)
559         in.get( c ); // read delim
560 
561         // CheckRemainingInput should have left the input right at the delim
562         // so that it would be read in in.get() above.  Since it did not find
563         // the delim this does not know how to find it either!
564         if( ( c != ',' ) && ( c != ')' ) ) {
565             // cannot recover so give up and let STEPattribute recover
566             err->GreaterSeverity( SEVERITY_INPUT_ERROR );
567             return SEVERITY_INPUT_ERROR;
568         }
569     }
570     if( c == ')' ) {
571         _null = 0;
572     } else { // expectation for end paren delim has not been met
573         err->GreaterSeverity( SEVERITY_INPUT_ERROR );
574         err->AppendToUserMsg( "Missing close paren for aggregate value" );
575         return SEVERITY_INPUT_ERROR;
576     }
577     return err->severity();
578 }
579 
580 
ShallowCopy(const STEPaggregate & a)581 STEPaggregate & EntityAggregate::ShallowCopy( const STEPaggregate & a ) {
582     const EntityNode * tmp = ( const EntityNode * ) a.GetHead();
583     while( tmp ) {
584         AddNode( new EntityNode( tmp -> node ) );
585         tmp = ( const EntityNode * ) tmp -> NextNode();
586     }
587     if( head ) {
588         _null = 0;
589     } else {
590         _null = 1;
591     }
592 
593     return *this;
594 }
595 
596 
NewNode()597 SingleLinkNode * EntityAggregate::NewNode() {
598     return new EntityNode();
599 }
600 
601 ///////////////////////////////////////////////////////////////////////////////
602 // EntityNode
603 ///////////////////////////////////////////////////////////////////////////////
604 
EntityNode()605 EntityNode::EntityNode() {
606 }
607 
~EntityNode()608 EntityNode::~EntityNode() {
609 }
610 
EntityNode(SDAI_Application_instance * e)611 EntityNode::EntityNode( SDAI_Application_instance  * e ) : node( e ) {
612 }
613 
NewNode()614 SingleLinkNode * EntityNode::NewNode() {
615     return new EntityNode();
616 }
617 ///////////////////////////////////////////////////////////////////////////////
618 
StrToVal(const char * s,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId)619 Severity EntityNode::StrToVal( const char * s, ErrorDescriptor * err,
620                                const TypeDescriptor * elem_type,
621                                InstMgrBase * insts, int addFileId ) {
622     SDAI_Application_instance * se = ReadEntityRef( s, err, ",)", insts,
623                                      addFileId );
624     if( se != S_ENTITY_NULL ) {
625         ErrorDescriptor error;
626         if( EntityValidLevel( se, elem_type, &error ) == SEVERITY_NULL ) {
627             node = se;
628         } else {
629             node = S_ENTITY_NULL;
630             err->AppendToDetailMsg( error.DetailMsg() );
631             err->AppendToUserMsg( error.UserMsg() );
632             err->GreaterSeverity( error.severity() );
633         }
634     } else {
635         node = S_ENTITY_NULL;
636     }
637     return err->severity();
638 }
639 
StrToVal(istream & in,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId)640 Severity EntityNode::StrToVal( istream & in, ErrorDescriptor * err,
641                                const TypeDescriptor * elem_type,
642                                InstMgrBase * insts, int addFileId ) {
643     return STEPread( in, err, elem_type, insts, addFileId );
644 }
645 
STEPread(const char * s,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId)646 Severity EntityNode::STEPread( const char * s, ErrorDescriptor * err,
647                                const TypeDescriptor * elem_type,
648                                InstMgrBase * insts, int addFileId ) {
649     istringstream in( ( char * )s );
650     return STEPread( in, err, elem_type, insts, addFileId );
651 }
652 
STEPread(istream & in,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId)653 Severity EntityNode::STEPread( istream & in, ErrorDescriptor * err,
654                                const TypeDescriptor * elem_type,
655                                InstMgrBase * insts, int addFileId ) {
656     SDAI_Application_instance * se = ReadEntityRef( in, err, ",)", insts,
657                                      addFileId );
658     if( se != S_ENTITY_NULL ) {
659         ErrorDescriptor error;
660         if( EntityValidLevel( se, elem_type, &error ) == SEVERITY_NULL ) {
661             node = se;
662         } else {
663             node = S_ENTITY_NULL;
664             err->AppendToDetailMsg( error.DetailMsg() );
665             err->AppendToUserMsg( error.UserMsg() );
666             err->GreaterSeverity( error.severity() );
667         }
668     } else {
669         node = S_ENTITY_NULL;
670     }
671     return err->severity();
672 }
673 
asStr(std::string & s)674 const char * EntityNode::asStr( std::string & s ) {
675     s.clear();
676     if( !node || ( node == S_ENTITY_NULL ) ) { //  nothing
677         return "";
678     } else { // otherwise return entity id
679         char tmp [64];
680         sprintf( tmp, "#%d", node->STEPfile_id );
681         s = tmp;
682     }
683     return const_cast<char *>( s.c_str() );
684 }
685 
STEPwrite(std::string & s,const char *)686 const char * EntityNode::STEPwrite( std::string & s, const char * ) {
687     if( !node || ( node == S_ENTITY_NULL ) ) { //  nothing
688         s = "$";
689         return const_cast<char *>( s.c_str() );
690     }
691     asStr( s );
692     return const_cast<char *>( s.c_str() );
693 }
694 
STEPwrite(ostream & out)695 void EntityNode::STEPwrite( ostream & out ) {
696     if( !node || ( node == S_ENTITY_NULL ) ) { //  nothing
697         out << "$";
698     }
699     std::string s;
700     out << asStr( s );
701 }
702 
703 
704 ///////////////////////////////////////////////////////////////////////////////
705 // SelectAggregate
706 ///////////////////////////////////////////////////////////////////////////////
707 
SelectAggregate()708 SelectAggregate::SelectAggregate() {
709 }
710 
~SelectAggregate()711 SelectAggregate::~SelectAggregate() {
712 }
713 
714 
715 /// if exchangeFileFormat == 1 then delims are required.
ReadValue(istream & in,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId,int assignVal,int exchangeFileFormat,const char * currSch)716 Severity SelectAggregate::ReadValue( istream & in, ErrorDescriptor * err,
717                                      const TypeDescriptor * elem_type, InstMgrBase * insts,
718                                      int addFileId, int assignVal,
719                                      int exchangeFileFormat, const char * currSch ) {
720     ErrorDescriptor errdesc;
721     char errmsg[BUFSIZ];
722     int value_cnt = 0;
723     std::string buf;
724 
725     if( assignVal ) {
726         Empty();    // read new values and discard existing ones
727     }
728 
729     char c;
730 
731     in >> ws; // skip white space
732 
733     c = in.peek(); // does not advance input
734 
735     if( in.eof() || ( c == '$' ) ) {
736         _null = 1;
737         err->GreaterSeverity( SEVERITY_INCOMPLETE );
738         return SEVERITY_INCOMPLETE;
739     }
740 
741     if( c == '(' ) {
742         in.get( c );
743     } else if( exchangeFileFormat ) {
744         // error did not find opening delim
745         // give up because you do not know where to stop reading.
746         err->GreaterSeverity( SEVERITY_INPUT_ERROR );
747         return SEVERITY_INPUT_ERROR;
748     } else if( !in.good() ) {
749         // this should actually have been caught by skipping white space above
750         err->GreaterSeverity( SEVERITY_INCOMPLETE );
751         return SEVERITY_INCOMPLETE;
752     }
753 
754     SelectNode * item = 0;
755 
756     in >> ws;
757     // take a peek to see if there are any elements before committing to an
758     // element
759     c = in.peek(); // does not advance input
760     if( c == ')' ) {
761         in.get( c );
762     }
763     // if not assigning values only need one node. So only one node is created.
764     // It is used to read the values
765     else if( !assignVal ) {
766         item = ( SelectNode * ) NewNode();
767     }
768 
769     while( in.good() && ( c != ')' ) ) {
770         value_cnt++;
771         if( assignVal ) { // create a new node each time through the loop
772             item = ( SelectNode * ) NewNode();
773         }
774 
775         errdesc.ClearErrorMsg();
776 
777         if( exchangeFileFormat ) {
778             item->STEPread( in, &errdesc, elem_type, insts, addFileId, currSch );
779         } else {
780             item->StrToVal( in, &errdesc, elem_type, insts, addFileId, currSch );
781         }
782 
783         // read up to the next delimiter and set errors if garbage is
784         // found before specified delims (i.e. comma and quote)
785         CheckRemainingInput( in, &errdesc, elem_type->AttrTypeName( buf ), ",)" );
786 
787         if( errdesc.severity() < SEVERITY_INCOMPLETE ) {
788             sprintf( errmsg, "  index:  %d\n", value_cnt );
789             errdesc.PrependToDetailMsg( errmsg );
790             err->AppendFromErrorArg( &errdesc );
791         }
792         if( assignVal ) {
793             AddNode( item );
794         }
795 
796         in >> ws; // skip white space (although should already be skipped)
797         in.get( c ); // read delim
798 
799         // CheckRemainingInput should have left the input right at the delim
800         // so that it would be read in in.get() above.  Since it did not find
801         // the delim this does not know how to find it either!
802         if( ( c != ',' ) && ( c != ')' ) ) {
803             // cannot recover so give up and let STEPattribute recover
804             err->GreaterSeverity( SEVERITY_INPUT_ERROR );
805             return SEVERITY_INPUT_ERROR;
806         }
807     }
808     if( c == ')' ) {
809         _null = 0;
810     } else { // expectation for end paren delim has not been met
811         err->GreaterSeverity( SEVERITY_INPUT_ERROR );
812         err->AppendToUserMsg( "Missing close paren for aggregate value" );
813         return SEVERITY_INPUT_ERROR;
814     }
815     return err->severity();
816 }
817 
818 
ShallowCopy(const STEPaggregate & a)819 STEPaggregate & SelectAggregate::ShallowCopy( const STEPaggregate & a ) {
820     const SelectNode * tmp = ( const SelectNode * ) a.GetHead();
821     while( tmp ) {
822         AddNode( new SelectNode( tmp -> node ) );
823 
824         tmp = ( const SelectNode * ) tmp -> NextNode();
825     }
826     if( head ) {
827         _null = 0;
828     } else {
829         _null = 1;
830     }
831 
832     return *this;
833 }
834 
835 
NewNode()836 SingleLinkNode * SelectAggregate::NewNode() {
837     return new SelectNode();
838 }
839 
840 ///////////////////////////////////////////////////////////////////////////////
841 // SelectNode
842 ///////////////////////////////////////////////////////////////////////////////
843 
SelectNode(SDAI_Select * s)844 SelectNode::SelectNode( SDAI_Select  * s ) :  node( s ) {
845 }
846 
SelectNode()847 SelectNode::SelectNode() {
848 }
849 
~SelectNode()850 SelectNode::~SelectNode() {
851     delete node;
852 }
853 
NewNode()854 SingleLinkNode * SelectNode::NewNode() {
855     return new SelectNode();
856 }
857 ///////////////////////////////////////////////////////////////////////////////
858 
StrToVal(const char * s,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId)859 Severity SelectNode::StrToVal( const char * s, ErrorDescriptor * err,
860                                const TypeDescriptor * elem_type,
861                                InstMgrBase * insts, int addFileId ) {
862     (void) elem_type; //unused
863     (void) addFileId; //unused
864     istringstream in( ( char * )s );
865     if( err->severity( node->STEPread( in, err, insts ) ) != SEVERITY_NULL ) {
866         err->AppendToDetailMsg( node ->Error() );
867     }
868     return err->severity();
869 }
870 
StrToVal(istream & in,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId,const char * currSch)871 Severity SelectNode::StrToVal( istream & in, ErrorDescriptor * err,
872                                const TypeDescriptor * elem_type,
873                                InstMgrBase * insts, int addFileId, const char * currSch ) {
874     return STEPread( in, err, elem_type, insts, addFileId, currSch );
875 }
876 
STEPread(const char * s,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId)877 Severity SelectNode::STEPread( const char * s, ErrorDescriptor * err,
878                                const TypeDescriptor * elem_type,
879                                InstMgrBase * insts, int addFileId ) {
880     istringstream in( ( char * )s );
881     return STEPread( in, err, elem_type, insts, addFileId );
882 }
883 
STEPread(istream & in,ErrorDescriptor * err,const TypeDescriptor * elem_type,InstMgrBase * insts,int addFileId,const char * currSch)884 Severity SelectNode::STEPread( istream & in, ErrorDescriptor * err,
885                                const TypeDescriptor * elem_type,
886                                InstMgrBase * insts, int addFileId, const char * currSch ) {
887     (void) elem_type; //unused
888     if( !node )  {
889         cerr << "Internal error:  " << __FILE__ << ": " <<  __LINE__ << "\n"
890              << _POC_ "\n";
891         cerr << "function:  SelectNode::STEPread \n" << "\n";
892         return SEVERITY_BUG;
893     }
894     err->severity( node->STEPread( in, err, insts, 0, addFileId, currSch ) );
895     CheckRemainingInput( in, err, "select", ",)" );
896     return err->severity();
897 }
898 
asStr(std::string & s)899 const char * SelectNode::asStr( std::string & s ) {
900     s.clear();
901     if( !node || ( node->is_null() ) ) {  //  nothing
902         return "";
903     } else { // otherwise return entity id
904         node -> STEPwrite( s );
905         return const_cast<char *>( s.c_str() );
906     }
907 }
908 
STEPwrite(std::string & s,const char * currSch)909 const char * SelectNode::STEPwrite( std::string & s, const char * currSch ) {
910     s.clear();
911     if( !node || ( node->is_null() ) ) {  //  nothing
912         s = "$";
913         return "$";
914     }
915     node -> STEPwrite( s, currSch );
916     return const_cast<char *>( s.c_str() );
917 }
918 
STEPwrite(ostream & out)919 void SelectNode::STEPwrite( ostream & out ) {
920     if( !node || ( node->is_null() ) ) {  //  nothing
921         out << "$";
922     }
923     std::string s;
924     out << asStr( s );
925 }
926 
927 ///////////////////////////////////////////////////////////////////////////////
928 // StringAggregate
929 ///////////////////////////////////////////////////////////////////////////////
930 
StringAggregate()931 StringAggregate::StringAggregate() {
932 }
933 
~StringAggregate()934 StringAggregate::~StringAggregate() {
935 }
936 
ShallowCopy(const STEPaggregate & a)937 STEPaggregate & StringAggregate::ShallowCopy( const STEPaggregate & a ) {
938     Empty();
939 
940     SingleLinkNode * next = a.GetHead();
941     SingleLinkNode * copy;
942 
943     while( next ) {
944         copy = new StringNode( *( StringNode * )next );
945         AddNode( copy );
946         next = next->NextNode();
947     }
948     if( head ) {
949         _null = 0;
950     } else {
951         _null = 1;
952     }
953     return *this;
954 
955 }
956 
NewNode()957 SingleLinkNode * StringAggregate::NewNode() {
958     return new StringNode();
959 }
960 
961 ///////////////////////////////////////////////////////////////////////////////
962 // StringNode
963 ///////////////////////////////////////////////////////////////////////////////
964 
StringNode()965 StringNode::StringNode() {
966     value = "";
967 }
968 
~StringNode()969 StringNode::~StringNode() {
970 }
971 
StringNode(StringNode & sn)972 StringNode::StringNode( StringNode & sn ) {
973     value = sn.value.c_str();
974 }
975 
StringNode(const char * sStr)976 StringNode::StringNode( const char * sStr ) {
977     // value is an SDAI_String (the memory is copied)
978     value = sStr;
979 }
980 
NewNode()981 SingleLinkNode * StringNode::NewNode() {
982     return new StringNode();
983 }
984 
985 /**
986  * non-whitespace chars following s are considered garbage and is an error.
987  * a valid value will still be assigned if it exists before the garbage.
988  */
StrToVal(const char * s,ErrorDescriptor * err)989 Severity StringNode::StrToVal( const char * s, ErrorDescriptor * err ) {
990     return STEPread( s, err );
991 }
992 
993 /**
994  * this function assumes you will check for garbage following input
995  */
StrToVal(istream & in,ErrorDescriptor * err)996 Severity StringNode::StrToVal( istream & in, ErrorDescriptor * err ) {
997     return value.STEPread( in, err );
998 }
999 
1000 /**
1001  * non-whitespace chars following s are considered garbage and is an error.
1002  * a valid value will still be assigned if it exists before the garbage.
1003  */
STEPread(const char * s,ErrorDescriptor * err)1004 Severity StringNode::STEPread( const char * s, ErrorDescriptor * err ) {
1005     istringstream in( ( char * )s );
1006 
1007     value.STEPread( in, err );
1008     CheckRemainingInput( in, err, "string", ",)" );
1009     return err->severity();
1010 }
1011 
1012 /**
1013  * this function assumes you will check for garbage following input
1014  */
STEPread(istream & in,ErrorDescriptor * err)1015 Severity StringNode::STEPread( istream & in, ErrorDescriptor * err ) {
1016     return value.STEPread( in, err );
1017 }
1018 
asStr(std::string & s)1019 const char * StringNode::asStr( std::string & s ) {
1020     value.asStr( s );
1021     return const_cast<char *>( s.c_str() );
1022 }
1023 
STEPwrite(std::string & s,const char *)1024 const char * StringNode::STEPwrite( std::string & s, const char * ) {
1025     value.STEPwrite( s );
1026     return const_cast<char *>( s.c_str() );
1027 }
1028 
STEPwrite(ostream & out)1029 void StringNode::STEPwrite( ostream & out ) {
1030     value.STEPwrite( out );
1031 }
1032 ///////////////////////////////////////////////////////////////////////////////
1033 // BinaryAggregate
1034 ///////////////////////////////////////////////////////////////////////////////
1035 
BinaryAggregate()1036 BinaryAggregate::BinaryAggregate() {
1037 }
1038 
~BinaryAggregate()1039 BinaryAggregate::~BinaryAggregate() {
1040 }
1041 
ShallowCopy(const STEPaggregate & a)1042 STEPaggregate & BinaryAggregate::ShallowCopy( const STEPaggregate & a ) {
1043     Empty();
1044 
1045     SingleLinkNode * next = a.GetHead();
1046     SingleLinkNode * copy;
1047 
1048     while( next ) {
1049         copy = new BinaryNode( *( BinaryNode * )next );
1050         AddNode( copy );
1051         next = next->NextNode();
1052     }
1053     if( head ) {
1054         _null = 0;
1055     } else {
1056         _null = 1;
1057     }
1058     return *this;
1059 
1060 }
1061 
NewNode()1062 SingleLinkNode * BinaryAggregate::NewNode() {
1063     return new BinaryNode();
1064 }
1065 
1066 ///////////////////////////////////////////////////////////////////////////////
1067 // BinaryNode
1068 ///////////////////////////////////////////////////////////////////////////////
1069 
BinaryNode()1070 BinaryNode::BinaryNode() {
1071     value = 0;
1072 }
1073 
~BinaryNode()1074 BinaryNode::~BinaryNode() {
1075 }
1076 
BinaryNode(BinaryNode & bn)1077 BinaryNode::BinaryNode( BinaryNode & bn ) {
1078     value = bn.value.c_str();
1079 }
1080 
BinaryNode(const char * sStr)1081 BinaryNode::BinaryNode( const char * sStr ) {
1082     // value is an SDAI_Binary (the memory is copied)
1083     value = sStr;
1084 }
1085 
1086 SingleLinkNode *
NewNode()1087 BinaryNode::NewNode() {
1088     return new BinaryNode();
1089 }
1090 
1091 /**
1092  * non-whitespace chars following s are considered garbage and is an error.
1093  * a valid value will still be assigned if it exists before the garbage.
1094  */
StrToVal(const char * s,ErrorDescriptor * err)1095 Severity BinaryNode::StrToVal( const char * s, ErrorDescriptor * err ) {
1096     return STEPread( s, err );
1097 }
1098 
1099 /**
1100  * this function assumes you will check for garbage following input
1101  */
StrToVal(istream & in,ErrorDescriptor * err)1102 Severity BinaryNode::StrToVal( istream & in, ErrorDescriptor * err ) {
1103     return value.STEPread( in, err );
1104 }
1105 
1106 /**
1107  * non-whitespace chars following s are considered garbage and is an error.
1108  * a valid value will still be assigned if it exists before the garbage.
1109  */
STEPread(const char * s,ErrorDescriptor * err)1110 Severity BinaryNode::STEPread( const char * s, ErrorDescriptor * err ) {
1111     istringstream in( ( char * )s );
1112 
1113     value.STEPread( in, err );
1114     CheckRemainingInput( in, err, "binary", ",)" );
1115     return err->severity();
1116 }
1117 
1118 /**
1119  * this function assumes you will check for garbage following input
1120  */
STEPread(istream & in,ErrorDescriptor * err)1121 Severity BinaryNode::STEPread( istream & in, ErrorDescriptor * err ) {
1122     return value.STEPread( in, err );
1123 }
1124 
asStr(std::string & s)1125 const char * BinaryNode::asStr( std::string & s ) {
1126     s = value.c_str();
1127     return const_cast<char *>( s.c_str() );
1128 }
1129 
STEPwrite(std::string & s,const char *)1130 const char * BinaryNode::STEPwrite( std::string & s, const char * ) {
1131     value.STEPwrite( s );
1132     return const_cast<char *>( s.c_str() );
1133 }
1134 
STEPwrite(ostream & out)1135 void BinaryNode::STEPwrite( ostream & out ) {
1136     value.STEPwrite( out );
1137 }
1138 
1139 ///////////////////////////////////////////////////////////////////////////////
1140 // EnumAggregate
1141 ///////////////////////////////////////////////////////////////////////////////
1142 
1143 /// COPY
ShallowCopy(const STEPaggregate & a)1144 STEPaggregate & EnumAggregate::ShallowCopy( const STEPaggregate & a ) {
1145     const EnumNode * tmp = ( const EnumNode * ) a.GetHead();
1146     EnumNode * to;
1147 
1148     while( tmp ) {
1149         to = ( EnumNode * ) NewNode();
1150         to -> node -> put( tmp -> node ->asInt() );
1151         AddNode( to );
1152         tmp = ( const EnumNode * ) tmp -> NextNode();
1153     }
1154     if( head ) {
1155         _null = 0;
1156     } else {
1157         _null = 1;
1158     }
1159 
1160     return *this;
1161 }
1162 
EnumAggregate()1163 EnumAggregate::EnumAggregate() {
1164 
1165 }
1166 
~EnumAggregate()1167 EnumAggregate::~EnumAggregate() {
1168 
1169 }
1170 
1171 /******************************************************************
1172  ** \returns a new EnumNode which is of the correct derived type
1173  ** \details  creates a node to put in an list of enumerated values
1174  **           function is virtual so that the right node will be
1175  **           created
1176  ** Status:  ok 2/91
1177  ******************************************************************/
NewNode()1178 SingleLinkNode * EnumAggregate::NewNode() {
1179     //  defined in subclass
1180     cerr << "Internal error:  " << __FILE__ << ": " <<  __LINE__ << "\n" ;
1181     cerr << "function:  EnumAggregate::NewNode () called instead of virtual function. \n"
1182          << _POC_ << "\n";
1183     return 0;
1184 }
1185 
1186 ///////////////////////////////////////////////////////////////////////////////
1187 // EnumNode
1188 ///////////////////////////////////////////////////////////////////////////////
1189 
EnumNode(SDAI_Enum * e)1190 EnumNode::EnumNode( SDAI_Enum  * e ) :  node( e ) {
1191 }
1192 
EnumNode()1193 EnumNode::EnumNode() {
1194 }
1195 
~EnumNode()1196 EnumNode::~EnumNode() {
1197 }
1198 
1199 ///  defined in subclass
NewNode()1200 SingleLinkNode * EnumNode::NewNode() {
1201     cerr << "Internal error:  " << __FILE__ << ": " <<  __LINE__ << "\n" ;
1202     cerr << "function:  EnumNode::NewNode () called instead of virtual function. \n"
1203          << _POC_ << "\n";
1204     return 0;
1205 }
1206 
1207 /**
1208  * non-whitespace chars following s are considered garbage and is an error.
1209  * a valid value will still be assigned if it exists before the garbage.
1210  */
StrToVal(const char * s,ErrorDescriptor * err)1211 Severity EnumNode::StrToVal( const char * s, ErrorDescriptor * err ) {
1212     return STEPread( s, err );
1213 }
1214 /**
1215  * this function assumes you will check for garbage following input
1216  */
StrToVal(istream & in,ErrorDescriptor * err)1217 Severity EnumNode::StrToVal( istream & in, ErrorDescriptor * err ) {
1218     return node->STEPread( in, err );
1219 }
1220 
1221 /**
1222  * non-whitespace chars following s are considered garbage and is an error.
1223  * a valid value will still be assigned if it exists before the garbage.
1224  */
STEPread(const char * s,ErrorDescriptor * err)1225 Severity EnumNode::STEPread( const char * s, ErrorDescriptor * err ) {
1226     istringstream in( ( char * )s ); // sz defaults to length of s
1227 
1228     int nullable = 0;
1229     node->STEPread( in, err,  nullable );
1230     CheckRemainingInput( in, err, "enumeration", ",)" );
1231     return err->severity();
1232 }
1233 
1234 /**
1235  * this function assumes you will check for garbage following input
1236  */
STEPread(istream & in,ErrorDescriptor * err)1237 Severity EnumNode::STEPread( istream & in, ErrorDescriptor * err ) {
1238     int nullable = 0;
1239     node->STEPread( in, err,  nullable );
1240     return err->severity();
1241 }
1242 
asStr(std::string & s)1243 const char * EnumNode::asStr( std::string & s ) {
1244     node -> asStr( s );
1245     return const_cast<char *>( s.c_str() );
1246 }
1247 
STEPwrite(std::string & s,const char *)1248 const char * EnumNode::STEPwrite( std::string & s, const char * ) {
1249     node->STEPwrite( s );
1250     return const_cast<char *>( s.c_str() );
1251 }
1252 
STEPwrite(ostream & out)1253 void EnumNode::STEPwrite( ostream & out ) {
1254     node->STEPwrite( out );
1255 }
1256 
1257 ///////////////////////////////////////////////////////////////////////////////
1258 // LOGICALS
1259 ///////////////////////////////////////////////////////////////////////////////
1260 
LOGICALS()1261 LOGICALS::LOGICALS() {
1262 }
1263 
~LOGICALS()1264 LOGICALS::~LOGICALS() {
1265 }
1266 
NewNode()1267 SingleLinkNode * LOGICALS::NewNode() {
1268     return new EnumNode( new SDAI_LOGICAL );
1269 }
1270 
create_LOGICALS()1271 LOGICALS * create_LOGICALS() {
1272     return new LOGICALS;
1273 }
1274 
1275 ///////////////////////////////////////////////////////////////////////////////
1276 // BOOLEANS
1277 ///////////////////////////////////////////////////////////////////////////////
1278 
BOOLEANS()1279 BOOLEANS::BOOLEANS() {
1280 }
1281 
~BOOLEANS()1282 BOOLEANS::~BOOLEANS() {
1283 }
1284 
NewNode()1285 SingleLinkNode * BOOLEANS::NewNode() {
1286     return new EnumNode( new SDAI_BOOLEAN );
1287 }
1288 
create_BOOLEANS()1289 BOOLEANS * create_BOOLEANS() {
1290     return new BOOLEANS ;
1291 }
1292 
1293 ///////////////////////////////////////////////////////////////////////////////
1294 // RealAggregate
1295 ///////////////////////////////////////////////////////////////////////////////
1296 
RealAggregate()1297 RealAggregate::RealAggregate() {
1298 }
1299 
~RealAggregate()1300 RealAggregate::~RealAggregate() {
1301 }
1302 
NewNode()1303 SingleLinkNode * RealAggregate::NewNode() {
1304     return new RealNode();
1305 }
1306 
1307 // COPY
ShallowCopy(const STEPaggregate & a)1308 STEPaggregate & RealAggregate::ShallowCopy( const STEPaggregate & a ) {
1309     const RealNode * tmp = ( const RealNode * ) a.GetHead();
1310     RealNode * to;
1311 
1312     while( tmp ) {
1313         to = ( RealNode * ) NewNode();
1314         to -> value = tmp -> value;
1315         AddNode( to );
1316         tmp = ( const RealNode * ) tmp -> NextNode();
1317     }
1318     if( head ) {
1319         _null = 0;
1320     } else {
1321         _null = 1;
1322     }
1323     return *this;
1324 }
1325 
1326 ///////////////////////////////////////////////////////////////////////////////
1327 // IntAggregate
1328 ///////////////////////////////////////////////////////////////////////////////
1329 
IntAggregate()1330 IntAggregate::IntAggregate() {
1331 }
1332 
~IntAggregate()1333 IntAggregate::~IntAggregate() {
1334 }
1335 
NewNode()1336 SingleLinkNode * IntAggregate::NewNode() {
1337     return new IntNode();
1338 }
1339 
1340 /// COPY
ShallowCopy(const STEPaggregate & a)1341 STEPaggregate & IntAggregate::ShallowCopy( const STEPaggregate & a ) {
1342     const IntNode * tmp = ( const IntNode * ) a.GetHead();
1343     IntNode * to;
1344 
1345     while( tmp ) {
1346         to = ( IntNode * ) NewNode();
1347         to -> value = tmp -> value;
1348         AddNode( to );
1349         tmp = ( const IntNode * ) tmp -> NextNode();
1350     }
1351     if( head ) {
1352         _null = 0;
1353     } else {
1354         _null = 1;
1355     }
1356     return *this;
1357 }
1358 
1359 ///////////////////////////////////////////////////////////////////////////////
1360 // RealNode
1361 ///////////////////////////////////////////////////////////////////////////////
1362 
RealNode()1363 RealNode::RealNode() {
1364     value = S_REAL_NULL;
1365 }
1366 
RealNode(SDAI_Real v)1367 RealNode::RealNode( SDAI_Real v) {
1368     value = v;
1369 }
1370 
~RealNode()1371 RealNode::~RealNode() {
1372 }
1373 
NewNode()1374 SingleLinkNode * RealNode::NewNode() {
1375     return new RealNode();
1376 }
1377 
StrToVal(const char * s,ErrorDescriptor * err)1378 Severity RealNode::StrToVal( const char * s, ErrorDescriptor * err ) {
1379     if( ReadReal( value, s, err, ",)" ) ) { // returns true if value is assigned
1380         _null = 0;
1381     } else {
1382         set_null();
1383         value = S_REAL_NULL;
1384     }
1385     return err->severity();
1386 }
1387 
StrToVal(istream & in,ErrorDescriptor * err)1388 Severity RealNode::StrToVal( istream & in, ErrorDescriptor * err ) {
1389     if( ReadReal( value, in, err, ",)" ) ) { // returns true if value is assigned
1390         _null = 0;
1391     } else {
1392         set_null();
1393         value = S_REAL_NULL;
1394     }
1395     return err->severity();
1396 }
1397 
STEPread(const char * s,ErrorDescriptor * err)1398 Severity RealNode::STEPread( const char * s, ErrorDescriptor * err ) {
1399     if( ReadReal( value, s, err, ",)" ) ) { // returns true if value is assigned
1400         _null = 0;
1401     } else {
1402         set_null();
1403         value = S_REAL_NULL;
1404     }
1405     return err->severity();
1406 }
1407 
STEPread(istream & in,ErrorDescriptor * err)1408 Severity RealNode::STEPread( istream & in, ErrorDescriptor * err ) {
1409     if( ReadReal( value, in, err, ",)" ) ) { // returns true if value is assigned
1410         _null = 0;
1411     } else {
1412         set_null();
1413         value = S_REAL_NULL;
1414     }
1415     return err->severity();
1416 }
1417 
asStr(std::string & s)1418 const char * RealNode::asStr( std::string & s ) {
1419     STEPwrite( s );
1420     return const_cast<char *>( s.c_str() );
1421 }
1422 
STEPwrite(std::string & s,const char *)1423 const char * RealNode::STEPwrite( std::string & s, const char * ) {
1424     if( value != S_REAL_NULL ) {
1425         s = WriteReal( value );
1426     } else {
1427         s.clear();
1428     }
1429     return s.c_str();
1430 }
1431 
STEPwrite(ostream & out)1432 void RealNode::STEPwrite( ostream & out ) {
1433     std::string s;
1434     out << STEPwrite( s );
1435 }
1436 
1437 ///////////////////////////////////////////////////////////////////////////////
1438 // IntNode
1439 ///////////////////////////////////////////////////////////////////////////////
1440 
IntNode()1441 IntNode::IntNode() {
1442     value = S_INT_NULL;
1443 }
1444 
IntNode(SDAI_Integer v)1445 IntNode::IntNode( SDAI_Integer v ) {
1446     value = v;
1447 }
1448 
~IntNode()1449 IntNode::~IntNode() {
1450 }
1451 
NewNode()1452 SingleLinkNode * IntNode::NewNode() {
1453     return new IntNode();
1454 }
1455 
StrToVal(const char * s,ErrorDescriptor * err)1456 Severity IntNode::StrToVal( const char * s, ErrorDescriptor * err ) {
1457     if( ReadInteger( value, s, err, ",)" ) ) { // returns true if value is assigned
1458         _null = 0;
1459     } else {
1460         set_null();
1461         value = S_INT_NULL;
1462     }
1463     return err->severity();
1464 }
1465 
StrToVal(istream & in,ErrorDescriptor * err)1466 Severity IntNode::StrToVal( istream & in, ErrorDescriptor * err ) {
1467     if( ReadInteger( value, in, err, ",)" ) ) { // returns true if value is assigned
1468         _null = 0;
1469     } else {
1470         set_null();
1471         value = S_INT_NULL;
1472     }
1473     return err->severity();
1474 }
1475 
STEPread(const char * s,ErrorDescriptor * err)1476 Severity IntNode::STEPread( const char * s, ErrorDescriptor * err ) {
1477     if( ReadInteger( value, s, err, ",)" ) ) { // returns true if value is assigned
1478         _null = 0;
1479     } else {
1480         set_null();
1481         value = S_INT_NULL;
1482     }
1483     return err->severity();
1484 }
1485 
STEPread(istream & in,ErrorDescriptor * err)1486 Severity IntNode::STEPread( istream & in, ErrorDescriptor * err ) {
1487     if( ReadInteger( value, in, err, ",)" ) ) { // returns true if value is assigned
1488         _null = 0;
1489     } else {
1490         set_null();
1491         value = S_INT_NULL;
1492     }
1493     return err->severity();
1494 }
1495 
asStr(std::string & s)1496 const char * IntNode::asStr( std::string & s ) {
1497     STEPwrite( s );
1498     return const_cast<char *>( s.c_str() );
1499 }
1500 
STEPwrite(std::string & s,const char *)1501 const char * IntNode::STEPwrite( std::string & s, const char * ) {
1502     char tmp[BUFSIZ];
1503     if( value != S_INT_NULL ) {
1504         sprintf( tmp, "%ld", value );
1505         s = tmp;
1506     } else {
1507         s.clear();
1508     }
1509     return const_cast<char *>( s.c_str() );
1510 }
1511 
STEPwrite(ostream & out)1512 void IntNode::STEPwrite( ostream & out ) {
1513     std::string s;
1514     out << STEPwrite( s );
1515 }
1516