Subversion Repositories tendra.SVN

Rev

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

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