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
/*** c-output.c --- Output routines.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 *** Commentary:
36
 *
37
 * This file implements the SID output routines.
38
 *
39
 *** Change Log:
40
 * $Log: c-output.c,v $
41
 * Revision 1.1.1.1  1998/01/17  15:57:43  release
42
 * First version to be checked into rolling release.
43
 *
44
 * Revision 1.6  1996/03/01  09:53:17  smf
45
 * c-code.c, c-out-info.c, c-out-info.h, c-output.c:
46
 * 	- improved unreachable code analysis;
47
 * 	- improved some output formatting;
48
 * 	- added support for comment or macro to mark unreachable code.
49
 *
50
 * Revision 1.5  1996/02/28  15:52:05  smf
51
 * Fixed a bug that occured when a rule with a single alternative and an
52
 * exception handler was inlined into another rule.  The bug caused the inner
53
 * rule's exception handler to handle any exceptions that occur in the enclosing
54
 * rule.
55
 *
56
 * Revision 1.4  1994/12/23  09:44:47  smf
57
 * Fixing "CR94_227.sid-exception-optimisation-bug" - corrected exception
58
 * terminal checking.
59
 *
60
 * Revision 1.3  1994/12/15  09:56:43  smf
61
 * Brought into line with OSSG C Coding Standards Document, as per
62
 * "CR94_178.sid+tld-update".
63
 *
64
 * Revision 1.2  1994/11/11  11:42:32  smf
65
 * Fixed the number of the error terminal, as it was one higher than necessary.
66
 *
67
 * Revision 1.1.1.1  1994/07/25  16:04:20  smf
68
 * Initial import of SID 1.8 non shared files.
69
 *
70
**/
71
 
72
/****************************************************************************/
73
 
74
#include "c-output.h"
75
#include "action.h"
76
#include "basic.h"
77
#include "c-code.h"
78
#include "c-out-key.h"
79
#include "c-out-nl.h"
80
#include "c-out-types.h"
81
#include "dstring.h"
82
#include "gen-errors.h"
83
#include "output.h"
84
#include "name.h"
85
#include "rstack.h"
86
#include "rule.h"
87
#include "type.h"
88
 
89
/*--------------------------------------------------------------------------*/
90
 
91
typedef struct COutClosureT {
92
    COutputInfoP		info;
93
    TableP			table;
94
    EntryP			predicate_id;
95
    EntryP			predicate_type;
96
    unsigned			error_terminal;
97
} COutClosureT, *COutClosureP;
98
 
99
/*--------------------------------------------------------------------------*/
100
 
101
static unsigned out_current_label;
102
 
103
/*--------------------------------------------------------------------------*/
104
 
105
static void
106
c_output_indent PROTO_N ((info, indent))
107
		PROTO_T (COutputInfoP info X
108
			 unsigned     indent)
109
{
110
    output_indent (c_out_info_info (info), indent);
111
}
112
#ifdef FS_FAST
113
#define c_output_indent(info, indent) \
114
	output_indent (c_out_info_info (info), indent)
115
#endif /* defined (FS_FAST) */
116
 
117
static void
118
c_output_identification PROTO_N ((info))
119
			PROTO_T (COutputInfoP info)
120
{
121
    OStreamP ostream = c_out_info_ostream (info);
122
 
123
    write_cstring (ostream, "/*");
124
    write_newline (ostream);
125
    write_cstring (ostream, " * Automatically generated from the files:");
126
    write_newline (ostream);
127
    write_cstring (ostream, " *\t");
128
    write_cstring (ostream, c_out_info_source_name (info));
129
    write_newline (ostream);
130
    write_cstring (ostream, " * and");
131
    write_newline (ostream);
132
    write_cstring (ostream, " *\t");
133
    write_cstring (ostream, c_out_info_c_source_name (info));
134
    write_newline (ostream);
135
    write_cstring (ostream, " * by:");
136
    write_newline (ostream);
137
    write_cstring (ostream, " *\t");
138
    write_cstring (ostream, c_out_info_program_name (info));
139
    write_newline (ostream);
140
    write_cstring (ostream, " */");
141
    write_newline (ostream);
142
    write_newline (ostream);
143
}
144
 
145
static void
146
c_output_declaration_1 PROTO_N ((info, rule))
147
		       PROTO_T (COutputInfoP info X
148
				RuleP        rule)
149
{
150
    OStreamP ostream = c_out_info_ostream (info);
151
    EntryP   entry   = rule_entry (rule);
152
 
153
    if (rule_is_required (rule)) {
154
	write_cstring (ostream, "extern void ");
155
    } else if (rule_needs_function (rule)) {
156
	if (c_out_info_get_split (info) != 0) {
157
	    write_cstring (ostream, "extern void ");
158
	} else {
159
	    write_cstring (ostream, "static void ");
160
	}
161
    } else {
162
	return;
163
    }
164
    c_output_mapped_key (info, entry);
165
    write_char (ostream, ' ');
166
    c_output_type_decl (info, rule_param (rule), rule_result (rule));
167
    write_char (ostream, ';');
168
    write_newline (ostream);
169
}
170
 
171
static void
172
c_output_declaration PROTO_N ((entry, gclosure))
173
		     PROTO_T (EntryP   entry X
174
			      GenericP gclosure)
175
{
176
    if (entry_is_rule (entry)) {
177
	RuleP        rule = entry_get_rule (entry);
178
	COutputInfoP info = (COutputInfoP) gclosure;
179
 
180
	c_output_declaration_1 (info, rule);
181
    }
182
}
183
 
184
static void
185
c_output_ext_declaration_1 PROTO_N ((info, rule))
186
			   PROTO_T (COutputInfoP info X
187
				    RuleP        rule)
188
{
189
    OStreamP ostream = c_out_info_ostream (info);
190
    EntryP   entry   = rule_entry (rule);
191
 
192
    if (rule_is_required (rule)) {
193
	write_cstring (ostream, "extern void ");
194
    } else {
195
	return;
196
    }
197
    c_output_mapped_key (info, entry);
198
    write_char (ostream, ' ');
199
    c_output_type_decl (info, rule_param (rule), rule_result (rule));
200
    write_char (ostream, ';');
201
    write_newline (ostream);
202
}
203
 
204
static void
205
c_output_ext_declaration PROTO_N ((entry, gclosure))
206
			 PROTO_T (EntryP   entry X
207
				  GenericP gclosure)
208
{
209
    if (entry_is_rule (entry)) {
210
	RuleP        rule = entry_get_rule (entry);
211
	COutputInfoP info = (COutputInfoP) gclosure;
212
 
213
	c_output_ext_declaration_1 (info, rule);
214
    }
215
}
216
 
217
static void
218
c_output_terminal_1 PROTO_N ((info, entry))
219
		    PROTO_T (COutputInfoP info X
220
			     EntryP       entry)
221
{
222
    OStreamP ostream = c_out_info_ostream (info);
223
    BasicP   basic   = entry_get_basic (entry);
224
 
225
    write_cstring (ostream, "#define ");
226
    c_output_mapped_key (info, entry);
227
    write_cstring (ostream, " (");
228
    write_unsigned (ostream, basic_terminal (basic));
229
    write_char (ostream, ')');
230
    write_newline (ostream);
231
}
232
 
233
static void
234
c_output_terminal PROTO_N ((entry, gclosure))
235
		  PROTO_T (EntryP   entry X
236
			   GenericP gclosure)
237
{
238
    if (entry_is_basic (entry)) {
239
	COutputInfoP info = (COutputInfoP) gclosure;
240
 
241
	c_output_terminal_1 (info, entry);
242
    }
243
}
244
 
245
static void
246
c_output_static_vars_1 PROTO_N ((entry, gclosure))
247
		       PROTO_T (EntryP   entry X
248
				GenericP gclosure)
249
{
250
    if (entry_is_rule (entry)) {
251
	COutputInfoP info = (COutputInfoP) gclosure;
252
	RuleP        rule = entry_get_rule (entry);
253
 
254
	c_output_non_locals (info, rule_non_locals (rule));
255
    }
256
}
257
 
258
static void
259
c_output_static_vars_2 PROTO_N ((entry, gclosure))
260
		       PROTO_T (EntryP   entry X
261
				GenericP gclosure)
262
{
263
    if (entry_is_rule (entry)) {
264
	COutputInfoP info = (COutputInfoP) gclosure;
265
	RuleP        rule = entry_get_rule (entry);
266
 
267
	c_output_declare_non_locals (info, rule_non_locals (rule));
268
    }
269
}
270
 
271
static void
272
c_output_static_vars PROTO_N ((info, grammar, def))
273
		     PROTO_T (COutputInfoP info X
274
			      GrammarP     grammar X
275
			      BoolT        def)
276
{
277
    OStreamP ostream        = c_out_info_ostream (info);
278
    TableP   table          = grammar_table (grammar);
279
    EntryP   predicate_type = grammar_get_predicate_type (grammar);
280
 
281
    if (def) {
282
	write_cstring (ostream, "/* BEGINNING OF STATIC VARIABLES */");
283
	write_newline (ostream);
284
	write_newline (ostream);
285
    }
286
    if (predicate_type) {
287
	if (def) {
288
	    if (c_out_info_get_split (info) == 0) {
289
		write_cstring (ostream, "static ");
290
	    }
291
	} else {
292
	    write_cstring (ostream, "extern ");
293
	}
294
	c_output_mapped_key (info, predicate_type);
295
	write_char (ostream, ' ');
296
	c_output_key (info, entry_key (grammar_get_predicate_id (grammar)),
297
		      c_out_info_in_prefix (info));
298
	write_char (ostream, ';');
299
	write_newline (ostream);
300
    }
301
    if (def) {
302
	table_iter (table, c_output_static_vars_1, (GenericP) info);
303
	write_newline (ostream);
304
    } else {
305
	table_iter (table, c_output_static_vars_2, (GenericP) info);
306
    }
307
}
308
 
309
static void
310
c_out_reset_labels PROTO_Z ()
311
{
312
    out_current_label = 0;
313
}
314
 
315
static void
316
c_output_label PROTO_N ((info, label, indent))
317
	       PROTO_T (COutputInfoP info X
318
			unsigned     label X
319
			unsigned     indent)
320
{
321
    OStreamP ostream = c_out_info_ostream (info);
322
    NStringP prefix  = c_out_info_label_prefix (info);
323
 
324
    c_output_indent (info, indent - C_INDENT_FOR_LABEL);
325
    write_nstring (ostream, prefix);
326
    write_unsigned (ostream, label);
327
    write_cstring (ostream, ":;");
328
    write_newline (ostream);
329
}
330
 
331
static void
332
c_output_jump PROTO_N ((info, label, indent))
333
	      PROTO_T (COutputInfoP info X
334
		       unsigned     label X
335
		       unsigned     indent)
336
{
337
    OStreamP ostream = c_out_info_ostream (info);
338
    NStringP prefix  = c_out_info_label_prefix (info);
339
 
340
    c_output_indent (info, indent);
341
    write_cstring (ostream, "goto ");
342
    write_nstring (ostream, prefix);
343
    write_unsigned (ostream, label);
344
    write_char (ostream, ';');
345
    write_newline (ostream);
346
}
347
 
348
static void
349
c_output_key_label PROTO_N ((info, key, label, indent))
350
		   PROTO_T (COutputInfoP info X
351
			    KeyP         key X
352
			    unsigned     label X
353
			    unsigned     indent)
354
{
355
    OStreamP ostream = c_out_info_ostream (info);
356
 
357
    c_output_indent (info, indent - C_INDENT_FOR_LABEL);
358
    c_output_label_key (info, key, label);
359
    write_cstring (ostream, ":;");
360
    write_newline (ostream);
361
}
362
 
363
static void
364
c_output_key_jump PROTO_N ((info, key, label, indent))
365
		  PROTO_T (COutputInfoP info X
366
			   KeyP         key X
367
			   unsigned     label X
368
			   unsigned     indent)
369
{
370
    OStreamP ostream = c_out_info_ostream (info);
371
 
372
    c_output_indent (info, indent);
373
    write_cstring (ostream, "goto ");
374
    c_output_label_key (info, key, label);
375
    write_char (ostream, ';');
376
    write_newline (ostream);
377
}
378
 
379
static void
380
c_output_switch PROTO_N ((info, indent))
381
		PROTO_T (COutputInfoP info X
382
			 unsigned     indent)
383
{
384
    OStreamP ostream = c_out_info_ostream (info);
385
 
386
    c_output_indent (info, indent);
387
    write_cstring (ostream, "switch (CURRENT_TERMINAL) {");
388
    write_newline (ostream);
389
}
390
 
391
static void
392
c_output_case PROTO_N ((info, terminal, indent))
393
	      PROTO_T (COutputInfoP info X
394
		       unsigned     terminal X
395
		       unsigned     indent)
396
{
397
    OStreamP ostream = c_out_info_ostream (info);
398
 
399
    c_output_indent (info, indent + C_INDENT_STEP - C_INDENT_FOR_CASE);
400
    write_cstring (ostream, "case ");
401
    write_unsigned (ostream, terminal);
402
    write_char (ostream, ':');
403
    write_newline (ostream);
404
}
405
 
406
static void
407
c_output_default PROTO_N ((info, indent))
408
		 PROTO_T (COutputInfoP info X
409
			  unsigned     indent)
410
{
411
    OStreamP ostream = c_out_info_ostream (info);
412
 
413
    c_output_indent (info, indent + C_INDENT_STEP - C_INDENT_FOR_CASE);
414
    write_cstring (ostream, "default:");
415
    write_newline (ostream);
416
}
417
 
418
static void
419
c_output_bitvec_cases PROTO_N ((info, bitvec, indent))
420
		      PROTO_T (COutputInfoP info X
421
			       BitVecP      bitvec X
422
			       unsigned     indent)
423
{
424
    OStreamP ostream  = c_out_info_ostream (info);
425
    unsigned terminal = bitvec_first_bit (bitvec);
426
    unsigned count    = 0;
427
 
428
    do {
429
	if (count ++ == 0) {
430
	    c_output_indent (info, indent + C_INDENT_STEP - C_INDENT_FOR_CASE);
431
	} else {
432
	    write_char (ostream, ' ');
433
	}
434
	write_cstring (ostream, "case ");
435
	write_unsigned (ostream, terminal);
436
	write_char (ostream, ':');
437
	if (count == 5) {
438
	    write_newline (ostream);
439
	    count = 0;
440
	}
441
    } while (bitvec_next_bit (bitvec, &terminal));
442
    if (count != 0) {
443
	write_newline (ostream);
444
    }
445
}
446
 
447
static void
448
c_output_break PROTO_N ((info, indent))
449
	       PROTO_T (COutputInfoP info X
450
			unsigned     indent)
451
{
452
    OStreamP ostream = c_out_info_ostream (info);
453
 
454
    c_output_indent (info, indent);
455
    write_cstring (ostream, "break;");
456
    write_newline (ostream);
457
}
458
 
459
static void
460
c_output_return PROTO_N ((info, indent))
461
		PROTO_T (COutputInfoP info X
462
			 unsigned     indent)
463
{
464
    OStreamP ostream = c_out_info_ostream (info);
465
 
466
    c_output_indent (info, indent);
467
    write_cstring (ostream, "return;");
468
    write_newline (ostream);
469
}
470
 
471
static void
472
c_output_error_if PROTO_N ((info, error_terminal, indent))
473
		  PROTO_T (COutputInfoP info X
474
			   unsigned     error_terminal X
475
			   unsigned     indent)
476
{
477
    OStreamP ostream = c_out_info_ostream (info);
478
 
479
    c_output_indent (info, indent);
480
    write_cstring (ostream, "if ((CURRENT_TERMINAL) == ");
481
    write_unsigned (ostream, error_terminal);
482
    write_cstring (ostream, ") {");
483
    write_newline (ostream);
484
}
485
 
486
static void
487
c_output_else PROTO_N ((info, indent))
488
	      PROTO_T (COutputInfoP info X
489
		       unsigned     indent)
490
{
491
    OStreamP ostream = c_out_info_ostream (info);
492
 
493
    c_output_indent (info, indent);
494
    write_cstring (ostream, "} else {");
495
    write_newline (ostream);
496
}
497
 
498
static void
499
c_output_restore PROTO_N ((info, handler_rule, outer_level, indent))
500
		 PROTO_T (COutputInfoP info X
501
			  RuleP        handler_rule X
502
			  BoolT        outer_level X
503
			  unsigned     indent)
504
{
505
    OStreamP ostream = c_out_info_ostream (info);
506
 
507
    if (outer_level) {
508
	c_output_return (info, indent);
509
    } else {
510
	c_output_indent (info, indent);
511
	write_cstring (ostream, "RESTORE_LEXER;");
512
	write_newline (ostream);
513
	c_output_jump (info, rule_get_handler_label (handler_rule), indent);
514
    }
515
}
516
 
517
static void
518
c_output_check PROTO_N ((info, handler_rule, outer_level, error_terminal,
519
			 indent))
520
	       PROTO_T (COutputInfoP info X
521
			RuleP        handler_rule X
522
			BoolT        outer_level X
523
			unsigned     error_terminal X
524
			unsigned     indent)
525
{
526
    c_output_error_if (info, error_terminal, indent);
527
    c_output_restore (info, handler_rule, outer_level, indent + C_INDENT_STEP);
528
    c_output_close (info, indent);
529
}
530
 
531
static void
532
c_output_advance PROTO_N ((info, indent))
533
		 PROTO_T (COutputInfoP info X
534
			  unsigned     indent)
535
{
536
    OStreamP ostream = c_out_info_ostream (info);
537
 
538
    c_output_indent (info, indent);
539
    write_cstring (ostream, "ADVANCE_LEXER;");
540
    write_newline (ostream);
541
}
542
 
543
static void
544
c_output_unreachable PROTO_N ((info, indent))
545
		     PROTO_T (COutputInfoP info X
546
			      unsigned     indent)
547
{
548
    OStreamP ostream = c_out_info_ostream (info);
549
 
550
    c_output_indent (info, indent);
551
    if (c_out_info_get_unreachable (info)) {
552
	write_cstring (ostream, "UNREACHED;");
553
    } else {
554
	write_cstring (ostream, "/*UNREACHED*/");
555
    }
556
    write_newline (ostream);
557
}
558
 
559
static void
560
c_output_basic_extract PROTO_N ((info, code, item, key, state, indent))
561
		       PROTO_T (COutputInfoP info X
562
				CCodeP       code X
563
				ItemP        item X
564
				KeyP         key X
565
				SaveRStackP  state X
566
				unsigned     indent)
567
{
568
    OStreamP ostream = c_out_info_ostream (info);
569
 
570
    c_output_key_message (info, "/* BEGINNING OF EXTRACT: ", key, " */",
571
			  indent);
572
    c_output_open (info, indent);
573
    c_output_location (info, c_code_file (code), c_code_line (code));
574
    c_output_c_code_basic (info, code, item_result (item), state);
575
    c_output_location (info, ostream_name (ostream),
576
		       ostream_line (ostream) + 1);
577
    c_output_close (info, indent);
578
    c_output_key_message (info, "/* END OF EXTRACT: ", key, " */", indent);
579
}
580
 
581
static void
582
c_output_basic_in_alt PROTO_N ((info, item, handler_rule, need_switch,
583
				need_check, outer_level, error_terminal, state,
584
				indent))
585
		      PROTO_T (COutputInfoP info X
586
			       ItemP        item X
587
			       RuleP        handler_rule X
588
			       BoolT        need_switch X
589
			       BoolT        need_check X
590
			       BoolT        outer_level X
591
			       unsigned     error_terminal X
592
			       SaveRStackP  state X
593
			       unsigned     indent)
594
{
595
    EntryP     entry       = item_entry (item);
596
    KeyP       key         = entry_key (entry);
597
    BasicP     basic       = entry_get_basic (entry);
598
    unsigned   terminal    = basic_terminal (basic);
599
    CCodeP     code        = basic_get_result_code (basic);
600
    unsigned   code_indent = (need_switch ? indent + C_INDENT_STEP : indent);
601
 
602
    if (need_switch) {
603
	c_output_switch (info, indent);
604
	c_output_case (info, terminal, indent);
605
	if (code) {
606
	    c_output_basic_extract (info, code, item, key, state, code_indent);
607
	}
608
	c_output_break (info, code_indent);
609
	if (need_check) {
610
	    c_output_case (info, error_terminal, indent);
611
	    c_output_restore (info, handler_rule, outer_level, code_indent);
612
	}
613
	c_output_default (info, indent);
614
	c_output_jump (info, rule_get_handler_label (handler_rule),
615
		       code_indent);
616
	c_output_close (info, indent);
617
    } else {
618
	ASSERT (!need_check);
619
	if (code) {
620
	    c_output_basic_extract (info, code, item, key, state, code_indent);
621
	}
622
    }
623
    c_output_advance (info, indent);
624
}
625
 
626
static void
627
c_output_tail_call PROTO_N ((info, item, handler_rule, need_check, outer_level,
628
			     error_terminal, rstack, non_local_stack, state,
629
			     indent))
630
		   PROTO_T (COutputInfoP info X
631
			    ItemP        item X
632
			    RuleP        handler_rule X
633
			    BoolT        need_check X
634
			    BoolT        outer_level X
635
			    unsigned     error_terminal X
636
			    RStackP      rstack X
637
			    RStackP      non_local_stack X
638
			    SaveRStackP  state X
639
			    unsigned     indent)
640
{
641
    unsigned code_indent = (need_check ? indent + C_INDENT_STEP : indent);
642
    EntryP   entry       = item_entry (item);
643
    RuleP    rule        = entry_get_rule (entry);
644
    KeyP     key         = entry_key (entry);
645
 
646
    if (need_check) {
647
	c_output_error_if (info, error_terminal, indent);
648
	c_output_restore (info, handler_rule, outer_level, code_indent);
649
	c_output_else (info, indent);
650
    }
651
    c_output_restore_non_locals (info, rule, indent, rstack, non_local_stack);
652
    c_output_tail_decls (info, item_param (item), state, rule_param (rule),
653
			 rule_rstack_state (rule), code_indent);
654
    c_output_key_jump (info, key, rule_get_start_label (rule), code_indent);
655
    if (need_check) {
656
	c_output_close (info, indent);
657
    }
658
}
659
 
660
static BoolT				c_output_rule
661
	PROTO_S ((COutputInfoP, RuleP, RuleP, EntryListP, BoolT, EntryP,
662
		  unsigned, unsigned, RStackP, RStackP, TableP));
663
 
664
static BoolT
665
c_output_rule_in_alt PROTO_N ((info, item, handler_rule, call_list, need_check,
666
			       outer_level, predicate_id, error_terminal,
667
			       indent, rstack, non_local_stack, table,
668
			       reachable_ref))
669
		     PROTO_T (COutputInfoP info X
670
			      ItemP        item X
671
			      RuleP        handler_rule X
672
			      EntryListP   call_list X
673
			      BoolT        need_check X
674
			      BoolT        outer_level X
675
			      EntryP       predicate_id X
676
			      unsigned     error_terminal X
677
			      unsigned     indent X
678
			      RStackP      rstack X
679
			      RStackP      non_local_stack X
680
			      TableP       table X
681
			      BoolT       *reachable_ref)
682
{
683
    OStreamP    ostream   = c_out_info_ostream (info);
684
    EntryP      entry     = item_entry (item);
685
    RuleP       rule      = entry_get_rule (entry);
686
    KeyP        key       = entry_key (entry);
687
    BoolT       tail_call = (item_is_tail_call (item) &&
688
			     rule_is_being_output (rule));
689
    SaveRStackT state;
690
 
691
    rstack_save_state (rstack, &state);
692
    if ((item_is_inlinable (item)) &&
693
	(tail_call || (!(rule_is_being_output (rule) ||
694
			 (rule_get_call_count (rule) > 1))))) {
695
	c_output_key_message (info, "/* BEGINNING OF INLINE: ", key, " */",
696
			      indent);
697
	if (tail_call) {
698
	    c_output_tail_call (info, item, handler_rule, need_check,
699
				outer_level, error_terminal, rstack,
700
				non_local_stack, &state, indent);
701
	    *reachable_ref = FALSE;
702
	} else {
703
	    unsigned code_indent = (indent + C_INDENT_STEP);
704
	    BoolT    copies;
705
 
706
	    c_output_open (info, indent);
707
	    rstack_push_frame (rstack);
708
	    copies = c_output_required_copies (info, rule_param (rule),
709
					       item_param (item), rstack,
710
					       &state, code_indent, table);
711
	    if (copies) {
712
		c_output_open (info, code_indent);
713
		code_indent += C_INDENT_STEP;
714
	    }
715
	    rstack_save_state (rstack, &state);
716
	    rstack_push_frame (rstack);
717
	    rstack_compute_formal_inlining (rstack, rule_param (rule),
718
					    item_param (item));
719
	    rstack_compute_formal_inlining (rstack, rule_result (rule),
720
					    item_result (item));
721
	    rstack_save_state (rstack, rule_rstack_state (rule));
722
	    if (!c_output_rule (info, rule, handler_rule,
723
				item_is_tail_call (item) ? call_list :
724
				rule_call_list (rule), need_check,
725
				predicate_id, error_terminal, code_indent,
726
				rstack, non_local_stack, table)) {
727
		*reachable_ref = FALSE;
728
	    }
729
	    rstack_pop_frame (rstack);
730
	    if (copies) {
731
		c_output_close (info, indent + C_INDENT_STEP);
732
	    }
733
	    rstack_pop_frame (rstack);
734
	    c_output_close (info, indent);
735
	}
736
	c_output_key_message (info, "/* END OF INLINE: ", key, " */", indent);
737
	return (FALSE);
738
    }
739
    if (need_check && outer_level) {
740
	c_output_check (info, handler_rule, TRUE, error_terminal, indent);
741
    }
742
    c_output_indent (info, indent);
743
    c_output_mapped_key (info, entry);
744
    write_cstring (ostream, " (");
745
    c_output_rule_params (info, item_param (item), item_result (item), &state);
746
    write_cstring (ostream, ");");
747
    write_newline (ostream);
748
    return (TRUE);
749
}
750
 
751
static void
752
c_output_action_in_alt PROTO_N ((info, item, handler_rule, need_check,
753
				 outer_level, error_terminal, rstack, indent,
754
				 table))
755
		       PROTO_T (COutputInfoP info X
756
				ItemP        item X
757
				RuleP        handler_rule X
758
				BoolT        need_check X
759
				BoolT        outer_level X
760
				unsigned     error_terminal X
761
				RStackP      rstack X
762
				unsigned     indent X
763
				TableP       table)
764
{
765
    OStreamP    ostream = c_out_info_ostream (info);
766
    EntryP      entry   = item_entry (item);
767
    ActionP     action  = entry_get_action (entry);
768
    KeyP        key     = entry_key (entry);
769
    CCodeP      code    = action_get_code (action);
770
    SaveRStackT state;
771
    BoolT       copies;
772
 
773
    if (need_check) {
774
	c_output_check (info, handler_rule, outer_level, error_terminal,
775
			indent);
776
    }
777
    c_output_key_message (info, "/* BEGINNING OF ACTION: ", key, " */",
778
			  indent);
779
    c_output_open (info, indent);
780
    rstack_save_state (rstack, &state);
781
    rstack_push_frame (rstack);
782
    copies = c_output_required_copies (info, c_code_param (code),
783
				       item_param (item), rstack, &state,
784
				       indent + C_INDENT_STEP, table);
785
    if (copies) {
786
	c_output_open (info, indent + C_INDENT_STEP);
787
    }
788
    rstack_save_state (rstack, &state);
789
    c_output_location (info, c_code_file (code), c_code_line (code));
790
    c_output_c_code_action (info, code, item_param (item),
791
			    item_result (item), &state, handler_rule);
792
    c_output_location (info, ostream_name (ostream),
793
		       ostream_line (ostream) + 1);
794
    rstack_pop_frame (rstack);
795
    if (copies) {
796
	c_output_close (info, indent + C_INDENT_STEP);
797
    }
798
    c_output_close (info, indent);
799
    c_output_key_message (info, "/* END OF ACTION: ", key, " */", indent);
800
}
801
 
802
static void
803
c_output_predicate_in_alt PROTO_N ((info, rule, item, initial, handler_rule,
804
				    needed_switch, need_check, outer_level,
805
				    predicate_id, error_terminal, rstack,
806
				    indent, table))
807
			  PROTO_T (COutputInfoP info X
808
				   RuleP        rule X
809
				   ItemP        item X
810
				   ItemP        initial X
811
				   RuleP        handler_rule X
812
				   BoolT        needed_switch X
813
				   BoolT        need_check X
814
				   BoolT        outer_level X
815
				   EntryP       predicate_id X
816
				   unsigned     error_terminal X
817
				   RStackP      rstack X
818
				   unsigned     indent X
819
				   TableP       table)
820
{
821
    OStreamP ostream = c_out_info_ostream (info);
822
 
823
    c_output_action_in_alt (info, item, handler_rule, need_check, outer_level,
824
			    error_terminal, rstack, indent, table);
825
    c_output_indent (info, indent);
826
    write_cstring (ostream, "if (!");
827
    c_output_key (info, entry_key (predicate_id), c_out_info_in_prefix (info));
828
    write_cstring (ostream, ")");
829
    write_newline (ostream);
830
    if ((item == initial) && (!needed_switch)) {
831
	unsigned label = c_out_next_label ();
832
 
833
	c_output_jump (info, label, indent + C_INDENT_STEP);
834
	rule_set_next_label (rule, label);
835
    } else {
836
	c_output_jump (info, rule_get_handler_label (handler_rule),
837
		       indent + C_INDENT_STEP);
838
    }
839
}
840
 
841
static BoolT
842
c_output_alt PROTO_N ((info, alt, rule, handler_rule, call_list, need_switch,
843
		       need_check, outer_level, predicate_id, error_terminal,
844
		       indent, rstack, non_local_stack, table))
845
	     PROTO_T (COutputInfoP info X
846
		      AltP         alt X
847
		      RuleP        rule X
848
		      RuleP        handler_rule X
849
		      EntryListP   call_list X
850
		      BoolT        need_switch X
851
		      BoolT        need_check X
852
		      BoolT        outer_level X
853
		      EntryP       predicate_id X
854
		      unsigned     error_terminal X
855
		      unsigned     indent X
856
		      RStackP      rstack X
857
		      RStackP      non_local_stack X
858
		      TableP       table)
859
{
860
    ItemP       initial       = alt_item_head (alt);
861
    BoolT       needed_switch = need_switch;
862
    unsigned    code_indent   = (indent + C_INDENT_STEP);
863
    BoolT       reachable     = TRUE;
864
    ItemP       item;
865
    SaveRStackT state;
866
 
867
    rstack_push_frame (rstack);
868
    rstack_compute_local_renaming (rstack, alt_names (alt), rule_result (rule),
869
				   table);
870
    rstack_save_state (rstack, &state);
871
    c_output_open (info, indent);
872
    c_output_alt_names (info, alt_names (alt), rule_result (rule), &state,
873
			code_indent);
874
    for (item = initial; item; item = item_next (item)) {
875
	switch (item_type (item)) EXHAUSTIVE {
876
	  case ET_BASIC:
877
	    c_output_basic_in_alt (info, item, handler_rule, need_switch,
878
				   need_check, outer_level, error_terminal,
879
				   &state, code_indent);
880
	    need_switch = TRUE;
881
	    need_check  = FALSE;
882
	    break;
883
	  case ET_RULE:
884
	    need_check  = c_output_rule_in_alt (info, item, handler_rule,
885
						call_list, need_check,
886
						outer_level, predicate_id,
887
						error_terminal, code_indent,
888
						rstack, non_local_stack, table,
889
						&reachable);
890
	    need_switch = TRUE;
891
	    break;
892
	  case ET_PREDICATE:
893
	    c_output_predicate_in_alt (info, rule, item, initial, handler_rule,
894
				       needed_switch, need_check, outer_level,
895
				       predicate_id, error_terminal, rstack,
896
				       code_indent, table);
897
	    need_switch = TRUE;
898
	    need_check  = FALSE;
899
	    break;
900
	  case ET_ACTION:
901
	    c_output_action_in_alt (info, item, handler_rule, need_check,
902
				    outer_level, error_terminal, rstack,
903
				    code_indent, table);
904
	    need_check = FALSE;
905
	    break;
906
	  case ET_RENAME:
907
	    if (need_check) {
908
		c_output_check (info, handler_rule, outer_level,
909
				error_terminal, code_indent);
910
	    }
911
	    c_output_rename (info, item_param (item), item_result (item),
912
			     &state, code_indent);
913
	    need_check = FALSE;
914
	    break;
915
	  case ET_NON_LOCAL:
916
	  case ET_NAME:
917
	  case ET_TYPE:
918
	    UNREACHED;
919
	}
920
	outer_level = FALSE;
921
    }
922
    if (reachable) {
923
	if (need_check) {
924
	    c_output_check (info, handler_rule, outer_level, error_terminal,
925
			    code_indent);
926
	}
927
	if (item_is_predicate (initial) && (!needed_switch)) {
928
	    c_output_jump (info, rule_get_end_label (rule), code_indent);
929
	    reachable = FALSE;
930
	}
931
    }
932
    c_output_close (info, indent);
933
    if (!reachable) {
934
	c_output_unreachable (info, indent);
935
    }
936
    rstack_pop_frame (rstack);
937
    return (reachable);
938
}
939
 
940
static BoolT
941
c_output_rule PROTO_N ((info, rule, handler_rule, call_list, need_check,
942
			predicate_id, error_terminal, indent, rstack,
943
			non_local_stack, table))
944
	      PROTO_T (COutputInfoP info X
945
		       RuleP        rule X
946
		       RuleP        handler_rule X
947
		       EntryListP   call_list X
948
		       BoolT        need_check X
949
		       EntryP       predicate_id X
950
		       unsigned     error_terminal X
951
		       unsigned     indent X
952
		       RStackP      rstack X
953
		       RStackP      non_local_stack X
954
		       TableP       table)
955
{
956
    EntryP        entry            = rule_entry (rule);
957
    KeyP          key              = entry_key (entry);
958
    EntryListP    predicate_firsts = rule_predicate_first (rule);
959
    BoolT         predicates       = (!entry_list_is_empty (predicate_firsts));
960
    RuleP         old_handler_rule = handler_rule;
961
    BoolT         outer_level      = (old_handler_rule == rule);
962
    BoolT         reachable        = TRUE;
963
    unsigned      code_indent      = indent;
964
    NonLocalListP non_locals       = rule_non_locals (rule);
965
    BoolT         has_non_locals   = (!non_local_list_is_empty (non_locals));
966
    AltP          handler          = rule_get_handler (rule);
967
    BoolT         full_first_set   = bitvec_is_full (rule_first_set (rule));
968
    BoolT         one_alt          = rule_has_one_alt (rule);
969
 
970
    ASSERT (!rule_is_being_output (rule));
971
    rule_being_output (rule);
972
    rule_set_end_label (rule, c_out_next_label ());
973
    if (need_check && (predicates || has_non_locals || one_alt)) {
974
	c_output_check (info, handler_rule, outer_level, error_terminal,
975
			indent);
976
	need_check = FALSE;
977
    }
978
    if (outer_level) {
979
	rule_set_handler_label (rule, c_out_next_label ());
980
    } else if ((handler != NIL (AltP)) || has_non_locals) {
981
	handler_rule = rule;
982
	rule_set_handler_label (rule, c_out_next_label ());
983
    }
984
    if (entry_list_contains (call_list, entry)) {
985
	unsigned label = c_out_next_label ();
986
 
987
	c_output_key_label (info, key, label, indent);
988
	rule_set_start_label (rule, label);
989
    }
990
    if (has_non_locals) {
991
	c_output_open (info, indent);
992
	code_indent += C_INDENT_STEP;
993
	rstack_push_frame (rstack);
994
	rstack_push_frame (non_local_stack);
995
	c_output_save_non_locals (info, rule, code_indent, rstack,
996
				  non_local_stack, handler_rule, table);
997
    }
998
    if (one_alt) {
999
	if (!rule_has_empty_alt (rule)) {
1000
	    AltP alt = rule_alt_head (rule);
1001
 
1002
	    reachable = c_output_alt (info, alt, rule, handler_rule, call_list,
1003
				      TRUE, need_check, outer_level,
1004
				      predicate_id, error_terminal,
1005
				      code_indent, rstack, non_local_stack,
1006
				      table);
1007
	} else {
1008
	    if (need_check) {
1009
		c_output_check (info, handler_rule, outer_level,
1010
				error_terminal, code_indent);
1011
	    }
1012
	    reachable  = TRUE;
1013
	}
1014
    } else {
1015
	BoolT non_predicate_alts = TRUE;
1016
	AltP  see_through_alt    = rule_see_through_alt (rule);
1017
	AltP  alt;
1018
 
1019
	if (predicates) {
1020
	    non_predicate_alts = FALSE;
1021
	    for (alt = rule_alt_head (rule); alt; alt = alt_next (alt)) {
1022
		ItemP item = alt_item_head (alt);
1023
 
1024
		if (item_is_predicate (item)) {
1025
		    (void) c_output_alt (info, alt, rule, handler_rule,
1026
					 call_list, FALSE, FALSE, FALSE,
1027
					 predicate_id, error_terminal,
1028
					 code_indent, rstack, non_local_stack,
1029
					 table);
1030
		    c_output_label (info, rule_get_next_label (rule),
1031
				    code_indent);
1032
		} else {
1033
		    non_predicate_alts = TRUE;
1034
		}
1035
	    }
1036
	}
1037
	if (non_predicate_alts) {
1038
	    reachable = FALSE;
1039
	    c_output_switch (info, code_indent);
1040
	    for (alt = rule_alt_head (rule); alt; alt = alt_next (alt)) {
1041
		ItemP item = alt_item_head (alt);
1042
 
1043
		if (!item_is_predicate (item)) {
1044
		    if (alt == see_through_alt) {
1045
			ASSERT (!full_first_set);
1046
			c_output_default (info, code_indent);
1047
		    } else {
1048
			c_output_bitvec_cases (info, alt_first_set (alt),
1049
					       code_indent);
1050
		    }
1051
		    if (c_output_alt (info, alt, rule, handler_rule, call_list,
1052
				      FALSE, FALSE, FALSE, predicate_id,
1053
				      error_terminal,
1054
				      code_indent + C_INDENT_STEP,
1055
				      rstack, non_local_stack, table)) {
1056
			c_output_break (info, code_indent + C_INDENT_STEP);
1057
			reachable = TRUE;
1058
		    }
1059
		}
1060
	    }
1061
	    if (need_check) {
1062
		c_output_case (info, error_terminal, code_indent);
1063
		c_output_restore (info, handler_rule, outer_level,
1064
				  code_indent + C_INDENT_STEP);
1065
	    }
1066
	    if ((see_through_alt == NIL (AltP)) && (!full_first_set)) {
1067
		c_output_default (info, code_indent);
1068
		if (!rule_has_empty_alt (rule)) {
1069
		    c_output_jump (info, rule_get_handler_label (handler_rule),
1070
				   code_indent + C_INDENT_STEP);
1071
		} else {
1072
		    c_output_break (info, code_indent + C_INDENT_STEP);
1073
		    reachable = TRUE;
1074
		}
1075
	    }
1076
	    c_output_close (info, code_indent);
1077
	} else {
1078
	    ASSERT (!need_check);
1079
	    if (!rule_has_empty_alt (rule)) {
1080
		c_output_jump (info, rule_get_handler_label (handler_rule),
1081
			       code_indent);
1082
	    }
1083
	}
1084
    }
1085
    if (((handler != NIL (AltP)) || has_non_locals || outer_level) &&
1086
	rule_used_handler_label (rule)) {
1087
	if (reachable) {
1088
	    if (outer_level && types_equal_zero_tuple (rule_result (rule)) &&
1089
		(!has_non_locals)) {
1090
		c_output_return (info, code_indent);
1091
	    } else {
1092
		c_output_jump (info, rule_get_end_label (rule), code_indent);
1093
	    }
1094
	} else {
1095
	    c_output_unreachable (info, code_indent);
1096
	}
1097
	reachable = FALSE;
1098
	if (handler) {
1099
	    RuleP cleanup_handler_rule = old_handler_rule;
1100
 
1101
	    c_output_label (info, rule_get_handler_label (rule), code_indent);
1102
	    reachable = TRUE;
1103
	    if (outer_level || has_non_locals) {
1104
		rule_set_handler_label (rule, c_out_next_label ());
1105
		cleanup_handler_rule = rule;
1106
	    }
1107
	    if (!c_output_alt (info, handler, rule, cleanup_handler_rule,
1108
			       call_list, TRUE, FALSE, FALSE, predicate_id,
1109
			       error_terminal, code_indent, rstack,
1110
			       non_local_stack, table)) {
1111
		reachable = FALSE;
1112
	    }
1113
	}
1114
	if ((outer_level || has_non_locals) &&
1115
	    rule_used_handler_label (rule)) {
1116
	    if (reachable) {
1117
		c_output_jump (info, rule_get_end_label (rule), code_indent);
1118
	    } else if (handler) {
1119
		c_output_unreachable (info, code_indent);
1120
	    }
1121
	    c_output_label (info, rule_get_handler_label (rule), code_indent);
1122
	    if (has_non_locals) {
1123
		c_output_restore_non_locals (info, rule, code_indent, rstack,
1124
					     non_local_stack);
1125
	    }
1126
	    if (outer_level) {
1127
		OStreamP ostream = c_out_info_ostream (info);
1128
 
1129
		c_output_indent (info, code_indent);
1130
		write_cstring (ostream, "SAVE_LEXER (");
1131
		write_unsigned (ostream, error_terminal);
1132
		write_cstring (ostream, ");");
1133
		write_newline (ostream);
1134
		c_output_return (info, code_indent);
1135
	    } else {
1136
		c_output_jump (info, rule_get_handler_label (old_handler_rule),
1137
			       code_indent);
1138
	    }
1139
	    reachable = FALSE;
1140
	}
1141
    }
1142
    if (rule_used_end_label (rule)) {
1143
	c_output_label (info, rule_get_end_label (rule), code_indent);
1144
	reachable = TRUE;
1145
    }
1146
    if (reachable) {
1147
	if (has_non_locals) {
1148
	    c_output_restore_non_locals (info, rule, code_indent, rstack,
1149
					 non_local_stack);
1150
	}
1151
	if (outer_level) {
1152
	    c_output_result_assign (info, rule_result (rule), code_indent);
1153
	}
1154
    }
1155
    if (has_non_locals) {
1156
	c_output_close (info, indent);
1157
	rstack_pop_frame (non_local_stack);
1158
	rstack_pop_frame (rstack);
1159
    }
1160
    rule_not_being_output (rule);
1161
    return (reachable);
1162
}
1163
 
1164
static void
1165
c_output_definition_1 PROTO_N ((info, rule, predicate_id, predicate_type,
1166
				error_terminal, table))
1167
		      PROTO_T (COutputInfoP info X
1168
			       RuleP        rule X
1169
			       EntryP       predicate_id X
1170
			       EntryP       predicate_type X
1171
			       unsigned     error_terminal X
1172
			       TableP       table)
1173
{
1174
    OStreamP ostream = c_out_info_ostream (info);
1175
    EntryP   entry   = rule_entry (rule);
1176
    unsigned split   = c_out_info_get_split (info);
1177
    RStackT  rstack;
1178
    RStackT  non_local_stack;
1179
 
1180
    if (rule_is_required (rule)) {
1181
	write_cstring (ostream, "void");
1182
    } else if (rule_needs_function (rule)) {
1183
	if (split != 0) {
1184
	    write_cstring (ostream, "void");
1185
	} else {
1186
	    write_cstring (ostream, "static void");
1187
	}
1188
    } else {
1189
	return;
1190
    }
1191
    write_newline (ostream);
1192
    c_output_mapped_key (info, entry);
1193
    write_char (ostream, ' ');
1194
    c_output_type_defn (info, rule_param (rule), rule_result (rule));
1195
    c_out_reset_labels ();
1196
    rstack_init (&rstack);
1197
    rstack_push_frame (&rstack);
1198
    rstack_add_translation (&rstack, predicate_id, predicate_id,
1199
			    predicate_type, FALSE);
1200
    rstack_compute_formal_renaming (&rstack, rule_param (rule));
1201
    rstack_compute_formal_renaming (&rstack, rule_result (rule));
1202
    rstack_save_state (&rstack, rule_rstack_state (rule));
1203
    rstack_init (&non_local_stack);
1204
    (void) c_output_rule (info, rule, rule, rule_call_list (rule), TRUE,
1205
			  predicate_id, error_terminal, C_INDENT_STEP,
1206
			  &rstack, &non_local_stack, table);
1207
    write_char (ostream, '}');
1208
    write_newline (ostream);
1209
    write_newline (ostream);
1210
    rstack_destroy (&rstack);
1211
    rstack_destroy (&non_local_stack);
1212
    if (split != 0) {
1213
	if (ostream_line (ostream) >= split) {
1214
	    CStringP     name    = ostream_gen_name (ostream);
1215
	    CCodeP       header  = c_out_info_get_header1 (info);
1216
	    write_cstring (ostream, "/* END OF FILE */");
1217
	    write_newline (ostream);
1218
	    ostream_close (ostream);
1219
	    if (!ostream_open (ostream, name)) {
1220
		E_cannot_open_output_file (name);
1221
		UNREACHED;
1222
	    }
1223
	    c_output_identification (info);
1224
	    write_cstring (ostream, "/* BEGINNING OF HEADER */");
1225
	    write_newline (ostream);
1226
	    write_newline (ostream);
1227
	    write_cstring (ostream, "#define __SID_SPLIT");
1228
	    write_newline (ostream);
1229
	    c_output_location (info, c_code_file (header),
1230
			       c_code_line (header));
1231
	    c_output_c_code (info, header);
1232
	    c_output_location (info, ostream_name (ostream),
1233
			       ostream_line (ostream) + 1);
1234
	    write_newline (ostream);
1235
	}
1236
    }
1237
}
1238
 
1239
static void
1240
c_output_definition PROTO_N ((entry, gclosure))
1241
		    PROTO_T (EntryP   entry X
1242
			     GenericP gclosure)
1243
{
1244
    if (entry_is_rule (entry)) {
1245
	RuleP        rule           = entry_get_rule (entry);
1246
	COutClosureP closure        = (COutClosureP) gclosure;
1247
	COutputInfoP info           = closure->info;
1248
	TableP       table          = closure->table;
1249
	EntryP       predicate_id   = closure->predicate_id;
1250
	EntryP       predicate_type = closure->predicate_type;
1251
	unsigned     error_terminal = closure->error_terminal;
1252
 
1253
	c_output_definition_1 (info, rule, predicate_id, predicate_type,
1254
			       error_terminal, table);
1255
    }
1256
}
1257
 
1258
/*--------------------------------------------------------------------------*/
1259
 
1260
void
1261
c_output_parser PROTO_N ((info, grammar))
1262
		PROTO_T (COutputInfoP info X
1263
			 GrammarP     grammar)
1264
{
1265
    TableP       table   = grammar_table (grammar);
1266
    OStreamP     ostream = c_out_info_ostream (info);
1267
    CCodeP       header  = c_out_info_get_header1 (info);
1268
    CCodeP       trailer = c_out_info_get_trailer1 (info);
1269
    COutClosureT closure;
1270
 
1271
    closure.info           = info;
1272
    closure.table          = table;
1273
    closure.predicate_id   = grammar_get_predicate_id (grammar);
1274
    closure.predicate_type = grammar_get_predicate_type (grammar);
1275
    closure.error_terminal = grammar_max_terminal (grammar);
1276
    c_output_identification (info);
1277
    write_cstring (ostream, "/* BEGINNING OF HEADER */");
1278
    write_newline (ostream);
1279
    write_newline (ostream);
1280
    if (c_out_info_get_split (info) != 0) {
1281
	write_cstring (ostream, "#define __SID_SPLIT");
1282
	write_newline (ostream);
1283
    }
1284
    c_output_location (info, c_code_file (header), c_code_line (header));
1285
    c_output_c_code (info, header);
1286
    c_output_location (info, ostream_name (ostream),
1287
		       ostream_line (ostream) + 1);
1288
    write_newline (ostream);
1289
    if (c_out_info_get_split (info) == 0) {
1290
	write_cstring (ostream, "/* BEGINNING OF FUNCTION DECLARATIONS */");
1291
	write_newline (ostream);
1292
	write_newline (ostream);
1293
	table_iter (table, c_output_declaration, (GenericP) info);
1294
	write_newline (ostream);
1295
    }
1296
    c_output_static_vars (info, grammar, TRUE);
1297
    write_cstring (ostream, "/* BEGINNING OF FUNCTION DEFINITIONS */");
1298
    write_newline (ostream);
1299
    write_newline (ostream);
1300
    table_iter (table, c_output_definition, (GenericP) &closure);
1301
    write_cstring (ostream, "/* BEGINNING OF TRAILER */");
1302
    write_newline (ostream);
1303
    write_newline (ostream);
1304
    c_output_location (info, c_code_file (trailer), c_code_line (trailer));
1305
    c_output_c_code (info, trailer);
1306
    c_output_location (info, ostream_name (ostream),
1307
		       ostream_line (ostream) + 1);
1308
    write_newline (ostream);
1309
    write_cstring (ostream, "/* END OF FILE */");
1310
    write_newline (ostream);
1311
}
1312
 
1313
void
1314
c_output_header PROTO_N ((info, grammar))
1315
		PROTO_T (COutputInfoP info X
1316
			 GrammarP     grammar)
1317
{
1318
    TableP   table   = grammar_table (grammar);
1319
    OStreamP ostream = c_out_info_ostream (info);
1320
    CCodeP   header  = c_out_info_get_header2 (info);
1321
    CCodeP   trailer = c_out_info_get_trailer2 (info);
1322
 
1323
    c_output_identification (info);
1324
    write_cstring (ostream, "/* BEGINNING OF HEADER */");
1325
    write_newline (ostream);
1326
    write_newline (ostream);
1327
    c_output_location (info, c_code_file (header), c_code_line (header));
1328
    c_output_c_code (info, header);
1329
    c_output_location (info, ostream_name (ostream),
1330
		       ostream_line (ostream) + 1);
1331
    write_newline (ostream);
1332
    write_cstring (ostream, "/* BEGINNING OF FUNCTION DECLARATIONS */");
1333
    write_newline (ostream);
1334
    write_newline (ostream);
1335
    if (c_out_info_get_split (info) != 0) {
1336
	write_cstring (ostream, "#ifndef __SID_SPLIT");
1337
	write_newline (ostream);
1338
	table_iter (table, c_output_ext_declaration, (GenericP) info);
1339
	write_cstring (ostream, "#else /* __SID_SPLIT */");
1340
	write_newline (ostream);
1341
	table_iter (table, c_output_declaration, (GenericP) info);
1342
	c_output_static_vars (info, grammar, FALSE);
1343
	write_cstring (ostream, "#endif /* __SID_SPLIT */");
1344
	write_newline (ostream);
1345
    } else {
1346
	table_iter (table, c_output_ext_declaration, (GenericP) info);
1347
    }
1348
    write_newline (ostream);
1349
    write_cstring (ostream, "/* BEGINNING OF TERMINAL DEFINITIONS */");
1350
    write_newline (ostream);
1351
    write_newline (ostream);
1352
    table_iter (table, c_output_terminal, (GenericP) info);
1353
    write_newline (ostream);
1354
    write_cstring (ostream, "/* BEGINNING OF TRAILER */");
1355
    write_newline (ostream);
1356
    write_newline (ostream);
1357
    c_output_location (info, c_code_file (trailer), c_code_line (trailer));
1358
    c_output_c_code (info, trailer);
1359
    c_output_location (info, ostream_name (ostream),
1360
		       ostream_line (ostream) + 1);
1361
    write_newline (ostream);
1362
    write_cstring (ostream, "/* END OF FILE */");
1363
    write_newline (ostream);
1364
}
1365
 
1366
void
1367
c_output_location PROTO_N ((info, file, line))
1368
		  PROTO_T (COutputInfoP info X
1369
			   CStringP     file X
1370
			   unsigned     line)
1371
{
1372
    if (c_out_info_get_lines (info)) {
1373
	OStreamP ostream = c_out_info_ostream (info);
1374
 
1375
	write_cstring (ostream, "#line ");
1376
	write_unsigned (ostream, line);
1377
	write_cstring (ostream, " \"");
1378
	write_cstring (ostream, file);
1379
	write_char (ostream, '"');
1380
	write_newline (ostream);
1381
    }
1382
}
1383
 
1384
void
1385
c_output_key_message PROTO_N ((info, prefix, key, suffix, indent))
1386
		     PROTO_T (COutputInfoP info X
1387
			      CStringP     prefix X
1388
			      KeyP         key X
1389
			      CStringP     suffix X
1390
			      unsigned     indent)
1391
{
1392
    if (c_out_info_get_lines (info)) {
1393
	OStreamP ostream = c_out_info_ostream (info);
1394
 
1395
	c_output_indent (info, indent);
1396
	write_cstring (ostream, prefix);
1397
	write_key (ostream, key);
1398
	write_cstring (ostream, suffix);
1399
	write_newline (ostream);
1400
    }
1401
}
1402
 
1403
unsigned
1404
c_out_next_label PROTO_Z ()
1405
{
1406
    return (out_current_label ++);
1407
}
1408
 
1409
void
1410
c_output_open PROTO_N ((info, indent))
1411
	      PROTO_T (COutputInfoP info X
1412
		       unsigned     indent)
1413
{
1414
    OStreamP ostream = c_out_info_ostream (info);
1415
 
1416
    c_output_indent (info, indent);
1417
    write_char (ostream, '{');
1418
    write_newline (ostream);
1419
}
1420
 
1421
void
1422
c_output_close PROTO_N ((info, indent))
1423
	       PROTO_T (COutputInfoP info X
1424
			unsigned     indent)
1425
{
1426
    OStreamP ostream = c_out_info_ostream (info);
1427
 
1428
    c_output_indent (info, indent);
1429
    write_char (ostream, '}');
1430
    write_newline (ostream);
1431
}
1432
 
1433
/*
1434
 * Local variables(smf):
1435
 * eval: (include::add-path-entry "../os-interface" "../library")
1436
 * eval: (include::add-path-entry "../transforms" "../output" "../generated")
1437
 * end:
1438
**/