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 "errors.h"
33
#include "entry_ops.h"
34
#include "map_ops.h"
35
#include "msg_ops.h"
36
#include "name_ops.h"
37
#include "param_ops.h"
38
#include "error.h"
39
#include "lex.h"
40
#include "process.h"
41
#include "xalloc.h"
42
 
43
 
44
/*
45
    DATABASE HEADER INFORMATION
46
 
47
    These variables are used to store the standard header information.
48
*/
49
 
50
char *db_name = "ERRORS" ;
51
char *db_name_alt = "ERRORS" ;
52
char *rig_name = "ERR_" ;
53
char *rig_comp_output = "ERR_" ;
54
char *rig_from_comp = "ERR_USE_" ;
55
char *rig_from_db = "ERR_NO_" ;
56
 
57
 
58
/*
59
    DATABASE SECTION LISTS
60
 
61
    These variables are used to store the various lists of information
62
    built up by the parser.
63
*/
64
 
65
LIST ( ENTRY ) all_entries = NULL_list ( ENTRY ) ;
66
LIST ( KEY ) all_keys = NULL_list ( KEY ) ;
67
LIST ( PROPERTY ) all_props = NULL_list ( PROPERTY ) ;
68
LIST ( TYPE ) all_types = NULL_list ( TYPE ) ;
69
LIST ( USAGE ) all_usages = NULL_list ( USAGE ) ;
70
LIST ( KEY ) all_keys_aux = NULL_list ( KEY ) ;
71
LIST ( PROPERTY ) all_props_aux = NULL_list ( PROPERTY ) ;
72
LIST ( TYPE ) all_types_aux = NULL_list ( TYPE ) ;
73
LIST ( USAGE ) all_usages_aux = NULL_list ( USAGE ) ;
74
LIST ( KEY ) all_keys_alt = NULL_list ( KEY ) ;
75
LIST ( PROPERTY ) all_props_alt = NULL_list ( PROPERTY ) ;
76
LIST ( TYPE ) all_types_alt = NULL_list ( TYPE ) ;
77
LIST ( USAGE ) all_usages_alt = NULL_list ( USAGE ) ;
78
 
79
 
80
/*
81
    FIND CODE LETTER
82
 
83
    This routine finds a code letter corresponding to the number n.  It
84
    assumes the ASCII character set.
85
*/
86
 
87
static int code_letter
88
    PROTO_N ( ( n ) )
89
    PROTO_T ( int n )
90
{
91
    if ( n < 10 ) return ( '0' + n ) ;
92
    if ( n < 36 ) return ( 'A' + ( n - 10 ) ) ;
93
    if ( n < 72 ) return ( 'a' + ( n - 36 ) ) ;
94
    return ( n + 128 ) ;
95
}
96
 
97
 
98
/*
99
    LOOK UP AN ERROR MAP
100
 
101
    This routine looks up the value of the property named s in the list
102
    of property mappings p.
103
*/
104
 
105
static MAP find_map
106
    PROTO_N ( ( p, s ) )
107
    PROTO_T ( LIST ( MAP ) p X string s )
108
{
109
    while ( !IS_NULL_list ( p ) ) {
110
	MAP m = DEREF_map ( HEAD_list ( p ) ) ;
111
	NAME n = DEREF_name ( map_key ( m ) ) ;
112
	if ( !IS_NULL_name ( n ) ) {
113
	    string t = DEREF_string ( name_id ( n ) ) ;
114
	    if ( streq ( s, t ) ) return ( m ) ;
115
	}
116
	p = TAIL_list ( p ) ;
117
    }
118
    return ( NULL_map ) ;
119
}
120
 
121
 
122
/*
123
    OUTPUT A MESSAGE LIST
124
 
125
    This routine prints the message list p to the file f.
126
*/
127
 
128
static void output_msg
129
    PROTO_N ( ( f, p ) )
130
    PROTO_T ( FILE *f X LIST ( MESSAGE ) p )
131
{
132
    int sp = 0 ;
133
    fputc_v ( '"', f ) ;
134
    while ( !IS_NULL_list ( p ) ) {
135
	MESSAGE m = DEREF_msg ( HEAD_list ( p ) ) ;
136
	if ( !IS_NULL_msg ( m ) ) {
137
	    if ( IS_msg_param ( m ) ) {
138
		PARAM a = DEREF_param ( msg_param_arg ( m ) ) ;
139
		int an = DEREF_int ( param_number ( a ) ) ;
140
		an = code_letter ( an ) ;
141
		if ( sp ) {
142
		    fputc_v ( ' ', f ) ;
143
		    sp = 0 ;
144
		}
145
		fprintf_v ( f, "%%%c", an ) ;
146
	    } else {
147
		char c ;
148
		string s = DEREF_string ( msg_text_arg ( m ) ) ;
149
		while ( c = *( s++ ), c != 0 ) {
150
		    if ( c == ' ' || c == '\t' || c == '\n' ) {
151
			sp = 1 ;
152
		    } else {
153
			if ( sp ) {
154
			    fputc_v ( ' ', f ) ;
155
			    sp = 0 ;
156
			}
157
			fputc_v ( c, f ) ;
158
		    }
159
		}
160
	    }
161
	}
162
	p = TAIL_list ( p ) ;
163
    }
164
    fputc_v ( '"', f ) ;
165
    return ;
166
}
167
 
168
 
169
/*
170
    OUTPUT ERROR DEFINITIONS 
171
 
172
    This routine outputs all the error definitions to the file f.
173
*/
174
 
175
static void output_defn
176
    PROTO_N ( ( f ) )
177
    PROTO_T ( FILE *f )
178
{
179
    /* Print error catalog */
180
    LIST ( NAME ) p ;
181
    char *d1 = db_name ;
182
    char *d2 = db_name_alt ;
183
    char *pre = rig_comp_output ;
184
    char *pre_comp = rig_from_comp ;
185
    LIST ( ENTRY ) q = all_entries ;
186
 
187
    /* Print each catalogue entry */
188
    fprintf_v ( f, "/* Error catalogue */\n\n" ) ;
189
    if ( streq ( d1, d2 ) ) {
190
	fprintf_v ( f, "%sCONST char *%sNAME = \"%s\" ;\n", pre, pre, d1 ) ;
191
    } else {
192
	fprintf_v ( f, "#ifndef %sALTERNATE\n", pre ) ;
193
	fprintf_v ( f, "%sCONST char *%sNAME = \"%s\" ;\n", pre, pre, d1 ) ;
194
	fprintf_v ( f, "#else\n" ) ;
195
	fprintf_v ( f, "%sCONST char *%sNAME = \"%s\" ;\n", pre, pre, d2 ) ;
196
	fprintf_v ( f, "#endif\n" ) ;
197
    }
198
    fprintf_v ( f, "\n%sDATA %sCATALOG [] = {\n", pre, pre ) ;
199
    while ( !IS_NULL_list ( q ) ) {
200
	unsigned u = 0 ;
201
	char *suff = ",\n" ;
202
	ENTRY e = DEREF_entry ( HEAD_list ( q ) ) ;
203
	string en = DEREF_string ( entry_name ( e ) ) ;
204
	USAGE eu = DEREF_name ( entry_use ( e ) ) ;
205
	USAGE ev = DEREF_name ( entry_alt_use ( e ) ) ;
206
	LIST ( MAP ) em = DEREF_list ( entry_maps ( e ) ) ;
207
	LIST ( PROPERTY ) eq = DEREF_list ( entry_props ( e ) ) ;
208
	LIST ( PARAM ) ep = DEREF_list ( entry_signature ( e ) ) ;
209
 
210
	/* Print error name */
211
	fprintf_v ( f, "    {\n\t\"%s\",\n", en ) ;
212
 
213
	/* Print error signature */
214
	if ( IS_NULL_list ( ep ) ) {
215
	    fprintf_v ( f, "\tNULL,\n" ) ;
216
	} else {
217
	    fprintf_v ( f, "\t\"" ) ;
218
	    while ( !IS_NULL_list ( ep ) ) {
219
		PARAM a = DEREF_param ( HEAD_list ( ep ) ) ;
220
		TYPE at = DEREF_name ( param_type ( a ) ) ;
221
		int an = DEREF_int ( name_number ( at ) ) ;
222
		an = code_letter ( an ) ;
223
		fputc_v ( an, f ) ;
224
		ep = TAIL_list ( ep ) ;
225
	    }
226
	    fprintf_v ( f, "\",\n" ) ;
227
	}
228
 
229
	/* Print error usage */
230
	if ( !EQ_name ( eu, ev ) ) {
231
	    fprintf_v ( f, "#ifndef %sALTERNATE\n", pre ) ;
232
	}
233
	if ( IS_NULL_name ( eu ) ) {
234
	    fprintf_v ( f, "\t0,\n" ) ;
235
	} else {
236
	    string un = DEREF_string ( name_id ( eu ) ) ;
237
	    fprintf_v ( f, "\t%s%s,\n", pre_comp, un ) ;
238
	}
239
	if ( !EQ_name ( eu, ev ) ) {
240
	    fprintf_v ( f, "#else\n" ) ;
241
	    if ( IS_NULL_name ( ev ) ) {
242
		fprintf_v ( f, "\t0,\n" ) ;
243
	    } else {
244
		string vn = DEREF_string ( name_id ( ev ) ) ;
245
		fprintf_v ( f, "\t%s%s,\n", pre_comp, vn ) ;
246
	    }
247
	    fprintf_v ( f, "#endif\n" ) ;
248
	}
249
 
250
	/* Print error properties */
251
	p = all_keys ;
252
	if ( IS_NULL_list ( p ) ) suff = "\n" ;
253
	while ( !IS_NULL_list ( eq ) ) {
254
	    PROPERTY nq = DEREF_name ( HEAD_list ( eq ) ) ;
255
	    unsigned n = ( unsigned ) DEREF_int ( name_number ( nq ) ) ;
256
	    u |= ( ( ( unsigned ) 1 ) << n ) ;
257
	    eq = TAIL_list ( eq ) ;
258
	}
259
	fprintf_v ( f, "\t%u%s", u, suff ) ;
260
 
261
	/* Print error keys */
262
	while ( !IS_NULL_list ( p ) ) {
263
	    NAME n = DEREF_name ( HEAD_list ( p ) ) ;
264
	    string pn = DEREF_string ( name_id ( n ) ) ;
265
	    MAP pm = find_map ( em, pn ) ;
266
	    p = TAIL_list ( p ) ;
267
	    if ( IS_NULL_list ( p ) ) suff = "\n" ;
268
	    if ( IS_NULL_map ( pm ) ) {
269
		fprintf_v ( f, "\tNULL%s", suff ) ;
270
	    } else {
271
		LIST ( MESSAGE ) m1 = DEREF_list ( map_msg ( pm ) ) ;
272
		LIST ( MESSAGE ) m2 = DEREF_list ( map_alt_msg ( pm ) ) ;
273
		if ( !EQ_list ( m1, m2 ) ) {
274
		    fprintf_v ( f, "#ifndef %sALTERNATE\n", pre ) ;
275
		}
276
		fprintf_v ( f, "\t" ) ;
277
		output_msg ( f, m1 ) ;
278
		fprintf_v ( f, "%s", suff ) ;
279
		if ( !EQ_list ( m1, m2 ) ) {
280
		    fprintf_v ( f, "#else\n\t" ) ;
281
		    output_msg ( f, m2 ) ;
282
		    fprintf_v ( f, "%s#endif\n", suff ) ;
283
		}
284
	    }
285
	}
286
	fprintf_v ( f, "    },\n" ) ;
287
	q = TAIL_list ( q ) ;
288
    }
289
 
290
    /* Print dummy end marker */
291
    fprintf_v ( f, "    {\n" ) ;
292
    fprintf_v ( f, "\tNULL,\n" ) ;
293
    fprintf_v ( f, "\tNULL,\n" ) ;
294
    fprintf_v ( f, "\t0,\n" ) ;
295
    fprintf_v ( f, "\t0" ) ;
296
    p = all_keys ;
297
    while ( !IS_NULL_list ( p ) ) {
298
	fprintf_v ( f, ",\n\tNULL" ) ;
299
	p = TAIL_list ( p ) ;
300
    }
301
    fprintf_v ( f, "\n    }\n" ) ;
302
    fprintf_v ( f, "} ;\n" ) ;
303
    return ;
304
}
305
 
306
 
307
/*
308
    OUTPUT ERROR DECLARATIONS 
309
 
310
    This routine outputs all the error declarations to the file f.
311
*/
312
 
313
static void output_decl
314
    PROTO_N ( ( f ) )
315
    PROTO_T ( FILE *f )
316
{
317
    int qn = 0 ;
318
    LIST ( ENTRY ) q = all_entries ;
319
 
320
    /* Print main type definition */
321
    char *pre = rig_comp_output ;
322
    char *pre_comp = rig_from_comp ;
323
    LIST ( NAME ) p = all_keys ;
324
    fprintf_v ( f, "#ifndef %sINCLUDED\n", pre ) ;
325
    fprintf_v ( f, "#define %sINCLUDED\n\n\n", pre ) ;
326
    fprintf_v ( f, "/* Error data structure */\n\n" ) ;
327
    fprintf_v ( f, "#ifndef %sCONST\n", pre ) ;
328
    fprintf_v ( f, "#define %sCONST\n", pre ) ;
329
    fprintf_v ( f, "#endif\n\n" ) ;
330
    if ( LENGTH_list ( all_props ) < 16 ) {
331
	fprintf_v ( f, "typedef unsigned %sPROPS ;\n\n", pre ) ;
332
    } else {
333
	fprintf_v ( f, "typedef unsigned long %sPROPS ;\n\n", pre ) ;
334
    }
335
    fprintf_v ( f, "typedef struct {\n" ) ;
336
    fprintf_v ( f, "    %sCONST char *name ;\n", pre ) ;
337
    fprintf_v ( f, "    %sCONST char *signature ;\n", pre ) ;
338
    fprintf_v ( f, "    int usage ;\n" ) ;
339
    fprintf_v ( f, "    %sPROPS props ;\n", pre ) ;
340
    while ( !IS_NULL_list ( p ) ) {
341
	NAME t = DEREF_name ( HEAD_list ( p ) ) ;
342
	string tn = DEREF_string ( name_id ( t ) ) ;
343
	fprintf_v ( f, "    %sCONST char *key_%s ;\n", pre, tn ) ;
344
	p = TAIL_list ( p ) ;
345
    }
346
    fprintf_v ( f, "} %sDATA ;\n\n", pre ) ;
347
    fprintf_v ( f, "extern %sDATA %sCATALOG [] ;\n", pre, pre ) ;
348
    fprintf_v ( f, "extern %sCONST char *%sNAME ;\n\n\n", pre, pre ) ;
349
 
350
    /* Print type keys */
351
    p = all_types ;
352
    fprintf_v ( f, "/* Error type keys */\n\n" ) ;
353
    while ( !IS_NULL_list ( p ) ) {
354
	NAME t = DEREF_name ( HEAD_list ( p ) ) ;
355
	string tn = DEREF_string ( name_id ( t ) ) ;
356
	int n = DEREF_int ( name_number ( t ) ) ;
357
	n = code_letter ( n ) ;
358
	fprintf_v ( f, "#define %sKEY_%s '%c'\n", pre, tn, n ) ;
359
	p = TAIL_list ( p ) ;
360
    }
361
    fprintf_v ( f, "\n\n" ) ;
362
 
363
    /* Print usage keys */
364
    p = all_usages ;
365
    fprintf_v ( f, "/* Error usage keys */\n\n" ) ;
366
    fprintf_v ( f, "#ifndef %sUSE\n", pre ) ;
367
    while ( !IS_NULL_list ( p ) ) {
368
	NAME t = DEREF_name ( HEAD_list ( p ) ) ;
369
	string tn = DEREF_string ( name_id ( t ) ) ;
370
	int n = DEREF_int ( name_number ( t ) ) ;
371
	fprintf_v ( f, "#define %s%s %d\n", pre_comp, tn, n ) ;
372
	p = TAIL_list ( p ) ;
373
    }
374
    fprintf_v ( f, "#endif\n\n\n" ) ;
375
 
376
    /* Print property keys */
377
    p = all_props ;
378
    fprintf_v ( f, "/* Error property keys */\n\n" ) ;
379
    fprintf_v ( f, "#ifndef %sPROP\n", pre ) ;
380
    while ( !IS_NULL_list ( p ) ) {
381
	NAME t = DEREF_name ( HEAD_list ( p ) ) ;
382
	string tn = DEREF_string ( name_id ( t ) ) ;
383
	unsigned n = ( unsigned ) DEREF_int ( name_number ( t ) ) ;
384
	unsigned u = ( ( ( unsigned ) 1 ) << n ) ;
385
	fprintf_v ( f, "#define %sPROP_%s ( ( %sPROPS ) 0x%x )\n",
386
		    pre, tn, pre, u ) ;
387
	p = TAIL_list ( p ) ;
388
    }
389
    fprintf_v ( f, "#endif\n\n\n" ) ;
390
 
391
    /* Print type checking macros */
392
    p = all_types ;
393
    fprintf_v ( f, "/* Error type checking */\n\n" ) ;
394
    fprintf_v ( f, "#if defined ( %sCHECK ) && defined ( __STDC__ )\n", pre ) ;
395
    while ( !IS_NULL_list ( p ) ) {
396
	NAME t = DEREF_name ( HEAD_list ( p ) ) ;
397
	string tn = DEREF_string ( name_id ( t ) ) ;
398
	int n = DEREF_int ( name_number ( t ) ) ;
399
	n = code_letter ( n ) ;
400
	fprintf_v ( f, "extern %s chk_%c ( %s ) ;\n", tn, n, tn ) ;
401
	p = TAIL_list ( p ) ;
402
    }
403
    fprintf_v ( f, "#else\n" ) ;
404
    p = all_types ;
405
    while ( !IS_NULL_list ( p ) ) {
406
	NAME t = DEREF_name ( HEAD_list ( p ) ) ;
407
	int n = DEREF_int ( name_number ( t ) ) ;
408
	n = code_letter ( n ) ;
409
	fprintf_v ( f, "#define chk_%c( A ) ( A )\n", n ) ;
410
	p = TAIL_list ( p ) ;
411
    }
412
    fprintf_v ( f, "#endif\n\n\n" ) ;
413
 
414
    /* Print error macros */
415
    fprintf_v ( f, "/* Error message macros */\n\n" ) ;
416
    fprintf_v ( f, "#ifdef %sGEN\n\n", pre ) ;
417
    while ( !IS_NULL_list ( q ) ) {
418
	ENTRY e = DEREF_entry ( HEAD_list ( q ) ) ;
419
	string en = DEREF_string ( entry_name ( e ) ) ;
420
	LIST ( PARAM ) ep = DEREF_list ( entry_signature ( e ) ) ;
421
	unsigned np = LENGTH_list ( ep ) ;
422
	fprintf_v ( f, "#define %s%s(", pre, en ) ;
423
	if ( !IS_NULL_list ( ep ) ) {
424
	    /* Print parameter list */
425
	    int arg = 0 ;
426
	    LIST ( PARAM ) eq = ep ;
427
	    while ( !IS_NULL_list ( eq ) ) {
428
		if ( arg ) fputc_v ( ',', f ) ;
429
		fprintf_v ( f, " %c", 'A' + arg ) ;
430
		eq = TAIL_list ( eq ) ;
431
		arg++ ;
432
	    }
433
	    fputc_v ( ' ', f ) ;
434
	}
435
	fprintf_v ( f, ")\\\n" ) ;
436
	fprintf_v ( f, "\t%sGEN ( %d", pre, qn ) ;
437
	if ( np ) {
438
	    /* Print error definition */
439
	    int arg = 0 ;
440
	    LIST ( PARAM ) eq = ep ;
441
	    while ( !IS_NULL_list ( eq ) ) {
442
		PARAM a = DEREF_param ( HEAD_list ( eq ) ) ;
443
		TYPE at = DEREF_name ( param_type ( a ) ) ;
444
		int an = DEREF_int ( name_number ( at ) ) ;
445
		an = code_letter ( an ) ;
446
		fprintf_v ( f, ", chk_%c ( %c )", an, 'A' + arg ) ;
447
		eq = TAIL_list ( eq ) ;
448
		arg++ ;
449
	    }
450
	}
451
	fprintf_v ( f, " )\n\n" ) ;
452
	q = TAIL_list ( q ) ;
453
	qn++ ;
454
    }
455
    fprintf_v ( f, "\n#endif\n#endif\n" ) ;
456
    return ;
457
}
458
 
459
 
460
/*
461
    OUTPUT ERROR NUMBERS 
462
 
463
    This routine outputs all the error numbers to the file f.
464
*/
465
 
466
static void output_number
467
    PROTO_N ( ( f ) )
468
    PROTO_T ( FILE *f )
469
{
470
    int qn = 0 ;
471
    LIST ( ENTRY ) q = all_entries ;
472
    char *pre = rig_comp_output ;
473
    char *pre_db = rig_from_db ;
474
    fprintf_v ( f, "#ifndef %sNO_INCLUDED\n", pre ) ;
475
    fprintf_v ( f, "#define %sNO_INCLUDED\n\n\n", pre ) ;
476
    fprintf_v ( f, "/* Error message macros */\n\n" ) ;
477
    while ( !IS_NULL_list ( q ) ) {
478
	ENTRY e = DEREF_entry ( HEAD_list ( q ) ) ;
479
	string en = DEREF_string ( entry_name ( e ) ) ;
480
	fprintf_v ( f, "#define %s%s %d\n", pre_db, en, qn ) ;
481
	q = TAIL_list ( q ) ;
482
	qn++ ;
483
    }
484
    fprintf_v ( f, "\n#endif\n" ) ;
485
    return ;
486
}
487
 
488
 
489
/*
490
    OUTPUT USAGES
491
 
492
    This routine output all the usages to the file f.
493
*/
494
 
495
static void output_usage
496
    PROTO_N ( ( f ) )
497
    PROTO_T ( FILE *f )
498
{
499
    char *pre = rig_comp_output ;
500
    char *pre_comp = rig_from_comp ;
501
    LIST ( USAGE ) p = all_usages ;
502
    LIST ( USAGE ) q = all_usages_aux ;
503
    LIST ( USAGE ) r = all_usages_alt ;
504
    while ( !IS_NULL_list ( p ) ) {
505
	USAGE u = DEREF_name ( HEAD_list ( p ) ) ;
506
	USAGE v = DEREF_name ( HEAD_list ( q ) ) ;
507
	USAGE w = DEREF_name ( HEAD_list ( r ) ) ;
508
	string s = DEREF_string ( name_id ( u ) ) ;
509
	string t = DEREF_string ( name_id ( v ) ) ;
510
	if ( !EQ_name ( v, w ) ) {
511
	    fprintf_v ( f, "#ifndef %sALTERNATE\n", pre ) ;
512
	}
513
	fprintf_v ( f, "{ \"%s\", %sVALUE_%s },\n", s, pre_comp, t ) ;
514
	if ( !EQ_name ( v, w ) ) {
515
	    t = DEREF_string ( name_id ( w ) ) ;
516
	    fprintf_v ( f, "#else\n" ) ;
517
	    fprintf_v ( f, "{ \"%s\", %sVALUE_%s },\n", s, pre_comp, t ) ;
518
	    fprintf_v ( f, "#endif\n" ) ;
519
	}
520
	r = TAIL_list ( r ) ;
521
	q = TAIL_list ( q ) ;
522
	p = TAIL_list ( p ) ;
523
    }
524
    return ;
525
}
526
 
527
 
528
/*
529
    OUTPUT ALL INFORMATION
530
 
531
    This routine outputs all the information gained into the file nm using
532
    the action indicated by act.  If nm is the null string then the standard
533
    output is used.
534
*/
535
 
536
void output_all
537
    PROTO_N ( ( nm, act ) )
538
    PROTO_T ( char *nm X int act )
539
{
540
    /* Open output file */
541
    FILE *f ;
542
    if ( nm == NULL || streq ( nm, "-" ) ) {
543
	f = stdout ;
544
	nm = NULL ;
545
    } else {
546
	f = fopen ( nm, "w" ) ;
547
	if ( f == NULL ) {
548
	    error ( ERROR_SERIOUS, "Can't open output file, '%s'", nm ) ;
549
	    return ;
550
	}
551
    }
552
 
553
    /* Print header comment */
554
    if ( first_comment ) fprintf_v ( f, "%s\n\n", first_comment ) ;
555
    fprintf_v ( f, "/* AUTOMATICALLY GENERATED BY %s FROM %s */\n\n\n",
556
		progname, db_name ) ;
557
 
558
    /* Print appropriate information */
559
    switch ( act ) {
560
	case 0 : output_decl ( f ) ; break ;
561
	case 1 : output_defn ( f ) ; break ;
562
	case 2 : output_number ( f ) ; break ;
563
	case 3 : output_usage ( f ) ; break ;
564
    }
565
 
566
    /* Close output file */
567
    if ( nm != NULL ) fclose_v ( f ) ;
568
    return ;
569
}