Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
6 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
6 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
6 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
6 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#include "system.h"
63
#include "c_types.h"
64
#include "exp_ops.h"
65
#include "hashid_ops.h"
66
#include "id_ops.h"
67
#include "loc_ext.h"
68
#include "member_ops.h"
69
#include "nat_ops.h"
70
#include "str_ops.h"
71
#include "tok_ops.h"
72
#include "type_ops.h"
73
#include "error.h"
74
#include "catalog.h"
75
#include "option.h"
76
#include "buffer.h"
77
#include "char.h"
78
#include "compile.h"
79
#include "constant.h"
80
#include "convert.h"
81
#include "dump.h"
82
#include "file.h"
83
#include "hash.h"
84
#include "identifier.h"
85
#include "lex.h"
86
#include "literal.h"
87
#include "macro.h"
88
#include "namespace.h"
89
#include "parse.h"
90
#include "pragma.h"
91
#include "predict.h"
92
#include "preproc.h"
93
#include "print.h"
94
#include "statement.h"
95
#include "symbols.h"
96
#include "syntax.h"
97
#include "tokdef.h"
98
#include "token.h"
99
#include "ustring.h"
100
#include "xalloc.h"
101
 
102
 
103
/*
104
    FORWARD DECLARATIONS
105
 
106
    The following functions, which are concerned with processing assertions,
107
    are used in read_if_exp before they are defined.
108
*/
109
 
6 7u83 110
static int eq_pptok(PPTOKEN *, PPTOKEN *);
111
static PPTOKEN *skip_predicate(PPTOKEN **, int);
112
static int check_assert(HASHID, PPTOKEN *, int);
2 7u83 113
 
114
 
115
/*
116
    PREPROCESSING FLAGS
117
 
118
    The flag in_preproc_dir is set to true in a preprocessing directive.
119
    The flag preproc_only causes only the preprocessor to be run.  Finally
120
    preproc_loc records the position of the start of each preprocessing
121
    directive.
122
*/
123
 
6 7u83 124
int in_preproc_dir = 0;
125
int no_preproc_dir = 0;
126
int in_pragma_dir = 0;
127
int in_hash_if_exp = 0;
128
int pragma_number = 0;
129
int preproc_only = 0;
130
int preproc_space = 0;
131
LOCATION preproc_loc = NULL_loc;
2 7u83 132
 
133
 
134
/*
135
    NEGATE A CONDITIONAL
136
 
137
    This routine negates the conditional cond.  Note that skipped and
138
    unresolved conditions negate to themselves.
139
*/
140
 
6 7u83 141
static unsigned
142
negate_cond(unsigned cond)
2 7u83 143
{
6 7u83 144
	if (cond == PP_TRUE) {
145
		return(PP_FALSE);
146
	}
147
	if (cond == PP_FALSE) {
148
		return(PP_TRUE);
149
	}
150
	if (cond == PP_PAST) {
151
		return(PP_FALSE);
152
	}
153
	return(cond);
2 7u83 154
}
155
 
156
 
157
/*
158
    CONDITIONAL COMPILATION STACK
159
 
160
    The stack preproc_stack gives all the active conditional compilation
161
    states.  In addition loc_stack records the corresponding file locations.
162
    preproc_depth gives the depth of conditional compilation within the
163
    current file.
164
*/
165
 
6 7u83 166
static STACK(unsigned)preproc_stack = NULL_stack(unsigned);
167
static STACK(LOCATION)loc_stack = NULL_stack(LOCATION);
168
static unsigned preproc_depth = 0;
2 7u83 169
 
170
 
171
/*
172
    SET UP CONDITIONAL COMPILATION STACK
173
 
174
    This routine sets up the conditional compilation stack at the start
175
    of a source file by pushing an end marker.
176
*/
177
 
6 7u83 178
void
179
start_preproc_if(void)
2 7u83 180
{
6 7u83 181
	PUSH_unsigned(preproc_depth, preproc_stack);
182
	PUSH_unsigned(PP_END, preproc_stack);
183
	PUSH_loc(crt_loc, loc_stack);
184
	preproc_depth = 0;
185
	return;
2 7u83 186
}
187
 
188
 
189
/*
190
    CLEAR CONDITIONAL COMPILATION STACK
191
 
192
    This routine is called at the end of each source file to check for
193
    any unmatched '#if', '#elif' or '#else' directives.  It clears the
194
    conditional compilation stack down as far as the end marker set up
195
    by the previous routine.  It is possible for the routine to be
196
    called more than once for the main source file, hence the necessity
197
    to check that the stack is not empty.  The routine returns true if
198
    no unmatched directives are found.
199
*/
200
 
6 7u83 201
int
202
clear_preproc_if(void)
2 7u83 203
{
6 7u83 204
	int ok = 1;
205
	while (!IS_NULL_stack(preproc_stack)) {
206
		int dir;
207
		LOCATION loc;
208
		unsigned cond;
209
		POP_unsigned(cond, preproc_stack);
210
		POP_loc(loc, loc_stack);
211
		if (cond == PP_END) {
212
			/* Restore stored preprocessing depth */
213
			POP_unsigned(preproc_depth, preproc_stack);
214
			break;
215
		}
216
		if (cond & PP_HAVE_ELSE) {
217
			dir = lex_else;
218
		} else if (cond & PP_HAVE_ELIF) {
219
			dir = lex_elif;
220
		} else {
221
			dir = lex_if;
222
		}
223
		report(loc, ERR_cpp_cond_if_match(dir, lex_endif));
224
		decr_value(OPT_VAL_hash_if_depth);
225
		preproc_depth--;
226
		ok = 0;
2 7u83 227
	}
6 7u83 228
	return(ok);
2 7u83 229
}
230
 
231
 
232
/*
233
    MACRO-LIKE TOKEN IDENTIFIER
234
 
235
    If check_macro finds a macro-like token then the corresponding identifier
236
    is stored in this variable.
237
*/
238
 
6 7u83 239
IDENTIFIER token_macro = NULL_id;
2 7u83 240
 
241
 
242
/*
243
    CHECK WHETHER A MACRO IS DEFINED
244
 
245
    This routine checks whether the hash table entry macro represents a
246
    valid macro.  It returns PP_TRUE if macro is already defined and
247
    PP_FALSE otherwise.  It also reports on ISO keywords and other invalid
248
    macro identifiers.  If used is true then the macro is marked as having
249
    been used.
250
*/
251
 
6 7u83 252
unsigned
253
check_macro(HASHID macro, int used)
2 7u83 254
{
6 7u83 255
	/* Check for simple macros */
256
	DECL_SPEC ds;
257
	IDENTIFIER id;
258
	if (IS_NULL_hashid(macro)) {
259
		/* Special case for protection macros */
260
		return(PP_TRUE);
2 7u83 261
	}
6 7u83 262
	id = DEREF_id(hashid_id(macro));
263
	switch (TAG_id(id)) {
264
	case id_obj_macro_tag:
265
	case id_func_macro_tag:
266
		if (used) {
267
			ds = DEREF_dspec(id_storage(id));
268
			ds |= dspec_used;
269
			COPY_dspec(id_storage(id), ds);
270
			if (do_macro && do_usage) {
271
				dump_use(id, &preproc_loc, 1);
272
			}
273
		}
274
		return(PP_TRUE);
275
	case id_iso_keyword_tag:
276
		if (used) {
277
			report(preproc_loc, ERR_lex_key_iso(macro));
278
		}
279
		break;
2 7u83 280
	}
281
 
6 7u83 282
	/* Check for tokenised values */
283
	if (preproc_only) {
284
		id = underlying_id(id);
285
		ds = DEREF_dspec(id_storage(id));
286
		if (ds & dspec_token) {
287
			/* May be a token */
288
			token_macro = id;
289
			return(PP_TOKEN | PP_UNRESOLVED);
290
		}
2 7u83 291
 
6 7u83 292
	} else {
293
		id = find_id(macro);
294
		while (!IS_NULL_id(id)) {
295
			IDENTIFIER tid = find_token(id);
296
			if (IS_id_token(tid)) {
297
				IDENTIFIER sid = DEREF_id(id_token_alt(tid));
298
				ds = DEREF_dspec(id_storage(sid));
299
				if ((ds & dspec_token) &&
300
				    !(ds & dspec_template)) {
301
					TOKEN tok =
302
					    DEREF_tok(id_token_sort(tid));
303
					switch (TAG_tok(tok)) {
304
					case tok_exp_tag:
305
					case tok_stmt_tag:
306
					case tok_nat_tag:
307
					case tok_snat_tag:
308
					case tok_func_tag:
309
					case tok_proc_tag:
310
						/* These are in the macro
311
						 * namespace */
312
						if (used) {
313
							use_id(id, 0);
314
						}
315
						token_macro = id;
316
						ds = DEREF_dspec(id_storage(tid));
317
						if (ds & (dspec_pure |
318
							  dspec_defn)) {
319
							return(PP_TOKEN |
320
							       PP_TRUE);
321
						}
322
						return(PP_TOKEN | PP_FALSE);
323
					}
324
				}
2 7u83 325
			}
6 7u83 326
			if (!IS_id_function_etc(id)) {
327
				break;
328
			}
329
			id = DEREF_id(id_function_etc_over(id));
2 7u83 330
		}
331
	}
6 7u83 332
	return(PP_FALSE);
2 7u83 333
}
334
 
335
 
336
/*
337
    TARGET DEPENDENT CONDITION
338
 
339
    Any target dependent conditional compilation expressions encountered
340
    are stored in this variable.
341
*/
342
 
6 7u83 343
EXP crt_hash_if_exp = NULL_exp;
2 7u83 344
 
345
 
346
/*
347
    PATCH PREPROCESSING DIRECTIVE INTO PREPROCESSOR OUTPUT
348
 
349
    This routine is used to patch the preprocessing directive given by
350
    the preprocessing tokens p into the main preprocessor output.  It is
351
    used to preserve target dependent conditionals and other directives
352
    which need to be passed through to the output.
353
*/
354
 
6 7u83 355
void
356
patch_preproc_dir(PPTOKEN *p)
2 7u83 357
{
6 7u83 358
	if (p) {
359
		PPTOKEN *q = p;
360
		while (q->next && q->next->tok != lex_newline) {
361
			q = q->next;
362
		}
363
		free_tok_list(q->next);
364
		q->next = crt_token->next;
365
		crt_token->next = p;
366
		p->pp_space = WHITE_SPACE;
367
	}
368
	return;
2 7u83 369
}
370
 
371
 
372
/*
373
    READ AN EXPRESSION COMPILATION CONDITION
374
 
375
    This routine reads the constant expression following a '#if' or '#elif'
376
    preprocessing directive.  It returns a value indicating whether the
377
    expression is zero or nonzero.  The argument act is false to indicate
378
    that the directive is being skipped.  The expression consists of all
379
    the preprocessing tokens in the rest of the directive with any
380
    defined operations suitably expanded.  This is then macro expanded
381
    and finally has any remaining identifiers replaced by 0.  All the
382
    parsing is done using this list of tokens - no other tokens are read
383
    from the input file (the newline appended by read_line ensures that
384
    the parser doesn't spill off the end).
385
*/
386
 
6 7u83 387
static unsigned
388
read_if_exp(int act, int dir)
2 7u83 389
{
6 7u83 390
	EXP e = NULL_exp;
391
	unsigned cond = PP_SKIP;
392
	if (act) {
393
		/* Read the rest of the line */
394
		PARSE_STATE ps;
395
		HASHID def = KEYWORD(lex_defined);
396
		PPTOKEN *p = read_line(lex_ignore_token, lex_newline);
397
		PPTOKEN *q = p;
2 7u83 398
 
6 7u83 399
		/* Scan line for defined operations and assertions */
400
		while (q != NULL) {
401
			int t = q->tok;
2 7u83 402
 
6 7u83 403
			if (t == lex_identifier &&
404
			    EQ_hashid(q->pp_data.id.hash, def)) {
405
				/* Deal with 'defined' */
406
				PPTOKEN *r = q->next;
407
				/* Because of final newline don't need to check
408
				 * r != NULL */
409
				t = r->tok;
410
				if (t == lex_identifier) {
411
					/* Operation of the form 'defined id' */
412
					HASHID macro = r->pp_data.id.hash;
413
					unsigned c = check_macro(macro, 1);
414
					c &= PP_COND_MASK;
415
					if (c == PP_UNRESOLVED) {
416
						q->tok = lex_defined;
417
						cond = PP_UNRESOLVED;
418
					} else {
419
						q->tok = lex_integer_Hlit;
420
						q->pp_data.text =
421
						    ustrlit(c ? "1" : "0");
422
						q->next = r->next;
423
						r->next = NULL;
424
						free_tok_list(r);
425
					}
2 7u83 426
 
6 7u83 427
				} else if (t == lex_open_Hround &&
428
					   r->next->tok == lex_identifier &&
429
					   r->next->next->tok ==
430
					   lex_close_Hround) {
431
					/* Operation of the form
432
					 * 'defined(id)' */
433
					HASHID macro = r->next->pp_data.id.hash;
434
					unsigned c = check_macro(macro, 1);
435
					c &= PP_COND_MASK;
436
					if (c == PP_UNRESOLVED) {
437
						q->tok = lex_defined;
438
						cond = PP_UNRESOLVED;
439
					} else {
440
						q->tok = lex_integer_Hlit;
441
						q->pp_data.text =
442
						    ustrlit(c ? "1" : "0");
443
						q->next = r->next->next->next;
444
						r->next->next->next = NULL;
445
						free_tok_list(r);
446
					}
2 7u83 447
 
6 7u83 448
				} else {
449
					/* Badly formed 'defined' operation */
450
					report(preproc_loc,
451
					       ERR_cpp_cond_def_id());
452
				}
2 7u83 453
 
6 7u83 454
			} else if ((t == lex_hash_H1 || t == lex_hash_H2) &&
455
				   q->next->tok == lex_identifier) {
456
				/* Deal with '#predicate' */
457
				CONST char *c = "0";
458
				PPTOKEN *r = q->next;
459
				HASHID pred = r->pp_data.id.hash;
460
				if (t == lex_hash_H2) {
461
					IGNORE get_digraph(t);
462
				}
463
				if (r->next->tok == lex_open_Hround) {
464
					/* Check for a particular predicate */
465
					PPTOKEN *s = r->next->next;
466
					q->next = skip_predicate(&s, dir);
467
					if (check_assert(pred, s, 0)) {
468
						c = "1";
469
					}
470
				} else {
471
					/* Check for any predicate */
472
					if (check_assert(pred, r, 1)) {
473
						c = "1";
474
					}
475
					q->next = r->next;
476
					r->next = NULL;
477
				}
478
				free_tok_list(r);
479
				q->tok = lex_integer_Hlit;
480
				q->pp_data.text = ustrlit(c);
481
			}
482
			q = q->next;
2 7u83 483
		}
484
 
6 7u83 485
		/* Macro expand the line */
486
		q = expand_tok_list(p);
487
		free_tok_list(p);
488
		p = q;
2 7u83 489
 
6 7u83 490
		/* Check for any remaining identifiers */
491
		while (q != NULL) {
492
			if (q->tok == lex_identifier) {
493
				HASHID nm = q->pp_data.id.hash;
494
				IDENTIFIER id = DEREF_id(hashid_id(nm));
495
				unsigned tag = TAG_id(id);
496
				if (tag == id_obj_macro_tag ||
497
				    tag == id_func_macro_tag) {
498
					/* Allow for unexpanded macros */
499
					id = DEREF_id(id_alias(id));
500
					tag = TAG_id(id);
501
				}
502
				if (tag == id_keyword_tag) {
503
					int u = (int)DEREF_ulong(id_no(id));
504
					if (u == lex_true || u == lex_false) {
505
						/* Preserve boolean literals */
506
						tag = id_iso_keyword_tag;
507
					}
508
				}
509
				if (tag == id_iso_keyword_tag) {
510
					/* Allow for ISO keywords */
511
					int u = (int)DEREF_ulong(id_no(id));
512
					int v = primary_form(u);
513
					if (v != u) {
514
						ERROR err =
515
						    ERR_lex_digraph_iso(nm, v);
516
						report(preproc_loc, err);
517
					}
518
					q->tok = v;
519
				} else {
520
					unsigned c = check_macro(nm, 0);
521
					if (c & PP_TOKEN) {
522
						/* Preserve token identifiers */
523
						c &= PP_COND_MASK;
524
						if (c == PP_UNRESOLVED) {
525
							cond = PP_UNRESOLVED;
526
						}
527
					} else {
528
						/* Replace other identifiers by
529
						 * 0 */
530
						ERROR err;
531
						if (EQ_hashid(nm, def)) {
532
							/* Shouldn't have
533
							 * defined */
534
							err = ERR_cpp_cond_def_replace();
535
							if (!IS_NULL_err(err)) {
536
								report(preproc_loc, err);
537
							}
538
						}
539
						/* QUERY: what about true and false? */
540
						err = ERR_cpp_cond_zero(nm);
541
						if (!IS_NULL_err(err)) {
542
							report(preproc_loc,
543
							       err);
544
						}
545
						q->tok = lex_integer_Hlit;
546
						q->pp_data.text = ustrlit("0");
547
					}
548
				}
549
			}
550
			q = q->next;
2 7u83 551
		}
6 7u83 552
 
553
		/* Parse the line for a constant expression */
554
		save_state(&ps, 0);
555
		init_parser(p);
556
		in_hash_if_exp++;
557
		crt_loc = preproc_loc;
558
		crt_line_changed = 1;
559
		ADVANCE_LEXER;
560
		if (cond == PP_UNRESOLVED) {
561
			/* Unresolved tokens when preprocessing */
562
			ASSERT(preproc_only);
563
			/* EMPTY */
2 7u83 564
		} else {
6 7u83 565
			/* Parse condition */
566
			cond = PP_FALSE;
567
			parse_nat(&e);
568
			if (crt_lex_token != lex_newline &&
569
			    !have_syntax_error) {
570
				/* Should have reached the end of the line */
571
				ERROR err = ERR_lex_parse(crt_token);
572
				err = concat_error(err, ERR_cpp_end(dir));
573
				report(preproc_loc, err);
2 7u83 574
			}
6 7u83 575
		}
576
		restore_state(&ps);
577
 
578
		/* Check the result expression */
579
		if (!IS_NULL_exp(e)) {
580
			/* Evaluate the expression */
581
			ERROR err = NULL_err;
582
			IGNORE make_nat_exp(e, &err);
583
			e = convert_boolean(e, exp_paren_tag, &err);
584
			if (!IS_NULL_err(err)) {
585
				err = concat_error(err,
586
						   ERR_cpp_cond_if_const(dir));
587
				report(preproc_loc, err);
588
				cond = PP_FALSE;
589
			} else {
590
				unsigned b = eval_const_cond(e);
591
				if (b == BOOL_TRUE) {
592
					cond = PP_TRUE;
593
				} else if (b == BOOL_FALSE) {
594
					cond = PP_FALSE;
595
				} else {
596
					cond = PP_UNRESOLVED;
597
				}
2 7u83 598
			}
599
		}
600
 
6 7u83 601
		/* Restore the parser */
602
		p = restore_parser();
603
		if (cond == PP_UNRESOLVED) {
604
			/* Save target dependent conditions */
605
			if (preproc_only) {
606
				/* Patch crt_token with tokens comprising
607
				 * condition */
608
				p = clean_tok_list(p);
609
				patch_preproc_dir(p);
610
				p = NULL;
611
			} else {
612
				/* Store condition in crt_hash_if_exp */
613
				report(preproc_loc, ERR_cpp_cond_if_ti(dir));
614
				crt_hash_if_exp = e;
615
			}
2 7u83 616
		}
6 7u83 617
		free_tok_list(p);
618
		in_hash_if_exp--;
2 7u83 619
	}
6 7u83 620
	if (in_preproc_dir) {
621
		IGNORE skip_to_end();
2 7u83 622
	}
6 7u83 623
	return(cond);
2 7u83 624
}
625
 
626
 
627
/*
628
    READ A DEFINED COMPILATION CONDITION
629
 
630
    This routine reads the macro identifier following a '#ifdef' or
631
    '#ifndef' preprocessing directive.  It returns a value indicating
632
    whether the macro is defined or not.  The argument act is false to
633
    indicate that the directive is being skipped, prev is as in
634
    read_preproc_dir.
635
*/
636
 
6 7u83 637
static unsigned
638
read_if_def(int act, int dir, int prev)
2 7u83 639
{
6 7u83 640
	unsigned cond;
641
	if (act) {
642
		int t = read_token();
643
		update_column();
644
		if (in_preproc_dir) {
645
			preproc_loc = crt_loc;
646
		}
647
		if (t == lex_identifier) {
648
			HASHID macro = token_hashid;
649
			cond = check_macro(macro, 1);
650
			cond &= PP_COND_MASK;
651
			if (prev == lex_included) {
652
				/* Protection macro begins '#ifndef macro' */
653
				protection_macro(macro, prev, dir);
654
			}
655
			if (in_preproc_dir && skip_to_end()) {
656
				report(preproc_loc, ERR_cpp_end(dir));
657
			}
658
		} else {
659
			report(preproc_loc, ERR_cpp_cond_ifdef_id(dir));
660
			cond = PP_FALSE;
661
		}
2 7u83 662
	} else {
6 7u83 663
		cond = PP_SKIP;
2 7u83 664
	}
6 7u83 665
	if (in_preproc_dir) {
666
		IGNORE skip_to_end();
667
	}
668
	return(cond);
2 7u83 669
}
670
 
671
 
672
/*
673
    DEAL WITH CONDITIONAL COMPILATIONS
674
 
675
    This routine deals with the various conditional compilation preprocessing
676
    directives.  dir gives the directive identifier and c indicates the
677
    associated condition.  The skipping of unused code is incorporated into
678
    this routine.  The routine returns lex_ignore_token for simple '#if' and
679
    '#elif' directives, lex_end_condition for simple '#else' and '#endif'
680
    directives, and one of the values lex_hash_Hif, lex_hash_Helif,
681
    lex_hash_Helse and lex_hash_Hendif for target dependent conditions.
682
*/
683
 
6 7u83 684
static int
685
read_if(int dir, unsigned c, int prev)
2 7u83 686
{
6 7u83 687
	unsigned cond = c;
688
	int ret = lex_ignore_token;
2 7u83 689
 
6 7u83 690
	if (dir == lex_if || dir == lex_ifdef || dir == lex_ifndef) {
691
		/* Deal with '#if', '#ifdef' and '#ifndef' */
692
		if (cond == PP_UNRESOLVED) {
693
			ret = lex_hash_Hif;
694
		}
695
		if (prev != lex_included && preproc_depth == 0) {
696
			/* Can't have second '#if' in protection macro */
697
			protection_macro(NULL_hashid, lex_ignore_token, dir);
698
		}
699
		PUSH_unsigned(cond, preproc_stack);
700
		PUSH_loc(preproc_loc, loc_stack);
701
		IGNORE incr_value(OPT_VAL_hash_if_depth);
702
		preproc_depth++;
2 7u83 703
 
6 7u83 704
	} else {
705
		/* Get current condition for other directives */
706
		LOCATION loc;
707
		unsigned crt_cond;
708
		POP_unsigned(cond, preproc_stack);
709
		decr_value(OPT_VAL_hash_if_depth);
710
		preproc_depth--;
711
		/* Don't pop location yet */
712
		if (cond == PP_END) {
713
			/* No matching '#if' */
714
			ERROR err = ERR_cpp_cond_if_match(dir, lex_if);
715
			report(preproc_loc, err);
716
			PUSH_unsigned(cond, preproc_stack);
717
			PUSH_loc(preproc_loc, loc_stack);
718
			IGNORE incr_value(OPT_VAL_hash_if_depth);
719
			preproc_depth++;
720
			cond = c;
721
		}
722
		crt_cond = (cond & PP_COND_MASK);
723
		ret = lex_end_condition;
2 7u83 724
 
6 7u83 725
		if (dir == lex_endif) {
726
			/* Deal with '#endif' */
727
			if (crt_cond == PP_UNRESOLVED) {
728
				ret = lex_hash_Hendif;
729
				cond = PP_TRUE;
730
			} else if (crt_cond == PP_SKIP) {
731
				cond = PP_SKIP;
732
			} else {
733
				cond = PP_TRUE;
734
			}
735
			POP_loc(loc, loc_stack);
736
			UNUSED(loc);
2 7u83 737
 
6 7u83 738
		} else if (dir == lex_else) {
739
			/* Deal with '#else' */
740
			PTR(LOCATION)ploc;
741
			ploc = HEAD_list(LIST_stack(loc_stack));
742
			if (cond & PP_HAVE_ELSE) {
743
				/* Duplicate '#else' directives */
744
				ERROR err = ERR_cpp_cond_else_dup(dir, dir,
745
								  ploc);
746
				report(preproc_loc, err);
747
			}
748
			if (crt_cond == PP_UNRESOLVED)ret = lex_hash_Helse;
749
			cond = (negate_cond(crt_cond) | PP_HAVE_ELSE);
750
			PUSH_unsigned(cond, preproc_stack);
751
			COPY_loc(ploc, preproc_loc);
752
			if (preproc_depth == 0) {
753
				/* Can't have '#else' in protection macro */
754
				protection_macro(NULL_hashid, lex_ignore_token,
755
						 dir);
756
			}
757
			IGNORE incr_value(OPT_VAL_hash_if_depth);
758
			preproc_depth++;
2 7u83 759
 
760
		} else {
6 7u83 761
			/* Deal with '#elif' (fairly tricky) */
762
			unsigned new_cond;
763
			PTR(LOCATION)ploc;
764
			ploc = HEAD_list(LIST_stack(loc_stack));
765
			if (cond & PP_HAVE_ELSE) {
766
				/* '#elif' after '#else' */
767
				ERROR err = ERR_cpp_cond_else_dup(dir, lex_else,
768
								  ploc);
769
				report(preproc_loc, err);
770
			}
771
			if (crt_cond == PP_TRUE || crt_cond == PP_PAST) {
772
				/* A previous '#if' or '#elif' was true */
773
				ret = lex_ignore_token;
774
				IGNORE read_if_exp(0, dir);
775
				c = PP_PAST;
776
				new_cond = (c | PP_HAVE_ELIF);
777
			} else if (crt_cond == PP_FALSE) {
778
				/* All previous '#if's and '#elif's were
779
				 * false */
780
				c = read_if_exp(1, dir);
781
				if (c == PP_UNRESOLVED) {
782
					ret = lex_hash_Hif;
783
				}
784
				new_cond = (c | PP_HAVE_ELIF);
785
			} else if (crt_cond == PP_UNRESOLVED) {
786
				/* Unresolved existing condition */
787
				c = read_if_exp(1, dir);
788
				if (c == PP_FALSE) {
789
					/* Overall condition is still
790
					 * unresolved */
791
					ret = lex_ignore_token;
792
					new_cond = (crt_cond | PP_HAVE_ELIF);
793
				} else if (c == PP_TRUE) {
794
					/* This terminates the conditional */
795
					ret = lex_hash_Hendif;
796
					new_cond = (c | PP_HAVE_ELIF);
797
				} else {
798
					/* A second unresolved condition */
799
					ret = lex_hash_Helif;
800
					new_cond = (c | PP_HAVE_ELIF);
801
				}
802
			} else {
803
				/* Skip this directive */
804
				ret = lex_ignore_token;
805
				c = read_if_exp(0, dir);
806
				new_cond = (c | PP_HAVE_ELIF);
807
			}
808
			PUSH_unsigned(new_cond, preproc_stack);
809
			COPY_loc(ploc, preproc_loc);
810
			if (preproc_depth == 0) {
811
				/* Can't have '#elif' in protection macro */
812
				protection_macro(NULL_hashid, lex_ignore_token,
813
						 dir);
814
			}
815
			IGNORE incr_value(OPT_VAL_hash_if_depth);
816
			preproc_depth++;
817
			cond = c;
2 7u83 818
		}
819
	}
6 7u83 820
	ASSERT(!in_preproc_dir);
2 7u83 821
 
6 7u83 822
	/* Step over any unused code */
823
	cond &= PP_COND_MASK;
824
	if (cond == PP_FALSE || cond == PP_PAST || cond == PP_SKIP) {
825
		for (;;) {
826
			int t;
827
			unsigned long sp = skip_white(1);
828
			in_preproc_dir = 1;
829
			t = read_token();
830
			update_column();
831
			if (in_preproc_dir) {
832
				preproc_loc = crt_loc;
2 7u83 833
			}
6 7u83 834
			if (t == lex_hash_H2) {
835
				t = get_digraph(t);
2 7u83 836
			}
6 7u83 837
			if (t == lex_hash_H1) {
838
				/* Scan any nested preprocessing directives */
839
				int p;
840
				unsigned long sp2 = skip_white(0);
841
				update_column();
842
				p = read_preproc_dir(0, lex_ignore_token);
843
				switch (p) {
844
				case lex_hash_Hif:
845
				case lex_hash_Helif:
846
				case lex_hash_Helse:
847
				case lex_hash_Hendif:
848
				case lex_end_condition: {
849
					/* These terminate the current
850
					 * condition */
851
					if (sp & (WHITE_SPACE |
852
						  WHITE_ESC_NEWLINE)) {
853
						report(preproc_loc,
854
						       ERR_cpp_indent());
855
					}
856
					if (sp2 & (WHITE_SPACE |
857
						   WHITE_ESC_NEWLINE)) {
858
						report(preproc_loc,
859
						       ERR_cpp_indent_dir());
860
					}
861
					in_preproc_dir = 0;
862
					return(p);
863
				}
864
				}
865
			} else if (t == lex_eof) {
866
				if (sp & (WHITE_SPACE | WHITE_ESC_NEWLINE)) {
867
					report(crt_loc, ERR_lex_phases_eof());
868
				}
869
				break;
870
			} else {
871
				if (in_preproc_dir)IGNORE skip_to_end();
872
			}
2 7u83 873
		}
874
	}
6 7u83 875
	in_preproc_dir = 0;
876
	return(ret);
2 7u83 877
}
878
 
879
 
880
/*
881
    PATCH TARGET DEPENDENT CONDITIONALS
882
 
883
    Any list of statements in a target dependent conditional are treated
884
    as if they comprised a compound statement.  In particular any variables
885
    declared within the conditional are only in scope inside that condition.
886
    The neatest way to do this is for the preprocessor to patch the necessary
887
    open and close braces into the parser input.  This is the purpose of
888
    this routine.
889
*/
890
 
6 7u83 891
int
892
patch_cond(int t, int dir)
2 7u83 893
{
6 7u83 894
	HASHID nm;
895
	PPTOKEN *p;
896
	IDENTIFIER id;
2 7u83 897
 
6 7u83 898
	/* Compilation action */
899
	if (!preproc_only) {
900
		switch (t) {
901
		case lex_hash_Hif:
902
			/* Create '#if {' */
903
			p = patch_tokens(1);
904
			p->tok = lex_open_Hbrace_H1;
905
			break;
906
		case lex_hash_Helif:
907
		case lex_hash_Helse:
908
			/* Create '} #elif {' and '} #else {' */
909
			p = patch_tokens(2);
910
			p->tok = t;
911
			token_parts(t, p);
912
			p->next->tok = lex_open_Hbrace_H1;
913
			t = lex_close_Hbrace_H1;
914
			break;
915
		case lex_hash_Hendif:
916
			/* Create '} #endif' */
917
			p = patch_tokens(1);
918
			p->tok = t;
919
			t = lex_close_Hbrace_H1;
920
			break;
921
		}
922
		return(t);
2 7u83 923
	}
924
 
6 7u83 925
	/* Preprocessing action */
926
	id = token_macro;
927
	if (IS_NULL_id(id)) {
928
		return(t);
2 7u83 929
	}
6 7u83 930
	nm = DEREF_hashid(id_name(id));
931
	switch (t) {
2 7u83 932
 
6 7u83 933
	case lex_hash_Hif:
934
		if (dir == lex_ifdef) {
935
			/* Create '#if defined x' */
936
			p = patch_tokens(2);
937
			p->tok = lex_identifier,
938
			    p->pp_data.id.hash = KEYWORD(lex_defined);
939
			p->next->tok = lex_identifier,
940
			    p->next->pp_data.id.hash = nm;
941
			p->next->pp_data.id.use = id;
942
		} else if (dir == lex_ifndef) {
943
			/* Create '#if !defined x' */
944
			p = patch_tokens(3);
945
			p->tok = lex_not_H1;
946
			p->next->tok = lex_identifier,
947
			    p->next->pp_data.id.hash = KEYWORD(lex_defined);
948
			p->next->pp_space = 0;
949
			p->next->next->tok = lex_identifier,
950
			    p->next->next->pp_data.id.hash = nm;
951
			p->next->next->pp_data.id.use = id;
2 7u83 952
		}
6 7u83 953
		break;
954
 
955
	case lex_hash_Hop:
956
		/* Create '#define x ...' or '#undef x' */
957
		if (dir == lex_define) {
958
			/* Patch in macro definition */
959
			PPTOKEN *q = NULL;
960
			unsigned tag = TAG_id(id);
961
			if (tag == id_obj_macro_tag) {
962
				q = DEREF_pptok(id_obj_macro_defn(id));
963
			} else if (tag == id_func_macro_tag) {
964
				q = DEREF_pptok(id_func_macro_defn(id));
2 7u83 965
			}
6 7u83 966
			q = expand_tok_list(q);
967
			q = clean_tok_list(q);
968
			patch_preproc_dir(q);
969
			if (tag == id_func_macro_tag) {
970
				unsigned n;
971
				LIST(HASHID)pars;
972
				pars = DEREF_list(id_func_macro_params(id));
973
				n = DEREF_unsigned(id_func_macro_no_params(id));
974
				p = patch_tokens((int)(2 * n + 2));
975
				p->tok = lex_open_Hround;
976
				p->pp_space = 0;
977
				p->next->tok = lex_close_Hround;
978
				p->next->pp_space = 0;
979
				while (!IS_NULL_list(pars)) {
980
					HASHID par =
981
					    DEREF_hashid(HEAD_list(pars));
982
					pars = TAIL_list(pars);
983
					p = p->next;
984
					p->tok = lex_identifier;
985
					p->pp_data.id.hash = par;
986
					p->pp_space = WHITE_SPACE;
987
					p = p->next;
988
					if (IS_NULL_list(pars)) {
989
						p->tok = lex_close_Hround;
990
						p->pp_space = WHITE_SPACE;
991
					} else {
992
						p->tok = lex_comma;
993
						p->pp_space = 0;
994
					}
995
				}
996
			}
2 7u83 997
		}
6 7u83 998
		p = patch_tokens(2);
999
		p->tok = lex_identifier;
1000
		p->pp_data.id.hash = KEYWORD(dir);
1001
		p->pp_space = 0;
1002
		p->next->tok = lex_identifier,
1003
		    p->next->pp_data.id.hash = nm;
1004
		p->next->pp_data.id.use = id;
1005
		break;
2 7u83 1006
	}
6 7u83 1007
	return(t);
2 7u83 1008
}
1009
 
1010
 
1011
/*
1012
    READ AN INCLUDE DIRECTIVE
1013
 
1014
    This routine processes a '#include' or similar directive.  This consists
1015
    of just a header name or a sequence of tokens which expand to a header
1016
    name.  If act is true then the actual inclusion is initialised.
1017
    The name of the preprocessing directive, dir, is passed in for the
1018
    purposes of error reporting.  The routine returns lex_included to
1019
    indicate that control has passed to the new file.
1020
*/
1021
 
6 7u83 1022
int
1023
read_include(int act, int dir)
2 7u83 1024
{
6 7u83 1025
	int ret = lex_ignore_token;
1026
	if (act) {
1027
		string s;
1028
		character c;
1029
		int end = 0;
1030
		int next = 0;
1031
		int legal = 1;
1032
		int import = 0;
1033
		character quote = 0;
2 7u83 1034
 
6 7u83 1035
		/* Look ahead for start of header name */
1036
		if (dir == lex_import) {
1037
			import = 1;
1038
		}
1039
		if (dir == lex_include_Hnext) {
1040
			next = 1;
1041
		}
1042
		IGNORE skip_white(0);
1043
		if (peek_char(char_less, &legal)) {
1044
			quote = char_greater;
1045
		} else if (peek_char(char_quote, &legal)) {
1046
			quote = char_quote;
1047
		} else if (dir == lex_pragma) {
1048
			if (peek_char(char_open_square, &legal)) {
1049
				quote = char_close_square;
1050
				next = 1;
1051
			}
1052
		}
1053
		update_column();
2 7u83 1054
 
6 7u83 1055
		if (quote) {
1056
			/* Read simple header name */
1057
			int e = read_string((int)quote, 0);
1058
			if (e != lex_eof) {
1059
				if (in_preproc_dir) {
1060
					end = skip_to_end();
1061
				}
1062
			}
1063
			s = token_buff.start;
1064
		} else {
1065
			/* Expand complex header name */
1066
			PPTOKEN *p = read_line(lex_ignore_token,
1067
					       lex_ignore_token);
1068
			PPTOKEN *q = expand_tok_list(p);
1069
			IGNORE quote_tok_list(q, 0, char_quote);
1070
			s = token_buff.start;
2 7u83 1071
 
6 7u83 1072
			/* Check first character */
1073
			c = s[0];
1074
			if (c == char_less) {
1075
				quote = char_greater;
1076
			} else if (c == char_quote) {
1077
				quote = char_quote;
1078
			} else if (dir == lex_pragma && c == char_open_square) {
1079
				quote = char_close_square;
1080
				next = 1;
1081
			} else {
1082
				report(preproc_loc, ERR_cpp_include_bad());
1083
				act = 0;
1084
			}
2 7u83 1085
 
6 7u83 1086
			/* Scan header name */
1087
			if (quote) {
1088
				string t = ++s;
1089
				for (;;) {
1090
					if (*t == quote) {
1091
						*t = 0;
1092
						if (t + 1 != token_buff.posn) {
1093
							end = 1;
1094
						}
1095
						break;
1096
					}
1097
					if (t == token_buff.posn) {
1098
						/* End of buffer reached */
1099
						report(preproc_loc,
1100
						       ERR_cpp_include_incompl());
1101
						break;
1102
					}
1103
					t++;
1104
				}
1105
			}
1106
			free_tok_list(p);
1107
			free_tok_list(q);
2 7u83 1108
		}
6 7u83 1109
		if (end) {
1110
			report(preproc_loc, ERR_cpp_end(dir));
2 7u83 1111
		}
6 7u83 1112
		in_preproc_dir = 0;
1113
		if (act) {
1114
			/* Check header name */
1115
			string t = s;
1116
			while (c = *(t++), c != 0) {
1117
				if (c == char_quote ||
1118
				    c == char_single_quote ||
1119
				    c == char_backslash ||
1120
				    (c == char_slash && *t == char_asterix) ||
1121
				    (c == char_slash && *t == char_slash)) {
1122
					report(preproc_loc,
1123
					       ERR_cpp_include_undef(s));
1124
					break;
1125
				}
1126
			}
1127
			if (start_include(s, (int)quote, import, next)) {
1128
				/* Control passed to new file */
1129
				ret = lex_included;
1130
			}
1131
		}
1132
	} else {
1133
		/* Ignore rest of line */
1134
		if (in_preproc_dir)IGNORE skip_to_end();
2 7u83 1135
	}
6 7u83 1136
	return(ret);
2 7u83 1137
}
1138
 
1139
 
1140
/*
1141
    CHECK THAT TWO PREPROCESSING TOKENS ARE EQUAL
1142
 
1143
    This routine checks whether the lists of preprocessing tokens p and q
1144
    are identical.  It returns 2 if they are equal including preceeding
1145
    white spaces, 1 if they are otherwise equal, and 0 otherwise.
1146
*/
1147
 
6 7u83 1148
static int
1149
eq_pptok(PPTOKEN *p, PPTOKEN *q)
2 7u83 1150
{
6 7u83 1151
	int eq = 2;
1152
	while (p && q) {
1153
		int t1 = p->tok;
1154
		int t2 = q->tok;
1155
		if (t1 != t2) {
1156
			return(0);
1157
		}
1158
		if (p->pp_space != q->pp_space) {
1159
			eq = 1;
1160
		}
1161
		switch (t1) {
1162
		case lex_identifier: {
1163
			/* Check identifiers */
1164
			HASHID n1 = p->pp_data.id.hash;
1165
			HASHID n2 = q->pp_data.id.hash;
1166
			if (!EQ_hashid(n1, n2)) {
1167
				return(0);
1168
			}
1169
			break;
1170
		}
1171
		case lex_integer_Hlit: {
1172
			/* Check integer and floating-point literals */
1173
			string s1 = p->pp_data.text;
1174
			string s2 = q->pp_data.text;
1175
			if (!ustreq(s1, s2)) {
1176
				return(0);
1177
			}
1178
			break;
1179
		}
1180
		case lex_char_Hlit:
1181
		case lex_string_Hlit:
1182
		case lex_wchar_Hlit:
1183
		case lex_wstring_Hlit: {
1184
			/* Check string and characters literals */
1185
			string s1 = p->pp_data.str.start;
1186
			string s2 = q->pp_data.str.start;
1187
			gen_size n1 = (gen_size)(p->pp_data.str.end - s1);
1188
			gen_size n2 = (gen_size)(q->pp_data.str.end - s2);
1189
			if (n1 != n2) {
1190
				return(0);
1191
			}
1192
			if (xumemcmp(s1, s2, n1)!= 0) {
1193
				return(0);
1194
			}
1195
			break;
1196
		}
1197
		case lex_unknown: {
1198
			/* Check unknown characters */
1199
			string s1 = p->pp_data.buff;
1200
			string s2 = q->pp_data.buff;
1201
			gen_size n1 = MULTI_WIDTH;
1202
			if (xumemcmp(s1, s2, n1)!= 0) {
1203
				return(0);
1204
			}
1205
			break;
1206
		}
1207
		case lex_macro_Harg: {
1208
			/* Check macro parameter applications */
1209
			unsigned long m1 = p->pp_data.par.no;
1210
			unsigned long m2 = q->pp_data.par.no;
1211
			if (m1 != m2) {
1212
				return(0);
1213
			}
1214
			break;
1215
		}
1216
		}
1217
		p = p->next;
1218
		q = q->next;
2 7u83 1219
	}
6 7u83 1220
	if (p || q) {
1221
		return(0);
1222
	}
1223
	return(eq);
2 7u83 1224
}
1225
 
1226
 
1227
/*
1228
    CHECK CONSISTENCY OF TWO MACRO DEFINITIONS
1229
 
1230
    This routine checks that a definition of the macro given by id_new is
1231
    consistent with the previous definition, id_old.  It returns an error
1232
    message reporting on the level of consistency.
1233
*/
1234
 
6 7u83 1235
static ERROR
1236
check_macro_redef(IDENTIFIER id_new, IDENTIFIER id_old)
2 7u83 1237
{
6 7u83 1238
	int defn_ok;
1239
	int pars_ok = 1;
1240
	ERROR err = NULL_err;
1241
	PTR(LOCATION)loc_old;
1242
	PPTOKEN *defn_new, *defn_old;
1243
	unsigned tag_new = TAG_id(id_new);
1244
	unsigned tag_old = TAG_id(id_old);
1245
	DECL_SPEC ds_old = DEREF_dspec(id_storage(id_old));
2 7u83 1246
 
6 7u83 1247
	/* Check on old macro definition */
1248
	loc_old = id_loc(id_old);
1249
	if ((ds_old & dspec_builtin) && crt_file_type == 0) {
1250
		/* Built-in macro redefined */
1251
		err = ERR_cpp_predef_redef(id_old);
1252
	}
2 7u83 1253
 
6 7u83 1254
	/* Macro types must agree */
1255
	if (tag_new != tag_old) {
1256
		ERROR e = ERR_cpp_replace_redef_bad(id_old, loc_old);
1257
		err = concat_error(err, e);
1258
		return(err);
1259
	}
2 7u83 1260
 
6 7u83 1261
	if (tag_new == id_obj_macro_tag) {
1262
		/* Find the definitions for object-like macros */
1263
		defn_new = DEREF_pptok(id_obj_macro_defn(id_new));
1264
		defn_old = DEREF_pptok(id_obj_macro_defn(id_old));
2 7u83 1265
 
6 7u83 1266
	} else {
1267
		/* Check parameter lists for function-like macros */
1268
		unsigned no_pars_new, no_pars_old;
1269
		LIST(HASHID)pars_new, pars_old;
1270
		pars_new = DEREF_list(id_func_macro_params(id_new));
1271
		pars_old = DEREF_list(id_func_macro_params(id_old));
1272
		no_pars_new = DEREF_unsigned(id_func_macro_no_params(id_new));
1273
		no_pars_old = DEREF_unsigned(id_func_macro_no_params(id_old));
2 7u83 1274
 
6 7u83 1275
		if (no_pars_new != no_pars_old) {
1276
			/* Number of parameters must match */
1277
			ERROR e = ERR_cpp_replace_redef_bad(id_old, loc_old);
1278
			err = concat_error(err, e);
1279
			return(err);
1280
		}
1281
 
1282
		while (!IS_NULL_list(pars_new)) {
1283
			/* Check that parameter names match */
1284
			HASHID p_new = DEREF_hashid(HEAD_list(pars_new));
1285
			HASHID p_old = DEREF_hashid(HEAD_list(pars_old));
1286
			if (!EQ_hashid(p_new, p_old)) {
1287
				/* Just clear pars_ok if they don't */
1288
				pars_ok = 0;
1289
				break;
1290
			}
1291
			pars_new = TAIL_list(pars_new);
1292
			pars_old = TAIL_list(pars_old);
1293
		}
1294
 
1295
		/* Find the definitions for function-like macros */
1296
		defn_new = DEREF_pptok(id_func_macro_defn(id_new));
1297
		defn_old = DEREF_pptok(id_func_macro_defn(id_old));
2 7u83 1298
	}
1299
 
6 7u83 1300
	/* Check that the definitions match */
1301
	defn_ok = eq_pptok(defn_new, defn_old);
1302
	if (defn_ok == 0) {
1303
		/* Inconsistent redefinition */
1304
		ERROR e = ERR_cpp_replace_redef_bad(id_old, loc_old);
1305
		err = concat_error(err, e);
1306
		return(err);
1307
	} else if (defn_ok == 1) {
1308
		/* Consistent redefinition up to white space */
1309
		ERROR e = ERR_cpp_replace_redef_space(id_old, loc_old);
1310
		e = set_severity(e, OPT_macro_redef, -1);
1311
		err = concat_error(err, e);
2 7u83 1312
	}
1313
 
6 7u83 1314
	/* Prepare final error */
1315
	if (pars_ok) {
1316
		/* Consistent macro redefinition */
1317
		if (IS_NULL_err(err)) {
1318
			err = ERR_cpp_replace_redef_ok(id_old, loc_old);
1319
		}
1320
	} else {
1321
		/* Consistent redefinition up to parameter names */
1322
		ERROR e = ERR_cpp_replace_redef_weak(id_old, loc_old);
1323
		e = set_severity(e, OPT_macro_redef, -1);
1324
		err = concat_error(err, e);
2 7u83 1325
	}
6 7u83 1326
	return(err);
2 7u83 1327
}
1328
 
1329
 
1330
/*
1331
    FREE A MACRO DEFINITION
1332
 
1333
    This routine frees the macro definition given by the identifier id.
1334
    It returns the previous definition of id.
1335
*/
1336
 
6 7u83 1337
static IDENTIFIER
1338
free_macro_defn(IDENTIFIER id)
2 7u83 1339
{
6 7u83 1340
	PPTOKEN *defn;
1341
	IDENTIFIER prev = DEREF_id(id_alias(id));
1342
	if (IS_id_obj_macro(id)) {
1343
		defn = DEREF_pptok(id_obj_macro_defn(id));
1344
		COPY_pptok(id_obj_macro_defn(id), NULL);
1345
	} else {
1346
		defn = DEREF_pptok(id_func_macro_defn(id));
1347
		COPY_pptok(id_func_macro_defn(id), NULL);
1348
	}
1349
	free_tok_list(defn);
1350
	return(prev);
2 7u83 1351
}
1352
 
1353
 
1354
/*
1355
    READ A DEFINE DIRECTIVE
1356
 
1357
    This routine processes a '#define' directive.  This consists of a macro
1358
    identifier, and optional list of macro parameters, and a list of token
1359
    comprising the macro definition.  Note that the list of parameters is
1360
    built up in the reverse order to that in which they appear in the file
1361
    (also see read_macro_args).  The routine returns true if the directive
1362
    is a macro definition.
1363
*/
1364
 
6 7u83 1365
static int
1366
read_define(void)
2 7u83 1367
{
6 7u83 1368
	HASHID macro;
1369
	PPTOKEN *defn;
1370
	int legal = 1;
1371
	IDENTIFIER id;
1372
	IDENTIFIER tok;
1373
	IDENTIFIER prev;
1374
	unsigned prev_def;
1375
	unsigned npars = 0;
1376
	int object_like = 0;
1377
	int ret = lex_ignore_token;
1378
	int first_tok = lex_ignore_token;
1379
	LIST(HASHID)pars = NULL_list(HASHID);
1380
	OPTION preproc_strings = option(OPT_preproc_old);
2 7u83 1381
 
6 7u83 1382
	/* Read the macro identifier */
1383
	int t = read_token();
1384
	update_column();
1385
	if (in_preproc_dir) {
1386
		preproc_loc = crt_loc;
2 7u83 1387
	}
6 7u83 1388
	if (t != lex_identifier) {
1389
		report(preproc_loc, ERR_cpp_replace_id(lex_define));
1390
		return(ret);
1391
	}
1392
	macro = token_hashid;
1393
	if (EQ_KEYWORD(macro, lex_defined)) {
1394
		/* Cannot define defined as a macro */
1395
		report(preproc_loc, ERR_cpp_predef_bad(macro, lex_define));
1396
	} else {
1397
		id = DEREF_id(hashid_id(macro));
1398
		if (IS_id_keyword(id) && !preproc_only) {
1399
			/* Warn about redefining keywords */
1400
			report(preproc_loc, ERR_cpp_predef_keyword(macro));
1401
		}
1402
	}
1403
	prev_def = check_macro(macro, 0);
1404
	tok = token_macro;
2 7u83 1405
 
6 7u83 1406
	/* Check for macro parameters */
1407
	if (peek_char(char_open_round, &legal)) {
1408
		PPTOKEN *p;
1409
		int err = 0;
1410
		int par_next = 2;
1411
		LIST(HASHID)lp;
1412
		unsigned long par_no = 1;
2 7u83 1413
 
6 7u83 1414
		/* Scan through definition looking for parameters */
1415
		update_column();
1416
		if (in_preproc_dir) {
1417
			preproc_loc = crt_loc;
1418
		}
1419
		while (t = read_token(), t != lex_close_Hround) {
1420
			update_column();
1421
			if (in_preproc_dir) {
1422
				preproc_loc = crt_loc;
1423
			}
1424
			if (t == lex_identifier) {
1425
				/* Identifiers are parameter names */
1426
				unsigned long mark;
1427
				HASHID par = token_hashid;
1428
				IGNORE check_macro(par, 0);
1429
				CONS_hashid(par, pars, pars);
2 7u83 1430
 
6 7u83 1431
				/* Mark name with parameter number */
1432
				mark = DEREF_ulong(hashid_hash(par));
1433
				if (mark >= HASH_SIZE) {
1434
					/* Parameter already marked */
1435
					ERROR e =
1436
					    ERR_cpp_replace_par_dup(par, macro);
1437
					report(preproc_loc, e);
1438
					mark %= HASH_SIZE;
1439
				}
1440
				mark += HASH_SIZE * par_no;
1441
				COPY_ulong(hashid_hash(par), mark);
1442
				if (!par_next) {
1443
					err = 1;
1444
				}
1445
				par_next = 0;
1446
				par_no++;
1447
			} else if (t == lex_comma) {
1448
				/* Commas separate parameters */
1449
				if (par_next) {
1450
					err = 1;
1451
				}
1452
				par_next = 1;
1453
			} else {
1454
				/* Anything else is an error */
1455
				first_tok = t;
1456
				err = 1;
1457
				break;
1458
			}
2 7u83 1459
		}
6 7u83 1460
		update_column();
1461
		if (in_preproc_dir) {
1462
			preproc_loc = crt_loc;
1463
		}
1464
		if (err || par_next == 1) {
1465
			/* Report any errors */
1466
			report(preproc_loc, ERR_cpp_replace_par_bad(macro));
1467
		}
2 7u83 1468
 
6 7u83 1469
		/* Allow for parameter expansion in strings */
1470
		if (preproc_strings) {
1471
			/* This causes strings not to be recognised */
1472
			set_char_lookup(char_quote, char_illegal);
1473
			set_char_lookup(char_single_quote, char_illegal);
1474
		}
2 7u83 1475
 
6 7u83 1476
		/* Read the macro definition for function-like macros */
1477
		defn = read_line(first_tok, lex_ignore_token);
1478
		if (defn)defn->pp_space = WHITE_SPACE;
2 7u83 1479
 
6 7u83 1480
		/* Restore string terminators */
1481
		if (preproc_strings) {
1482
			set_char_lookup(char_quote, char_quote);
1483
			set_char_lookup(char_single_quote, char_single_quote);
1484
		}
2 7u83 1485
 
6 7u83 1486
		/* Mark the macro parameters in the definition */
1487
		for (p = defn; p != NULL; p = p->next) {
1488
			int tk = p->tok;
1489
			if (tk == lex_identifier) {
1490
				HASHID par = p->pp_data.id.hash;
1491
				unsigned long mark =
1492
				    DEREF_ulong(hashid_hash(par));
1493
				if (mark >= HASH_SIZE) {
1494
					/* Parameters are identified by the
1495
					 * parameter number */
1496
					p->tok = lex_macro_Harg;
1497
					p->pp_data.par.hash = par;
1498
					p->pp_data.par.no = (mark / HASH_SIZE);
1499
				}
1500
			}
2 7u83 1501
		}
1502
 
6 7u83 1503
		/* Check for quoted parameters */
1504
		if (preproc_strings) {
1505
			defn = recognise_strings(defn, macro, 0);
1506
		}
2 7u83 1507
 
6 7u83 1508
		/* Check for '#' operators */
1509
		for (p = defn; p != NULL; p = p->next) {
1510
			int tk = p->tok;
1511
			if (tk == lex_hash_H2) {
1512
				tk = get_digraph(tk);
1513
			}
1514
			if (tk == lex_hash_H1) {
1515
				/* '#' should be followed by a parameter */
1516
				if (p->next == NULL ||
1517
				    p->next->tok != lex_macro_Harg) {
1518
					report(preproc_loc,
1519
					       ERR_cpp_stringize_par(macro));
1520
				} else {
1521
					p->tok = lex_hash_Hop;
1522
				}
1523
			}
2 7u83 1524
		}
6 7u83 1525
 
1526
		/* Clear the parameter marks */
1527
		for (lp = pars; !IS_NULL_list(lp); lp = TAIL_list(lp)) {
1528
			HASHID par = DEREF_hashid(HEAD_list(lp));
1529
			unsigned long mark = DEREF_ulong(hashid_hash(par));
1530
			mark %= HASH_SIZE;
1531
			COPY_ulong(hashid_hash(par), mark);
1532
			npars++;
1533
		}
1534
		pars = REVERSE_list(pars);
1535
 
1536
	} else {
1537
		/* Read the macro definition for object-like macros */
1538
		if (!legal) {
1539
			report(preproc_loc, ERR_cpp_space_replace());
1540
		}
1541
		defn = read_line(first_tok, lex_ignore_token);
1542
		object_like = 1;
2 7u83 1543
	}
1544
 
6 7u83 1545
	/* Check for '##' operators */
1546
	if (defn) {
1547
		PPTOKEN *p;
1548
		int tk = defn->tok;
1549
		if (tk == lex_hash_Hhash_H2) {
1550
			tk = get_digraph(tk);
1551
		}
1552
		if (tk == lex_hash_Hhash_H1) {
1553
			/* Definition can't start with '##' */
1554
			report(preproc_loc, ERR_cpp_concat_place(macro));
1555
		}
1556
		for (p = defn->next; p != NULL; p = p->next) {
1557
			tk = p->tok;
1558
			if (tk == lex_hash_Hhash_H2) {
1559
				tk = get_digraph(tk);
1560
			}
1561
			if (tk == lex_hash_Hhash_H1) {
1562
				if (p->next == NULL) {
1563
					/* Definition can't end with '##' */
1564
					report(preproc_loc,
1565
					       ERR_cpp_concat_place(macro));
1566
				} else {
1567
					p->tok = lex_hash_Hhash_Hop;
1568
				}
1569
			}
1570
		}
2 7u83 1571
	}
1572
 
6 7u83 1573
	/* Define the macro */
1574
	if (!IS_NULL_exp(crt_hash_cond)) {
1575
		report(preproc_loc, ERR_cpp_cond_if_macro(macro));
2 7u83 1576
	}
6 7u83 1577
	prev = DEREF_id(hashid_id(macro));
1578
	if (object_like) {
1579
		MAKE_id_obj_macro(macro, dspec_defn, NULL_nspace, preproc_loc,
1580
				  defn, id);
1581
	} else {
1582
		IGNORE check_value(OPT_VAL_macro_pars, (ulong)npars);
1583
		MAKE_id_func_macro(macro, dspec_defn, NULL_nspace, preproc_loc,
1584
				   defn, pars, npars, id);
1585
	}
1586
	COPY_id(id_alias(id), prev);
1587
	if (prev_def & PP_TOKEN) {
1588
		/* Allow for token definitions */
1589
		prev_def &= PP_COND_MASK;
1590
		if (prev_def == PP_UNRESOLVED) {
1591
			/* Can only happen when preprocessing */
1592
			token_macro = id;
1593
			ret = lex_hash_Hop;
2 7u83 1594
		} else {
6 7u83 1595
			int tokdef;
1596
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
1597
			COPY_dspec(id_storage(id), (ds | dspec_temp));
1598
			tokdef = define_token_macro(tok, id);
1599
			COPY_dspec(id_storage(id), ds);
1600
			if (tokdef) {
1601
				IGNORE free_macro_defn(id);
1602
				no_declarations++;
1603
				return(ret);
1604
			}
1605
			prev_def = PP_FALSE;
2 7u83 1606
		}
1607
	}
6 7u83 1608
	COPY_id(hashid_id(macro), id);
1609
	if (do_macro) {
1610
		/* Dump macro definition using current namespace */
1611
		COPY_nspace(id_parent(id), crt_namespace);
1612
		dump_declare(id, &preproc_loc, 1);
1613
		COPY_nspace(id_parent(id), NULL_nspace);
2 7u83 1614
	}
1615
 
6 7u83 1616
	/* Check consistency of previous definition */
1617
	if (prev_def == PP_TRUE) {
1618
		ERROR err;
1619
		if (option(OPT_macro_nest) == OPTION_DISALLOW) {
1620
			err = check_macro_redef(id, prev);
1621
			prev = free_macro_defn(prev);
1622
		} else {
1623
			PTR(LOCATION)loc = id_loc(prev);
1624
			err = ERR_cpp_replace_redef_nest(prev, loc);
1625
		}
1626
		if (!IS_NULL_err(err)) {
1627
			report(preproc_loc, err);
1628
		}
1629
		COPY_id(id_alias(id), prev);
2 7u83 1630
	} else {
6 7u83 1631
		IGNORE incr_value(OPT_VAL_macro_ids);
2 7u83 1632
	}
6 7u83 1633
	return(ret);
2 7u83 1634
}
1635
 
1636
 
1637
/*
1638
    READ AN UNDEFINE DIRECTIVE
1639
 
1640
    This routine processes a '#undef' directive.  This just consists of a
1641
    macro identifier.  The routine returns true if the macro represents
1642
    a token.
1643
*/
1644
 
6 7u83 1645
static int
1646
read_undef(void)
2 7u83 1647
{
6 7u83 1648
	/* Read the macro identifier */
1649
	unsigned def;
1650
	HASHID macro;
1651
	int ret = lex_ignore_token;
1652
	int t = read_token();
1653
	update_column();
1654
	if (in_preproc_dir) {
1655
		preproc_loc = crt_loc;
2 7u83 1656
	}
6 7u83 1657
	if (t != lex_identifier) {
1658
		report(preproc_loc, ERR_cpp_scope_id(lex_undef));
1659
		return(ret);
1660
	}
1661
	macro = token_hashid;
1662
	if (EQ_KEYWORD(macro, lex_defined)) {
1663
		/* Cannot undefine defined */
1664
		report(preproc_loc, ERR_cpp_predef_bad(macro, lex_undef));
1665
	}
2 7u83 1666
 
6 7u83 1667
	/* Undefine the macro if necessary */
1668
	def = check_macro(macro, 0);
1669
	if (def == PP_TRUE) {
1670
		/* Previously defined as macro */
1671
		IDENTIFIER prev = DEREF_id(hashid_id(macro));
1672
		DECL_SPEC ds = DEREF_dspec(id_storage(prev));
1673
		if ((ds & dspec_builtin) && crt_file_type == 0) {
1674
			report(preproc_loc, ERR_cpp_predef_undef(prev));
1675
		}
1676
		if (do_macro) {
1677
			dump_undefine(prev, &preproc_loc, 1);
1678
		}
1679
		prev = free_macro_defn(prev);
1680
		COPY_id(hashid_id(macro), prev);
1681
		decr_value(OPT_VAL_macro_ids);
1682
 
1683
	} else if (def & PP_TOKEN) {
1684
		/* Previously defined as token */
1685
		IDENTIFIER prev = token_macro;
1686
		def &= PP_COND_MASK;
1687
		if (def == PP_UNRESOLVED) {
1688
			/* Can only happen when preprocessing */
1689
			ret = lex_hash_Hop;
1690
		} else {
1691
			if (IS_id_function_etc(prev)) {
1692
				do {
1693
					DECL_SPEC ds =
1694
					    DEREF_dspec(id_storage(prev));
1695
					TYPE f = DEREF_type(id_function_etc_form(prev));
1696
					if (!IS_NULL_type(f) &&
1697
					    IS_type_token(f)) {
1698
						IDENTIFIER ext =
1699
						    DEREF_id(type_token_tok(f));
1700
						if (!IS_NULL_id(ext) &&
1701
						    IS_id_token(ext)) {
1702
							if (do_dump) {
1703
								dump_undefine(prev, &preproc_loc, 1);
1704
							}
1705
							f = NULL_type;
1706
							COPY_type(id_function_etc_form(prev), f);
1707
						}
1708
					}
1709
					ds &= ~dspec_token;
1710
					COPY_dspec(id_storage(prev), ds);
1711
					prev = DEREF_id(id_function_etc_over(prev));
1712
				} while (!IS_NULL_id(prev));
1713
			} else {
1714
				if (do_dump) {
1715
					dump_undefine(prev, &preproc_loc, 1);
1716
				}
1717
				remove_id(prev);
1718
			}
1719
		}
2 7u83 1720
	} else {
6 7u83 1721
		/* Not previously declared */
1722
		report(preproc_loc, ERR_cpp_scope_undef(macro));
2 7u83 1723
	}
1724
 
6 7u83 1725
	/* Check the rest of the directive */
1726
	if (in_preproc_dir && skip_to_end()) {
1727
		report(preproc_loc, ERR_cpp_end(lex_undef));
1728
	}
1729
	return(ret);
2 7u83 1730
}
1731
 
1732
 
1733
/*
1734
    READ A LINE DIRECTIVE
1735
 
1736
    This routine processes a '#line' or '#file' directive (as indicated
1737
    by dir).
1738
*/
1739
 
6 7u83 1740
static void
1741
read_location(int dir)
2 7u83 1742
{
6 7u83 1743
	/* Read the line */
1744
	PPTOKEN *p = read_line(lex_ignore_token, lex_ignore_token);
1745
	unsigned long ln = crt_loc.line;
1746
	string fn = DEREF_string(posn_file(crt_loc.posn));
1747
	unsigned long ln_old = ln;
1748
	string fn_old = fn;
2 7u83 1749
 
6 7u83 1750
	/* Macro expand the line */
1751
	PPTOKEN *q = expand_tok_list(p);
1752
	q = clean_tok_list(q);
1753
	if (q && q->tok == lex_integer_Hlit && dir == lex_line) {
1754
		/* Process '#line number string-opt' */
1755
		unsigned err = 0;
1756
		PPTOKEN *r = q->next;
1757
		ln = eval_line_digits(q->pp_data.text, &err);
1758
		if (ln != ln_old) {
1759
			crt_line_changed = 1;
1760
		}
1761
		if (err & 2) {
1762
			report(preproc_loc, ERR_cpp_line_float(dir));
1763
		}
1764
		if ((err & 1) || (ln == 0)) {
1765
			report(preproc_loc, ERR_cpp_line_range(dir));
1766
		}
1767
		if (r && r->tok == lex_string_Hlit) {
1768
			fn = r->pp_data.str.start;
1769
			if (!ustreq(fn, fn_old)) {
1770
				crt_file_changed = 1;
1771
				crt_line_changed = 1;
1772
			}
1773
			r = r->next;
1774
		}
1775
		if (r) {
1776
			report(preproc_loc, ERR_cpp_end(dir));
1777
		}
1778
	} else if (q && q->tok == lex_string_Hlit && dir == lex_file) {
1779
		/* Process '#file string' */
1780
		PPTOKEN *r = q->next;
1781
		fn = q->pp_data.str.start;
1782
		if (!ustreq(fn, fn_old)) {
1783
			crt_file_changed = 1;
1784
			crt_line_changed = 1;
1785
		}
1786
		if (r) {
1787
			report(preproc_loc, ERR_cpp_end(dir));
1788
		}
1789
	} else {
1790
		report(preproc_loc, ERR_cpp_line_bad(dir));
2 7u83 1791
	}
6 7u83 1792
	free_tok_list(p);
1793
	free_tok_list(q);
1794
	if (crt_line_changed) {
1795
		PTR(POSITION)posn = crt_loc.posn;
1796
		string d = DEREF_string(posn_dir(posn));
1797
		string input = DEREF_string(posn_input(posn));
1798
		unsigned long off = DEREF_ulong(posn_offset(posn));
1799
		unsigned long date = DEREF_ulong(posn_datestamp(posn));
1800
		PTR(LOCATION)from = DEREF_ptr(posn_from(posn));
1801
		off += (ln - ln_old);
1802
		posn = MAKE_ptr(SIZE_posn);
1803
		MAKE_posn(fn, input, fn, d, off, from, date, posn);
1804
		crt_loc.posn = posn;
2 7u83 1805
	}
6 7u83 1806
	crt_loc.line = ln;
1807
	crt_loc.column = 0;
1808
	return;
2 7u83 1809
}
1810
 
1811
 
1812
/*
1813
    READ AN ERROR DIRECTIVE
1814
 
1815
    This routine processes a '#error' or '#warning' directive (as indicated
1816
    by the error severity level sev).
1817
*/
1818
 
6 7u83 1819
static void
1820
read_error(int opt)
2 7u83 1821
{
6 7u83 1822
	ERROR err;
1823
	PPTOKEN *p = read_line(lex_ignore_token, lex_ignore_token);
1824
	IGNORE quote_tok_list(p, 0, char_quote);
1825
	err = ERR_cpp_error_msg(token_buff.start);
1826
	if (!IS_NULL_err(err)) {
1827
		err = set_severity(err, opt, 0);
1828
		report(preproc_loc, err);
1829
	}
1830
	free_tok_list(p);
1831
	return;
2 7u83 1832
}
1833
 
1834
 
1835
/*
1836
    READ AN IDENT DIRECTIVE
1837
 
1838
    This routine processes a '#ident' directive.
1839
*/
1840
 
6 7u83 1841
void
1842
read_ident(int dir)
2 7u83 1843
{
6 7u83 1844
	int t = read_token();
1845
	update_column();
1846
	if (in_preproc_dir) {
1847
		preproc_loc = crt_loc;
2 7u83 1848
	}
6 7u83 1849
	if (t == lex_string_Hlit) {
1850
		string s = token_buff.start;
1851
		unsigned long n = (unsigned long)(token_buff.posn - s);
1852
		compile_comment(s, n);
1853
		if (in_preproc_dir && skip_to_end()) {
1854
			report(preproc_loc, ERR_cpp_end(dir));
1855
		}
1856
	} else {
1857
		report(preproc_loc, ERR_pragma_cpp_ident(dir));
1858
	}
1859
	return;
2 7u83 1860
}
1861
 
1862
 
1863
/*
1864
    CREATE AN ASSERTION
1865
 
1866
    This routine looks up the assertion named pred, creating it if it does
1867
    not already exist.
1868
*/
1869
 
6 7u83 1870
IDENTIFIER
1871
make_assert(HASHID pred, int key)
2 7u83 1872
{
6 7u83 1873
	NAMESPACE ns = assert_namespace;
1874
	MEMBER mem = search_member(ns, pred, 1);
1875
	IDENTIFIER id = DEREF_id(member_id(mem));
1876
	if (IS_NULL_id(id)) {
1877
		/* Define assertion if not already defined */
1878
		MAKE_id_predicate(pred, dspec_none, ns, preproc_loc, id);
1879
		COPY_ulong(id_no(id), (unsigned long)key);
1880
		COPY_id(member_id(mem), id);
1881
	}
1882
	return(id);
2 7u83 1883
}
1884
 
1885
 
1886
/*
1887
    SKIP A PREDICATE
1888
 
1889
    This routine skips a predicate given by the list of preprocessing
1890
    tokens p.  It is entered after the initial open bracket and returns
1891
    the token after the matching close bracket.
1892
*/
1893
 
6 7u83 1894
static PPTOKEN *
1895
skip_predicate(PPTOKEN **p, int dir)
2 7u83 1896
{
6 7u83 1897
	PPTOKEN *q = *p;
1898
	PPTOKEN *r = NULL;
1899
	int bracket = 1;
1900
	if (q) {
1901
		q->pp_space = 0;
1902
	}
1903
	while (q) {
1904
		int t = q->tok;
1905
		if (t == lex_open_Hround) {
1906
			/* Increase bracket count */
1907
			bracket++;
1908
		} else if (t == lex_close_Hround) {
1909
			/* Decrease bracket count */
1910
			if (--bracket == 0) {
1911
				if (r) {
1912
					r->next = NULL;
1913
				} else if (dir == lex_define ||
1914
					   dir == lex_undef) {
1915
					*p = NULL;
1916
				} else {
1917
					report(preproc_loc,
1918
					       ERR_pragma_assert_empty(dir));
1919
					*p = NULL;
1920
				}
1921
				r = q->next;
1922
				q->next = free_tokens;
1923
				free_tokens = q;
1924
				return(r);
1925
			}
1926
		} else if (t == lex_newline) {
1927
			/* Terminate if a newline is reached */
1928
			report(preproc_loc, ERR_pragma_assert_paren(dir));
1929
			if (r) {
1930
				r->next = NULL;
1931
			} else {
1932
				report(preproc_loc,
1933
				       ERR_pragma_assert_empty(dir));
1934
				*p = NULL;
1935
			}
1936
			return(q);
2 7u83 1937
		}
6 7u83 1938
		r = q;
1939
		q = q->next;
2 7u83 1940
	}
6 7u83 1941
	report(preproc_loc, ERR_pragma_assert_paren(dir));
1942
	return(NULL);
2 7u83 1943
}
1944
 
1945
 
1946
/*
1947
    CHECK A PREDICATE VALUE
1948
 
1949
    This routine checks whether the value p, or any value if def is true,
1950
    has been defined in the predicate pred.
1951
*/
1952
 
6 7u83 1953
static int
1954
check_assert(HASHID pred, PPTOKEN *p, int def)
2 7u83 1955
{
6 7u83 1956
	IDENTIFIER id = make_assert(pred, lex_unknown);
1957
	int key = (int)DEREF_ulong(id_no(id));
1958
	LIST(PPTOKEN_P)s = DEREF_list(id_predicate_values(id));
1959
	report(preproc_loc, ERR_pragma_assert_pred(pred));
1960
	if (def) {
1961
		/* Check for any predicate */
1962
		if (!IS_NULL_list(s)) {
1963
			return(1);
1964
		}
1965
	} else {
1966
		while (!IS_NULL_list(s)) {
1967
			PPTOKEN *q = DEREF_pptok(HEAD_list(s));
1968
			if (eq_pptok(p, q) == 2) {
1969
				return(1);
1970
			}
1971
			s = TAIL_list(s);
1972
		}
2 7u83 1973
	}
6 7u83 1974
	if (key == lex_include) {
1975
		/* '#include' checks for included files */
1976
		if (def) {
1977
			return(1);
1978
		}
1979
		IGNORE quote_tok_list(p, 0, char_quote);
1980
		return(start_include(token_buff.start, char_quote, 4, 0));
2 7u83 1981
	}
6 7u83 1982
	if (key == lex_keyword) {
1983
		/* '#keyword' checks for keywords */
1984
		if (def) {
1985
			return(1);
1986
		}
1987
		if (p && p->next == NULL) {
1988
			if (p->tok == lex_identifier) {
1989
				IDENTIFIER pid = p->pp_data.id.use;
1990
				if (IS_id_keyword(pid)) {
1991
					return(1);
1992
				}
1993
				if (IS_id_iso_keyword(pid)) {
1994
					return(1);
1995
				}
1996
			}
1997
		}
2 7u83 1998
	}
6 7u83 1999
	if (key == lex_option) {
2000
		/* '#option' checks for options */
2001
		int n;
2002
		ulong sn;
2003
		string sb;
2004
		static STRING str = NULL_str;
2005
		if (def) {
2006
			return(1);
2007
		}
2008
		IGNORE quote_tok_list(p, 0, char_quote);
2009
		sb = token_buff.start;
2010
		sn = (ulong)(token_buff.posn - sb);
2011
		if (IS_NULL_str(str)) {
2012
			MAKE_str_simple(sn, sb, STRING_NONE, str);
2013
		} else {
2014
			COPY_string(str_simple_text(str), sb);
2015
			COPY_ulong(str_simple_len(str), sn);
2016
		}
2017
		n = find_option_no(str, 0);
2018
		if (n != -1 && option(n)) {
2019
			return(1);
2020
		}
2021
	}
2022
	return(0);
2 7u83 2023
}
2024
 
2025
 
2026
/*
2027
    SET A PREDICATE VALUE
2028
 
2029
    This routine sets the assertion value of the preprocessing tokens p
2030
    in the predicate id to be def.
2031
*/
2032
 
6 7u83 2033
static void
2034
set_assert(IDENTIFIER id, PPTOKEN *p, int def)
2 7u83 2035
{
6 7u83 2036
	LIST(PPTOKEN_P)s;
2037
	PTR(LIST(PPTOKEN_P))ps = id_predicate_values(id);
2038
	LIST(PPTOKEN_P)r = DEREF_list(ps);
2039
	while (s = DEREF_list(ps), !IS_NULL_list(s)) {
2040
		PPTOKEN *q = DEREF_pptok(HEAD_list(s));
2041
		if (eq_pptok(p, q) == 2) {
2042
			/* Already asserted */
2043
			if (!def) {
2044
				DESTROY_CONS_pptok(destroy, q, s, s);
2045
				COPY_list(ps, s);
2046
				free_tok_list(q);
2047
			}
2048
			free_tok_list(p);
2049
			return;
2050
		}
2051
		ps = PTR_TAIL_list(s);
2 7u83 2052
	}
6 7u83 2053
	if (def) {
2054
		/* Create assertion */
2055
		CONS_pptok(p, r, r);
2056
		COPY_list(id_predicate_values(id), r);
2057
	} else {
2058
		free_tok_list(p);
2059
	}
2060
	return;
2 7u83 2061
}
2062
 
2063
 
2064
/*
2065
    READ AN ASSERT DIRECTIVE
2066
 
2067
    This routine processes a '#assert' directive.
2068
*/
2069
 
6 7u83 2070
static void
2071
read_assert(int dir)
2 7u83 2072
{
6 7u83 2073
	/* Read the predicate name */
2074
	int def = 1;
2075
	IDENTIFIER id;
2076
	PPTOKEN *p, *q;
2077
	int t = read_token();
2078
	update_column();
2079
	if (in_preproc_dir) {
2080
		preproc_loc = crt_loc;
2081
	}
2082
	if (t != lex_identifier) {
2083
		report(preproc_loc, ERR_pragma_assert_id(dir));
2084
		return;
2085
	}
2086
	id = make_assert(token_hashid, lex_unknown);
2 7u83 2087
 
6 7u83 2088
	/* Read the predicate token sequence */
2089
	t = read_token();
2090
	update_column();
2091
	if (in_preproc_dir) {
2092
		preproc_loc = crt_loc;
2093
	}
2094
	if (t != lex_open_Hround) {
2095
		report(preproc_loc, ERR_pragma_assert_open(dir));
2096
		return;
2097
	}
2098
	p = read_line(lex_ignore_token, lex_ignore_token);
2099
	q = skip_predicate(&p, dir);
2100
	if (q) {
2101
		report(preproc_loc, ERR_cpp_end(dir));
2102
		free_tok_list(q);
2103
	}
2 7u83 2104
 
6 7u83 2105
	/* Create the assertion */
2106
	if (p) {
2107
		set_assert(id, p, def);
2108
	}
2109
	return;
2 7u83 2110
}
2111
 
2112
 
2113
/*
2114
    READ AN UNASSERT DIRECTIVE
2115
 
2116
    This routine processes a '#unassert' directive.
2117
*/
2118
 
6 7u83 2119
static void
2120
read_unassert(int dir)
2 7u83 2121
{
6 7u83 2122
	/* Read the predicate name */
2123
	IDENTIFIER id;
2124
	PPTOKEN *p, *q;
2125
	int t = read_token();
2126
	update_column();
2127
	if (in_preproc_dir) {
2128
		preproc_loc = crt_loc;
2129
	}
2130
	if (t != lex_identifier) {
2131
		report(preproc_loc, ERR_pragma_assert_id(dir));
2132
		return;
2133
	}
2134
	id = make_assert(token_hashid, lex_unknown);
2 7u83 2135
 
6 7u83 2136
	/* Check for simple identifier */
2137
	t = read_token();
2138
	update_column();
2139
	if (in_preproc_dir) {
2140
		preproc_loc = crt_loc;
2 7u83 2141
	}
6 7u83 2142
	if (t == lex_newline) {
2143
		p = NULL;
2144
	} else {
2145
		/* Read the predicate token sequence */
2146
		if (t != lex_open_Hround) {
2147
			report(preproc_loc, ERR_pragma_assert_open(dir));
2148
			return;
2149
		}
2150
		p = read_line(lex_ignore_token, lex_ignore_token);
2151
		q = skip_predicate(&p, dir);
2152
		if (q) {
2153
			report(preproc_loc, ERR_cpp_end(dir));
2154
			free_tok_list(q);
2155
		}
2 7u83 2156
	}
2157
 
6 7u83 2158
	if (p == NULL) {
2159
		/* Unassert all values */
2160
		LIST(PPTOKEN_P)r;
2161
		r = DEREF_list(id_predicate_values(id));
2162
		while (!IS_NULL_list(r)) {
2163
			DESTROY_CONS_pptok(destroy, q, r, r);
2164
			free_tok_list(q);
2165
		}
2166
		COPY_list(id_predicate_values(id), r);
2167
		COPY_ulong(id_no(id), lex_unknown);
2168
	} else {
2169
		/* Destroy the assertion */
2170
		set_assert(id, p, 0);
2 7u83 2171
	}
6 7u83 2172
	return;
2 7u83 2173
}
2174
 
2175
 
2176
/*
2177
    LOOK UP AN IDENTIFIER IN A PRAGMA WEAK DIRECTIVE
2178
 
2179
    This routine looks up the identifier named nm used in a '#pragma
2180
    weak' directive.  The result should be an external variable or
2181
    function.  The null identifier is returned to indicate an error.
2182
*/
2183
 
6 7u83 2184
static IDENTIFIER
2185
find_weak_id(HASHID nm)
2 7u83 2186
{
6 7u83 2187
	if (!IS_NULL_hashid(nm)) {
2188
		ERROR err;
2189
		IDENTIFIER id = find_id(nm);
2190
		switch (TAG_id(id)) {
2191
		case id_variable_tag: {
2192
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
2193
			if (!(ds & dspec_auto)) {
2194
				ds |= dspec_used;
2195
				COPY_dspec(id_storage(id), ds);
2196
				return(id);
2197
			}
2198
			break;
2 7u83 2199
		}
6 7u83 2200
		case id_function_tag: {
2201
			TYPE t = DEREF_type(id_function_type(id));
2202
			IDENTIFIER over = DEREF_id(id_function_over(id));
2203
			if (IS_NULL_id(over) && IS_type_func(t)) {
2204
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
2205
				ds |= dspec_used;
2206
				COPY_dspec(id_storage(id), ds);
2207
				return(id);
2208
			}
2209
			break;
2 7u83 2210
		}
6 7u83 2211
		}
2212
		err = ERR_pragma_preserve_undecl(lex_weak, id);
2213
		report(preproc_loc, err);
2 7u83 2214
	}
6 7u83 2215
	return(NULL_id);
2 7u83 2216
}
2217
 
2218
 
2219
/*
2220
    READ A PRAGMA WEAK DIRECTIVE
2221
 
2222
    This routine processes a '#pragma weak' directive.
2223
*/
2224
 
6 7u83 2225
void
2226
read_weak(int dir)
2 7u83 2227
{
6 7u83 2228
	IDENTIFIER id = NULL_id;
2229
	IDENTIFIER aid = NULL_id;
2230
	int t = read_token();
2231
	update_column();
2232
	if (in_preproc_dir) {
2233
		preproc_loc = crt_loc;
2 7u83 2234
	}
6 7u83 2235
	if (t == lex_identifier) {
2236
		id = find_weak_id(token_hashid);
2237
		t = read_token();
2238
		update_column();
2239
		if (in_preproc_dir) {
2240
			preproc_loc = crt_loc;
2241
		}
2242
		if (t == lex_assign) {
2243
			t = read_token();
2244
			update_column();
2245
			if (in_preproc_dir) {
2246
				preproc_loc = crt_loc;
2247
			}
2248
			if (t == lex_identifier) {
2249
				aid = find_weak_id(token_hashid);
2250
				t = read_token();
2251
				update_column();
2252
				if (in_preproc_dir)preproc_loc = crt_loc;
2253
			}
2254
		}
2255
	} else {
2256
		t = lex_unknown;
2 7u83 2257
	}
6 7u83 2258
	if (!IS_NULL_id(aid)) {
2259
		static LIST(IDENTIFIER)weak_ids = NULL_list(IDENTIFIER);
2260
		LIST(IDENTIFIER)p = weak_ids;
2261
		while (!IS_NULL_list(p)) {
2262
			IDENTIFIER pid = DEREF_id(HEAD_list(p));
2263
			if (EQ_id(id, pid)) {
2264
				report(preproc_loc, ERR_pragma_weak_redef(id));
2265
				id = NULL_id;
2266
				break;
2267
			}
2268
			p = TAIL_list(p);
2269
		}
2270
		if (!IS_NULL_id(id)) {
2271
			CONS_id(id, weak_ids, weak_ids);
2272
		}
2 7u83 2273
	}
6 7u83 2274
	compile_weak(id, aid);
2275
	if (t != lex_newline) {
2276
		report(preproc_loc, ERR_cpp_end(dir));
2277
	}
2278
	if (in_preproc_dir) {
2279
		IGNORE skip_to_end();
2280
	}
2281
	return;
2 7u83 2282
}
2283
 
2284
 
2285
/*
2286
    READ A PREPROCESSING DIRECTIVE
2287
 
2288
    This routine processes a preprocessing directive up to and including
2289
    the terminating newline character.  The act argument indicates
2290
    whether the directive is active or is being skipped in a conditional
2291
    compilation.  prev gives the previous preprocessing directive value.
2292
    The routine returns a lexical token value which is used to
2293
    communicate the effect of the directive on the main processor.  Most
2294
    directives are only visible to the preprocessor, and return one of
2295
    the values lex_ignore_token, lex_end_condition or lex_included (note
2296
    that these are all less than zero).  Other directives (for example,
2297
    target dependent conditionals) do communicate with the main
2298
    processor by returning a valid lexical token value.
2299
*/
2300
 
6 7u83 2301
int
2302
read_preproc_dir(int act, int prev)
2 7u83 2303
{
6 7u83 2304
	int t;
2305
	ERROR err;
2306
	HASHID dir;
2307
	int pp = lex_ignore_token;
2308
	in_preproc_dir = 1;
2309
	preproc_loc = crt_loc;
2 7u83 2310
 
6 7u83 2311
	/* Read the token following the '#' */
2312
	t = read_token();
2313
	update_column();
2314
	if (in_preproc_dir) {
2315
		preproc_loc = crt_loc;
2 7u83 2316
	}
6 7u83 2317
	if (t != lex_identifier) {
2318
		if (t == lex_newline || t == lex_eof) {
2319
			/* Warn about empty directives */
2320
			report(preproc_loc, ERR_cpp_null());
2321
			goto end_label;
2322
		}
2323
		/* Give an error for other directives */
2324
		report(preproc_loc, ERR_cpp_bad());
2325
		goto end_label;
2326
	}
2 7u83 2327
 
6 7u83 2328
	/* Analyse the '#identifier' directive */
2329
	dir = token_hashid;
2330
	t = find_hashid(dir);
2331
	switch (t) {
2 7u83 2332
 
6 7u83 2333
	case lex_define:
2334
		/* Deal with '#define' */
2335
		if (act) {
2336
			pp = read_define();
2337
			if (pp >= 0) {
2338
				pp = patch_cond(pp, t);
2339
			}
2340
		}
2341
		goto end_label;
2 7u83 2342
 
6 7u83 2343
	case lex_else:
2344
	case lex_endif:
2345
		/* Deal with '#else' and '#endif' */
2346
		if (in_preproc_dir && skip_to_end()) {
2347
			/* Check end of directive */
2348
			report(preproc_loc, ERR_cpp_cond_endif_end(t));
2349
		}
2350
		pp = read_if(t, PP_FALSE, lex_ignore_token);
2351
		if (act && pp >= 0)pp = patch_cond(pp, t);
2352
		return(pp);
2 7u83 2353
 
6 7u83 2354
	case lex_elif:
2355
		/* Deal with '#elif' (expression is read in read_if) */
2356
		report(preproc_loc, ERR_cpp_old(t));
2357
		pp = read_if(t, PP_FALSE, lex_ignore_token);
2358
		if (act && pp >= 0) {
2359
			pp = patch_cond(pp, t);
2360
		}
2361
		return(pp);
2 7u83 2362
 
6 7u83 2363
	case lex_error:
2364
		/* Deal with '#error' */
2365
		report(preproc_loc, ERR_cpp_old(t));
2366
		if (act) {
2367
			read_error(OPT_error);
2368
		}
2369
		goto end_label;
2 7u83 2370
 
6 7u83 2371
	case lex_include:
2372
		/* Deal with '#include' */
2373
		pp = read_include(act, t);
2374
		return(pp);
2 7u83 2375
 
6 7u83 2376
	case lex_if: {
2377
		/* Deal with '#if' */
2378
		unsigned cond = read_if_exp(act, t);
2379
		pp = read_if (t, cond, lex_ignore_token);
2380
		if (act && pp >= 0)pp = patch_cond(pp, t);
2381
		return(pp);
2 7u83 2382
	}
2383
 
6 7u83 2384
	case lex_ifdef: {
2385
		/* Deal with '#ifdef' */
2386
		unsigned cond = read_if_def(act, t, prev);
2387
		pp = read_if (t, cond, prev);
2388
		if (act && pp >= 0)pp = patch_cond(pp, t);
2389
		return(pp);
2 7u83 2390
	}
2391
 
6 7u83 2392
	case lex_ifndef: {
2393
		/* Deal with '#ifndef' */
2394
		unsigned cond = read_if_def(act, t, prev);
2395
		pp = read_if (t, negate_cond(cond), prev);
2396
		if (act && pp >= 0)pp = patch_cond(pp, t);
2397
		return(pp);
2 7u83 2398
	}
2399
 
6 7u83 2400
	case lex_line:
2401
		/* Deal with '#line' */
2402
		if (act) {
2403
			read_location(t);
2404
		}
2405
		goto end_label;
2 7u83 2406
 
6 7u83 2407
	case lex_pragma:
2408
		/* Deal with '#pragma' */
2409
		if (act) {
2410
			int ts = have_type_specifier;
2411
			int td = have_type_declaration;
2412
			int fd = have_func_declarator;
2413
			QUALIFIER cq = crt_id_qualifier;
2414
			in_pragma_dir = 1;
2415
			pp = read_pragma();
2416
			in_pragma_dir = 0;
2417
			pragma_number = 0;
2418
			crt_id_qualifier = cq;
2419
			have_type_specifier = ts;
2420
			have_type_declaration = td;
2421
			have_func_declarator = fd;
2422
		}
2423
		goto end_label;
2 7u83 2424
 
6 7u83 2425
	case lex_undef:
2426
		/* Deal with '#undef' */
2427
		if (act) {
2428
			pp = read_undef();
2429
			if (pp >= 0)pp = patch_cond(pp, t);
2430
		}
2431
		goto end_label;
2 7u83 2432
 
6 7u83 2433
	case lex_assert: {
2434
		/* Deal with '#assert' (extension) */
2435
		OPTION opt = option(OPT_ppdir_assert);
2436
		if (opt != OPTION_DISALLOW) {
2437
			if (opt != OPTION_ALLOW) {
2438
				err = ERR_pragma_cpp_known(t);
2439
				err = set_severity(err, OPT_ppdir_assert, 0);
2440
				report(preproc_loc, err);
2441
			}
2442
			if (act && !option(OPT_ppdir_assert_ignore)) {
2443
				read_assert(t);
2444
			}
2445
			goto end_label;
2 7u83 2446
		}
6 7u83 2447
		break;
2 7u83 2448
	}
2449
 
6 7u83 2450
	case lex_file: {
2451
		/* Deal with '#file' (extension) */
2452
		OPTION opt = option(OPT_ppdir_file);
2453
		if (opt != OPTION_DISALLOW) {
2454
			if (opt != OPTION_ALLOW) {
2455
				err = ERR_pragma_cpp_known(t);
2456
				err = set_severity(err, OPT_ppdir_file, 0);
2457
				report(preproc_loc, err);
2458
			}
2459
			if (act && !option(OPT_ppdir_file_ignore)) {
2460
				read_location(t);
2461
			}
2462
			goto end_label;
2 7u83 2463
		}
6 7u83 2464
		break;
2 7u83 2465
	}
2466
 
6 7u83 2467
	case lex_ident: {
2468
		/* Deal with '#ident' (extension) */
2469
		OPTION opt = option(OPT_ppdir_ident);
2470
		if (opt != OPTION_DISALLOW) {
2471
			if (opt != OPTION_ALLOW) {
2472
				err = ERR_pragma_cpp_known(t);
2473
				err = set_severity(err, OPT_ppdir_ident, 0);
2474
				report(preproc_loc, err);
2475
			}
2476
			if (act && !option(OPT_ppdir_ident_ignore)) {
2477
				read_ident(t);
2478
			}
2479
			goto end_label;
2 7u83 2480
		}
6 7u83 2481
		break;
2 7u83 2482
	}
2483
 
6 7u83 2484
	case lex_import:
2485
	case lex_include_Hnext: {
2486
		/* Deal with '#import' and '#include_next' (extension) */
2487
		OPTION opt = option(OPT_ppdir_import);
2488
		if (opt != OPTION_DISALLOW) {
2489
			if (opt != OPTION_ALLOW) {
2490
				err = ERR_pragma_cpp_known(t);
2491
				err = set_severity(err, OPT_ppdir_import, 0);
2492
				report(preproc_loc, err);
2493
			}
2494
			if (!option(OPT_ppdir_import_ignore)) {
2495
				pp = read_include(act, t);
2496
				return(pp);
2497
			}
2498
			goto end_label;
2 7u83 2499
		}
6 7u83 2500
		break;
2 7u83 2501
	}
2502
 
6 7u83 2503
	case lex_unassert: {
2504
		/* Deal with '#unassert' (extension) */
2505
		OPTION opt = option(OPT_ppdir_unassert);
2506
		if (opt != OPTION_DISALLOW) {
2507
			if (opt != OPTION_ALLOW) {
2508
				err = ERR_pragma_cpp_known(t);
2509
				err = set_severity(err, OPT_ppdir_unassert, 0);
2510
				report(preproc_loc, err);
2511
			}
2512
			if (act && !option(OPT_ppdir_unassert_ignore)) {
2513
				read_unassert(t);
2514
			}
2515
			goto end_label;
2 7u83 2516
		}
6 7u83 2517
		break;
2 7u83 2518
	}
2519
 
6 7u83 2520
	case lex_warning: {
2521
		/* Deal with '#warning' (extension) */
2522
		OPTION opt = option(OPT_ppdir_warning);
2523
		if (opt != OPTION_DISALLOW) {
2524
			if (opt != OPTION_ALLOW) {
2525
				err = ERR_pragma_cpp_known(t);
2526
				err = set_severity(err, OPT_ppdir_warning, 0);
2527
				report(preproc_loc, err);
2528
			}
2529
			if (act && !option(OPT_ppdir_warning_ignore)) {
2530
				read_error(OPT_warning);
2531
			}
2532
			goto end_label;
2 7u83 2533
		}
6 7u83 2534
		break;
2 7u83 2535
	}
2536
 
6 7u83 2537
	case lex_weak: {
2538
		/* Deal with '#weak' (extension) */
2539
		OPTION opt = option(OPT_ppdir_weak);
2540
		if (opt != OPTION_DISALLOW) {
2541
			if (opt != OPTION_ALLOW) {
2542
				err = ERR_pragma_cpp_known(t);
2543
				err = set_severity(err, OPT_ppdir_weak, 0);
2544
				report(preproc_loc, err);
2545
			}
2546
			if (act && !option(OPT_ppdir_weak_ignore)) {
2547
				read_weak(t);
2548
			}
2549
			goto end_label;
2 7u83 2550
		}
6 7u83 2551
		break;
2 7u83 2552
	}
6 7u83 2553
	}
2 7u83 2554
 
6 7u83 2555
	/* Unknown directives */
2556
	report(preproc_loc, ERR_cpp_unknown(dir));
2557
end_label:
2558
	if (in_preproc_dir) {
2559
		IGNORE skip_to_end();
2560
	}
2561
	return(pp);
2 7u83 2562
}
2563
 
2564
 
2565
/*
2566
    PREPROCESS A FILE
2567
 
2568
    This routine gives the preprocessor entry point for the compiler.  Each
2569
    token is read, preprocessed, and printed.  The white space in the output
2570
    does not necessarily bear any resemblance to that in the input.
2571
*/
2572
 
6 7u83 2573
void
2574
preprocess_file(void)
2 7u83 2575
{
6 7u83 2576
	int t;
2577
	FILE *f;
2578
	string fn;
2579
	BUFFER *bf;
2580
	unsigned long ws = 0;
2581
	unsigned long ln = 0;
2582
	int force_space = preproc_space;
2583
	static BUFFER preproc_buff = { NULL, NULL, NULL, NULL };
2 7u83 2584
 
6 7u83 2585
	/* Initialise input file */
2586
	init_lex();
2587
	fn = DEREF_string(posn_file(preproc_loc.posn));
2 7u83 2588
 
6 7u83 2589
	/* Open output file */
2590
	if (!open_output(OUTPUT_PREPROC, text_mode)) {
2591
		string nm = output_name[OUTPUT_PREPROC];
2592
		fail(ERR_fail_output(nm));
2593
		term_error(0);
2594
		return;
2 7u83 2595
	}
6 7u83 2596
	f = output_file[OUTPUT_PREPROC];
2597
	bf = clear_buffer(&preproc_buff, f);
2598
	fprintf_v(f, "#line 1 \"%s\"", strlit(fn));
2599
	crt_file_changed = 1;
2 7u83 2600
 
6 7u83 2601
	/* Scan through preprocessing tokens */
2602
	while (t = expand_preproc(EXPAND_NORMAL), t != lex_eof) {
2603
		/* Allow for skipped files */
2604
		if (crt_file_type) {
2605
			continue;
2 7u83 2606
		}
6 7u83 2607
 
2608
		/* Replace keywords by underlying identifier */
2609
		if (t >= FIRST_KEYWORD && t <= LAST_KEYWORD) {
2610
			crt_token->tok = lex_identifier;
2 7u83 2611
		}
6 7u83 2612
		if (t == lex_builtin_Hfile) {
2613
			fputc_v('\n', f);
2614
			ln++;
2615
			crt_line_changed = 1;
2616
			crt_spaces = 0;
2617
			continue;
2618
		}
2 7u83 2619
 
6 7u83 2620
		/* Print any required '#line' directives */
2621
		if (crt_line_changed) {
2622
			int ch = crt_file_changed;
2623
			unsigned long n = crt_loc.line;
2624
			unsigned long sp = crt_spaces;
2625
			unsigned long tab = tab_width;
2626
			output_buffer(bf, 0);
2627
			if (ch) {
2628
				string fm =
2629
				    DEREF_string(posn_file(crt_loc.posn));
2630
				if (ch > 1 || !ustreq(fn, fm)) {
2631
					char *s = strlit(fm);
2632
					fprintf_v(f, "\n\n#line %lu \"%s\"\n",
2633
						  n, s);
2634
					fn = fm;
2635
					ln = n;
2636
				}
2637
				crt_file_changed = 0;
2638
			}
2639
			if (n != ln) {
2640
				if (n > ln && n <= ln + 10) {
2641
					for (; ln < n; ln++) {
2642
						fputc_v('\n', f);
2643
					}
2644
				} else {
2645
					/* Force '#line' for more than 10 blank
2646
					 * lines */
2647
					fprintf_v(f, "\n\n#line %lu\n", n);
2648
				}
2649
				ln = n;
2650
			}
2651
			crt_line_changed = 0;
2 7u83 2652
 
6 7u83 2653
			/* Print indentation */
2654
			ws = sp;
2655
			for (; sp >= tab; sp -= tab) {
2656
				bfputc(bf, '\t');
2657
			}
2658
			for (; sp; sp--) {
2659
				bfputc(bf, ' ');
2660
			}
2 7u83 2661
 
6 7u83 2662
			/* Allow for hash symbols */
2663
			if (t == lex_hash_H1) {
2664
				crt_token->tok = lex_hash_Hhash_H1;
2665
			}
2666
			if (t == lex_hash_H2) {
2667
				crt_token->tok = lex_hash_Hhash_H2;
2668
			}
2669
 
2670
		} else {
2671
			unsigned long sp = crt_spaces;
2672
			if (sp != ws || force_space) {
2673
				/* Print space */
2674
				ws = sp;
2675
				bfputc(bf, ' ');
2676
			}
2677
		}
2678
 
2679
		/* Print the token name */
2680
		IGNORE print_pptok(crt_token, bf, 0);
2 7u83 2681
	}
6 7u83 2682
	bfputc(bf, '\n');
2683
	output_buffer(bf, 0);
2684
	close_output(OUTPUT_PREPROC);
2685
	return;
2 7u83 2686
}