Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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