Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

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