Subversion Repositories tendra.SVN

Rev

Rev 7 | 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
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 "etype_ops.h"
66
#include "exp_ops.h"
67
#include "ftype_ops.h"
68
#include "hashid_ops.h"
69
#include "id_ops.h"
70
#include "itype_ops.h"
71
#include "nat_ops.h"
72
#include "nspace_ops.h"
73
#include "member_ops.h"
74
#include "off_ops.h"
75
#include "tok_ops.h"
76
#include "type_ops.h"
77
#include "error.h"
78
#include "catalog.h"
79
#include "option.h"
80
#include "access.h"
81
#include "basetype.h"
82
#include "check.h"
83
#include "chktype.h"
84
#include "class.h"
85
#include "constant.h"
86
#include "convert.h"
87
#include "copy.h"
88
#include "declare.h"
89
#include "dump.h"
90
#include "exception.h"
91
#include "expression.h"
92
#include "function.h"
93
#include "hash.h"
94
#include "identifier.h"
95
#include "initialise.h"
96
#include "instance.h"
97
#include "inttype.h"
98
#include "lex.h"
99
#include "macro.h"
100
#include "namespace.h"
101
#include "parse.h"
102
#include "predict.h"
103
#include "preproc.h"
104
#include "redeclare.h"
105
#include "statement.h"
106
#include "syntax.h"
107
#include "template.h"
108
#include "tok.h"
109
#include "tokdef.h"
110
#include "token.h"
111
 
112
 
113
/*
114
    FIND A TYPE TOKEN KEY
115
 
116
    This routine returns the keyword associated with a type token of
117
    kind bt.
118
*/
119
 
7 7u83 120
int
121
type_token_key(BASE_TYPE bt)
2 7u83 122
{
7 7u83 123
	int key = lex_type_Hcap;
124
	if (bt & btype_float) {
125
		if (bt & btype_star) {
126
			key = lex_scalar_Hcap;
127
		} else if (bt & btype_int) {
128
			key = lex_arith_Hcap;
129
		} else {
130
			key = lex_float_Hcap;
131
		}
132
	} else if (bt & btype_int) {
133
		if (bt & btype_signed) {
134
			key = lex_signed;
135
		} else if (bt & btype_unsigned) {
136
			key = lex_unsigned;
137
		} else {
138
			key = lex_variety_Hcap;
139
		}
140
	} else if (bt == btype_class) {
141
		key = lex_class_Hcap;
142
	} else if (bt == btype_struct) {
143
		key = lex_struct_Hcap;
144
	} else if (bt == btype_union) {
145
		key = lex_union_Hcap;
2 7u83 146
	}
7 7u83 147
	return (key);
2 7u83 148
}
149
 
150
 
151
/*
152
    CREATE A TYPE TOKEN
153
 
154
    This routine creates a type token of kind bt.
155
*/
156
 
7 7u83 157
TOKEN
158
make_type_token(BASE_TYPE bt)
2 7u83 159
{
7 7u83 160
	TOKEN tok;
161
	MAKE_tok_type(bt, NULL_type, tok);
162
	return (tok);
2 7u83 163
}
164
 
165
 
166
/*
167
    CREATE AN EXPRESSION TOKEN
168
 
169
    This routine creates an expression token of type t.
170
*/
171
 
7 7u83 172
TOKEN
173
make_exp_token(TYPE t, int lv, int c)
2 7u83 174
{
7 7u83 175
	TOKEN tok;
176
	if (lv) {
177
		t = lvalue_type(t);
178
	} else {
179
		t = rvalue_type(t);
180
	}
181
	object_type(t, id_token_tag);
182
	MAKE_tok_exp(t, c, NULL_exp, tok);
183
	return (tok);
2 7u83 184
}
185
 
186
 
187
/*
188
    CREATE A FUNCTION TOKEN
189
 
190
    This routine creates a function token of type t.
191
*/
192
 
7 7u83 193
TOKEN
194
make_func_token(TYPE t)
2 7u83 195
{
7 7u83 196
	int ell;
197
	TOKEN tok;
198
	if (!IS_type_func(t)) {
199
		report(preproc_loc, ERR_token_func(t));
200
		tok = make_exp_token(t, 0, 0);
201
		return (tok);
202
	}
203
	ell = DEREF_int(type_func_ellipsis(t));
204
	if (ell & FUNC_NO_PARAMS) {
205
		/* Map 't ()' to 't ( void )' */
206
		COPY_int(type_func_ellipsis(t), FUNC_NONE);
207
	}
208
	MAKE_tok_func(t, tok);
209
	return (tok);
2 7u83 210
}
211
 
212
 
213
/*
214
    CREATE A MEMBER SELECTOR TOKEN
215
 
216
    This routine creates a member selector token for a member of s of
217
    type t.  acc gives the member access.
218
*/
219
 
7 7u83 220
TOKEN
221
make_member_token(TYPE t, TYPE s, DECL_SPEC acc)
2 7u83 222
{
7 7u83 223
	TOKEN tok;
224
	if (!IS_type_compound(s)) {
225
		report(preproc_loc, ERR_token_mem(s));
226
		tok = make_exp_token(t, 0, 0);
227
		return (tok);
228
	}
2 7u83 229
#if LANGUAGE_CPP
7 7u83 230
	crt_access = acc;
2 7u83 231
#else
7 7u83 232
	UNUSED(acc);
2 7u83 233
#endif
7 7u83 234
	MAKE_tok_member(s, t, NULL_off, tok);
235
	return (tok);
2 7u83 236
}
237
 
238
 
239
/*
240
    CHECK A TOKEN PARAMETER OR RESULT SORT
241
 
242
    Procedure tokens which take or return other procedure tokens are not
243
    allowed.  This routine checks the parameter token sort tok.
244
*/
245
 
7 7u83 246
static TOKEN
247
check_param_sort(TOKEN tok)
2 7u83 248
{
7 7u83 249
	if (!IS_NULL_tok(tok)) {
250
		if (IS_tok_func(tok)) {
251
			tok = func_proc_token(tok);
252
		}
253
		if (IS_tok_proc(tok)) {
254
			report(preproc_loc, ERR_token_proc_high());
255
			tok = DEREF_tok(tok_proc_res(tok));
256
		}
2 7u83 257
	}
7 7u83 258
	return (tok);
2 7u83 259
}
260
 
261
 
262
/*
263
    BEGIN THE DEFINITION OF A PROCEDURE TOKEN
264
 
265
    This routine begins the construction of a procedure token.
266
*/
267
 
7 7u83 268
TOKEN
269
begin_proc_token(void)
2 7u83 270
{
7 7u83 271
	TOKEN tok;
272
	begin_param(NULL_id);
273
	MAKE_tok_proc(NULL_tok, crt_namespace, lex_identifier, tok);
274
	return (tok);
2 7u83 275
}
276
 
277
 
278
/*
279
    SET THE PARAMETER NUMBERS FOR A PROCEDURE TOKEN
280
 
281
    This routine sets the token numbers for the list of procedure token
282
    parameters p.
283
*/
284
 
7 7u83 285
void
286
set_proc_token(LIST(IDENTIFIER) p)
2 7u83 287
{
7 7u83 288
	ulong n = 0;
289
	while (!IS_NULL_list(p)) {
290
		IDENTIFIER pid = DEREF_id(HEAD_list(p));
291
		if (!IS_NULL_id(pid)) {
292
			COPY_ulong(id_no(pid), n);
293
		}
294
		n++;
295
		p = TAIL_list(p);
2 7u83 296
	}
7 7u83 297
	return;
2 7u83 298
}
299
 
300
 
301
/*
302
    CONTINUE THE DEFINITION OF A PROCEDURE TOKEN
303
 
304
    This routine continues the definition of the procedure token prev
305
    by adding the lists of bound and program parameters, p and q.
306
*/
307
 
7 7u83 308
TOKEN
309
cont_proc_token(TOKEN prev, LIST(IDENTIFIER) p, LIST(IDENTIFIER) q)
2 7u83 310
{
7 7u83 311
	if (!IS_NULL_tok(prev)) {
312
		unsigned n;
313
		if (!EQ_list(p, q)) {
314
			int eq = 1;
315
			LIST(IDENTIFIER) ps = p;
316
			LIST(IDENTIFIER) qs = q;
317
			while (!IS_NULL_list(ps) && !IS_NULL_list(qs)) {
318
				IDENTIFIER ip = DEREF_id(HEAD_list(ps));
319
				IDENTIFIER iq = DEREF_id(HEAD_list(qs));
320
				if (!EQ_id(ip, iq)) {
321
					eq = 0;
322
					break;
323
				}
324
				ps = TAIL_list(ps);
325
				qs = TAIL_list(qs);
326
			}
327
			if (eq && EQ_list(ps, qs)) {
328
				/* Parameter lists match */
329
				DESTROY_list(q, SIZE_id);
330
				q = p;
331
			} else {
332
				set_proc_token(q);
333
			}
2 7u83 334
		}
7 7u83 335
		set_proc_token(p);
336
		COPY_list(tok_proc_bids(prev), p);
337
		COPY_list(tok_proc_pids(prev), q);
338
		n = LENGTH_list(q);
339
		IGNORE check_value(OPT_VAL_macro_pars,(ulong)n);
2 7u83 340
	}
7 7u83 341
	return (prev);
2 7u83 342
}
343
 
344
 
345
/*
346
    COMPLETE THE DEFINITION OF A PROCEDURE TOKEN
347
 
348
    This routine completes the definition of the procedure token prev by
349
    filling in the token result sort res.
350
*/
351
 
7 7u83 352
TOKEN
353
end_proc_token(TOKEN prev, TOKEN res)
2 7u83 354
{
7 7u83 355
	res = check_param_sort(res);
356
	if (!IS_NULL_tok(prev)) {
357
		COPY_tok(tok_proc_res(prev), res);
358
	}
359
	end_param();
360
	return (prev);
2 7u83 361
}
362
 
363
 
364
/*
365
    CREATE A TOKEN PARAMETER
366
 
367
    This routine declares a token bound parameter of sort tok with name
368
    id, which belongs to the tag namespace if tag is true.
369
*/
370
 
7 7u83 371
IDENTIFIER
372
make_tok_param(TOKEN tok, int tag, IDENTIFIER id)
2 7u83 373
{
7 7u83 374
	if (IS_NULL_id(id)) {
375
		HASHID nm = lookup_anon();
376
		id = DEREF_id(hashid_id(nm));
377
	}
378
	tok = check_param_sort(tok);
379
	id = make_token_decl(tok, tag, id, NULL_id);
380
	if (do_dump) {
381
		dump_token_param(id);
382
	}
383
	return (id);
2 7u83 384
}
385
 
386
 
387
/*
388
    FIND A TOKEN MEMBER
389
 
390
    This routine looks up a member id of the class type t.  If the member
391
    is not found or t is not a class type then an error message is printed
392
    and the null identifier is returned.
393
*/
394
 
7 7u83 395
IDENTIFIER
396
tok_member(IDENTIFIER id, TYPE t, int force)
2 7u83 397
{
7 7u83 398
	if (IS_type_compound(t)) {
399
		HASHID nm = DEREF_hashid(id_name(id));
400
		CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
401
		NAMESPACE ns = DEREF_nspace(ctype_member(ct));
402
		IDENTIFIER fid = search_id(ns, nm, 0, 0);
403
		if (IS_NULL_id(fid)) {
404
			/* Member not declared */
405
			if (force) {
406
				/* Report error */
407
				report(preproc_loc,
408
				       ERR_lookup_qual_bad(id, ns));
409
			} else {
410
				/* Create token member */
411
				TOKEN tok;
412
				HASHID fnm = lookup_anon();
413
				fid = DEREF_id(hashid_id(fnm));
414
				MAKE_tok_member(t, type_error, NULL_off, tok);
415
				fid = make_token_decl(tok, 0, id, fid);
416
				fid = DEREF_id(id_token_alt(fid));
417
			}
418
		}
419
		return (fid);
2 7u83 420
	}
7 7u83 421
	report(preproc_loc, ERR_token_mem(t));
422
	return (NULL_id);
2 7u83 423
}
424
 
425
 
426
/*
427
    CREATE A TOKEN PROGRAM PARAMETER
428
 
429
    This routine declares a token program parameter named id.  tt gives
430
    the associated token sort, while t gives the structure type if this
431
    denotes a member token or the parameter type if this denotes a type
432
    token.
433
*/
434
 
7 7u83 435
IDENTIFIER
436
prog_tok_param(IDENTIFIER id, TYPE t, unsigned tt, LIST(IDENTIFIER) p)
2 7u83 437
{
7 7u83 438
	/* Look up member identifier */
439
	IDENTIFIER tid = id;
440
	if (tt == tok_member_tag) {
441
		tid = tok_member(tid, t, 1);
442
		if (IS_NULL_id(tid)) {
443
			return (NULL_id);
444
		}
445
	}
2 7u83 446
 
7 7u83 447
	/* Check through tokens */
448
	while (!IS_NULL_list(p)) {
449
		IDENTIFIER pid = DEREF_id(HEAD_list(p));
450
		if (!IS_NULL_id(pid) && IS_id_token(pid)) {
451
			IDENTIFIER qid = DEREF_id(id_token_alt(pid));
452
			if (EQ_id(qid, tid)) {
453
				/* Matching token found */
454
				TOKEN tok = DEREF_tok(id_token_sort(pid));
455
				unsigned pt = TAG_tok(tok);
456
				switch (pt) {
457
				case tok_nat_tag:
458
				case tok_snat_tag:
459
					pt = tok_exp_tag;
460
					break;
461
				case tok_templ_tag:
462
				case tok_func_tag:
463
					pt = tok_proc_tag;
464
					break;
465
				}
466
				if (pt != tt) {
467
					/* Wrong sort given for token
468
					 * parameter */
469
					report(preproc_loc,
470
					       ERR_token_arg_sort(pid));
471
				}
472
				return (pid);
473
			}
2 7u83 474
		}
7 7u83 475
		p = TAIL_list(p);
2 7u83 476
	}
477
 
7 7u83 478
	/* Allow for complex type parameters */
479
	if (tt == tok_type_tag) {
480
		HASHID nm = lookup_anon();
481
		int tq = crt_templ_qualifier;
482
		QUALIFIER cq = crt_id_qualifier;
483
		crt_id_qualifier = qual_none;
484
		crt_templ_qualifier = 0;
485
		tid = DEREF_id(hashid_id(nm));
486
		tid = make_object_decl(dspec_typedef, t, tid, 0);
487
		crt_templ_qualifier = tq;
488
		crt_id_qualifier = cq;
489
		return (tid);
490
	}
491
	report(preproc_loc, ERR_token_arg_bad(tid));
492
	return (NULL_id);
2 7u83 493
}
494
 
495
 
496
/*
497
    FIND AN UNDERLYING PROCEDURE TOKEN
498
 
499
    This routine returns the procedure token underlying the function
500
    token tok, creating this if necessary.
501
*/
502
 
7 7u83 503
TOKEN
504
func_proc_token(TOKEN tok)
2 7u83 505
{
7 7u83 506
	TOKEN res;
507
	if (!IS_tok_func(tok)) {
508
		return (tok);
509
	}
510
	res = DEREF_tok(tok_func_proc(tok));
511
	if (IS_NULL_tok(res)) {
512
		TYPE t = DEREF_type(tok_func_type(tok));
513
		int ell = DEREF_int(type_func_ellipsis(t));
514
		if (ell & FUNC_ELLIPSIS) {
515
			res = tok;
516
		} else {
517
			TOKEN rtok;
518
			IDENTIFIER pid;
519
			EXP e = NULL_exp;
520
			LIST(IDENTIFIER) qids;
521
			IDENTIFIER fn = DEREF_id(tok_func_defn(tok));
522
			TYPE r = DEREF_type(type_func_ret(t));
523
			LIST(TYPE) p = DEREF_list(type_func_mtypes(t));
524
			LIST(IDENTIFIER) pids = NULL_list(IDENTIFIER);
525
			res = begin_proc_token();
526
			while (!IS_NULL_list(p)) {
527
				/* Normal function parameters */
528
				TYPE s = DEREF_type(HEAD_list(p));
529
				if (pass_complex_type(s)) {
530
					MAKE_type_ptr(cv_none, s, s);
531
				}
532
				MAKE_tok_exp(s, 0, NULL_exp, rtok);
533
				pid = make_tok_param(rtok, 0, NULL_id);
534
				CONS_id(pid, pids, pids);
535
				p = TAIL_list(p);
536
			}
537
			/* Extra constructor parameters ... */
538
			pids = REVERSE_list(pids);
539
			qids = pids;
540
			if (pass_complex_type(r)) {
541
				/* Complex function return */
542
				TYPE s;
543
				MAKE_type_ptr(cv_none, r, s);
544
				MAKE_tok_exp(s, 0, NULL_exp, rtok);
545
				pid = make_tok_param(rtok, 0, NULL_id);
546
				CONS_id(pid, pids, pids);
547
				r = type_void;
548
			}
549
			res = cont_proc_token(res, pids, qids);
550
			if (!IS_NULL_id(fn)) {
551
				/* Token already defined */
552
				MAKE_exp_value(t, e);
553
			}
554
			MAKE_tok_exp(r, 0, e, rtok);
555
			res = end_proc_token(res, rtok);
2 7u83 556
		}
7 7u83 557
		COPY_tok(tok_func_proc(tok), res);
2 7u83 558
	}
7 7u83 559
	return (res);
2 7u83 560
}
561
 
562
 
563
/*
564
    EXPAND A TOKEN VALUE
565
 
566
    This routine expands the token value tok. If force is true then a copy
567
    is always made.
568
*/
569
 
7 7u83 570
TOKEN
571
expand_sort(TOKEN tok, int rec, int force)
2 7u83 572
{
7 7u83 573
	if (!IS_NULL_tok(tok)) {
574
		unsigned tag = TAG_tok(tok);
575
		switch (tag) {
576
		case tok_exp_tag: {
577
			/* Expression tokens */
578
			EXP a1 = DEREF_exp(tok_exp_value(tok));
579
			EXP a2 = expand_exp(a1, rec, 0);
580
			if (force || !eq_exp_exact(a1, a2)) {
581
				int c = DEREF_int(tok_exp_constant(tok));
582
				TYPE t = DEREF_type(tok_exp_type(tok));
583
				t = expand_type(t, rec);
584
				MAKE_tok_exp(t, c, a2, tok);
585
			}
586
			break;
2 7u83 587
		}
7 7u83 588
		case tok_nat_tag:
589
		case tok_snat_tag: {
590
			/* Integral constant tokens */
591
			ERROR err = NULL_err;
592
			NAT n1 = DEREF_nat(tok_nat_etc_value(tok));
593
			NAT n2 = expand_nat(n1, rec, 0, &err);
594
			if (!IS_NULL_err(err)) {
595
				report(crt_loc, err);
596
			}
597
			if (force || !EQ_nat(n1, n2)) {
598
				MAKE_tok_nat_etc(tag, n2, tok);
599
			}
600
			break;
2 7u83 601
		}
7 7u83 602
		case tok_stmt_tag: {
603
			/* Statement tokens */
604
			EXP a1 = DEREF_exp(tok_stmt_value(tok));
605
			EXP a2 = expand_exp(a1, rec, 1);
606
			if (force || !eq_exp_exact(a1, a2)) {
607
				EXP b = get_parent_stmt(a1);
608
				set_parent_stmt(a2, b);
609
				MAKE_tok_stmt(a2, tok);
610
			}
611
			break;
2 7u83 612
		}
7 7u83 613
		case tok_member_tag: {
614
			/* Member tokens */
615
			OFFSET a1 = DEREF_off(tok_member_value(tok));
616
			OFFSET a2 = expand_offset(a1, rec);
617
			if (force || !EQ_off(a1, a2)) {
618
				TYPE s = DEREF_type(tok_member_of(tok));
619
				TYPE t = DEREF_type(tok_member_type(tok));
620
				s = expand_type(s, rec);
621
				t = expand_type(t, rec);
622
				MAKE_tok_member(s, t, a2, tok);
623
			}
624
			break;
2 7u83 625
		}
7 7u83 626
		case tok_type_tag: {
627
			/* Type tokens */
628
			TYPE t1 = DEREF_type(tok_type_value(tok));
629
			TYPE t2 = expand_type(t1, rec);
630
			if (force || !EQ_type(t1, t2)) {
631
				BASE_TYPE bs = DEREF_btype(tok_type_kind(tok));
632
				MAKE_tok_type(bs, t2, tok);
633
			}
634
			break;
2 7u83 635
		}
7 7u83 636
		case tok_class_tag: {
637
			/* Template class tokens */
638
			IDENTIFIER cid = DEREF_id(tok_class_value(tok));
639
			/* NOT YET IMPLEMENTED */
640
			if (force) {
641
				TYPE s = DEREF_type(tok_class_type(tok));
642
				TYPE t = DEREF_type(tok_class_alt(tok));
643
				MAKE_tok_class(s, cid, tok);
644
				COPY_type(tok_class_alt(tok), t);
645
			}
646
			break;
2 7u83 647
		}
7 7u83 648
		case tok_templ_tag: {
649
			/* Template tokens */
650
			if (force) {
651
				int d;
652
				LIST(IDENTIFIER) pids;
653
				LIST(IDENTIFIER) rids;
654
				LIST(IDENTIFIER) qids = NULL_list(IDENTIFIER);
655
				DECL_SPEC ds =
656
				    DEREF_dspec(tok_templ_usage(tok));
657
				NAMESPACE ns =
658
				    DEREF_nspace(tok_templ_pars(tok));
659
				pids = DEREF_list(tok_templ_pids(tok));
660
				rids = pids;
661
				d = save_token_args(rids, NULL_list(TOKEN));
662
				while (!IS_NULL_list(pids)) {
663
					/* Copy template parameters */
664
					TOKEN arg;
665
					IDENTIFIER qid2;
666
					IDENTIFIER pid =
667
					    DEREF_id(HEAD_list(pids));
668
					IDENTIFIER pid2 =
669
					    DEREF_id(id_token_alt(pid));
670
					IDENTIFIER qid = copy_id(pid, 2);
671
					DECL_SPEC qds =
672
					    DEREF_dspec(id_storage(qid));
673
					qds |= dspec_pure;
674
					COPY_dspec(id_storage(qid), qds);
675
					arg = apply_token(qid,
676
							  NULL_list(TOKEN));
677
					assign_token(pid, arg);
678
					qid2 = copy_id(pid2, 2);
679
					COPY_id(id_token_alt(qid), qid2);
680
					CONS_id(qid, qids, qids);
681
					pids = TAIL_list(pids);
682
				}
683
				restore_token_args(rids, d);
684
				MAKE_tok_templ(ds, ns, tok);
685
				qids = REVERSE_list(qids);
686
				COPY_list(tok_templ_pids(tok), qids);
687
				set_proc_token(qids);
688
			}
689
			break;
2 7u83 690
		}
7 7u83 691
		}
2 7u83 692
	}
7 7u83 693
	return (tok);
2 7u83 694
}
695
 
696
 
697
/*
698
    EXPAND A LIST OF TOKEN ARGUMENTS
699
 
700
    This routine expands the list of token arguments p passing the parameter
701
    rec to the individual expansion routines.  The null list is returned to
702
    indicate that the expansion has no effect.
703
*/
704
 
7 7u83 705
LIST(TOKEN)
706
expand_args(LIST(TOKEN) p, int rec, int force)
2 7u83 707
{
7 7u83 708
	int changed = 0;
709
	LIST(TOKEN) q = NULL_list(TOKEN);
710
	while (!IS_NULL_list(p)) {
711
		TOKEN a = DEREF_tok(HEAD_list(p));
712
		TOKEN b = expand_sort(a, rec, force);
713
		if (!EQ_tok(a, b)) {
714
			changed = 1;
715
		}
716
		CONS_tok(b, q, q);
717
		p = TAIL_list(p);
718
	}
719
	if (!changed) {
720
		/* No effect */
721
		DESTROY_list(q, SIZE_tok);
722
		return (NULL_list(TOKEN));
723
	}
724
	q = REVERSE_list(q);
725
	return (q);
2 7u83 726
}
727
 
728
 
729
/*
730
    EXPAND A TEMPLATE SORT
731
 
732
    This routine copies the given template sort producing a new sort
733
    comprising only those parameters which are unbound.  If all the
734
    parameters are bound then the null sort is returned.
735
*/
736
 
7 7u83 737
TOKEN
738
expand_templ_sort(TOKEN sort, int rec)
2 7u83 739
{
7 7u83 740
	NAMESPACE ns;
741
	int changed = 0;
742
	int all_unbound = 1;
743
	LIST(TOKEN) dargs = NULL_list(TOKEN);
744
	DECL_SPEC ex = DEREF_dspec(tok_templ_usage(sort));
745
	LIST(IDENTIFIER) p = DEREF_list(tok_templ_pids(sort));
746
	LIST(IDENTIFIER) q = NULL_list(IDENTIFIER);
747
	LIST(IDENTIFIER) p0 = p;
748
	while (!IS_NULL_list(p)) {
749
		IDENTIFIER pid = DEREF_id(HEAD_list(p));
750
		if (!IS_NULL_id(pid) && IS_id_token(pid)) {
751
			TOKEN tok = DEREF_tok(id_token_sort(pid));
752
			if (is_bound_tok(tok, 0)) {
753
				/* Have bound parameter */
754
				all_unbound = 0;
755
				changed = 1;
756
			} else {
757
				/* Add unbound parameter to list */
758
				/* NOT YET IMPLEMENTED */
759
				CONS_id(pid, q, q);
760
			}
761
		}
762
		p = TAIL_list(p);
2 7u83 763
	}
7 7u83 764
	if (IS_NULL_list(q)) {
765
		/* All parameters are bound */
766
		return (NULL_tok);
767
	}
768
	if (changed) {
769
		/* Get unbound parameters into order */
770
		q = REVERSE_list(q);
771
	} else {
772
		/* Use existing list */
773
		DESTROY_list(q, SIZE_id);
774
		q = p0;
775
	}
776
	if (all_unbound) {
777
		/* Preserve instances and default arguments */
778
		LIST(TOKEN) d;
779
		dargs = DEREF_list(tok_templ_dargs(sort));
780
		d = expand_args(dargs, rec, 0);
781
		if (!IS_NULL_list(d)) {
782
			dargs = d;
783
		}
784
	}
785
	ns = DEREF_nspace(tok_templ_pars(sort));
786
	MAKE_tok_templ(ex, ns, sort);
787
	COPY_list(tok_templ_pids(sort), q);
788
	COPY_list(tok_templ_dargs(sort), dargs);
789
	return (sort);
2 7u83 790
}
791
 
792
 
793
/*
794
    RESTORE A TEMPLATE SORT
795
 
796
    This routine is called at the end of the expansion of a template
797
    type to restore the sort produced by expand_templ_sort.
798
*/
799
 
7 7u83 800
void
801
reset_templ_sort(TOKEN sort)
2 7u83 802
{
7 7u83 803
	UNUSED(sort);
804
	return;
2 7u83 805
}
806
 
807
 
808
/*
809
    EXPAND AN EXPRESSION TOKEN
810
 
811
    This routine expands any token definitions in the expression e.
812
    rec gives the level of expansion, 0 for just the top level, 1 for a
813
    complete recursive expansion, and 2 for a recursive expansion of
814
    token parameters only.  Negative values just return e.
815
*/
816
 
7 7u83 817
EXP
818
expand_exp(EXP e, int rec, int stmt)
2 7u83 819
{
7 7u83 820
	unsigned etag;
821
	if (rec < 0) {
822
		return (e);
2 7u83 823
	}
7 7u83 824
	if (IS_NULL_exp(e)) {
825
		return (NULL_exp);
2 7u83 826
	}
7 7u83 827
	etag = TAG_exp(e);
828
	if (etag == exp_token_tag) {
829
		/* Tokenised values */
830
		TOKEN tok;
831
		DECL_SPEC ds;
832
		unsigned tag;
833
		IDENTIFIER id = DEREF_id(exp_token_tok(e));
834
		IDENTIFIER aid = DEREF_id(id_alias(id));
835
		LIST(TOKEN) p = DEREF_list(exp_token_args(e));
836
		if (!EQ_id(id, aid)) {
837
			/* Replace token by its alias */
838
			e = apply_exp_token(aid, p, 1);
839
			id = aid;
2 7u83 840
		}
7 7u83 841
		ds = DEREF_dspec(id_storage(id));
842
		tok = DEREF_tok(id_token_sort(id));
843
		tag = TAG_tok(tok);
844
		if (tag == tok_proc_tag) {
845
			tok = DEREF_tok(tok_proc_res(tok));
846
			tag = TAG_tok(tok);
2 7u83 847
		}
7 7u83 848
		if (rec) {
849
			/* Expand token arguments */
850
			p = expand_args(p, rec, 1);
851
			e = apply_exp_token(id, p, rec);
852
		}
853
		/* if ( rec == 2 && !( ds & dspec_auto ) ) break ; */
854
		if (ds & dspec_temp) {
855
			/* Check for recursive token expansions */
856
			report(crt_loc, ERR_token_recursive(id));
857
			return (make_error_exp(0));
858
		}
859
		COPY_dspec(id_storage(id), (ds | dspec_temp));
860
		if (tag == tok_exp_tag) {
861
			EXP a = DEREF_exp(tok_exp_value(tok));
862
			if (!IS_NULL_exp(a)) {
863
				/* Expand token definition */
864
				e = expand_exp(a, rec, 0);
865
				if (ds & dspec_auto) {
866
					COPY_exp(tok_exp_value(tok), e);
867
				}
868
			}
869
		} else if (tag == tok_stmt_tag) {
870
			EXP a = DEREF_exp(tok_stmt_value(tok));
871
			if (!IS_NULL_exp(a)) {
872
				/* Expand token definition */
873
				EXP b = get_parent_stmt(a);
874
				e = expand_exp(a, rec, 1);
875
				set_parent_stmt(e, b);
876
				if (ds & dspec_auto) {
877
					COPY_exp(tok_stmt_value(tok), e);
878
				}
879
			}
880
		}
881
		COPY_dspec(id_storage(id), ds);
2 7u83 882
 
7 7u83 883
	} else if (etag == exp_int_lit_tag) {
884
		/* Integer constants */
885
		ERROR err = NULL_err;
886
		NAT n1 = DEREF_nat(exp_int_lit_nat(e));
887
		NAT n2 = expand_nat(n1, rec, 0, &err);
888
		if (rec || !EQ_nat(n1, n2)) {
889
			TYPE t = DEREF_type(exp_type(e));
890
			unsigned tag = DEREF_unsigned(exp_int_lit_etag(e));
891
			MAKE_exp_int_lit(t, n2, tag, e);
892
			if (!IS_NULL_err(err)) {
893
				report(crt_loc, err);
894
			}
895
		}
896
	} else {
897
		/* Other cases */
898
		if (rec && !stmt) {
899
			e = copy_exp(e, NULL_type, NULL_type);
900
		}
2 7u83 901
	}
7 7u83 902
	return (e);
2 7u83 903
}
904
 
905
 
906
/*
907
    EXPAND AN INTEGER CONSTANT TOKEN
908
 
909
    This routine expands any token definitions in the integer constant
910
    expression n.  rec is as above, ch is as in eval_exp.
911
*/
912
 
7 7u83 913
NAT
914
expand_nat(NAT n, int rec, int ch, ERROR *err)
2 7u83 915
{
7 7u83 916
	if (rec < 0) {
917
		return (n);
918
	}
919
	if (IS_NULL_nat(n)) {
920
		return (NULL_nat);
921
	}
922
	switch (TAG_nat(n)) {
923
	case nat_calc_tag: {
924
		/* Calculated values */
925
		EXP e2;
926
		EXP e1 = DEREF_exp(nat_calc_value(n));
927
		ulong tok = DEREF_ulong(nat_calc_tok(n));
928
		if (rec) {
929
			e2 = eval_exp(e1, ch);
930
		} else {
931
			e2 = expand_exp(e1, 0, 0);
2 7u83 932
		}
7 7u83 933
		e2 = convert_reference(e2, REF_NORMAL);
934
		e2 = convert_lvalue(e2);
935
		if (!EQ_exp(e1, e2) && !eq_exp_exact(e1, e2)) {
936
			n = make_nat_exp(e2, err);
937
			if (IS_nat_calc(n)) {
938
				COPY_ulong(nat_calc_tok(n), tok);
939
			}
940
		}
941
		break;
2 7u83 942
	}
7 7u83 943
	case nat_token_tag: {
944
		/* Tokenised values */
945
		TOKEN tok;
946
		DECL_SPEC ds;
947
		unsigned tag;
948
		IDENTIFIER id = DEREF_id(nat_token_tok(n));
949
		IDENTIFIER aid = DEREF_id(id_alias(id));
950
		LIST(TOKEN)p = DEREF_list(nat_token_args(n));
951
		if (!EQ_id(id, aid)) {
952
			/* Replace token by its alias */
953
			n = apply_nat_token(aid, p);
954
			id = aid;
2 7u83 955
		}
7 7u83 956
		ds = DEREF_dspec(id_storage(id));
957
		tok = DEREF_tok(id_token_sort(id));
958
		tag = TAG_tok(tok);
959
		if (tag == tok_proc_tag) {
960
			if (rec) {
961
				/* Expand token arguments */
962
				p = expand_args(p, rec, 0);
963
				if (!IS_NULL_list(p)) {
964
					n = apply_nat_token(id, p);
965
				}
966
			}
967
			tok = DEREF_tok(tok_proc_res(tok));
968
			tag = TAG_tok(tok);
2 7u83 969
		}
7 7u83 970
		/* if ( rec == 2 && !( ds & dspec_auto ) ) break ; */
971
		if (ds & dspec_temp) {
972
			/* Check for recursive token expansions */
973
			report(crt_loc, ERR_token_recursive(id));
974
			return (small_nat[1]);
975
		}
976
		COPY_dspec(id_storage(id), (ds | dspec_temp));
977
		if (tag == tok_nat_tag || tag == tok_snat_tag) {
978
			NAT m = DEREF_nat(tok_nat_etc_value(tok));
979
			if (!IS_NULL_nat(m)) {
980
				/* Expand token definition */
981
				n = expand_nat(m, rec, ch, err);
982
				if (ds & dspec_auto) {
983
					COPY_nat(tok_nat_etc_value(tok), n);
984
				}
985
			}
986
		}
987
		COPY_dspec(id_storage(id), ds);
988
		break;
2 7u83 989
	}
7 7u83 990
	}
991
	return (n);
2 7u83 992
}
993
 
994
 
995
/*
996
    EXPAND A MEMBER TOKEN
997
 
998
    This routine expands any token definitions in the offset off.  rec
999
    is as above.
1000
*/
1001
 
7 7u83 1002
OFFSET
1003
expand_offset(OFFSET off, int rec)
2 7u83 1004
{
7 7u83 1005
	if (rec > 0) {
1006
		off = copy_offset(off, lex_plus);
1007
	}
1008
	return (off);
2 7u83 1009
}
1010
 
1011
 
1012
/*
1013
    EXPAND A TEMPLATE TYPE
1014
 
1015
    This routine is a special case of expand_type which deals with
1016
    template types.
1017
*/
1018
 
7 7u83 1019
static TYPE
1020
expand_templ_type(TYPE t, int rec)
2 7u83 1021
{
7 7u83 1022
	CV_SPEC cv = DEREF_cv(type_qual(t));
1023
	TYPE s = DEREF_type(type_templ_defn(t));
1024
	TOKEN sort = DEREF_tok(type_templ_sort(t));
1025
	sort = expand_templ_sort(sort, rec);
1026
	if (IS_type_compound(s)) {
1027
		/* Template classes */
1028
		s = copy_class(s, dspec_instance);
1029
	} else {
1030
		/* Other template types */
1031
		s = expand_type(s, rec);
1032
	}
1033
	if (IS_NULL_tok(sort)) {
1034
		/* No unbound parameters */
1035
		t = qualify_type(s, cv, 0);
1036
	} else {
1037
		/* Unbound parameters - result is a specialisation */
1038
		MAKE_type_templ(cv, sort, s, 1, t);
1039
	}
1040
	reset_templ_sort(sort);
1041
	return (t);
2 7u83 1042
}
1043
 
1044
 
1045
/*
1046
    EXPAND A LIST OF EXCEPTION TYPES
1047
 
1048
    This routine expands the list of exception types p, setting changed to
1049
    true if any changes.
1050
*/
1051
 
7 7u83 1052
LIST(TYPE)
1053
expand_exceptions(LIST(TYPE) p, int rec, int *changed)
2 7u83 1054
{
7 7u83 1055
	LIST(TYPE) q = NULL_list(TYPE);
1056
	if (EQ_list(p, univ_type_set)) {
1057
		q = p;
1058
	} else if (EQ_list(p, empty_type_set)) {
1059
		q = p;
1060
	} else {
1061
		while (!IS_NULL_list(p)) {
1062
			TYPE s1 = DEREF_type(HEAD_list(p));
1063
			TYPE s2 = expand_type(s1, rec);
1064
			if (!EQ_type(s1, s2)) {
1065
				s2 = check_except_type(s2, 0);
1066
				*changed = 1;
1067
			}
1068
			CONS_type(s2, q, q);
1069
			p = TAIL_list(p);
1070
		}
1071
		q = REVERSE_list(q);
2 7u83 1072
	}
7 7u83 1073
	return (q);
2 7u83 1074
}
1075
 
1076
 
1077
/*
1078
    EXPAND A FUNCTION TYPE
1079
 
1080
    This routine is a special case of expand_type which deals with
1081
    function types.  rec will not be zero.
1082
*/
1083
 
7 7u83 1084
static TYPE
1085
expand_func_type(TYPE t, int rec)
2 7u83 1086
{
7 7u83 1087
	int mf = 0;
1088
	int expanded = 0;
1089
	TYPE r1 = DEREF_type(type_func_ret(t));
1090
	TYPE r2;
1091
	LIST(TYPE) p1 = DEREF_list(type_func_ptypes(t));
1092
	LIST(TYPE) p2;
1093
	LIST(TYPE) m1 = DEREF_list(type_func_mtypes(t));
1094
	LIST(TYPE) m2 = NULL_list(TYPE);
1095
	LIST(TYPE) e1 = DEREF_list(type_func_except(t));
1096
	LIST(TYPE) e2;
1097
	if (!EQ_list(p1, m1)) {
1098
		if (!IS_NULL_list(m1) && EQ_list(p1, TAIL_list(m1))) {
1099
			/* Normal member function type */
1100
			mf = 1;
1101
		} else {
1102
			/* Swapped member function type */
1103
			mf = -1;
1104
			m1 = p1;
1105
		}
2 7u83 1106
	}
1107
 
7 7u83 1108
	/* Copy return type */
1109
	r2 = expand_type(r1, rec);
1110
	if (!EQ_type(r1, r2)) {
1111
		expanded = 1;
1112
	}
2 7u83 1113
 
7 7u83 1114
	/* Copy parameter types */
1115
	while (!IS_NULL_list(m1)) {
1116
		TYPE s1 = DEREF_type(HEAD_list(m1));
1117
		TYPE s2 = expand_type(s1, rec);
1118
		if (!EQ_type(s1, s2)) {
1119
			expanded = 1;
1120
		}
1121
		CONS_type(s2, m2, m2);
1122
		m1 = TAIL_list(m1);
1123
	}
1124
	m2 = REVERSE_list(m2);
2 7u83 1125
 
7 7u83 1126
	/* Copy exception types */
1127
	e2 = expand_exceptions(e1, rec, &expanded);
2 7u83 1128
 
7 7u83 1129
	/* Check for default arguments */
1130
	if (!expanded) {
1131
		LIST(IDENTIFIER) pids = DEREF_list(type_func_pids(t));
1132
		while (!IS_NULL_list(pids)) {
1133
			IDENTIFIER id = DEREF_id(HEAD_list(pids));
1134
			EXP e = DEREF_exp(id_parameter_init(id));
1135
			if (!IS_NULL_exp(e)) {
1136
				if (depends_on_exp(e, any_token_param, 0)) {
1137
					/* Needs expansion */
1138
					expanded = 1;
1139
					break;
1140
				}
1141
			}
1142
			pids = TAIL_list(pids);
2 7u83 1143
		}
1144
	}
1145
 
7 7u83 1146
	/* Expand remaining items */
1147
	if (expanded) {
1148
		CV_SPEC cv = DEREF_cv(type_qual(t));
1149
		CV_SPEC mq = DEREF_cv(type_func_mqual(t));
1150
		int ell = DEREF_int(type_func_ellipsis(t));
1151
		NAMESPACE pars = DEREF_nspace(type_func_pars(t));
1152
		LIST(IDENTIFIER) pids = DEREF_list(type_func_pids(t));
1153
		LIST(IDENTIFIER) qids = NULL_list(IDENTIFIER);
2 7u83 1154
 
7 7u83 1155
		/* Copy parameters */
1156
		while (!IS_NULL_list(pids)) {
1157
			TYPE s;
1158
			IDENTIFIER id = DEREF_id(HEAD_list(pids));
1159
			IDENTIFIER lid = chase_alias(id);
1160
			EXP e = DEREF_exp(id_parameter_init(id));
1161
			id = copy_id(id, 2);
1162
			COPY_id(id_alias(id), lid);
1163
			s = DEREF_type(id_parameter_type(id));
1164
			check_par_decl(s, id, CONTEXT_WEAK_PARAM);
1165
			if (!IS_NULL_exp(e)) {
1166
				/* Copy default argument */
1167
				EXP d;
1168
				e = expand_exp(e, rec, 0);
1169
				e = init_general(s, e, id, 0);
1170
				d = destroy_general(s, id);
1171
				COPY_exp(id_parameter_term(id), d);
1172
				COPY_exp(id_parameter_init(id), e);
1173
			}
1174
			CONS_id(id, qids, qids);
1175
			pids = TAIL_list(pids);
1176
		}
1177
		qids = REVERSE_list(qids);
2 7u83 1178
 
7 7u83 1179
		/* Form function type */
1180
		if (mf == 0) {
1181
			p2 = m2;
1182
		} else if (mf == 1) {
1183
			p2 = TAIL_list(m2);
1184
		} else {
1185
			p2 = m2;
1186
			m2 = TAIL_list(p2);
1187
		}
1188
		MAKE_type_func(cv, NULL_type, p2, ell, mq, m2, pars, qids, e2,
1189
			       t);
1190
		t = inject_pre_type(t, r2, 0);
2 7u83 1191
	} else {
7 7u83 1192
		/* Free unused type lists */
1193
		if (!EQ_list(m2, m1)) {
1194
			DESTROY_list(m2, SIZE_type);
1195
		}
1196
		if (!EQ_list(e2, e1)) {
1197
			DESTROY_list(e2, SIZE_type);
1198
		}
2 7u83 1199
	}
7 7u83 1200
	return (t);
2 7u83 1201
}
1202
 
1203
 
1204
/*
1205
    RESCAN A CLASS NAME
1206
 
1207
    This routine expands the class type ct by rescanning its name in the
1208
    current context.  It returns the null type if the result is not a
1209
    type name.
1210
*/
1211
 
7 7u83 1212
static TYPE
1213
rescan_class(CLASS_TYPE ct)
2 7u83 1214
{
7 7u83 1215
	IDENTIFIER cid = DEREF_id(ctype_name(ct));
1216
	TYPE t = find_typename(cid, NULL_list(TOKEN), btype_none, 1);
1217
	return (t);
2 7u83 1218
}
1219
 
1220
 
1221
/*
1222
    RESCAN AN ENUMERATION NAME
1223
 
1224
    This routine expands the enumeration type et by rescanning its name
1225
    in the current context.  It returns the null type if the result is
1226
    not a type name.
1227
*/
1228
 
7 7u83 1229
static TYPE
1230
rescan_enum(ENUM_TYPE et)
2 7u83 1231
{
7 7u83 1232
	IDENTIFIER eid = DEREF_id(etype_name(et));
1233
	TYPE t = find_typename(eid, NULL_list(TOKEN), btype_none, 1);
1234
	return (t);
2 7u83 1235
}
1236
 
1237
 
1238
/*
1239
    EXPAND A CLASS TYPE
1240
 
1241
    This routine expands any token definitions in the class type ct.
1242
    rec is as above.  The null class is returned if the result is not
1243
    a class type with the actual type being assigned to pt.
1244
*/
1245
 
7 7u83 1246
CLASS_TYPE
1247
expand_ctype(CLASS_TYPE ct, int rec, TYPE *pt)
2 7u83 1248
{
7 7u83 1249
	if (rec >= 0) {
1250
		TYPE s = NULL_type;
1251
		TYPE t = DEREF_type(ctype_form(ct));
1252
		if (!IS_NULL_type(t)) {
1253
			if (IS_type_token(t)) {
1254
				IDENTIFIER id = DEREF_id(type_token_tok(t));
1255
				LIST(TOKEN) p = DEREF_list(type_token_args(t));
1256
				if (IS_id_token(id)) {
1257
					/* Tokenised classes */
1258
					s = expand_type(t, rec);
1259
				} else if (rec) {
1260
					/* Template classes */
1261
					p = expand_args(p, rec, 0);
1262
					if (!IS_NULL_list(p)) {
1263
						/* Template class instance */
1264
						id = instance_type(id, p, 0, 1);
1265
						s = DEREF_type(id_class_name_defn(id));
1266
						while (IS_type_templ(s)) {
1267
							s = DEREF_type(type_templ_defn(s));
1268
						}
1269
					}
1270
				}
1271
				if (EQ_type(s, t)) {
1272
					/* No expansion possible */
1273
					return (ct);
1274
				}
1275
			} else if (IS_type_instance(t)) {
1276
				s = rescan_class(ct);
1277
				if (EQ_type(s, t)) {
1278
					/* No expansion possible */
1279
					return (ct);
1280
				}
1281
			} else {
1282
				/* Recursive template classes */
1283
				s = expand_type(t, rec);
2 7u83 1284
			}
7 7u83 1285
		} else {
1286
			CLASS_INFO ci = DEREF_cinfo(ctype_info(ct));
1287
			if (ci & cinfo_rescan)s = rescan_class(ct);
2 7u83 1288
		}
7 7u83 1289
		if (!IS_NULL_type(s)) {
1290
			if (IS_type_compound(s)) {
1291
				ct = DEREF_ctype(type_compound_defn(s));
1292
			} else {
1293
				*pt = s;
1294
				if (is_templ_type(s)) {
1295
					IDENTIFIER id =
1296
					    DEREF_id(type_token_tok(s));
1297
					ct = find_class(id);
1298
				} else {
1299
					ct = NULL_ctype;
1300
				}
1301
			}
2 7u83 1302
		}
1303
	}
7 7u83 1304
	return (ct);
2 7u83 1305
}
1306
 
1307
 
1308
/*
1309
    BITFIELD EXPANSION FLAG
1310
 
1311
    This flag may be set to true to allow for zero sized bitfields in
1312
    expand_type.  The only way this can occur is in the expansion
1313
    of an anonymous member type.
1314
*/
1315
 
7 7u83 1316
int expand_anon_bitfield = 0;
2 7u83 1317
 
1318
 
1319
/*
1320
    EXPAND A TYPE TOKEN
1321
 
1322
    This routine expands any token definitions in the type t.  rec is
1323
    as above.
1324
*/
1325
 
7 7u83 1326
TYPE
1327
expand_type(TYPE t, int rec)
2 7u83 1328
{
7 7u83 1329
	CV_SPEC cv;
1330
	int prom = 0;
1331
	IDENTIFIER id;
1332
	LIST(TOKEN) p;
1333
	if (rec < 0) {
1334
		return (t);
2 7u83 1335
	}
7 7u83 1336
	if (IS_NULL_type(t)) {
1337
		return (NULL_type);
2 7u83 1338
	}
7 7u83 1339
	cv = DEREF_cv(type_qual(t));
1340
	ASSERT(ORDER_type == 18);
1341
	switch (TAG_type(t)) {
1342
	case type_integer_tag: {
1343
		/* Integral types */
1344
		INT_TYPE it = DEREF_itype(type_integer_rep(t));
1345
		unsigned tag = TAG_itype(it);
1346
		if (tag == itype_arith_tag) {
1347
			/* Expand arithmetic types */
1348
			INT_TYPE ir = DEREF_itype(itype_arith_arg1(it));
1349
			INT_TYPE is = DEREF_itype(itype_arith_arg2(it));
1350
			TYPE r1 = DEREF_type(itype_prom(ir));
1351
			TYPE r2 = expand_type(r1, rec);
1352
			TYPE s1 = DEREF_type(itype_prom(is));
1353
			TYPE s2 = expand_type(s1, rec);
1354
			if (!EQ_type(r1, r2) || !EQ_type(s1, s2)) {
1355
				t = arith_type(r2, s2, NULL_exp, NULL_exp);
1356
				if (cv) {
1357
					t = qualify_type(t, cv, 0);
1358
				}
1359
			}
1360
		} else {
1361
			/* Expand other integral types */
1362
			if (tag == itype_promote_tag) {
1363
				it = DEREF_itype(itype_promote_arg(it));
1364
				tag = TAG_itype(it);
1365
				prom = 1;
1366
			}
1367
			if (tag == itype_token_tag) {
1368
				id = DEREF_id(itype_token_tok(it));
1369
				p = DEREF_list(itype_token_args(it));
1370
				goto expand_label;
1371
			}
1372
			if (tag == itype_basic_tag) {
1373
				/* Allow for special tokens */
1374
				BUILTIN_TYPE n =
1375
				    DEREF_ntype(itype_basic_no(it));
1376
				id = get_special(base_token[n].tok, 0);
1377
				if (!IS_NULL_id(id)) {
1378
					p = NULL_list(TOKEN);
1379
					goto expand_label;
1380
				}
1381
			}
2 7u83 1382
		}
7 7u83 1383
		break;
2 7u83 1384
	}
7 7u83 1385
	case type_floating_tag: {
1386
		/* Floating point types */
1387
		FLOAT_TYPE ft = DEREF_ftype(type_floating_rep(t));
1388
		unsigned tag = TAG_ftype(ft);
1389
		if (tag == ftype_arith_tag) {
1390
			/* Expand arithmetic types */
1391
			FLOAT_TYPE fr = DEREF_ftype(ftype_arith_arg1(ft));
1392
			FLOAT_TYPE fs = DEREF_ftype(ftype_arith_arg2(ft));
1393
			TYPE r1 = make_ftype(fr, NULL_ftype);
1394
			TYPE r2 = expand_type(r1, rec);
1395
			TYPE s1 = make_ftype(fs, NULL_ftype);
1396
			TYPE s2 = expand_type(s1, rec);
1397
			if (!EQ_type(r1, r2) || !EQ_type(s1, s2)) {
1398
				t = arith_type(r2, s2, NULL_exp, NULL_exp);
1399
				if (cv) {
1400
					t = qualify_type(t, cv, 0);
1401
				}
1402
			}
1403
		} else {
1404
			/* Expand other floating point types */
1405
			if (tag == ftype_arg_promote_tag) {
1406
				ft = DEREF_ftype(ftype_arg_promote_arg(ft));
1407
				tag = TAG_ftype(ft);
1408
				prom = 2;
1409
			}
1410
			if (tag == ftype_token_tag) {
1411
				id = DEREF_id(ftype_token_tok(ft));
1412
				p = DEREF_list(ftype_token_args(ft));
1413
				goto expand_label;
1414
			}
2 7u83 1415
		}
7 7u83 1416
		break;
2 7u83 1417
	}
7 7u83 1418
	case type_ptr_tag:
1419
		/* Pointer types */
1420
		if (rec) {
1421
			TYPE s1 = DEREF_type(type_ptr_sub(t));
1422
			TYPE s2 = expand_type(s1, rec);
1423
			if (!EQ_type(s1, s2)) {
1424
				if (TAG_type(s1) == TAG_type(s2)) {
1425
					/* Don't check in this case */
1426
					MAKE_type_ptr(cv, s2, t);
1427
				} else {
1428
					MAKE_type_ptr(cv, NULL_type, t);
1429
					t = inject_pre_type(t, s2, 0);
1430
				}
1431
			}
2 7u83 1432
		}
7 7u83 1433
		break;
1434
	case type_ref_tag:
1435
		/* Reference types */
1436
		if (rec) {
1437
			TYPE s1 = DEREF_type(type_ref_sub(t));
1438
			TYPE s2 = expand_type(s1, rec);
1439
			if (!EQ_type(s1, s2)) {
1440
				MAKE_type_ref(cv, NULL_type, t);
1441
				t = inject_pre_type(t, s2, 0);
1442
			}
2 7u83 1443
		}
7 7u83 1444
		break;
1445
	case type_ptr_mem_tag: {
1446
		/* Pointer to member types */
1447
		if (rec) {
1448
			TYPE r2 = NULL_type;
1449
			CLASS_TYPE c1 = DEREF_ctype(type_ptr_mem_of(t));
1450
			CLASS_TYPE c2 = expand_ctype(c1, rec, &r2);
1451
			TYPE s1 = DEREF_type(type_ptr_mem_sub(t));
1452
			TYPE s2 = expand_type(s1, rec);
1453
			if (!EQ_ctype(c1, c2)) {
1454
				if (IS_NULL_ctype(c2)) {
1455
					/* Illegal class type expansion */
1456
					report(crt_loc, ERR_dcl_mptr_class(r2));
1457
					MAKE_type_ptr(cv, NULL_type, t);
1458
				} else {
1459
					MAKE_type_ptr_mem(cv, c2, NULL_type, t);
1460
				}
1461
				t = inject_pre_type(t, s2, 0);
1462
			} else if (!EQ_type(s1, s2)) {
1463
				MAKE_type_ptr_mem(cv, c1, NULL_type, t);
1464
				t = inject_pre_type(t, s2, 0);
2 7u83 1465
			}
1466
		}
7 7u83 1467
		break;
2 7u83 1468
	}
7 7u83 1469
	case type_func_tag:
1470
		/* Function types */
1471
		if (rec) {
1472
			t = expand_func_type(t, rec);
2 7u83 1473
		}
7 7u83 1474
		break;
1475
	case type_array_tag:
1476
		/* Array types */
1477
		if (rec) {
1478
			ERROR err = NULL_err;
1479
			TYPE s1 = DEREF_type(type_array_sub(t));
1480
			TYPE s2 = expand_type(s1, rec);
1481
			NAT n1 = DEREF_nat(type_array_size(t));
1482
			NAT n2 = expand_nat(n1, rec, 0, &err);
1483
			if (!EQ_nat(n1, n2)) {
1484
				if (!IS_NULL_err(err)) {
1485
					ERROR err2 = ERR_dcl_array_dim_const();
1486
					err = concat_error(err, err2);
1487
					report(crt_loc, err);
1488
				}
1489
				n2 = check_array_dim(n2);
1490
				MAKE_type_array(cv, NULL_type, n2, t);
1491
				t = inject_pre_type(t, s2, 0);
1492
			} else if (!EQ_type(s1, s2)) {
1493
				MAKE_type_array(cv, NULL_type, n2, t);
1494
				t = inject_pre_type(t, s2, 0);
1495
			}
2 7u83 1496
		}
7 7u83 1497
		break;
1498
	case type_bitfield_tag:
1499
		/* Bitfield types */
1500
		if (rec) {
1501
			ERROR err = NULL_err;
1502
			INT_TYPE it = DEREF_itype(type_bitfield_defn(t));
1503
			TYPE s1 = DEREF_type(itype_bitfield_sub(it));
1504
			NAT n1 = DEREF_nat(itype_bitfield_size(it));
1505
			TYPE s2 = expand_type(s1, rec);
1506
			NAT n2 = expand_nat(n1, rec, 0, &err);
1507
			if (!EQ_type(s1, s2) || !EQ_nat(n1, n2)) {
1508
				BASE_TYPE rep;
1509
				int anon = expand_anon_bitfield;
1510
				rep = DEREF_btype(itype_bitfield_rep(it));
1511
				if (!IS_NULL_err(err)) {
1512
					ERROR err2 = ERR_class_bit_dim_const();
1513
					err = concat_error(err, err2);
1514
					report(crt_loc, err);
1515
				}
1516
				rep = get_bitfield_rep(s2, rep);
1517
				t = check_bitfield_type(cv, s2, rep, n2, anon);
2 7u83 1518
			}
1519
		}
7 7u83 1520
		break;
1521
	case type_compound_tag: {
1522
		/* Class types */
1523
		CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
1524
		TYPE s = DEREF_type(ctype_form(ct));
1525
		if (!IS_NULL_type(s)) {
1526
			if (IS_type_token(s)) {
1527
				/* Tokenised and template classes */
1528
				id = DEREF_id(type_token_tok(s));
1529
				p = DEREF_list(type_token_args(s));
1530
				if (IS_id_token(id)) {
1531
					goto expand_label;
1532
				}
1533
				if (rec) {
1534
					p = expand_args(p, rec, 0);
1535
					if (!IS_NULL_list(p)) {
1536
						/* Template class instance */
1537
						id = instance_type(id, p, 0, 1);
1538
						t = DEREF_type(id_class_name_defn(id));
1539
						while (IS_type_templ(t)) {
1540
							t = DEREF_type(type_templ_defn(t));
1541
						}
1542
						if (cv) {
1543
							t = qualify_type(t, cv, 0);
1544
						}
1545
					}
1546
				}
1547
			} else if (IS_type_instance(s)) {
1548
				s = rescan_class(ct);
1549
				if (!IS_NULL_type(s)) {
1550
					t = s;
1551
					if (cv) {
1552
						t = qualify_type(t, cv, 0);
1553
					}
1554
				}
1555
			} else {
1556
				/* Recursive template classes */
1557
				t = expand_type(s, rec);
1558
				if (cv) {
1559
					t = qualify_type(t, cv, 0);
1560
				}
2 7u83 1561
			}
7 7u83 1562
		} else {
1563
			CLASS_INFO ci = DEREF_cinfo(ctype_info(ct));
1564
			if (ci & cinfo_rescan) {
1565
				/* Force rescan */
1566
				s = rescan_class(ct);
1567
				if (!IS_NULL_type(s)) {
1568
					t = s;
1569
					if (cv) {
1570
						t = qualify_type(t, cv, 0);
1571
					}
1572
				}
2 7u83 1573
			}
7 7u83 1574
		}
1575
		break;
1576
	}
1577
	case type_enumerate_tag: {
1578
		/* Enumeration types */
1579
		ENUM_TYPE et = DEREF_etype(type_enumerate_defn(t));
1580
		CLASS_INFO ei = DEREF_cinfo(etype_info(et));
1581
		if (ei & cinfo_rescan) {
1582
			/* Force rescan */
1583
			TYPE s = rescan_enum(et);
1584
			if (!IS_NULL_type(s)) {
1585
				t = s;
1586
				if (cv) {
1587
					t = qualify_type(t, cv, 0);
1588
				}
2 7u83 1589
			}
1590
		}
7 7u83 1591
		break;
2 7u83 1592
	}
7 7u83 1593
	case type_token_tag:
1594
		/* Tokenised types */
1595
		id = DEREF_id(type_token_tok(t));
1596
		p = DEREF_list(type_token_args(t));
1597
expand_label: {
1598
		      TOKEN tok;
1599
		      unsigned tag;
1600
		      DECL_SPEC ds;
1601
		      IDENTIFIER aid;
1602
		      int changed = 0;
1603
		      if (!IS_id_token(id)) {
1604
			      break;
1605
		      }
1606
		      aid = DEREF_id(id_alias(id));
1607
		      if (!EQ_id(id, aid)) {
1608
			      /* Replace token by its alias */
1609
			      t = apply_type_token(aid, p, NULL_id);
1610
			      changed = 1;
1611
			      id = aid;
1612
		      }
1613
		      ds = DEREF_dspec(id_storage(id));
1614
		      tok = DEREF_tok(id_token_sort(id));
1615
		      tag = TAG_tok(tok);
1616
		      if (tag == tok_proc_tag) {
1617
			      if (rec) {
1618
				      /* Expand token arguments */
1619
				      p = expand_args(p, rec, 0);
1620
				      if (!IS_NULL_list(p)) {
1621
					      t = apply_type_token(id, p,
1622
								   NULL_id);
1623
					      changed = 1;
1624
				      }
1625
			      }
1626
			      tok = DEREF_tok(tok_proc_res(tok));
1627
			      tag = TAG_tok(tok);
1628
		      }
1629
		      /* if ( rec == 2 && !( ds & dspec_auto ) ) break ; */
1630
		      if (ds & dspec_temp) {
1631
			      /* Check for recursive token expansions */
1632
			      report(crt_loc, ERR_token_recursive(id));
1633
			      return (type_error);
1634
		      }
1635
		      COPY_dspec(id_storage(id), (ds | dspec_temp));
1636
		      if (tag == tok_type_tag) {
1637
			      /* Tokenised type */
1638
			      TYPE s = DEREF_type(tok_type_value(tok));
1639
			      if (!IS_NULL_type(s)) {
1640
				      /* Expand token definition */
1641
				      t = expand_type(s, rec);
1642
				      if (ds & dspec_auto) {
1643
					      COPY_type(tok_type_value(tok), t);
1644
				      }
1645
				      changed = 1;
1646
			      } else {
1647
				      BASE_TYPE bt;
1648
				      bt = DEREF_btype(tok_type_kind(tok));
1649
				      if (bt & btype_typename) {
1650
					      /* Allow for typename */
1651
					      s = find_typename(id, p, bt, 0);
1652
					      if (!IS_NULL_type(s)) {
1653
						      t = expand_type(s, rec);
1654
						      changed = 1;
1655
					      }
1656
				      }
1657
			      }
1658
		      } else if (tag == tok_class_tag) {
1659
			      /* Template template parameter */
1660
			      aid = DEREF_id(tok_class_value(tok));
1661
			      if (!IS_NULL_id(aid) && rec) {
1662
				      p = expand_args(p, rec, 1);
1663
				      aid = apply_template(aid, p, 0, 0);
1664
				      if (IS_id_class_name_etc(aid)) {
1665
					      t = DEREF_type(id_class_name_etc_defn(aid));
1666
					      changed = 1;
1667
				      }
1668
			      }
1669
		      }
1670
		      if (changed) {
1671
			      /* Qualify modified type */
1672
			      if (prom == 1) {
1673
				      t = promote_type(t);
1674
			      } else if (prom == 2) {
1675
				      t = arg_promote_type(t, KILL_err);
1676
			      }
1677
			      if (cv) {
1678
				      CV_SPEC qual = DEREF_cv(type_qual(t));
1679
				      t = qualify_type(t,(qual | cv), 0);
1680
			      }
1681
		      }
1682
		      COPY_dspec(id_storage(id), ds);
1683
	      }
1684
	      break;
1685
	case type_templ_tag:
1686
		/* Template types */
1687
		t = expand_templ_type(t, rec);
1688
		break;
2 7u83 1689
	}
7 7u83 1690
	return (t);
2 7u83 1691
}
1692
 
1693
 
1694
/*
1695
    APPLY AN EXPRESSION TOKEN
1696
 
1697
    This routine applies the expression, statement or integer constant
1698
    token id to the arguments args.  If rec is true then the result
1699
    type is expanded.
1700
*/
1701
 
7 7u83 1702
EXP
1703
apply_exp_token(IDENTIFIER id, LIST(TOKEN) args, int rec)
2 7u83 1704
{
7 7u83 1705
	EXP e;
1706
	int is_proc = 0;
1707
	TOKEN tok = DEREF_tok(id_token_sort(id));
1708
	unsigned tag = TAG_tok(tok);
1709
	if (tag == tok_func_tag) {
1710
		tok = func_proc_token(tok);
1711
		tag = TAG_tok(tok);
1712
	}
1713
	if (tag == tok_proc_tag) {
1714
		is_proc = 1;
1715
		tok = DEREF_tok(tok_proc_res(tok));
1716
		tag = TAG_tok(tok);
1717
	}
1718
	switch (tag) {
1719
	case tok_exp_tag: {
1720
		/* Expression tokens */
1721
		int pt = in_proc_token;
1722
		TYPE t = DEREF_type(tok_exp_type(tok));
1723
		int c = DEREF_int(tok_exp_constant(tok));
1724
		if (rec > 0) {
1725
			t = expand_type(t, rec);
1726
		} else if (pt) {
1727
			in_proc_token = 0;
1728
			t = expand_type(t, 2);
1729
			in_proc_token = pt;
2 7u83 1730
		}
7 7u83 1731
		t = convert_qual_type(t);
1732
		MAKE_exp_token(t, id, args, e);
1733
		if (c) {
1734
			/* Check for integer constant tokens */
1735
			unsigned tt = TAG_type(t);
1736
			if (tt == type_integer_tag ||
1737
			    tt == type_enumerate_tag) {
1738
				NAT n;
1739
				MAKE_nat_calc(e, n);
1740
				MAKE_exp_int_lit(t, n, exp_token_tag, e);
1741
			}
1742
		} else {
1743
			/* Allow for exceptions */
1744
			if (is_proc) {
1745
				IGNORE check_throw(NULL_type, 0);
1746
			}
2 7u83 1747
		}
7 7u83 1748
		break;
2 7u83 1749
	}
7 7u83 1750
	case tok_stmt_tag:
1751
		/* Statement tokens */
1752
		MAKE_exp_token(type_void, id, args, e);
1753
		while (!IS_NULL_list(args)) {
1754
			TOKEN arg = DEREF_tok(HEAD_list(args));
1755
			if (IS_tok_stmt(arg)) {
1756
				/* Set parent statement for arguments */
1757
				EXP a = DEREF_exp(tok_stmt_value(arg));
1758
				set_parent_stmt(a, e);
1759
			}
1760
			args = TAIL_list(args);
2 7u83 1761
		}
7 7u83 1762
		IGNORE check_throw(NULL_type, 0);
1763
		break;
1764
	case tok_nat_tag:
1765
	case tok_snat_tag: {
1766
		/* Integer constant tokens */
1767
		NAT n;
1768
		MAKE_nat_token(id, args, n);
1769
		MAKE_exp_int_lit(type_sint, n, exp_token_tag, e);
1770
		break;
2 7u83 1771
	}
7 7u83 1772
	default:
1773
		/* Other tokens */
1774
		e = NULL_exp;
1775
		break;
2 7u83 1776
	}
7 7u83 1777
	return (e);
2 7u83 1778
}
1779
 
1780
 
1781
/*
1782
    APPLY AN INTEGER CONSTANT TOKEN
1783
 
1784
    This routine applies the integer constant token id to the arguments args.
1785
*/
1786
 
7 7u83 1787
NAT
1788
apply_nat_token(IDENTIFIER id, LIST(TOKEN) args)
2 7u83 1789
{
7 7u83 1790
	NAT n;
1791
	TOKEN tok = DEREF_tok(id_token_sort(id));
1792
	unsigned tag = TAG_tok(tok);
1793
	if (tag == tok_proc_tag) {
1794
		tok = DEREF_tok(tok_proc_res(tok));
1795
		tag = TAG_tok(tok);
1796
	}
1797
	if (tag == tok_nat_tag || tag == tok_snat_tag) {
1798
		MAKE_nat_token(id, args, n);
1799
	} else {
1800
		n = NULL_nat;
1801
	}
1802
	return (n);
2 7u83 1803
}
1804
 
1805
 
1806
/*
1807
    APPLY A BUILT-IN TYPE TOKEN
1808
 
1809
    Certain language extensions are implemented as built-in tokens (see
1810
    define_keyword).  This routine applies such a token, given by the
1811
    keyword lex, to the arguments args.
1812
*/
1813
 
7 7u83 1814
static TYPE
1815
key_type_token(int lex, LIST(TOKEN) args)
2 7u83 1816
{
7 7u83 1817
	TYPE t = NULL_type;
1818
	switch (lex) {
1819
	case lex_representation: {
1820
		TOKEN arg = DEREF_tok(HEAD_list(args));
1821
		t = DEREF_type(tok_type_value(arg));
1822
		if (!IS_NULL_type(t) && IS_type_integer(t)) {
1823
			TYPE s;
1824
			args = TAIL_list(args);
1825
			arg = DEREF_tok(HEAD_list(args));
1826
			s = DEREF_type(tok_type_value(arg));
1827
			if (!IS_NULL_type(s) && IS_type_integer(s)) {
1828
				INT_TYPE it = DEREF_itype(type_integer_rep(t));
1829
				INT_TYPE is = DEREF_itype(type_integer_rep(s));
1830
				t = make_itype(it, is);
1831
			}
2 7u83 1832
		}
7 7u83 1833
		break;
2 7u83 1834
	}
7 7u83 1835
	case lex_typeof: {
1836
		TOKEN arg = DEREF_tok(HEAD_list(args));
1837
		EXP e = DEREF_exp(tok_exp_value(arg));
1838
		if (!IS_NULL_exp(e)) {
1839
			t = DEREF_type(exp_type(e));
1840
			if (IS_type_bitfield(t)) {
1841
				t = promote_type(t);
1842
			}
2 7u83 1843
		}
7 7u83 1844
		break;
2 7u83 1845
	}
7 7u83 1846
	}
1847
	return (t);
2 7u83 1848
}
1849
 
1850
 
1851
/*
1852
    APPLY A TYPE TOKEN
1853
 
1854
    This routine applies the type token id to the arguments args.  tid
1855
    gives the name, if any, to be given to any class created.
1856
*/
1857
 
7 7u83 1858
TYPE
1859
apply_type_token(IDENTIFIER id, LIST(TOKEN) args, IDENTIFIER tid)
2 7u83 1860
{
7 7u83 1861
	TYPE t;
1862
	int pt = in_proc_token;
1863
	TOKEN tok = DEREF_tok(id_token_sort(id));
1864
	unsigned tag = TAG_tok(tok);
1865
	if (tag == tok_proc_tag) {
1866
		int lex = DEREF_int(tok_proc_key(tok));
1867
		if (lex != lex_identifier) {
1868
			t = key_type_token(lex, args);
1869
			if (!IS_NULL_type(t)) {
1870
				return (t);
1871
			}
1872
		}
1873
		tok = DEREF_tok(tok_proc_res(tok));
1874
		tag = TAG_tok(tok);
2 7u83 1875
	}
7 7u83 1876
	if (tag == tok_type_tag) {
1877
		BASE_TYPE bt = DEREF_btype(tok_type_kind(tok));
1878
		if (bt & btype_scalar) {
1879
			/* Scalar types */
1880
			t = apply_itype_token(id, args);
2 7u83 1881
 
7 7u83 1882
		} else if (bt & btype_named) {
1883
			/* Structure and union types */
1884
			TYPE s;
1885
			CLASS_TYPE ct;
1886
			CLASS_INFO ci;
1887
			int tq = crt_templ_qualifier;
1888
			QUALIFIER cq = crt_id_qualifier;
1889
			int td = have_type_declaration;
1890
			if (IS_NULL_id(tid)) {
1891
				/* Make up class name if necessary */
1892
				HASHID tnm = lookup_anon();
1893
				tid = DEREF_id(hashid_id(tnm));
1894
			}
2 7u83 1895
 
7 7u83 1896
			/* Define the class */
1897
			crt_id_qualifier = qual_none;
1898
			crt_templ_qualifier = 0;
1899
			tid = begin_class_defn(tid, bt, cinfo_token, NULL_type);
1900
			if (IS_NULL_list(args)) {
1901
				COPY_id(id_token_alt(id), tid);
1902
			}
1903
			t = DEREF_type(id_class_name_etc_defn(tid));
1904
			while (IS_type_templ(t)) {
1905
				t = DEREF_type(type_templ_defn(t));
1906
			}
1907
			ct = DEREF_ctype(type_compound_defn(t));
1908
			ci = DEREF_cinfo(ctype_info(ct));
1909
			ci &= ~cinfo_empty;
1910
			COPY_cinfo(ctype_info(ct), ci);
1911
			MAKE_type_token(cv_none, id, args, s);
1912
			COPY_type(ctype_form(ct), s);
1913
			in_class_defn++;
1914
			really_in_class_defn++;
1915
			IGNORE end_class_defn(tid);
1916
			really_in_class_defn--;
1917
			in_class_defn--;
1918
			have_type_declaration = td;
1919
			crt_templ_qualifier = tq;
1920
			crt_id_qualifier = cq;
2 7u83 1921
 
7 7u83 1922
		} else {
1923
			/* Generic types */
1924
			MAKE_type_token(cv_none, id, args, t);
1925
		}
2 7u83 1926
	} else {
7 7u83 1927
		/* Shouldn't occur */
1928
		t = type_error;
2 7u83 1929
	}
7 7u83 1930
	if (pt) {
1931
		/* Expand token arguments */
1932
		in_proc_token = 0;
1933
		t = expand_type(t, 2);
1934
		in_proc_token = pt;
1935
	}
1936
	return (t);
2 7u83 1937
}
1938
 
1939
 
1940
/*
1941
    APPLY A MEMBER TOKEN
1942
 
1943
    This routine applies the member token id to the arguments args.
1944
*/
1945
 
7 7u83 1946
OFFSET
1947
apply_mem_token(IDENTIFIER id, LIST(TOKEN) args)
2 7u83 1948
{
7 7u83 1949
	OFFSET off;
1950
	MAKE_off_token(id, args, off);
1951
	return (off);
2 7u83 1952
}
1953
 
1954
 
1955
/*
1956
    APPLY A TOKEN
1957
 
1958
    This routine applies the token id to the arguments args.
1959
*/
1960
 
7 7u83 1961
TOKEN
1962
apply_token(IDENTIFIER id, LIST(TOKEN) args)
2 7u83 1963
{
7 7u83 1964
	TOKEN tok = NULL_tok;
1965
	TOKEN sort = DEREF_tok(id_token_sort(id));
1966
	unsigned tag = TAG_tok(sort);
1967
	if (tag == tok_proc_tag) {
1968
		sort = DEREF_tok(tok_proc_res(sort));
1969
		tag = TAG_tok(sort);
2 7u83 1970
	}
7 7u83 1971
	switch (tag) {
1972
	case tok_exp_tag: {
1973
		EXP e = apply_exp_token(id, args, 0);
1974
		TYPE t = DEREF_type(exp_type(e));
1975
		int c = DEREF_int(tok_exp_constant(sort));
1976
		MAKE_tok_exp(t, c, e, tok);
1977
		break;
2 7u83 1978
	}
7 7u83 1979
	case tok_nat_tag:
1980
	case tok_snat_tag: {
1981
		NAT n = apply_nat_token(id, args);
1982
		MAKE_tok_nat_etc(tag, n, tok);
1983
		break;
2 7u83 1984
	}
7 7u83 1985
	case tok_stmt_tag: {
1986
		EXP e = apply_exp_token(id, args, 0);
1987
		MAKE_tok_stmt(e, tok);
1988
		break;
2 7u83 1989
	}
7 7u83 1990
	case tok_type_tag: {
1991
		TYPE t;
1992
		BASE_TYPE bt = DEREF_btype(tok_type_kind(sort));
1993
		t = apply_type_token(id, args, NULL_id);
1994
		MAKE_tok_type(bt, t, tok);
1995
		break;
2 7u83 1996
	}
7 7u83 1997
	case tok_member_tag: {
1998
		TYPE s = DEREF_type(tok_member_of(sort));
1999
		TYPE t = DEREF_type(tok_member_type(sort));
2000
		OFFSET off = apply_mem_token(id, args);
2001
		MAKE_tok_member(s, t, off, tok);
2002
		break;
2 7u83 2003
	}
7 7u83 2004
	case tok_class_tag: {
2005
		TYPE t = DEREF_type(tok_class_type(sort));
2006
		MAKE_tok_class(t, id, tok);
2007
		break;
2008
	}
2009
	}
2010
	return (tok);
2 7u83 2011
}
2012
 
2013
 
2014
/*
2015
    COMPARE TWO TOKENS
2016
 
2017
    This routine compares the token sorts a and b.
2018
*/
2019
 
7 7u83 2020
static int
2021
eq_tok(TOKEN a, TOKEN b)
2 7u83 2022
{
7 7u83 2023
	/* Check for obvious equality */
2024
	unsigned na, nb;
2025
	if (EQ_tok(a, b)) {
2026
		return (1);
2 7u83 2027
	}
7 7u83 2028
	if (IS_NULL_tok(a)) {
2029
		return (0);
2 7u83 2030
	}
7 7u83 2031
	if (IS_NULL_tok(b)) {
2032
		return (0);
2033
	}
2 7u83 2034
 
7 7u83 2035
	/* Compare tags */
2036
	na = TAG_tok(a);
2037
	nb = TAG_tok(b);
2038
	if (na != nb) {
2039
		return (0);
2 7u83 2040
	}
2041
 
7 7u83 2042
	/* Compare token components */
2043
	ASSERT(ORDER_tok == 10);
2044
	switch (na) {
2045
	case tok_exp_tag: {
2046
		/* Expression tokens */
2047
		TYPE ta = DEREF_type(tok_exp_type(a));
2048
		TYPE tb = DEREF_type(tok_exp_type(b));
2049
		CV_SPEC qa = DEREF_cv(type_qual(ta));
2050
		CV_SPEC qb = DEREF_cv(type_qual(tb));
2051
		int ca = DEREF_int(tok_exp_constant(a));
2052
		int cb = DEREF_int(tok_exp_constant(b));
2053
		return (ca == cb && qa == qb && eq_type(ta, tb));
2 7u83 2054
	}
7 7u83 2055
	case tok_nat_tag:
2056
	case tok_snat_tag:
2057
	case tok_stmt_tag:
2058
		/* Trivial cases */
2059
		break;
2060
	case tok_func_tag: {
2061
		/* Function tokens */
2062
		TYPE ta = DEREF_type(tok_func_type(a));
2063
		TYPE tb = DEREF_type(tok_func_type(b));
2064
		return (eq_type(ta, tb));
2065
	}
2066
	case tok_member_tag: {
2067
		/* Member tokens */
2068
		TYPE sa = DEREF_type(tok_member_of(a));
2069
		TYPE sb = DEREF_type(tok_member_of(b));
2070
		TYPE ta = DEREF_type(tok_member_type(a));
2071
		TYPE tb = DEREF_type(tok_member_type(b));
2072
		return (eq_type(sa, sb) && eq_type(ta, tb));
2073
	}
2074
	case tok_proc_tag: {
2075
		/* Procedure tokens */
2076
		LIST(IDENTIFIER) pa, pb;
2077
		TOKEN ra = DEREF_tok(tok_proc_res(a));
2078
		TOKEN rb = DEREF_tok(tok_proc_res(b));
2079
		if (!eq_tok(ra, rb)) {
2080
			return (0);
2081
		}
2 7u83 2082
 
7 7u83 2083
		/* Compare program parameters */
2084
		pa = DEREF_list(tok_proc_pids(a));
2085
		pb = DEREF_list(tok_proc_pids(b));
2086
		if (LENGTH_list(pa)!= LENGTH_list(pb)) {
2087
			return (0);
2088
		}
2089
		while (!IS_NULL_list(pa) && !IS_NULL_list(pb)) {
2090
			IDENTIFIER u = DEREF_id(HEAD_list(pa));
2091
			IDENTIFIER v = DEREF_id(HEAD_list(pb));
2092
			if (IS_NULL_id(u) || !IS_id_token(u)) {
2093
				return (0);
2094
			}
2095
			if (IS_NULL_id(v) || !IS_id_token(v)) {
2096
				return (0);
2097
			}
2098
			ra = DEREF_tok(id_token_sort(u));
2099
			rb = DEREF_tok(id_token_sort(v));
2100
			if (!eq_tok(ra, rb)) {
2101
				return (0);
2102
			}
2103
			pa = TAIL_list(pa);
2104
			pb = TAIL_list(pb);
2105
		}
2 7u83 2106
 
7 7u83 2107
		/* Compare bound parameters */
2108
		pa = DEREF_list(tok_proc_bids(a));
2109
		pb = DEREF_list(tok_proc_bids(b));
2110
		if (LENGTH_list(pa) != LENGTH_list(pb)) {
2111
			return (0);
2112
		}
2113
		while (!IS_NULL_list(pa) && !IS_NULL_list(pb)) {
2114
			IDENTIFIER u = DEREF_id(HEAD_list(pa));
2115
			IDENTIFIER v = DEREF_id(HEAD_list(pb));
2116
			if (IS_NULL_id(u) || !IS_id_token(u)) {
2117
				return (0);
2118
			}
2119
			if (IS_NULL_id(v) || !IS_id_token(v)) {
2120
				return (0);
2121
			}
2122
			ra = DEREF_tok(id_token_sort(u));
2123
			rb = DEREF_tok(id_token_sort(v));
2124
			if (!eq_tok(ra, rb)) {
2125
				return (0);
2126
			}
2127
			pa = TAIL_list(pa);
2128
			pb = TAIL_list(pb);
2129
		}
2130
		break;
2 7u83 2131
	}
2132
 
7 7u83 2133
	case tok_type_tag: {
2134
		/* Type tokens */
2135
		BASE_TYPE ta = DEREF_btype(tok_type_kind(a));
2136
		BASE_TYPE tb = DEREF_btype(tok_type_kind(b));
2137
		if (ta != tb) {
2138
			return (0);
2139
		}
2140
		break;
2 7u83 2141
	}
2142
 
7 7u83 2143
	case tok_class_tag: {
2144
		/* Template class tokens */
2145
		TYPE ta = DEREF_type(tok_class_type(a));
2146
		TYPE tb = DEREF_type(tok_class_type(b));
2147
		if (eq_type(ta, tb) == 1) {
2148
			return (1);
2149
		}
2150
		return (0);
2 7u83 2151
	}
2152
 
7 7u83 2153
	case tok_templ_tag:
2154
		/* Templates */
2155
		/* NOT YET IMPLEMENTED */
2156
		return (0);
2 7u83 2157
	}
7 7u83 2158
	return (1);
2 7u83 2159
}
2160
 
2161
 
2162
/*
2163
    DECLARE A TOKEN IDENTIFIER
2164
 
2165
    This routine declares a token identifier id with sort tok and external
2166
    name ext in the namespace ns.
2167
*/
2168
 
7 7u83 2169
static IDENTIFIER
2170
declare_token(IDENTIFIER id, TOKEN tok, NAMESPACE ns, IDENTIFIER ext)
2 7u83 2171
{
7 7u83 2172
	HASHID nm = DEREF_hashid(id_name(id));
2173
	MEMBER mem = search_member(ns, nm, 1);
2 7u83 2174
 
7 7u83 2175
	/* Check identifier name */
2176
	ERROR err = check_id_name(id, CONTEXT_OBJECT);
2177
	if (!IS_NULL_err(err))report(crt_loc, err);
2 7u83 2178
 
7 7u83 2179
	/* Check for previous definition */
2180
	id = DEREF_id(member_id(mem));
2181
	if (!IS_NULL_id(id)) {
2182
		id = redecl_inherit(id, qual_none, 0, 0);
2183
		if (!IS_NULL_id(id)) {
2184
			if (IS_id_token(id)) {
2185
				/* Allow for redeclarations */
2186
				IDENTIFIER tid = DEREF_id(id_token_alt(id));
2187
				if (EQ_id(tid, ext)) {
2188
					return (id);
2189
				}
2 7u83 2190
			}
7 7u83 2191
			if (IS_id_function(id) && IS_tok_proc(tok)) {
2192
				IDENTIFIER pid = id;
2193
				while (!IS_NULL_id(pid)) {
2194
					TYPE t =
2195
					    DEREF_type(id_function_type(pid));
2196
					if (IS_type_func(t)) {
2197
						TOKEN ptok;
2198
						MAKE_tok_func(t, ptok);
2199
						ptok = func_proc_token(ptok);
2200
						if (eq_tok(ptok, tok)) {
2201
							/* Procedure token
2202
							 * matches function */
2203
							return (pid);
2204
						}
2205
					}
2206
					pid = DEREF_id(id_function_over(pid));
2207
				}
2208
			}
2 7u83 2209
		}
2210
	}
2211
 
7 7u83 2212
	/* Declare the token */
2213
	MAKE_id_token(nm, dspec_token, ns, preproc_loc, tok, ext, id);
2214
	set_member(mem, id);
2215
	return (id);
2 7u83 2216
}
2217
 
2218
 
2219
/*
2220
    DECLARE AN EXTERNAL TOKEN
2221
 
2222
    This routine declares a token of sort tok with internal name id,
2223
    which belongs to the tag namespace if tag is true, and external name
2224
    ext.  It returns the external token identifier.
2225
*/
2226
 
7 7u83 2227
IDENTIFIER
2228
make_token_decl(TOKEN tok, int tag, IDENTIFIER id, IDENTIFIER ext)
2 7u83 2229
{
7 7u83 2230
	int tq;
2231
	HASHID nm;
2232
	MEMBER mem;
2233
	unsigned tt;
2234
	QUALIFIER cq;
2235
	NAMESPACE ns;
2236
	NAMESPACE gns;
2237
	int macro = 0;
2238
	int pushed = 0;
2239
	int done_dump = 0;
2240
	IDENTIFIER tid = NULL_id;
2241
	DECL_SPEC ds = dspec_token;
2242
	DECL_SPEC mark = dspec_token;
2 7u83 2243
 
7 7u83 2244
	/* Ignore illegal tokens */
2245
	if (IS_NULL_tok(tok)) {
2246
		return (NULL_id);
2247
	}
2 7u83 2248
 
7 7u83 2249
	/* Find token name */
2250
	if (!IS_NULL_id(ext)) {
2251
		/* Externally named token */
2252
		ns = token_namespace;
2253
		/* gns = global_namespace ; */
2254
		gns = nonblock_namespace;
2255
		nm = DEREF_hashid(id_name(ext));
2256
		mem = search_member(ns, nm, 1);
2257
		ext = DEREF_id(member_id(mem));
2258
		if (!IS_NULL_id(ext)) {
2259
			TOKEN tok2 = DEREF_tok(id_token_sort(ext));
2260
			force_tokdef++;
2261
			if (!eq_tok(tok, tok2)) {
2262
				ERROR err = ERR_token_redecl(ext, id_loc(ext));
2263
				report(preproc_loc, err);
2264
				ext = NULL_id;
2265
			}
2266
			force_tokdef--;
2267
		}
2268
		if (IS_hashid_anon(nm)) {
2269
			ds |= dspec_static;
2270
		} else {
2271
			ds |= dspec_extern;
2272
		}
2 7u83 2273
	} else {
7 7u83 2274
		/* Token parameter */
2275
		ns = crt_namespace;
2276
		gns = ns;
2277
		nm = DEREF_hashid(id_name(id));
2278
		mem = NULL_member;
2279
		ds |= (dspec_auto | dspec_pure);
2 7u83 2280
	}
2281
 
7 7u83 2282
	/* Create the token */
2283
	if (IS_NULL_id(ext)) {
2284
		IDENTIFIER uid = underlying_id(id);
2285
		MAKE_id_token(nm, ds, ns, preproc_loc, tok, uid, ext);
2286
		if (!IS_NULL_member(mem)) {
2287
			COPY_id(member_id(mem), ext);
2288
		}
2 7u83 2289
	}
2290
 
7 7u83 2291
	/* Declare the corresponding identifier */
2292
	cq = crt_id_qualifier;
2293
	tq = crt_templ_qualifier;
2294
	crt_id_qualifier = qual_none;
2295
	crt_templ_qualifier = 0;
2296
	if (!EQ_nspace(gns, crt_namespace)) {
2297
		push_namespace(gns);
2298
		pushed = 1;
2299
	}
2300
	tt = TAG_tok(tok);
2301
	if (tt == tok_type_tag) {
2302
		BASE_TYPE bt = DEREF_btype(tok_type_kind(tok));
2303
		if (bt & btype_named) {
2304
			/* Allow structure and union tags */
2305
			if (tag) {
2306
				tid = id;
2307
			}
2308
		} else {
2309
			tag = 0;
2310
		}
2 7u83 2311
	} else {
7 7u83 2312
		/* Other tags are not allowed */
2313
		tag = 0;
2 7u83 2314
	}
7 7u83 2315
	switch (tt) {
2316
	case tok_type_tag: {
2317
		/* Simple type tokens */
2318
		TYPE t = apply_type_token(ext, NULL_list(TOKEN), tid);
2319
		if (tag) {
2320
			CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
2321
			id = DEREF_id(ctype_name(ct));
2322
			done_dump = 1;
2323
		} else {
2324
			id = make_object_decl(dspec_typedef, t, id, 0);
2325
			if (!(ds & dspec_auto)) {
2326
				macro = 2;
2327
			}
2328
		}
2329
		break;
2 7u83 2330
	}
7 7u83 2331
	case tok_func_tag: {
2332
		/* Function tokens (C linkage by default) */
2333
		TYPE t = DEREF_type(tok_func_type(tok));
2334
		int ell = DEREF_int(type_func_ellipsis(t));
2335
		DECL_SPEC ln = crt_linkage;
2336
		if (ln == dspec_none) {
2337
			crt_linkage = dspec_c;
2 7u83 2338
		}
7 7u83 2339
		id = make_func_decl(dspec_extern, t, id, 0);
2340
		IGNORE init_object(id, NULL_exp);
2341
		if (IS_id_function_etc(id) && ell == FUNC_NONE) {
2342
			TYPE form;
2343
			MAKE_type_token(cv_none, ext, NULL_list(TOKEN), form);
2344
			COPY_type(id_function_etc_form(id), form);
2345
			if (!(ds & dspec_auto)) {
2346
				macro = 1;
2347
			}
2348
			if (is_redeclared) {
2349
				/* Mark functions which have already been
2350
				 * declared */
2351
				ds |= dspec_explicit;
2352
				COPY_dspec(id_storage(ext), ds);
2353
			}
2354
		} else {
2355
			/* Ellipsis functions are not really tokenised */
2356
			mark = dspec_none;
2357
		}
2358
		crt_linkage = ln;
2359
		break;
2 7u83 2360
	}
7 7u83 2361
	case tok_member_tag: {
2362
		/* Member tokens */
2363
		int pt = in_proc_token;
2364
		CLASS_TYPE cs = crt_class;
2365
		TYPE t = DEREF_type(tok_member_of(tok));
2366
		CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
2367
		NAMESPACE cns = DEREF_nspace(ctype_member(ct));
2368
		crt_class = ct;
2369
		in_class_defn++;
2370
		really_in_class_defn++;
2371
		push_namespace(cns);
2372
		t = DEREF_type(tok_member_type(tok));
2373
		if (pt) {
2374
			in_proc_token = 0;
2375
			t = expand_type(t, 2);
2376
			in_proc_token = pt;
2377
		}
2378
		id = make_member_decl(dspec_token, t, id, 0);
2379
		if (IS_id_member(id)) {
2380
			OFFSET off = DEREF_off(id_member_off(id));
2381
			if (!IS_NULL_off(off)) {
2382
				t = DEREF_type(id_member_type(id));
2383
				IGNORE define_mem_token(ext, off, t, 1);
2384
				if (!IS_NULL_member(mem)) {
2385
					if (IS_off_member(off)) {
2386
						/* Record old member name */
2387
						IDENTIFIER pid;
2388
						pid = DEREF_id(off_member_id(off));
2389
						COPY_id(member_alt(mem), pid);
2390
					}
2391
				}
2 7u83 2392
			}
7 7u83 2393
			off = apply_mem_token(ext, NULL_list(TOKEN));
2394
			COPY_off(id_member_off(id), off);
2395
			if (!(ds & dspec_auto)) {
2396
				macro = 2;
2397
			}
2 7u83 2398
		}
7 7u83 2399
		IGNORE pop_namespace();
2400
		really_in_class_defn--;
2401
		in_class_defn--;
2402
		crt_class = cs;
2403
		break;
2 7u83 2404
	}
7 7u83 2405
	case tok_class_tag: {
2406
		/* Template template parameters */
2407
		TYPE t;
2408
		TYPE q = DEREF_type(tok_class_type(tok));
2409
		MAKE_type_token(cv_none, ext, NULL_list(TOKEN), t);
2410
		id = make_object_decl(dspec_typedef, t, id, 0);
2411
		t = inject_pre_type(q, t, 0);
2412
		COPY_type(id_class_name_etc_defn(id), t);
2413
		COPY_type(tok_class_type(tok), t);
2414
		mark |= dspec_template;
2415
		break;
2 7u83 2416
	}
7 7u83 2417
	default:
2418
		/* Other tokens */
2419
		decl_loc = preproc_loc;
2420
		id = declare_token(id, tok, gns, ext);
2421
		if (IS_id_function(id)) {
2422
			TYPE form;
2423
			MAKE_type_token(cv_none, ext, NULL_list(TOKEN), form);
2424
			COPY_type(id_function_form(id), form);
2425
		}
2426
		if (!(ds & dspec_auto)) {
2427
			macro = 1;
2428
		}
2429
		break;
2 7u83 2430
	}
7 7u83 2431
	if (mark) {
2432
		/* Mark object as a token */
2433
		ds = DEREF_dspec(id_storage(id));
2434
		ds |= mark;
2435
		COPY_dspec(id_storage(id), ds);
2 7u83 2436
	}
7 7u83 2437
	COPY_id(id_token_alt(ext), id);
2438
	if (!IS_NULL_member(mem)) {
2439
		IDENTIFIER pid = DEREF_id(member_alt(mem));
2440
		if (IS_NULL_id(pid)) {
2441
			COPY_id(member_alt(mem), id);
2442
		}
2443
		if (do_dump) {
2444
			if (!done_dump) {
2445
				dump_declare(id, &preproc_loc, 0);
2446
			}
2447
			dump_token(id, ext);
2448
		}
2449
	}
2450
	if (pushed) {
2451
		IGNORE pop_namespace();
2452
	}
2453
	crt_templ_qualifier = tq;
2454
	crt_id_qualifier = cq;
2 7u83 2455
 
7 7u83 2456
	/* Check for previous macro definition */
2457
	if (macro) {
2458
		IDENTIFIER mid;
2459
		nm = DEREF_hashid(id_name(id));
2460
		mid = DEREF_id(hashid_id(nm));
2461
		switch (TAG_id(mid)) {
2462
		case id_obj_macro_tag:
2463
		case id_func_macro_tag: {
2464
			LOCATION loc;
2465
			loc = preproc_loc;
2466
			DEREF_loc(id_loc(mid), preproc_loc);
2467
			ds = DEREF_dspec(id_storage(mid));
2468
			COPY_dspec(id_storage(mid), (ds | dspec_temp));
2469
			if (define_token_macro(id, mid)) {
2470
				ds |= dspec_used;
2471
				if (do_macro && do_usage) {
2472
					dump_use(mid, &loc, 1);
2473
				}
2474
				COPY_loc(id_loc(ext), preproc_loc);
2475
				no_declarations++;
2476
			}
2477
			COPY_dspec(id_storage(mid), ds);
2478
			preproc_loc = loc;
2479
			break;
2 7u83 2480
		}
7 7u83 2481
		}
2 7u83 2482
	}
7 7u83 2483
	return (ext);
2 7u83 2484
}
2485
 
2486
 
2487
/*
2488
    FIND A TOKEN IDENTIFIER
2489
 
2490
    This routine finds the token identifier associated with the identifier
2491
    id.
2492
*/
2493
 
7 7u83 2494
static IDENTIFIER
2495
find_token_aux(IDENTIFIER id)
2 7u83 2496
{
7 7u83 2497
	switch (TAG_id(id)) {
2498
	case id_class_name_tag:
2499
	case id_class_alias_tag: {
2500
		/* Classes */
2501
		TYPE t = DEREF_type(id_class_name_etc_defn(id));
2502
		if (IS_type_compound(t)) {
2503
			CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
2504
			t = DEREF_type(ctype_form(ct));
2505
			if (!IS_NULL_type(t) && IS_type_token(t)) {
2506
				id = DEREF_id(type_token_tok(t));
2507
				return (id);
2508
			}
2 7u83 2509
		}
7 7u83 2510
		break;
2 7u83 2511
	}
7 7u83 2512
	case id_type_alias_tag: {
2513
		/* Types */
2514
		TYPE t = DEREF_type(id_type_alias_defn(id));
2515
		if (IS_type_token(t)) {
2516
			id = DEREF_id(type_token_tok(t));
2517
			return (id);
2518
		}
2519
		break;
2 7u83 2520
	}
7 7u83 2521
	case id_function_tag:
2522
	case id_mem_func_tag:
2523
	case id_stat_mem_func_tag: {
2524
		/* Functions */
2525
		TYPE form = DEREF_type(id_function_etc_form(id));
2526
		if (!IS_NULL_type(form) && IS_type_token(form)) {
2527
			IDENTIFIER ext = DEREF_id(type_token_tok(form));
2528
			if (!IS_NULL_id(ext)) {
2529
				return (ext);
2530
			}
2531
		}
2532
		return (id);
2 7u83 2533
	}
7 7u83 2534
	case id_member_tag: {
2535
		/* Members */
2536
		OFFSET off = DEREF_off(id_member_off(id));
2537
		if (IS_off_token(off)) {
2538
			id = DEREF_id(off_token_tok(off));
2539
			return (id);
2540
		}
2541
		break;
2 7u83 2542
	}
7 7u83 2543
	case id_token_tag: {
2544
		/* Tokens */
2545
		IDENTIFIER alt = DEREF_id(id_token_alt(id));
2546
		if (IS_id_token(alt)) {
2547
			return (alt);
2548
		}
2549
		return (id);
2 7u83 2550
	}
7 7u83 2551
	}
2552
	return (id);
2 7u83 2553
}
2554
 
2555
 
2556
/*
2557
    FIND AN EXTERNAL TOKEN IDENTIFIER
2558
 
2559
    This routine finds the external token corresponding to the identifier id.
2560
    For functions this refers only to the function id itself and not to
2561
    any overloading functions.
2562
*/
2563
 
7 7u83 2564
IDENTIFIER
2565
find_token(IDENTIFIER id)
2 7u83 2566
{
7 7u83 2567
	MEMBER mem;
2568
	DECL_SPEC ds;
2569
	IDENTIFIER tid;
2570
	HASHID nm = DEREF_hashid(id_name(id));
2571
	if (IS_id_keyword_etc(id)) {
2572
		/* Rescan keywords */
2573
		id = find_id(nm);
2 7u83 2574
	}
7 7u83 2575
	ds = DEREF_dspec(id_storage(id));
2576
	if (ds & dspec_token) {
2577
		/* Deal with simple tokens */
2578
		tid = find_token_aux(id);
2579
		if (IS_id_token(tid)) {
2580
			ds = DEREF_dspec(id_storage(tid));
2581
			if (!(ds & dspec_auto)) {
2582
				return (tid);
2583
			}
2584
		}
2585
	}
2 7u83 2586
 
7 7u83 2587
	/* Complex cases - check through token namespace */
2588
	id = DEREF_id(id_alias(id));
2589
	mem = DEREF_member(nspace_global_first(token_namespace));
2590
	while (!IS_NULL_member(mem)) {
2591
		tid = DEREF_id(member_alt(mem));
2592
		if (EQ_id(tid, id)) {
2593
			tid = DEREF_id(member_id(mem));
2594
			return (tid);
2595
		}
2596
		mem = DEREF_member(member_next(mem));
2 7u83 2597
	}
7 7u83 2598
	return (id);
2 7u83 2599
}
2600
 
2601
 
2602
/*
2603
    FIND A TAG TOKEN IDENTIFIER
2604
 
2605
    This routine finds the token corresponding to the tag identifier id.
2606
*/
2607
 
7 7u83 2608
IDENTIFIER
2609
find_tag_token(IDENTIFIER id)
2 7u83 2610
{
7 7u83 2611
	id = find_elaborate_type(id, btype_any, NULL_type, dspec_used);
2612
	return (id);
2 7u83 2613
}
2614
 
2615
 
2616
/*
2617
    FIND A MEMBER TOKEN IDENTIFIER
2618
 
2619
    This routine finds the token corresponding to the member mid of cid.
2620
*/
2621
 
7 7u83 2622
IDENTIFIER
2623
find_mem_token(IDENTIFIER cid, IDENTIFIER mid)
2 7u83 2624
{
7 7u83 2625
	if (IS_id_class_name_etc(cid)) {
2626
		TYPE t = DEREF_type(id_class_name_etc_defn(cid));
2627
		IDENTIFIER fid = tok_member(mid, t, 1);
2628
		if (!IS_NULL_id(fid)) {
2629
			return (fid);
2630
		}
2631
		return (mid);
2632
	}
2633
	report(preproc_loc, ERR_dcl_type_simple_undef(cid));
2634
	return (mid);
2 7u83 2635
}
2636
 
2637
 
2638
/*
2639
    FIND AN EXTERNAL TOKEN IDENTIFIER
2640
 
2641
    This routine finds the token with external name given by id.
2642
*/
2643
 
7 7u83 2644
IDENTIFIER
2645
find_ext_token(IDENTIFIER id)
2 7u83 2646
{
7 7u83 2647
	HASHID nm = DEREF_hashid(id_name(id));
2648
	id = search_id(token_namespace, nm, 0, 0);
2649
	if (IS_NULL_id(id)) {
2650
		id = DEREF_id(hashid_id(nm));
2651
	}
2652
	return (id);
2 7u83 2653
}
2654
 
2655
 
2656
/*
2657
    FIND A FUNCTION TOKEN IDENTIFIER
2658
 
2659
    This routine is identical to find_token except that it does a primitive
2660
    form of overload resolution on function tokens based on the number of
2661
    arguments n.  A value of UINT_MAX indicates that any number of
2662
    parameters is allowed.
2663
*/
2664
 
7 7u83 2665
IDENTIFIER
2666
find_func_token(IDENTIFIER id, unsigned n)
2 7u83 2667
{
7 7u83 2668
    if (IS_id_function_etc(id)) {
2669
	int no = 0;
2670
	IDENTIFIER tid = NULL_id;
2671
	IDENTIFIER fid = id;
2672
	while (!IS_NULL_id(fid)) {
2673
	    TYPE form = DEREF_type(id_function_etc_form(fid));
2674
	    if (!IS_NULL_type(form) && IS_type_token(form)) {
2675
		IDENTIFIER ext = DEREF_id(type_token_tok(form));
2676
		if (!IS_NULL_id(ext) && IS_id_token(ext)) {
2677
		    if (n == (unsigned)UINT_MAX) {
2678
			tid = ext;
2679
			no++;
2 7u83 2680
		    } else {
7 7u83 2681
			TYPE t;
2682
			int ell;
2683
			LIST(TYPE)p;
2684
			t = DEREF_type(id_function_etc_type(fid));
2685
			while (IS_type_templ(t)) {
2686
			    t = DEREF_type(type_templ_defn(t));
2 7u83 2687
			}
7 7u83 2688
			p = DEREF_list(type_func_ptypes(t));
2689
			ell = DEREF_int(type_func_ellipsis(t));
2690
			if (LENGTH_list(p) == n) {
2691
			    if (!(ell & FUNC_ELLIPSIS)) {
2692
				tid = ext;
2693
				no++;
2 7u83 2694
			    }
2695
			}
2696
		    }
2697
		}
2698
	    }
7 7u83 2699
	    fid = DEREF_id(id_function_etc_over(fid));
2 7u83 2700
	}
7 7u83 2701
	if (no > 1) {
2702
		report(preproc_loc, ERR_token_def_ambig(id));
2703
	}
2704
	return (tid);
2 7u83 2705
    }
7 7u83 2706
    return (find_token(id));
2 7u83 2707
}
2708
 
2709
 
2710
/*
2711
    CURRENT INTERFACE METHOD
2712
 
2713
    This flag is used to record the current interface method.  It gives the
2714
    mapping of any '#pragma interface' to one of '#pragma define', '#pragma
2715
    no_def' or '#pragma ignore'.
2716
*/
2717
 
7 7u83 2718
int crt_interface = lex_no_Hdef;
2 7u83 2719
 
2720
 
2721
/*
2722
    PERFORM A TOKEN INTERFACE OPERATION
2723
 
2724
    This routine performs the token interface operation indicated by i
2725
    (which will be lex_define, lex_no_Hdef, lex_ignore) on the token tid.
2726
*/
2727
 
7 7u83 2728
static void
2729
mark_interface(IDENTIFIER tid, int i)
2 7u83 2730
{
7 7u83 2731
	DECL_SPEC ds = DEREF_dspec(id_storage(tid));
2732
	if (i == lex_define) {
2733
		/* Token must be defined */
2734
		ds |= dspec_static;
2735
		ds &= ~dspec_pure;
2736
	} else if (i == lex_no_Hdef) {
2737
		/* Token must not be defined */
2738
		ds |= dspec_pure;
2739
		if (ds & dspec_defn) {
2740
			/* Token already defined */
2741
			PTR(LOCATION)loc = id_loc(tid);
2742
			report(preproc_loc, ERR_token_no_def(tid, loc));
2743
		}
2744
	} else {
2745
		/* Ignore token definitions */
2746
		ds |= dspec_done;
2747
		ds &= ~dspec_pure;
2 7u83 2748
	}
7 7u83 2749
	COPY_dspec(id_storage(tid), ds);
2750
	return;
2 7u83 2751
}
2752
 
2753
 
2754
/*
2755
    PERFORM A TOKEN INTERFACE OPERATION
2756
 
2757
    This routine looks up the token id and performs the token operation
2758
    i on it.  In addition to the values above i can be lex_undef indicating
2759
    that the token should be undefined.
2760
*/
2761
 
7 7u83 2762
void
2763
token_interface(IDENTIFIER id, int i)
2 7u83 2764
{
7 7u83 2765
	int ok = 0;
2766
	IDENTIFIER pid = id;
2767
	while (!IS_NULL_id(pid)) {
2768
		IDENTIFIER tid = find_token(pid);
2769
		if (IS_id_token(tid)) {
2770
			/* Token found */
2771
			if (i == lex_undef) {
2772
				if (do_dump) {
2773
					dump_undefine(pid, &preproc_loc, 1);
2774
				}
2775
				remove_id(pid);
2776
			} else {
2777
				mark_interface(tid, i);
2778
			}
2779
			ok = 1;
2780
		}
2781
		if (!IS_id_function_etc(pid)) {
2782
			break;
2783
		}
2784
		pid = DEREF_id(id_function_etc_over(pid));
2 7u83 2785
	}
7 7u83 2786
	if (!ok) {
2787
		/* Token not found */
2788
		report(preproc_loc, ERR_token_undecl(id));
2789
	}
2790
	return;
2 7u83 2791
}