Subversion Repositories tendra.SVN

Rev

Rev 5 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5 Rev 6
Line -... Line 1...
-
 
1
/*
-
 
2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
-
 
3
 * All rights reserved.
-
 
4
 *
-
 
5
 * Redistribution and use in source and binary forms, with or without
-
 
6
 * modification, are permitted provided that the following conditions are met:
-
 
7
 *
-
 
8
 * 1. Redistributions of source code must retain the above copyright notice,
-
 
9
 *    this list of conditions and the following disclaimer.
-
 
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
-
 
11
 *    this list of conditions and the following disclaimer in the documentation
-
 
12
 *    and/or other materials provided with the distribution.
-
 
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
-
 
14
 *    may be used to endorse or promote products derived from this software
-
 
15
 *    without specific, prior written permission.
-
 
16
 *
-
 
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
-
 
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-
 
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-
 
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
-
 
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-
 
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-
 
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-
 
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-
 
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-
 
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-
 
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 
28
 *
-
 
29
 * $Id$
-
 
30
 */
1
/*
31
/*
2
    		 Crown Copyright (c) 1997
32
    		 Crown Copyright (c) 1997
3
    
33
 
4
    This TenDRA(r) Computer Program is subject to Copyright
34
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
35
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
36
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
37
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
38
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
39
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
40
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
41
    shall be deemed to be acceptance of the following conditions:-
12
    
42
 
13
        (1) Its Recipients shall ensure that this Notice is
43
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
44
        reproduced upon any copies or amended versions of it;
15
    
45
 
16
        (2) Any amended version of it shall be clearly marked to
46
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
47
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
48
        for the relevant amendment or amendments;
19
    
49
 
20
        (3) Its onward transfer from a recipient to another
50
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
51
        party shall be deemed to be that party's acceptance of
22
        these conditions;
52
        these conditions;
23
    
53
 
24
        (4) DERA gives no warranty or assurance as to its
54
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
55
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
56
        no liability whatsoever in relation to any use to which
27
        it may be put.
57
        it may be put.
28
*/
58
*/
Line 34... Line 64...
34
#include "name.h"
64
#include "name.h"
35
#include "type.h"
65
#include "type.h"
36
#include "print.h"
66
#include "print.h"
37
#include "utility.h"
67
#include "utility.h"
38
 
68
 
39
 
69
 
40
/*
70
/*
41
    COPYRIGHT MESSAGE
71
    COPYRIGHT MESSAGE
42
 
72
 
43
    These variables give the file containing the copyright message, and,
73
    These variables give the file containing the copyright message, and,
44
    after the first time it is processed, the message text.
74
    after the first time it is processed, the message text.
45
*/
75
*/
46
 
76
 
47
char *copyright = null ;
77
char *copyright = null;
48
static char *copyright_text = null ;
78
static char *copyright_text = null;
49
 
79
 
50
 
80
 
51
/*
81
/*
52
    OUTPUT MACROS
82
    OUTPUT MACROS
53
 
83
 
54
    These macros are used as convenient shorthands for various print
84
    These macros are used as convenient shorthands for various print
55
    routines.
85
    routines.
56
*/
86
*/
57
 
87
 
58
#define OUT		IGNORE fprintf
88
#define OUT		IGNORE fprintf
59
#define OUTC( X, Y )	IGNORE fputc ( Y, X )
89
#define OUTC(X, Y)	IGNORE fputc(Y, X)
60
#define OUTS( X, Y )	IGNORE fputs ( Y, X )
90
#define OUTS(X, Y)	IGNORE fputs(Y, X)
61
 
91
 
62
 
92
 
63
/*
93
/*
64
    OUTPUT TRICKS
94
    OUTPUT TRICKS
65
 
95
 
66
    A number of minor tricks are required in the headers, mostly due to
96
    A number of minor tricks are required in the headers, mostly due to
67
    library building problems.
97
    library building problems.
68
*/
98
*/
69
 
99
 
70
static boolean weak_proto = 0 ;
100
static boolean weak_proto = 0;
71
#define enum_hack	"__enum_"
101
#define enum_hack	"__enum_"
72
#define is_hidden( X )	strneq ( X, HIDDEN_NAME, HIDDEN_LEN )
102
#define is_hidden(X)	strneq(X, HIDDEN_NAME, HIDDEN_LEN)
73
 
103
 
74
 
104
 
75
/*
105
/*
76
    OUTPUT FILE
106
    OUTPUT FILE
77
 
107
 
78
    These variables hold information about the current output file.
108
    These variables hold information about the current output file.
79
*/
109
*/
80
 
110
 
81
static info *crt_info = null ;
111
static info *crt_info = null;
82
static int column = 0 ;
112
static int column = 0;
83
 
113
 
84
 
114
 
85
/*
115
/*
86
    DOES A TYPE HAVE A TAIL COMPONENT?
116
    DOES A TYPE HAVE A TAIL COMPONENT?
87
 
117
 
88
    This routine checks whether the type t has an array, bitfield or
118
    This routine checks whether the type t has an array, bitfield or
89
    function component.
119
    function component.
90
*/
120
*/
91
 
121
 
92
static int is_tailed_type
122
static int
93
    PROTO_N ( ( t ) )
-
 
94
    PROTO_T ( type *t )
123
is_tailed_type(type *t)
95
{
124
{
96
    if ( t ) {
125
    if (t) {
97
	switch ( t->id ) {
126
	switch (t->id) {
98
	    case TYPE_ARRAY :
127
	    case TYPE_ARRAY:
99
	    case TYPE_BITFIELD :
128
	    case TYPE_BITFIELD:
100
	    case TYPE_PROC : {
129
	    case TYPE_PROC: {
101
		return ( 1 ) ;
130
		return(1);
102
	    }
131
	    }
103
	}
132
	}
104
    }
133
    }
105
    return ( 0 ) ;
134
    return(0);
106
}
135
}
107
 
136
 
108
 
137
 
109
/*
138
/*
110
    PRINT THE HEAD OF A TYPE
139
    PRINT THE HEAD OF A TYPE
111
 
140
 
112
    This routine prints the head of the type t, that is to say the base type
141
    This routine prints the head of the type t, that is to say the base type
113
    and the pointer components, to the file output.
142
    and the pointer components, to the file output.
114
*/
143
*/
115
 
144
 
116
static int print_head
145
static int
117
    PROTO_N ( ( output, t, sp, tok ) )
-
 
118
    PROTO_T ( FILE *output X type *t X int sp X int tok )
146
print_head(FILE *output, type *t, int sp, int tok)
119
{
147
{
120
    if ( t == null ) return ( sp ) ;
148
    if (t == null) return(sp);
121
    switch ( t->id ) {
149
    switch (t->id) {
122
	case TYPE_VOID :
150
	case TYPE_VOID:
123
	case TYPE_INT :
151
	case TYPE_INT:
124
	case TYPE_SIGNED :
152
	case TYPE_SIGNED:
125
	case TYPE_UNSIGNED :
153
	case TYPE_UNSIGNED:
126
	case TYPE_FLOAT :
154
	case TYPE_FLOAT:
127
	case TYPE_ARITH :
155
	case TYPE_ARITH:
128
	case TYPE_SCALAR :
156
	case TYPE_SCALAR:
129
	case TYPE_STRUCT :
157
	case TYPE_STRUCT:
130
	case TYPE_UNION :
158
	case TYPE_UNION:
131
	case TYPE_ENUM :
159
	case TYPE_ENUM:
132
	case TYPE_GENERIC :
160
	case TYPE_GENERIC:
133
	case TYPE_DEFINED :
161
	case TYPE_DEFINED:
134
	case TYPE_PROMOTE : {
162
	case TYPE_PROMOTE: {
135
	    OUTS ( output, t->u.obj->name ) ;
163
	    OUTS(output, t->u.obj->name);
136
	    sp = 1 ;
164
	    sp = 1;
137
	    break ;
165
	    break;
138
	}
166
	}
139
	case TYPE_STRUCT_TAG : {
167
	case TYPE_STRUCT_TAG: {
140
	    OUT ( output, "struct %s", t->u.obj->name ) ;
168
	    OUT(output, "struct %s", t->u.obj->name);
141
	    sp = 1 ;
169
	    sp = 1;
142
	    break ;
170
	    break;
143
	}
171
	}
144
	case TYPE_UNION_TAG : {
172
	case TYPE_UNION_TAG: {
145
	    OUT ( output, "union %s", t->u.obj->name ) ;
173
	    OUT(output, "union %s", t->u.obj->name);
146
	    sp = 1 ;
174
	    sp = 1;
147
	    break ;
175
	    break;
148
	}
176
	}
149
	case TYPE_ENUM_TAG : {
177
	case TYPE_ENUM_TAG: {
150
	    if ( tok ) {
178
	    if (tok) {
151
		OUT ( output, "%s%s", enum_hack, t->u.obj->name ) ;
179
		OUT(output, "%s%s", enum_hack, t->u.obj->name);
152
	    } else {
180
	    } else {
153
		OUT ( output, "enum %s", t->u.obj->name ) ;
181
		OUT(output, "enum %s", t->u.obj->name);
154
	    }
182
	    }
155
	    sp = 1 ;
183
	    sp = 1;
156
	    break ;
184
	    break;
157
	}
185
	}
158
	case TYPE_LVALUE : {
186
	case TYPE_LVALUE: {
159
	    OUTS ( output, "lvalue " ) ;
187
	    OUTS(output, "lvalue ");
160
	    if ( tok ) OUTS ( output, ": " ) ;
188
	    if (tok)OUTS(output, ": ");
161
	    sp = print_head ( output, t->u.subtype, 0, tok ) ;
189
	    sp = print_head(output, t->u.subtype, 0, tok);
162
	    break ;
190
	    break;
163
	}
191
	}
164
	case TYPE_QUALIFIER : {
192
	case TYPE_QUALIFIER: {
165
	    OUT ( output, "%s ", t->v.str ) ;
193
	    OUT(output, "%s ", t->v.str);
166
	    sp = print_head ( output, t->u.subtype, 0, tok ) ;
194
	    sp = print_head(output, t->u.subtype, 0, tok);
167
	    break ;
195
	    break;
168
	}
196
	}
169
	case TYPE_RVALUE : {
197
	case TYPE_RVALUE: {
170
	    if ( tok ) OUTS ( output, "rvalue : " ) ;
198
	    if (tok)OUTS(output, "rvalue : ");
171
	    sp = print_head ( output, t->u.subtype, 0, tok ) ;
199
	    sp = print_head(output, t->u.subtype, 0, tok);
172
	    break ;
200
	    break;
173
	}
201
	}
174
	case TYPE_PTR : {
202
	case TYPE_PTR: {
175
	    type *s = t->u.subtype ;
203
	    type *s = t->u.subtype;
176
	    char *q = t->v.str ;
204
	    char *q = t->v.str;
177
	    sp = print_head ( output, s, sp, tok ) ;
205
	    sp = print_head(output, s, sp, tok);
178
	    if ( sp ) OUTC ( output, ' ' ) ;
206
	    if (sp)OUTC(output, ' ');
179
	    if ( is_tailed_type ( s ) ) {
207
	    if (is_tailed_type(s)) {
180
		OUTS ( output, "( *" ) ;
208
		OUTS(output, "( *");
181
	    } else {
209
	    } else {
182
		OUTS ( output, "*" ) ;
210
		OUTS(output, "*");
183
	    }
211
	    }
184
	    sp = 0 ;
212
	    sp = 0;
185
	    if ( q ) {
213
	    if (q) {
186
		OUT ( output, " %s", q ) ;
214
		OUT(output, " %s", q);
187
		sp = 1 ;
215
		sp = 1;
188
	    }
216
	    }
189
	    break ;
217
	    break;
190
	}
218
	}
191
	case TYPE_ARRAY :
219
	case TYPE_ARRAY:
192
	case TYPE_BITFIELD :
220
	case TYPE_BITFIELD:
193
	case TYPE_PROC : {
221
	case TYPE_PROC: {
194
	    sp = print_head ( output, t->u.subtype, sp, tok ) ;
222
	    sp = print_head(output, t->u.subtype, sp, tok);
195
	    break ;
223
	    break;
196
	}
224
	}
197
	default : {
225
	default : {
198
	    /* Unknown types */
226
	    /* Unknown types */
199
	    error ( ERR_INTERNAL, "Unknown type identifier, '%d'", t->id ) ;
227
	    error(ERR_INTERNAL, "Unknown type identifier, '%d'", t->id);
200
	    break ;
228
	    break;
201
	}
229
	}
202
    }
230
    }
203
    return ( sp ) ;
231
    return(sp);
204
}
232
}
205
 
233
 
206
 
234
 
207
/*
235
/*
208
    PRINT THE TAIL OF A TYPE
236
    PRINT THE TAIL OF A TYPE
209
 
237
 
210
    This routine prints the tail of the type t, that is to say the array,
238
    This routine prints the tail of the type t, that is to say the array,
211
    bitfield and function components, to the file output.
239
    bitfield and function components, to the file output.
212
*/
240
*/
213
 
241
 
214
static void print_tail
242
static void
215
    PROTO_N ( ( output, t, tok ) )
-
 
216
    PROTO_T ( FILE *output X type *t X int tok )
243
print_tail(FILE *output, type *t, int tok)
217
{
244
{
218
    if ( t == null ) return ;
245
    if (t == null) return;
219
    switch ( t->id ) {
246
    switch (t->id) {
220
	case TYPE_LVALUE :
247
	case TYPE_LVALUE:
221
	case TYPE_RVALUE :
248
	case TYPE_RVALUE:
222
	case TYPE_QUALIFIER : {
249
	case TYPE_QUALIFIER: {
223
	    print_tail ( output, t->u.subtype, tok ) ;
250
	    print_tail(output, t->u.subtype, tok);
224
	    break ;
251
	    break;
225
	}
252
	}
226
	case TYPE_PTR : {
253
	case TYPE_PTR: {
227
	    type *s = t->u.subtype ;
254
	    type *s = t->u.subtype;
228
	    if ( is_tailed_type ( s ) ) {
255
	    if (is_tailed_type(s)) {
229
		OUTS ( output, " )" ) ;
256
		OUTS(output, " )");
-
 
257
	    }
-
 
258
	    print_tail(output, s, tok);
-
 
259
	    break;
-
 
260
	}
-
 
261
	case TYPE_ARRAY: {
-
 
262
	    OUT(output, " [%s]", t->v.str);
-
 
263
	    print_tail(output, t->u.subtype, tok);
-
 
264
	    break;
-
 
265
	}
-
 
266
	case TYPE_BITFIELD: {
-
 
267
	    if (tok) {
-
 
268
		OUT(output, " %% %s", t->v.str);
-
 
269
	    } else {
-
 
270
		OUT(output, " : %s", t->v.str);
230
	    }
271
	    }
231
	    print_tail ( output, s, tok ) ;
-
 
232
	    break ;
-
 
233
	}
-
 
234
	case TYPE_ARRAY : {
-
 
235
	    OUT ( output, " [%s]", t->v.str ) ;
-
 
236
	    print_tail ( output, t->u.subtype, tok ) ;
272
	    print_tail(output, t->u.subtype, tok);
237
	    break ;
273
	    break;
238
	}
274
	}
239
	case TYPE_BITFIELD : {
-
 
240
	    if ( tok ) {
-
 
241
		OUT ( output, " %% %s", t->v.str ) ;
-
 
242
	    } else {
-
 
243
		OUT ( output, " : %s", t->v.str ) ;
-
 
244
	    }
-
 
245
	    print_tail ( output, t->u.subtype, tok ) ;
-
 
246
	    break ;
-
 
247
	}
-
 
248
	case TYPE_PROC : {
275
	case TYPE_PROC: {
249
	    type *s = t->v.next ;
276
	    type *s = t->v.next;
250
	    if ( s ) {
277
	    if (s) {
251
		OUTS ( output, " ( " ) ;
278
		OUTS(output, " ( ");
252
		while ( s ) {
279
		while (s) {
253
		    print_type ( output, s->u.subtype, null_str, tok ) ;
280
		    print_type(output, s->u.subtype, null_str, tok);
254
		    s = s->v.next ;
281
		    s = s->v.next;
255
		    if ( s ) OUTS ( output, ", " ) ;
282
		    if (s)OUTS(output, ", ");
256
		}
283
		}
257
		OUTS ( output, " )" ) ;
284
		OUTS(output, " )");
258
	    } else {
285
	    } else {
259
		OUTS ( output, " ()" ) ;
286
		OUTS(output, " ()");
260
	    }
287
	    }
261
	    print_tail ( output, t->u.subtype, tok ) ;
288
	    print_tail(output, t->u.subtype, tok);
262
	    break ;
289
	    break;
263
	}
290
	}
264
    }
291
    }
265
    return ;
292
    return;
266
}
293
}
267
 
294
 
268
 
295
 
269
/*
296
/*
270
    PRINT A TYPE
297
    PRINT A TYPE
271
 
298
 
272
    This routine prints the object nm of type t to the file output.
299
    This routine prints the object nm of type t to the file output.
273
*/
300
*/
274
 
301
 
275
void print_type
302
void
276
    PROTO_N ( ( output, t, nm, tok ) )
-
 
277
    PROTO_T ( FILE *output X type *t X char *nm X int tok )
303
print_type(FILE *output, type *t, char *nm, int tok)
278
{
304
{
279
    if ( t ) {
305
    if (t) {
280
	int sp = print_head ( output, t, 0, tok ) ;
306
	int sp = print_head(output, t, 0, tok);
281
	if ( nm ) {
307
	if (nm) {
282
	    if ( sp ) OUTC ( output, ' ' ) ;
308
	    if (sp)OUTC(output, ' ');
283
	    OUTS ( output, nm ) ;
309
	    OUTS(output, nm);
284
	}
310
	}
285
	print_tail ( output, t, tok ) ;
311
	print_tail(output, t, tok);
286
    }
312
    }
287
    return ;
313
    return;
288
}
314
}
289
 
315
 
290
 
316
 
291
/*
317
/*
292
    PRINT A STRUCT OR UNION DEFINITION
318
    PRINT A STRUCT OR UNION DEFINITION
293
 
319
 
294
    This routine prints the specification for a structure or union type,
320
    This routine prints the specification for a structure or union type,
295
    t, with internal name nm and external name tnm, to output.
321
    t, with internal name nm and external name tnm, to output.
296
*/
322
*/
297
 
323
 
298
static void print_struct_defn
324
static void
299
    PROTO_N ( ( output, t, nm, tnm, d ) )
-
 
300
    PROTO_T ( FILE *output X type *t X char *nm X char *tnm X int d )
325
print_struct_defn(FILE *output, type *t, char *nm, char *tnm, int d)
301
{
326
{
302
    char *tok, *tag ;
327
    char *tok, *tag;
303
    object *q = t->v.obj2 ;
328
    object *q = t->v.obj2;
304
    boolean show_token = 1, show_interface = 1 ;
329
    boolean show_token = 1, show_interface = 1;
305
    boolean show_ignore = 1, show_defn = 1 ;
330
    boolean show_ignore = 1, show_defn = 1;
306
 
331
 
307
    /* Find the token type */
332
    /* Find the token type */
308
    switch ( t->id ) EXHAUSTIVE {
333
    switch (t->id)EXHAUSTIVE {
309
	case TYPE_STRUCT : tok = "STRUCT" ; tag = "" ; break ;
334
	case TYPE_STRUCT: tok = "STRUCT"; tag = ""; break;
310
	case TYPE_STRUCT_TAG : tok = "STRUCT" ; tag = "TAG " ; break ;
335
	case TYPE_STRUCT_TAG: tok = "STRUCT"; tag = "TAG "; break;
311
	case TYPE_UNION : tok = "UNION" ; tag = "" ; break ;
336
	case TYPE_UNION: tok = "UNION"; tag = ""; break;
312
	case TYPE_UNION_TAG : tok = "UNION" ; tag = "TAG " ; break ;
337
	case TYPE_UNION_TAG: tok = "UNION"; tag = "TAG "; break;
313
    }
338
    }
314
 
339
 
315
    /* Deal with undefined tokens immediately */
340
    /* Deal with undefined tokens immediately */
316
    if ( q == null ) {
341
    if (q == null) {
317
	OUT ( output, "#pragma token %s %s%s # %s\n", tok, tag, nm, tnm ) ;
342
	OUT(output, "#pragma token %s %s%s # %s\n", tok, tag, nm, tnm);
318
	return ;
343
	return;
319
    }
344
    }
320
 
345
 
321
    /* Deal with the various definition cases */
346
    /* Deal with the various definition cases */
322
    switch ( t->state ) {
347
    switch (t->state) {
323
	case 0 : {
348
	case 0: {
324
	    /* Definition is immediate */
349
	    /* Definition is immediate */
325
	    if ( is_hidden ( nm ) ) {
350
	    if (is_hidden(nm)) {
326
		show_token = 0 ;
351
		show_token = 0;
327
		show_interface = 0 ;
352
		show_interface = 0;
328
		show_ignore = 0 ;
353
		show_ignore = 0;
329
	    }
354
	    }
330
	    break ;
355
	    break;
331
	}
356
	}
332
	case 1 : {
357
	case 1: {
333
	    /* Definition is elsewhere */
358
	    /* Definition is elsewhere */
334
	    show_interface = 0 ;
359
	    show_interface = 0;
335
	    show_ignore = 0 ;
360
	    show_ignore = 0;
336
	    show_defn = 0 ;
361
	    show_defn = 0;
337
	    t->state = 2 ;
362
	    t->state = 2;
338
	    break ;
363
	    break;
339
	}
364
	}
340
	case 2 : {
365
	case 2: {
341
	    /* Declaration was earlier in file */
366
	    /* Declaration was earlier in file */
342
	    show_token = 0 ;
367
	    show_token = 0;
343
	    t->state = 0 ;
368
	    t->state = 0;
344
	    break ;
369
	    break;
345
	}
370
	}
346
	case 3 : {
371
	case 3: {
347
	    /* Declaration was in another file */
372
	    /* Declaration was in another file */
348
	    if ( d ) {
373
	    if (d) {
349
		show_token = 0 ;
374
		show_token = 0;
350
		show_interface = 0 ;
375
		show_interface = 0;
351
		t->state = 1 ;
376
		t->state = 1;
352
	    } else {
377
	    } else {
353
		show_interface = 0 ;
378
		show_interface = 0;
354
		show_ignore = 0 ;
379
		show_ignore = 0;
355
		show_defn = 0 ;
380
		show_defn = 0;
356
		t->state = 2 ;
381
		t->state = 2;
357
	    }
382
	    }
358
	    break ;
383
	    break;
359
	}
384
	}
360
    }
385
    }
361
 
386
 
362
    /* Print the token if necessary */
387
    /* Print the token if necessary */
363
    if ( show_token ) {
388
    if (show_token) {
364
	OUT ( output, "#pragma token %s %s%s # %s\n", tok, tag, nm, tnm ) ;
389
	OUT(output, "#pragma token %s %s%s # %s\n", tok, tag, nm, tnm);
365
    }
390
    }
366
 
391
 
367
    /* Print the interface statement */
392
    /* Print the interface statement */
368
    if ( show_interface ) {
393
    if (show_interface) {
369
	char *b = BUILDING_MACRO ;
394
	char *b = BUILDING_MACRO;
370
	OUT ( output, "#ifdef %s\n", b ) ;
395
	OUT(output, "#ifdef %s\n", b);
371
	OUT ( output, "#pragma interface %s%s\n", tag, nm ) ;
396
	OUT(output, "#pragma interface %s%s\n", tag, nm);
372
	OUT ( output, "#else /* %s */\n", b ) ;
397
	OUT ( output, "#else /* %s */\n", b ) ;
373
    }
398
    }
374
 
399
 
375
    /* Print the ignore statement */
400
    /* Print the ignore statement */
376
    if ( show_ignore ) {
401
    if (show_ignore) {
377
	if ( !show_interface ) {
402
	if (!show_interface) {
378
	    char *b = BUILDING_MACRO ;
403
	    char *b = BUILDING_MACRO;
379
	    OUT ( output, "#ifndef %s\n", b ) ;
404
	    OUT(output, "#ifndef %s\n", b);
380
	}
405
	}
381
	OUT ( output, "#pragma ignore %s%s\n", tag, nm ) ;
406
	OUT(output, "#pragma ignore %s%s\n", tag, nm);
382
    }
407
    }
383
 
408
 
384
    /* Print the type definition */
409
    /* Print the type definition */
385
    if ( show_defn ) {
410
    if (show_defn) {
386
	tok = ( tok [0] == 'S' ? "struct" : "union" ) ;
411
	tok = (tok [0] == 'S' ? "struct" : "union");
387
	if ( *tag ) {
412
	if (*tag) {
388
	    OUT ( output, "%s %s {\n", tok, nm ) ;
413
	    OUT(output, "%s %s {\n", tok, nm);
389
	} else {
414
	} else {
390
	    OUT ( output, "typedef %s {\n", tok ) ;
415
	    OUT(output, "typedef %s {\n", tok);
391
	}
416
	}
392
	while ( q ) {
417
	while (q) {
393
	    field *f = q->u.u_obj->u.u_field ;
418
	    field *f = q->u.u_obj->u.u_field;
394
	    OUTS ( output, "    " ) ;
419
	    OUTS(output, "    ");
395
	    print_type ( output, f->ftype, f->fname, 0 ) ;
420
	    print_type(output, f->ftype, f->fname, 0);
396
	    OUTS ( output, " ;\n" ) ;
421
	    OUTS(output, " ;\n");
397
	    q = q->next ;
422
	    q = q->next;
398
	}
423
	}
399
	if ( *tag ) {
424
	if (*tag) {
400
	    OUTS ( output, "} ;\n" ) ;
425
	    OUTS(output, "} ;\n");
401
	} else {
426
	} else {
402
	    OUT ( output, "} %s ;\n", nm ) ;
427
	    OUT(output, "} %s ;\n", nm);
403
	}
428
	}
404
    }
429
    }
405
 
430
 
406
    /* Print the final #endif */
431
    /* Print the final #endif */
407
    if ( show_interface || show_ignore ) {
432
    if (show_interface || show_ignore) {
408
	char *b = BUILDING_MACRO ;
433
	char *b = BUILDING_MACRO;
409
	OUT ( output, "#endif /* %s */\n", b ) ;
434
	OUT ( output, "#endif /* %s */\n", b ) ;
410
    }
435
    }
411
    return ;
436
    return;
412
}
437
}
413
 
438
 
414
 
439
 
415
/*
440
/*
416
    PRINT A TOKENISED TYPE
441
    PRINT A TOKENISED TYPE
417
 
442
 
418
    This routine is the special case of print_token which deals with
443
    This routine is the special case of print_token which deals with
419
    tokenised types.
444
    tokenised types.
420
*/
445
*/
421
 
446
 
422
static void print_token_type
447
static void
423
    PROTO_N ( ( output, p, tnm ) )
-
 
424
    PROTO_T ( FILE *output X object *p X char *tnm )
448
print_token_type(FILE *output, object *p, char *tnm)
425
{
449
{
426
    char *tok = "TYPE" ;
450
    char *tok = "TYPE";
427
    char *nm = p->name ;
451
    char *nm = p->name;
428
    type *t = p->u.u_type ;
452
    type *t = p->u.u_type;
429
    int i = t->id ;
453
    int i = t->id;
430
    switch ( i ) {
454
    switch (i) {
431
 
455
 
432
	case TYPE_DEFINED : {
456
	case TYPE_DEFINED: {
433
	    /* Defined types */
457
	    /* Defined types */
434
	    char *tm, *sp ;
458
	    char *tm, *sp;
435
	    type *s = t->v.next ;
459
	    type *s = t->v.next;
436
	    char *b = BUILDING_MACRO ;
460
	    char *b = BUILDING_MACRO;
437
	    if ( s == type_bottom ) {
461
	    if (s == type_bottom) {
438
		sp = "bottom" ;
462
		sp = "bottom";
439
	    } else if ( s == type_printf ) {
463
	    } else if (s == type_printf) {
440
		sp = "... printf" ;
464
		sp = "... printf";
441
	    } else if ( s == type_scanf ) {
465
	    } else if (s == type_scanf) {
442
		sp = "... scanf" ;
466
		sp = "... scanf";
443
	    } else {
467
	    } else {
444
		OUTS ( output, "typedef " ) ;
468
		OUTS(output, "typedef ");
445
		print_type ( output, s, nm, 0 ) ;
469
		print_type(output, s, nm, 0);
446
		OUTS ( output, " ;\n" ) ;
470
		OUTS(output, " ;\n");
447
		break ;
471
		break;
448
	    }
472
	    }
449
	    /* Allow for special types */
473
	    /* Allow for special types */
450
	    tm = "__TenDRA__" ;
474
	    tm = "__TenDRA__";
451
	    OUT ( output, "#ifndef %s\n", b ) ;
475
	    OUT(output, "#ifndef %s\n", b);
452
	    OUT ( output, "#ifdef %s\n", tm ) ;
476
	    OUT(output, "#ifdef %s\n", tm);
453
	    OUT ( output, "#pragma TenDRA type %s for %s\n", nm, sp ) ;
477
	    OUT(output, "#pragma TenDRA type %s for %s\n", nm, sp);
454
	    OUT ( output, "#else /* %s */\n", tm ) ;
478
	    OUT ( output, "#else /* %s */\n", tm ) ;
455
	    OUT ( output, "typedef %s %s ;\n", s->u.obj->name, nm ) ;
479
	    OUT(output, "typedef %s %s ;\n", s->u.obj->name, nm);
456
	    OUT ( output, "#endif /* %s */\n", tm ) ;
480
	    OUT ( output, "#endif /* %s */\n", tm ) ;
457
	    OUT ( output, "#else /* %s */\n", b ) ;
481
	    OUT ( output, "#else /* %s */\n", b ) ;
458
	    OUT ( output, "typedef %s %s ;\n", s->u.obj->name, nm ) ;
482
	    OUT(output, "typedef %s %s ;\n", s->u.obj->name, nm);
459
	    OUT ( output, "#endif /* %s */\n", b ) ;
483
	    OUT ( output, "#endif /* %s */\n", b ) ;
460
	    break ;
484
	    break;
461
	}
485
	}
462
 
486
 
463
	case TYPE_INT : tok = "VARIETY" ; goto generic_lab ;
487
	case TYPE_INT: tok = "VARIETY"; goto generic_lab;
464
	case TYPE_SIGNED : tok = "VARIETY signed" ; goto generic_lab ;
488
	case TYPE_SIGNED: tok = "VARIETY signed"; goto generic_lab;
465
	case TYPE_UNSIGNED : tok = "VARIETY unsigned" ; goto generic_lab ;
489
	case TYPE_UNSIGNED: tok = "VARIETY unsigned"; goto generic_lab;
466
	case TYPE_FLOAT : tok = "FLOAT" ; goto generic_lab ;
490
	case TYPE_FLOAT: tok = "FLOAT"; goto generic_lab;
467
	case TYPE_ARITH : tok = "ARITHMETIC" ; goto generic_lab ;
491
	case TYPE_ARITH: tok = "ARITHMETIC"; goto generic_lab;
468
	case TYPE_SCALAR : tok = "SCALAR" ; goto generic_lab ;
492
	case TYPE_SCALAR: tok = "SCALAR"; goto generic_lab;
469
 
493
 
470
	case TYPE_GENERIC :
494
	case TYPE_GENERIC:
471
	generic_lab : {
495
	generic_lab : {
472
	    /* Generic types */
496
	    /* Generic types */
473
	    OUT ( output, "#pragma token %s %s # %s\n", tok, nm, tnm ) ;
497
	    OUT(output, "#pragma token %s %s # %s\n", tok, nm, tnm);
474
	    break ;
498
	    break;
475
	}
499
	}
476
 
500
 
477
	case TYPE_PROMOTE : {
501
	case TYPE_PROMOTE: {
478
	    /* Promotion types */
502
	    /* Promotion types */
479
	    char *pt = t->v.next->u.obj->name ;
503
	    char *pt = t->v.next->u.obj->name;
480
	    OUT ( output, "#pragma token VARIETY %s # %s\n", nm, tnm ) ;
504
	    OUT(output, "#pragma token VARIETY %s # %s\n", nm, tnm);
481
	    OUT ( output, "#pragma promote %s : %s\n", pt, nm ) ;
505
	    OUT(output, "#pragma promote %s : %s\n", pt, nm);
482
	    break ;
506
	    break;
483
	}
507
	}
484
 
508
 
485
	case TYPE_STRUCT :
509
	case TYPE_STRUCT:
486
	case TYPE_STRUCT_TAG :
510
	case TYPE_STRUCT_TAG:
487
	case TYPE_UNION :
511
	case TYPE_UNION:
488
	case TYPE_UNION_TAG : {
512
	case TYPE_UNION_TAG: {
489
	    /* Structure or union types */
513
	    /* Structure or union types */
490
	    print_struct_defn ( output, t, nm, tnm, 0 ) ;
514
	    print_struct_defn(output, t, nm, tnm, 0);
491
	    break ;
515
	    break;
492
	}
516
	}
493
 
517
 
494
	case TYPE_ENUM :
518
	case TYPE_ENUM:
495
	case TYPE_ENUM_TAG : {
519
	case TYPE_ENUM_TAG: {
496
	    /* Enumeration types are a complete hack */
520
	    /* Enumeration types are a complete hack */
497
	    char *b = BUILDING_MACRO ;
521
	    char *b = BUILDING_MACRO;
498
	    boolean tagged = ( boolean ) ( i == TYPE_ENUM ? 0 : 1 ) ;
522
	    boolean tagged = (boolean)(i == TYPE_ENUM ? 0 : 1);
499
	    object *q = t->v.obj2 ;
523
	    object *q = t->v.obj2;
500
	    OUT ( output, "#ifndef %s\n", b ) ;
524
	    OUT(output, "#ifndef %s\n", b);
501
 
525
 
502
	    /* Print the enumeration type */
526
	    /* Print the enumeration type */
503
	    if ( tagged ) {
527
	    if (tagged) {
504
		OUT ( output, "typedef enum %s {", nm ) ;
528
		OUT(output, "typedef enum %s {", nm);
505
	    } else {
529
	    } else {
506
		OUTS ( output, "typedef enum {" ) ;
530
		OUTS(output, "typedef enum {");
507
	    }
531
	    }
508
 
532
 
509
	    /* Print the enumeration elements */
533
	    /* Print the enumeration elements */
510
	    while ( q ) {
534
	    while (q) {
511
		object *r = q->u.u_obj ;
535
		object *r = q->u.u_obj;
512
		char *v = r->u.u_str ;
536
		char *v = r->u.u_str;
513
		if ( v && v [0] ) {
537
		if (v && v [0]) {
514
		    OUT ( output, "\n    %s = %s", r->name, v ) ;
538
		    OUT(output, "\n    %s = %s", r->name, v);
515
		} else {
539
		} else {
516
		    OUT ( output, "\n    %s", r->name ) ;
540
		    OUT(output, "\n    %s", r->name);
517
		}
541
		}
518
		q = q->next ;
542
		q = q->next;
519
		if ( q ) OUTC ( output, ',' ) ;
543
		if (q)OUTC(output, ',');
520
	    }
544
	    }
521
 
545
 
522
	    /* Print the end of the enumeration type */
546
	    /* Print the end of the enumeration type */
523
	    if ( tagged ) {
547
	    if (tagged) {
524
		IGNORE sprintf ( buffer, "%s%s", enum_hack, nm ) ;
548
		IGNORE sprintf(buffer, "%s%s", enum_hack, nm);
525
		OUT ( output, "\n} %s ;\n", buffer ) ;
549
		OUT(output, "\n} %s ;\n", buffer);
526
	    } else {
550
	    } else {
527
		OUT ( output, "\n} %s ;\n", nm ) ;
551
		OUT(output, "\n} %s ;\n", nm);
528
	    }
552
	    }
529
 
553
 
530
	    /* Print the hacked library building version */
554
	    /* Print the hacked library building version */
531
	    OUT ( output, "#else /* %s */\n", b ) ;
555
	    OUT ( output, "#else /* %s */\n", b ) ;
532
	    if ( tagged ) {
556
	    if (tagged) {
533
		OUT ( output, "typedef int %s ;\n", buffer ) ;
557
		OUT(output, "typedef int %s ;\n", buffer);
534
	    } else {
558
	    } else {
535
		OUT ( output, "#pragma token VARIETY %s # %s\n", nm, tnm ) ;
559
		OUT(output, "#pragma token VARIETY %s # %s\n", nm, tnm);
536
		OUT ( output, "#pragma promote %s : %s\n", nm, nm ) ;
560
		OUT(output, "#pragma promote %s : %s\n", nm, nm);
537
		OUT ( output, "#pragma interface %s\n", nm ) ;
561
		OUT(output, "#pragma interface %s\n", nm);
538
	    }
562
	    }
539
	    OUT ( output, "#endif /* %s */\n", b ) ;
563
	    OUT ( output, "#endif /* %s */\n", b ) ;
540
	    break ;
564
	    break;
541
	}
565
	}
542
 
566
 
543
	default : {
567
	default : {
544
	    /* Other types */
568
	    /* Other types */
545
	    error ( ERR_INTERNAL, "Unknown type identifier, '%d'\n", i ) ;
569
	    error(ERR_INTERNAL, "Unknown type identifier, '%d'", i);
546
	    break ;
570
	    break;
547
	}
571
	}
548
    }
572
    }
549
    return ;
573
    return;
550
}
574
}
551
 
575
 
552
 
576
 
553
/*
577
/*
554
    PRINT A TOKEN
578
    PRINT A TOKEN
555
 
579
 
556
    This routine prints the object p, representing the token tnm, to the
580
    This routine prints the object p, representing the token tnm, to the
557
    file output.
581
    file output.
558
*/
582
*/
559
 
583
 
560
static void print_token
584
static void
561
    PROTO_N ( ( output, p, tnm ) )
-
 
562
    PROTO_T ( FILE *output X object *p X char *tnm )
585
print_token(FILE *output, object *p, char *tnm)
563
{
586
{
564
    char *nm = p->name ;
587
    char *nm = p->name;
565
    switch ( p->objtype ) {
588
    switch (p->objtype) {
566
 
589
 
567
	case OBJ_CONST :
590
	case OBJ_CONST:
568
	case OBJ_EXP : {
591
	case OBJ_EXP: {
569
	    /* Constants and expressions */
592
	    /* Constants and expressions */
570
	    type *t = p->u.u_type ;
593
	    type *t = p->u.u_type;
571
	    OUTS ( output, "#pragma token EXP " ) ;
594
	    OUTS(output, "#pragma token EXP ");
572
	    if ( p->objtype == OBJ_CONST && t->id == TYPE_RVALUE ) {
595
	    if (p->objtype == OBJ_CONST && t->id == TYPE_RVALUE) {
573
		OUTS ( output, "const : " ) ;
596
		OUTS(output, "const : ");
574
		t = t->u.subtype ;
597
		t = t->u.subtype;
575
	    }
598
	    }
576
	    print_type ( output, t, null_str, 1 ) ;
599
	    print_type(output, t, null_str, 1);
577
	    OUT ( output, " : %s # %s\n", nm, tnm ) ;
600
	    OUT(output, " : %s # %s\n", nm, tnm);
578
	    break ;
601
	    break;
579
	}
602
	}
580
 
603
 
581
	case OBJ_EXTERN : {
604
	case OBJ_EXTERN: {
582
	    /* External expressions */
605
	    /* External expressions */
583
	    type *t = p->u.u_type ;
606
	    type *t = p->u.u_type;
584
	    if ( t->id == TYPE_LVALUE ) t = t->u.subtype ;
607
	    if (t->id == TYPE_LVALUE)t = t->u.subtype;
585
	    OUTS ( output, "extern " ) ;
608
	    OUTS(output, "extern ");
586
	    print_type ( output, t, nm, 0 ) ;
609
	    print_type(output, t, nm, 0);
587
	    OUTS ( output, " ;\n" ) ;
610
	    OUTS(output, " ;\n");
588
	    break ;
611
	    break;
589
	}
612
	}
590
 
613
 
591
	case OBJ_WEAK : {
614
	case OBJ_WEAK: {
592
	    /* Weak prototype declarations */
615
	    /* Weak prototype declarations */
593
	    int sp ;
616
	    int sp;
594
	    char *w = WEAK_PROTO ;
617
	    char *w = WEAK_PROTO;
595
	    type *t = p->u.u_type ;
618
	    type *t = p->u.u_type;
596
	    if ( !weak_proto ) {
619
	    if (!weak_proto) {
597
		char *b = BUILDING_MACRO ;
620
		char *b = BUILDING_MACRO;
598
		OUT ( output, "#ifndef %s\n", w ) ;
621
		OUT(output, "#ifndef %s\n", w);
599
		OUT ( output, "#ifndef %s\n", b ) ;
622
		OUT(output, "#ifndef %s\n", b);
600
		OUT ( output, "#pragma TenDRA keyword %s_KEY for weak\n", w ) ;
623
		OUT(output, "#pragma TenDRA keyword %s_KEY for weak\n", w);
601
		OUT ( output, "#define %s( A )\t%s_KEY A\n", w, w ) ;
624
		OUT(output, "#define %s( A )\t%s_KEY A\n", w, w);
602
		OUT ( output, "#else /* %s */\n", b ) ;
625
		OUT ( output, "#else /* %s */\n", b ) ;
603
		OUT ( output, "#define %s( A )\t()\n", w ) ;
626
		OUT(output, "#define %s( A )\t()\n", w);
604
		OUT ( output, "#endif /* %s */\n", b ) ;
627
		OUT ( output, "#endif /* %s */\n", b ) ;
605
		OUT ( output, "#endif /* %s */\n\n", w ) ;
628
		OUT ( output, "#endif /* %s */\n\n", w ) ;
606
		weak_proto = 1 ;
629
		weak_proto = 1;
607
	    }
630
	    }
608
	    OUTS ( output, "extern " ) ;
631
	    OUTS(output, "extern ");
609
	    sp = print_head ( output, t, 0, 0 ) ;
632
	    sp = print_head(output, t, 0, 0);
610
	    if ( sp ) OUTC ( output, ' ' ) ;
633
	    if (sp)OUTC(output, ' ');
611
	    OUT ( output, "%s %s (", nm, w ) ;
634
	    OUT(output, "%s %s (", nm, w);
612
	    print_tail ( output, t, 0 ) ;
635
	    print_tail(output, t, 0);
613
	    OUTS ( output, " ) ;\n" ) ;
636
	    OUTS(output, " ) ;\n");
-
 
637
	    break;
-
 
638
	}
-
 
639
 
-
 
640
	case OBJ_DEFINE: {
-
 
641
	    /* Macro definitions */
-
 
642
	    char *s = p->u.u_str;
-
 
643
	    OUT(output, "#define %s%s\n", nm, s);
614
	    break ;
644
	    break;
615
	}
645
	}
616
 
646
 
617
	case OBJ_DEFINE : {
647
	case OBJ_DEFMIN: {
618
	    /* Macro definitions */
648
	    /* Macro definitions */
619
	    char *s = p->u.u_str ;
649
	    char *s = p->u.u_str;
-
 
650
	    OUT(output, "#if defined(%s) && %s < %s\n", nm, nm, s);
-
 
651
	    OUT(output, "/* Should probably me an #error */\n");
-
 
652
	    OUT(output, "#define %s%s\n", nm, s);
-
 
653
	    OUT(output, "#elif !defined(%s)\n", nm);
620
	    OUT ( output, "#define %s%s\n", nm, s ) ;
654
	    OUT(output, "#define %s%s\n", nm, s);
-
 
655
	    OUT(output, "#endif\n");
621
	    break ;
656
	    break;
622
	}
657
	}
623
 
658
 
624
	case OBJ_FIELD : {
659
	case OBJ_FIELD: {
625
	    /* Field selectors */
660
	    /* Field selectors */
626
	    field *f = p->u.u_field ;
661
	    field *f = p->u.u_field;
627
	    OUTS ( output, "#pragma token MEMBER " ) ;
662
	    OUTS(output, "#pragma token MEMBER ");
628
	    print_type ( output, f->ftype, null_str, 1 ) ;
663
	    print_type(output, f->ftype, null_str, 1);
629
	    OUTS ( output, " : " ) ;
664
	    OUTS(output, " : ");
630
	    print_type ( output, f->stype, null_str, 1 ) ;
665
	    print_type(output, f->stype, null_str, 1);
631
	    OUT ( output, " : %s # %s\n", f->fname, tnm ) ;
666
	    OUT(output, " : %s # %s\n", f->fname, tnm);
632
	    break ;
667
	    break;
633
	}
668
	}
634
 
669
 
635
	case OBJ_FUNC : {
670
	case OBJ_FUNC: {
636
	    /* Functions */
671
	    /* Functions */
637
	    type *t = p->u.u_type ;
672
	    type *t = p->u.u_type;
638
	    OUTS ( output, "#pragma token FUNC " ) ;
673
	    OUTS(output, "#pragma token FUNC ");
639
	    print_type ( output, t, null_str, 1 ) ;
674
	    print_type(output, t, null_str, 1);
640
	    OUT ( output, " : %s # %s\n", nm, tnm ) ;
675
	    OUT(output, " : %s # %s\n", nm, tnm);
641
	    break ;
676
	    break;
642
	}
677
	}
643
 
678
 
644
	case OBJ_MACRO : {
679
	case OBJ_MACRO: {
645
	    /* Macros */
680
	    /* Macros */
646
	    type *t = p->u.u_type ;
681
	    type *t = p->u.u_type;
647
	    type *s = t->v.next ;
682
	    type *s = t->v.next;
648
	    OUTS ( output, "#pragma token PROC ( " ) ;
683
	    OUTS(output, "#pragma token PROC ( ");
649
	    /* Print the macro arguments */
684
	    /* Print the macro arguments */
650
	    while ( s && s != type_none  ) {
685
	    while (s && s != type_none ) {
651
		OUTS ( output, "EXP " ) ;
686
		OUTS(output, "EXP ");
652
		print_type ( output, s->u.subtype, null_str, 1 ) ;
687
		print_type(output, s->u.subtype, null_str, 1);
653
		s = s->v.next ;
688
		s = s->v.next;
654
		OUTS ( output, ( s ? " : , " : " : " ) ) ;
689
		OUTS(output,(s ? " : , " : " : "));
655
	    }
690
	    }
656
	    /* Print the macro result */
691
	    /* Print the macro result */
657
	    OUTS ( output, ") EXP " ) ;
692
	    OUTS(output, ") EXP ");
658
	    print_type ( output, t->u.subtype, null_str, 1 ) ;
693
	    print_type(output, t->u.subtype, null_str, 1);
659
	    OUT ( output, " : %s # %s\n", nm, tnm ) ;
694
	    OUT(output, " : %s # %s\n", nm, tnm);
660
	    break ;
695
	    break;
661
	}
696
	}
662
 
697
 
663
	case OBJ_NAT : {
698
	case OBJ_NAT: {
664
	    /* Nats */
699
	    /* Nats */
665
	    OUT ( output, "#pragma token NAT %s # %s\n", nm, tnm ) ;
700
	    OUT(output, "#pragma token NAT %s # %s\n", nm, tnm);
666
	    break ;
701
	    break;
667
	}
702
	}
668
 
703
 
669
	case OBJ_STATEMENT : {
704
	case OBJ_STATEMENT: {
670
	    /* Statements */
705
	    /* Statements */
671
	    type *t = p->u.u_type ;
706
	    type *t = p->u.u_type;
672
	    if ( t != null ) {
707
	    if (t != null) {
673
		/* Statements with arguments */
708
		/* Statements with arguments */
674
		type *s = t->v.next ;
709
		type *s = t->v.next;
675
		OUTS ( output, "#pragma token PROC ( " ) ;
710
		OUTS(output, "#pragma token PROC ( ");
676
		while ( s && s != type_none ) {
711
		while (s && s != type_none) {
677
		    OUTS ( output, "EXP " ) ;
712
		    OUTS(output, "EXP ");
678
		    print_type ( output, s->u.subtype, null_str, 1 ) ;
713
		    print_type(output, s->u.subtype, null_str, 1);
679
		    s = s->v.next ;
714
		    s = s->v.next;
680
		    OUTS ( output, ( s ? " : , " : " : " ) ) ;
715
		    OUTS(output,(s ? " : , " : " : "));
681
		}
716
		}
682
		OUT ( output, ") STATEMENT %s # %s\n", nm, tnm ) ;
717
		OUT(output, ") STATEMENT %s # %s\n", nm, tnm);
683
	    } else {
718
	    } else {
684
		/* Statements with no arguments */
719
		/* Statements with no arguments */
685
		OUT ( output, "#pragma token STATEMENT %s # %s\n", nm, tnm ) ;
720
		OUT(output, "#pragma token STATEMENT %s # %s\n", nm, tnm);
686
	    }
721
	    }
687
	    break ;
722
	    break;
688
	}
723
	}
689
 
724
 
690
	case OBJ_TOKEN : {
725
	case OBJ_TOKEN: {
691
	    /* Tokens */
726
	    /* Tokens */
692
	    char *s = p->u.u_str ;
727
	    char *s = p->u.u_str;
693
	    OUT ( output, "#pragma token %s %s # %s\n", s, nm, tnm ) ;
728
	    OUT(output, "#pragma token %s %s # %s\n", s, nm, tnm);
694
	    break ;
729
	    break;
695
	}
730
	}
696
 
731
 
697
	case OBJ_TYPE : {
732
	case OBJ_TYPE: {
698
	    /* Types */
733
	    /* Types */
699
	    print_token_type ( output, p, tnm ) ;
734
	    print_token_type(output, p, tnm);
700
	    break ;
735
	    break;
701
	}
736
	}
702
 
737
 
703
	default : {
738
	default : {
704
	    /* Unknown objects */
739
	    /* Unknown objects */
705
	    error ( ERR_INTERNAL, "Unknown object type, '%d'", p->objtype ) ;
740
	    error(ERR_INTERNAL, "Unknown object type, '%d'", p->objtype);
706
	    break ;
741
	    break;
707
	}
742
	}
708
    }
743
    }
709
    return ;
744
    return;
710
}
745
}
711
 
746
 
712
 
747
 
713
/*
748
/*
714
    TYPE REPRESENTING AN IF STATEMENT
749
    TYPE REPRESENTING AN IF STATEMENT
Line 718... Line 753...
718
    the dir field giving the command type and the nm field the associated
753
    the dir field giving the command type and the nm field the associated
719
    expression.
754
    expression.
720
*/
755
*/
721
 
756
 
722
typedef struct {
757
typedef struct {
723
    int dir ;
758
    int dir;
724
    char *nm ;
759
    char *nm;
725
} ifcmd ;
760
} ifcmd;
726
 
761
 
727
 
762
 
728
/*
763
/*
729
    PRINT A NUMBER OF IF STATEMENTS
764
    PRINT A NUMBER OF IF STATEMENTS
730
 
765
 
731
    This routine outputs the list of if statements, ifs, to the file
766
    This routine outputs the list of if statements, ifs, to the file
732
    output.
767
    output.
733
*/
768
*/
734
 
769
 
735
static void print_ifs
770
static void
736
    PROTO_N ( ( output, ifs ) )
-
 
737
    PROTO_T ( FILE *output X ifcmd *ifs )
771
print_ifs(FILE *output, ifcmd *ifs)
738
{
772
{
739
    ifcmd *p ;
773
    ifcmd *p;
740
    boolean changed ;
774
    boolean changed;
741
 
775
 
742
    /* Simplify the list of statements */
776
    /* Simplify the list of statements */
743
    do {
777
    do {
744
	ifcmd *q = null ;
778
	ifcmd *q = null;
745
	changed = 0 ;
779
	changed = 0;
746
	for ( p = ifs ; p->dir != CMD_END ; p++ ) {
780
	for (p = ifs; p->dir != CMD_END; p++) {
747
	    int d = p->dir ;
781
	    int d = p->dir;
748
	    if ( d != CMD_NONE ) {
782
	    if (d != CMD_NONE) {
749
		if ( q && q->dir != CMD_NONE ) {
783
		if (q && q->dir != CMD_NONE) {
750
		    int e = q->dir ;
784
		    int e = q->dir;
751
		    if ( d == CMD_ENDIF ) {
785
		    if (d == CMD_ENDIF) {
752
			if ( e == CMD_ELSE ) {
786
			if (e == CMD_ELSE) {
753
			    /* else + endif -> endif */
787
			    /* else + endif -> endif */
754
			    q->dir = CMD_NONE ;
788
			    q->dir = CMD_NONE;
755
			    changed = 1 ;
789
			    changed = 1;
756
			} else if ( e != CMD_ENDIF ) {
790
			} else if (e != CMD_ENDIF) {
757
			    /* if + endif -> nothing */
791
			    /* if + endif -> nothing */
758
			    p->dir = CMD_NONE ;
792
			    p->dir = CMD_NONE;
759
			    q->dir = CMD_NONE ;
793
			    q->dir = CMD_NONE;
760
			    changed = 1 ;
794
			    changed = 1;
761
			}
795
			}
762
		    }
796
		    }
763
		    if ( d == CMD_ELSE ) {
797
		    if (d == CMD_ELSE) {
764
			if ( e == CMD_IFDEF ) {
798
			if (e == CMD_IFDEF) {
765
			    /* ifdef + else -> ifndef */
799
			    /* ifdef + else -> ifndef */
766
			    p->dir = CMD_IFNDEF ;
800
			    p->dir = CMD_IFNDEF;
767
			    q->dir = CMD_NONE ;
801
			    q->dir = CMD_NONE;
768
			    changed = 1 ;
802
			    changed = 1;
769
			} else if ( e == CMD_IFDEF ) {
803
			} else if (e == CMD_IFDEF) {
770
			    /* ifndef + else -> ifdef */
804
			    /* ifndef + else -> ifdef */
771
			    p->dir = CMD_IFDEF ;
805
			    p->dir = CMD_IFDEF;
772
			    q->dir = CMD_NONE ;
806
			    q->dir = CMD_NONE;
773
			    changed = 1 ;
807
			    changed = 1;
774
			}
808
			}
775
		    }
809
		    }
776
		}
810
		}
777
		q = p ;
811
		q = p;
778
	    }
812
	    }
779
	}
813
	}
780
    } while ( changed ) ;
814
    } while (changed);
781
 
815
 
782
    /* Print the result */
816
    /* Print the result */
783
    if ( column ) OUTC ( output, '\n' ) ;
817
    if (column)OUTC(output, '\n');
784
    for ( p = ifs ; p->dir != CMD_END ; p++ ) {
818
    for (p = ifs; p->dir != CMD_END; p++) {
785
	switch ( p->dir ) {
819
	switch (p->dir) {
786
	    case CMD_IF : {
820
	    case CMD_IF: {
787
		OUT ( output, "#if %s\n", p->nm ) ;
821
		OUT(output, "#if %s\n", p->nm);
788
		break ;
822
		break;
789
	    }
823
	    }
790
	    case CMD_IFDEF : {
824
	    case CMD_IFDEF: {
791
		OUT ( output, "#ifdef %s\n", p->nm ) ;
825
		OUT(output, "#ifdef %s\n", p->nm);
792
		break ;
826
		break;
793
	    }
827
	    }
794
	    case CMD_IFNDEF : {
828
	    case CMD_IFNDEF: {
795
		OUT ( output, "#ifndef %s\n", p->nm ) ;
829
		OUT(output, "#ifndef %s\n", p->nm);
796
		break ;
830
		break;
797
	    }
831
	    }
798
	    case CMD_ELSE : {
832
	    case CMD_ELSE: {
799
		OUT ( output, "#else /* %s */\n", p->nm ) ;
833
		OUT ( output, "#else /* %s */\n", p->nm ) ;
800
		break ;
834
		break;
801
	    }
835
	    }
802
	    case CMD_ENDIF : {
836
	    case CMD_ENDIF: {
803
		OUT ( output, "#endif /* %s */\n", p->nm ) ;
837
		OUT ( output, "#endif /* %s */\n", p->nm ) ;
804
		break ;
838
		break;
805
	    }
839
	    }
806
	}
840
	}
807
    }
841
    }
808
    column = 0 ;
842
    column = 0;
809
    ifs [0].dir = CMD_END ;
843
    ifs [0].dir = CMD_END;
810
    return ;
844
    return;
811
}
845
}
812
 
846
 
813
 
847
 
814
/*
848
/*
815
    PRINT AN INTERFACE ITEM
849
    PRINT AN INTERFACE ITEM
816
 
850
 
817
    This routine prints an interface statement for the object p to the
851
    This routine prints an interface statement for the object p to the
818
    file output.
852
    file output.
819
*/
853
*/
820
 
854
 
821
static void print_interface
855
static void
822
    PROTO_N ( ( output, p, ifs ) )
-
 
823
    PROTO_T ( FILE *output X object *p X ifcmd *ifs )
856
print_interface(FILE *output, object *p, ifcmd *ifs)
824
{
857
{
825
    char *nm = p->name ;
858
    char *nm = p->name;
826
    switch ( p->objtype ) {
859
    switch (p->objtype) {
827
 
860
 
828
	case OBJ_CONST :
861
	case OBJ_CONST:
829
	case OBJ_EXP :
862
	case OBJ_EXP:
830
	case OBJ_MACRO :
863
	case OBJ_MACRO:
831
	case OBJ_NAT :
864
	case OBJ_NAT:
832
	case OBJ_STATEMENT :
865
	case OBJ_STATEMENT:
833
	case OBJ_TOKEN : {
866
	case OBJ_TOKEN: {
834
	    /* Simple tokens are easy */
867
	    /* Simple tokens are easy */
835
	    break ;
868
	    break;
836
	}
869
	}
837
 
870
 
838
	case OBJ_EXTERN :
871
	case OBJ_EXTERN:
839
	case OBJ_WEAK : {
872
	case OBJ_WEAK: {
840
	    /* Deal with externals */
873
	    /* Deal with externals */
841
	    nm = null ;
874
	    nm = null;
842
	    break ;
875
	    break;
843
	}
876
	}
844
 
877
 
845
	case OBJ_FIELD : {
878
	case OBJ_FIELD: {
846
	    /* Deal with fields */
879
	    /* Deal with fields */
847
	    field *f = p->u.u_field ;
880
	    field *f = p->u.u_field;
848
	    switch ( f->stype->id ) {
881
	    switch (f->stype->id) {
849
		case TYPE_STRUCT_TAG :
882
		case TYPE_STRUCT_TAG:
850
		case TYPE_UNION_TAG : {
883
		case TYPE_UNION_TAG: {
851
		    /* Tagged types require some attention */
884
		    /* Tagged types require some attention */
852
		    IGNORE sprintf ( buffer, "TAG %s", nm ) ;
885
		    IGNORE sprintf(buffer, "TAG %s", nm);
853
		    nm = buffer ;
886
		    nm = buffer;
854
		    break ;
887
		    break;
855
		}
888
		}
856
	    }
889
	    }
857
	    break ;
890
	    break;
858
	}
891
	}
859
 
892
 
860
	case OBJ_FUNC : {
893
	case OBJ_FUNC: {
861
	    /* Functions containing ... are not actually tokens */
894
	    /* Functions containing ... are not actually tokens */
862
	    type *t = p->u.u_type->v.next ;
895
	    type *t = p->u.u_type->v.next;
863
	    while ( t != null ) {
896
	    while (t != null) {
864
		if ( t->u.subtype == type_ellipsis ) {
897
		if (t->u.subtype == type_ellipsis) {
865
		    nm = null ;
898
		    nm = null;
866
		    break ;
899
		    break;
867
		}
900
		}
868
		t = t->v.next ;
901
		t = t->v.next;
869
	    }
902
	    }
870
	    break ;
903
	    break;
871
	}
904
	}
872
 
905
 
873
	case OBJ_DEFINE : {
906
	case OBJ_DEFINE: {
874
	    /* Macro definitions are not tokens */
907
	    /* Macro definitions are not tokens */
875
	    nm = null ;
908
	    nm = null;
876
	    break ;
909
	    break;
877
	}
910
	}
878
 
911
 
-
 
912
	case OBJ_DEFMIN: {
-
 
913
	    /* Macro definitions are not tokens */
-
 
914
	    nm = null;
-
 
915
	    break;
-
 
916
	}
-
 
917
 
-
 
918
 
879
	case OBJ_TYPE : {
919
	case OBJ_TYPE: {
880
	    /* Deal with types */
920
	    /* Deal with types */
881
	    type *t = p->u.u_type ;
921
	    type *t = p->u.u_type;
882
	    switch ( t->id ) {
922
	    switch (t->id) {
883
		case TYPE_STRUCT_TAG :
923
		case TYPE_STRUCT_TAG:
884
		case TYPE_UNION_TAG : {
924
		case TYPE_UNION_TAG: {
885
		    /* Tagged types require some attention */
925
		    /* Tagged types require some attention */
886
		    IGNORE sprintf ( buffer, "TAG %s", nm ) ;
926
		    IGNORE sprintf(buffer, "TAG %s", nm);
887
		    nm = buffer ;
927
		    nm = buffer;
888
		    goto type_struct_lab ;
928
		    goto type_struct_lab;
889
		}
929
		}
890
		case TYPE_STRUCT :
930
		case TYPE_STRUCT:
891
		case TYPE_UNION :
931
		case TYPE_UNION:
892
		type_struct_lab : {
932
		type_struct_lab : {
893
		    /* Some structures and unions are not tokens */
933
		    /* Some structures and unions are not tokens */
894
		    if ( t->v.obj2 ) {
934
		    if (t->v.obj2) {
895
			if ( t->state == 2 ) {
935
			if (t->state == 2) {
896
			    t->state = 3 ;
936
			    t->state = 3;
897
			} else {
937
			} else {
898
			    nm = null ;
938
			    nm = null;
899
			}
939
			}
900
		    }
940
		    }
901
		    break ;
941
		    break;
902
		}
942
		}
903
		case TYPE_DEFINED : {
943
		case TYPE_DEFINED: {
904
		    /* Type definitions are not tokens */
944
		    /* Type definitions are not tokens */
905
		    nm = null ;
945
		    nm = null;
906
		    break ;
946
		    break;
907
		}
947
		}
908
		case TYPE_ENUM :
948
		case TYPE_ENUM:
909
		case TYPE_ENUM_TAG : {
949
		case TYPE_ENUM_TAG: {
910
		    /* Enumeration types are not tokens */
950
		    /* Enumeration types are not tokens */
911
		    nm = null ;
951
		    nm = null;
912
		    break ;
952
		    break;
913
		}
953
		}
914
	    }
954
	    }
915
	    break ;
955
	    break;
916
	}
956
	}
917
 
957
 
918
	default : {
958
	default : {
919
	    /* Unknown objects */
959
	    /* Unknown objects */
920
	    error ( ERR_INTERNAL, "Unknown object type, '%d'", p->objtype ) ;
960
	    error(ERR_INTERNAL, "Unknown object type, '%d'", p->objtype);
921
	    nm = null ;
961
	    nm = null;
922
	    break ;
962
	    break;
923
	}
963
	}
924
    }
964
    }
925
 
965
 
926
    /* Print the interface statement */
966
    /* Print the interface statement */
927
    if ( nm ) {
967
    if (nm) {
928
	int n = ( int ) strlen ( nm ) + 1 ;
968
	int n = (int)strlen(nm) + 1;
929
	if ( ifs [0].dir != CMD_END ) print_ifs ( output, ifs ) ;
969
	if (ifs [0].dir != CMD_END)print_ifs(output, ifs);
930
	if ( column + n >= 60 ) {
970
	if (column + n >= 60) {
931
	    OUTC ( output, '\n' ) ;
971
	    OUTC(output, '\n');
932
	    column = 0 ;
972
	    column = 0;
933
	}
973
	}
934
	if ( column == 0 ) OUTS ( output, "#pragma interface" ) ;
974
	if (column == 0)OUTS(output, "#pragma interface");
935
	OUTC ( output, ' ' ) ;
975
	OUTC(output, ' ');
936
	OUTS ( output, nm ) ;
976
	OUTS(output, nm);
937
	column += n ;
977
	column += n;
938
    }
978
    }
939
    return ;
979
    return;
940
}
980
}
941
 
981
 
942
 
982
 
943
/*
983
/*
944
    PRINT AN INCLUDED FILE
984
    PRINT AN INCLUDED FILE
945
*/
985
*/
946
 
986
 
947
static void print_include
987
static void
948
    PROTO_N ( ( output, nm, on ) )
-
 
949
    PROTO_T ( FILE *output X char *nm X int on )
988
print_include(FILE *output, char *nm, int on)
950
{
989
{
951
    object *p ;
990
    object *p;
952
    if ( nm == null ) return ;
991
    if (nm == null) return;
953
    IGNORE sprintf ( buffer, "%s[%s]", crt_info->src, nm ) ;
992
    IGNORE sprintf(buffer, "%s[%s]", crt_info->src, nm);
954
    if ( search_hash ( files, buffer, no_version ) ) return ;
993
    if (search_hash(files, buffer, no_version)) return;
955
    p = make_object ( string_copy ( buffer ), OBJ_FILE ) ;
994
    p = make_object(string_copy(buffer), OBJ_FILE);
956
    p->u.u_file = null ;
995
    p->u.u_file = null;
957
    IGNORE add_hash ( files, p, no_version ) ;
996
    IGNORE add_hash(files, p, no_version);
958
    if ( on ) OUT ( output, "#include <%s>\n", nm ) ;
997
    if (on)OUT(output, "#include <%s>\n", nm);
959
    return ;
998
    return;
960
}
999
}
961
 
1000
 
962
 
1001
 
963
/*
1002
/*
964
    PRINT AN OBJECT
1003
    PRINT AN OBJECT
965
 
1004
 
966
    This routine prints the list of objects input to the file output, the
1005
    This routine prints the list of objects input to the file output, the
967
    form of the information to be printed being indicated by pass.
1006
    form of the information to be printed being indicated by pass.
968
*/
1007
*/
969
 
1008
 
970
static void print_object
1009
static void
971
    PROTO_N ( ( output, input, pass ) )
-
 
972
    PROTO_T ( FILE *output X object *input X int pass )
1010
print_object(FILE *output, object *input, int pass)
973
{
1011
{
974
    object *p ;
1012
    object *p;
975
    ifcmd ifs [100] ;
1013
    ifcmd ifs [100];
976
    ifs [0].dir = CMD_END ;
1014
    ifs [0].dir = CMD_END;
977
    for ( p = input ; p != null ; p = p->next ) {
1015
    for (p = input; p != null; p = p->next) {
978
	char *nm = p->name ;
1016
	char *nm = p->name;
979
	switch ( p->objtype ) {
1017
	switch (p->objtype) {
980
 
1018
 
981
	    case OBJ_IF	 : {
1019
	    case OBJ_IF	: {
982
		/* If statements etc. */
1020
		/* If statements etc. */
983
		if ( pass != 1 ) {
1021
		if (pass != 1) {
984
		    int i = 0 ;
1022
		    int i = 0;
985
		    while ( ifs [i].dir != CMD_END ) i++ ;
1023
		    while (ifs [i].dir != CMD_END)i++;
986
		    ifs [i].dir = p->u.u_num ;
1024
		    ifs [i].dir = p->u.u_num;
987
		    ifs [i].nm = p->name ;
1025
		    ifs [i].nm = p->name;
988
		    ifs [ i + 1 ].dir = CMD_END ;
1026
		    ifs [ i + 1 ].dir = CMD_END;
989
		    if ( i >= 90 ) print_ifs ( output, ifs ) ;
1027
		    if (i >= 90)print_ifs(output, ifs);
990
		}
1028
		}
991
		break ;
1029
		break;
992
	    }
1030
	    }
993
 
1031
 
994
	    case OBJ_IMPLEMENT :
1032
	    case OBJ_IMPLEMENT:
995
	    case OBJ_USE : {
1033
	    case OBJ_USE: {
996
		/* Inclusion statements */
1034
		/* Inclusion statements */
997
		if ( pass < 2 && nm [ pass ] == '1' ) {
1035
		if (pass < 2 && nm [ pass ] == '1') {
998
		    object *q = p->u.u_obj ;
1036
		    object *q = p->u.u_obj;
999
		    info *i = q->u.u_info ;
1037
		    info *i = q->u.u_info;
1000
		    char *b = BUILDING_MACRO ;
1038
		    char *b = BUILDING_MACRO;
1001
		    if ( streq ( i->api, LOCAL_API ) ) break ;
1039
		    if (streq(i->api, LOCAL_API))break;
1002
		    if ( ifs [0].dir != CMD_END ) print_ifs ( output, ifs ) ;
1040
		    if (ifs [0].dir != CMD_END)print_ifs(output, ifs);
1003
		    if ( pass == 0 ) {
1041
		    if (pass == 0) {
1004
			char *f ;
1042
			char *f;
1005
			char *dir ;
1043
			char *dir;
1006
			char *m = i->protect ;
1044
			char *m = i->protect;
1007
			int n = output_incl_len ;
1045
			int n = output_incl_len;
1008
			if ( nm [2] == 'G' ) {
1046
			if (nm [2] == 'G') {
1009
			    OUT ( output, "#ifndef %s\n", b ) ;
1047
			    OUT(output, "#ifndef %s\n", b);
1010
			    dir = "#pragma extend interface [%s]\n" ;
1048
			    dir = "#pragma extend interface [%s]\n";
1011
			    OUT ( output, dir, i->file ) ;
1049
			    OUT(output, dir, i->file);
1012
			    OUT ( output, "#else /* %s */\n", b ) ;
1050
			    OUT ( output, "#else /* %s */\n", b ) ;
1013
			    m = "" ;
1051
			    m = "";
1014
			}
1052
			}
1015
			if ( *m ) OUT ( output, "#ifndef %s\n", m ) ;
1053
			if (*m)OUT(output, "#ifndef %s\n", m);
1016
			if ( local_input ) {
1054
			if (local_input) {
1017
			    f = i->incl + n ;
1055
			    f = i->incl + n;
1018
			    dir = "#pragma extend interface <../%s>\n" ;
1056
			    dir = "#pragma extend interface <../%s>\n";
1019
			} else {
1057
			} else {
1020
			    f = relative ( crt_info->incl, i->incl, n ) ;
1058
			    f = relative(crt_info->incl, i->incl, n);
1021
			    dir = "#pragma extend interface \"%s\"\n" ;
1059
			    dir = "#pragma extend interface \"%s\"\n";
1022
			}
1060
			}
1023
			OUT ( output, dir, f ) ;
1061
			OUT(output, dir, f);
1024
			if ( *m ) OUT ( output, "#endif /* %s */\n", m ) ;
1062
			if ( *m ) OUT ( output, "#endif /* %s */\n", m ) ;
1025
			if ( nm [2] == 'G' ) {
1063
			if (nm [2] == 'G') {
1026
			    OUT ( output, "#endif /* %s */\n", b ) ;
1064
			    OUT ( output, "#endif /* %s */\n", b ) ;
1027
			}
1065
			}
1028
		    } else {
1066
		    } else {
1029
			print_include ( output, i->file, 1 ) ;
1067
			print_include(output, i->file, 1);
1030
		    }
1068
		    }
1031
		}
1069
		}
1032
		break ;
1070
		break;
1033
	    }
1071
	    }
1034
 
1072
 
1035
	    case OBJ_SET : {
1073
	    case OBJ_SET: {
1036
		/* Subsets */
1074
		/* Subsets */
1037
		object *q = p->u.u_obj ;
1075
		object *q = p->u.u_obj;
1038
		info *i = q->u.u_info ;
1076
		info *i = q->u.u_info;
1039
		if ( streq ( i->api, LOCAL_API ) ) {
1077
		if (streq(i->api, LOCAL_API)) {
1040
		    if ( ifs [0].dir != CMD_END ) print_ifs ( output, ifs ) ;
1078
		    if (ifs [0].dir != CMD_END)print_ifs(output, ifs);
1041
		    print_object ( output, i->elements, pass ) ;
1079
		    print_object(output, i->elements, pass);
1042
		} else {
1080
		} else {
1043
		    if ( pass < 2 ) {
1081
		    if (pass < 2) {
1044
			if ( ifs [0].dir != CMD_END ) {
1082
			if (ifs [0].dir != CMD_END) {
1045
			    print_ifs ( output, ifs ) ;
1083
			    print_ifs(output, ifs);
1046
			}
1084
			}
1047
			print_set ( p, pass ) ;
1085
			print_set(p, pass);
1048
		    }
1086
		    }
1049
		}
1087
		}
1050
		break ;
1088
		break;
1051
	    }
1089
	    }
1052
 
1090
 
1053
	    case OBJ_TEXT_INCL : {
1091
	    case OBJ_TEXT_INCL: {
1054
		/* Include file quoted text */
1092
		/* Include file quoted text */
1055
		if ( pass == 0 ) {
1093
		if (pass == 0) {
1056
		    if ( ifs [0].dir != CMD_END ) print_ifs ( output, ifs ) ;
1094
		    if (ifs [0].dir != CMD_END)print_ifs(output, ifs);
1057
		    OUTS ( output, nm ) ;
1095
		    OUTS(output, nm);
1058
		    OUTC ( output, '\n' ) ;
1096
		    OUTC(output, '\n');
1059
		}
1097
		}
1060
		break ;
1098
		break;
1061
	    }
1099
	    }
1062
 
1100
 
1063
	    case OBJ_TEXT_SRC : {
1101
	    case OBJ_TEXT_SRC: {
1064
		/* Source file quoted text */
1102
		/* Source file quoted text */
1065
		if ( pass == 1 ) {
1103
		if (pass == 1) {
1066
		    if ( ifs [0].dir != CMD_END ) print_ifs ( output, ifs ) ;
1104
		    if (ifs [0].dir != CMD_END)print_ifs(output, ifs);
1067
		    OUTS ( output, nm ) ;
1105
		    OUTS(output, nm);
1068
		    OUTC ( output, '\n' ) ;
1106
		    OUTC(output, '\n');
1069
		}
1107
		}
1070
		break ;
1108
		break;
1071
	    }
1109
	    }
1072
 
1110
 
1073
	    case OBJ_TOKEN : {
1111
	    case OBJ_TOKEN: {
1074
		/* Tokenised objects */
1112
		/* Tokenised objects */
1075
		if ( pass == 0 ) {
1113
		if (pass == 0) {
1076
		    if ( ifs [0].dir != CMD_END ) print_ifs ( output, ifs ) ;
1114
		    if (ifs [0].dir != CMD_END)print_ifs(output, ifs);
1077
		    print_token ( output, p->u.u_obj, nm ) ;
1115
		    print_token(output, p->u.u_obj, nm);
1078
		} else if ( pass == 2 ) {
1116
		} else if (pass == 2) {
1079
		    print_interface ( output, p->u.u_obj, ifs ) ;
1117
		    print_interface(output, p->u.u_obj, ifs);
1080
		}
1118
		}
1081
		break ;
1119
		break;
1082
	    }
1120
	    }
1083
 
1121
 
1084
	    case OBJ_TYPE : {
1122
	    case OBJ_TYPE: {
1085
		/* Definition of previously declared type */
1123
		/* Definition of previously declared type */
1086
		if ( pass == 0 ) {
1124
		if (pass == 0) {
1087
		    type *t = p->u.u_type ;
1125
		    type *t = p->u.u_type;
1088
		    char *tnm = t->u.obj->name ;
1126
		    char *tnm = t->u.obj->name;
1089
		    print_struct_defn ( output, t, tnm, tnm, 1 ) ;
1127
		    print_struct_defn(output, t, tnm, tnm, 1);
1090
		}
1128
		}
1091
		break ;
1129
		break;
1092
	    }
1130
	    }
1093
 
1131
 
1094
	    default : {
1132
	    default : {
1095
		/* Unknown objects */
1133
		/* Unknown objects */
1096
		char *err = "Unknown object type, '%d'" ;
1134
		char *err = "Unknown object type, '%d'";
1097
		error ( ERR_INTERNAL, err, p->objtype ) ;
1135
		error(ERR_INTERNAL, err, p->objtype);
1098
		break ;
1136
		break;
1099
	    }
1137
	    }
1100
	}
1138
	}
1101
    }
1139
    }
1102
    if ( ifs [0].dir != CMD_END ) print_ifs ( output, ifs ) ;
1140
    if (ifs [0].dir != CMD_END)print_ifs(output, ifs);
1103
    return ;
1141
    return;
1104
}
1142
}
1105
 
1143
 
1106
 
1144
 
1107
/*
1145
/*
1108
    SCAN AN OBJECT
1146
    SCAN AN OBJECT
1109
 
1147
 
1110
    This routine scans the object input, calling print_set on any subsets.
1148
    This routine scans the object input, calling print_set on any subsets.
1111
*/
1149
*/
1112
 
1150
 
1113
static void scan_object
1151
static void
1114
    PROTO_N ( ( input, pass ) )
-
 
1115
    PROTO_T ( object *input X int pass )
1152
scan_object(object *input, int pass)
1116
{
1153
{
1117
    object *p ;
1154
    object *p;
1118
    for ( p = input ; p != null ; p = p->next ) {
1155
    for (p = input; p != null; p = p->next) {
1119
	if ( p->objtype == OBJ_SET ) {
1156
	if (p->objtype == OBJ_SET) {
1120
	    object *q = p->u.u_obj ;
1157
	    object *q = p->u.u_obj;
1121
	    info *i = q->u.u_info ;
1158
	    info *i = q->u.u_info;
1122
	    if ( streq ( i->api, LOCAL_API ) ) {
1159
	    if (streq(i->api, LOCAL_API)) {
1123
		scan_object ( i->elements, pass ) ;
1160
		scan_object(i->elements, pass);
1124
	    } else {
1161
	    } else {
1125
		if ( pass < 2 ) print_set ( p, pass ) ;
1162
		if (pass < 2)print_set(p, pass);
1126
	    }
1163
	    }
1127
	}
1164
	}
1128
    }
1165
    }
1129
    return ;
1166
    return;
1130
}
1167
}
1131
 
1168
 
1132
 
1169
 
1133
/*
1170
/*
1134
    PRINT A SET
1171
    PRINT A SET
1135
 
1172
 
1136
    This routine prints the set of objects given by input.  The form of the
1173
    This routine prints the set of objects given by input.  The form of the
1137
    output is indicated by pass.
1174
    output is indicated by pass.
1138
*/
1175
*/
1139
 
1176
 
1140
void print_set
1177
void
1141
    PROTO_N ( ( input, pass ) )
-
 
1142
    PROTO_T ( object *input X int pass )
1178
print_set(object *input, int pass)
1143
{
1179
{
1144
    char *nm ;
1180
    char *nm;
1145
    time_t t1, t2 ;
1181
    time_t t1, t2;
1146
    FILE *output = null ;
1182
    FILE *output = null;
1147
    object *ss = input->u.u_obj ;
1183
    object *ss = input->u.u_obj;
1148
    info *i = ss->u.u_info ;
1184
    info *i = ss->u.u_info;
1149
    column = 0 ;
1185
    column = 0;
1150
 
1186
 
1151
    if ( streq ( i->api, LOCAL_API ) ) {
1187
    if (streq(i->api, LOCAL_API)) {
1152
	/* Local files go to the standard output */
1188
	/* Local files go to the standard output */
1153
	if ( pass != 0 ) return ;
1189
	if (pass != 0) return;
1154
	nm = "stdout" ;
1190
	nm = "stdout";
1155
	output = stdout ;
1191
	output = stdout;
1156
	t1 = ( time_t ) 0 ;
1192
	t1 = (time_t)0;
1157
	t2 = ( time_t ) 0 ;
1193
	t2 = (time_t)0;
1158
    } else {
1194
    } else {
1159
	nm = ( pass ? i->src : i->incl ) ;
1195
	nm = (pass ? i->src : i->incl);
1160
	if ( nm == null || ( restrict_use && i->implemented == 0 ) ) {
1196
	if (nm == null || (restrict_use && i->implemented == 0)) {
1161
	    scan_object ( i->elements, 1 ) ;
1197
	    scan_object(i->elements, 1);
1162
	    return ;
1198
	    return;
1163
	}
1199
	}
1164
	if ( pass == 1 && i->tokens == 0 ) {
1200
	if (pass == 1 && i->tokens == 0) {
1165
	    if ( verbose > 1 ) {
1201
	    if (verbose > 1) {
1166
		error ( ERR_INFO, "%s is not required ...", nm ) ;
1202
		IGNORE printf("%s is not required ...\n", nm);
1167
	    }
1203
	    }
1168
	    scan_object ( i->elements, 1 ) ;
1204
	    scan_object(i->elements, 1);
1169
	    return ;
1205
	    return;
1170
	}
1206
	}
1171
	t1 = i->age ;
1207
	t1 = i->age;
1172
	if ( progdate > t1 ) t1 = progdate ;
1208
	if (progdate > t1)t1 = progdate;
1173
	t2 = date_stamp ( nm ) ;
1209
	t2 = date_stamp(nm);
1174
    }
1210
    }
1175
 
1211
 
1176
    if ( ( t1 && t1 < t2 ) && !force_output ) {
1212
    if ((t1 && t1 < t2) && !force_output) {
1177
	/* Output file is up to date */
1213
	/* Output file is up to date */
1178
	object *q ;
1214
	object *q;
1179
	if ( verbose > 1 ) error ( ERR_INFO, "%s is up to date ...", nm ) ;
1215
	if (verbose > 1) IGNORE printf("%s is up to date ...\n", nm);
1180
	q = make_object ( nm, OBJ_FILE ) ;
1216
	q = make_object(nm, OBJ_FILE);
1181
	q->u.u_file = null ;
1217
	q->u.u_file = null;
1182
	IGNORE add_hash ( files, q, no_version ) ;
1218
	IGNORE add_hash(files, q, no_version);
1183
	for ( q = i->elements ; q != null ; q = q->next ) {
1219
	for (q = i->elements; q != null; q = q->next) {
1184
	    if ( q->objtype == OBJ_SET ) print_set ( q, pass ) ;
1220
	    if (q->objtype == OBJ_SET)print_set(q, pass);
1185
	}
1221
	}
1186
    } else {
1222
    } else {
1187
	/* Output file needs updating */
1223
	/* Output file needs updating */
1188
	object *q = null ;
1224
	object *q = null;
1189
	info *old_info = crt_info ;
1225
	info *old_info = crt_info;
1190
	int old_column = column ;
1226
	int old_column = column;
1191
	boolean old_weak_proto = weak_proto ;
1227
	boolean old_weak_proto = weak_proto;
1192
	weak_proto = 0 ;
1228
	weak_proto = 0;
1193
 
1229
 
1194
	/* Open output file */
1230
	/* Open output file */
1195
	if ( output == null ) {
1231
	if (output == null) {
1196
	    create_dir ( nm ) ;
1232
	    create_dir(nm);
1197
	    if ( verbose ) error ( ERR_INFO, "Creating %s ...", nm ) ;
1233
	    if (verbose) IGNORE printf("Creating %s ...\n", nm);
1198
	    check_name ( nm ) ;
1234
	    check_name(nm);
1199
	    q = make_object ( nm, OBJ_FILE ) ;
1235
	    q = make_object(nm, OBJ_FILE);
1200
	    q->u.u_file = null ;
1236
	    q->u.u_file = null;
1201
	    IGNORE add_hash ( files, q, no_version ) ;
1237
	    IGNORE add_hash(files, q, no_version);
1202
	    output = fopen ( nm, "w" ) ;
1238
	    output = fopen(nm, "w");
1203
	    q->u.u_file = output ;
1239
	    q->u.u_file = output;
1204
	    if ( output == null ) {
1240
	    if (output == null) {
1205
		error ( ERR_SERIOUS, "Can't open output file, %s", nm ) ;
1241
		error(ERR_SERIOUS, "Can't open output file, %s", nm);
1206
		return ;
1242
		return;
1207
	    }
1243
	    }
1208
	}
1244
	}
1209
 
1245
 
1210
	crt_info = i ;
1246
	crt_info = i;
1211
	if ( pass == 0 ) {
1247
	if (pass == 0) {
1212
	    /* Include output file */
1248
	    /* Include output file */
1213
	    char *m = i->protect ;
1249
	    char *m = i->protect;
1214
	    char *v = i->version ;
1250
	    char *v = i->version;
1215
 
1251
 
1216
	    /* Print the copyright message */
1252
	    /* Print the copyright message */
1217
	    if ( copyright ) {
1253
	    if (copyright) {
1218
		if ( copyright_text == null ) {
1254
		if (copyright_text == null) {
1219
		    FILE *f = fopen ( copyright, "r" ) ;
1255
		    FILE *f = fopen(copyright, "r");
1220
		    if ( f == null ) {
1256
		    if (f == null) {
1221
			char *err = "Can't open copyright file, %s" ;
1257
			char *err = "Can't open copyright file, %s";
1222
			error ( ERR_SERIOUS, err, copyright ) ;
1258
			error(ERR_SERIOUS, err, copyright);
1223
			copyright_text = "" ;
1259
			copyright_text = "";
1224
		    } else {
1260
		    } else {
1225
			int c, j = 0 ;
1261
			int c, j = 0;
1226
			while ( c = getc ( f ), c != EOF ) {
1262
			while (c = getc(f), c != EOF) {
1227
			    buffer [j] = ( char ) c ;
1263
			    buffer [j] = (char)c;
1228
			    if ( ++j >= buffsize ) {
1264
			    if (++j >= buffsize) {
1229
				error ( ERR_SERIOUS, "Copyright too long" ) ;
1265
				error(ERR_SERIOUS, "Copyright too long");
1230
				break ;
1266
				break;
1231
			    }
1267
			    }
1232
			}
1268
			}
1233
			buffer [j] = 0 ;
1269
			buffer [j] = 0;
1234
			copyright_text = string_copy ( buffer ) ;
1270
			copyright_text = string_copy(buffer);
1235
			IGNORE fclose ( f ) ;
1271
			IGNORE fclose(f);
1236
		    }
1272
		    }
1237
		}
1273
		}
1238
		OUTS ( output, copyright_text ) ;
1274
		OUTS(output, copyright_text);
1239
	    }
1275
	    }
1240
 
1276
 
1241
	    /* Find the version number */
1277
	    /* Find the version number */
1242
	    if ( v == null && i->subset ) {
1278
	    if (v == null && i->subset) {
1243
		char *a = subset_name ( i->api, i->file, null_str ) ;
1279
		char *a = subset_name(i->api, i->file, null_str);
1244
		object *ap = make_subset ( a ) ;
1280
		object *ap = make_subset(a);
1245
		v = ap->u.u_info->version ;
1281
		v = ap->u.u_info->version;
1246
	    }
1282
	    }
1247
	    if ( v == null && i->file ) {
1283
	    if (v == null && i->file) {
1248
		char *a = subset_name ( i->api, null_str, null_str ) ;
1284
		char *a = subset_name(i->api, null_str, null_str);
1249
		object *ap = make_subset ( a ) ;
1285
		object *ap = make_subset(a);
1250
		v = ap->u.u_info->version ;
1286
		v = ap->u.u_info->version;
1251
	    }
1287
	    }
1252
 
1288
 
1253
	    /* Print the file header */
1289
	    /* Print the file header */
1254
	    OUTS ( output, "/*\n    AUTOMATICALLY GENERATED BY " ) ;
1290
	    OUTS ( output, "/*\n    AUTOMATICALLY GENERATED BY " ) ;
1255
	    OUT ( output, "%s %s\n", progname, progvers ) ;
1291
	    OUT ( output, "%s %s\n", progname, progvers ) ;
1256
	    OUT ( output, "    API SUBSET: %s", ss->name ) ;
1292
	    OUT ( output, "    API SUBSET: %s", ss->name ) ;
1257
	    if ( v ) OUT ( output, " (VERSION %s)", v ) ;
1293
	    if ( v ) OUT ( output, " (VERSION %s)", v ) ;
1258
	    OUTS ( output, "\n*/\n\n" ) ;
1294
	    OUTS ( output, "\n*/\n\n" ) ;
1259
 
1295
 
1260
	    /* Print the file body */
1296
	    /* Print the file body */
1261
	    if ( *m ) {
1297
	    if (*m) {
1262
		OUT ( output, "#ifndef %s\n", m ) ;
1298
		OUT(output, "#ifndef %s\n", m);
1263
		OUT ( output, "#define %s\n\n", m ) ;
1299
		OUT(output, "#define %s\n\n", m);
1264
	    }
1300
	    }
1265
	    if ( i->elements ) {
1301
	    if (i->elements) {
1266
		boolean is_cpplus = 0 ;
1302
		boolean is_cpplus = 0;
1267
		if ( i->linkage ) {
1303
		if (i->linkage) {
1268
		    if ( streq ( i->linkage, "C++" ) ) {
1304
		    if (streq(i->linkage, "C++")) {
1269
			OUT ( output, "extern \"%s\" {\n\n", i->linkage ) ;
1305
			OUT(output, "extern \"%s\" {\n\n", i->linkage);
1270
			is_cpplus = 1 ;
1306
			is_cpplus = 1;
1271
		    } else {
1307
		    } else {
1272
			OUT ( output, "#ifdef __cplusplus\n" ) ;
1308
			OUT(output, "#ifdef __cplusplus\n");
1273
			OUT ( output, "extern \"%s\" {\n", i->linkage ) ;
1309
			OUT(output, "extern \"%s\" {\n", i->linkage);
1274
			OUT ( output, "#endif\n\n" ) ;
1310
			OUT(output, "#endif\n\n");
1275
		    }
1311
		    }
1276
		}
1312
		}
1277
		if ( i->nspace ) {
1313
		if (i->nspace) {
1278
		    if ( is_cpplus ) {
1314
		    if (is_cpplus) {
1279
			OUT ( output, "namespace %s {\n\n", i->nspace ) ;
1315
			OUT(output, "namespace %s {\n\n", i->nspace);
1280
		    } else {
1316
		    } else {
1281
			OUT ( output, "#ifdef __cplusplus\n" ) ;
1317
			OUT(output, "#ifdef __cplusplus\n");
1282
			OUT ( output, "namespace %s {\n", i->nspace ) ;
1318
			OUT(output, "namespace %s {\n", i->nspace);
1283
			OUT ( output, "#endif\n\n" ) ;
1319
			OUT(output, "#endif\n\n");
1284
		    }
1320
		    }
1285
		}
1321
		}
1286
		if ( i->block ) {
1322
		if (i->block) {
1287
		    char *dir ;
1323
		    char *dir;
1288
		    dir = "#pragma TenDRA declaration block %s begin\n\n" ;
1324
		    dir = "#pragma TenDRA declaration block %s begin\n\n";
1289
		    OUT ( output, dir, i->block ) ;
1325
		    OUT(output, dir, i->block);
1290
		}
1326
		}
1291
		print_object ( output, i->elements, 0 ) ;
1327
		print_object(output, i->elements, 0);
1292
		if ( i->tokens ) OUTC ( output, '\n' ) ;
1328
		if (i->tokens)OUTC(output, '\n');
1293
		print_object ( output, i->elements, 2 ) ;
1329
		print_object(output, i->elements, 2);
1294
		if ( column ) OUTC ( output, '\n' ) ;
1330
		if (column)OUTC(output, '\n');
1295
		if ( i->block ) {
1331
		if (i->block) {
1296
		    char *dir ;
1332
		    char *dir;
1297
		    dir = "\n#pragma TenDRA declaration block end\n" ;
1333
		    dir = "\n#pragma TenDRA declaration block end\n";
1298
		    OUT ( output, dir ) ;
1334
		    OUT(output, dir);
1299
		}
1335
		}
1300
		if ( i->nspace ) {
1336
		if (i->nspace) {
1301
		    if ( is_cpplus ) {
1337
		    if (is_cpplus) {
1302
			OUT ( output, "\n}\n" ) ;
1338
			OUT(output, "\n}\n");
1303
		    } else {
1339
		    } else {
1304
			OUT ( output, "\n#ifdef __cplusplus\n" ) ;
1340
			OUT(output, "\n#ifdef __cplusplus\n");
1305
			OUT ( output, "}\n" ) ;
1341
			OUT(output, "}\n");
1306
			OUT ( output, "#endif\n" ) ;
1342
			OUT(output, "#endif\n");
1307
		    }
1343
		    }
1308
		}
1344
		}
1309
		if ( i->linkage ) {
1345
		if (i->linkage) {
1310
		    if ( is_cpplus ) {
1346
		    if (is_cpplus) {
1311
			OUT ( output, "\n}\n" ) ;
1347
			OUT(output, "\n}\n");
1312
		    } else {
1348
		    } else {
1313
			OUT ( output, "\n#ifdef __cplusplus\n" ) ;
1349
			OUT(output, "\n#ifdef __cplusplus\n");
1314
			OUT ( output, "}\n" ) ;
1350
			OUT(output, "}\n");
1315
			OUT ( output, "#endif\n" ) ;
1351
			OUT(output, "#endif\n");
1316
		    }
1352
		    }
1317
		}
1353
		}
1318
	    }
1354
	    }
1319
	    if ( *m ) OUT ( output, "\n#endif /* %s */\n", m ) ;
1355
	    if ( *m ) OUT ( output, "\n#endif /* %s */\n", m ) ;
1320
 
1356
 
1321
	} else {
1357
	} else {
1322
	    /* Source output file */
1358
	    /* Source output file */
1323
	    if ( i->method == null ) {
1359
	    if (i->method == null) {
1324
		char *m, *s ;
1360
		char *m, *s;
1325
		char *w1, *w2 ;
1361
		char *w1, *w2;
1326
		int n = output_incl_len ;
1362
		int n = output_incl_len;
1327
		m = macro_name ( DEFINE_PREFIX, i->api, i->file, i->subset ) ;
1363
		m = macro_name(DEFINE_PREFIX, i->api, i->file, i->subset);
1328
		w1 = macro_name ( WRONG_PREFIX, i->api, null_str, null_str ) ;
1364
		w1 = macro_name(WRONG_PREFIX, i->api, null_str, null_str);
1329
		w2 = macro_name ( WRONG_PREFIX, i->api, i->file, i->subset ) ;
1365
		w2 = macro_name(WRONG_PREFIX, i->api, i->file, i->subset);
1330
		s = i->incl + n ;
1366
		s = i->incl + n;
1331
		OUTS ( output, "/* AUTOMATICALLY GENERATED BY " ) ;
1367
		OUTS ( output, "/* AUTOMATICALLY GENERATED BY " ) ;
1332
		OUT ( output, "%s %s */\n", progname, progvers ) ;
1368
		OUT ( output, "%s %s */\n", progname, progvers ) ;
1333
		OUT ( output, "#ifndef %s\n", w1 ) ;
1369
		OUT(output, "#ifndef %s\n", w1);
1334
		OUT ( output, "#ifndef %s\n", w2 ) ;
1370
		OUT(output, "#ifndef %s\n", w2);
1335
		OUT ( output, "#if #include ( %s )\n", i->file ) ;
1371
		OUT(output, "#if #include ( %s )\n", i->file);
1336
		OUT ( output, "#define %s\n", m ) ;
1372
		OUT(output, "#define %s\n", m);
1337
		print_include ( output, i->file, 0 ) ;
1373
		print_include(output, i->file, 0);
1338
		print_object ( output, i->elements, 1 ) ;
1374
		print_object(output, i->elements, 1);
1339
		OUT ( output, "#include <%s>\n", i->file ) ;
1375
		OUT(output, "#include <%s>\n", i->file);
1340
		OUT ( output, "#endif\n" ) ;
1376
		OUT(output, "#endif\n");
1341
		OUT ( output, "#endif\n\n" ) ;
1377
		OUT(output, "#endif\n\n");
1342
		OUT ( output, "#ifndef %s\n", m ) ;
1378
		OUT(output, "#ifndef %s\n", m);
1343
		OUT ( output, "#pragma TenDRA no token definition allow\n" ) ;
1379
		OUT(output, "#pragma TenDRA no token definition allow\n");
1344
		OUT ( output, "#endif\n" ) ;
1380
		OUT(output, "#endif\n");
1345
		OUT ( output, "#pragma implement interface <../%s>\n", s ) ;
1381
		OUT(output, "#pragma implement interface <../%s>\n", s);
1346
		OUT ( output, "#endif\n" ) ;
1382
		OUT(output, "#endif\n");
1347
	    } else {
1383
	    } else {
1348
		print_object ( output, i->elements, 1 ) ;
1384
		print_object(output, i->elements, 1);
1349
	    }
1385
	    }
1350
	}
1386
	}
1351
 
1387
 
1352
	/* End the output */
1388
	/* End the output */
1353
	IGNORE fclose ( output ) ;
1389
	IGNORE fclose(output);
1354
	if ( q ) q->u.u_file = null ;
1390
	if (q)q->u.u_file = null;
1355
	crt_info = old_info ;
1391
	crt_info = old_info;
1356
	column = old_column ;
1392
	column = old_column;
1357
	weak_proto = old_weak_proto ;
1393
	weak_proto = old_weak_proto;
1358
    }
1394
    }
1359
    return ;
1395
    return;
1360
}
1396
}