Subversion Repositories tendra.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
#!/usr/local/bin/perl -w
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
###############################################################################
32
$[    = 1 ;
33
$prog = $0;
34
($tmp = rindex ($prog, "/")) && ($prog = substr ($prog, $tmp + 1));
35
###############################################################################
36
 
37
sub fatal {
38
    print STDERR ($prog, ": fatal: ", @_, "\n");
39
    exit (1);
40
}
41
 
42
sub ifatal {
43
    print STDERR ($prog, ": fatal: ", $lexer'file, ": ", $lexer'line_num, ": ",
44
		  @_, "\n");
45
    exit (1);
46
}
47
 
48
###############################################################################
49
### Lexical analyser:
50
 
51
$lexer'file		= undef;
52
$lexer'line_num		= undef;
53
$lexer'line		= undef;
54
 
55
###############################################################################
56
 
57
$TOK_EOF		= 0;
58
$TOK_OPEN_BRACE		= 1;
59
$TOK_CLOSE_BRACE	= 2;
60
$TOK_COMMA		= 3;
61
$TOK_SEMI_COLON		= 4;
62
$TOK_COLON		= 5;
63
$TOK_STRING		= 6;
64
$TOK_PROGRAM		= 7;
65
$TOK_SEVERITY		= 8;
66
$TOK_HEADER		= 9;
67
$TOK_C_HEADER		= 10;
68
$TOK_OPEN		= 11;
69
$TOK_CLOSE		= 12;
70
 
71
%error_severity		= (
72
	"info",		"ERROR_SEVERITY_INFORMATION",
73
	"information",	"ERROR_SEVERITY_INFORMATION",
74
	"warning",	"ERROR_SEVERITY_WARNING",
75
	"error",	"ERROR_SEVERITY_ERROR",
76
	"fatal",	"ERROR_SEVERITY_FATAL",
77
	"internal",	"ERROR_SEVERITY_INTERNAL",
78
);
79
 
80
###############################################################################
81
 
82
sub reset_lexer {
83
    local ($file) = @_;
84
 
85
    $lexer'file     = $file;
86
    $lexer'line_num = 0;
87
    $lexer'line     = "";
88
    open (INFILE, "<" . $file) ||
89
	&fatal ("cannot open input file '", $file, "'");
90
}
91
 
92
sub lexer'read_string {
93
    local ($string) = "";
94
 
95
    read_string: {
96
	(($lexer'line eq "") &&
97
	    (($lexer'line = <INFILE>), ($lexer'line_num ++)));
98
	(defined ($lexer'line)) ||
99
	    &ifatal ("unexpected end of file in string");
100
 
101
	if ($lexer'line =~ s/^([^"]*)"//) {
102
	    $string .= $1;
103
	} else {
104
	    $string    .= $lexer'line;
105
	    $lexer'line = "";
106
	    redo read_string;
107
	}
108
    }
109
    $string;
110
}
111
 
112
sub lexer'read_program {
113
    local ($program) = "";
114
    local ($index, $tmp);
115
 
116
    read_program: {
117
	(($lexer'line eq "") &&
118
	    (($lexer'line = <INFILE>), ($lexer'line_num ++)));
119
	(defined ($lexer'line)) ||
120
	    &ifatal ("unexpected end of file in program segment");
121
 
122
	if ($index = index ($lexer'line, "]\$")) {
123
	    $tmp        = substr ($lexer'line, 1, $index - 1);
124
	    $lexer'line = substr ($lexer'line, $index + 2);
125
	    $tmp        =~ s/^[ \t]*//;
126
	    $program   .= $tmp;
127
	} else {
128
	    $program   .= $lexer'line;
129
	    $lexer'line = "";
130
	    redo read_program;
131
	}
132
    }
133
    $program;
134
}
135
 
136
sub next_token {
137
    local ($token, $data);
138
 
139
    get_token: {
140
	(($lexer'line eq "") &&
141
	    (($lexer'line = <INFILE>), ($lexer'line_num ++)));
142
	(defined ($lexer'line)) || return ($TOK_EOF, 0);
143
	$lexer'line =~ s/^[ \t\n]*(#.*$)?\n?//;
144
	($lexer'line eq "") && redo get_token;
145
 
146
	if ($lexer'line =~ s/^{//) {
147
	    $token = $TOK_OPEN_BRACE;
148
	    $data  = 0;
149
	} elsif ($lexer'line =~ s/^}//) {
150
	    $token = $TOK_CLOSE_BRACE;
151
	    $data  = 0;
152
	} elsif ($lexer'line =~ s/^\(//) {
153
	    $token = $TOK_OPEN;
154
	    $data  = 0;
155
	} elsif ($lexer'line =~ s/^\)//) {
156
	    $token = $TOK_CLOSE;
157
	    $data  = 0;
158
	} elsif ($lexer'line =~ s/^,//) {
159
	    $token = $TOK_COMMA;
160
	    $data  = 0;
161
	} elsif ($lexer'line =~ s/^;//) {
162
	    $token = $TOK_SEMI_COLON;
163
	    $data  = 0;
164
	} elsif ($lexer'line =~ s/^://) {
165
	    $token = $TOK_COLON;
166
	    $data  = 0;
167
	} elsif ($lexer'line =~ s/^"//) {
168
	    $token = $TOK_STRING;
169
	    $data  = &lexer'read_string;
170
	} elsif ($lexer'line =~ s/^\$\[([ \t]*\n)?//) {
171
	    $token = $TOK_PROGRAM;
172
	    $data  = &lexer'read_program;
173
	} elsif ($lexer'line =~ s/^header\(c\)//) {
174
	    $token = $TOK_C_HEADER;
175
	    $data  = 0;
176
	} elsif ($lexer'line =~ s/^header\(h\)//) {
177
	    $token = $TOK_HEADER;
178
	    $data  = 0;
179
	} elsif ($lexer'line =~ s/^header//) {
180
	    $token = $TOK_HEADER;
181
	    $data  = 0;
182
	} elsif ($lexer'line =~ s/^[A-Za-z_]+//) {
183
	    $token = $TOK_SEVERITY;
184
	    $data  = $error_severity{$&};
185
	    defined ($data) ||
186
		&ifatal ("unknown error severity '", $&, "'");
187
	} elsif ($lexer'line =~ s/^.//) {
188
	    &ifatal ("illegal character '", $&, "'");
189
	}
190
    }
191
    ($token, $data);
192
}
193
 
194
###############################################################################
195
### Parser:
196
 
197
$error_header		= "";
198
$error_c_header		= "";
199
$error_tag_index	= 0;
200
$error_struct_num	= 0;
201
$error_tproc_num	= 0;
202
 
203
@error_tag_order	= ();
204
@error_order		= ();
205
@error_structures	= ();
206
@error_tag_procs	= ();
207
 
208
%error_tags		= ();
209
%error_tag_index	= ();
210
%error_severities	= ();
211
%error_munged_names	= ();
212
%error_messages		= ();
213
%error_client_data	= ();
214
%error_struct_match	= ();
215
%error_struct_name	= ();
216
%error_proc_decs	= ();
217
%error_proc_defs	= ();
218
%error_index		= ();
219
%error_tproc_match	= ();
220
%error_tproc_name	= ();
221
 
222
###############################################################################
223
 
224
sub munge_name {
225
    local ($name) = @_;
226
 
227
    $name =~ s/[^A-Za-z0-9_]/_/g;
228
    $name;
229
}
230
 
231
sub basename {
232
    local ($name) = @_;
233
    local ($tmp);
234
 
235
    ($tmp = rindex ($name, "/")) && ($name = substr ($name, $tmp + 1));
236
    $name;
237
}
238
 
239
sub find_tags {
240
    local ($mesg) = @_;
241
    local (%tag_names);
242
 
243
    while ($mesg =~ /\$\{([^\}\n]+)\}/) {
244
	$tag_names{$1} = 1;
245
	$mesg          = $';
246
    }
247
    keys (%tag_names);
248
}
249
 
250
sub indent_to {
251
    local ($prefix, $col) = @_;
252
    local ($length);
253
 
254
    if (($length = length ($prefix)) >= $col) {
255
	" ";
256
    } else {
257
	(" " x ($col - $length));
258
    }
259
}
260
 
261
###############################################################################
262
 
263
sub parse_param_list {
264
    local ($error, *param_types, *param_order) = @_;
265
    local ($token, $data, $name, $type);
266
 
267
    parse_param: {
268
	if ((($token, $data) = &next_token), ($token != $TOK_STRING)) {
269
	    &ifatal ("expected parameter name string");
270
	}
271
	$name = $data;
272
	if ((($token, $data) = &next_token), ($token != $TOK_COLON)) {
273
	    &ifatal ("expected ':'");
274
	}
275
	if ((($token, $data) = &next_token), ($token != $TOK_STRING)) {
276
	    &ifatal ("expected parameter type string");
277
	}
278
	$type = $data;
279
	if (defined ($param_types{$name})) {
280
	    &fatal ("parameter '", $name, "' already defined in error '",
281
		    $error, "'");
282
	} else {
283
	    $param_types{$name} = $type;
284
	    push (@param_order, $name);
285
	}
286
	if ((($token, $data) = &next_token), ($token == $TOK_COMMA)) {
287
	    redo parse_param;
288
	} elsif ($token != $TOK_CLOSE) {
289
	    &ifatal ("expected ')'");
290
	}
291
    }
292
}
293
 
294
sub parse_error_header {
295
    local ($severity, *tag_names, *param_types, *param_order) = @_;
296
    local ($token, $data, $name, $munged_name, $tmp);
297
 
298
    if ((($token, $data) = &next_token), ($token != $TOK_STRING)) {
299
	&ifatal ("expected error name string");
300
    }
301
    $name = $data;
302
    if (defined ($error_severities{$name})) {
303
	&ifatal ("error '", $name, "' is already defined");
304
    }
305
    $error_severities{$name} = $severity;
306
    if ((($token, $data) = &next_token), ($token == $TOK_COLON)) {
307
	if ((($token, $data) = &next_token), ($token != $TOK_STRING)) {
308
	    &ifatal ("expected error function name string");
309
	} elsif (($data =~ /[^A-Za-z_0-9]/) || ($data =~ /^[0-9]/)) {
310
	    &ifatal ("illegal error function name string '", $data, "'");
311
	}
312
	$munged_name = $data;
313
	($token, $data) = &next_token;
314
    } else {
315
	$munged_name = &munge_name ($name);
316
    }
317
    if (defined ($tmp = $error_munged_names{$munged_name})) {
318
	&ifatal ("error '", $name, "' clashes with error '", $tmp, "'");
319
    }
320
    $error_munged_names{$munged_name} = $name;
321
    if ($token == $TOK_OPEN) {
322
	&parse_param_list ($error, *param_types, *param_order);
323
	($token, $data) = &next_token;
324
    }
325
    if ($token != $TOK_OPEN_BRACE) {
326
	&ifatal ("expected '{'");
327
    }
328
    if ((($token, $data) = &next_token), ($token != $TOK_STRING)) {
329
	&ifatal ("expected error message text string");
330
    }
331
    $error_messages{$name} = $data;
332
    @tag_names = &find_tags ($data);
333
    ($name, $munged_name);
334
}
335
 
336
sub parse_error_tag {
337
    local ($name, *tag_types, *tag_names, *tag_mnames, *tag_code, *tag_init,
338
	   *tag_order, *param_types) = @_;
339
    local ($token, $data, $tag_name, $tag_type, $tag_code, $tag_init);
340
    local ($munged_name, $tmp);
341
 
342
    if ((($token, $data) = &next_token), ($token != $TOK_OPEN_BRACE)) {
343
	&ifatal ("expected '{'");
344
    }
345
    if ((($token, $data) = &next_token), ($token != $TOK_STRING)) {
346
	&ifatal ("expected tag name");
347
    }
348
    $tag_name    = $data;
349
    $munged_name = &munge_name ($tag_name);
350
    if (defined ($tag_types{$tag_name})) {
351
	&ifatal ("tag '", $tag_name, "' defined twice in error '", $name, "'");
352
    } elsif (defined ($tmp = $tag_mnames{$munged_name})) {
353
	&ifatal ("tag '", $tag_name, "' clashes with tag '", $tmp,
354
		 "' in error '", $name, "'");
355
    } elsif (defined ($tmp = $param_types{$munged_name})) {
356
	&ifatal ("tag '", $tag_name, "' clashes with parameter '",
357
		 $munged_name, "' in error '", $name, "'");
358
    }
359
    if ((($token, $data) = &next_token), ($token != $TOK_COLON)) {
360
	&ifatal ("expected ':'");
361
    }
362
    if ((($token, $data) = &next_token), ($token != $TOK_STRING)) {
363
	&ifatal ("expected tag type string");
364
    }
365
    $tag_type = $data;
366
    if ((($token, $data) = &next_token), ($token != $TOK_PROGRAM)) {
367
	&ifatal ("expected tag handling code");
368
    }
369
    $tag_code = $data;
370
    if ((($token, $data) = &next_token), ($token == $TOK_PROGRAM)) {
371
	$tag_init = $data;
372
	($token, $data) = &next_token;
373
    }
374
    if ($token != $TOK_CLOSE_BRACE) {
375
	&ifatal ("expected '}'");
376
    }
377
    if (!defined ($error_tags{$tag_name})) {
378
	$error_tags{$tag_name} = $error_tag_index ++;
379
	push (@error_tag_order, $tag_name);
380
    }
381
    $tag_types{$tag_name}     = $tag_type;
382
    $tag_mnames{$munged_name} = $tag_name;
383
    $tag_names{$tag_name}     = $munged_name;
384
    $tag_code{$tag_name}      = $tag_code;
385
    if (defined ($tag_init)) {
386
	$tag_init{$tag_name}  = $tag_init;
387
    }
388
    push (@tag_order, $tag_name);
389
}
390
 
391
sub build_structure {
392
    local ($error, *tag_types, *tag_names, *tag_order) = @_;
393
    local ($header, $def, $i, $tag, $type, $name, $indent, $tmp);
394
 
395
    if ($#tag_order) {
396
	$def = (" {\n");
397
	for ($i = 1; $i <= $#tag_order; $i ++) {
398
	    $tag    = $tag_order [$i];
399
	    $type   = $tag_types{$tag};
400
	    $name   = $tag_names{$tag};
401
	    $indent = &indent_to ("    " . $type, 30);
402
	    $def   .= ("    " . $type . $indent . $name . ";\n");
403
	}
404
	$def .= "};\n";
405
	if (defined ($tmp = $error_struct_match{$def})) {
406
	    $error_struct_name{$error} = $tmp;
407
	} else {
408
	    $header = sprintf ("struct ES_%05d", $error_struct_num ++);
409
	    $error_struct_match{$def}  = $header;
410
	    $error_struct_name{$error} = $header;
411
	    push (@error_structures, ($header . $def));
412
	}
413
    }
414
}
415
 
416
sub build_tag_proc {
417
    local ($error, *tag_types, *tag_names, *tag_order, *tag_code) = @_;
418
    local ($header, $def, $i, $tag, $code, $index, $name, $struct);
419
 
420
    if (defined ($struct = $error_struct_name{$error})) {
421
	$def    = ("{\n    " . $struct . " *closure = (" . $struct .
422
		   " *) gclosure;\n\n");
423
	for ($i = 1; $i <= $#tag_order; $i ++) {
424
	    $tag   = $tag_order [$i];
425
	    $name  = $tag_names{$tag};
426
	    $code  = $tag_code{$tag};
427
	    $index = $error_tags{$tag};
428
	    if ($i == 1) {
429
		$def .= ("    if (tag == ET [" . $index . "].tag) {\n");
430
	    } else {
431
		$def .= ("    } else if (tag == ET [" . $index . "].tag) {\n");
432
	    }
433
	    $def .= $code;
434
	}
435
	$def .= "    }\n}\n";
436
    } else {
437
	$def = ("{\n    UNUSED (ostream);\n" . "    UNUSED (tag);\n" .
438
		"    UNUSED (gclosure);\n}\n");
439
    }
440
    if (defined ($tmp = $error_tproc_match{$def})) {
441
	$error_tproc_name{$error} = $tmp;
442
    } else {
443
	$name   = sprintf ("ET_%05d", $error_tproc_num ++);
444
	$header = ("static void\n" . $name .
445
		   " PROTO_N ((ostream, tag, gclosure))\n" .
446
		   &indent_to ("", 9) . "PROTO_T (OStreamP ostream X\n" .
447
		   &indent_to ("", 18) . "ETagP    tag X\n" .
448
		   &indent_to ("", 18) . "GenericP gclosure)\n");
449
	$error_tproc_match{$def}  = $name;
450
	$error_tproc_name{$error} = $name;
451
	push (@error_tag_procs, ($header . $def));
452
    }
453
}
454
 
455
sub build_proc_dec {
456
    local ($error, $munged_name, *tag_types, *tag_names, *tag_init, *tag_order,
457
	   *param_types, *param_order) = @_;
458
    local ($dec, $i, $tag, $type, $sep, $args, $param);
459
 
460
    $sep  = undef;
461
    $dec  = ("extern void E_" . $munged_name . "\n\tPROTO_S ((");
462
    $args = 0;
463
    for ($i = 1; $i <= $#param_order; $i ++) {
464
	$param = $param_order [$i];
465
	$type  = $param_types{$param};
466
	if (defined ($sep)) {
467
	    $dec .= $sep;
468
	}
469
	$dec .= $type;
470
	$sep  = ", ";
471
	$args ++;
472
    }
473
    for ($i = 1; $i <= $#tag_order; $i ++) {
474
	$tag  = $tag_order [$i];
475
	$type = $tag_types{$tag};
476
	if (!defined ($tag_init{$tag})) {
477
	    if (defined ($sep)) {
478
		$dec .= $sep;
479
	    }
480
	    $dec .= $type;
481
	    $sep  = ", ";
482
	    $args ++;
483
	}
484
    }
485
    if ($args == 0) {
486
	$dec .= "void";
487
    }
488
    $error_proc_decs{$error} = ($dec . "));\n");
489
}
490
 
491
sub build_proc_def {
492
    local ($error, $munged_name, *tag_types, *tag_names, *tag_init,
493
	   *tag_order, *param_types, *param_order) = @_;
494
    local ($def, $tmp_def, $i, $tag, $type, $name, $col, $sep, $init, $args);
495
    local ($param, $struct, $closure);
496
 
497
    $sep     = undef;
498
    $def     = ("void\nE_" . $munged_name);
499
    $tmp_def = " PROTO_N ((";
500
    $col     = (length ($munged_name) + 3);
501
    $args    = 0;
502
    $sep     = undef;
503
    for ($i = 1; $i <= $#param_order; $i ++) {
504
	$param = $param_order [$i];
505
	if (defined ($sep)) {
506
	    $tmp_def .= $sep;
507
	}
508
	$tmp_def .= $param;
509
	$sep      = ", ";
510
	$args ++;
511
    }
512
    for ($i = 1; $i <= $#tag_order; $i ++) {
513
	$tag  = $tag_order [$i];
514
	$name = $tag_names{$tag};
515
	if (!defined ($tag_init{$tag})) {
516
	    if (defined ($sep)) {
517
		$tmp_def .= $sep;
518
	    }
519
	    $tmp_def .= $name;
520
	    $sep      = ", ";
521
	    $args ++;
522
	}
523
    }
524
    $tmp_def .= ("))\n" . &indent_to ("", $col) . "PROTO_T (");
525
    $col     += 9;
526
    if ($args == 0) {
527
	$def .= " PROTO_Z ()\n";
528
    } else {
529
	$def .= $tmp_def;
530
	$sep  = undef;
531
	for ($i = 1; $i <= $#param_order; $i ++) {
532
	    $param = $param_order [$i];
533
	    $type  = $param_types{$param};
534
	    if (defined ($sep)) {
535
		$def .= $sep;
536
	    }
537
	    $def .= ($type . " " . $param);
538
	    $sep  = (" X\n" . &indent_to ("", $col));
539
	}
540
	for ($i = 1; $i <= $#tag_order; $i ++) {
541
	    $tag  = $tag_order [$i];
542
	    $name = $tag_names{$tag};
543
	    $type = $tag_types{$tag};
544
	    if (!defined ($tag_init{$tag})) {
545
		if (defined ($sep)) {
546
		    $def .= $sep;
547
		}
548
		$def .= ($type . " " . $name);
549
		$sep  = (" X\n" . &indent_to ("", $col));
550
	    }
551
	}
552
	$def .= ")\n";
553
    }
554
    $def .= "{\n";
555
    if (defined ($struct = $error_struct_name{$error})) {
556
	$def .= ("    " . $struct . " closure; \n\n");
557
	for ($i = 1; $i <= $#tag_order; $i ++) {
558
	    $tag  = $tag_order [$i];
559
	    $name = $tag_names{$tag};
560
	    if (defined ($init = $tag_init{$tag})) {
561
		$def .= $init;
562
	    } else {
563
		$def .= ("    closure." . $name . " = " . $name . ";\n");
564
	    }
565
	}
566
	$closure = "(GenericP) &closure";
567
    } else {
568
	$closure = "NIL (GenericP)";
569
    }
570
    $def .= ("    error_call_init_proc ();\n    error_report (EE [" .
571
	     $error_index{$error} . "].error, " . $error_tproc_name{$error} .
572
	     ", " . $closure . ");\n");
573
    if (($error_severities{$error} eq "ERROR_SEVERITY_FATAL") ||
574
	($error_severities{$error} eq "ERROR_SEVERITY_INTERNAL")) {
575
	$def .= "    UNREACHED;\n";
576
    }
577
    $error_proc_defs{$error} = ($def . "}\n");
578
}
579
 
580
sub parse_error {
581
    local ($severity) = @_;
582
    local ($token, $data, $name, $munged_name);
583
    local (%tag_types, %tag_names, %tag_mnames, %tag_code, %tag_init,
584
	   @tag_order, @used_tags, $tag, %param_types, @param_order);
585
 
586
    ($name, $munged_name) = &parse_error_header ($severity, *used_tags,
587
						 *param_types, *param_order);
588
    while ((($token, $data) = &next_token), ($token == $TOK_COMMA)) {
589
	&parse_error_tag ($name, *tag_types, *tag_names, *tag_mnames,
590
			  *tag_code, *tag_init, *tag_order, *param_types);
591
    }
592
    if ($token == $TOK_PROGRAM) {
593
	$error_client_data{$name} = $data;
594
	($token, $data) = &next_token;
595
    } else {
596
	$error_client_data{$name} = "NIL (GenericP)";
597
    }
598
    if ($token != $TOK_CLOSE_BRACE) {
599
	&ifatal ("expected '}'");
600
    }
601
    foreach $tag (@used_tags) {
602
	if (!defined ($tag_types{$tag})) {
603
	    &fatal ("error '", $name, "' uses undefined tag '", $tag, "'");
604
	}
605
    }
606
    $error_index{$name} = $#error_order;
607
    &build_structure ($name, *tag_types, *tag_names, *tag_order);
608
    &build_tag_proc  ($name, *tag_types, *tag_names, *tag_order, *tag_code);
609
    &build_proc_dec  ($name, $munged_name, *tag_types, *tag_names, *tag_init,
610
		      *tag_order, *param_types, *param_order);
611
    &build_proc_def  ($name, $munged_name, *tag_types, *tag_names, *tag_init,
612
		      *tag_order, *param_types, *param_order);
613
    push (@error_order, $name);
614
}
615
 
616
sub parse_header {
617
    local ($token, $data);
618
 
619
    if ((($token, $data) = &next_token), ($token != $TOK_PROGRAM)) {
620
	&ifatal ("expected program section");
621
    }
622
    $error_header .= ("/* Header from input file '" . $infile . "' */\n" .
623
		      $data . "\n");
624
}
625
 
626
sub parse_c_header {
627
    local ($token, $data);
628
 
629
    if ((($token, $data) = &next_token), ($token != $TOK_PROGRAM)) {
630
	&ifatal ("expected program section");
631
    }
632
    $error_c_header .= ("/* Header from input file '" . $infile . "' */\n" .
633
			$data . "\n");
634
}
635
 
636
sub parse_file {
637
    local ($file) = @_;
638
 
639
    &reset_lexer ($file);
640
    while ((($token, $data) = &next_token), ($token != $TOK_EOF)) {
641
	if ($token == $TOK_HEADER) {
642
	    &parse_header;
643
	} elsif ($token == $TOK_C_HEADER) {
644
	    &parse_c_header;
645
	} elsif ($token == $TOK_SEVERITY) {
646
	    &parse_error ($data);
647
	} else {
648
	    &ifatal ("expected header or severity level");
649
	}
650
	if ((($token, $data) = &next_token), ($token != $TOK_SEMI_COLON)) {
651
	    &ifatal ("expected ';'");
652
	}
653
    }
654
    close (INFILE);
655
}
656
 
657
###############################################################################
658
### Output:
659
 
660
sub output_c_file {
661
    local ($i, $tag, $error, $name);
662
 
663
    print OUTFILE ("/* Automatically generated by '", $prog, "' */\n\n");
664
    print OUTFILE ("#include \"", &basename ($outfile), ".h\"\n");
665
    print OUTFILE ("#include \"error.h\"\n");
666
    print OUTFILE ("#include \"ostream.h\"\n\n");
667
    print OUTFILE ($error_c_header, "\n");
668
 
669
    print OUTFILE ("static ETagDataT ET [] = {\n");
670
    for ($i = 1; $i <= $#error_tag_order; $i ++) {
671
	$tag = $error_tag_order [$i];
672
	print OUTFILE ("    UB \"", $tag, "\" UE,\n");
673
    }
674
    print OUTFILE ("    ERROR_END_TAG_LIST\n");
675
    print OUTFILE ("};\n\n");
676
 
677
    print OUTFILE ("static ErrorDataT EE [] = {\n");
678
    for ($i = 1; $i <= $#error_order; $i ++) {
679
	$error = $error_order [$i];
680
	print OUTFILE ("    UB {\n\t\"", $error, "\",\n\t",
681
		       $error_severities{$error}, ",\n\t\"",
682
		       $error_messages{$error}, "\",\n\t",
683
		       $error_client_data{$error}, "\n    } UE,\n");
684
    }
685
    print OUTFILE ("    ERROR_END_ERROR_LIST\n");
686
    print OUTFILE ("};\n\n");
687
 
688
    for ($i = 1; $i <= $#error_structures; $i ++) {
689
	print OUTFILE ($error_structures [$i]);
690
    }
691
    print OUTFILE ("\n");
692
 
693
    for ($i = 1; $i <= $#error_tag_procs; $i ++) {
694
	print OUTFILE ($error_tag_procs [$i]);
695
    }
696
    print OUTFILE ("\n");
697
 
698
    for ($i = 1; $i <= $#error_order; $i ++) {
699
	$error = $error_order [$i];
700
	print OUTFILE ($error_proc_defs{$error});
701
    }
702
    $name = &munge_name (&basename ($outfile));
703
    print OUTFILE ("\nvoid\n", $name, "_init_errors PROTO_Z ()\n",
704
		   "{\n    error_intern_tags (ET);\n",
705
		   "    error_intern_errors (EE);\n}\n");
706
}
707
 
708
sub output_h_file {
709
    local ($i);
710
 
711
    print OUTFILE ("/* Automatically generated by '", $prog, "' */\n\n");
712
    print OUTFILE ("#include \"os-interface.h\"\n\n");
713
    print OUTFILE ($error_header, "\n");
714
 
715
    print OUTFILE ("/* Error function declarations */\n\n");
716
    for ($i = 1; $i <= $#error_order; $i ++) {
717
	$error = $error_order [$i];
718
	print OUTFILE ($error_proc_decs{$error});
719
    }
720
    print OUTFILE ("\nextern void ", &munge_name (&basename ($outfile)),
721
		   "_init_errors\n\tPROTO_S ((void));\n");
722
}
723
 
724
###############################################################################
725
 
726
$outfile	= "error-mesgs";
727
 
728
###############################################################################
729
 
730
arg:
731
while (defined ($arg = shift (@ARGV))) {
732
    if ($arg =~ /^-o/) {
733
	(defined ($outfile = shift (@ARGV))) ||
734
	    &fatal ("no output file name specified after '", $arg, "' option");
735
    } elsif ($arg =~ /^-/) {
736
	&fatal ("unknown option '", $arg, "'");
737
    } else {
738
	unshift (@ARGV, $arg);
739
	last arg;
740
    }
741
}
742
 
743
while (defined ($infile = shift (@ARGV))) {
744
    &parse_file ($infile);
745
}
746
 
747
open (OUTFILE, ">" . $outfile . ".c") ||
748
    &fatal ("cannot open output file '", $outfile, ".c'");
749
&output_c_file;
750
close (OUTFILE);
751
open (OUTFILE, ">" . $outfile . ".h") ||
752
    &fatal ("cannot open output file '", $outfile, ".h'");
753
&output_h_file;
754
close (OUTFILE);
755
exit (0);