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, 1998
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 "c_types.h"
63
#include "ctype_ops.h"
64
#include "hashid_ops.h"
65
#include "id_ops.h"
66
#include "member_ops.h"
67
#include "nspace_ops.h"
68
#include "tok_ops.h"
69
#include "type_ops.h"
70
#include "error.h"
71
#include "catalog.h"
72
#include "access.h"
73
#include "char.h"
74
#include "class.h"
75
#include "derive.h"
76
#include "file.h"
77
#include "hash.h"
78
#include "identifier.h"
79
#include "lex.h"
80
#include "literal.h"
81
#include "macro.h"
82
#include "namespace.h"
83
#include "option.h"
84
#include "parse.h"
85
#include "predict.h"
86
#include "preproc.h"
87
#include "redeclare.h"
88
#include "symbols.h"
89
#include "syntax.h"
90
#include "template.h"
91
#include "tokdef.h"
92
 
93
 
94
/*
95
    CURRENT LEXICAL TOKEN NUMBERS
96
 
97
    These variables are used by the parser to hold the current and former
98
    lexical token numbers.
99
*/
100
 
6 7u83 101
int crt_lex_token = lex_unknown;
102
int last_lex_token = lex_unknown;
103
int saved_lex_token = lex_unknown;
104
static int have_template = 0;
105
int have_syntax_error = 0;
2 7u83 106
 
107
 
108
/*
109
    LIST OF ACTIVE LEXICAL TOKENS
110
 
111
    The currently active lexical tokens are formed into a list starting
112
    with first_token.  The position of the current token within this list
113
    is given by crt_token.  The main routine for building up this list
114
    is expand_token which either advances crt_token one step along the
115
    list, or, if crt_token points to the end of the list, reads and macro
116
    expands the next token from the input file, appending the resulting
117
    tokens to the end of the list.  The list is periodically garbage
118
    collected by setting first_token to crt_token and freeing all the
119
    tokens from the old first_token.
120
*/
121
 
6 7u83 122
PPTOKEN *crt_token = NULL;
123
static PPTOKEN *first_token = NULL;
124
NAMESPACE crt_lookup = NULL_nspace;
125
static unsigned long crt_lookup_depth = 0;
126
static OPTIONS *prev_opts = NULL;
127
static STACK(int)token_stack = NULL_stack(int);
128
static STACK(PPTOKEN_P)parser_stack = NULL_stack(PPTOKEN_P);
129
static STACK(NAMESPACE)lookup_stack = NULL_stack(NAMESPACE);
2 7u83 130
 
131
 
132
/*
133
    INITIALISE ACTIVE TOKEN LIST
134
 
135
    This routine initialises a new list of active lexical tokens with the
136
    value toks by pushing the old values of first_token and crt_token onto
137
    the stack parser_stack and setting them to point to a new dummy token
138
    whose next field is toks.
139
*/
140
 
6 7u83 141
void
142
init_parser(PPTOKEN *toks)
2 7u83 143
{
6 7u83 144
	PPTOKEN *q;
145
	PUSH_int(crt_lex_token, token_stack);
146
	PUSH_int(last_lex_token, token_stack);
147
	PUSH_int(saved_lex_token, token_stack);
148
	PUSH_nspace(crt_lookup, lookup_stack);
149
	PUSH_pptok(first_token, parser_stack);
150
	PUSH_pptok(crt_token, parser_stack);
151
	q = new_pptok();
152
	q->tok = lex_ignore_token;
153
	q->pp_space = 0;
154
	q->next = toks;
155
	first_token = q;
156
	crt_token = q;
157
	crt_lookup = NULL_nspace;
158
	crt_lookup_depth = 0;
159
	crt_lex_token = lex_unknown;
160
	last_lex_token = lex_unknown;
161
	saved_lex_token = lex_unknown;
162
	return;
2 7u83 163
}
164
 
165
 
166
/*
167
    RESTORE ACTIVE TOKEN LIST
168
 
169
    This routine restores the previous list of active lexical tokens by
170
    popping the values of first_token and crt_token from the stack.  The
171
    previous list is returned.
172
*/
173
 
6 7u83 174
PPTOKEN *
175
restore_parser(void)
2 7u83 176
{
6 7u83 177
	PPTOKEN *p = first_token;
178
	POP_pptok(crt_token, parser_stack);
179
	POP_pptok(first_token, parser_stack);
180
	POP_nspace(crt_lookup, lookup_stack);
181
	POP_int(last_lex_token, token_stack);
182
	POP_int(saved_lex_token, token_stack);
183
	POP_int(crt_lex_token, token_stack);
184
	crt_lookup_depth = 0;
185
	ASSERT(first_token != NULL);
186
	return(p);
2 7u83 187
}
188
 
189
 
190
/*
191
    REMOVE A LIST OF TOKENS FROM THE CURRENT LIST
192
 
193
    This routine removes the tokens from p to q inclusive from the current
194
    list.  crt_token must not be included within this range.
195
*/
196
 
6 7u83 197
void
198
snip_tokens(PPTOKEN *p, PPTOKEN *q)
2 7u83 199
{
6 7u83 200
	PPTOKEN *r = first_token;
201
	if (r == p) {
202
		first_token = q->next;
203
	} else {
204
		while (r->next != p) {
205
			r = r->next;
206
		}
207
		r->next = q->next;
208
	}
209
	r = new_pptok();
210
	r->tok = lex_eof;
211
	q->next = r;
212
	r->next = NULL;
213
	return;
2 7u83 214
}
215
 
216
 
217
/*
218
    PATCH A NUMBER OF TOKENS INTO THE CURRENT LIST
219
 
220
    This routine patches n tokens into the current list immediately after
221
    crt_token, returning the first token.  This is used by the preprocessor
222
    to pass more than one token to the parser.
223
*/
224
 
6 7u83 225
PPTOKEN *
226
patch_tokens(int n)
2 7u83 227
{
6 7u83 228
	while (n) {
229
		PPTOKEN *p = new_pptok();
230
		p->tok = lex_ignore_token;
231
		p->next = crt_token->next;
232
		p->pp_space = WHITE_SPACE;
233
		crt_token->next = p;
234
		n--;
235
	}
236
	return(crt_token->next);
2 7u83 237
}
238
 
239
 
240
/*
241
    CURRENT PARSER STATE DEPTH
242
 
243
    This variable is used to record the current depth of saved parser
244
    states.
245
*/
246
 
6 7u83 247
int crt_state_depth = 0;
2 7u83 248
 
249
 
250
/*
251
    SAVE PARSER STATE
252
 
253
    This routine saves the current parser state into s, it also clears the
254
    syntax error flag.  col is true if column numbers are to be considered
255
    during the parsing.
256
*/
257
 
6 7u83 258
void
259
save_state(PARSE_STATE *s, int col)
2 7u83 260
{
6 7u83 261
	/* Save current location */
262
	s->loc = crt_loc;
2 7u83 263
 
6 7u83 264
	/* Save current namespace */
265
	s->nspace[0] = crt_namespace;
266
	s->nspace[1] = templ_namespace;
267
	s->nstack[0] = namespace_stack;
268
	s->nstack[1] = crt_nspace_stack;
269
	s->nstack[2] = local_nspace_stack;
2 7u83 270
 
6 7u83 271
	/* Save flag values */
272
	s->flag[0] = in_class_defn;
273
	s->flag[1] = in_function_defn;
274
	s->flag[2] = really_in_class_defn;
275
	s->flag[3] = really_in_function_defn;
276
	s->flag[4] = in_declaration;
277
	s->flag[5] = in_template_decl;
278
	s->flag[6] = have_syntax_error;
279
	s->flag[7] = cache_lookup;
280
	s->flag[8] = crt_col_changed;
281
	have_syntax_error = 0;
282
	cache_lookup = old_cache_lookup;
283
	crt_col_changed = col;
2 7u83 284
 
6 7u83 285
	/* Save declaration specifiers */
286
	s->dspec[0] = crt_access;
287
	s->dspec[1] = crt_linkage;
288
	crt_access = dspec_public;
289
	crt_state_depth++;
290
	bad_crt_loc++;
291
	return;
2 7u83 292
}
293
 
294
 
295
/*
296
    RESTORE PARSER STATE
297
 
298
    This routine restores the parser state from the value stored in s.
299
    Note that there is some attempt at recovering the state following
300
    some intervening error, particularly with regard to resetting the
301
    current namespace.
302
*/
303
 
6 7u83 304
void
305
restore_state(PARSE_STATE *s)
2 7u83 306
{
6 7u83 307
	/* Restore current namespace */
308
	NAMESPACE ns = s->nspace[0];
309
	NAMESPACE cns = crt_namespace;
310
	LIST(NAMESPACE)pns = LIST_stack(s->nstack[0]);
311
	cache_lookup = old_cache_lookup;
312
	while (!EQ_list(pns, LIST_stack(namespace_stack))) {
313
		/* Reset name look-up stack */
314
		remove_namespace();
315
	}
316
	crt_namespace = ns;
317
	crt_nspace_stack = s->nstack[1];
318
	local_nspace_stack = s->nstack[2];
319
	if (!EQ_nspace(ns, cns)) {
320
		/* Recalculate namespaces if necessary */
321
		update_namespace();
322
	}
323
	templ_namespace = s->nspace[1];
2 7u83 324
 
6 7u83 325
	/* Restore current location */
326
	crt_loc = s->loc;
327
	crt_line_changed = 1;
328
	crt_file_changed = 1;
2 7u83 329
 
6 7u83 330
	/* Restore flag values */
331
	in_class_defn = s->flag[0];
332
	in_function_defn = s->flag[1];
333
	really_in_class_defn = s->flag[2];
334
	really_in_function_defn = s->flag[3];
335
	in_declaration = s->flag[4];
336
	in_template_decl = s->flag[5];
337
	have_syntax_error = s->flag[6];
338
	cache_lookup = s->flag[7];
339
	crt_col_changed = s->flag[8];
2 7u83 340
 
6 7u83 341
	/* Restore declaration specifiers */
342
	crt_access = s->dspec[0];
343
	crt_linkage = s->dspec[1];
344
	crt_state_depth--;
345
	bad_crt_loc--;
346
	return;
2 7u83 347
}
348
 
349
 
350
/*
351
    SET UP FILE LOCATION TOKENS
352
 
353
    This routine sets up preprocessing tokens recording the current file
354
    position immediately following p.
355
*/
356
 
6 7u83 357
static void
358
make_loc_tokens(PPTOKEN *p)
2 7u83 359
{
6 7u83 360
	PPTOKEN *q = new_pptok();
361
	if (crt_file_changed) {
362
		q->tok = lex_builtin_Hfile;
363
		crt_file_changed = 0;
364
	} else {
365
		q->tok = lex_builtin_Hline;
366
	}
367
	crt_line_changed = 0;
368
	q->pp_space = crt_loc.column;
369
	q->pp_data.loc.line = crt_loc.line;
370
	q->pp_data.loc.posn = crt_loc.posn;
371
	q->next = p->next;
372
	p->next = q;
373
	return;
2 7u83 374
}
375
 
376
 
377
/*
378
    READ FILE LOCATION TOKENS
379
 
380
    This routine adjusts the current line number according to the
381
    preprocessing tokens p.
382
*/
383
 
6 7u83 384
PPTOKEN *
385
read_loc_tokens(PPTOKEN *p)
2 7u83 386
{
6 7u83 387
	if (p) {
388
		int t = p->tok;
389
		if (t == lex_builtin_Hline) {
390
			/* Set line number */
391
			crt_loc.column = p->pp_space;
392
			crt_loc.line = p->pp_data.loc.line;
393
			crt_loc.posn = p->pp_data.loc.posn;
394
			crt_line_changed = 1;
395
			p = p->next;
396
		} else if (t == lex_builtin_Hfile) {
397
			/* Set file name */
398
			crt_loc.column = p->pp_space;
399
			crt_loc.line = p->pp_data.loc.line;
400
			crt_loc.posn = p->pp_data.loc.posn;
401
			crt_line_changed = 1;
402
			crt_file_changed = 1;
403
			p = p->next;
404
		} else if (crt_col_changed) {
405
			unsigned long sp = p->pp_space;
406
			if (sp)crt_loc.column = sp;
407
		}
2 7u83 408
	}
6 7u83 409
	return(p);
2 7u83 410
}
411
 
412
 
413
/*
414
    FIND A DESTRUCTOR NAME
415
 
416
    This routine returns the destructor name for the class name cid or the
417
    null identifier if cid is not a class name.
418
*/
419
 
420
#if LANGUAGE_CPP
421
 
6 7u83 422
static IDENTIFIER
423
find_destr_id(IDENTIFIER cid)
2 7u83 424
{
6 7u83 425
	CLASS_TYPE ct = NULL_ctype;
426
	if (IS_id_class_name_etc(cid)) {
427
		TYPE t = DEREF_type(id_class_name_etc_defn(cid));
428
		unsigned tag = TAG_type(t);
429
		while (tag == type_templ_tag) {
430
			t = DEREF_type(type_templ_defn(t));
431
			tag = TAG_type(t);
432
		}
433
		if (tag == type_compound_tag) {
434
			ct = DEREF_ctype(type_compound_defn(t));
435
		}
436
	} else {
437
		ct = find_class(cid);
2 7u83 438
	}
6 7u83 439
	if (!IS_NULL_ctype(ct)) {
440
		/* Find destructor name */
441
		IDENTIFIER tid = DEREF_id(ctype_destr(ct));
442
		HASHID nm = DEREF_hashid(id_name(tid));
443
		tid = DEREF_id(hashid_id(nm));
444
		set_hashid_loc(tid, cid);
445
		return(tid);
2 7u83 446
	}
6 7u83 447
	return(NULL_id);
2 7u83 448
}
449
 
450
#endif
451
 
452
 
453
/*
454
    CHECK A DESTRUCTOR NAME
455
 
456
    This routine checks whether the destructor name cid specified using
457
    nm is legal.  For example, nm might be a typedef-name for the class
458
    rather than the class itself.  d is the result of the previous call
459
    to predict_destr.
460
*/
461
 
462
#if LANGUAGE_CPP
463
 
6 7u83 464
static void
465
check_destr_id(IDENTIFIER cid, HASHID nm, int d)
2 7u83 466
{
6 7u83 467
	if (d <= 2) {
468
		HASHID cnm = DEREF_hashid(id_name(cid));
469
		IDENTIFIER tid = DEREF_id(hashid_destr_tid(cnm));
470
		HASHID tnm = DEREF_hashid(id_name(tid));
471
		if (!EQ_hashid(tnm, nm)) {
472
			/* Destructor names don't match */
473
			IDENTIFIER id = DEREF_id(hashid_id(nm));
474
			report(crt_loc, ERR_dcl_typedef_destr(id, cnm));
475
		}
2 7u83 476
	}
6 7u83 477
	return;
2 7u83 478
}
479
 
480
#endif
481
 
482
 
483
/*
484
    READ AND EXPAND THE NEXT TOKEN
485
 
486
    This routine reads the next token from the list of all active tokens,
487
    first_token (see above).  This consists either of advancing crt_token
488
    along this list, or reading and expanding a new token from the input
489
    file, appending the result to the list.  The argument store gives the
490
    context for the token.  The usual cases are EXPAND_NORMAL, indicating
491
    that the token is to be used and then discarded (allowing first_token
492
    to be garbage collected up to crt_token), and EXPAND_AHEAD, indicating
493
    that the token is to be stored for use later.  The value EXPAND_RESCAN
494
    can be used to force the current token to be rescanned.  Other values
495
    are used internally.  Note that crt_token is set to the token currently
496
    being defined during all calls to read_token.  The routine can be
497
    considerably simplified for C, and because of the performance critical
498
    nature of the routine this has been done by conditional compilation.
499
 
500
    There is a problem with the look-ahead method in that certain tokens
501
    are context dependent, and thus may not mean the same in the initial
502
    scan using expand_token ( EXPAND_AHEAD ) as they do when the same
503
    tokens are re-analysed using expand_token ( EXPAND_NORMAL ).  This
504
    is solved by storing all the tokens in these cases and reinterpreting
505
    them later.  This means in particular than a context dependent
506
    interpretation such as an identifier being a type name is not set
507
    in stone by being recorded in the token's tok field.  Instead this
508
    interpretation is returned, but the identifier is only marked as
509
    an identifier.
510
 
511
    Note also that SID is always one token ahead of itself.  For example
512
    in:
513
 
514
		void f ()
515
		{
516
		    {
517
			extern void g ( int ) ;
518
			g ( 0 ) ;
519
		    }
520
		    g ( 1 ) ;
521
		}
522
 
523
    g goes out of scope after the first close brace, by which time SID has
524
    already read the following token and resolved it as g.  Thus in these
525
    cases it is necessary to insert an explicit rescan of the current token
526
    (with a store value of EXPAND_RESCAN) after the close brace so that
527
    g is seen not to be in scope.  This problem only ever occurs one
528
    token ahead of the current token.
529
*/
530
 
6 7u83 531
int
532
expand_token(int store)
2 7u83 533
{
6 7u83 534
	int t;
535
	int expand;
2 7u83 536
#if LANGUAGE_CPP
6 7u83 537
	NAMESPACE ns = crt_lookup;
2 7u83 538
#endif
6 7u83 539
	PPTOKEN *prev_tok = crt_token;
540
	PPTOKEN *this_tok = prev_tok->next;
2 7u83 541
 
6 7u83 542
	/* A store value of EXPAND_RESCAN means rescan this token */
543
	if (store == EXPAND_RESCAN) {
544
		this_tok = prev_tok;
2 7u83 545
#if LANGUAGE_CPP
6 7u83 546
		ns = NULL_nspace;
2 7u83 547
#endif
6 7u83 548
	}
2 7u83 549
 
6 7u83 550
	/* Get the next token */
551
start_label:
552
	if (this_tok == NULL) {
553
		/* Read the token from the file */
554
		this_tok = new_pptok();
555
		this_tok->next = NULL;
556
		prev_tok->next = this_tok;
557
		crt_token = this_tok;
558
		t = read_token();
559
		update_column();
560
		this_tok->tok = t;
561
		if (t <= LAST_COMPLEX_TOKEN) {
562
			token_parts(t, this_tok);
563
		}
564
		/* Don't bother with the space field */
2 7u83 565
 
6 7u83 566
		if (store == EXPAND_NORMAL) {
567
			/* Garbage collect stored tokens */
568
			prev_tok->next = free_tokens;
569
			free_tokens = first_token;
570
			first_token = this_tok;
571
		}
572
		expand = 1;
2 7u83 573
 
574
	} else {
6 7u83 575
		/* Use a previously stored token */
576
		t = this_tok->tok;
577
		if (t == lex_ignore_token) {
578
			/* Step over any ignored tokens */
579
			prev_tok = this_tok;
580
			this_tok = this_tok->next;
581
			goto start_label;
582
		} else if (t == lex_builtin_Hline || t == lex_builtin_Hfile) {
583
			/* Set line number */
584
			prev_tok = this_tok;
585
			this_tok = read_loc_tokens(this_tok);
586
			goto start_label;
587
		} else if (crt_col_changed) {
588
			unsigned long sp = this_tok->pp_space;
589
			if (sp) {
590
				crt_loc.column = sp;
591
			}
592
		}
593
		crt_token = this_tok;
594
		expand = 0;
2 7u83 595
	}
6 7u83 596
	crt_lookup = NULL_nspace;
2 7u83 597
 
6 7u83 598
	/* Deal with context switch */
599
	if (store == EXPAND_NORMAL) {
600
		OPTIONS *opts = prev_opts;
601
		if (opts != crt_opts) {
602
			set_mode(opts);
603
		}
604
		prev_opts = this_tok->pp_opts;
605
	}
2 7u83 606
 
6 7u83 607
	/* Analyse the token */
608
	switch (t) {
2 7u83 609
 
6 7u83 610
	case lex_identifier: {
611
		/* Deal with identifiers */
612
		unsigned tag;
613
		int tt = lex_identifier;
2 7u83 614
 
6 7u83 615
		/* Check for macro expansion */
616
		HASHID nm = this_tok->pp_data.id.hash;
617
		IDENTIFIER id = DEREF_id(hashid_id(nm));
618
expand_label:
619
		tag = TAG_id(id);
620
		switch (tag) {
2 7u83 621
 
6 7u83 622
		case id_obj_macro_tag:
623
		case id_func_macro_tag:
2 7u83 624
			/* Check for expansion of macros */
6 7u83 625
			if (expand) {
626
				PPTOKEN *toks;
627
				toks = expand_macro(nm, file_loc, 1);
628
				this_tok->tok = lex_ignore_token;
629
				this_tok->next = toks;
630
				prev_tok = this_tok;
631
				this_tok = toks;
632
				goto start_label;
2 7u83 633
			}
6 7u83 634
			id = DEREF_id(id_alias(id));
635
			goto expand_label;
2 7u83 636
 
6 7u83 637
		case id_keyword_tag:
2 7u83 638
			/* Check on keywords */
6 7u83 639
			this_tok->pp_data.id.use = id;
640
			t = (int)DEREF_ulong(id_no(id));
641
			this_tok->tok = t;
642
			return(t);
2 7u83 643
 
6 7u83 644
		case id_iso_keyword_tag:
2 7u83 645
			/* Check on ISO keywords */
6 7u83 646
			this_tok->pp_data.id.use = id;
647
			if (!in_pragma_dir) {
648
				ERROR err;
649
				t = (int)DEREF_ulong(id_no(id));
650
				t = primary_form(t);
651
				err = ERR_lex_digraph_iso(nm, t);
652
				if (!IS_NULL_err(err)) {
653
					report(crt_loc, err);
654
				}
655
				this_tok->tok = t;
2 7u83 656
#if LANGUAGE_CPP
6 7u83 657
				if (t == lex_compl_H1)goto compl_label;
2 7u83 658
#endif
6 7u83 659
				return(t);
2 7u83 660
			}
6 7u83 661
			break;
2 7u83 662
 
6 7u83 663
		case id_reserved_tag:
2 7u83 664
			/* Report reserved identifiers */
6 7u83 665
			if (store == EXPAND_NORMAL && !in_pragma_dir) {
666
				ERROR err = ERR_lex_key_reserve(nm);
667
				report(crt_loc, err);
2 7u83 668
			}
6 7u83 669
			break;
2 7u83 670
		}
671
 
6 7u83 672
		/* Perform name look-up */
2 7u83 673
#if LANGUAGE_CPP
6 7u83 674
		if (IS_NULL_nspace(ns)) {
675
			id = find_id(nm);
676
		} else {
677
			IDENTIFIER mid = find_qual_id(ns, nm, 0, 0);
678
			if (!IS_NULL_id(mid))id = mid;
679
		}
2 7u83 680
#else
6 7u83 681
		id = find_op_id(nm);
2 7u83 682
#endif
6 7u83 683
		tag = TAG_id(id);
2 7u83 684
 
685
#if LANGUAGE_CPP
6 7u83 686
		/* Look ahead for following '::' (C++ only) */
687
		t = expand_token(EXPAND_CHECK_COLON);
688
		crt_token = this_tok;
2 7u83 689
#endif
690
 
6 7u83 691
		/* Allow for tokens and templates */
692
		if (tag == id_token_tag) {
693
			TOKEN sort = DEREF_tok(id_token_sort(id));
694
			if (IS_tok_proc(sort)) {
695
				/* Procedure token application */
2 7u83 696
#if LANGUAGE_CPP
6 7u83 697
				/* Following token already read */
2 7u83 698
#else
6 7u83 699
				/* Check for following '(' */
700
				t = expand_token(EXPAND_CHECK_COLON);
701
				crt_token = this_tok;
2 7u83 702
#endif
6 7u83 703
				if (t == lex_open_Hround) {
704
					PPTOKEN *args = skip_token_args(id);
705
					id = DEREF_id(id_token_alt(id));
706
					this_tok->pp_data.tok.id = id;
707
					this_tok->pp_data.tok.args = args;
708
					sort = DEREF_tok(tok_proc_res(sort));
709
					switch (TAG_tok(sort)) {
710
					case tok_exp_tag:
711
					case tok_nat_tag:
712
					case tok_snat_tag: {
713
						tt = lex_complex_Hexp;
714
						break;
715
					}
716
					case tok_stmt_tag: {
717
						tt = lex_complex_Hstmt;
718
						break;
719
					}
720
					case tok_member_tag: {
721
						/* NOT YET IMPLEMENTED */
722
						tt = lex_complex_Hexp;
723
						break;
724
					}
725
					default : {
726
						tt = lex_complex_Htype;
2 7u83 727
#if LANGUAGE_CPP
6 7u83 728
						/* Check again for following
729
						 * '::' */
730
						t = expand_token(EXPAND_CHECK_COLON);
731
						crt_token = this_tok;
2 7u83 732
#endif
6 7u83 733
						break;
734
					}
735
					}
736
				} else {
737
					tt = DEREF_int(tok_proc_key(sort));
738
					if (store == EXPAND_NORMAL) {
739
						if (tt != lex_identifier &&
740
						    !in_pragma_dir) {
741
							ERROR err = ERR_cpp_replace_arg_none(nm);
742
							report(crt_loc, err);
743
						}
744
					}
745
				}
2 7u83 746
			}
747
 
748
#if LANGUAGE_CPP
6 7u83 749
		} else if (t == lex_less) {
750
			/* Check for templates (C++ only) */
751
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
752
			if (ds & dspec_template) {
753
				/* Template application */
754
				PPTOKEN *args;
755
				if (ds & dspec_implicit) {
756
					/* Allow for injected template names */
757
					IDENTIFIER tid = find_template(id, 0);
758
					if (!IS_NULL_id(tid)) {
759
						id = tid;
760
						tag = TAG_id(id);
761
					}
762
				}
763
				args = skip_template_args(id, 0);
764
				if (store == EXPAND_TEMPLATE) {
765
					have_template = 1;
766
				}
767
				switch (tag) {
768
				case id_class_name_tag:
769
					tt = lex_template_Htype;
770
					goto class_template_lab;
771
				case id_class_alias_tag:
772
					tt = lex_complex_Htype;
773
					goto class_template_lab;
774
				case id_type_alias_tag: {
775
					CLASS_TYPE ct = find_class(id);
776
					tt = lex_complex_Htype;
777
					if (!IS_NULL_ctype(ct)) {
778
						goto class_template_lab;
779
					}
780
					break;
781
				}
782
class_template_lab:	{
783
				t = expand_token(EXPAND_CHECK_COLON);
784
				crt_token = this_tok;
785
				if (t == lex_colon_Hcolon) {
786
					/* Expand the template class now */
787
					id = parse_type_template(id, args, 1);
788
					tt = lex_identifier;
789
				}
790
				break;
2 7u83 791
			}
6 7u83 792
				case id_enum_name_tag:
793
				case id_enum_alias_tag:
794
			tt = lex_complex_Htype;
795
			break;
796
				default:
797
			/* Function template */
798
			tt = lex_template_Hid;
799
			break;
800
				}
801
				if (tt != lex_identifier) {
802
					this_tok->pp_data.tok.id = id;
803
					this_tok->pp_data.tok.args = args;
804
				}
805
			} else if (store == EXPAND_TEMPLATE) {
806
				/* Have 'template id < ... >' */
807
				PPTOKEN *args = skip_template_args(id, 0);
808
				this_tok->pp_data.tok.id = id;
809
				this_tok->pp_data.tok.args = args;
810
				tt = lex_template_Hid;
811
				have_template = 1;
2 7u83 812
			}
6 7u83 813
#endif
2 7u83 814
		}
815
 
816
#if LANGUAGE_CPP
6 7u83 817
		/* Allow for destructors (C++ only) */
818
		if (store == EXPAND_DESTRUCTOR && t != lex_colon_Hcolon) {
819
			int level = 2;
820
			IDENTIFIER cid = id;
821
			do {
822
				switch (TAG_id(cid)) {
823
				case id_class_name_tag:
824
				case id_class_alias_tag:
825
				case id_token_tag: {
826
					IDENTIFIER tid;
827
					if (tt == lex_template_Htype) {
828
						this_tok->tok = tt;
829
						t = lex_destructor_Hname;
830
						return(t);
831
					}
832
					tid = find_destr_id(cid);
833
					if (!IS_NULL_id(tid)) {
834
						this_tok->pp_data.id.use = tid;
835
						t = lex_destructor_Hname;
836
						return(t);
837
					}
838
					level = 0;
839
					break;
840
				}
841
				default:
842
					if (level == 2 && !IS_NULL_nspace(ns)) {
843
						cid = find_id(nm);
844
						level = 1;
845
					} else {
846
						level = 0;
847
					}
848
					break;
849
				}
850
			} while (level);
851
		}
2 7u83 852
#endif
853
 
854
#if LANGUAGE_CPP
6 7u83 855
		/* Look ahead for further qualifiers (C++ only) */
856
		if (t == lex_colon_Hcolon) {
857
			/* Following token is '::' */
858
			int level = 2;
859
			IDENTIFIER cid = id;
860
			do {
861
				switch (TAG_id(cid)) {
862
				case id_class_name_tag:
863
				case id_class_alias_tag:
864
				case id_nspace_name_tag:
865
				case id_nspace_alias_tag: {
866
					/* Have namespace or class name */
867
					ns = find_namespace(cid);
868
					if (!IS_NULL_nspace(ns)) {
869
						crt_lookup = ns;
870
						t = expand_token(EXPAND_IDENTIFIER);
871
						switch (t) {
872
						case lex_full_Hname:
873
						case lex_colon_Hcolon:
874
							t = lex_nested_Hname;
875
							this_tok->tok =
876
							    lex_ignore_token;
877
							crt_token->tok = t;
878
							return(t);
879
						case lex_full_Hname_Hstar:
880
							t = lex_nested_Hname_Hstar;
881
							this_tok->tok =
882
							    lex_ignore_token;
883
							crt_token->tok = t;
884
							return(t);
885
						}
886
						crt_token = this_tok;
887
					}
888
					level = 0;
889
					break;
2 7u83 890
				}
891
 
6 7u83 892
				default: {
893
					/* Look up namespace or class name */
894
					if (level == 2) {
895
						CLASS_TYPE ct = find_class(cid);
896
						if (!IS_NULL_ctype(ct)) {
897
							cid = DEREF_id(ctype_name(ct));
898
						} else {
899
							if (IS_NULL_nspace(ns)) {
900
								cid = find_type_id(nm, 3);
901
							} else {
902
								cid = find_qual_id(ns, nm, 0, 3);
903
							}
904
						}
905
						if (IS_NULL_id(cid)) {
906
							level = 0;
907
						} else {
908
							level = 1;
909
						}
910
					} else {
911
						level = 0;
912
					}
913
					break;
2 7u83 914
				}
915
				}
6 7u83 916
			} while (level);
917
		}
2 7u83 918
#endif
919
 
6 7u83 920
		/* Deal with context dependent identifiers */
921
		switch (tag) {
2 7u83 922
 
923
#if LANGUAGE_CPP
6 7u83 924
		case id_class_name_tag:
925
		case id_enum_name_tag:
926
			/* Type names (C++ only) */
927
			t = lex_type_Hname;
928
			break;
2 7u83 929
#endif
6 7u83 930
		case id_class_alias_tag:
931
		case id_enum_alias_tag:
932
		case id_type_alias_tag:
933
			/* Type aliases */
934
			t = lex_type_Hname;
935
			break;
2 7u83 936
#if LANGUAGE_CPP
6 7u83 937
		case id_nspace_name_tag:
938
		case id_nspace_alias_tag:
939
			/* Namespace names (C++ only) */
940
			t = lex_namespace_Hname;
941
			break;
2 7u83 942
#endif
6 7u83 943
		case id_token_tag: {
944
			/* Token names */
945
			TOKEN sort = DEREF_tok(id_token_sort(id));
946
			if (IS_tok_stmt(sort)) {
947
				t = lex_statement_Hname;
948
			} else {
949
				t = lex_identifier;
950
			}
951
			break;
2 7u83 952
		}
953
 
6 7u83 954
		default:
955
			/* Other names */
956
			t = lex_identifier;
957
			break;
2 7u83 958
		}
6 7u83 959
		if (tt == lex_identifier) {
960
			this_tok->pp_data.id.use = id;
961
		} else {
962
			this_tok->tok = tt;
963
			t = tt;
964
		}
965
		break;
2 7u83 966
	}
967
 
968
#if LANGUAGE_CPP
6 7u83 969
	case lex_colon_Hcolon: {
970
		/* Deal with qualified names (C++ only) */
971
		int nt;
972
		unsigned long depth;
973
		if (store == EXPAND_CHECK_COLON) {
974
			/* Look ahead for '::' */
975
			return(t);
976
		} else if (IS_NULL_nspace(ns)) {
977
			/* Initial '::' */
978
			ns = global_namespace;
979
			depth = 0;
980
		} else if (store == EXPAND_IDENTIFIER) {
981
			/* Following a namespace identifier */
982
			depth = crt_lookup_depth + 1;
983
		} else {
984
			/* Badly placed '::' */
985
			return(t);
986
		}
2 7u83 987
 
6 7u83 988
		/* Look ahead to further tokens */
989
		crt_lookup = ns;
990
		crt_lookup_depth = depth;
991
		nt = expand_token(EXPAND_COLON_COLON);
992
		crt_lookup_depth = 0;
993
		if (nt == lex_nested_Hname) {
994
			nt = lex_full_Hname;
995
			this_tok->tok = lex_ignore_token;
996
			crt_token->tok = nt;
997
			return(nt);
2 7u83 998
		}
6 7u83 999
		if (nt == lex_nested_Hname_Hstar) {
1000
			if (crt_token == this_tok->next) {
1001
				IGNORE check_value(OPT_VAL_scope_qualifiers,
1002
						   depth);
1003
			}
1004
			nt = lex_full_Hname_Hstar;
1005
			this_tok->tok = lex_ignore_token;
1006
			crt_token->tok = nt;
1007
			return(nt);
1008
		}
1009
		IGNORE check_value(OPT_VAL_scope_qualifiers, depth);
1010
		this_tok->pp_data.ns = ns;
1011
		crt_lookup = ns;
1012
		crt_token = this_tok;
1013
		break;
2 7u83 1014
	}
1015
#endif
1016
 
1017
#if LANGUAGE_CPP
6 7u83 1018
	case lex_full_Hname:
1019
	case lex_nested_Hname: {
1020
		/* Deal with stored nested names (C++ only) */
1021
		int nt;
1022
		ns = this_tok->pp_data.ns;
1023
		crt_lookup = ns;
1024
		crt_lookup_depth++;
1025
		nt = expand_token(EXPAND_COLON_COLON);
1026
		crt_lookup_depth = 0;
1027
		if (nt == lex_nested_Hname) {
1028
			this_tok->tok = lex_ignore_token;
1029
			crt_token->tok = t;
1030
			return(nt);
1031
		}
1032
		if (nt == lex_nested_Hname_Hstar) {
1033
			if (t == lex_full_Hname)nt = lex_full_Hname_Hstar;
1034
			this_tok->tok = lex_ignore_token;
1035
			crt_token->tok = nt;
1036
			return(nt);
1037
		}
1038
		crt_lookup = ns;
1039
		crt_token = this_tok;
1040
		break;
2 7u83 1041
	}
1042
#endif
1043
 
1044
#if LANGUAGE_CPP
6 7u83 1045
	case lex_star:
1046
		/* Deal with pointer to members (C++ only) */
1047
		if (store == EXPAND_COLON_COLON && crt_lookup_depth) {
1048
			IDENTIFIER cid = DEREF_id(nspace_name(ns));
1049
			t = lex_nested_Hname_Hstar;
1050
			this_tok->tok = t;
1051
			this_tok->pp_data.id.use = cid;
1052
		}
1053
		break;
2 7u83 1054
#endif
1055
 
1056
#if LANGUAGE_CPP
6 7u83 1057
	case lex_compl_H1:
1058
compl_label:
1059
		/* Deal with destructors (C++ only) */
1060
		if (store != EXPAND_COLON_COLON) {
1061
			int nt;
1062
			crt_lookup = ns;
1063
			nt = expand_token(EXPAND_DESTRUCTOR);
1064
			if (nt == lex_destructor_Hname) {
1065
				int d = predict_destr(ns);
1066
				if (d) {
1067
					this_tok->tok = lex_ignore_token;
1068
					this_tok = crt_token;
1069
					t = this_tok->tok;
1070
					if (t == lex_template_Htype) {
1071
						/* Template class destructors */
1072
						IDENTIFIER id =
1073
						    this_tok->pp_data.tok.id;
1074
						PPTOKEN *args =
1075
						    this_tok->pp_data.tok.args;
1076
						HASHID nm =
1077
						    DEREF_hashid(id_name(id));
1078
						id = parse_type_template(id,
1079
									 args,
1080
									 1);
1081
						id = find_destr_id(id);
1082
						this_tok->pp_data.id.hash = nm;
1083
						this_tok->pp_data.id.use = id;
1084
					} else {
1085
						/* Simple destructors */
1086
						IDENTIFIER id =
1087
						    this_tok->pp_data.id.use;
1088
						HASHID nm =
1089
						    this_tok->pp_data.id.hash;
1090
						check_destr_id(id, nm, d);
1091
					}
1092
					this_tok->tok = nt;
1093
					return(nt);
1094
				}
2 7u83 1095
			}
6 7u83 1096
			crt_token = this_tok;
2 7u83 1097
		}
6 7u83 1098
		break;
2 7u83 1099
#endif
1100
 
6 7u83 1101
	case lex_integer_Hlit: {
1102
		/* Deal with integer and floating point literals */
1103
		int nt;
1104
		int pn = pragma_number;
1105
		OPTIONS *opts = crt_opts;
1106
		OPTIONS *nopts = this_tok->pp_opts;
1107
		string n = this_tok->pp_data.text;
1108
		if (opts != nopts)set_mode(nopts);
1109
		this_tok->pp_data.exp = make_literal_exp(n, &nt, pn);
1110
		this_tok->tok = nt;
1111
		if (opts != nopts)set_mode(opts);
1112
		t = nt;
1113
		break;
2 7u83 1114
	}
1115
 
6 7u83 1116
	case lex_char_Hlit:
1117
	case lex_wchar_Hlit: {
1118
		/* Deal with character literals */
1119
		STRING s;
1120
		OPTIONS *opts = crt_opts;
1121
		OPTIONS *nopts = this_tok->pp_opts;
1122
		string sb = this_tok->pp_data.str.start;
1123
		string se = this_tok->pp_data.str.end;
1124
		if (opts != nopts)set_mode(nopts);
1125
		s = new_string_lit(sb, se, t);
1126
		if (t == lex_char_Hlit) {
1127
			t = lex_char_Hexp;
1128
		} else {
1129
			t = lex_wchar_Hexp;
1130
		}
1131
		this_tok->pp_data.exp = make_string_exp(s);
1132
		this_tok->tok = t;
1133
		if (opts != nopts)set_mode(opts);
1134
		break;
2 7u83 1135
	}
1136
 
6 7u83 1137
	case lex_string_Hlit:
1138
	case lex_wstring_Hlit: {
1139
		/* Deal with string literals */
1140
		int nt;
1141
		STRING s;
1142
		OPTIONS *opts = crt_opts;
1143
		OPTIONS *nopts = this_tok->pp_opts;
1144
		string sb = this_tok->pp_data.str.start;
1145
		string se = this_tok->pp_data.str.end;
1146
		if (opts != nopts) {
1147
			set_mode(nopts);
1148
		}
1149
		s = new_string_lit(sb, se, t);
2 7u83 1150
 
6 7u83 1151
		/* Concatenate adjacent strings */
1152
		nt = expand_token(EXPAND_STRING);
1153
		if (nt == lex_string_Hlit || nt == lex_wstring_Hlit) {
1154
			/* Combine the following string with this one */
1155
			if (nt != t) {
1156
				/* String types don't match */
1157
				report(crt_loc, ERR_lex_string_concat());
1158
				t = lex_wstring_Hlit;
1159
			}
1160
			s = concat_string_lit(s, crt_token->pp_data.strlit);
1161
			crt_token->tok = lex_ignore_token;
2 7u83 1162
		}
6 7u83 1163
		crt_token = this_tok;
1164
		if (store == EXPAND_STRING) {
1165
			/* Continue concatenation */
1166
			this_tok->pp_data.strlit = s;
2 7u83 1167
		} else {
6 7u83 1168
			/* Transform string literal into expression */
1169
			if (t == lex_string_Hlit) {
1170
				t = lex_string_Hexp;
1171
			} else {
1172
				t = lex_wstring_Hexp;
1173
			}
1174
			this_tok->pp_data.exp = make_string_exp(s);
1175
			this_tok->tok = t;
2 7u83 1176
		}
6 7u83 1177
		if (opts != nopts) {
1178
			set_mode(opts);
1179
		}
1180
		break;
2 7u83 1181
	}
1182
 
6 7u83 1183
	case lex_ellipsis:
1184
		/* Ellipses */
1185
		if (store == EXPAND_NORMAL) {
1186
			OPTION opt = option(OPT_ellipsis_ident);
1187
			NAMESPACE cns = crt_namespace;
1188
			if (opt != OPTION_DISALLOW && IS_nspace_block(cns)) {
1189
				t = lex_ellipsis_Hexp;
1190
				this_tok->tok = t;
1191
			}
2 7u83 1192
		}
6 7u83 1193
		break;
2 7u83 1194
 
6 7u83 1195
	case lex_hash_H2:
1196
	case lex_hash_Hhash_H2:
1197
	case lex_open_Hbrace_H2:
1198
	case lex_open_Hsquare_H2:
1199
	case lex_close_Hbrace_H2:
1200
	case lex_close_Hsquare_H2:
1201
		/* Digraphs */
1202
		t = get_digraph(t);
1203
		this_tok->tok = t;
1204
		break;
2 7u83 1205
 
6 7u83 1206
	case lex_and_H2:
1207
	case lex_and_Heq_H2:
1208
	case lex_compl_H2:
1209
	case lex_logical_Hand_H2:
1210
	case lex_logical_Hor_H2:
1211
	case lex_not_H2:
1212
	case lex_not_Heq_H2:
1213
	case lex_or_H2:
1214
	case lex_or_Heq_H2:
1215
	case lex_xor_H2:
1216
	case lex_xor_Heq_H2: {
1217
		/* ISO keywords */
1218
		int tt;
1219
		IDENTIFIER id = this_tok->pp_data.id.use;
1220
		t = (int)DEREF_ulong(id_no(id));
1221
		tt = primary_form(t);
1222
		if (tt != t) {
1223
			HASHID nm;
1224
			if (in_pragma_dir) {
1225
				break;
1226
			}
1227
			nm = this_tok->pp_data.id.hash;
1228
			report(crt_loc, ERR_lex_digraph_iso(nm, tt));
1229
			t = tt;
1230
		}
1231
		this_tok->tok = t;
2 7u83 1232
#if LANGUAGE_CPP
6 7u83 1233
		if (t == lex_compl_H1) {
1234
			goto compl_label;
1235
		}
2 7u83 1236
#endif
6 7u83 1237
		break;
2 7u83 1238
	}
1239
 
6 7u83 1240
	case lex_unknown: {
1241
		/* Unknown characters */
1242
		unsigned long u;
1243
		int ch = CHAR_SIMPLE;
1244
		u = get_multi_char(this_tok->pp_data.buff, &ch);
1245
		if (ch == CHAR_SIMPLE) {
1246
			if (is_legal_char(u)) {
1247
				if (!is_white_char(u)) {
1248
					break;
1249
				}
1250
			} else {
1251
				int c = (int)u;
1252
				report(crt_loc, ERR_lex_pptoken_unknown(c));
1253
			}
2 7u83 1254
		} else {
6 7u83 1255
			report(crt_loc, ERR_lex_pptoken_unicode(u));
2 7u83 1256
		}
6 7u83 1257
		this_tok->tok = lex_ignore_token;
1258
		t = expand_token(store);
1259
		break;
2 7u83 1260
	}
6 7u83 1261
	}
1262
	return(t);
2 7u83 1263
}
1264
 
1265
 
1266
/*
1267
    READ AND EXPAND THE NEXT TOKEN (PREPROCESSOR VERSION)
1268
 
1269
    This routine is a cut-down version of expand_token with only the macro
1270
    expansion and keyword actions.  This is for use with the stand-alone
1271
    preprocessor and in the rewriting rules.
1272
*/
1273
 
6 7u83 1274
int
1275
expand_preproc(int store)
2 7u83 1276
{
6 7u83 1277
	int t;
1278
	int expand;
1279
	PPTOKEN *prev_tok = crt_token;
1280
	PPTOKEN *this_tok = prev_tok->next;
2 7u83 1281
 
6 7u83 1282
	/* Get the next token */
1283
start_label:
1284
	if (this_tok == NULL) {
1285
		/* Read the token from the file */
1286
		this_tok = new_pptok();
1287
		this_tok->next = NULL;
1288
		prev_tok->next = this_tok;
1289
		crt_token = this_tok;
1290
		t = read_token();
1291
		update_column();
1292
		this_tok->tok = t;
1293
		if (t <= LAST_COMPLEX_TOKEN) {
1294
			token_parts(t, this_tok);
1295
		}
2 7u83 1296
 
6 7u83 1297
		if (store == EXPAND_NORMAL) {
1298
			/* Garbage collect stored tokens */
1299
			this_tok->pp_space = 0;
1300
			prev_tok->next = free_tokens;
1301
			free_tokens = first_token;
1302
			first_token = this_tok;
1303
		} else {
1304
			this_tok->pp_space = crt_loc.column;
1305
			if (crt_line_changed) {
1306
				/* Record file position */
1307
				make_loc_tokens(prev_tok);
1308
			}
2 7u83 1309
		}
6 7u83 1310
		expand = 1;
2 7u83 1311
 
1312
	} else {
6 7u83 1313
		/* Use a previously stored token */
1314
		if (this_tok->pp_space) {
1315
			/* Increase space count if necessary */
1316
			if (!crt_line_changed) {
1317
				crt_spaces++;
1318
			}
1319
			if (store == EXPAND_AHEAD) {
1320
				this_tok->pp_space = 0;
1321
			}
1322
		}
1323
		t = this_tok->tok;
1324
		if (t == lex_ignore_token) {
1325
			/* Step over any ignored tokens */
1326
			prev_tok = this_tok;
1327
			this_tok = this_tok->next;
1328
			goto start_label;
1329
		}
1330
		crt_token = this_tok;
1331
		expand = 0;
2 7u83 1332
	}
1333
 
6 7u83 1334
	/* Deal with context switch */
1335
	if (store == EXPAND_NORMAL) {
1336
		OPTIONS *opts = prev_opts;
1337
		if (opts != crt_opts) {
1338
			set_mode(opts);
1339
		}
1340
		prev_opts = this_tok->pp_opts;
1341
	}
2 7u83 1342
 
6 7u83 1343
	/* Deal with identifiers */
1344
	if (t == lex_identifier) {
1345
		HASHID nm = this_tok->pp_data.id.hash;
1346
		IDENTIFIER id = DEREF_id(hashid_id(nm));
1347
expand_label:
1348
		switch (TAG_id(id)) {
1349
		case id_obj_macro_tag:
1350
		case id_func_macro_tag:
1351
			if (expand) {
1352
				PPTOKEN *toks = expand_macro(nm, file_loc, 1);
1353
				if (!crt_line_changed)crt_spaces++;
1354
				this_tok->tok = lex_ignore_token;
1355
				this_tok->next = toks;
1356
				prev_tok = this_tok;
1357
				this_tok = toks;
1358
				goto start_label;
2 7u83 1359
			}
6 7u83 1360
			id = DEREF_id(id_alias(id));
1361
			goto expand_label;
1362
		case id_keyword_tag:
1363
			if (store == EXPAND_AHEAD) {
1364
				t = (int)DEREF_ulong(id_no(id));
1365
				this_tok->tok = t;
1366
			}
1367
			break;
1368
		case id_iso_keyword_tag:
1369
			if (store == EXPAND_AHEAD) {
1370
				t = (int)DEREF_ulong(id_no(id));
1371
				if (t >= FIRST_SYMBOL && t <= LAST_SYMBOL) {
1372
					/* Will be reinterpreted later */
1373
					t = lex_and_H2;
1374
				}
1375
				this_tok->tok = t;
1376
			}
1377
			break;
2 7u83 1378
		}
6 7u83 1379
		this_tok->pp_data.id.use = id;
2 7u83 1380
	}
6 7u83 1381
	return(t);
2 7u83 1382
}
1383
 
1384
 
1385
/*
1386
    PARSE A TEMPLATE IDENTIFIER
1387
 
1388
    This routine is called after the optional 'template' at the start of
1389
    a qualified identifier or a field member selector.  It forces the
1390
    following identifier to be treated as a template-id even if it doesn't
1391
    seem to be one.
1392
*/
1393
 
6 7u83 1394
void
1395
rescan_template(NAMESPACE ns)
2 7u83 1396
{
6 7u83 1397
	PPTOKEN *p = crt_token;
1398
	crt_lookup = ns;
1399
	have_template = 0;
1400
	IGNORE expand_token(EXPAND_TEMPLATE);
1401
	if (!have_template) {
1402
		/* Didn't read template-id */
1403
		report(crt_loc, ERR_temp_names_bad());
1404
	}
1405
	crt_token = p;
1406
	crt_lookup = ns;
1407
	return;
2 7u83 1408
}