Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 2
 * Copyright (c) 2002-2006 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
7 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
7 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
7 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
7 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
7 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#include <limits.h>
63
#include "c_types.h"
64
#include "ctype_ops.h"
65
#include "exp_ops.h"
66
#include "hashid_ops.h"
67
#include "id_ops.h"
68
#include "member_ops.h"
69
#include "nat_ops.h"
70
#include "nspace_ops.h"
71
#include "off_ops.h"
72
#include "tok_ops.h"
73
#include "type_ops.h"
74
#include "error.h"
75
#include "catalog.h"
76
#include "option.h"
77
#include "access.h"
78
#include "basetype.h"
79
#include "check.h"
80
#include "chktype.h"
81
#include "class.h"
82
#include "constant.h"
83
#include "convert.h"
84
#include "derive.h"
85
#include "dump.h"
86
#include "exception.h"
87
#include "expression.h"
88
#include "file.h"
89
#include "function.h"
90
#include "hash.h"
91
#include "identifier.h"
92
#include "initialise.h"
93
#include "inttype.h"
94
#include "lex.h"
95
#include "macro.h"
96
#include "member.h"
97
#include "namespace.h"
98
#include "overload.h"
99
#include "parse.h"
100
#include "predict.h"
101
#include "preproc.h"
102
#include "redeclare.h"
103
#include "statement.h"
104
#include "syntax.h"
105
#include "template.h"
106
#include "tokdef.h"
107
#include "token.h"
108
 
109
 
110
/*
111
    TOKEN DEFINITION FLAG
112
 
113
    Tokens are defined by the equality routines if the flag force_tokdef
114
    is set.  This is only done if we are reasonably sure that the equality
115
    should hold.  Similarly template specialisation is only considered
116
    if force_template is true.
117
*/
118
 
7 7u83 119
int force_tokdef = 0;
120
int force_template = 0;
121
int expand_tokdef = 0;
2 7u83 122
 
123
 
124
/*
125
    IS A TOKEN BEING DEFINED?
126
 
127
    This routine uses the values force_tokdef and force_template to
128
    determine whether the token id is available for token unification.
129
*/
130
 
7 7u83 131
int
132
defining_token(IDENTIFIER id)
2 7u83 133
{
7 7u83 134
	if (!IS_NULL_id(id) && IS_id_token(id)) {
135
		DECL_SPEC ds;
136
		if (force_tokdef) {
137
			return (1);
138
		}
139
		ds = DEREF_dspec(id_storage(id));
140
		if (ds & dspec_template) {
141
			return (force_template);
142
		}
143
	}
144
	return (0);
2 7u83 145
}
146
 
147
 
148
/*
149
    FIND THE RESULT COMPONENT OF A TOKEN
150
 
151
    This routine finds the result component of the token id.
152
*/
153
 
7 7u83 154
TOKEN
155
find_tokdef(IDENTIFIER id)
2 7u83 156
{
7 7u83 157
	TOKEN tok = NULL_tok;
158
	if (!IS_NULL_id(id) && IS_id_token(id)) {
159
		unsigned tag;
160
		tok = DEREF_tok(id_token_sort(id));
161
		tag = TAG_tok(tok);
162
		if (tag == tok_func_tag) {
163
			TOKEN ptok = DEREF_tok(tok_func_proc(tok));
164
			if (!IS_NULL_tok(ptok)) {
165
				tok = DEREF_tok(tok_proc_res(ptok));
166
			}
167
		} else if (tag == tok_proc_tag) {
168
			tok = DEREF_tok(tok_proc_res(tok));
169
		}
2 7u83 170
	}
7 7u83 171
	return (tok);
2 7u83 172
}
173
 
174
 
175
/*
176
    DUMMY TOKEN PARAMETER VALUES
177
 
178
    These values are used to indicate that a token parameter has been
179
    redefined inconsistently.
180
*/
181
 
7 7u83 182
static NAT redef_nat = NULL_nat;
183
static EXP redef_exp = NULL_exp;
184
TYPE redef_type = NULL_type;
185
static IDENTIFIER redef_id = NULL_id;
186
static OFFSET redef_off = NULL_off;
2 7u83 187
 
188
 
189
/*
190
    INITIALISE DUMMY TOKEN PARAMETER VALUES
191
 
192
    This routine initialises the dummy token parameter values above.
193
    They are set to impossible values which could not arise naturally.
194
*/
195
 
7 7u83 196
void
197
init_token_args(void)
2 7u83 198
{
7 7u83 199
	HASHID nm = KEYWORD(lex_error);
200
	redef_id = DEREF_id(hashid_id(nm));
201
	MAKE_type_ref(cv_none, type_void, redef_type);
202
	MAKE_exp_value(redef_type, redef_exp);
203
	MAKE_nat_calc(redef_exp, redef_nat);
204
	MAKE_off_zero(redef_type, redef_off);
205
	return;
2 7u83 206
}
207
 
208
 
209
/*
210
    DEFINE AN INTEGER CONSTANT TOKEN
211
 
212
    This routine defines the integer constant token id to be e.  It
213
    returns true if the token is assigned a value.
214
*/
215
 
7 7u83 216
int
217
define_nat_token(IDENTIFIER id, NAT n)
2 7u83 218
{
7 7u83 219
	if (!IS_NULL_nat(n)) {
220
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
221
		if (!(ds & dspec_pure)) {
222
			int ok = 1;
223
			TOKEN tok = find_tokdef(id);
224
			if (IS_NULL_tok(tok)) {
225
				return (0);
2 7u83 226
			}
7 7u83 227
			switch (TAG_tok(tok)) {
228
			case tok_nat_tag:
229
			case tok_snat_tag: {
230
				/* Integer constant tokens */
231
				NAT m = DEREF_nat(tok_nat_etc_value(tok));
232
				if (!IS_NULL_nat(m) && !eq_nat(n, m)) {
233
					if (ds & dspec_auto) {
234
						n = redef_nat;
235
					} else {
236
						PTR(LOCATION) loc = id_loc(id);
237
						report(crt_loc, ERR_token_redef(id, loc));
238
					}
239
					ok = 0;
240
				}
241
				COPY_nat(tok_nat_etc_value(tok), n);
242
				break;
243
			}
244
			case tok_exp_tag:
245
			case tok_stmt_tag: {
246
				/* Expression tokens */
247
				EXP e = calc_nat_value(n, type_sint);
248
				return (define_exp_token(id, e, 1));
249
			}
250
			default:
251
				/* Other tokens */
252
				return (0);
253
			}
254
 
255
			if (!(ds & dspec_auto)) {
256
				no_token_defns++;
257
			}
258
			ds |= dspec_defn;
259
			COPY_dspec(id_storage(id), ds);
260
			COPY_loc(id_loc(id), crt_loc);
261
			return (ok);
2 7u83 262
		}
263
	}
7 7u83 264
	return (0);
2 7u83 265
}
266
 
267
 
268
/*
269
    DEFINE AN EXPRESSION TOKEN
270
 
271
    This routine defines the expression, statement or integer constant
272
    token id to be e.  It returns true if the token is assigned a value.
273
    expl is false for an enforcing external declaration, such as that
274
    arising from unify_id.
275
*/
276
 
7 7u83 277
int
278
define_exp_token(IDENTIFIER id, EXP e, int expl)
2 7u83 279
{
7 7u83 280
    if (!IS_NULL_exp(e)) {
281
	DECL_SPEC ds = DEREF_dspec(id_storage(id));
282
	if (!(ds & dspec_pure)) {
283
	    int ok = 1;
284
	    unsigned tt;
285
	    TOKEN tok = find_tokdef(id);
286
	    if (IS_NULL_tok(tok)) {
287
		    return (0);
288
	    }
289
	    tt = TAG_tok(tok);
290
	    switch (tt) {
291
		case tok_exp_tag: {
2 7u83 292
		    /* Expression tokens */
7 7u83 293
		    TYPE s;
294
		    ERROR err = NULL_err;
295
		    unsigned etag = TAG_exp(e);
296
		    EXP d = DEREF_exp(tok_exp_value(tok));
297
		    int c = DEREF_int(tok_exp_constant(tok));
298
		    TYPE t = DEREF_type(tok_exp_type(tok));
299
		    CV_SPEC cv = DEREF_cv(type_qual(t));
300
		    LIST(IDENTIFIER) pids = NULL_list(IDENTIFIER);
301
		    force_tokdef++;
302
		    e = convert_reference(e, REF_ASSIGN);
303
		    e = resolve_cast(t, e, &err, 1, 0, pids);
304
		    s = DEREF_type(exp_type(e));
305
		    if (cv & cv_lvalue) {
2 7u83 306
			/* lvalue tokens */
7 7u83 307
			cv = DEREF_cv(type_qual(s));
308
			if (cv & cv_lvalue) {
309
			    if (eq_type(s, t)) {
310
				if (!IS_exp_address(e)) {
311
				    MAKE_exp_address(t, e, e);
2 7u83 312
				}
313
			    } else {
7 7u83 314
				EXP a = init_ref_lvalue(t, e, &err);
315
				if (IS_NULL_exp(a)) {
316
				    err = ERR_basic_link_incompat(t, s);
2 7u83 317
				} else {
7 7u83 318
				    e = make_ref_init(t, a);
2 7u83 319
				}
320
			    }
321
			} else {
7 7u83 322
			    report(crt_loc, ERR_token_arg_lvalue(id));
2 7u83 323
			}
324
		    } else {
325
			/* rvalue tokens */
7 7u83 326
			if (IS_exp_aggregate(e)) {
2 7u83 327
			    /* Aggregate initialiser */
7 7u83 328
			    e = init_aggregate(t, e, id, &err);
2 7u83 329
			} else {
7 7u83 330
			    switch (TAG_type(t)) {
331
				case type_top_tag:
332
				case type_bottom_tag:
2 7u83 333
				    /* Void expressions */
7 7u83 334
				    e = convert_lvalue(e);
335
				    e = convert_none(e);
336
				    e = make_discard_exp(e);
337
				    if (!IS_type_top_etc(s)) {
338
					EXP a = make_null_exp(t);
339
					e = join_exp(e, a);
2 7u83 340
				    }
7 7u83 341
				    break;
342
				case type_ref_tag:
2 7u83 343
				    /* Reference initialiser */
7 7u83 344
				    e = init_assign(t, cv_none, e, &err);
345
				    break;
346
				case type_array_tag:
2 7u83 347
				    /* Array initialiser */
7 7u83 348
				    if (etag == exp_paren_tag) {
349
					e = make_paren_exp(e);
2 7u83 350
				    }
7 7u83 351
				    e = init_array(t, cv_none, e, 1, &err);
352
				    break;
353
				case type_error_tag:
354
				    e = convert_none(e);
355
				    break;
356
				default:
2 7u83 357
				    /* Simple initialiser */
7 7u83 358
				    e = convert_lvalue(e);
359
				    e = init_assign(t, cv_none, e, &err);
360
				    break;
2 7u83 361
			    }
362
			}
363
		    }
7 7u83 364
		    force_tokdef--;
365
		    if (!IS_NULL_err(err)) {
2 7u83 366
			/* Conversion error */
7 7u83 367
			err = init_error(err, 0);
368
			err = concat_error(err, ERR_token_arg_exp(id));
369
			report(crt_loc, err);
2 7u83 370
		    }
7 7u83 371
		    if (c == 1 && !is_const_exp(e, 1)) {
372
			report(crt_loc, ERR_token_arg_const(id));
2 7u83 373
		    }
7 7u83 374
		    if (!IS_NULL_exp(d) && !eq_exp(e, d, 0)) {
375
			int redef = 0;
376
			if (ds & dspec_auto) {
377
			    e = redef_exp;
2 7u83 378
			} else {
7 7u83 379
			    if (expl) {
380
				if (ds & dspec_main) {
381
				    redef = 1;
2 7u83 382
				} else {
7 7u83 383
				    ds |= dspec_main;
2 7u83 384
				}
385
			    } else {
7 7u83 386
				if (ds & dspec_main) {
387
				    e = d;
2 7u83 388
				} else {
7 7u83 389
				    redef = 1;
2 7u83 390
				}
391
			    }
392
			}
7 7u83 393
			if (redef) {
394
			    PTR(LOCATION) loc = id_loc(id);
395
			    report(crt_loc, ERR_token_redef(id, loc));
396
			    ok = 0;
2 7u83 397
			}
398
		    } else {
7 7u83 399
			if (expl && !(ds & dspec_auto)) {
2 7u83 400
			    /* Mark explicit definitions */
7 7u83 401
			    ds |= dspec_main;
2 7u83 402
			}
403
		    }
7 7u83 404
		    COPY_exp(tok_exp_value(tok), e);
405
		    break;
2 7u83 406
		}
407
 
7 7u83 408
		case tok_nat_tag:
409
		case tok_snat_tag: {
2 7u83 410
		    /* Constant tokens */
7 7u83 411
		    NAT n;
412
		    ERROR err = NULL_err;
413
		    e = convert_reference(e, REF_NORMAL);
414
		    e = convert_lvalue(e);
415
		    n = make_nat_exp(e, &err);
416
		    if (!IS_NULL_err(err)) {
2 7u83 417
			/* Not a constant expression */
7 7u83 418
			err = concat_error(err, ERR_token_arg_nat(id));
419
			report(crt_loc, err);
2 7u83 420
		    } else {
7 7u83 421
			if (tt == tok_nat_tag && is_negative_nat(n)) {
2 7u83 422
			    /* Negative constant */
7 7u83 423
			    report(crt_loc, ERR_token_arg_nat(id));
424
			    n = negate_nat(n);
2 7u83 425
			}
426
		    }
7 7u83 427
		    return (define_nat_token(id, n));
2 7u83 428
		}
429
 
7 7u83 430
		case tok_stmt_tag: {
2 7u83 431
		    /* Statement tokens */
7 7u83 432
		    EXP d = DEREF_exp(tok_stmt_value(tok));
433
		    if (!IS_NULL_exp(d) && !eq_exp(e, d, 0)) {
434
			if (ds & dspec_auto) {
435
			    e = redef_exp;
2 7u83 436
			} else {
7 7u83 437
			    PTR(LOCATION) loc = id_loc(id);
438
			    report(crt_loc, ERR_token_redef(id, loc));
2 7u83 439
			}
7 7u83 440
			ok = 0;
2 7u83 441
		    }
7 7u83 442
		    COPY_exp(tok_stmt_value(tok), e);
443
		    break;
2 7u83 444
		}
445
 
7 7u83 446
		default:
2 7u83 447
		    /* Other tokens */
7 7u83 448
		    return (0);
2 7u83 449
	    }
7 7u83 450
	    if (!(ds & dspec_auto)) {
451
		    no_token_defns++;
452
	    }
453
	    ds |= dspec_defn;
454
	    COPY_dspec(id_storage(id), ds);
455
	    COPY_loc(id_loc(id), crt_loc);
456
	    return (ok);
2 7u83 457
	}
458
    }
7 7u83 459
    return (0);
2 7u83 460
}
461
 
462
 
463
/*
464
    DEFINE THE FIELDS OF A TYPE TOKEN
465
 
466
    This routine is called when a tokenised structure or union id is defined
467
    by the compound type t.  It checks for any tokenised members of id
468
    which may also be defined as a result of this identification.  This
469
    should really be done by the class merging routines.
470
*/
471
 
7 7u83 472
static void
473
define_field_tokens(IDENTIFIER id, TYPE t)
2 7u83 474
{
7 7u83 475
    IDENTIFIER tid = DEREF_id(id_token_alt(id));
476
    unsigned tag = TAG_id(tid);
477
    if (tag == id_class_name_tag || tag == id_class_alias_tag) {
478
	TYPE s = DEREF_type(id_class_name_etc_defn(tid));
479
	if (IS_type_compound(s) && IS_type_compound(t)) {
480
	    MEMBER mem;
481
	    CLASS_TYPE cs = DEREF_ctype(type_compound_defn(s));
482
	    CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
483
	    NAMESPACE ns = DEREF_nspace(ctype_member(cs));
484
	    NAMESPACE nt = DEREF_nspace(ctype_member(ct));
2 7u83 485
 
486
	    /* Check that keys match for type aliases */
7 7u83 487
	    if (tag == id_class_alias_tag) {
488
		BASE_TYPE bs = find_class_key(cs);
489
		BASE_TYPE bt = find_class_key(ct);
490
		if (!equal_key(bs, bt)) {
491
		    PTR(LOCATION) loc = id_loc(id);
492
		    ERROR err = ERR_dcl_type_elab_bad(bt, bs, id, loc);
493
		    report(crt_loc, err);
2 7u83 494
		}
495
	    }
496
 
497
	    /* Scan through members of ns */
7 7u83 498
	    mem = DEREF_member(nspace_ctype_first(ns));
499
	    while (!IS_NULL_member(mem)) {
500
		IDENTIFIER mid = DEREF_id(member_id(mem));
501
		if (!IS_NULL_id(mid) && IS_id_member(mid)) {
502
		    DECL_SPEC ds = DEREF_dspec(id_storage(mid));
503
		    if (ds & dspec_token) {
2 7u83 504
			/* Tokenised member found */
7 7u83 505
			HASHID nm = DEREF_hashid(id_name(mid));
506
			IDENTIFIER nid = search_field(nt, nm, 0, 0);
507
			if (!IS_NULL_id(nid)) {
2 7u83 508
			    /* Token definition found */
7 7u83 509
			    IDENTIFIER tok = find_token(mid);
510
			    ds = DEREF_dspec(id_storage(tok));
511
			    if (ds & dspec_pure) {
512
				LOCATION loc;
513
				DEREF_loc(id_loc(nid), loc);
514
				report(loc, ERR_token_def_not(nid));
2 7u83 515
			    } else {
7 7u83 516
				OFFSET off;
517
				TYPE r = NULL_type;
518
				off = offset_member(t, nid, &r, nt, 0);
519
				IGNORE define_mem_token(tok, off, r, 1);
2 7u83 520
			    }
521
			} else {
522
			    /* Copy tokenised member */
7 7u83 523
			    MEMBER mem2 = search_member(nt, nm, 1);
524
			    mid = copy_id(mid, 0);
525
			    COPY_nspace(id_parent(mid), nt);
526
			    set_member(mem2, mid);
2 7u83 527
			}
528
		    }
529
		}
7 7u83 530
		mem = DEREF_member(member_next(mem));
2 7u83 531
	    }
532
 
533
	    /* Scan through members of nt */
7 7u83 534
	    mem = DEREF_member(nspace_ctype_first(nt));
535
	    while (!IS_NULL_member(mem)) {
536
		MEMBER mem2 = NULL_member;
537
		IDENTIFIER mid = DEREF_id(member_id(mem));
538
		IDENTIFIER nid = DEREF_id(member_alt(mem));
539
		if (!IS_NULL_id(mid)) {
540
		    IDENTIFIER pid;
541
		    HASHID nm = DEREF_hashid(id_name(mid));
542
		    mem2 = search_member(ns, nm, 1);
543
		    mid = copy_id(mid, 0);
544
		    COPY_nspace(id_parent(mid), ns);
545
		    pid = DEREF_id(member_id(mem2));
546
		    if (IS_NULL_id(pid)) {
547
			set_member(mem2, mid);
2 7u83 548
		    }
549
		}
7 7u83 550
		if (!IS_NULL_id(nid) && !EQ_id(mid, nid)) {
551
		    if (IS_NULL_member(mem2)) {
552
			HASHID nm = DEREF_hashid(id_name(nid));
553
			mem2 = search_member(ns, nm, 1);
2 7u83 554
		    }
7 7u83 555
		    nid = copy_id(nid, 0);
556
		    COPY_nspace(id_parent(nid), ns);
557
		    if (!IS_NULL_id(nid)) {
558
			set_type_member(mem2, mid);
2 7u83 559
		    }
560
		}
7 7u83 561
		mem = DEREF_member(member_next(mem));
2 7u83 562
	    }
563
	}
564
    }
7 7u83 565
    return;
2 7u83 566
}
567
 
568
 
569
/*
570
    CHECK A TYPE CATEGORY
571
 
572
    This routine checks whether the type t of category ca can be used to
573
    define a token of kind bt.
574
*/
575
 
7 7u83 576
static int
577
match_type_token(BASE_TYPE bt, unsigned ca, TYPE t)
2 7u83 578
{
7 7u83 579
	int ok = 1;
580
	if (bt & btype_star) {
581
		/* Scalar types */
582
		if (!IS_TYPE_SCALAR(ca)) {
583
			ok = 0;
584
		}
585
	} else if (bt & btype_float) {
586
		/* Arithmetic types */
587
		if (bt & btype_int) {
588
			if (!IS_TYPE_ARITH(ca)) {
589
				ok = 0;
590
			}
591
		} else {
592
			if (!IS_TYPE_FLOAT(ca)) {
593
				ok = 0;
594
			}
595
		}
596
	} else if (bt & btype_int) {
597
		/* Integral types */
598
		if (IS_TYPE_INT(ca)) {
599
			if (bt & btype_signed) {
600
				if (check_int_type(t, btype_unsigned)) {
601
					ok = 0;
602
				}
603
			} else if (bt & btype_unsigned) {
604
				if (check_int_type(t, btype_signed)) {
605
					ok = 0;
606
				}
607
			}
608
		} else {
609
			ok = 0;
610
		}
2 7u83 611
	}
7 7u83 612
	return (ok);
2 7u83 613
}
614
 
615
 
616
/*
617
    DEFINE A TYPE TOKEN
618
 
619
    This routine defines the type token id to be t.  It returns true if
620
    the token is assigned a value.  qual is as in check_compatible.
621
*/
622
 
7 7u83 623
int
624
define_type_token(IDENTIFIER id, TYPE t, int qual)
2 7u83 625
{
7 7u83 626
    if (!IS_NULL_type(t)) {
627
	DECL_SPEC ds = DEREF_dspec(id_storage(id));
628
	if (!(ds & dspec_pure)) {
629
	    TYPE s;
630
	    int ok = 1;
631
	    int check_promote = 0;
632
	    TOKEN tok = find_tokdef(id);
633
	    if (IS_NULL_tok(tok) || !IS_tok_type(tok)) {
634
		    return (0);
635
	    }
636
	    s = DEREF_type(tok_type_value(tok));
637
	    if (!IS_NULL_type(s)) {
638
		ERROR err = NULL_err;
639
		t = check_compatible(s, t, qual, &err, 1);
640
		if (!IS_NULL_err(err)) {
641
		    if (ds & dspec_auto) {
642
			destroy_error(err, 1);
643
			t = redef_type;
2 7u83 644
		    } else {
7 7u83 645
			ERROR err2;
646
			err2 = ERR_token_redef(id, id_loc(id));
647
			err = concat_error(err, err2);
648
			report(crt_loc, err);
2 7u83 649
		    }
7 7u83 650
		    ok = 0;
2 7u83 651
		}
652
	    } else {
7 7u83 653
		unsigned ca = type_category(&t);
654
		BASE_TYPE bt = DEREF_btype(tok_type_kind(tok));
655
		if (!(bt & btype_template)) {
2 7u83 656
		    /* Tokens */
7 7u83 657
		    ERROR err = NULL_err;
658
		    switch (TAG_type(t)) {
659
			case type_ref_tag:
660
			case type_func_tag:
661
			case type_bitfield_tag:
2 7u83 662
			    /* These types can't be tokenised */
7 7u83 663
			    ok = 0;
664
			    break;
665
			case type_compound_tag:
2 7u83 666
			    /* Can only tokenise trivial classes */
7 7u83 667
			    if (bt != btype_none || !(ds & dspec_auto)) {
668
				CLASS_TYPE ct;
669
				ct = DEREF_ctype(type_compound_defn(t));
670
				err = check_trivial_class(ct);
671
				if (!IS_NULL_err(err))ok = 0;
2 7u83 672
			    }
7 7u83 673
			    break;
2 7u83 674
		    }
7 7u83 675
		    if (bt) {
676
			if (bt & btype_named) {
2 7u83 677
			    /* Structure and union types */
7 7u83 678
			    if (IS_type_compound(t)) {
679
				if (!(ds & dspec_auto)) {
2 7u83 680
				    /* Check structure fields */
7 7u83 681
				    define_field_tokens(id, t);
2 7u83 682
				}
683
			    } else {
7 7u83 684
				ok = 0;
2 7u83 685
			    }
686
			} else {
687
			    /* Check scalar types */
7 7u83 688
			    if (!match_type_token(bt, ca, t)) {
689
				    ok = 0;
690
			    }
2 7u83 691
			}
7 7u83 692
			if (bt & btype_int) {
693
				check_promote = ok;
694
			}
2 7u83 695
		    }
7 7u83 696
		    if (!ok) {
2 7u83 697
			/* Report any type mismatch errors */
7 7u83 698
			if (!IS_type_error(t)) {
699
			    int lex = type_token_key(bt);
700
			    ERROR err2 = ERR_token_arg_type(lex, id, t);
701
			    err = concat_error(err, err2);
702
			    report(crt_loc, err);
703
			    t = type_error;
2 7u83 704
			}
705
		    }
706
		}
7 7u83 707
		if (!IS_TYPE_INT(ca)) {
708
			check_promote = 0;
709
		}
2 7u83 710
	    }
7 7u83 711
	    COPY_type(tok_type_value(tok), t);
712
	    if (ds & dspec_auto) {
713
		check_promote = 0;
2 7u83 714
	    } else {
7 7u83 715
		no_token_defns++;
2 7u83 716
	    }
7 7u83 717
	    ds |= dspec_defn;
718
	    COPY_dspec(id_storage(id), ds);
719
	    COPY_loc(id_loc(id), crt_loc);
720
	    if (check_promote) {
2 7u83 721
		/* Check that promoted types are compatible */
7 7u83 722
		s = apply_itype_token(id, NULL_list(TOKEN));
723
		t = promote_type(t);
724
		set_promote_type(s, t, ntype_none);
2 7u83 725
	    }
7 7u83 726
	    return (ok);
2 7u83 727
	}
728
    }
7 7u83 729
    return (0);
2 7u83 730
}
731
 
732
 
733
/*
734
    DEFINE A TEMPLATE TEMPLATE PARAMETER
735
 
736
    This routine defines the template template parameter id to be the
737
    class given by tid.  It returns true if the parameter is assigned a
738
    value.
739
*/
740
 
7 7u83 741
int
742
define_templ_token(IDENTIFIER id, IDENTIFIER tid)
2 7u83 743
{
7 7u83 744
    if (!IS_NULL_id(tid)) {
745
	DECL_SPEC ds = DEREF_dspec(id_storage(id));
746
	if (!(ds & dspec_pure)) {
747
	    TOKEN tok = DEREF_tok(id_token_sort(id));
748
	    if (IS_tok_class(tok)) {
749
		int ok = 0;
750
		IDENTIFIER sid = DEREF_id(tok_class_value(tok));
751
		if (EQ_id(sid, tid)) {
752
			return (1);
753
		}
754
		if (IS_id_class_name_etc(tid)) {
755
		    TYPE t = DEREF_type(tok_class_type(tok));
756
		    TYPE s = DEREF_type(id_class_name_etc_defn(tid));
757
		    if (IS_type_templ(t) && IS_type_templ(s)) {
2 7u83 758
			/* Check for equality of template parameters */
7 7u83 759
			LIST(IDENTIFIER) ps, pt;
760
			TOKEN as = DEREF_tok(type_templ_sort(s));
761
			TOKEN at = DEREF_tok(type_templ_sort(t));
762
			ps = DEREF_list(tok_templ_pids(as));
763
			pt = DEREF_list(tok_templ_pids(at));
764
			ok = eq_templ_params(ps, pt);
765
			restore_templ_params(ps);
2 7u83 766
		    }
7 7u83 767
		    if (!ok) {
2 7u83 768
			/* Report illegal definitions */
7 7u83 769
			ERROR err = ERR_temp_arg_templ_bad(id, s);
770
			report(crt_loc, err);
2 7u83 771
		    }
7 7u83 772
		    if (!IS_NULL_id(sid)) {
2 7u83 773
			/* Check for redefinitions */
7 7u83 774
			if (ds & dspec_auto) {
775
			    tid = redef_id;
2 7u83 776
			} else {
7 7u83 777
			    PTR(LOCATION) loc = id_loc(id);
778
			    report(crt_loc, ERR_token_redef(id, loc));
2 7u83 779
			}
7 7u83 780
			ok = 0;
2 7u83 781
		    }
782
		} else {
7 7u83 783
		    ok = 0;
2 7u83 784
		}
7 7u83 785
		COPY_id(tok_class_value(tok), tid);
786
		if (!(ds & dspec_auto)) {
787
			no_token_defns++;
788
		}
789
		ds |= dspec_defn;
790
		COPY_dspec(id_storage(id), ds);
791
		COPY_loc(id_loc(id), crt_loc);
792
		return (ok);
2 7u83 793
	    }
794
	}
795
    }
7 7u83 796
    return (0);
2 7u83 797
}
798
 
799
 
800
/*
801
    DEFINE A MEMBER TOKEN
802
 
803
    This routine defines the member token id to be a member of offset off
804
    and type t.  It returns true if the token is assigned a value.  ext is
805
    true for an external token definition.
806
*/
807
 
7 7u83 808
int
809
define_mem_token(IDENTIFIER id, OFFSET off, TYPE t, int ext)
2 7u83 810
{
7 7u83 811
    if (!IS_NULL_off(off)) {
812
	DECL_SPEC ds = DEREF_dspec(id_storage(id));
813
	if ((ds & dspec_auto) && ext) {
814
	    ERROR err = ERR_class_mem_redecl(id, id_loc(id));
815
	    report(crt_loc, err);
816
	} else if (!(ds & dspec_pure)) {
817
	    TOKEN tok = find_tokdef(id);
818
	    if (!IS_NULL_tok(tok) && IS_tok_member(tok)) {
819
		TYPE u;
820
		ERROR err = NULL_err;
821
		TYPE s = DEREF_type(tok_member_type(tok));
822
		OFFSET d = DEREF_off(tok_member_value(tok));
823
		if (!IS_NULL_off(d) && !eq_offset(off, d, 0)) {
824
		    if (ds & dspec_auto) {
825
			off = redef_off;
2 7u83 826
		    } else {
7 7u83 827
			PTR(LOCATION) loc = id_loc(id);
828
			report(crt_loc, ERR_token_redef(id, loc));
2 7u83 829
		    }
830
		}
7 7u83 831
		u = check_compatible(s, t, 0, &err, 0);
832
		if (!IS_NULL_err(err)) {
2 7u83 833
		    /* Member type is wrong */
7 7u83 834
		    if (eq_type_offset(s, t)) {
2 7u83 835
			/* Types have same representation */
7 7u83 836
			err = set_severity(err, OPT_member_incompat, -1);
2 7u83 837
		    }
7 7u83 838
		    err = concat_error(err, ERR_token_arg_mem(id));
839
		    report(crt_loc, err);
2 7u83 840
		}
7 7u83 841
		COPY_off(tok_member_value(tok), off);
842
		if (!(ds & dspec_auto)) {
843
		    if (IS_type_error(s)) {
2 7u83 844
			/* Fill in type if not known */
7 7u83 845
			IDENTIFIER mid = DEREF_id(id_token_alt(id));
846
			COPY_type(tok_member_type(tok), u);
847
			u = lvalue_type(u);
848
			COPY_type(id_member_type(mid), u);
2 7u83 849
		    }
7 7u83 850
		    no_token_defns++;
2 7u83 851
		}
7 7u83 852
		ds |= dspec_defn;
853
		COPY_dspec(id_storage(id), ds);
854
		COPY_loc(id_loc(id), crt_loc);
855
		UNUSED(ext);
856
		return (1);
2 7u83 857
	    }
858
	}
859
    }
7 7u83 860
    return (0);
2 7u83 861
}
862
 
863
 
864
/*
865
    DEFINE A FUNCTION TOKEN
866
 
867
    This routine defines the function token id to be the function fid.
868
*/
869
 
7 7u83 870
int
871
define_func_token(IDENTIFIER id, IDENTIFIER fid)
2 7u83 872
{
7 7u83 873
    if (!IS_NULL_id(fid)) {
874
	DECL_SPEC ds = DEREF_dspec(id_storage(id));
875
	if (!(ds & dspec_pure)) {
876
	    TOKEN tok = DEREF_tok(id_token_sort(id));
877
	    if (IS_tok_func(tok)) {
878
		int eq = 0;
879
		int redef = 0;
880
		LIST(IDENTIFIER) pids = NULL_list(IDENTIFIER);
881
		TYPE t = DEREF_type(tok_func_type(tok));
882
		TOKEN res = DEREF_tok(tok_func_proc(tok));
883
		IDENTIFIER pid = DEREF_id(tok_func_defn(tok));
884
		IDENTIFIER qid = resolve_func(fid, t, 1, 0, pids, &eq);
885
		if (!IS_NULL_id(qid)) {
886
		    switch (TAG_id(qid)) {
887
			case id_function_tag:
888
			case id_stat_mem_func_tag:
889
			    use_id(qid, 0);
890
			    break;
891
			default:
892
			    qid = NULL_id;
893
			    break;
2 7u83 894
		    }
895
		}
7 7u83 896
		if (IS_NULL_id(qid)) {
897
		    report(crt_loc, ERR_token_def_func(fid, t));
898
		    qid = fid;
2 7u83 899
		} else {
7 7u83 900
		    TYPE s = DEREF_type(id_function_etc_type(qid));
901
		    if (eq == 2) {
902
			report(crt_loc, ERR_dcl_link_conv());
2 7u83 903
		    }
7 7u83 904
		    if (eq_except(s, t)!= 2) {
905
			report(crt_loc, ERR_token_def_except());
2 7u83 906
		    }
907
		}
7 7u83 908
		if (!IS_NULL_tok(res)) {
2 7u83 909
		    /* Previously defined by macro */
7 7u83 910
		    redef = 1;
2 7u83 911
		}
7 7u83 912
		if (!IS_NULL_id(pid) && !EQ_id(pid, qid)) {
2 7u83 913
		    /* Previously defined by different function */
7 7u83 914
		    redef = 1;
2 7u83 915
		}
7 7u83 916
		if (redef) {
917
		    PTR(LOCATION) loc = id_loc(id);
918
		    report(crt_loc, ERR_token_redef(id, loc));
2 7u83 919
		}
7 7u83 920
		COPY_id(tok_func_defn(tok), qid);
921
		if (!(ds & dspec_auto)) {
922
			no_token_defns++;
923
		}
924
		ds |= dspec_defn;
925
		COPY_dspec(id_storage(id), ds);
926
		COPY_loc(id_loc(id), crt_loc);
927
		return (1);
2 7u83 928
	    }
929
	}
930
    }
7 7u83 931
    return (0);
2 7u83 932
}
933
 
934
 
935
/*
936
    PROCEDURE TOKEN FLAG
937
 
938
    This variable is used to keep track of the depth of procedure token
939
    arguments being read.
940
*/
941
 
7 7u83 942
int in_proc_token = 0;
2 7u83 943
 
944
 
945
/*
946
    FIND A TOKEN MEMBER TYPE
947
 
948
    If id represents a member token then this routine returns the type
949
    of which id is a member, suitably expanded.  Otherwise the null type
950
    is returned.  This represents the only barrier to doing argument
951
    deduction in procedure tokens independently for each argument - if
952
    a member parameter is a member of a previous structure parameter
953
    (as in offsetof), we need to know the value of the structure
954
    argument before we can decode the member argument.
955
*/
956
 
7 7u83 957
static TYPE
958
expand_member_type(IDENTIFIER id)
2 7u83 959
{
7 7u83 960
	TYPE t = NULL_type;
961
	TOKEN tok = find_tokdef(id);
962
	if (!IS_NULL_tok(tok) && IS_tok_member(tok)) {
963
		t = DEREF_type(tok_member_of(tok));
964
		t = expand_type(t, 1);
965
	}
966
	return (t);
2 7u83 967
}
968
 
969
 
970
/*
971
    PARSE A TOKEN DEFINITION
972
 
973
    This routine reads the definition of the token id.  It returns true
974
    if a value is assigned to the token.  If mt is not null it is the
975
    class type for a member token.  fn is true for procedure tokens and
976
    mac is true is true for macro token definitions.
977
*/
978
 
7 7u83 979
static int
980
parse_token(IDENTIFIER id, TYPE t, int fn, int mac, LIST(IDENTIFIER) pids)
2 7u83 981
{
7 7u83 982
	int def;
983
	TOKEN tok = NULL_tok;
984
	unsigned tag = null_tag;
985
	if (IS_id_token(id)) {
986
		/* Find token sort */
987
		tok = DEREF_tok(id_token_sort(id));
988
		if (fn) {
989
			tok = find_tokdef(id);
2 7u83 990
		}
7 7u83 991
		tag = TAG_tok(tok);
2 7u83 992
	}
7 7u83 993
	switch (tag) {
994
	case tok_exp_tag:
995
	case tok_nat_tag:
996
	case tok_snat_tag: {
997
		/* Expression tokens */
998
		EXP e = NULL_exp;
999
		ERROR err = NULL_err;
1000
		int tn = crt_lex_token;
1001
		if (mac && tn == lex_newline && tag == tok_exp_tag) {
1002
			/* Map empty definition to default value */
1003
			TYPE s = DEREF_type(tok_exp_type(tok));
1004
			e = init_empty(s, cv_none, 1, &err);
1005
		} else if (mac && tn == lex_open_Hbrace_H1) {
1006
			parse_init(id, &e);
1007
		} else {
1008
			parse_exp(&e);
2 7u83 1009
		}
7 7u83 1010
		if (!IS_NULL_exp(e) && tag == tok_exp_tag) {
1011
			/* Deal with overloaded functions */
1012
			TYPE s = DEREF_type(tok_exp_type(tok));
1013
			force_tokdef++;
1014
			e = resolve_cast(s, e, &err, 1, 0, pids);
1015
			if (!IS_NULL_err(err)) {
1016
				err = concat_error(err, ERR_token_arg_exp(id));
1017
				report(crt_loc, err);
1018
			}
1019
			force_tokdef--;
2 7u83 1020
		}
7 7u83 1021
		def = define_exp_token(id, e, 1);
1022
		break;
1023
	}
1024
	case tok_stmt_tag: {
1025
		/* Statement tokens */
1026
		EXP e;
1027
		EXP a = NULL_exp;
1028
		int ic = in_class_defn;
1029
		int fd = in_function_defn;
1030
		int uc = unreached_code;
1031
		TYPE r = crt_func_return;
1032
		NAMESPACE bns = block_namespace;
1033
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
1034
		IDENTIFIER fid = DEREF_id(id_token_alt(id));
1035
		unreached_code = 0;
1036
		if (fd) {
1037
			if (!(ds & dspec_auto)) {
1038
				/* Force return errors */
1039
				crt_func_return = NULL_type;
1040
			}
1041
		} else {
1042
			/* Treat as dummy function definition */
1043
			in_class_defn = 0;
1044
			in_function_defn = fd + 1;
1045
			really_in_function_defn++;
1046
			begin_function(fid);
1047
			crt_func_return = NULL_type;
2 7u83 1048
		}
7 7u83 1049
		block_namespace = NULL_nspace;
1050
		e = begin_compound_stmt(1);
1051
		parse_stmt(&a);
1052
		e = add_compound_stmt(e, a);
1053
		e = end_compound_stmt(e);
1054
		if (fd) {
1055
			if (ds & dspec_auto) {
1056
				/* Set dummy parent statement */
1057
				MAKE_exp_token(type_void, id,
1058
					       NULL_list(TOKEN), a);
1059
				set_parent_stmt(e, a);
1060
			}
1061
		} else {
1062
			/* End dummy function definition */
1063
			if (crt_access_list.pending) {
1064
				IGNORE report_access(fid);
1065
			}
1066
			e = end_function(fid, e);
1067
			really_in_function_defn--;
1068
			in_function_defn = fd;
1069
			in_class_defn = ic;
1070
		}
1071
		unreached_code = uc;
1072
		block_namespace = bns;
1073
		crt_func_return = r;
1074
		def = define_exp_token(id, e, 1);
1075
		break;
2 7u83 1076
	}
7 7u83 1077
	case tok_member_tag: {
1078
		/* Member tokens */
1079
		TYPE s = type_error;
1080
		OFFSET off = NULL_off;
1081
		if (IS_NULL_type(t)) {
1082
			t = expand_member_type(id);
1083
		}
1084
		parse_offset(NULL_off, t, &off, &s);
1085
		def = define_mem_token(id, off, s, 0);
1086
		break;
2 7u83 1087
	}
7 7u83 1088
	case tok_func_tag: {
1089
		/* Function tokens */
1090
		IDENTIFIER fid = NULL_id;
1091
		parse_id(&fid);
1092
		def = define_func_token(id, fid);
1093
		break;
2 7u83 1094
	}
7 7u83 1095
	default: {
1096
		/* Type tokens */
1097
		TYPE s = NULL_type;
1098
		have_type_specifier = 0;
1099
		parse_type(&s);
1100
		if (tag == tok_type_tag) {
1101
			/* Simple type token */
1102
			def = define_type_token(id, s, 0);
1103
		} else {
1104
			/* Complex type value */
1105
			TYPE r = DEREF_type(id_class_name_etc_defn(id));
1106
			force_tokdef++;
1107
			def = eq_type(r, s);
1108
			if (!def && !IS_NULL_type(s)) {
1109
				ERROR err =
1110
				    ERR_token_arg_type(lex_type_Hcap, id, s);
1111
				report(crt_loc, err);
1112
			}
1113
			force_tokdef--;
2 7u83 1114
		}
7 7u83 1115
		break;
2 7u83 1116
	}
7 7u83 1117
	}
1118
	return (def);
2 7u83 1119
}
1120
 
1121
 
1122
/*
1123
    SET A TOKEN VALUE
1124
 
1125
    This routine sets the value of the token id to be arg.
1126
*/
1127
 
7 7u83 1128
void
1129
assign_token(IDENTIFIER id, TOKEN arg)
2 7u83 1130
{
7 7u83 1131
	if (!IS_NULL_tok(arg)) {
1132
		TOKEN sort = DEREF_tok(id_token_sort(id));
1133
		unsigned na = TAG_tok(arg);
1134
		unsigned nb = TAG_tok(sort);
1135
		if (nb == tok_proc_tag) {
1136
			sort = DEREF_tok(tok_proc_res(sort));
1137
			nb = TAG_tok(sort);
2 7u83 1138
		}
7 7u83 1139
		if (na == nb) {
1140
			switch (na) {
1141
			case tok_exp_tag: {
1142
				EXP e = DEREF_exp(tok_exp_value(arg));
1143
				COPY_exp(tok_exp_value(sort), e);
1144
				break;
1145
			}
1146
			case tok_nat_tag:
1147
			case tok_snat_tag: {
1148
				NAT n = DEREF_nat(tok_nat_etc_value(arg));
1149
				COPY_nat(tok_nat_etc_value(sort), n);
1150
				break;
1151
			}
1152
			case tok_stmt_tag: {
1153
				EXP e = DEREF_exp(tok_stmt_value(arg));
1154
				COPY_exp(tok_stmt_value(sort), e);
1155
				break;
1156
			}
1157
			case tok_member_tag: {
1158
				OFFSET off = DEREF_off(tok_member_value(arg));
1159
				COPY_off(tok_member_value(sort), off);
1160
				break;
1161
			}
1162
			case tok_type_tag: {
1163
				TYPE t = DEREF_type(tok_type_value(arg));
1164
				COPY_type(tok_type_value(sort), t);
1165
				break;
1166
			}
1167
			case tok_class_tag: {
1168
				IDENTIFIER cid = DEREF_id(tok_class_value(arg));
1169
				COPY_id(tok_class_value(sort), cid);
1170
				break;
1171
			}
1172
			}
2 7u83 1173
		}
1174
	}
7 7u83 1175
	return;
2 7u83 1176
}
1177
 
1178
 
1179
/*
1180
    TOKEN ARGUMENT STACKS
1181
 
1182
    These stacks are used to store the values of the token arguments to
1183
    allow for recursive token applications.
1184
*/
1185
 
7 7u83 1186
static STACK(EXP) token_exp_stack = NULL_stack(EXP);
1187
static STACK(NAT) token_nat_stack = NULL_stack(NAT);
1188
static STACK(EXP) token_stmt_stack = NULL_stack(EXP);
1189
static STACK(OFFSET) token_mem_stack = NULL_stack(OFFSET);
1190
static STACK(TYPE) token_type_stack = NULL_stack(TYPE);
1191
static STACK(IDENTIFIER) token_class_stack = NULL_stack(IDENTIFIER);
2 7u83 1192
 
1193
 
1194
/*
1195
    SAVE TOKEN ARGUMENT VALUES
1196
 
1197
    This routine saves the argument values for the token parameters pids
1198
    by pushing them onto the stacks above.  The argument values set to those
1199
    stored in args, or the null value when these are exhausted.  The routine
1200
    also clears the pure field of the token, returning 0 if they were
1201
    previously set.
1202
*/
1203
 
7 7u83 1204
int
1205
save_token_args(LIST(IDENTIFIER) pids, LIST(TOKEN) args)
2 7u83 1206
{
7 7u83 1207
	int depth = 1;
1208
	LIST(IDENTIFIER) bids = pids;
1209
	while (!IS_NULL_list(bids)) {
1210
		IDENTIFIER bid = DEREF_id(HEAD_list(bids));
2 7u83 1211
 
7 7u83 1212
		/* Get argument token value */
1213
		TOKEN atok = NULL_tok;
1214
		unsigned at = null_tag;
1215
		if (!IS_NULL_list(args)) {
1216
			atok = DEREF_tok(HEAD_list(args));
1217
			if (!IS_NULL_tok(atok)) {
1218
				at = TAG_tok(atok);
1219
			}
1220
			args = TAIL_list(args);
1221
		}
2 7u83 1222
 
7 7u83 1223
		/* Save previous token value */
1224
		if (!IS_NULL_id(bid) && IS_id_token(bid)) {
1225
			DECL_SPEC ds;
1226
			TOKEN btok = DEREF_tok(id_token_sort(bid));
1227
			unsigned bt = TAG_tok(btok);
1228
			switch (bt) {
1229
			case tok_exp_tag: {
1230
				EXP e = DEREF_exp(tok_exp_value(btok));
1231
				PUSH_exp(e, token_exp_stack);
1232
				if (at == bt) {
1233
					e = DEREF_exp(tok_exp_value(atok));
1234
				} else {
1235
					e = NULL_exp;
1236
				}
1237
				COPY_exp(tok_exp_value(btok), e);
1238
				break;
1239
			}
1240
			case tok_nat_tag:
1241
			case tok_snat_tag: {
1242
				NAT n = DEREF_nat(tok_nat_etc_value(btok));
1243
				PUSH_nat(n, token_nat_stack);
1244
				if (at == bt) {
1245
					n = DEREF_nat(tok_nat_etc_value(atok));
1246
				} else {
1247
					n = NULL_nat;
1248
				}
1249
				COPY_nat(tok_nat_etc_value(btok), n);
1250
				break;
1251
			}
1252
			case tok_stmt_tag: {
1253
				EXP e = DEREF_exp(tok_stmt_value(btok));
1254
				PUSH_exp(e, token_stmt_stack);
1255
				if (at == bt) {
1256
					e = DEREF_exp(tok_stmt_value(atok));
1257
				} else {
1258
					e = NULL_exp;
1259
				}
1260
				COPY_exp(tok_stmt_value(btok), e);
1261
				break;
1262
			}
1263
			case tok_member_tag: {
1264
				OFFSET off = DEREF_off(tok_member_value(btok));
1265
				PUSH_off(off, token_mem_stack);
1266
				if (at == bt) {
1267
					off = DEREF_off(tok_member_value(atok));
1268
				} else {
1269
					off = NULL_off;
1270
				}
1271
				COPY_off(tok_member_value(btok), off);
1272
				break;
1273
			}
1274
			case tok_type_tag: {
1275
				TYPE t = DEREF_type(tok_type_value(btok));
1276
				PUSH_type(t, token_type_stack);
1277
				if (at == bt) {
1278
					t = DEREF_type(tok_type_value(atok));
1279
				} else {
1280
					t = NULL_type;
1281
				}
1282
				COPY_type(tok_type_value(btok), t);
1283
				break;
1284
			}
1285
			case tok_class_tag: {
1286
				IDENTIFIER cid = DEREF_id(tok_class_value(btok));
1287
				PUSH_id(cid, token_class_stack);
1288
				if (at == bt) {
1289
					cid = DEREF_id(tok_class_value(atok));
1290
				} else {
1291
					cid = NULL_id;
1292
				}
1293
				COPY_id(tok_class_value(btok), cid);
1294
				break;
1295
			}
1296
			default:
1297
				/* Procedure arguments not allowed */
1298
				break;
1299
			}
1300
 
1301
			/* Allow definition of parameter */
1302
			ds = DEREF_dspec(id_storage(bid));
1303
			if (ds & dspec_pure) {
1304
				ds &= ~dspec_pure;
1305
				COPY_dspec(id_storage(bid), ds);
1306
				depth = 0;
1307
			}
2 7u83 1308
		}
7 7u83 1309
		bids = TAIL_list(bids);
2 7u83 1310
	}
7 7u83 1311
	in_proc_token++;
1312
	return (depth);
2 7u83 1313
}
1314
 
1315
 
1316
/*
1317
    RESTORE TOKEN ARGUMENT VALUES
1318
 
1319
    This routine restores the argument values for the token parameters
1320
    pids by popping them from the stacks above.  The pure field of the
1321
    tokens is set if depth is 0.
1322
*/
1323
 
7 7u83 1324
void
1325
restore_token_args(LIST(IDENTIFIER) pids, int depth)
2 7u83 1326
{
7 7u83 1327
	LIST(IDENTIFIER) bids = pids;
1328
	if (!IS_NULL_list(bids)) {
1329
		IDENTIFIER bid = DEREF_id(HEAD_list(bids));
1330
		bids = TAIL_list(bids);
1331
		if (!IS_NULL_list(bids)) {
1332
			restore_token_args(bids, depth);
1333
			in_proc_token++;
2 7u83 1334
		}
7 7u83 1335
		if (!IS_NULL_id(bid) && IS_id_token(bid)) {
1336
			TOKEN btok = DEREF_tok(id_token_sort(bid));
1337
			unsigned bt = TAG_tok(btok);
1338
			switch (bt) {
1339
			case tok_exp_tag: {
1340
				EXP e;
1341
				POP_exp(e, token_exp_stack);
1342
				COPY_exp(tok_exp_value(btok), e);
1343
				break;
1344
			}
1345
			case tok_nat_tag:
1346
			case tok_snat_tag: {
1347
				NAT n;
1348
				POP_nat(n, token_nat_stack);
1349
				COPY_nat(tok_nat_etc_value(btok), n);
1350
				break;
1351
			}
1352
			case tok_stmt_tag: {
1353
				EXP e;
1354
				POP_exp(e, token_stmt_stack);
1355
				COPY_exp(tok_stmt_value(btok), e);
1356
				break;
1357
			}
1358
			case tok_member_tag: {
1359
				OFFSET off;
1360
				POP_off(off, token_mem_stack);
1361
				COPY_off(tok_member_value(btok), off);
1362
				break;
1363
			}
1364
			case tok_type_tag: {
1365
				TYPE t;
1366
				POP_type(t, token_type_stack);
1367
				COPY_type(tok_type_value(btok), t);
1368
				break;
1369
			}
1370
			case tok_class_tag: {
1371
				IDENTIFIER cid;
1372
				POP_id(cid, token_class_stack);
1373
				COPY_id(tok_class_value(btok), cid);
1374
				break;
1375
			}
1376
			default:
1377
				/* Procedure arguments not allowed */
1378
				break;
1379
			}
1380
			if (depth == 0) {
1381
				/* Can't define parameter at outer level */
1382
				DECL_SPEC ds = DEREF_dspec(id_storage(bid));
1383
				ds |= dspec_pure;
1384
				COPY_dspec(id_storage(bid), ds);
1385
			}
2 7u83 1386
		}
1387
	}
7 7u83 1388
	in_proc_token--;
1389
	return;
2 7u83 1390
}
1391
 
1392
 
1393
/*
1394
    MERGE TOKEN ARGUMENT VALUES
1395
 
1396
    This routine merges the argument values for the token parameters
1397
    pids with the values popped off the stacks above.  It returns true
1398
    if the merge was successful.  The pure field of the tokens is set
1399
    if depth is 0.
1400
*/
1401
 
7 7u83 1402
int
1403
merge_token_args(LIST(IDENTIFIER) pids, int depth, int qual)
2 7u83 1404
{
7 7u83 1405
	int ok = 1;
1406
	LIST(IDENTIFIER) bids = pids;
1407
	if (!IS_NULL_list(bids)) {
1408
		IDENTIFIER bid = DEREF_id(HEAD_list(bids));
1409
		bids = TAIL_list(bids);
1410
		if (!IS_NULL_list(bids)) {
1411
			ok = merge_token_args(bids, depth, qual);
1412
			in_proc_token++;
2 7u83 1413
		}
7 7u83 1414
		if (!IS_NULL_id(bid) && IS_id_token(bid)) {
1415
			TOKEN btok = DEREF_tok(id_token_sort(bid));
1416
			unsigned bt = TAG_tok(btok);
1417
			switch (bt) {
1418
			case tok_exp_tag: {
1419
				EXP e;
1420
				POP_exp(e, token_exp_stack);
1421
				if (!IS_NULL_exp(e)) {
1422
					if (!define_exp_token(bid, e, 1)) {
1423
						ok = 0;
1424
					}
1425
				}
1426
				break;
1427
			}
1428
			case tok_nat_tag:
1429
			case tok_snat_tag: {
1430
				NAT n;
1431
				POP_nat(n, token_nat_stack);
1432
				if (!IS_NULL_nat(n)) {
1433
					if (!define_nat_token(bid, n)) {
1434
						ok = 0;
1435
					}
1436
				}
1437
				break;
1438
			}
1439
			case tok_stmt_tag: {
1440
				EXP e;
1441
				POP_exp(e, token_stmt_stack);
1442
				if (!IS_NULL_exp(e)) {
1443
					if (!define_exp_token(bid, e, 1)) {
1444
						ok = 0;
1445
					}
1446
				}
1447
				break;
1448
			}
1449
			case tok_member_tag: {
1450
				OFFSET off;
1451
				POP_off(off, token_mem_stack);
1452
				if (!IS_NULL_off(off)) {
1453
					TYPE t =
1454
					    DEREF_type(tok_member_type(btok));
1455
					if (!define_mem_token(bid, off, t, 0)) {
1456
						ok = 0;
1457
					}
1458
				}
1459
				break;
1460
			}
1461
			case tok_type_tag: {
1462
				TYPE t;
1463
				POP_type(t, token_type_stack);
1464
				if (!IS_NULL_type(t)) {
1465
					if (!define_type_token(bid, t, qual)) {
1466
						ok = 0;
1467
					}
1468
				}
1469
				break;
1470
			}
1471
			case tok_class_tag: {
1472
				IDENTIFIER cid;
1473
				POP_id(cid, token_class_stack);
1474
				if (!IS_NULL_id(cid)) {
1475
					if (!define_templ_token(bid, cid)) {
1476
						ok = 0;
1477
					}
1478
				}
1479
				break;
1480
			}
1481
			default:
1482
				/* Procedure arguments not allowed */
1483
				break;
1484
			}
1485
			if (depth == 0) {
1486
				/* Can't define parameter at outer level */
1487
				DECL_SPEC ds = DEREF_dspec(id_storage(bid));
1488
				ds |= dspec_pure;
1489
				COPY_dspec(id_storage(bid), ds);
1490
			}
2 7u83 1491
		}
1492
	}
7 7u83 1493
	in_proc_token--;
1494
	return (ok);
2 7u83 1495
}
1496
 
1497
 
1498
/*
1499
    HAS A TOKEN BEEN BOUND?
1500
 
1501
    This routine checks whether a value has been bound to the token tok.
1502
    If def is true then a dummy value is constructed for unbound values.
1503
*/
1504
 
7 7u83 1505
int
1506
is_bound_tok(TOKEN tok, int def)
2 7u83 1507
{
7 7u83 1508
	int bound = 1;
1509
	if (!IS_NULL_tok(tok)) {
1510
		switch (TAG_tok(tok)) {
1511
		case tok_exp_tag: {
1512
			/* Expression tokens */
1513
			EXP e = DEREF_exp(tok_exp_value(tok));
1514
			if (IS_NULL_exp(e) || EQ_exp(e, redef_exp)) {
1515
				if (def) {
1516
					TYPE t = DEREF_type(tok_exp_type(tok));
1517
					MAKE_exp_value(t, e);
1518
					COPY_exp(tok_exp_value(tok), e);
1519
				}
1520
				bound = 0;
1521
			}
1522
			break;
2 7u83 1523
		}
7 7u83 1524
		case tok_nat_tag:
1525
		case tok_snat_tag: {
1526
			/* Integer constant tokens */
1527
			NAT n = DEREF_nat(tok_nat_etc_value(tok));
1528
			if (IS_NULL_nat(n) || EQ_nat(n, redef_nat)) {
1529
				if (def) {
1530
					n = small_nat[1];
1531
					COPY_nat(tok_nat_etc_value(tok), n);
1532
				}
1533
				bound = 0;
1534
			}
1535
			break;
2 7u83 1536
		}
7 7u83 1537
		case tok_stmt_tag: {
1538
			/* Statement tokens */
1539
			EXP e = DEREF_exp(tok_stmt_value(tok));
1540
			if (IS_NULL_exp(e) || EQ_exp(e, redef_exp)) {
1541
				if (def) {
1542
					MAKE_exp_value(type_void, e);
1543
					COPY_exp(tok_stmt_value(tok), e);
1544
				}
1545
				bound = 0;
1546
			}
1547
			break;
2 7u83 1548
		}
7 7u83 1549
		case tok_member_tag: {
1550
			/* Member tokens */
1551
			OFFSET off = DEREF_off(tok_member_value(tok));
1552
			if (IS_NULL_off(off) || EQ_off(off, redef_off)) {
1553
				if (def) {
1554
					TYPE t =
1555
					    DEREF_type(tok_member_type(tok));
1556
					MAKE_off_zero(t, off);
1557
					COPY_off(tok_member_value(tok), off);
1558
				}
1559
				bound = 0;
1560
			}
1561
			break;
2 7u83 1562
		}
7 7u83 1563
		case tok_type_tag: {
1564
			/* Type tokens */
1565
			TYPE t = DEREF_type(tok_type_value(tok));
1566
			if (IS_NULL_type(t) || EQ_type(t, redef_type)) {
1567
				if (def) {
1568
					t = type_error;
1569
					COPY_type(tok_type_value(tok), t);
1570
				}
1571
				bound = 0;
1572
			}
1573
			break;
2 7u83 1574
		}
7 7u83 1575
		case tok_class_tag: {
1576
			/* Template class tokens */
1577
			IDENTIFIER cid = DEREF_id(tok_class_value(tok));
1578
			if (IS_NULL_id(cid) || EQ_id(cid, redef_id)) {
1579
				if (def) {
1580
					HASHID nm = KEYWORD(lex_zzzz);
1581
					cid = DEREF_id(hashid_id(nm));
1582
					COPY_id(tok_class_value(tok), cid);
1583
				}
1584
				bound = 0;
1585
			}
1586
			break;
2 7u83 1587
		}
7 7u83 1588
		}
2 7u83 1589
	}
7 7u83 1590
	return (bound);
2 7u83 1591
}
1592
 
1593
 
1594
/*
1595
    CONSTRUCT A LIST OF TOKEN ARGUMENTS
1596
 
1597
    This routine constructs a list of token arguments for the token id
1598
    from the token parameters pids.  Any errors arising from undefined
1599
    parameters are added to err.
1600
*/
1601
 
7 7u83 1602
LIST(TOKEN)
1603
make_token_args(IDENTIFIER id, LIST(IDENTIFIER) pids, ERROR *err)
2 7u83 1604
{
7 7u83 1605
	LIST(TOKEN) args = NULL_list(TOKEN);
1606
	while (!IS_NULL_list(pids)) {
1607
		IDENTIFIER pid = DEREF_id(HEAD_list(pids));
1608
		if (!IS_NULL_id(pid) && IS_id_token(pid)) {
1609
			TOKEN tok = DEREF_tok(id_token_sort(pid));
1610
			if (!is_bound_tok(tok, 1)) {
1611
				/* Token parameter not defined */
1612
				if (IS_id_token(id)) {
1613
					add_error(err, ERR_token_arg_undef(pid, id));
1614
				} else {
1615
					add_error(err, ERR_temp_deduct_undef(pid, id));
1616
				}
1617
			}
1618
			tok = expand_sort(tok, 2, 1);
1619
			CONS_tok(tok, args, args);
2 7u83 1620
		}
7 7u83 1621
		pids = TAIL_list(pids);
2 7u83 1622
	}
7 7u83 1623
	args = REVERSE_list(args);
1624
	return (args);
2 7u83 1625
}
1626
 
1627
 
1628
/*
1629
    SKIP TOKEN ARGUMENTS
1630
 
1631
    This routine skips a set of token arguments for the token id.  It is
1632
    entered with the current token pointing to the token name preceding
1633
    the initial open bracket.
1634
*/
1635
 
7 7u83 1636
PPTOKEN *
1637
skip_token_args(IDENTIFIER id)
2 7u83 1638
{
7 7u83 1639
	PPTOKEN *q;
1640
	LOCATION loc;
1641
	int brackets = 0;
1642
	PPTOKEN *p = crt_token;
1643
	loc = crt_loc;
1644
	for (;;) {
1645
		int t = expand_preproc(EXPAND_AHEAD);
1646
		if (t == lex_open_Hround) {
1647
			brackets++;
1648
		} else if (t == lex_close_Hround) {
1649
			if (--brackets == 0) {
1650
				break;
1651
			}
1652
		} else if (t == lex_eof) {
1653
			HASHID nm = DEREF_hashid(id_name(id));
1654
			report(loc, ERR_cpp_replace_arg_eof(nm));
1655
			break;
1656
		}
2 7u83 1657
	}
7 7u83 1658
	q = p->next;
1659
	snip_tokens(q, crt_token);
1660
	crt_token = p;
1661
	return (q);
2 7u83 1662
}
1663
 
1664
 
1665
/*
1666
    PARSE A SET OF TOKEN ARGUMENTS
1667
 
1668
    This routine parses the preprocessing tokens p as a list of arguments
1669
    for the procedure token id.
1670
*/
1671
 
7 7u83 1672
static LIST(TOKEN)
1673
parse_token_args(IDENTIFIER id, PPTOKEN *p)
2 7u83 1674
{
7 7u83 1675
	int t;
1676
	int d = 0;
1677
	int ok = 1;
1678
	PARSE_STATE st;
1679
	unsigned m = 0;
1680
	int started = 0;
1681
	LIST(TOKEN) args;
1682
	ERROR err = NULL_err;
1683
	TOKEN tok = DEREF_tok(id_token_sort(id));
1684
	LIST(IDENTIFIER) pids = DEREF_list(tok_proc_pids(tok));
1685
	LIST(IDENTIFIER) bids = DEREF_list(tok_proc_bids(tok));
1686
	unsigned n = LENGTH_list(pids);
2 7u83 1687
 
7 7u83 1688
	/* Initialise parser */
1689
	save_state(&st, 1);
1690
	init_parser(p);
1691
	ADVANCE_LEXER;
1692
	t = crt_lex_token;
1693
	if (t == lex_open_Hround || t == lex_open_Htemplate) {
1694
		ADVANCE_LEXER;
2 7u83 1695
	}
7 7u83 1696
	if (IS_NULL_list(pids)) {
1697
		/* Empty parameter list */
1698
		t = crt_lex_token;
1699
		if (t == lex_close_Hround || t == lex_close_Htemplate) {
1700
			ADVANCE_LEXER;
2 7u83 1701
		}
7 7u83 1702
	} else {
1703
		/* Non-empty parameter list */
1704
		while (!IS_NULL_list(pids)) {
1705
			IDENTIFIER pid = DEREF_id(HEAD_list(pids));
1706
			if (!IS_NULL_id(pid)) {
1707
				TYPE mt = NULL_type;
1708
				t = crt_lex_token;
1709
				if (t == lex_close_Hround ||
1710
				    t == lex_close_Htemplate) {
1711
					ADVANCE_LEXER;
1712
					break;
1713
				}
1714
				if (started) {
1715
					/* Each argument deduction is (nearly)
1716
					 * independent */
1717
					mt = expand_member_type(pid);
1718
					d = save_token_args(bids,
1719
							    NULL_list(TOKEN));
1720
				}
1721
				if (!parse_token(pid, mt, 1, 0, bids)) {
1722
					ok = 0;
1723
				}
1724
				if (started) {
1725
					/* Combine argument deductions */
1726
					IGNORE merge_token_args(bids, d, 2);
1727
				}
1728
				started = 1;
1729
				if (have_syntax_error) {
1730
					ok = 0;
1731
					break;
1732
				}
1733
			} else {
1734
				ok = 0;
1735
				break;
1736
			}
1737
			m++;
1738
			t = crt_lex_token;
1739
			if (t == lex_close_Hround ||
1740
			    t == lex_close_Htemplate) {
1741
				ADVANCE_LEXER;
1742
				break;
1743
			}
1744
			pids = TAIL_list(pids);
1745
			if (!IS_NULL_list(pids)) {
1746
				if (t == lex_comma) {
1747
					ADVANCE_LEXER;
1748
				} else {
1749
					report(crt_loc,
1750
					       ERR_lex_expect(lex_comma));
1751
				}
1752
			}
2 7u83 1753
		}
7 7u83 1754
	}
1755
 
1756
	/* Check for end of arguments */
1757
	if (ok) {
1758
		t = crt_lex_token;
1759
		if (t == lex_comma) {
1760
			m = n + 1;
1761
		} else if (t != lex_eof) {
1762
			ERROR err2 = ERR_lex_parse(crt_token);
1763
			report(crt_loc, err2);
1764
			ok = 0;
2 7u83 1765
		}
7 7u83 1766
		if (ok && m != n) {
1767
			HASHID nm = DEREF_hashid(id_name(id));
1768
			ERROR err2 = ERR_cpp_replace_arg_number(nm, m, m, n);
1769
			report(crt_loc, err2);
2 7u83 1770
		}
7 7u83 1771
		IGNORE check_value(OPT_VAL_macro_args,(ulong)m);
2 7u83 1772
	}
1773
 
7 7u83 1774
	/* Restore state */
1775
	restore_state(&st);
1776
	p = restore_parser();
1777
	free_tok_list(p);
2 7u83 1778
 
7 7u83 1779
	/* Construct token arguments */
1780
	args = make_token_args(id, bids, &err);
1781
	if (!IS_NULL_err(err)) {
1782
		if (ok) {
1783
			report(crt_loc, err);
1784
		} else {
1785
			destroy_error(err, 1);
1786
		}
2 7u83 1787
	}
7 7u83 1788
	return (args);
2 7u83 1789
}
1790
 
1791
 
1792
/*
1793
    PARSE AN EXPRESSION TOKEN
1794
 
1795
    This routine applies the expression procedure token id to the
1796
    arguments given by the preprocessing tokens p.
1797
*/
1798
 
7 7u83 1799
EXP
1800
parse_exp_token(IDENTIFIER id, PPTOKEN *p)
2 7u83 1801
{
7 7u83 1802
	EXP e;
1803
	LIST(TOKEN) args;
1804
	TOKEN tok = DEREF_tok(id_token_sort(id));
1805
	LIST(IDENTIFIER) bids = DEREF_list(tok_proc_bids(tok));
1806
	int d = save_token_args(bids, NULL_list(TOKEN));
1807
	args = parse_token_args(id, p);
1808
	e = apply_exp_token(id, args, 2);
1809
	restore_token_args(bids, d);
1810
	return (e);
2 7u83 1811
}
1812
 
1813
 
1814
/*
1815
    PARSE A TYPE TOKEN
1816
 
1817
    This routine applies the type procedure token id to the arguments
1818
    given by the preprocessing tokens p.
1819
*/
1820
 
7 7u83 1821
TYPE
1822
parse_type_token(IDENTIFIER id, PPTOKEN *p)
2 7u83 1823
{
7 7u83 1824
	TYPE t;
1825
	if (IS_id_token(id)) {
1826
		/* Type token */
1827
		LIST(TOKEN) args;
1828
		TOKEN tok = DEREF_tok(id_token_sort(id));
1829
		LIST(IDENTIFIER) bids = DEREF_list(tok_proc_bids(tok));
1830
		int d = save_token_args(bids, NULL_list(TOKEN));
1831
		args = parse_token_args(id, p);
1832
		t = apply_type_token(id, args, NULL_id);
1833
		restore_token_args(bids, d);
1834
	} else {
1835
		/* Typedef template */
1836
		t = parse_typedef_templ(id, p);
1837
	}
1838
	return (t);
2 7u83 1839
}
1840
 
1841
 
1842
/*
1843
    PARSE A MEMBER TOKEN
1844
 
1845
    This routine applies the member procedure token id to the arguments
1846
    given by the preprocessing tokens p.
1847
*/
1848
 
7 7u83 1849
OFFSET
1850
parse_mem_token(IDENTIFIER id, PPTOKEN *p)
2 7u83 1851
{
7 7u83 1852
	OFFSET off;
1853
	LIST(TOKEN) args;
1854
	TOKEN tok = DEREF_tok(id_token_sort(id));
1855
	LIST(IDENTIFIER) bids = DEREF_list(tok_proc_bids(tok));
1856
	int d = save_token_args(bids, NULL_list(TOKEN));
1857
	args = parse_token_args(id, p);
1858
	off = apply_mem_token(id, args);
1859
	restore_token_args(bids, d);
1860
	return (off);
2 7u83 1861
}
1862
 
1863
 
1864
/*
1865
    DEFINE A TOKEN USING A MACRO
1866
 
1867
    This routine defines the tokenised object id by means of the macro
1868
    mid.  It returns true if this is possible.
1869
*/
1870
 
7 7u83 1871
int
1872
define_token_macro(IDENTIFIER id, IDENTIFIER mid)
2 7u83 1873
{
7 7u83 1874
    DECL_SPEC fds = DEREF_dspec(id_storage(id));
1875
    IDENTIFIER tid = find_token(id);
1876
    if (IS_id_token(tid)) {
1877
	int fn = 1;
1878
	PPTOKEN *p;
1879
	PPTOKEN *r;
1880
	LOCATION loc;
1881
	PARSE_STATE st;
1882
	STACK(EXP) tries;
1883
	LIST(IDENTIFIER) pids;
1884
	LIST(TYPE) ex = univ_type_set;
1885
	TOKEN tok = DEREF_tok(id_token_sort(tid));
1886
	DECL_SPEC ds = DEREF_dspec(id_storage(tid));
2 7u83 1887
 
1888
	/* Find token definition */
7 7u83 1889
	if (IS_id_obj_macro(mid)) {
1890
	    switch (TAG_tok(tok)) {
1891
		case tok_func_tag:
2 7u83 1892
		    /* Function tokens read as identifiers */
7 7u83 1893
		    IGNORE find_func_token(id,(unsigned)UINT_MAX);
1894
		    COPY_dspec(id_storage(id), (fds & ~dspec_token));
1895
		    fn = 0;
1896
		    break;
1897
		case tok_templ_tag:
1898
		case tok_proc_tag:
2 7u83 1899
		    /* Can't have procedure tokens */
7 7u83 1900
		    report(preproc_loc, ERR_token_def_args(id));
1901
		    return (1);
2 7u83 1902
	    }
7 7u83 1903
	    p = DEREF_pptok(id_obj_macro_defn(mid));
2 7u83 1904
	} else {
7 7u83 1905
	    unsigned n = DEREF_unsigned(id_func_macro_no_params(mid));
1906
	    switch (TAG_tok(tok)) {
1907
		case tok_func_tag: {
2 7u83 1908
		    /* Find function token with n parameters */
7 7u83 1909
		    TYPE t = DEREF_type(tok_func_type(tok));
1910
		    tid = find_func_token(id, n);
1911
		    if (IS_NULL_id(tid)) {
1912
			report(preproc_loc, ERR_token_def_args(id));
1913
			return (1);
2 7u83 1914
		    }
7 7u83 1915
		    tok = DEREF_tok(id_token_sort(tid));
1916
		    tok = func_proc_token(tok);
1917
		    id = DEREF_id(id_token_alt(tid));
1918
		    fds = DEREF_dspec(id_storage(id));
1919
		    COPY_dspec(id_storage(id), (fds & ~dspec_token));
1920
		    ex = DEREF_list(type_func_except(t));
1921
		    break;
2 7u83 1922
		}
7 7u83 1923
		case tok_proc_tag:
2 7u83 1924
		    /* Procedure tokens */
7 7u83 1925
		    pids = DEREF_list(tok_proc_pids(tok));
1926
		    if (LENGTH_list(pids)!= n) {
1927
			report(preproc_loc, ERR_token_def_args(id));
1928
			return (1);
2 7u83 1929
		    }
7 7u83 1930
		    break;
1931
		default:
2 7u83 1932
		    /* Can't have simple tokens */
7 7u83 1933
		    report(preproc_loc, ERR_token_def_args(id));
1934
		    return (1);
2 7u83 1935
	    }
7 7u83 1936
	    p = DEREF_pptok(id_func_macro_defn(mid));
2 7u83 1937
	}
1938
 
1939
	/* Expand token definition */
7 7u83 1940
	p = expand_tok_list(p);
1941
	r = new_pptok();
1942
	r->tok = lex_newline;
1943
	r->next = NULL;
1944
	if (p == NULL) {
1945
	    p = r;
2 7u83 1946
	} else {
7 7u83 1947
	    PPTOKEN *q = p;
1948
	    while (q->next)q = q->next;
1949
	    q->next = r;
2 7u83 1950
	}
1951
 
1952
	/* Allow for procedure tokens */
7 7u83 1953
	if (IS_tok_proc(tok)) {
1954
	    NAMESPACE ns;
1955
	    PPTOKEN *q = p;
1956
	    pids = DEREF_list(tok_proc_pids(tok));
1957
	    while (q != NULL) {
1958
		if (q->tok == lex_macro_Harg) {
1959
		    unsigned long pn = q->pp_data.par.no - 1;
1960
		    LIST(IDENTIFIER)qids = pids;
1961
		    while (pn && !IS_NULL_list(qids)) {
1962
			qids = TAIL_list(qids);
1963
			pn--;
2 7u83 1964
		    }
7 7u83 1965
		    if (!IS_NULL_list(qids)) {
1966
			IDENTIFIER qid = DEREF_id(HEAD_list(qids));
1967
			if (!IS_NULL_id(qid)) {
1968
			    HASHID qnm = DEREF_hashid(id_name(qid));
1969
			    q->tok = lex_identifier;
1970
			    q->pp_data.id.hash = qnm;
1971
			    q->pp_data.id.use = qid;
2 7u83 1972
			}
1973
		    }
1974
		}
7 7u83 1975
		q = q->next;
2 7u83 1976
	    }
7 7u83 1977
	    pids = DEREF_list(tok_proc_bids(tok));
1978
	    while (!IS_NULL_list(pids)) {
1979
		IDENTIFIER pid = DEREF_id(HEAD_list(pids));
1980
		if (!IS_NULL_id(pid)) {
1981
		    DECL_SPEC pds = DEREF_dspec(id_storage(pid));
1982
		    pds |= dspec_pure;
1983
		    COPY_dspec(id_storage(pid), pds);
2 7u83 1984
		}
7 7u83 1985
		pids = TAIL_list(pids);
2 7u83 1986
	    }
7 7u83 1987
	    ns = DEREF_nspace(tok_proc_pars(tok));
1988
	    add_namespace(ns);
2 7u83 1989
	}
1990
 
1991
	/* Parse token */
7 7u83 1992
	loc = crt_loc;
1993
	bad_crt_loc++;
1994
	crt_loc = preproc_loc;
1995
	tries = crt_try_blocks;
1996
	start_try_check(ex);
1997
	save_state(&st, 0);
1998
	init_parser(p);
1999
	ADVANCE_LEXER;
2000
	pids = NULL_list(IDENTIFIER);
2001
	IGNORE parse_token(tid, NULL_type, fn, 1, pids);
2002
	if (!have_syntax_error && crt_lex_token != lex_newline) {
2003
	    ERROR err = ERR_lex_parse(crt_token);
2004
	    report(crt_loc, err);
2 7u83 2005
	}
7 7u83 2006
	if (ds & dspec_pure) {
2007
	    report(preproc_loc, ERR_token_def_not(id));
2 7u83 2008
	} else {
7 7u83 2009
	    if (do_dump) {
2010
		    dump_declare(id, &crt_loc, 1);
2011
	    }
2 7u83 2012
	}
7 7u83 2013
	restore_state(&st);
2014
	p = restore_parser();
2015
	free_tok_list(p);
2016
	IGNORE end_try_check(id, NULL_exp);
2017
	crt_try_blocks = tries;
2018
	crt_loc = loc;
2019
	bad_crt_loc--;
2 7u83 2020
 
2021
	/* Allow for procedure tokens */
7 7u83 2022
	if (IS_tok_proc(tok)) {
2023
	    remove_namespace();
2024
	    pids = DEREF_list(tok_proc_bids(tok));
2025
	    while (!IS_NULL_list(pids)) {
2026
		IDENTIFIER pid = DEREF_id(HEAD_list(pids));
2027
		if (!IS_NULL_id(pid)) {
2028
		    DECL_SPEC pds = DEREF_dspec(id_storage(pid));
2029
		    pds &= ~dspec_pure;
2030
		    COPY_dspec(id_storage(pid), pds);
2 7u83 2031
		}
7 7u83 2032
		pids = TAIL_list(pids);
2 7u83 2033
	    }
2034
	}
7 7u83 2035
	COPY_dspec(id_storage(id), fds);
2036
	return (1);
2 7u83 2037
    }
7 7u83 2038
    return (0);
2 7u83 2039
}
2040
 
2041
 
2042
/*
2043
    DEFINE A MEMBER TOKEN
2044
 
2045
    This routine is used to define the tokenised member id of t by the
2046
    list of immediately following preprocessing tokens.  This is used
2047
    to implement the '#pragma TenDRA member definition' command.
2048
*/
2049
 
7 7u83 2050
int
2051
define_mem_macro(IDENTIFIER id, TYPE t)
2 7u83 2052
{
7 7u83 2053
	IDENTIFIER tid = tok_member(id, t, 0);
2054
	if (!IS_NULL_id(tid)) {
2055
		id = tid;
2056
		tid = find_token(tid);
2057
		if (!IS_NULL_id(tid) && IS_id_token(tid)) {
2058
			TOKEN tok = DEREF_tok(id_token_sort(tid));
2059
			if (IS_tok_member(tok)) {
2060
				int def;
2061
				LOCATION loc;
2062
				DECL_SPEC ds = DEREF_dspec(id_storage(tid));
2063
				LIST(IDENTIFIER) pids = NULL_list(IDENTIFIER);
2064
				bad_crt_loc++;
2065
				loc = crt_loc;
2066
				crt_loc = preproc_loc;
2067
				def = parse_token(tid, NULL_type, 1, 1, pids);
2068
				if (ds & dspec_pure) {
2069
					report(preproc_loc,
2070
					       ERR_token_def_not(id));
2071
				} else {
2072
					if (do_dump) {
2073
						dump_declare(id, &crt_loc, 1);
2074
					}
2075
				}
2076
				crt_loc = loc;
2077
				bad_crt_loc--;
2078
				return (def);
2079
			}
2 7u83 2080
		}
7 7u83 2081
		report(preproc_loc, ERR_token_undecl(id));
2 7u83 2082
	}
7 7u83 2083
	if (in_preproc_dir) {
2084
		IGNORE skip_to_end();
2085
	}
2086
	return (0);
2 7u83 2087
}
2088
 
2089
 
2090
/*
2091
    PENDING TOKEN FOR IDENTIFIER UNIFICATION
2092
 
2093
    The normal unification routine is called immediately after the
2094
    declaration of an object.  However for 'const' objects it is more
2095
    useful to postpone the unification until after the initialisation.
2096
*/
2097
 
7 7u83 2098
IDENTIFIER unify_id_pending = NULL_id;
2 7u83 2099
 
2100
 
2101
/*
2102
    UNIFY TWO IDENTIFIERS
2103
 
2104
    This routine is called whenever an identifier id hides an identifier
2105
    pid from the same namespace.  Normally this is a redeclaration error
2106
    which will have been caught by the declaration routines, however if
2107
    pid is a token identifier it may be a token definition.  The routine
2108
    returns true if this is the case.
2109
*/
2110
 
2111
int unify_id
7 7u83 2112
(IDENTIFIER pid, IDENTIFIER id, int def)
2 7u83 2113
{
7 7u83 2114
    int ok = 0;
2115
    IDENTIFIER tid = DEREF_id(id_token_alt(pid));
2116
    if (IS_id_token(tid)) {
2 7u83 2117
	/* Previous definition was a token */
7 7u83 2118
	TOKEN tok = DEREF_tok(id_token_sort(tid));
2119
	switch (TAG_tok(tok)) {
2120
	    case tok_exp_tag:
2121
	    case tok_nat_tag:
2122
	    case tok_snat_tag: {
2 7u83 2123
		/* Expression tokens */
7 7u83 2124
		EXP e;
2125
		int expl = 0;
2126
		switch (TAG_id(id)) {
2127
		    case id_variable_tag: {
2 7u83 2128
#if LANGUAGE_CPP
7 7u83 2129
			TYPE t = DEREF_type(id_variable_type(id));
2130
			CV_SPEC cv = DEREF_cv(type_qual(t));
2131
			if (cv == (cv_lvalue | cv_const)) {
2 7u83 2132
			    /* Allow for const objects */
7 7u83 2133
			    e = DEREF_exp(id_variable_init(id));
2134
			    if (IS_NULL_exp(e)) {
2135
				if (IS_NULL_id(unify_id_pending)) {
2136
				    unify_id_pending = pid;
2137
				    return (1);
2 7u83 2138
				}
2139
			    }
2140
			}
2141
#endif
7 7u83 2142
			unify_id_pending = NULL_id;
2143
			goto variable_label;
2 7u83 2144
		    }
7 7u83 2145
		    case id_enumerator_tag:
2146
			expl = 1;
2147
			goto variable_label;
2148
variable_label:
2149
		    case id_parameter_tag:
2150
		    case id_stat_member_tag: {
2151
			e = make_id_exp(id);
2152
			if (define_exp_token(tid, e, expl)) {
2153
			    LOCATION loc;
2154
			    DEREF_loc(id_loc(id), loc);
2155
			    COPY_loc(id_loc(tid), loc);
2 7u83 2156
			}
7 7u83 2157
			ok = 1;
2158
			break;
2 7u83 2159
		    }
2160
		}
7 7u83 2161
		break;
2 7u83 2162
	    }
2163
	}
7 7u83 2164
	if (ok) {
2 7u83 2165
	    /* Set alternate look-up for token */
7 7u83 2166
	    HASHID nm = DEREF_hashid(id_name(tid));
2167
	    MEMBER mem = search_member(token_namespace, nm, 0);
2168
	    if (!IS_NULL_member(mem)) {
2169
		COPY_id(member_alt(mem), id);
2 7u83 2170
	    }
2171
	}
2172
    }
7 7u83 2173
    if (ok) {
2 7u83 2174
	/* Token definition */
7 7u83 2175
	DECL_SPEC ds = DEREF_dspec(id_storage(tid));
2176
	if (ds & dspec_pure) {
2177
	    report(crt_loc, ERR_token_def_not(pid));
2 7u83 2178
	} else {
7 7u83 2179
	    if (do_dump) {
2180
		    dump_declare(pid, &crt_loc, 1);
2181
	    }
2 7u83 2182
	}
2183
    } else {
2184
	/* Illegal redeclaration */
7 7u83 2185
	if (def) {
2186
		id = pid;
2187
	}
2188
	report(crt_loc, ERR_basic_odr_diff(id, id_loc(id)));
2 7u83 2189
    }
7 7u83 2190
    return (ok);
2 7u83 2191
}