Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
#include "config.h"
32
#include "calculus.h"
33
#include "code.h"
34
#include "error.h"
35
#include "common.h"
36
#include "lex.h"
37
#include "output.h"
38
#include "suffix.h"
39
#include "type_ops.h"
40
 
41
 
42
/*
43
    OUTPUT FLAGS
44
 
45
    The flag extra_asserts, if set to true, will cause the C implementation
46
    of the output to include assertions for run-time checks.  check_null is
47
    a string used in the assertions output.  extra_headers and map_proto
48
    are used for backwards compatibility on extra headers and union map
49
    prototypes.
50
*/
51
 
52
int extra_asserts = 0 ;
53
int extra_headers = 0 ;
54
int map_proto = 1 ;
55
static char *check_null ;
56
 
57
 
58
/*
59
    PRINT AN ASSIGNMENT COMPONENT
60
 
61
    This routine prints the series of assignment operations to assign the
62
    value of type t given by nm to an offset p from the variable x%u_.  It
63
    returns the offset from x%u_ at the end of these assignments.
64
*/
65
 
66
static int assign_component
67
    PROTO_N ( ( t, p, nm, depth ) )
68
    PROTO_T ( TYPE_P t X int p X char *nm X int depth )
69
{
70
    TYPE t0 = DEREF_type ( t ) ;
71
    if ( depth > MAX_TYPE_DEPTH ) {
72
	error ( ERROR_SERIOUS, "Cyclic type definition involving %s",
73
		name_type ( t ) ) ;
74
	return ( p ) ;
75
    }
76
 
77
    if ( IS_type_ident ( t0 ) ) {
78
	/* Use identity definition */
79
	IDENTITY_P id = DEREF_ptr ( type_ident_id ( t0 ) ) ;
80
	TYPE_P s = DEREF_ptr ( ident_defn ( id ) ) ;
81
	return ( assign_component ( s, p, nm, depth + 1 ) ) ;
82
 
83
    } else if ( IS_type_structure ( t0 ) ) {
84
	/* Deal with structures componentwise */
85
	char buff [500] ;
86
	STRUCTURE_P str ;
87
	LIST ( COMPONENT_P ) c ;
88
	str = DEREF_ptr ( type_structure_struc ( t0 ) ) ;
89
	c = DEREF_list ( str_defn ( str ) ) ;
90
	while ( !IS_NULL_list ( c ) ) {
91
	    COMPONENT_P cmp = DEREF_ptr ( HEAD_list ( c ) ) ;
92
	    char *c_nm = DEREF_string ( cmp_name ( cmp ) ) ;
93
	    TYPE_P c_type = DEREF_ptr ( cmp_type ( cmp ) ) ;
94
	    int n = ( int ) strlen ( nm ) + ( int ) strlen ( c_nm ) + 8 ;
95
	    if ( n > ( int ) sizeof ( buff ) ) {
96
		error ( ERROR_SERIOUS, "Too many field selectors in type %s",
97
			name_type ( t ) ) ;
98
		break ;
99
	    }
100
	    sprintf_v ( buff, "%s.%s", nm, c_nm ) ;
101
	    p = assign_component ( c_type, p, buff, depth + 1 ) ;
102
	    c = TAIL_list ( c ) ;
103
	}
104
	return ( p ) ;
105
    }
106
 
107
    /* Other types are simple */
108
    output ( "\tCOPY_%TM ( x%u_ + %d, %e ) ;\\\n", t, p, nm ) ;
109
    return ( p + size_type ( t, 0 ) ) ;
110
}
111
 
112
 
113
/*
114
    PRINT A DEREFERENCE COMPONENT
115
 
116
    This routine prints the series of dereference operations to assign the
117
    value of type t given by an offset p from the variable x%u_ into nm.  It
118
    returns the offset from x%u_ at the end of these dereferences.  depth is
119
    used to catch cyclic type definitions.
120
*/
121
 
122
static int deref_component
123
    PROTO_N ( ( t, p, nm, depth ) )
124
    PROTO_T ( TYPE_P t X int p X char *nm X int depth )
125
{
126
    TYPE t0 = DEREF_type ( t ) ;
127
    if ( depth > MAX_TYPE_DEPTH ) {
128
	error ( ERROR_SERIOUS, "Cyclic type definition involving %s",
129
		name_type ( t ) ) ;
130
	return ( p ) ;
131
    }
132
 
133
    if ( IS_type_ident ( t0 ) ) {
134
	/* Use identity definition */
135
	IDENTITY_P id = DEREF_ptr ( type_ident_id ( t0 ) ) ;
136
	TYPE_P s = DEREF_ptr ( ident_defn ( id ) ) ;
137
	return ( deref_component ( s, p, nm, depth + 1 ) ) ;
138
 
139
    } else if ( IS_type_structure ( t0 ) ) {
140
	/* Deal with structures componentwise */
141
	char buff [500] ;
142
	STRUCTURE_P str ;
143
	LIST ( COMPONENT_P ) c ;
144
	str = DEREF_ptr ( type_structure_struc ( t0 ) ) ;
145
	c = DEREF_list ( str_defn ( str ) ) ;
146
	while ( !IS_NULL_list ( c ) ) {
147
	    COMPONENT_P cmp = DEREF_ptr ( HEAD_list ( c ) ) ;
148
	    char *c_nm = DEREF_string ( cmp_name ( cmp ) ) ;
149
	    TYPE_P c_type = DEREF_ptr ( cmp_type ( cmp ) ) ;
150
	    int n = ( int ) strlen ( nm ) + ( int ) strlen ( c_nm ) + 8 ;
151
	    if ( n > ( int ) sizeof ( buff ) ) {
152
		error ( ERROR_SERIOUS, "Too many field selectors in type %s",
153
			name_type ( t ) ) ;
154
		break ;
155
	    }
156
	    sprintf_v ( buff, "%s.%s", nm, c_nm ) ;
157
	    p = deref_component ( c_type, p, buff, depth + 1 ) ;
158
	    c = TAIL_list ( c ) ;
159
	}
160
	return ( p ) ;
161
    }
162
 
163
    /* Other types are simple */
164
    if ( is_complex_type ( t ) ) {
165
	output ( "\tDEREF_%TM ( x%u_ + %d, %e ) ;\\\n", t, p, nm ) ;
166
    } else {
167
	output ( "\t%e = DEREF_%TM ( x%u_ + %d ) ;\\\n", nm, t, p ) ;
168
    }
169
    return ( p + size_type ( t, 0 ) ) ;
170
}
171
 
172
 
173
/*
174
    PRINT A DEREFERENCE INSTRUCTION
175
 
176
    This routine prints code to dereference an object of type t from a
177
    into b.
178
*/
179
 
180
void print_deref
181
    PROTO_N ( ( t, a, b ) )
182
    PROTO_T ( TYPE_P t X char *a X char *b )
183
{
184
    if ( is_complex_type ( t ) ) {
185
	output ( "DEREF_%TM ( %e, %e ) ;\n", t, a, b ) ;
186
    } else {
187
	output ( "%e = DEREF_%TM ( %e ) ;\n", b, t, a ) ;
188
    }
189
    return ;
190
}
191
 
192
 
193
/*
194
    PRINT PROTOTYPE MACROS
195
 
196
    This routine prints the prototype macros used by the output.  The
197
    default values correspond to the non-prototype case.
198
*/
199
 
200
void print_proto
201
    PROTO_Z ()
202
{
203
    comment ( "Prototype macros" ) ;
204
    output ( "#ifndef PROTO_S\n" ) ;
205
    output ( "#ifdef __STDC__\n" ) ;
206
    output ( "#define PROTO_S( types )%t40types\n" ) ;
207
    output ( "#define PROTO_N( names )\n" ) ;
208
    output ( "#define PROTO_T( parms )%t40( parms )\n" ) ;
209
    output ( "#define PROTO_Z()%t40( void )\n" ) ;
210
    output ( "#define X%t40,\n" ) ;
211
    output ( "#else\n" ) ;
212
    output ( "#define PROTO_S( types )%t40()\n" ) ;
213
    output ( "#define PROTO_N( names )%t40names\n" ) ;
214
    output ( "#define PROTO_T( parms )%t40parms ;\n" ) ;
215
    output ( "#define PROTO_Z()%t40()\n" ) ;
216
    output ( "#define X%t40;\n" ) ;
217
    output ( "#endif\n" ) ;
218
    output ( "#endif\n\n" ) ;
219
    output ( "#ifndef CONST_S\n" ) ;
220
    output ( "#define CONST_S\n" ) ;
221
    output ( "#endif\n\n\n" ) ;
222
    return ;
223
}
224
 
225
 
226
/*
227
    PRINT FILE INCLUSIONS
228
 
229
    This routine prints file inclusions for all the major output files.
230
*/
231
 
232
void print_include
233
    PROTO_Z ()
234
{
235
    output ( "#include \"%s%s\"\n", MAIN_PREFIX, MAIN_SUFFIX ) ;
236
    LOOP_UNION output ( "#include \"%UM%s\"\n", OPS_SUFFIX ) ;
237
    output ( "\n" ) ;
238
    return ;
239
}
240
 
241
 
242
/*
243
    PRINT RUNTIME ASSERTION MACROS
244
 
245
    These macros are used, if the extra_asserts variable is set, to make the
246
    output code a little more readable.  Moreover, if the checks need to
247
    be turned off, then ASSERTS may be undefined.
248
*/
249
 
250
static void print_assert_decs
251
    PROTO_Z ()
252
{
253
    output ( "#ifdef ASSERTS\n" ) ;
254
    output ( "extern %X *check_null_%X PROTO_S " ) ;
255
    output ( "( ( %X *, CONST_S char *, int ) ) ;\n" ) ;
256
    output ( "extern %X *check_tag_%X PROTO_S " ) ;
257
    output ( "( ( %X *, unsigned, CONST_S char *, int ) ) ;\n" ) ;
258
    output ( "extern %X *check_tag_etc_%X PROTO_S " ) ;
259
    output ( "( ( %X *, unsigned, unsigned, CONST_S char *, int ) ) ;\n" ) ;
260
    if ( allow_vec ) {
261
	output ( "extern int check_int_size PROTO_S " ) ;
262
	output ( "( ( int, int, CONST_S char *, int ) ) ;\n" ) ;
263
    }
264
    output ( "#define CHECK_NULL( P )\\\n" ) ;
265
    output ( "    ( check_null_%X ( ( P ), __FILE__, __LINE__ ) )\n" ) ;
266
    output ( "#define CHECK_TAG( P, N )\\\n" ) ;
267
    output ( "    ( check_tag_%X ( ( P ), ( unsigned ) ( N ), " ) ;
268
    output ( "__FILE__, __LINE__ ) )\n" ) ;
269
    output ( "#define CHECK_TAG_ETC( P, L, U )\\\n" ) ;
270
    output ( "    ( check_tag_etc_%X ( ( P ), ( unsigned ) ( L ), " ) ;
271
    output ( "( unsigned ) ( U ), __FILE__, __LINE__ ) )\n" ) ;
272
    if ( allow_vec ) {
273
	output ( "#define CHECK_INT( N, M )\\\n" ) ;
274
	output ( "     ( check_int_size ( ( N ), ( M ), " ) ;
275
	output ( "__FILE__, __LINE__ ) )\n" ) ;
276
    }
277
    output ( "#else\n" ) ;
278
    output ( "#define CHECK_NULL( P )%t40( P )\n" ) ;
279
    output ( "#define CHECK_TAG( P, N )%t40( P )\n" ) ;
280
    output ( "#define CHECK_TAG_ETC( P, L, U )%t40( P )\n" ) ;
281
    if ( allow_vec ) output ( "#define CHECK_INT( N, M )%t40( N )\n" ) ;
282
    output ( "#endif\n\n\n" ) ;
283
    return ;
284
}
285
 
286
 
287
/*
288
    PRINT RUN-TIME CHECK FUNCTIONS
289
 
290
    If the assertion variable is set then these functions will be printed,
291
    they are to be used to perform run-time checks on the calculus.
292
    These functions are delivered to a special file.
293
*/
294
 
295
void print_assert_fns
296
    PROTO_Z ()
297
{
298
    /* Assertion printing */
299
    output ( "#ifndef assert_%X\n" ) ;
300
    output ( "static void assert_%X\n" ) ;
301
    output ( "    PROTO_N ( ( s, fn, ln ) )\n" ) ;
302
    output ( "    PROTO_T ( CONST_S char *s X CONST_S char *fn X int ln )\n" ) ;
303
    output ( "{\n" ) ;
304
    output ( "    ( void ) fprintf ( stderr, \"Assertion %%s failed, " ) ;
305
    output ( "%%s, line %%d.\\n\", s, fn, ln ) ;\n" ) ;
306
    output ( "    abort () ;\n" ) ;
307
    output ( "}\n" ) ;
308
    output ( "#endif\n\n" ) ;
309
 
310
    /* Null pointer check */
311
    output ( "%X *check_null_%X\n" ) ;
312
    output ( "    PROTO_N ( ( p, fn, ln ) )\n" ) ;
313
    output ( "    PROTO_T ( %X *p X CONST_S char *fn X int ln )\n" ) ;
314
    output ( "{\n" ) ;
315
    output ( "    if ( p == NULL ) " ) ;
316
    output ( "assert_%X ( \"Null pointer\", fn, ln ) ;\n" ) ;
317
    output ( "    return ( p ) ;\n" ) ;
318
    output ( "}\n\n" ) ;
319
 
320
    /* Union tag check */
321
    output ( "%X *check_tag_%X\n" ) ;
322
    output ( "    PROTO_N ( ( p, t, fn, ln ) )\n" ) ;
323
    output ( "    PROTO_T ( %X *p X unsigned t X CONST_S char *fn X int ln )\n" ) ;
324
    output ( "{\n" ) ;
325
    output ( "    p = check_null_%X ( p, fn, ln ) ;\n" ) ;
326
    output ( "    if ( p->ag_tag != t ) " ) ;
327
    output ( "assert_%X ( \"Union tag\", fn, ln ) ;\n" ) ;
328
    output ( "    return ( p ) ;\n" ) ;
329
    output ( "}\n\n" ) ;
330
 
331
    /* Union tag range check */
332
    output ( "%X *check_tag_etc_%X\n" ) ;
333
    output ( "    PROTO_N ( ( p, tl, tb, fn, ln ) )\n" ) ;
334
    output ( "    PROTO_T ( %X *p X unsigned tl X unsigned tb " ) ;
335
    output ( "X CONST_S char *fn X int ln )\n" ) ;
336
    output ( "{\n" ) ;
337
    output ( "    p = check_null_%X ( p, fn, ln ) ;\n" ) ;
338
    output ( "    if ( p->ag_tag < tl || p->ag_tag >= tb ) {\n" ) ;
339
    output ( "\tassert_%X ( \"Union tag\", fn, ln ) ;\n" ) ;
340
    output ( "    }\n" ) ;
341
    output ( "    return ( p ) ;\n" ) ;
342
    output ( "}\n\n" ) ;
343
 
344
    /* Vector trim range check */
345
    if ( !allow_vec ) return ;
346
    output ( "int check_int_size\n" ) ;
347
    output ( "    PROTO_N ( ( n, m, fn, ln ) )\n" ) ;
348
    output ( "    PROTO_T ( int n X int m X CONST_S char *fn X int ln )\n" ) ;
349
    output ( "{\n" ) ;
350
    output ( "    if ( n > m ) assert_%X ( \"Vector bound\", fn, ln ) ;\n" ) ;
351
    output ( "    return ( n ) ;\n" ) ;
352
    output ( "}\n\n" ) ;
353
    return ;
354
}
355
 
356
 
357
/*
358
    MAXIMUM ALLOCATION CHUNK
359
 
360
    This variable is used to keep track of the largest block used in
361
    the memory allocation routine.
362
*/
363
 
364
static int gen_max = 0 ;
365
 
366
 
367
/*
368
    FIND A MEMORY ALLOCATION INSTRUCTION
369
 
370
    This routine returns the instruction for allocating a block of n
371
    objects.  gen_max is also kept up to date.
372
*/
373
 
374
static char *gen
375
    PROTO_N ( ( n, nm ) )
376
    PROTO_T ( int n X char *nm )
377
{
378
    static char gbuff [100] ;
379
    sprintf_v ( gbuff, "GEN_%%X ( %d, TYPEID_%s )", n, nm ) ;
380
    if ( n > gen_max ) gen_max = n ;
381
    return ( gbuff ) ;
382
}
383
 
384
 
385
/*
386
    PRINT SIMPLE LIST CONSTRUCTORS
387
 
388
    This routine prints the list construction and deconstruction routines
389
    for the type named nm of size sz.  d is true for simply dereferenced
390
    types.
391
*/
392
 
393
static void print_simple_cons
394
    PROTO_N ( ( nm, sz, d ) )
395
    PROTO_T ( char *nm X int sz X int d )
396
{
397
    /* CONS routine */
398
    char *g ;
399
    output ( "#define CONS_%e( A, B, C )\\\n", nm ) ;
400
    output ( "    {\\\n" ) ;
401
    g = gen ( sz + 1, "list" ) ;
402
    output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
403
    output ( "\tCOPY_%e ( x%u_ + 1, ( A ) ) ;\\\n", nm ) ;
404
    output ( "\tx%u_->ag_ptr = ( B ) ;\\\n" ) ;
405
    output ( "\t( C ) = x%u_ ;\\\n" ) ;
406
    output ( "    }\n\n" ) ;
407
    unique++ ;
408
 
409
    /* UN_CONS routine */
410
    output ( "#define UN_CONS_%e( A, B, C )\\\n", nm ) ;
411
    output ( "    {\\\n" ) ;
412
    output ( "\t%X *x%u_ = %s( C ) ;\\\n", check_null ) ;
413
    if ( d ) {
414
	output ( "\t( A ) = DEREF_%e ( x%u_ + 1 ) ;\\\n", nm ) ;
415
    } else {
416
	output ( "\tDEREF_%e ( x%u_ + 1, ( A ) ) ;\\\n", nm ) ;
417
    }
418
    output ( "\t( B ) = x%u_->ag_ptr ;\\\n" ) ;
419
    output ( "    }\n\n" ) ;
420
    unique++ ;
421
 
422
    /* DESTROY_CONS routine */
423
    output ( "#define DESTROY_CONS_%e( D, A, B, C )\\\n", nm ) ;
424
    output ( "    {\\\n" ) ;
425
    output ( "\t%X *x%u_ = %s( C ) ;\\\n", check_null ) ;
426
    if ( d ) {
427
	output ( "\t( A ) = DEREF_%e ( x%u_ + 1 ) ;\\\n", nm ) ;
428
    } else {
429
	output ( "\tDEREF_%e ( x%u_ + 1, ( A ) ) ;\\\n", nm ) ;
430
    }
431
    output ( "\t( B ) = x%u_->ag_ptr ;\\\n" ) ;
432
    output ( "\t( D ) ( x%u_, ( unsigned ) %d ) ;\\\n", sz + 1 ) ;
433
    output ( "    }\n\n" ) ;
434
    unique++ ;
435
 
436
    if ( allow_stack ) {
437
	/* PUSH routine */
438
	output ( "#define PUSH_%e( A, B )\\\n", nm ) ;
439
	output ( "    {\\\n" ) ;
440
	output ( "\t%X **r%u_ = &( B ) ;\\\n" ) ;
441
	g = gen ( sz + 1, "stack" ) ;
442
	output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
443
	output ( "\tCOPY_%e ( x%u_ + 1, ( A ) ) ;\\\n", nm ) ;
444
	output ( "\tx%u_->ag_ptr = *r%u_ ;\\\n" ) ;
445
	output ( "\t*r%u_ = x%u_ ;\\\n" ) ;
446
	output ( "    }\n\n" ) ;
447
	unique++ ;
448
 
449
	/* POP routine */
450
	output ( "#define POP_%e( A, B )\\\n", nm ) ;
451
	output ( "    {\\\n" ) ;
452
	output ( "\t%X **r%u_ = &( B ) ;\\\n" ) ;
453
	output ( "\t%X *x%u_ = %s( *r%u_ ) ;\\\n", check_null ) ;
454
	if ( d ) {
455
	    output ( "\t( A ) = DEREF_%e ( x%u_ + 1 ) ;\\\n", nm ) ;
456
	} else {
457
	    output ( "\tDEREF_%e ( x%u_ + 1, ( A ) ) ;\\\n", nm ) ;
458
	}
459
	output ( "\t*r%u_ = x%u_->ag_ptr ;\\\n" ) ;
460
	output ( "\tdestroy_%X ( x%u_, ( unsigned ) %d ) ;\\\n", sz + 1 ) ;
461
	output ( "    }\n\n" ) ;
462
	unique++ ;
463
    }
464
 
465
    /* End of routine */
466
    output ( "\n" ) ;
467
    return ;
468
}
469
 
470
 
471
/*
472
    PRINT STRUCTURE DEFINITIONS
473
 
474
    This routine prints all the structure declarations and definitions
475
    and all identity declarations.  Some care needs to be taken with the
476
    ordering of the structure definitions.  Cyclic structures will have
477
    already been detected, so there is no need to worry about them.
478
*/
479
 
480
void print_struct_defn
481
    PROTO_Z ()
482
{
483
    int ok ;
484
    comment ( "Structure declarations" ) ;
485
    LOOP_STRUCTURE {
486
	output ( "typedef struct %SM_tag %SN ;\n" ) ;
487
	COPY_int ( str_output ( CRT_STRUCTURE ), 0 ) ;
488
    }
489
    output ( "\n\n" ) ;
490
 
491
    comment ( "Identity type definitions" ) ;
492
    LOOP_IDENTITY output ( "typedef %IT %IN ;\n" ) ;
493
    output ( "\n\n" ) ;
494
 
495
    comment ( "Structure definitions" ) ;
496
    output ( "#ifndef %X_STRUCT_DEFINED\n" ) ;
497
    output ( "#define %X_STRUCT_DEFINED\n\n" ) ;
498
    do {
499
	ok = 1 ;
500
	LOOP_STRUCTURE {
501
	    int pr = DEREF_int ( str_output ( CRT_STRUCTURE ) ) ;
502
	    if ( pr == 0 ) {
503
		/* Check if all components have been printed */
504
		pr = 1 ;
505
		LOOP_STRUCTURE_COMPONENT {
506
		    TYPE t0 ;
507
		    TYPE_P t = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
508
		    t0 = DEREF_type ( t ) ;
509
		    while ( IS_type_ident ( t0 ) ) {
510
			IDENTITY_P id ;
511
			id = DEREF_ptr ( type_ident_id ( t0 ) ) ;
512
			t = DEREF_ptr ( ident_defn ( id ) ) ;
513
			t0 = DEREF_type ( t ) ;
514
		    }
515
		    if ( IS_type_structure ( t0 ) ) {
516
			STRUCTURE_P str ;
517
			str = DEREF_ptr ( type_structure_struc ( t0 ) ) ;
518
			pr = DEREF_int ( str_output ( str ) ) ;
519
			if ( pr == 0 ) break ;
520
		    }
521
		}
522
		if ( pr ) {
523
		    /* Print structure definition */
524
		    output ( "struct %SM_tag {\n" ) ;
525
		    LOOP_STRUCTURE_COMPONENT output ( "    %CT %CN ;\n" ) ;
526
		    output ( "} ;\n\n" ) ;
527
		    COPY_int ( str_output ( CRT_STRUCTURE ), 1 ) ;
528
		} else {
529
		    /* Structure definition postponed */
530
		    output ( "/* struct %SM_tag later */\n\n" ) ;
531
		    ok = 0 ;
532
		}
533
	    }
534
	}
535
    } while ( !ok ) ;
536
    output ( "#endif /* %X_STRUCT_DEFINED */\n\n\n" ) ;
537
    return ;
538
}
539
 
540
 
541
/*
542
    PRINT BASIC TYPES (C VERSION)
543
 
544
    This routine prints the C versions of the basic type definitions.
545
*/
546
 
547
static void print_types_c
548
    PROTO_Z ()
549
{
550
    int n ;
551
    comment ( "Primitive types" ) ;
552
    LOOP_PRIMITIVE {
553
	CLASS_ID_P c = DEREF_ptr ( prim_id ( CRT_PRIMITIVE ) ) ;
554
	char *pn = DEREF_string ( cid_name ( c ) ) ;
555
	char *pd = DEREF_string ( prim_defn ( CRT_PRIMITIVE ) ) ;
556
	if ( !streq ( pn, pd ) ) output ( "typedef %PD %PN ;\n" ) ;
557
    }
558
    output ( "\n\n" ) ;
559
 
560
    comment ( "Basic types" ) ;
561
    if ( allow_vec ) output ( "typedef unsigned %X_dim ;\n\n" ) ;
562
    output ( "typedef union %X_tag {\n" ) ;
563
    output ( "    unsigned ag_tag ;\n" ) ;
564
    output ( "    union %X_tag *ag_ptr ;\n" ) ;
565
    if ( allow_vec ) output ( "    %X_dim ag_dim ;\n" ) ;
566
    output ( "    unsigned ag_enum ;\n" ) ;
567
    output ( "    unsigned long ag_long_enum ;\n" ) ;
568
    LOOP_PRIMITIVE output ( "    %PN ag_prim_%PM ;\n" ) ;
569
    output ( "} %X ;\n\n" ) ;
570
    output ( "typedef %X *%X_PTR ;\n\n" ) ;
571
 
572
    if ( allow_vec ) {
573
	output ( "typedef struct {\n" ) ;
574
	output ( "    %X *vec ;\n" ) ;
575
	output ( "    %X *ptr ;\n" ) ;
576
	output ( "} %X_VEC_PTR ;\n\n" ) ;
577
 
578
	output ( "typedef struct {\n" ) ;
579
	output ( "    %X_dim dim ;\n" ) ;
580
	output ( "    %X_VEC_PTR elems ;\n" ) ;
581
	output ( "} %X_VEC ;\n\n" ) ;
582
    }
583
 
584
    output ( "#ifndef %X_DESTR_DEFINED\n" ) ;
585
    output ( "#define %X_DESTR_DEFINED\n" ) ;
586
    output ( "typedef void ( *DESTROYER ) " ) ;
587
    output ( "PROTO_S ( ( %X *, unsigned ) ) ;\n" ) ;
588
    output ( "#endif\n\n" ) ;
589
 
590
    output ( "#define PTR( A )\t%X_PTR\n" ) ;
591
    output ( "#define LIST( A )\t%X_PTR\n" ) ;
592
    if ( allow_stack ) {
593
	output ( "#define STACK( A )\t%X_PTR\n" ) ;
594
    }
595
    if ( allow_vec ) {
596
	output ( "#define VEC( A )\t%X_VEC\n" ) ;
597
	output ( "#define VEC_PTR( A )\t%X_VEC_PTR\n" ) ;
598
    }
599
    output ( "#define SIZE( A )\tint\n\n\n" ) ;
600
 
601
    if ( extra_asserts ) {
602
	comment ( "Assertion macros" ) ;
603
	print_assert_decs () ;
604
    }
605
 
606
    comment ( "Enumeration definitions" ) ;
607
    LOOP_ENUM {
608
	number m = DEREF_number ( en_order ( CRT_ENUM ) ) ;
609
	if ( m > ( number ) 0x10000 ) {
610
	    output ( "typedef unsigned long %EN ;\n" ) ;
611
	} else {
612
	    output ( "typedef unsigned %EN ;\n" ) ;
613
	}
614
    }
615
    output ( "\n\n" ) ;
616
 
617
    comment ( "Union type definitions" ) ;
618
    LOOP_UNION output ( "typedef %X *%UN ;\n" ) ;
619
    output ( "\n\n" ) ;
620
 
621
    print_struct_defn () ;
622
 
623
    comment ( "Function declarations" ) ;
624
    output ( "extern %X *gen_%X PROTO_S ( ( unsigned ) ) ;\n" ) ;
625
    output ( "extern void destroy_%X PROTO_S ( ( %X *, unsigned ) ) ;\n" ) ;
626
    output ( "extern void dummy_destroy_%X " ) ;
627
    output ( "PROTO_S ( ( %X *, unsigned ) ) ;\n" ) ;
628
    output ( "extern void destroy_%X_list " ) ;
629
    output ( "PROTO_S ( ( %X *, unsigned ) ) ;\n" ) ;
630
    output ( "extern %X *append_%X_list PROTO_S ( ( %X *, %X * ) ) ;\n" ) ;
631
    output ( "extern %X *end_%X_list PROTO_S ( ( %X * ) ) ;\n" ) ;
632
    output ( "extern unsigned length_%X_list PROTO_S ( ( %X * ) ) ;\n" ) ;
633
    output ( "extern %X *reverse_%X_list PROTO_S ( ( %X * ) ) ;\n" ) ;
634
    if ( allow_vec ) output ( "extern %X_VEC empty_%X_vec ;\n" ) ;
635
    output ( "#ifdef %X_IO_ROUTINES\n" ) ;
636
    output ( "extern unsigned crt_%X_alias ;\n" ) ;
637
    output ( "extern void set_%X_alias PROTO_S ( ( %X *, unsigned ) ) ;\n" ) ;
638
    output ( "extern %X *find_%X_alias PROTO_S ( ( unsigned ) ) ;\n" ) ;
639
    output ( "extern void clear_%X_alias PROTO_S ( ( void ) ) ;\n" ) ;
640
    output ( "#endif\n" ) ;
641
    output ( "\n\n" ) ;
642
    comment ( "Run-time type information" ) ;
643
    output ( "#ifndef GEN_%X\n" ) ;
644
    output ( "#define GEN_%X( A, B )%t40gen_%X ( ( unsigned ) ( A ) )\n" ) ;
645
    output ( "#endif\n" ) ;
646
    output ( "#define TYPEID_ptr%t40( ( unsigned ) 0 )\n" ) ;
647
    output ( "#define TYPEID_list%t40( ( unsigned ) 1 )\n" ) ;
648
    output ( "#define TYPEID_stack%t40( ( unsigned ) 2 )\n" ) ;
649
    n = 3 ;
650
    LOOP_UNION {
651
	output ( "#define TYPEID_%UM%t40( ( unsigned ) %d )\n", n ) ;
652
	n++ ;
653
    }
654
    output ( "\n\n" ) ;
655
    return ;
656
}
657
 
658
 
659
/*
660
    PRINT POINTER CONSTRUCTS (C VERSION)
661
 
662
    This routine prints the C versions of the pointer constructs.
663
*/
664
 
665
static void print_ptr_c
666
    PROTO_Z ()
667
{
668
    /* Pointers */
669
    char *g ;
670
    comment ( "Definitions for pointers" ) ;
671
    output ( "#define STEP_ptr( A, B )%t40" ) ;
672
    output ( "( %s( A ) + B )\n", check_null ) ;
673
    output ( "#define SIZE_ptr( A )%t40%d\n", SIZE_PTR ) ;
674
    output ( "#define NULL_ptr( A )%t40( ( %X * ) 0 )\n" ) ;
675
    output ( "#define IS_NULL_ptr( A )%t40( ( A ) == 0 )\n" ) ;
676
    output ( "#define EQ_ptr( A, B )%t40( ( A ) == ( B ) )\n" ) ;
677
    output ( "#define MAKE_ptr( A )%t40GEN_%X ( ( A ), TYPEID_ptr )\n" ) ;
678
    output ( "#define DESTROY_ptr( A, B )%t40" ) ;
679
    output ( "destroy_%X ( ( A ), ( unsigned ) ( B ) )\n" ) ;
680
    g = gen ( 1, "ptr" ) ;
681
    output ( "#define UNIQ_ptr( A )%t40%e\n", g ) ;
682
    output ( "#define DESTROY_UNIQ_ptr( A )%t40" ) ;
683
    output ( "destroy_%X ( ( A ), ( unsigned ) 1 )\n" ) ;
684
    output ( "#ifdef %X_IO_ROUTINES\n" ) ;
685
    output ( "#define VOIDSTAR_ptr( A )%t40( ( void * ) ( A ) )\n" ) ;
686
    output ( "#endif\n\n" ) ;
687
 
688
    /* Assignment and dereference of pointers */
689
    output ( "#define COPY_ptr( A, B )%t40" ) ;
690
    output ( "( %s( A )->ag_ptr = ( B ) )\n", check_null ) ;
691
    output ( "#define DEREF_ptr( A )%t40" ) ;
692
    output ( "( %s( A )->ag_ptr )\n", check_null ) ;
693
 
694
    /* Pointer list constructor */
695
    output ( "#define CONS_ptr( A, B, C )\\\n" ) ;
696
    output ( "    {\\\n" ) ;
697
    g = gen ( SIZE_PTR + 1, "list" ) ;
698
    output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
699
    output ( "\tx%u_ [1].ag_ptr = ( A ) ;\\\n" ) ;
700
    output ( "\tx%u_->ag_ptr = ( B ) ;\\\n" ) ;
701
    output ( "\t( C ) = x%u_ ;\\\n" ) ;
702
    output ( "    }\n\n" ) ;
703
    unique++ ;
704
 
705
    /* Pointer list deconstructor */
706
    output ( "#define UN_CONS_ptr( A, B, C )\\\n" ) ;
707
    output ( "    {\\\n" ) ;
708
    output ( "\t%X *x%u_ = %s( C ) ;\\\n", check_null ) ;
709
    output ( "\t( A ) = x%u_ [1].ag_ptr ;\\\n" ) ;
710
    output ( "\t( B ) = x%u_->ag_ptr ;\\\n" ) ;
711
    output ( "    }\n\n" ) ;
712
    unique++ ;
713
 
714
    /* Pointer list destructor */
715
    output ( "#define DESTROY_CONS_ptr( D, A, B, C )\\\n" ) ;
716
    output ( "    {\\\n" ) ;
717
    output ( "\t%X *x%u_ = %s( C ) ;\\\n", check_null ) ;
718
    output ( "\t( A ) = x%u_ [1].ag_ptr ;\\\n" ) ;
719
    output ( "\t( B ) = x%u_->ag_ptr ;\\\n" ) ;
720
    output ( "\t( D ) ( x%u_, ( unsigned ) 2 ) ;\\\n" ) ;
721
    output ( "    }\n\n" ) ;
722
    unique++ ;
723
 
724
    if ( allow_stack ) {
725
	/* Pointer stack constructor */
726
	output ( "#define PUSH_ptr( A, B )\\\n" ) ;
727
	output ( "    {\\\n" ) ;
728
	output ( "\t%X **r%u_ = &( B ) ;\\\n" ) ;
729
	g = gen ( SIZE_PTR + 1, "stack" ) ;
730
	output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
731
	output ( "\tx%u_ [1].ag_ptr = ( A ) ;\\\n" ) ;
732
	output ( "\tx%u_->ag_ptr = *r%u_ ;\\\n" ) ;
733
	output ( "\t*r%u_ = x%u_ ;\\\n" ) ;
734
	output ( "    }\n\n" ) ;
735
	unique++ ;
736
 
737
	/* Pointer stack destructor */
738
	output ( "#define POP_ptr( A, B )\\\n" ) ;
739
	output ( "    {\\\n" ) ;
740
	output ( "\t%X **r%u_ = &( B ) ;\\\n" ) ;
741
	output ( "\t%X *x%u_ = %s( *r%u_ ) ;\\\n", check_null ) ;
742
	output ( "\t( A ) = x%u_ [1].ag_ptr ;\\\n" ) ;
743
	output ( "\t*r%u_ = x%u_->ag_ptr ;\\\n" ) ;
744
	output ( "\tdestroy_%X ( x%u_, ( unsigned ) 2 ) ;\\\n" ) ;
745
	output ( "    }\n\n" ) ;
746
	unique++ ;
747
    }
748
 
749
    output ( "\n" ) ;
750
    return ;
751
}
752
 
753
 
754
/*
755
    PRINT LIST CONSTRUCTS (C VERSION)
756
 
757
    This routine prints the C versions of the list constructs.
758
*/
759
 
760
static void print_list_c
761
    PROTO_Z ()
762
{
763
    /* Lists */
764
    char *g ;
765
    comment ( "Definitions for lists" ) ;
766
    output ( "#define HEAD_list( A )%t40" ) ;
767
    output ( "( %s( A ) + 1 )\n", check_null ) ;
768
    output ( "#define PTR_TAIL_list( A )%t40" ) ;
769
    output ( "( %s( A ) )\n", check_null ) ;
770
    output ( "#define TAIL_list( A )%t40" ) ;
771
    output ( "( %s( A )->ag_ptr )\n", check_null ) ;
772
 
773
    output ( "#define LENGTH_list( A )%t40length_%X_list ( ( A ) )\n" ) ;
774
    output ( "#define END_list( A )%t40end_%X_list ( ( A ) )\n" ) ;
775
    output ( "#define REVERSE_list( A )%t40reverse_%X_list ( ( A ) )\n" ) ;
776
    output ( "#define APPEND_list( A, B )%t40" ) ;
777
    output ( "append_%X_list ( ( A ), ( B ) )\n\n" ) ;
778
    output ( "#define SIZE_list( A )%t40%d\n", SIZE_LIST ) ;
779
    output ( "#define NULL_list( A )%t40( ( %X * ) 0 )\n" ) ;
780
    output ( "#define IS_NULL_list( A )%t40( ( A ) == 0 )\n" ) ;
781
    output ( "#define EQ_list( A, B )%t40( ( A ) == ( B ) )\n" ) ;
782
    g = gen ( 1, "list" ) ;
783
    output ( "#define UNIQ_list( A )%t40%e\n", g ) ;
784
    output ( "#define DESTROY_UNIQ_list( A )%t40" ) ;
785
    output ( "destroy_%X ( ( A ), ( unsigned ) 1 )\n" ) ;
786
    output ( "#ifdef %X_IO_ROUTINES\n" ) ;
787
    output ( "#define VOIDSTAR_list( A )%t40( ( void * ) ( A ) )\n" ) ;
788
    output ( "#endif\n\n" ) ;
789
 
790
    /* Destruction of lists */
791
    output ( "#define DESTROY_list( A, B )\\\n" ) ;
792
    output ( "    {\\\n" ) ;
793
    output ( "\tdestroy_%X_list ( ( A ), ( unsigned ) ( B ) ) ;\\\n" ) ;
794
    output ( "    }\n\n" ) ;
795
 
796
    /* Assignment and dereference of lists */
797
    output ( "#define COPY_list( A, B )%t40" ) ;
798
    output ( "( %s( A )->ag_ptr = ( B ) )\n", check_null ) ;
799
    output ( "#define DEREF_list( A )%t40" ) ;
800
    output ( "( %s( A )->ag_ptr )\n", check_null ) ;
801
 
802
    /* List list constructor */
803
    output ( "#define CONS_list( A, B, C )\\\n" ) ;
804
    output ( "    {\\\n" ) ;
805
    g = gen ( SIZE_LIST + 1, "list" ) ;
806
    output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
807
    output ( "\tx%u_ [1].ag_ptr = ( A ) ;\\\n" ) ;
808
    output ( "\tx%u_->ag_ptr = ( B ) ;\\\n" ) ;
809
    output ( "\t( C ) = x%u_ ;\\\n" ) ;
810
    output ( "    }\n\n" ) ;
811
    unique++ ;
812
 
813
    /* List list deconstructor */
814
    output ( "#define UN_CONS_list( A, B, C )\\\n" ) ;
815
    output ( "    {\\\n" ) ;
816
    output ( "\t%X *x%u_ = %s( C ) ;\\\n", check_null ) ;
817
    output ( "\t( A ) = x%u_ [1].ag_ptr ;\\\n" ) ;
818
    output ( "\t( B ) = x%u_->ag_ptr ;\\\n" ) ;
819
    output ( "    }\n\n" ) ;
820
    unique++ ;
821
 
822
    /* List list destructor */
823
    output ( "#define DESTROY_CONS_list( D, A, B, C )\\\n" ) ;
824
    output ( "    {\\\n" ) ;
825
    output ( "\t%X *x%u_ = %s( C ) ;\\\n", check_null ) ;
826
    output ( "\t( A ) = x%u_ [1].ag_ptr ;\\\n" ) ;
827
    output ( "\t( B ) = x%u_->ag_ptr ;\\\n" ) ;
828
    output ( "\t( D ) ( x%u_, ( unsigned ) 2 ) ;\\\n" ) ;
829
    output ( "    }\n\n" ) ;
830
    unique++ ;
831
 
832
    if ( allow_stack ) {
833
	/* List stack constructor */
834
	output ( "#define PUSH_list( A, B )\\\n" ) ;
835
	output ( "    {\\\n" ) ;
836
	output ( "\t%X **r%u_ = &( B ) ;\\\n" ) ;
837
	g = gen ( SIZE_LIST + 1, "stack" ) ;
838
	output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
839
	output ( "\tx%u_ [1].ag_ptr = ( A ) ;\\\n" ) ;
840
	output ( "\tx%u_->ag_ptr = *r%u_ ;\\\n" ) ;
841
	output ( "\t*r%u_ = x%u_ ;\\\n" ) ;
842
	output ( "    }\n\n" ) ;
843
	unique++ ;
844
 
845
	/* List stack destructor */
846
	output ( "#define POP_list( A, B )\\\n" ) ;
847
	output ( "    {\\\n" ) ;
848
	output ( "\t%X **r%u_ = &( B ) ;\\\n" ) ;
849
	output ( "\t%X *x%u_ = %s( *r%u_ ) ;\\\n", check_null ) ;
850
	output ( "\t( A ) = x%u_ [1].ag_ptr ;\\\n" ) ;
851
	output ( "\t*r%u_ = x%u_->ag_ptr ;\\\n" ) ;
852
	output ( "\tdestroy_%X ( x%u_, ( unsigned ) 2 ) ;\\\n" ) ;
853
	output ( "    }\n\n" ) ;
854
	unique++ ;
855
    }
856
 
857
    output ( "\n" ) ;
858
    return ;
859
}
860
 
861
 
862
/*
863
    PRINT STACK CONSTRUCTS (C VERSION)
864
 
865
    This routine prints the C versions of the stack constructs.
866
*/
867
 
868
static void print_stack_c
869
    PROTO_Z ()
870
{
871
    /* Stacks */
872
    char *g ;
873
    comment ( "Definitions for stacks" ) ;
874
    output ( "#define SIZE_stack( A )%t40%d\n", SIZE_STACK ) ;
875
    output ( "#define NULL_stack( A )%t40( ( %X * ) 0 )\n" ) ;
876
    output ( "#define IS_NULL_stack( A )%t40( ( A ) == 0 )\n" ) ;
877
    output ( "#define STACK_list( A )%t40( A )\n" ) ;
878
    output ( "#define LIST_stack( A )%t40( A )\n\n" ) ;
879
 
880
    /* Assignment and dereference of stacks */
881
    output ( "#define COPY_stack( A, B )%t40" ) ;
882
    output ( "( %s( A )->ag_ptr = ( B ) )\n", check_null ) ;
883
    output ( "#define DEREF_stack( A )%t40" ) ;
884
    output ( "( %s( A )->ag_ptr )\n", check_null ) ;
885
 
886
    /* Stack list constructor */
887
    output ( "#define CONS_stack( A, B, C )\\\n" ) ;
888
    output ( "    {\\\n" ) ;
889
    g = gen ( SIZE_STACK + 1, "list" ) ;
890
    output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
891
    output ( "\tx%u_ [1].ag_ptr = ( A ) ;\\\n" ) ;
892
    output ( "\tx%u_->ag_ptr = ( B ) ;\\\n" ) ;
893
    output ( "\t( C ) = x%u_ ;\\\n" ) ;
894
    output ( "    }\n\n" ) ;
895
    unique++ ;
896
 
897
    /* Stack list deconstructor */
898
    output ( "#define UN_CONS_stack( A, B, C )\\\n" ) ;
899
    output ( "    {\\\n" ) ;
900
    output ( "\t%X *x%u_ = %s( C ) ;\\\n", check_null ) ;
901
    output ( "\t( A ) = x%u_ [1].ag_ptr ;\\\n" ) ;
902
    output ( "\t( B ) = x%u_->ag_ptr ;\\\n" ) ;
903
    output ( "    }\n\n" ) ;
904
    unique++ ;
905
 
906
    /* Stack list destructor */
907
    output ( "#define DESTROY_CONS_stack( D, A, B, C )\\\n" ) ;
908
    output ( "    {\\\n" ) ;
909
    output ( "\t%X *x%u_ = %s( C ) ;\\\n", check_null ) ;
910
    output ( "\t( A ) = x%u_ [1].ag_ptr ;\\\n" ) ;
911
    output ( "\t( B ) = x%u_->ag_ptr ;\\\n" ) ;
912
    output ( "\t( D ) ( x%u_, ( unsigned ) 2 ) ;\\\n" ) ;
913
    output ( "    }\n\n" ) ;
914
    unique++ ;
915
 
916
    if ( allow_stack ) {
917
	/* Stack stack constructor */
918
	output ( "#define PUSH_stack( A, B )\\\n" ) ;
919
	output ( "    {\\\n" ) ;
920
	output ( "\t%X **r%u_ = &( B ) ;\\\n" ) ;
921
	g = gen ( SIZE_STACK + 1, "stack" ) ;
922
	output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
923
	output ( "\tx%u_ [1].ag_ptr = ( A ) ;\\\n" ) ;
924
	output ( "\tx%u_->ag_ptr = *r%u_ ;\\\n" ) ;
925
	output ( "\t*r%u_ = x%u_ ;\\\n" ) ;
926
	output ( "    }\n\n" ) ;
927
	unique++ ;
928
 
929
	/* Stack stack destructor */
930
	output ( "#define POP_stack( A, B )\\\n" ) ;
931
	output ( "    {\\\n" ) ;
932
	output ( "\t%X **r%u_ = &( B ) ;\\\n" ) ;
933
	output ( "\t%X *x%u_ = %s( *r%u_ ) ;\\\n", check_null ) ;
934
	output ( "\t( A ) = x%u_ [1].ag_ptr ;\\\n" ) ;
935
	output ( "\t*r%u_ = x%u_->ag_ptr ;\\\n" ) ;
936
	output ( "\tdestroy_%X ( x%u_, ( unsigned ) 2 ) ;\\\n" ) ;
937
	output ( "    }\n\n" ) ;
938
	unique++ ;
939
    }
940
 
941
    output ( "\n" ) ;
942
    return ;
943
}
944
 
945
 
946
/*
947
    PRINT VECTOR CONSTRUCTS (C VERSION)
948
 
949
    This routine prints the C versions of the vector constructs.
950
*/
951
 
952
static void print_vec_c
953
    PROTO_Z ()
954
{
955
    /* Vectors */
956
    char *g ;
957
    comment ( "Definitions for vectors" ) ;
958
    output ( "#define DIM_vec( A )%t40( ( A ).dim )\n" ) ;
959
    output ( "#define PTR_ptr_vec( A )%t40" ) ;
960
    output ( "( %s( A ) [2].ag_ptr )\n", check_null ) ;
961
    output ( "#define DIM_ptr_vec( A )%t40( ( A )->ag_dim )\n" ) ;
962
    output ( "#define SIZE_vec( A )%t40%d\n", SIZE_VEC ) ;
963
    output ( "#define NULL_vec( A )%t40empty_%X_vec\n\n" ) ;
964
 
965
    /* Vector creation */
966
    output ( "#define MAKE_vec( SZ, U, RES )\\\n" ) ;
967
    output ( "    {\\\n" ) ;
968
    output ( "\t%X_VEC x%u_ ;\\\n" ) ;
969
    output ( "\t%X_dim u%u_ = ( U ) ;\\\n" ) ;
970
    output ( "\tx%u_.dim = u%u_ ;\\\n" ) ;
971
    output ( "\tif ( u%u_ == 0 ) u%u_ = 1 ;\\\n" ) ;
972
    output ( "\tx%u_.elems.ptr = " ) ;
973
    output ( "GEN_%X ( ( SZ ) * u%u_, TYPEID_ptr ) ;\\\n" ) ;
974
    output ( "\tx%u_.elems.vec = x%u_.elems.ptr ;\\\n" ) ;
975
    output ( "\t( RES ) = x%u_ ;\\\n" ) ;
976
    output ( "    }\n\n" ) ;
977
    unique++ ;
978
 
979
    /* Vector destroyer */
980
    output ( "#define DESTROY_vec( V, SZ )\\\n" ) ;
981
    output ( "    {\\\n" ) ;
982
    output ( "\t%X_VEC x%u_ ;\\\n" ) ;
983
    output ( "\tx%u_ = ( V ) ;\\\n" ) ;
984
    output ( "\tdestroy_%X ( x%u_.elems.ptr, " ) ;
985
    output ( "( unsigned ) ( ( SZ ) * x%u_.dim ) ) ;\\\n" ) ;
986
    output ( "    }\n\n" ) ;
987
    unique++ ;
988
 
989
    /* Vector trimmer */
990
    output ( "#define TRIM_vec( V, SZ, L, U, RES )\\\n" ) ;
991
    output ( "    {\\\n" ) ;
992
    output ( "\t%X_VEC x%u_ ;\\\n" ) ;
993
    if ( extra_asserts ) {
994
	output ( "\tint u%u_, l%u_ ;\\\n" ) ;
995
	output ( "\tx%u_ = ( V ) ;\\\n" ) ;
996
	output ( "\tu%u_ = CHECK_INT ( ( U ), DIM_vec ( x%u_ ) ) ;\\\n" ) ;
997
	output ( "\tl%u_ = CHECK_INT ( ( L ), u%u_ ) ;\\\n" ) ;
998
	output ( "\tx%u_.elems.ptr += ( ( SZ ) * l%u_ ) ;\\\n" ) ;
999
	output ( "\tx%u_.dim = ( unsigned ) ( u%u_ - l%u_ ) ;\\\n" ) ;
1000
    } else {
1001
	output ( "\tint l%u_ = ( L ) ;\\\n" ) ;
1002
	output ( "\tx%u_ = ( V ) ;\\\n" ) ;
1003
	output ( "\tx%u_.elems.ptr += ( ( SZ ) * l%u_ ) ;\\\n" ) ;
1004
	output ( "\tx%u_.dim = ( unsigned ) ( ( U ) - l%u_ ) ;\\\n" ) ;
1005
    }
1006
    output ( "\t( RES ) = x%u_ ;\\\n" ) ;
1007
    output ( "    }\n\n" ) ;
1008
    unique++ ;
1009
 
1010
    /* Vector assignment */
1011
    output ( "#define COPY_vec( A, B )\\\n" ) ;
1012
    output ( "    {\\\n" ) ;
1013
    output ( "\t%X *x%u_ = %s( A ) ;\\\n", check_null ) ;
1014
    output ( "\t%X_VEC y%u_ ;\\\n" ) ;
1015
    output ( "\ty%u_ = ( B ) ;\\\n" ) ;
1016
    output ( "\tx%u_ [0].ag_dim = y%u_.dim ;\\\n" ) ;
1017
    output ( "\tx%u_ [1].ag_ptr = y%u_.elems.vec ;\\\n" ) ;
1018
    output ( "\tx%u_ [2].ag_ptr = y%u_.elems.ptr ;\\\n" ) ;
1019
    output ( "    }\n\n" ) ;
1020
    unique++ ;
1021
 
1022
    /* Vector dereference */
1023
    output ( "#define DEREF_vec( A, B )\\\n" ) ;
1024
    output ( "    {\\\n" ) ;
1025
    output ( "\t%X *x%u_ = %s( A ) ;\\\n", check_null ) ;
1026
    output ( "\t%X_VEC *y%u_ = &( B ) ;\\\n" ) ;
1027
    output ( "\ty%u_->dim = x%u_ [0].ag_dim ;\\\n" ) ;
1028
    output ( "\ty%u_->elems.vec = x%u_ [1].ag_ptr ;\\\n" ) ;
1029
    output ( "\ty%u_->elems.ptr = x%u_ [2].ag_ptr ;\\\n" ) ;
1030
    output ( "    }\n\n" ) ;
1031
    unique++ ;
1032
 
1033
    /* Vector list constructor */
1034
    output ( "#define CONS_vec( A, B, C )\\\n" ) ;
1035
    output ( "    {\\\n" ) ;
1036
    g = gen ( SIZE_VEC + 1, "list" ) ;
1037
    output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
1038
    output ( "\t%X_VEC y%u_ ;\\\n" ) ;
1039
    output ( "\ty%u_ = ( A ) ;\\\n" ) ;
1040
    output ( "\tx%u_ [1].ag_dim = y%u_.dim ;\\\n" ) ;
1041
    output ( "\tx%u_ [2].ag_ptr = y%u_.elems.vec ;\\\n" ) ;
1042
    output ( "\tx%u_ [3].ag_ptr = y%u_.elems.ptr ;\\\n" ) ;
1043
    output ( "\tx%u_->ag_ptr = ( B ) ;\\\n" ) ;
1044
    output ( "\t( C ) = x%u_ ;\\\n" ) ;
1045
    output ( "    }\n\n" ) ;
1046
    unique++ ;
1047
 
1048
    /* Vector list deconstructor */
1049
    output ( "#define UN_CONS_vec( A, B, C )\\\n" ) ;
1050
    output ( "    {\\\n" ) ;
1051
    output ( "\t%X *x%u_ = %s( C ) ;\\\n", check_null ) ;
1052
    output ( "\t%X_VEC *y%u_ = &( A ) ;\\\n" ) ;
1053
    output ( "\ty%u_->dim = x%u_ [1].ag_dim ;\\\n" ) ;
1054
    output ( "\ty%u_->elems.vec = x%u_ [2].ag_ptr ;\\\n" ) ;
1055
    output ( "\ty%u_->elems.ptr = x%u_ [3].ag_ptr ;\\\n" ) ;
1056
    output ( "\t( B ) = x%u_->ag_ptr ;\\\n" ) ;
1057
    output ( "    }\n\n" ) ;
1058
    unique++ ;
1059
 
1060
    /* Vector list destructor */
1061
    output ( "#define DESTROY_CONS_vec( D, A, B, C )\\\n" ) ;
1062
    output ( "    {\\\n" ) ;
1063
    output ( "\t%X *x%u_ = %s( C ) ;\\\n", check_null ) ;
1064
    output ( "\t%X_VEC *y%u_ = &( A ) ;\\\n" ) ;
1065
    output ( "\ty%u_->dim = x%u_ [1].ag_dim ;\\\n" ) ;
1066
    output ( "\ty%u_->elems.vec = x%u_ [2].ag_ptr ;\\\n" ) ;
1067
    output ( "\ty%u_->elems.ptr = x%u_ [3].ag_ptr ;\\\n" ) ;
1068
    output ( "\t( B ) = x%u_->ag_ptr ;\\\n" ) ;
1069
    output ( "\t( D ) ( x%u_, ( unsigned ) 4 ) ;\\\n" ) ;
1070
    output ( "    }\n\n" ) ;
1071
    unique++ ;
1072
 
1073
    if ( allow_stack ) {
1074
	/* Vector stack constructor */
1075
	output ( "#define PUSH_vec( A, B )\\\n" ) ;
1076
	output ( "    {\\\n" ) ;
1077
	output ( "\t%X **r%u_ = &( B ) ;\\\n" ) ;
1078
	g = gen ( SIZE_VEC + 1, "stack" ) ;
1079
	output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
1080
	output ( "\t%X_VEC y%u_ ;\\\n" ) ;
1081
	output ( "\ty%u_ = ( A ) ;\\\n" ) ;
1082
	output ( "\tx%u_ [1].ag_dim = y%u_.dim ;\\\n" ) ;
1083
	output ( "\tx%u_ [2].ag_ptr = y%u_.elems.vec ;\\\n" ) ;
1084
	output ( "\tx%u_ [3].ag_ptr = y%u_.elems.ptr ;\\\n" ) ;
1085
	output ( "\tx%u_->ag_ptr = *r%u_ ;\\\n" ) ;
1086
	output ( "\t*r%u_ = x%u_ ;\\\n" ) ;
1087
	output ( "    }\n\n" ) ;
1088
	unique++ ;
1089
 
1090
	/* Vector stack destructor */
1091
	output ( "#define POP_vec( A, B )\\\n" ) ;
1092
	output ( "    {\\\n" ) ;
1093
	output ( "\t%X **r%u_ = &( B ) ;\\\n" ) ;
1094
	output ( "\t%X *x%u_ = %s( *r%u_ ) ;\\\n", check_null ) ;
1095
	output ( "\t%X_VEC *y%u_ = &( A ) ;\\\n" ) ;
1096
	output ( "\ty%u_->dim = x%u_ [1].ag_dim ;\\\n" ) ;
1097
	output ( "\ty%u_->elems.vec = x%u_ [2].ag_ptr ;\\\n" ) ;
1098
	output ( "\ty%u_->elems.ptr = x%u_ [3].ag_ptr ;\\\n" ) ;
1099
	output ( "\t*r%u_ = x%u_->ag_ptr ;\\\n" ) ;
1100
	output ( "\tdestroy_%X ( x%u_, ( unsigned ) 4 ) ;\\\n" ) ;
1101
	output ( "    }\n\n" ) ;
1102
	unique++ ;
1103
    }
1104
 
1105
    output ( "\n" ) ;
1106
    return ;
1107
}
1108
 
1109
 
1110
/*
1111
    PRINT VECTOR POINTER CONSTRUCTS (C VERSION)
1112
 
1113
    This routine prints the C versions of the vector pointer constructs.
1114
*/
1115
 
1116
static void print_vec_ptr_c
1117
    PROTO_Z ()
1118
{
1119
    /* Vector pointers */
1120
    char *g ;
1121
    comment ( "Definitions for vector pointers" ) ;
1122
    output ( "#define VEC_PTR_vec( A )%t40( ( A ).elems )\n" ) ;
1123
    output ( "#define PTR_vec_ptr( A )%t40( ( A ).ptr )\n" ) ;
1124
    output ( "#define SIZE_vec_ptr( A )%t40%d\n\n", SIZE_VEC_PTR ) ;
1125
 
1126
    /* Vector pointer assignment */
1127
    output ( "#define COPY_vec_ptr( A, B )\\\n" ) ;
1128
    output ( "    {\\\n" ) ;
1129
    output ( "\t%X *x%u_ = %s( A ) ;\\\n", check_null ) ;
1130
    output ( "\t%X_VEC_PTR y%u_ ;\\\n" ) ;
1131
    output ( "\ty%u_ = ( B ) ;\\\n" ) ;
1132
    output ( "\tx%u_->ag_ptr = y%u_.vec ;\\\n" ) ;
1133
    output ( "\tx%u_ [1].ag_ptr = y%u_.ptr ;\\\n" ) ;
1134
    output ( "    }\n\n" ) ;
1135
    unique++ ;
1136
 
1137
    /* Vector pointer dereference */
1138
    output ( "#define DEREF_vec_ptr( A, B )\\\n" ) ;
1139
    output ( "    {\\\n" ) ;
1140
    output ( "\t%X *x%u_ = %s( A ) ;\\\n", check_null ) ;
1141
    output ( "\t%X_VEC_PTR *y%u_ = &( B ) ;\\\n" ) ;
1142
    output ( "\ty%u_->vec = x%u_->ag_ptr ;\\\n" ) ;
1143
    output ( "\ty%u_->ptr = x%u_ [1].ag_ptr ;\\\n" ) ;
1144
    output ( "    }\n\n" ) ;
1145
    unique++ ;
1146
 
1147
    /* Vector pointer list constructor */
1148
    output ( "#define CONS_vec_ptr( A, B, C )\\\n" ) ;
1149
    output ( "    {\\\n" ) ;
1150
    g = gen ( SIZE_VEC_PTR + 1, "list" ) ;
1151
    output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
1152
    output ( "\t%X_VEC_PTR y%u_ ;\\\n" ) ;
1153
    output ( "\ty%u_ = ( A ) ;\\\n" ) ;
1154
    output ( "\tx%u_ [1].ag_ptr = y%u_.vec ;\\\n" ) ;
1155
    output ( "\tx%u_ [2].ag_ptr = y%u_.ptr ;\\\n" ) ;
1156
    output ( "\tx%u_->ag_ptr = ( B ) ;\\\n" ) ;
1157
    output ( "\t( C ) = x%u_ ;\\\n" ) ;
1158
    output ( "    }\n\n" ) ;
1159
    unique++ ;
1160
 
1161
    /* Vector pointer list deconstructor */
1162
    output ( "#define UN_CONS_vec_ptr( A, B, C )\\\n" ) ;
1163
    output ( "    {\\\n" ) ;
1164
    output ( "\t%X *x%u_ = %s( C ) ;\\\n", check_null ) ;
1165
    output ( "\t%X_VEC_PTR *y%u_ = &( A ) ;\\\n" ) ;
1166
    output ( "\ty%u_->vec = x%u_ [1].ag_ptr ;\\\n" ) ;
1167
    output ( "\ty%u_->ptr = x%u_ [2].ag_ptr ;\\\n" ) ;
1168
    output ( "\t( B ) = x%u_->ag_ptr ;\\\n" ) ;
1169
    output ( "    }\n\n" ) ;
1170
    unique++ ;
1171
 
1172
    /* Vector pointer list destructor */
1173
    output ( "#define DESTROY_CONS_vec_ptr( D, A, B, C )\\\n" ) ;
1174
    output ( "    {\\\n" ) ;
1175
    output ( "\t%X *x%u_ = %s( C ) ;\\\n", check_null ) ;
1176
    output ( "\t%X_VEC_PTR *y%u_ = &( A ) ;\\\n" ) ;
1177
    output ( "\ty%u_->vec = x%u_ [1].ag_ptr ;\\\n" ) ;
1178
    output ( "\ty%u_->ptr = x%u_ [2].ag_ptr ;\\\n" ) ;
1179
    output ( "\t( B ) = x%u_->ag_ptr ;\\\n" ) ;
1180
    output ( "\t( D ) ( x%u_, ( unsigned ) 3 ) ;\\\n" ) ;
1181
    output ( "    }\n\n" ) ;
1182
    unique++ ;
1183
 
1184
    if ( allow_stack ) {
1185
	/* Vector stack constructor */
1186
	output ( "#define PUSH_vec_ptr( A, B )\\\n" ) ;
1187
	output ( "    {\\\n" ) ;
1188
	output ( "\t%X **r%u_ = &( B ) ;\\\n" ) ;
1189
	g = gen ( SIZE_VEC_PTR + 1, "stack" ) ;
1190
	output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
1191
	output ( "\t%X_VEC_PTR y%u_ ;\\\n" ) ;
1192
	output ( "\ty%u_ = ( A ) ;\\\n" ) ;
1193
	output ( "\tx%u_ [1].ag_ptr = y%u_.vec ;\\\n" ) ;
1194
	output ( "\tx%u_ [2].ag_ptr = y%u_.ptr ;\\\n" ) ;
1195
	output ( "\tx%u_->ag_ptr = *r%u_ ;\\\n" ) ;
1196
	output ( "\t*r%u_ = x%u_ ;\\\n" ) ;
1197
	output ( "    }\n\n" ) ;
1198
	unique++ ;
1199
 
1200
	/* Vector stack destructor */
1201
	output ( "#define POP_vec_ptr( A, B )\\\n" ) ;
1202
	output ( "    {\\\n" ) ;
1203
	output ( "\t%X **r%u_ = &( B ) ;\\\n" ) ;
1204
	output ( "\t%X *x%u_ = %s( *r%u_ ) ;\\\n", check_null ) ;
1205
	output ( "\t%X_VEC *y%u_ = &( A ) ;\\\n" ) ;
1206
	output ( "\ty%u_->vec = x%u_ [1].ag_ptr ;\\\n" ) ;
1207
	output ( "\ty%u_->ptr = x%u_ [2].ag_ptr ;\\\n" ) ;
1208
	output ( "\t*r%u_ = x%u_->ag_ptr ;\\\n" ) ;
1209
	output ( "\tdestroy_%X ( x%u_, ( unsigned ) 3 ) ;\\\n" ) ;
1210
	output ( "    }\n\n" ) ;
1211
	unique++ ;
1212
    }
1213
 
1214
    output ( "\n" ) ;
1215
    return ;
1216
}
1217
 
1218
 
1219
/*
1220
    PRINT SIZE CONSTRUCTS (C VERSION)
1221
 
1222
    This routine prints the C versions of the size constructs.
1223
*/
1224
 
1225
static void print_size_c
1226
    PROTO_Z ()
1227
{
1228
    comment ( "Definitions for sizes" ) ;
1229
    output ( "#define SCALE( A, B )%t40( ( A ) * ( int ) ( B ) )\n\n\n" ) ;
1230
    return ;
1231
}
1232
 
1233
 
1234
/*
1235
    PRINT PRIMITIVE CONSTRUCTS (C VERSION)
1236
 
1237
    This routine prints the C versions of the primitive constructs.
1238
*/
1239
 
1240
static void print_prim_c
1241
    PROTO_Z ()
1242
{
1243
    comment ( "Definitions for primitive %PN" ) ;
1244
    output ( "#define SIZE_%PM%t40%d\n\n", SIZE_PRIM ) ;
1245
    output ( "#define COPY_%PM( A, B )%t40" ) ;
1246
    output ( "( %s( A )->ag_prim_%PM = ( B ) )\n", check_null ) ;
1247
    output ( "#define DEREF_%PM( A )%t40" ) ;
1248
    output ( "( %s( A )->ag_prim_%PM )\n", check_null ) ;
1249
    print_simple_cons ( "%PM", SIZE_PRIM, 1 ) ;
1250
    return ;
1251
}
1252
 
1253
 
1254
/*
1255
    PRINT ENUMERATION CONSTANTS
1256
 
1257
    This routine prints the definitions of the enumeration constants.
1258
*/
1259
 
1260
void print_enum_consts
1261
    PROTO_Z ()
1262
{
1263
    number n = DEREF_number ( en_order ( CRT_ENUM ) ) ;
1264
    if ( n > ( number ) 0x10000 ) {
1265
	output ( "#ifdef __STDC__\n" ) ;
1266
	LOOP_ENUM_CONST output ( "#define %EM_%ES%t40( ( %EN ) %EVUL )\n" ) ;
1267
	output ( "#define ORDER_%EM%t40( %EOUL )\n" ) ;
1268
	output ( "#else\n" ) ;
1269
    }
1270
    LOOP_ENUM_CONST output ( "#define %EM_%ES%t40( ( %EN ) %EV )\n" ) ;
1271
    output ( "#define ORDER_%EM%t40( ( unsigned long ) %EO )\n" ) ;
1272
    if ( n > ( number ) 0x10000 ) {
1273
	output ( "#endif\n" ) ;
1274
    }
1275
    return ;
1276
}
1277
 
1278
 
1279
/*
1280
    PRINT ENUMERATION CONSTRUCTS (C VERSION)
1281
 
1282
    This routine prints the C versions of the enumeration constructs.
1283
*/
1284
 
1285
static void print_enum_c
1286
    PROTO_Z ()
1287
{
1288
    char *fld = "ag_enum" ;
1289
    number n = DEREF_number ( en_order ( CRT_ENUM ) ) ;
1290
    if ( n > ( number ) 0x10000 ) fld = "ag_long_enum" ;
1291
    comment ( "Definitions for enumeration %EN" ) ;
1292
    print_enum_consts () ;
1293
    output ( "#define SIZE_%EM%t40%d\n\n", SIZE_ENUM ) ;
1294
    output ( "#define COPY_%EM( A, B )%t40" ) ;
1295
    output ( "( %s( A )->%s = ( B ) )\n", check_null, fld ) ;
1296
    output ( "#define DEREF_%EM( A )%t40" ) ;
1297
    output ( "( %s( A )->%s )\n", check_null, fld ) ;
1298
    if ( DEREF_int ( en_lists ( CRT_ENUM ) ) ) {
1299
	print_simple_cons ( "%EM", SIZE_ENUM, 1 ) ;
1300
    } else {
1301
	output ( "\n\n" ) ;
1302
    }
1303
    return ;
1304
}
1305
 
1306
 
1307
/*
1308
    PRINT STRUCTURE CONSTRUCTS (C VERSION)
1309
 
1310
    This routine prints the C versions of the structure constructs.
1311
*/
1312
 
1313
static void print_struct_c
1314
    PROTO_Z ()
1315
{
1316
    /* Structure constructors etc. */
1317
    int posn ;
1318
    int sz = 0 ;
1319
    STRUCTURE_P base = DEREF_ptr ( str_base ( CRT_STRUCTURE ) ) ;
1320
 
1321
    comment ( "Definitions for structure %SN" ) ;
1322
    LOOP_STRUCTURE_COMPONENT {
1323
	TYPE_P ct = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
1324
	output ( "#define %SM_%CN( P )%t40" ) ;
1325
	output ( "( ( P ) + %d )\n", sz ) ;
1326
	sz += size_type ( ct, 0 ) ;
1327
    }
1328
    output ( "#define SIZE_%SM%t40%d\n\n", sz ) ;
1329
 
1330
    output ( "#define COPY_%SM( A, B )\\\n" ) ;
1331
    output ( "    {\\\n" ) ;
1332
    output ( "\t%X *x%u_ = %s( A ) ;\\\n", check_null ) ;
1333
    output ( "\t%SN y%u_ ;\\\n" ) ;
1334
    output ( "\ty%u_ = ( B ) ;\\\n" ) ;
1335
    posn = 0 ;
1336
    LOOP_STRUCTURE_COMPONENT {
1337
	TYPE_P ct = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
1338
	posn = assign_component ( ct, posn, "y%u_.%CN", 0 ) ;
1339
    }
1340
    output ( "    }\n\n" ) ;
1341
    unique++ ;
1342
 
1343
    output ( "#define DEREF_%SM( A, B )\\\n" ) ;
1344
    output ( "    {\\\n" ) ;
1345
    output ( "\t%X *x%u_ = %s( A ) ;\\\n", check_null ) ;
1346
    output ( "\t%SN *y%u_ = &( B ) ;\\\n" ) ;
1347
    posn = 0 ;
1348
    LOOP_STRUCTURE_COMPONENT {
1349
	TYPE_P ct = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
1350
	posn = deref_component ( ct, posn, "y%u_->%CN", 0 ) ;
1351
    }
1352
    output ( "    }\n\n" ) ;
1353
    unique++ ;
1354
 
1355
    output ( "#define MAKE_%SM( " ) ;
1356
    LOOP_STRUCTURE_COMPONENT {
1357
	string v = DEREF_string ( cmp_value ( CRT_COMPONENT ) ) ;
1358
	if ( v == NULL ) output ( "%CN_, " ) ;
1359
    }
1360
    output ( "%SM_ )\\\n" ) ;
1361
    output ( "    {\\\n" ) ;
1362
    output ( "\t%X *x%u_ = %s( %SM_ ) ;\\\n", check_null ) ;
1363
    posn = 0 ;
1364
    LOOP_STRUCTURE_COMPONENT {
1365
	TYPE_P ct = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
1366
	string v = DEREF_string ( cmp_value ( CRT_COMPONENT ) ) ;
1367
	if ( v == NULL ) v = "( %CN_ )" ;
1368
	posn = assign_component ( ct, posn, v, 0 ) ;
1369
    }
1370
    output ( "    }\n\n" ) ;
1371
    unique++ ;
1372
 
1373
    if ( !IS_NULL_ptr ( base ) ) {
1374
	CLASS_ID_P id = DEREF_ptr ( str_id ( base ) ) ;
1375
	char *nm = DEREF_string ( cid_name_aux ( id ) ) ;
1376
	output ( "#define CONVERT_%SM_%s( P )%t40( P )\n\n", nm ) ;
1377
    }
1378
 
1379
    print_simple_cons ( "%SM", sz, 0 ) ;
1380
    return ;
1381
}
1382
 
1383
 
1384
/*
1385
    PRINT UNION CONSTRUCTS (C VERSION)
1386
 
1387
    This routine prints the C versions of the union constructs.
1388
*/
1389
 
1390
static void print_union_c
1391
    PROTO_Z ()
1392
{
1393
    UNION_P base = DEREF_ptr ( un_base ( CRT_UNION ) ) ;
1394
 
1395
    comment ( "Definitions for union %UN" ) ;
1396
    output ( "#define ORDER_%UM%t40( ( unsigned ) %UO )\n" ) ;
1397
    output ( "#define SIZE_%UM%t40%d\n", SIZE_UNION ) ;
1398
    output ( "#define NULL_%UM%t40( ( %UN ) 0 )\n" ) ;
1399
    output ( "#define IS_NULL_%UM( A )%t40( ( A ) == 0 )\n" ) ;
1400
    output ( "#define EQ_%UM( A, B )%t40( ( A ) == ( B ) )\n\n" ) ;
1401
    output ( "#define COPY_%UM( A, B )%t40" ) ;
1402
    output ( "( %s( A )->ag_ptr = ( B ) )\n", check_null ) ;
1403
    output ( "#define DEREF_%UM( A )%t40" ) ;
1404
    output ( "( %s( A )->ag_ptr )\n\n", check_null ) ;
1405
 
1406
    if ( !IS_NULL_ptr ( base ) ) {
1407
	CLASS_ID_P id = DEREF_ptr ( un_id ( base ) ) ;
1408
	char *nm = DEREF_string ( cid_name_aux ( id ) ) ;
1409
	output ( "#define CONVERT_%UM_%s( P )%t40( P )\n\n", nm ) ;
1410
    }
1411
 
1412
    print_simple_cons ( "%UM", SIZE_UNION, 1 ) ;
1413
    return ;
1414
}
1415
 
1416
 
1417
/*
1418
    PRINT THE MAIN OUTPUT FILE
1419
 
1420
    This routine prints the main output file, describing the implementation
1421
    of the various types described in the calculus.
1422
*/
1423
 
1424
static void print_main_c
1425
    PROTO_Z ()
1426
{
1427
    if ( extra_headers ) {
1428
	output ( "#include \"%s_bscs.h\"\n\n", MAIN_PREFIX ) ;
1429
    }
1430
    output ( "#ifndef %X_NAME\n" ) ;
1431
    output ( "#define %X_NAME%t40\"%X\"\n" ) ;
1432
    output ( "#define %X_VERSION%t40\"%V\"\n" ) ;
1433
    output ( "#define %X_SPECIFICATION%t40%d\n", 0 ) ;
1434
    output ( "#define %X_IMPLEMENTATION%t40%d\n", 1 ) ;
1435
    output ( "#endif\n\n\n" ) ;
1436
 
1437
    print_proto () ;
1438
    print_types_c () ;
1439
    print_ptr_c () ;
1440
    print_list_c () ;
1441
    if ( allow_stack ) {
1442
	print_stack_c () ;
1443
    }
1444
    if ( allow_vec ) {
1445
	print_vec_c () ;
1446
	print_vec_ptr_c () ;
1447
    }
1448
    print_size_c () ;
1449
 
1450
    LOOP_PRIMITIVE print_prim_c () ;
1451
    LOOP_ENUM print_enum_c () ;
1452
    LOOP_STRUCTURE print_struct_c () ;
1453
    LOOP_UNION print_union_c () ;
1454
 
1455
    if ( extra_headers ) {
1456
	output ( "#include \"%s_term.h\"\n\n", MAIN_PREFIX ) ;
1457
    }
1458
    return ;
1459
}
1460
 
1461
 
1462
/*
1463
    PRINT ARGUMENTS FOR A UNION CONSTRUCTOR
1464
 
1465
    This routine prints the list of arguments for a union constructor and
1466
    similar functions.
1467
*/
1468
 
1469
static void print_cons_args
1470
    PROTO_N ( ( d, suff ) )
1471
    PROTO_T ( int d X char *suff )
1472
{
1473
    LOOP_UNION_COMPONENT {
1474
	string v = DEREF_string ( cmp_value ( CRT_COMPONENT ) ) ;
1475
	if ( v == NULL || d == 0 ) output ( "%CN%s, ", suff ) ;
1476
    }
1477
    LOOP_FIELD_COMPONENT {
1478
	string v = DEREF_string ( cmp_value ( CRT_COMPONENT ) ) ;
1479
	if ( v == NULL || d == 0 ) output ( "%CN%s, ", suff ) ;
1480
    }
1481
    output ( "%X_%UM" ) ;
1482
    return ;
1483
}
1484
 
1485
 
1486
/*
1487
    DOES THE CURRENT FIELD HAVE ANY COMPONENTS?
1488
 
1489
    This routine returns 1 if the current field of the current union has
1490
    a component, and 0 otherwise.
1491
*/
1492
 
1493
int field_not_empty
1494
    PROTO_Z ()
1495
{
1496
    LIST ( COMPONENT_P ) c ;
1497
    c = DEREF_list ( un_s_defn ( CRT_UNION ) ) ;
1498
    if ( !IS_NULL_list ( c ) ) return ( 1 ) ;
1499
    c = DEREF_list ( fld_defn ( CRT_FIELD ) ) ;
1500
    if ( !IS_NULL_list ( c ) ) return ( 1 ) ;
1501
    return ( 0 ) ;
1502
}
1503
 
1504
 
1505
/*
1506
    PRINT FIELD SELECTOR OPERATIONS
1507
 
1508
    This routine prints the operations on field selectors (C version).
1509
    sz gives the size of the common union components.  tag is the field
1510
    tag number (or -1 for untagged unions).  rng gives the number of
1511
    elements in the field set (if appropriate).  al is true if the
1512
    field is aliased.
1513
*/
1514
 
1515
static void print_field_c
1516
    PROTO_N ( ( sz, tag, rng, al ) )
1517
    PROTO_T ( int sz X int tag X int rng X int al )
1518
{
1519
    char *g ;
1520
    int posn = 0 ;
1521
    char *f = ( rng ? "%FN_etc" : "%FN" ) ;
1522
 
1523
    LOOP_FIELD_COMPONENT {
1524
	TYPE_P ct = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
1525
	output ( "#define %UM_%e_%CN( P )%t40", f ) ;
1526
	if ( extra_asserts && tag != -1 ) {
1527
	    if ( rng ) {
1528
		output ( "( CHECK_TAG_ETC ( ( P ), %d, %d ) + %d )\n",
1529
			 tag, tag + rng, sz ) ;
1530
	    } else {
1531
		output ( "( CHECK_TAG ( ( P ), %d ) + %d )\n", tag, sz ) ;
1532
	    }
1533
	} else {
1534
	    output ( "( ( P ) + %d )\n", sz ) ;
1535
	}
1536
	sz += size_type ( ct, 0 ) ;
1537
    }
1538
 
1539
    /* Component constructor */
1540
    output ( "\n#define MAKE_%UM_%e( ", f ) ;
1541
    if ( rng ) output ( "tag, " ) ;
1542
    print_cons_args ( 1, "_" ) ;
1543
    output ( " )\\\n" ) ;
1544
    output ( "    {\\\n" ) ;
1545
    g = gen ( sz + al, "%UM" ) ;
1546
    output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
1547
    if ( tag != -1 ) {
1548
	if ( rng ) {
1549
	    output ( "\tx%u_->ag_tag = ( tag ) ;\\\n" ) ;
1550
	} else {
1551
	    output ( "\tx%u_->ag_tag = %d ;\\\n", tag ) ;
1552
	}
1553
	posn = 1 ;
1554
    }
1555
    LOOP_UNION_COMPONENT {
1556
	TYPE_P ct = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
1557
	string v = DEREF_string ( cmp_value ( CRT_COMPONENT ) ) ;
1558
	if ( v == NULL ) v = "( %CN_ )" ;
1559
	posn = assign_component ( ct, posn, v, 0 ) ;
1560
    }
1561
    LOOP_FIELD_COMPONENT {
1562
	TYPE_P ct = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
1563
	string v = DEREF_string ( cmp_value ( CRT_COMPONENT ) ) ;
1564
	if ( v == NULL ) v = "( %CN_ )" ;
1565
	posn = assign_component ( ct, posn, v, 0 ) ;
1566
    }
1567
    if ( al ) output ( "\tx%u_ [%d].ag_tag = 0 ;\\\n", sz ) ;
1568
    if ( rng && extra_asserts ) {
1569
	output ( "\t( %X_%UM ) = CHECK_TAG_ETC ( x%u_, %d, %d ) ;\\\n",
1570
		 tag, tag + rng ) ;
1571
    } else {
1572
	output ( "\t( %X_%UM ) = x%u_ ;\\\n" ) ;
1573
    }
1574
    output ( "    }\n\n" ) ;
1575
    unique++ ;
1576
 
1577
    /* Tag modifier */
1578
    if ( rng ) {
1579
	output ( "#define MODIFY_%UM_%e( tag, %X_%UM )\\\n", f ) ;
1580
	output ( "    {\\\n" ) ;
1581
	if ( extra_asserts ) {
1582
	    output ( "\t%X *x%u_ = CHECK_TAG_ETC" ) ;
1583
	    output ( " ( ( %X_%UM ), %d, %d ) ;\\\n", tag, tag + rng ) ;
1584
	    output ( "\tx%u_->ag_tag = ( tag ) ;\\\n" ) ;
1585
	    output ( "\t( void ) CHECK_TAG_ETC" ) ;
1586
	    output ( " ( x%u_, %d, %d ) ;\\\n", tag, tag + rng ) ;
1587
	} else {
1588
	    output ( "\t( %X_%UM )->ag_tag = ( tag ) ;\\\n" ) ;
1589
	}
1590
	output ( "    }\n\n" ) ;
1591
	unique++ ;
1592
    }
1593
 
1594
    /* Component deconstructor */
1595
    if ( field_not_empty () ) {
1596
	output ( "#define DECONS_%UM_%e( ", f ) ;
1597
	print_cons_args ( 0, "_" ) ;
1598
	output ( " )\\\n" ) ;
1599
	output ( "    {\\\n" ) ;
1600
	output ( "\t%X *x%u_ = " ) ;
1601
	if ( tag != -1 ) {
1602
	    if ( extra_asserts ) {
1603
		if ( rng ) {
1604
		    output ( "CHECK_TAG_ETC ( ( %X_%UM ), %d, %d ) ;\\\n",
1605
			      tag, tag + rng ) ;
1606
		} else {
1607
		    output ( "CHECK_TAG ( ( %X_%UM ), %d ) ;\\\n", tag ) ;
1608
		}
1609
	    } else {
1610
		output ( "( %X_%UM ) ;\\\n" ) ;
1611
	    }
1612
	    posn = 1 ;
1613
	} else {
1614
	    output ( "( %X_%UM ) ;\\\n" ) ;
1615
	    posn = 0 ;
1616
	}
1617
	LOOP_UNION_COMPONENT {
1618
	    TYPE_P ct = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
1619
	    posn = deref_component ( ct, posn, "( %CN_ )", 0 ) ;
1620
	}
1621
	LOOP_FIELD_COMPONENT {
1622
	    TYPE_P ct = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
1623
	    posn = deref_component ( ct, posn, "( %CN_ )", 0 ) ;
1624
	}
1625
	output ( "    }\n\n" ) ;
1626
	unique++ ;
1627
    }
1628
 
1629
    /* Component destructor */
1630
    output ( "#define DESTROY_%UM_%e( destroyer_, ", f ) ;
1631
    print_cons_args ( 0, "_" ) ;
1632
    output ( " )\\\n" ) ;
1633
    output ( "    {\\\n" ) ;
1634
    output ( "\t%X *x%u_ = " ) ;
1635
    if ( tag != -1 ) {
1636
	if ( extra_asserts ) {
1637
	    if ( rng ) {
1638
		output ( "CHECK_TAG_ETC ( ( %X_%UM ), %d, %d ) ;\\\n",
1639
			 tag, tag + rng ) ;
1640
	    } else {
1641
		output ( "CHECK_TAG ( ( %X_%UM ), %d ) ;\\\n", tag ) ;
1642
	    }
1643
	} else {
1644
	    output ( "( %X_%UM ) ;\\\n" ) ;
1645
	}
1646
	posn = 1 ;
1647
    } else {
1648
	output ( "( %X_%UM ) ;\\\n" ) ;
1649
	posn = 0 ;
1650
    }
1651
    LOOP_UNION_COMPONENT {
1652
	TYPE_P ct = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
1653
	posn = deref_component ( ct, posn, "( %CN_ )", 0 ) ;
1654
    }
1655
    LOOP_FIELD_COMPONENT {
1656
	TYPE_P ct = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
1657
	posn = deref_component ( ct, posn, "( %CN_ )", 0 ) ;
1658
    }
1659
    output ( "\t( destroyer_ ) ( x%u_, ( unsigned ) %d ) ;\\\n", sz + al ) ;
1660
    output ( "    }\n\n" ) ;
1661
    unique++ ;
1662
 
1663
    /* Aliasing commands */
1664
    if ( al && !rng ) {
1665
	output ( "#ifdef %X_IO_ROUTINES\n\n" ) ;
1666
	output ( "#define NEW_ALIAS_%UM_%FN( P, N )\\\n" ) ;
1667
	output ( "    {\\\n" ) ;
1668
	g = gen ( sz + al, "list" ) ;
1669
	output ( "\t%X *x%u_ = %e ;\\\n", g ) ;
1670
	output ( "\tunsigned a%u_ = ( N ) ;\\\n" ) ;
1671
	if ( tag != -1 ) output ( "\tx%u_->ag_tag = %d ;\\\n", tag ) ;
1672
	output ( "\tx%u_ [%d].ag_tag = a%u_ ;\\\n", sz ) ;
1673
	output ( "\tset_%X_alias ( x%u_ + %d, a%u_ ) ;\\\n", sz ) ;
1674
	output ( "\t( P ) = x%u_ ;\\\n" ) ;
1675
	output ( "    }\n\n" ) ;
1676
	unique++ ;
1677
 
1678
	output ( "#define GET_ALIAS_%UM_%FN( P )%t40" ) ;
1679
	output ( "( ( %s( P ) + %d )->ag_tag )\n", check_null, sz ) ;
1680
	output ( "#define SET_ALIAS_%UM_%FN( P, N )%t40" ) ;
1681
	output ( "set_%X_alias ( %s( P ) + %d, ( N ) )\n", check_null, sz ) ;
1682
	output ( "#define FIND_ALIAS_%UM_%FN( N )%t40" ) ;
1683
	output ( "( find_%X_alias ( N ) - %d )\n\n", sz ) ;
1684
	output ( "#endif\n\n" ) ;
1685
    }
1686
    output ( "\n" ) ;
1687
    return ;
1688
}
1689
 
1690
 
1691
/*
1692
    PRINT DECLARATION FOR A UNION MAP TABLE
1693
 
1694
    This routine prints the type of the current map table.
1695
*/
1696
 
1697
static void print_map_table
1698
    PROTO_N ( ( d ) )
1699
    PROTO_T ( int d )
1700
{
1701
    output ( "%MR ( *%MN_%UM_table [ ORDER_%UM ] )" ) ;
1702
    if ( map_proto ) {
1703
	output ( "\n    PROTO_S ( ( %UN" ) ;
1704
	if ( d ) output ( ", DESTROYER" ) ;
1705
	LOOP_MAP_ARGUMENT output ( ", %AT" ) ;
1706
	output ( " ) )" ) ;
1707
    } else {
1708
	output ( " ()" ) ;
1709
    }
1710
    return ;
1711
}
1712
 
1713
 
1714
/*
1715
    PRINT ARGUMENTS FOR A UNION MAP
1716
 
1717
    This routine prints the list of arguments for the current map.  The
1718
    argument d, if present, gives the destructor argument.
1719
*/
1720
 
1721
void print_map_args
1722
    PROTO_N ( ( d ) )
1723
    PROTO_T ( char *d )
1724
{
1725
    output ( "( %X_%UM" ) ;
1726
    if ( d ) output ( ", %e", d ) ;
1727
    LOOP_MAP_ARGUMENT output ( ", %AN" ) ;
1728
    output ( " )" ) ;
1729
    return ;
1730
}
1731
 
1732
 
1733
/*
1734
    PRINT THE UNION OPERATIONS OUTPUT FILE
1735
 
1736
    For each union in the calculus there is an operations file.
1737
*/
1738
 
1739
void print_union_ops_c
1740
    PROTO_N ( ( dir, un ) )
1741
    PROTO_T ( char *dir X char *un )
1742
{
1743
    int sz = 1 ;
1744
    int tag = 0 ;
1745
    int is_tagged = 1 ;
1746
    open_file ( dir, un, OPS_SUFFIX ) ;
1747
    if ( extra_headers ) {
1748
	output ( "#include \"%s%s\"\n", MAIN_PREFIX, MAIN_SUFFIX ) ;
1749
	output ( "#include <%s_ops.h>\n\n", MAIN_PREFIX ) ;
1750
    }
1751
 
1752
    /* Check for unions with one field */
1753
    LOOP_UNION_FIELD tag++ ;
1754
    if ( tag < 2 ) {
1755
	sz = 0 ;
1756
	is_tagged = 0 ;
1757
    }
1758
 
1759
    comment ( "Operations for union %UN" ) ;
1760
    output ( "#define TAG_%UM( P )%t40", check_null ) ;
1761
    if ( is_tagged ) {
1762
	output ( "( %s( P )->ag_tag )\n\n\n", check_null ) ;
1763
    } else {
1764
	output ( "( ( unsigned ) 0 )\n\n\n" ) ;
1765
    }
1766
 
1767
    /* Operations on common components */
1768
    LOOP_UNION_COMPONENT {
1769
	TYPE_P ct = DEREF_ptr ( cmp_type ( CRT_COMPONENT ) ) ;
1770
	comment ( "Operations for component %CN of union %UN" ) ;
1771
	output ( "#define %UM_%CN( P )%t40" ) ;
1772
	output ( "( %s( P ) + %d )\n\n\n", check_null, sz ) ;
1773
	sz += size_type ( ct, 0 ) ;
1774
    }
1775
 
1776
    /* Operations on field components */
1777
    tag = 0 ;
1778
    LOOP_UNION_FIELD {
1779
	int rng = DEREF_int ( fld_set ( CRT_FIELD ) ) ;
1780
	int hash = DEREF_int ( fld_flag ( CRT_FIELD ) ) ;
1781
	int al = ( hash ? 1 : 0 ) ;
1782
 
1783
	if ( rng ) {
1784
	    comment ( "Operations for field set %FN_etc of union %UN" ) ;
1785
	    output ( "#define %UM_%FN_etc_tag%t40( ( unsigned ) %d )\n",
1786
		     tag + rng ) ;
1787
	    output ( "#define IS_%UM_%FN_etc( P )%t40" ) ;
1788
	    output ( "( ( unsigned ) ( %s( P )->ag_tag - %d )",
1789
		     check_null, tag ) ;
1790
	    output ( " < ( unsigned ) %d )\n\n", rng ) ;
1791
	    print_field_c ( sz, tag, rng, al ) ;
1792
	}
1793
 
1794
	comment ( "Operations for field %FN of union %UN" ) ;
1795
	output ( "#define %UM_%FN_tag%t40( ( unsigned ) %d )\n", tag ) ;
1796
	output ( "#define IS_%UM_%FN( P )%t40" ) ;
1797
	if ( is_tagged ) {
1798
	    output ( "( %s( P )->ag_tag == %d )\n\n", check_null, tag ) ;
1799
	    print_field_c ( sz, tag, 0, al ) ;
1800
	} else {
1801
	    output ( "1\n\n" ) ;
1802
	    print_field_c ( sz, -1, 0, al ) ;
1803
	}
1804
	ASSERT ( DEREF_int ( fld_tag ( CRT_FIELD ) ) == tag ) ;
1805
	tag++ ;
1806
    }
1807
 
1808
    /* Map tables */
1809
    LOOP_UNION_MAP {
1810
	int hash = DEREF_int ( map_flag ( CRT_MAP ) ) ;
1811
	char *dest = ( hash ? "destroyer" : NULL ) ;
1812
	comment ( "Map %MN on union %UN" ) ;
1813
	output ( "extern " ) ;
1814
	print_map_table ( hash ) ;
1815
	output ( " ;\n\n#define %MN_%UM" ) ;
1816
	print_map_args ( dest ) ;
1817
	output ( "\\\n    ( ( %MN_%UM_table [ " ) ;
1818
	if ( is_tagged ) {
1819
	    if ( extra_asserts ) {
1820
		output ( "CHECK_TAG_ETC ( ( %X_%UM ), 0, ORDER_%UM )" ) ;
1821
	    } else {
1822
		output ( "( %X_%UM )" ) ;
1823
	    }
1824
	    output ( "->ag_tag ] ) " ) ;
1825
	} else {
1826
	    output ( "0 ] ) " ) ;
1827
	}
1828
	print_map_args ( dest ) ;
1829
	output ( " )\n\n\n" ) ;
1830
    }
1831
 
1832
    /* End of file */
1833
    close_file () ;
1834
    return ;
1835
}
1836
 
1837
 
1838
/*
1839
    PRINT A UNION MAPPING TABLE
1840
 
1841
    This routine prints a single union mapping table.
1842
*/
1843
 
1844
static void print_func_tab
1845
    PROTO_N ( ( i ) )
1846
    PROTO_T ( int i )
1847
{
1848
    int hash = DEREF_int ( map_flag ( CRT_MAP ) ) ;
1849
    comment ( "Function table for map %MN on union %UN" ) ;
1850
    if ( i ) output ( "#ifndef IGNORE_%MN_%UM\n\n" ) ;
1851
    print_map_table ( hash ) ;
1852
    output ( " = {\n" ) ;
1853
    LOOP_UNION_FIELD output ( "    %MN_%UM_%FN%F,\n" ) ;
1854
    output ( "} ;\n\n" ) ;
1855
    if ( i ) output ( "#endif\n\n" ) ;
1856
    output ( "\n" ) ;
1857
    return ;
1858
}
1859
 
1860
 
1861
/*
1862
    PRINT A FUNCTION HEADER
1863
 
1864
    This routine prints the function headers required in print_union_hdr_c.
1865
    The argument d is true if this is the destructor version.  The argument
1866
    e is true if this is the header for a field set.
1867
*/
1868
 
1869
static void print_func_hdr
1870
    PROTO_N ( ( d, e ) )
1871
    PROTO_T ( int d X int e )
1872
{
1873
    int hash = DEREF_int ( map_flag ( CRT_MAP ) ) ;
1874
    char *dest = ( d ? "_d_" : "_" ) ;
1875
    char *etc = ( e ? "_etc" : "" ) ;
1876
    output ( "#define HDR_%MN%s%UM_%FN%s\\\n", dest, etc ) ;
1877
 
1878
    /* Function header */
1879
    output ( "    %MR %MN_%UM_%FN\\\n" ) ;
1880
    output ( "\tPROTO_N ( " ) ;
1881
    print_map_args ( hash ? "destroyer" : NULL ) ;
1882
    output ( " )\\\n" ) ;
1883
 
1884
    /* Function argument declarations */
1885
    output ( "\tPROTO_T ( %UN %X_%UM" ) ;
1886
    if ( hash ) output ( " X DESTROYER destroyer" ) ;
1887
    LOOP_MAP_ARGUMENT output ( " X %AT %AN" ) ;
1888
    output ( " )\\\n    {" ) ;
1889
 
1890
    /* Field component declarations */
1891
    LOOP_UNION_COMPONENT output ( "\\\n\t%CT %CN ;" ) ;
1892
    LOOP_FIELD_COMPONENT output ( "\\\n\t%CT %CN ;" ) ;
1893
 
1894
    /* Assignment of field components */
1895
    if ( d ) {
1896
	output ( "\\\n\tDESTROY_%UM_%FN%s ( ", etc ) ;
1897
	output ( hash ? "destroyer, " : "destroy_%X, " ) ;
1898
	print_cons_args ( 0, "" ) ;
1899
	output ( " ) ;" ) ;
1900
    } else {
1901
	if ( field_not_empty () ) {
1902
	    output ( "\\\n\tDECONS_%UM_%FN%s ( ", etc ) ;
1903
	    print_cons_args ( 0, "" ) ;
1904
	    output ( " ) ;" ) ;
1905
	}
1906
    }
1907
    output ( "\n\n" ) ;
1908
    return ;
1909
}
1910
 
1911
 
1912
/*
1913
    PRINT A UNION MAP OUTPUT FILE
1914
 
1915
    For each union with maps in the calculus a file is printed giving the
1916
    tables which give the actions of each map on each union component.
1917
*/
1918
 
1919
void print_union_map_c
1920
    PROTO_N ( ( dir, un ) )
1921
    PROTO_T ( char *dir X char *un )
1922
{
1923
    open_file ( dir, un, MAP_SUFFIX ) ;
1924
    LOOP_UNION_MAP print_func_tab ( 1 ) ;
1925
    close_file () ;
1926
    return ;
1927
}
1928
 
1929
 
1930
/*
1931
    PRINT THE UNION MAPPING HEADERS OUTPUT FILE
1932
 
1933
    For each union with maps in the calculus a file is printed giving the
1934
    function headers for the actions in the previous file.  Note that two
1935
    versions of the header are given - a deconstructor and a destructor
1936
    version.  Also versions are given for any field sets.
1937
*/
1938
 
1939
void print_union_hdr_c
1940
    PROTO_N ( ( dir, un ) )
1941
    PROTO_T ( char *dir X char *un )
1942
{
1943
    open_file ( dir, un, HDR_SUFFIX ) ;
1944
    LOOP_UNION_MAP {
1945
	comment ( "Function headers for map %MN on union %UN" ) ;
1946
	output ( "#ifndef IGNORE_%MN_%UM\n\n" ) ;
1947
	LOOP_UNION_FIELD {
1948
	    print_func_hdr ( 0, 0 ) ;
1949
	    print_func_hdr ( 1, 0 ) ;
1950
	    if ( DEREF_int ( fld_set ( CRT_FIELD ) ) ) {
1951
		print_func_hdr ( 0, 1 ) ;
1952
		print_func_hdr ( 1, 1 ) ;
1953
	    }
1954
	}
1955
	output ( "#endif\n\n\n" ) ;
1956
    }
1957
    close_file () ;
1958
    return ;
1959
}
1960
 
1961
 
1962
/*
1963
    MAIN ACTION (C VERSION)
1964
 
1965
    This routine prints all the output files for the calculus (C version).
1966
*/
1967
 
1968
void main_action_c
1969
    PROTO_N ( ( dir ) )
1970
    PROTO_T ( char *dir )
1971
{
1972
    int ign = 0 ;
1973
    gen_max = 0 ;
1974
    output_c_code = 1 ;
1975
    check_null = ( extra_asserts ? "CHECK_NULL " : "" ) ;
1976
 
1977
    open_file ( dir, MAIN_PREFIX, MAIN_SUFFIX ) ;
1978
    print_main_c () ;
1979
 
1980
    LOOP_UNION {
1981
	LIST ( MAP_P ) maps ;
1982
	CLASS_ID_P cid = DEREF_ptr ( un_id ( CRT_UNION ) ) ;
1983
	char *un = DEREF_string ( cid_name_aux ( cid ) ) ;
1984
	print_union_ops_c ( dir, un ) ;
1985
	maps = DEREF_list ( un_map ( CRT_UNION ) ) ;
1986
	if ( !IS_NULL_list ( maps ) ) {
1987
	    print_union_map_c ( dir, un ) ;
1988
	    print_union_hdr_c ( dir, un ) ;
1989
	    ign = 1 ;
1990
        }
1991
    }
1992
 
1993
    comment ( "Maximum allocation size" ) ;
1994
    output ( "#define %X_GEN_MAX%t40%d\n\n", gen_max + 1 ) ;
1995
    close_file () ;
1996
 
1997
    if ( ign ) {
1998
	open_file ( dir, IGNORE_PREFIX, DEF_SUFFIX ) ;
1999
	comment ( "Map ignore macros" ) ;
2000
	LOOP_UNION {
2001
	    LOOP_UNION_MAP output ( "#define IGNORE_%MN_%UM%t40%d\n", 1 ) ;
2002
	}
2003
	output ( "\n" ) ;
2004
	close_file () ;
2005
    }
2006
 
2007
    if ( extra_asserts ) {
2008
	open_file ( dir, ASSERT_PREFIX, DEF_SUFFIX ) ;
2009
	comment ( "Assertion function definitions" ) ;
2010
	print_assert_fns () ;
2011
	close_file () ;
2012
    }
2013
    return ;
2014
}