-
Notifications
You must be signed in to change notification settings - Fork 131
Expand file tree
/
Copy pathclasses_type.c
More file actions
1414 lines (1227 loc) · 51.5 KB
/
classes_type.c
File metadata and controls
1414 lines (1227 loc) · 51.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/** *****************************************************************
** \file classes_type.c
** FedEx parser output module for generating C++ class definitions
**
** Development of FedEx was funded by the United States Government,
** and is not subject to copyright.
*******************************************************************
The conventions used in this binding follow the proposed specification
for the STEP Standard Data Access Interface as defined in document
N350 ( August 31, 1993 ) of ISO 10303 TC184/SC4/WG7.
*******************************************************************/
/* this is used to add new dictionary calls */
/* #define NEWDICT */
#define _XOPEN_SOURCE /* for S_IFDIR */
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#ifdef _WIN32
# include <direct.h>
#endif /* _WIN32 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "classes.h"
#include "class_strings.h"
#include "genCxxFilenames.h"
#include <ordered_attrs.h>
#include "rules.h"
#include "./trace_fprintf.h"
static int type_count; /**< number each temporary type for same reason as \sa attr_count */
extern char * non_unique_types_string( const Type type );
static void printEnumCreateHdr( FILE *, const Type );
static void printEnumCreateBody( FILE *, const Type );
static void printEnumAggrCrHdr( FILE *, const Type );
static void printEnumAggrCrBody( FILE *, const Type );
int TYPEget_RefTypeVarNm( const Type t, char * buf, size_t buflen, Schema schema );
int isMultiDimAggregateType( const Type t );
void Type_Description( const Type, char * );
void TypeBody_Description( TypeBody body, char * buf );
/* cross-platform mkdir */
static int sc_mkdir( const char * path ) {
#ifdef _WIN32
return mkdir( path );
#else
return mkdir( path, 0777 );
#endif /* _WIN32 */
}
/* return -1 if error, 0 if created, 1 if dir existed already */
static int mkDirIfNone( const char * path ) {
struct stat s;
if( stat( path, &s ) != 0 ) {
if( errno == ENOENT ) {
return sc_mkdir( path );
}
} else if( s.st_mode & S_IFDIR ) {
return 1;
}
/* either stat returned an error other than ENOENT, or 'path' exists but isn't a dir */
return -1;
}
#ifdef _WIN32
/* for windows, rewrite backslashes in paths
* that will be written to generated code
*/
static const char * path2str_fn( const char * fileMacro ) {
static char * result = 0;
static size_t rlen = 0;
char * p;
if( rlen < strlen( fileMacro ) ) {
if( result ) {
free( result );
}
rlen = strlen( fileMacro );
result = ( char * )malloc( rlen * sizeof( char ) + 1 );
}
strcpy( result, fileMacro );
p = result;
while( *p ) {
if( *p == '\\' ) {
*p = '/';
}
p++;
}
return result;
}
# define path2str(path) path2str_fn(path)
#else
# define path2str(path) path
#endif
/** write representation of expression to end of buf
*
* TODO: add buflen arg and check for overflow
*/
void strcat_expr( Expression e, char * buf ) {
if( e == LITERAL_INFINITY ) {
strcat( buf, "?" );
} else if( e == LITERAL_PI ) {
strcat( buf, "PI" );
} else if( e == LITERAL_E ) {
strcat( buf, "E" );
} else if( e == LITERAL_ZERO ) {
strcat( buf, "0" );
} else if( e == LITERAL_ONE ) {
strcat( buf, "1" );
} else if( TYPEget_name( e ) ) {
strcat( buf, TYPEget_name( e ) );
} else if( TYPEget_body( e->type )->type == integer_ ) {
char tmpbuf[30];
snprintf( tmpbuf, sizeof(tmpbuf), "%d", e->u.integer );
strcat( buf, tmpbuf );
} else {
strcat( buf, "??" );
}
}
/** print t's bounds to end of buf
*
* TODO: add buflen arg and check for overflow
*/
void strcat_bounds( TypeBody b, char * buf ) {
if( !b->upper ) {
return;
}
strcat( buf, " [" );
strcat_expr( b->lower, buf );
strcat( buf, ":" );
strcat_expr( b->upper, buf );
strcat( buf, "]" );
}
/******************************************************************
** Procedure: TYPEprint_enum
** Parameters: const Type type - type to print
** FILE* f - file on which to print
** Returns:
** Requires: TYPEget_class(type) == TYPE_ENUM
** Description: prints code to represent an enumerated type in c++
** Side Effects: prints to header file
** Status: ok 1/15/91
** Changes: Modified to check for appropriate key words as described
** in "SDAI C++ Binding for PDES, Inc. Prototyping" by
** Stephen Clark.
** - Changed to match CD2 Part 23, 1/14/97 DAS
** Change Date: 5/22/91 CD
******************************************************************/
const char * EnumCElementName( Type type, Expression expr ) {
static char buf [BUFSIZ+1];
snprintf( buf, sizeof(buf), "%s__",
EnumName( TYPEget_name( type ) ) );
strncat( buf, StrToLower( EXPget_name( expr ) ), BUFSIZ );
return buf;
}
char * CheckEnumSymbol( char * s ) {
static char b [BUFSIZ+1];
if( strcmp( s, "sdaiTRUE" )
&& strcmp( s, "sdaiFALSE" )
&& strcmp( s, "sdaiUNKNOWN" ) ) {
/* if the symbol is not a reserved one */
return ( s );
} else {
strcpy( b, s );
strcat( b, "_" );
fprintf( stderr, "Warning in %s: the enumerated value %s is already being used and has been changed to %s\n", __func__, s, b );
return ( b );
}
}
/**
* return printable version of entire type definition
* return it in static buffer
*/
char * TypeDescription( const Type t ) {
static char buf[6000];
buf[0] = '\0';
if( TYPEget_head( t ) ) {
Type_Description( TYPEget_head( t ), buf );
} else {
TypeBody_Description( TYPEget_body( t ), buf );
}
/* should also print out where clause here */
return buf + 1;
}
/**************************************************************//**
** Procedure: TYPEenum_inc_print
** Description: Writes enum type descriptors and classes.
** Change Date:
********************************************************************/
void TYPEenum_inc_print( const Type type, FILE * inc ) {
Expression expr;
char tdnm[BUFSIZ+1],
enumAggrNm[BUFSIZ+1];
const char * n; /* pointer to class name */
int cnt = 0;
/* print c++ enumerated values for class */
fprintf( inc, "enum %s {\n", EnumName( TYPEget_name( type ) ) );
LISTdo_links( TYPEget_body( type )->list, link )
/* print the elements of the c++ enum type */
expr = ( Expression )link->data;
if( cnt != 0 ) {
fprintf( inc, ",\n" );
}
++cnt;
fprintf( inc, " %s", EnumCElementName( type, expr ) );
LISTod
fprintf( inc, ",\n %s_unset\n};\n", EnumName( TYPEget_name( type ) ) );
/* print class for enumeration */
n = TYPEget_ctype( type );
fprintf( inc, "\nclass SC_SCHEMA_EXPORT %s : public SDAI_Enum {\n", n );
fprintf( inc, " protected:\n EnumTypeDescriptor *type;\n\n" );
/* constructors */
strncpy( tdnm, TYPEtd_name( type ), BUFSIZ );
tdnm[BUFSIZ - 1] = '\0';
fprintf( inc, " public:\n %s (const char * n =0, EnumTypeDescriptor *et =%s);\n", n, tdnm );
fprintf( inc, " %s (%s e, EnumTypeDescriptor *et =%s)\n"
" : type(et) { set_value (e); }\n",
n, EnumName( TYPEget_name( type ) ), tdnm );
fprintf( inc, " %s (const %s &e) { set_value(e); }\n", n, TYPEget_ctype( type ) );
/* destructor */
fprintf( inc, " ~%s () { }\n", n );
/* operator = */
fprintf( inc, " %s& operator= (const %s& e)\n",
n, TYPEget_ctype( type ) );
fprintf( inc, " { set_value (e); return *this; }\n" );
/* operator to cast to an enumerated type */
fprintf( inc, " operator %s () const;\n",
EnumName( TYPEget_name( type ) ) );
/* others */
fprintf( inc, "\n inline virtual const char * Name () const\n" );
fprintf( inc, " { return type->Name(); }\n" );
fprintf( inc, " inline virtual int no_elements () const"
" { return %d; }\n", cnt );
fprintf( inc, " virtual const char * element_at (int n) const;\n" );
/* end class definition */
fprintf( inc, "};\n" );
fprintf( inc, "\ntypedef %s * %s_ptr;\n", n, n );
fprintf( inc, "\ntypedef const %s * %s_ptr_c;\n", n, n );
/* Print ObjectStore Access Hook function */
printEnumCreateHdr( inc, type );
/* DAS brandnew above */
/* print things for aggregate class */
snprintf( enumAggrNm, sizeof(enumAggrNm), "%s_agg", n );
fprintf( inc, "\nclass %s_agg : public EnumAggregate {\n", n );
fprintf( inc, " protected:\n EnumTypeDescriptor *enum_type;\n\n" );
fprintf( inc, " public:\n" );
fprintf( inc, " %s_agg( EnumTypeDescriptor * =%s);\n", n, tdnm );
fprintf( inc, " virtual ~%s_agg();\n", n );
fprintf( inc, " virtual SingleLinkNode * NewNode()\n" );
fprintf( inc, " { return new EnumNode (new %s( \"\", enum_type )); }"
"\n", n );
fprintf( inc, "};\n" );
fprintf( inc, "\ntypedef %s_agg * %s_agg_ptr;\n", n, n );
fprintf( inc, "\ntypedef const %s_agg * %s_agg_ptr_c;\n", n, n );
/* DAS brandnew below */
/* DAS creation function for enum aggregate class */
printEnumAggrCrHdr( inc, type );
/* DAS brandnew above */
}
void TYPEenum_lib_print( const Type type, FILE * f ) {
DictionaryEntry de;
Expression expr;
const char * n; /* pointer to class name */
char c_enum_ele [BUFSIZ+1];
n = TYPEget_ctype( type );
/* set up the dictionary info */
fprintf( f, "const char *\n%s::element_at (int n) const {\n", n );
fprintf( f, " switch (n) {\n" );
DICTdo_type_init( ENUM_TYPEget_items( type ), &de, OBJ_ENUM );
while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
strncpy( c_enum_ele, EnumCElementName( type, expr ), BUFSIZ );
c_enum_ele[BUFSIZ-1] = '\0';
fprintf( f, " case %s: return \"%s\";\n",
c_enum_ele,
StrToUpper( EXPget_name( expr ) ) );
}
fprintf( f, " case %s_unset :\n", EnumName( TYPEget_name( type ) ) );
fprintf( f, " default : return \"UNSET\";\n }\n}\n" );
/* constructors */
/* construct with character string */
fprintf( f, "\n%s::%s (const char * n, EnumTypeDescriptor *et)\n"
" : type(et)\n{\n", n, n );
fprintf( f, " set_value (n);\n}\n" );
/* cast operator to an enumerated type */
fprintf( f, "\n%s::operator %s () const {\n", n,
EnumName( TYPEget_name( type ) ) );
fprintf( f, " switch (v) {\n" );
DICTdo_type_init( ENUM_TYPEget_items( type ), &de, OBJ_ENUM );
while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
strncpy( c_enum_ele, EnumCElementName( type, expr ), BUFSIZ );
fprintf( f, " case %s : ", c_enum_ele );
fprintf( f, "return %s;\n", c_enum_ele );
}
/* print the last case with the default so sun c++ doesn't complain */
fprintf( f, " case %s_unset :\n", EnumName( TYPEget_name( type ) ) );
fprintf( f, " default : return %s_unset;\n }\n}\n", EnumName( TYPEget_name( type ) ) );
printEnumCreateBody( f, type );
/* print the enum aggregate functions */
fprintf( f, "\n%s_agg::%s_agg( EnumTypeDescriptor *et )\n", n, n );
fprintf( f, " : enum_type(et)\n{\n}\n\n" );
fprintf( f, "%s_agg::~%s_agg()\n{\n}\n", n, n );
printEnumAggrCrBody( f, type );
}
void TYPEPrint_h( const Type type, FILE * file ) {
DEBUG( "Entering TYPEPrint_h for %s\n", TYPEget_ctype( type ) );
if ( TYPEis_enumeration( type ) ) {
TYPEenum_inc_print( type, file );
} else if ( TYPEis_select( type ) ) {
TYPEselect_inc_print( type, file );
}
fprintf( file, "void init_%s(Registry& reg);\n\n", TYPEget_ctype( type ) );
DEBUG( "DONE TYPEPrint_h\n" );
}
void TYPEPrint_cc( const Type type, const filenames_t * names, FILE * hdr, FILE * impl, Schema schema ) {
DEBUG( "Entering TYPEPrint_cc for %s\n", names->impl );
fprintf( impl, "#include \"schema.h\"\n" );
fprintf( impl, "#include \"%s\"\n\n", names->header );
if ( TYPEis_enumeration( type ) ) {
TYPEenum_lib_print( type, impl );
} else if ( TYPEis_select( type ) ) {
TYPEselect_lib_print( type, impl );
}
fprintf( impl, "\nvoid init_%s( Registry& reg ) {\n", TYPEget_ctype( type ) );
fprintf( impl, " std::string str;\n" );
/* moved from SCOPEPrint in classes_wrapper */
TYPEprint_new( type, impl, schema, true );
TYPEprint_init( type, hdr, impl, schema );
fprintf( impl, "}\n\n" );
DEBUG( "DONE TYPEPrint_cc\n" );
}
void TYPEPrint( const Type type, FILES *files, Schema schema ) {
FILE * hdr, * impl;
filenames_t names = getTypeFilenames( type );
fprintf( files->inc, "#include \"%s\"\n", names.header );
fprintf( files->init, " init_%s( reg );\n", TYPEget_ctype( type ) );
if( mkDirIfNone( "type" ) == -1 ) {
fprintf( stderr, "At %s:%d - mkdir() failed with error ", __FILE__, __LINE__);
perror( 0 );
abort();
}
hdr = FILEcreate( names.header );
impl = FILEcreate( names.impl );
assert( hdr && impl && "error creating files" );
fprintf( files->unity.type.hdr, "#include \"%s\"\n", names.header );
fprintf( files->unity.type.impl, "#include \"%s\"\n", names.impl );
TYPEPrint_h( type, hdr );
TYPEPrint_cc( type, &names, hdr, impl, schema );
FILEclose( hdr );
FILEclose( impl );
}
/**
* Prints a bunch of lines for enumeration creation functions (i.e., "cre-
* ate_SdaiEnum1()"). Since this is done both for an enum and for "copies"
* of it (when "TYPE enum2 = enum1"), I placed this code in a separate fn.
*
* NOTE - "Print ObjectStore Access Hook function" comment seen at one of
* the calls seems to imply it's ObjectStore specific...
*/
static void printEnumCreateHdr( FILE * inc, const Type type ) {
const char * nm = TYPEget_ctype( type );
fprintf( inc, " SDAI_Enum * create_%s();\n", nm );
}
/** See header comment above by printEnumCreateHdr. */
static void printEnumCreateBody( FILE * lib, const Type type ) {
const char * nm = TYPEget_ctype( type );
char tdnm[BUFSIZ+1];
tdnm[BUFSIZ-1] = '\0';
strncpy( tdnm, TYPEtd_name( type ), BUFSIZ );
tdnm[BUFSIZ-1] = '\0';
fprintf( lib, "\nSDAI_Enum *\ncreate_%s ()\n{\n", nm );
fprintf( lib, " return new %s( \"\", %s );\n}\n\n", nm, tdnm );
}
/** Similar to printEnumCreateHdr above for the enum aggregate. */
static void printEnumAggrCrHdr( FILE * inc, const Type type ) {
const char * n = TYPEget_ctype( type );
/* const char *n = ClassName( TYPEget_name(type) ));*/
fprintf( inc, " STEPaggregate * create_%s_agg ();\n", n );
}
static void printEnumAggrCrBody( FILE * lib, const Type type ) {
const char * n = TYPEget_ctype( type );
char tdnm[BUFSIZ+1];
strncpy( tdnm, TYPEtd_name( type ), BUFSIZ );
tdnm[BUFSIZ-1] = '\0';
fprintf( lib, "\nSTEPaggregate *\ncreate_%s_agg ()\n{\n", n );
fprintf( lib, " return new %s_agg( %s );\n}\n", n, tdnm );
}
/** ************************************************************************
** Procedure: TYPEprint_typedefs
** Parameters: const Type type
** Returns:
** Description:
** Prints in Sdaiclasses.h typedefs, forward declarations, and externs
** for user-defined types. Only a fraction of the typedefs and decla-
** rations are needed in Sdaiclasses.h. Enum's and selects must actu-
** ally be defined before objects (such as entities) which use it can
** be defined. So forward declarations will not serve any purpose.
** Other redefined types and aggregate types may be declared here.
** Side Effects:
** Status: 16-Mar-1993 kcm; updated 04-Feb-1997 dar
** Dec 2011 - MAP - remove goto
**************************************************************************/
void TYPEprint_typedefs( Type t, FILE * classes ) {
char nm [BUFSIZ+1];
Type i;
bool aggrNot1d = true; /* added so I can get rid of a goto */
/* Print the typedef statement (poss also a forward class def: */
if( TYPEis_enumeration( t ) ) {
/* For enums and sels (else clause below), we need forward decl's so
that if we later come across a type which is an aggregate of one of
them, we'll be able to process it. For selects, we also need a decl
of the class itself, while for enum's we don't. Objects which con-
tain an enum can't be generated until the enum is generated. (The
same is basically true for the select, but a sel containing an ent
containing a sel needs the forward decl (trust me ;-) ).
*/
if( !TYPEget_head( t ) ) {
/* Only print this enum if it is an actual type and not a redefi-
nition of another enum. (Those are printed at the end of the
classes file - after all the actual enum's. They must be
printed last since they depend on the others.)
*/
strncpy( nm, TYPEget_ctype( t ), BUFSIZ );
nm[BUFSIZ-1] = '\0';
fprintf( classes, "class %s_agg;\n", nm );
}
} else if( TYPEis_select( t ) ) {
if( !TYPEget_head( t ) ) {
/* Same comment as above. */
strncpy( nm, SelectName( TYPEget_name( t ) ), BUFSIZ );
nm[BUFSIZ-1] = '\0';
fprintf( classes, "class %s;\n", nm );
fprintf( classes, "typedef %s * %s_ptr;\n", nm, nm );
fprintf( classes, "typedef const %s * %s_ptr_c;\n", nm, nm );
fprintf( classes, "class %s_agg;\n", nm );
fprintf( classes, "typedef %s_agg * %s_agg_ptr;\n", nm, nm );
fprintf( classes, "typedef const %s_agg * %s_agg_ptr_c;\n", nm, nm );
}
} else {
if( TYPEis_aggregate( t ) ) {
i = TYPEget_base_type( t );
if( TYPEis_enumeration( i ) || TYPEis_select( i ) ) {
/* One exceptional case - a 1d aggregate of an enum or select.
We must wait till the enum/sel itself has been processed.
To ensure this, we process all such 1d aggrs in a special
loop at the end (in multpass.c). 2d aggrs (or higher), how-
ever, can be processed now - they only require GenericAggr
for their definition here.
*/
aggrNot1d = false;
}
}
if( aggrNot1d ) {
/* At this point, we'll print typedefs for types which are redefined
fundamental types and their aggregates, and for 2D aggregates(aggre-
gates of aggregates) of enum's and selects.
*/
strncpy( nm, ClassName( TYPEget_name( t ) ), BUFSIZ );
nm[BUFSIZ-1] = '\0';
fprintf( classes, "typedef %s %s;\n", TYPEget_ctype( t ), nm );
if( TYPEis_aggregate( t ) ) {
fprintf( classes, "typedef %s * %sH;\n", nm, nm );
fprintf( classes, "typedef %s * %s_ptr;\n", nm, nm );
fprintf( classes, "typedef const %s * %s_ptr_c;\n", nm, nm );
fprintf( classes, "typedef %s_ptr %s_var;\n", nm, nm );
}
}
}
/* Print the extern statement: */
strncpy( nm, TYPEtd_name( t ), BUFSIZ );
fprintf( classes, "extern SC_SCHEMA_EXPORT %s *%s;\n", GetTypeDescriptorName( t ), nm );
}
/** **
print stuff for types that are declared in Express TYPE statements... i.e.
extern descriptor declaration in .h file - MOVED BY DAR to TYPEprint_type-
defs - in order to print all the Sdaiclasses.h stuff in exp2cxx's
first pass through each schema.
descriptor definition in the .cc file
initialize it in the .init.cc file (DAR - all initialization done in fn
TYPEprint_init() (below) which is done in exp2cxx's 1st pass only.)
*****/
void TYPEprint_descriptions( const Type type, FILES * files, Schema schema ) {
char tdnm [BUFSIZ+1],
typename_buf [MAX_LEN+1],
base [BUFSIZ+1],
nm [BUFSIZ+1];
Type i;
strncpy( tdnm, TYPEtd_name( type ), BUFSIZ );
tdnm[BUFSIZ-1] = '\0';
/* define type descriptor pointer */
/* in source - declare the real definition of the pointer */
/* i.e. in the .cc file */
fprintf( files -> lib, "%s *%s;\n", GetTypeDescriptorName( type ), tdnm );
if( isAggregateType( type ) ) {
const char * ctype = TYPEget_ctype( type );
fprintf( files->inc, "STEPaggregate * create_%s ();\n\n",
ClassName( TYPEget_name( type ) ) );
fprintf( files->lib,
"STEPaggregate *\ncreate_%s () { return create_%s(); }\n",
ClassName( TYPEget_name( type ) ), ctype );
/* this function is assigned to the aggrCreator var in TYPEprint_new */
}
if( TYPEis_enumeration( type ) && ( i = TYPEget_ancestor( type ) ) != NULL ) {
/* If we're a renamed enum type, just print a few typedef's to the
* original and some specialized create functions:
*/
strncpy( base, EnumName( TYPEget_name( i ) ), BUFSIZ );
strncpy( nm, EnumName( TYPEget_name( type ) ), BUFSIZ );
fprintf( files->inc, "typedef %s %s;\n", base, nm );
strncpy( base, TYPEget_ctype( i ), BUFSIZ );
strncpy( nm, TYPEget_ctype( type ), BUFSIZ );
fprintf( files->inc, "typedef %s %s;\n", base, nm );
printEnumCreateHdr( files->inc, type );
printEnumCreateBody( files->lib, type );
fprintf( files->inc, "typedef %s_agg * %s_agg_ptr;\n", nm, nm );
fprintf( files->inc, "typedef const %s_agg * %s_agg_ptr_c;\n", nm, nm );
printEnumAggrCrHdr( files->inc, type );
printEnumAggrCrBody( files->lib, type );
return;
}
if( !TYPEget_RefTypeVarNm( type, typename_buf, sizeof(typename_buf), schema ) ) {
if( TYPEis_enumeration( type ) ) {
TYPEPrint( type, files, schema );
} /* so we don't do anything for non-enums??? */
} else {
TYPEprint_new( type, files->create, schema, false );
TYPEprint_init( type, files->inc, files->init, schema );
}
}
void TYPEprint_init( const Type type, FILE * header, FILE * impl, Schema schema ) {
char tdnm [BUFSIZ+1];
char typename_buf[MAX_LEN+1];
strncpy( tdnm, TYPEtd_name( type ), BUFSIZ );
if( isAggregateType( type ) ) {
AGGRprint_init( header, impl, type, tdnm, type->symbol.name );
}
/* fill in the TD's values in the SchemaInit function (it is already
declared with basic values) */
if( TYPEget_RefTypeVarNm( type, typename_buf, sizeof(typename_buf), schema ) ) {
fprintf( impl, " %s->ReferentType(%s);\n", tdnm, typename_buf );
} else {
switch( TYPEget_body( type )->type ) {
case aggregate_: /* aggregate_ should not happen? DAS */
case array_:
case bag_:
case set_:
case list_: {
if( isMultiDimAggregateType( type ) ) {
print_typechain( header, impl, TYPEget_body( type )->base,
typename_buf, sizeof(typename_buf), schema, type->symbol.name );
fprintf( impl, " %s->ReferentType(%s);\n", tdnm,
typename_buf );
}
break;
}
default:
break;
}
}
/* DAR - moved fn call below from TYPEselect_print to here to put all init
** info together. */
if( TYPEis_select( type ) ) {
TYPEselect_init_print( type, impl );
}
#ifdef NEWDICT
/* DAS New SDAI Dictionary 5/95 */
/* insert the type into the schema descriptor */
fprintf( impl,
" ((SDAIAGGRH(Set,DefinedTypeH))%s::schema->Types())->Add((DefinedTypeH)%s);\n",
SCHEMAget_name( schema ), tdnm );
#endif
/* insert into type dictionary */
fprintf( impl, " reg.AddType (*%s);\n", tdnm );
}
/** print name, fundamental type, and description initialization function calls */
void TYPEprint_nm_ft_desc( Schema schema, const Type type, FILE * f, char * endChars ) {
fprintf( f, " \"%s\", // Name\n", PrettyTmpName( TYPEget_name( type ) ) );
fprintf( f, " %s, // FundamentalType\n", FundamentalType( type, 1 ) );
fprintf( f, " %s::schema, // Originating Schema\n", SCHEMAget_name( schema ) );
fprintf( f, " \"%s\"%s // Description\n", TypeDescription( type ), endChars );
}
/** new space for a variable of type TypeDescriptor (or subtype). This
* function is called for Types that have an Express name.
*/
void TYPEprint_new( const Type type, FILE * create, Schema schema, bool needWR ) {
Type tmpType = TYPEget_head( type );
Type bodyType = tmpType;
/* define type definition */
/* in source - the real definition of the TypeDescriptor */
if( TYPEis_select( type ) ) {
char * temp;
temp = non_unique_types_string( type );
fprintf( create, " %s = new SelectTypeDescriptor (\n ~%s, //unique elements,\n", TYPEtd_name( type ), temp );
free( temp );
TYPEprint_nm_ft_desc( schema, type, create, "," );
fprintf( create, " (SelectCreator) create_%s); // Creator function\n", SelectName( TYPEget_name( type ) ) );
} else {
switch( TYPEget_body( type )->type ) {
case boolean_:
fprintf( create, " %s = new EnumTypeDescriptor (\n", TYPEtd_name( type ) );
TYPEprint_nm_ft_desc( schema, type, create, "," );
fprintf( create, " (EnumCreator) create_BOOLEAN); // Creator function\n" );
break;
case logical_:
fprintf( create, " %s = new EnumTypeDescriptor (\n", TYPEtd_name( type ) );
TYPEprint_nm_ft_desc( schema, type, create, "," );
fprintf( create, " (EnumCreator) create_LOGICAL); // Creator function\n" );
break;
case enumeration_:
fprintf( create, " %s = new EnumTypeDescriptor (\n", TYPEtd_name( type ) );
TYPEprint_nm_ft_desc( schema, type, create, "," );
/* get the type name of the underlying type - it is the type that needs to get created */
tmpType = TYPEget_head( type );
if( tmpType ) {
bodyType = tmpType;
while( tmpType ) {
bodyType = tmpType;
tmpType = TYPEget_head( tmpType );
}
fprintf( create, " (EnumCreator) create_%s); // Creator function\n", TYPEget_ctype( bodyType ) );
} else {
fprintf( create, " (EnumCreator) create_%s); // Creator function\n", TYPEget_ctype( type ) );
}
break;
case aggregate_:
case array_:
case bag_:
case set_:
case list_:
fprintf( create, "\n %s = new %s (\n", TYPEtd_name( type ), GetTypeDescriptorName( type ) );
TYPEprint_nm_ft_desc( schema, type, create, "," );
fprintf( create, " (AggregateCreator) create_%s); // Creator function\n\n", ClassName( TYPEget_name( type ) ) );
break;
default:
fprintf( create, " %s = new TypeDescriptor (\n", TYPEtd_name( type ) );
TYPEprint_nm_ft_desc( schema, type, create, ");" );
break;
}
}
/* add the type to the Schema dictionary entry */
fprintf( create, " %s::schema->AddType(%s);\n", SCHEMAget_name( schema ), TYPEtd_name( type ) );
WHEREprint( TYPEtd_name( type ), type->where, create, 0, needWR );
}
/** Get the TypeDescriptor variable name that t's TypeDescriptor references (if
possible).
pass space in through buf, buff will be filled in with the name of the
TypeDescriptor (TD) that needs to be referenced by the TD that is
generated for Type t. Return 1 if buf has been filled in with the name
of a TD. Return 0 if it hasn't for these reasons: Enumeration TDs don't
reference another TD, select TDs reference several TDs and are handled
separately, Multidimensional aggregates generate unique intermediate TD
variables that are referenced - when these don't have an Express related
name this function can't know about them - e.g.
TYPE listSetAggr = LIST OF SET OF STRING; This function won't fill in the
name that listSetAggr's ListTypeDescriptor will reference.
TYPE arrListSetAggr = ARRAY [1:4] of listSetAggr; This function will
return the name of the TD that arrlistSetAggr's ArrayTypeDescriptor should
reference since it has an Express name associated with it.
*
Nov 2011 - MAP - modified to insert scope operator into variable name.
Reason: use of namespace for global variables
*/
int TYPEget_RefTypeVarNm( const Type t, char * buf, size_t buflen, Schema schema ) {
if (!buf || !buflen)
return 0;
/* It looks like TYPEget_head(t) is true when processing a type
that refers to another type. e.g. when processing "name" in:
TYPE name = label; ENDTYPE; TYPE label = STRING; ENDTYPE; DAS */
if( TYPEget_head( t ) ) {
/* this means that it is defined in an Express TYPE stmt and
it refers to another Express TYPE stmt */
/* it would be a reference_ type */
/* a TypeDescriptor of the form <schema_name>t_<type_name_referred_to> */
snprintf( buf, buflen, "%s::%s%s",
SCHEMAget_name( TYPEget_head( t )->superscope ),
TYPEprefix( t ), TYPEget_name( TYPEget_head( t ) ) );
return 1;
} else {
switch( TYPEget_body( t )->type ) {
case integer_:
case real_:
case boolean_:
case logical_:
case string_:
case binary_:
case number_:
/* one of the SCL builtin TypeDescriptors of the form
t_STRING_TYPE, or t_REAL_TYPE */
snprintf( buf, buflen, "%s%s", TD_PREFIX, FundamentalType( t, 0 ) );
return 1;
break;
case enumeration_: /* enums don't have a referent type */
case select_: /* selects are handled differently elsewhere, they
refer to several TypeDescriptors */
return 0;
break;
case entity_:
snprintf( buf, buflen, "%s", TYPEtd_name( t ) );
/* following assumes we are not in a nested entity */
/* otherwise we should search upward for schema */
return 1;
break;
case aggregate_:
case array_:
case bag_:
case set_:
case list_:
/* referent TypeDescriptor will be the one for the element unless it
is a multidimensional aggregate then return 0 */
if( isMultiDimAggregateType( t ) ) {
if( TYPEget_name( TYPEget_body( t )->base ) ) {
snprintf( buf, buflen, "%s::%s%s",
SCHEMAget_name( TYPEget_body( t )->base->superscope ),
TYPEprefix( t ), TYPEget_name( TYPEget_body( t )->base ) );
return 1;
}
/* if the multi aggr doesn't have a name then we are out of scope
of what this function can do */
return 0;
} else {
/* for a single dimensional aggregate return TypeDescriptor
for element */
/* being an aggregate implies that base below is not 0 */
if( TYPEget_body( TYPEget_body( t )->base )->type == enumeration_ ||
TYPEget_body( TYPEget_body( t )->base )->type == select_ ) {
snprintf( buf, buflen, "%s", TYPEtd_name( TYPEget_body( t )->base ) );
return 1;
} else if( TYPEget_name( TYPEget_body( t )->base ) ) {
if( TYPEget_body( TYPEget_body( t )->base )->type == entity_ ) {
snprintf( buf, buflen, "%s", TYPEtd_name( TYPEget_body( t )->base ) );
return 1;
}
snprintf( buf, buflen, "%s::%s%s",
SCHEMAget_name( TYPEget_body( t )->base->superscope ),
TYPEprefix( t ), TYPEget_name( TYPEget_body( t )->base ) );
return 1;
}
return TYPEget_RefTypeVarNm( TYPEget_body( t )->base, buf, buflen, schema );
}
break;
default:
return 0;
}
}
/* NOTREACHED */
return 0;
}
/** go down through a type's base type chain,
make and print new TypeDescriptors for each type with no name.
This function should only be called for types that don't have an
associated Express name. Currently this only includes aggregates.
If this changes this function needs to be changed to support the type
that changed. This function prints TypeDescriptors for types
without names and it will go down through the type chain until it hits
a type that has a name. i.e. when it hits a type with a name it stops.
There are only two places where a type can not have a name - both
cases are aggregate types.
1. an aggregate created in an attr declaration
e.g. names : ARRAY [1:3] of STRING;
2. an aggregate that is an element of another aggregate.
e.g. TYPE Label = STRING; END_TYPE;
TYPE listSetOfLabel = LIST of SET of Label; END_TYPE;
LIST of SET of Label has a name i.e. listSetOfReal
SET of Label does not have a name and this function should be called
to generate one.
This function will not generate the code to handle Label.
Type t contains the Type with no Express name that needs to have
TypeDecriptor[s] generated for it.
buf needs to have space declared enough to hold the name of the var
that can be referenced to refer to the type that was created for
Type t.
*/
void print_typechain( FILE * header, FILE * impl, const Type t, char * buf, size_t buflen, Schema schema, const char * type_name ) {
/* if we've been called, current type has no name */
/* nor is it a built-in type */
/* the type_count variable is there for debugging purposes */
const char * ctype = TYPEget_ctype( t );
int count = type_count++;
char name_buf[MAX_LEN+1];
int s;
switch( TYPEget_body( t )->type ) {
case aggregate_:
case array_:
case bag_:
case set_:
case list_:
/* create a new TypeDescriptor variable, e.g. t1, and new space for it */
fprintf( impl, " %s * %s%d = new %s;\n",
GetTypeDescriptorName( t ), TD_PREFIX, count,
GetTypeDescriptorName( t ) );
fprintf( impl,
" %s%d->AssignAggrCreator((AggregateCreator) create_%s);%s",
TD_PREFIX, count, ctype, " // Creator function\n" );
s = snprintf( name_buf, sizeof(name_buf), "%s%d", TD_PREFIX, count );
assert( ( s > 0 ) && ( s < MAX_LEN ) );
AGGRprint_init( header, impl, t, name_buf, type_name );
break;
default: /* this should not happen since only aggregates are allowed to
not have a name. This funct should only be called for aggrs
without names. */
fprintf( impl, " TypeDescriptor * %s%d = new TypeDescriptor;\n",
TD_PREFIX, count );
}
/* there is no name so name doesn't need to be initialized */
fprintf( impl, " %s%d->FundamentalType(%s);\n", TD_PREFIX, count,
FundamentalType( t, 1 ) );
fprintf( impl, " %s%d->Description(\"%s\");\n", TD_PREFIX, count,
TypeDescription( t ) );
/* DAS ORIG SCHEMA FIX */
fprintf( impl, " %s%d->OriginatingSchema(%s::schema);\n", TD_PREFIX, count, SCHEMAget_name( schema ) );
if( TYPEget_RefTypeVarNm( t, name_buf, sizeof(name_buf), schema ) ) {
fprintf( impl, " %s%d->ReferentType(%s);\n", TD_PREFIX, count, name_buf );
} else {
Type base = 0;
/* no name, recurse */
char callee_buffer[MAX_LEN+1];
if( TYPEget_body( t ) ) {
base = TYPEget_body( t )->base;
}
print_typechain( header, impl, base, callee_buffer, sizeof(callee_buffer), schema, type_name );
fprintf( impl, " %s%d->ReferentType(%s);\n", TD_PREFIX, count, callee_buffer );
}
snprintf( buf, buflen, "%s%d", TD_PREFIX, count );
/* Types */
fprintf( impl, " %s::schema->AddUnnamedType(%s%d);\n", SCHEMAget_name( schema ), TD_PREFIX, count );
}
/** return 1 if it is a multidimensional aggregate at the level passed in
otherwise return 0; If it refers to a type that is a multidimensional
aggregate 0 is still returned. */
int isMultiDimAggregateType( const Type t ) {
if( TYPEget_body( t )->base )
if( isAggregateType( TYPEget_body( t )->base ) ) {
return 1;
}
return 0;
}
void Type_Description( const Type t, char * buf ) {
if( TYPEget_name( t ) ) {
strcat( buf, " " );
strcat( buf, TYPEget_name( t ) );
} else {
TypeBody_Description( TYPEget_body( t ), buf );
}
}
void TypeBody_Description( TypeBody body, char * buf ) {
char * s;
switch( body->type ) {
case integer_:
strcat( buf, " INTEGER" );
break;
case real_:
strcat( buf, " REAL" );
break;
case string_:
strcat( buf, " STRING" );
break;
case binary_:
strcat( buf, " BINARY" );
break;
case boolean_:
strcat( buf, " BOOLEAN" );
break;
case logical_:
strcat( buf, " LOGICAL" );
break;
case number_:
strcat( buf, " NUMBER" );
break;
case entity_: