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-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
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 "types.h"
63
#include "alignment.h"
64
#include "check.h"
65
#include "eval.h"
66
#include "node.h"
67
#include "shape.h"
68
#include "table.h"
69
#include "tdf.h"
70
#include "utility.h"
71
 
72
 
73
/*
74
    BASIC SHAPES
75
 
76
    These shapes are fixed.
77
*/
78
 
7 7u83 79
node *sh_bottom = null;
80
node *sh_proc = null;
81
node *sh_top = null;
2 7u83 82
 
83
 
84
/*
85
    INITIALIZE BASIC SHAPES
86
 
87
    This routine initializes the basic shapes above.
88
*/
89
 
7 7u83 90
void
91
init_shapes(void)
2 7u83 92
{
7 7u83 93
    if (sh_bottom == null) {
2 7u83 94
	/* Construct sh_bottom */
7 7u83 95
	sh_bottom = new_node();
96
	sh_bottom->cons = cons_no(SORT_shape, ENC_bottom);
2 7u83 97
 
98
	/* Construct sh_proc */
7 7u83 99
	sh_proc = new_node();
100
	sh_proc->cons = cons_no(SORT_shape, ENC_proc);
2 7u83 101
 
102
	/* Construct sh_top */
7 7u83 103
	sh_top = new_node();
104
	sh_top->cons = cons_no(SORT_shape, ENC_top);
2 7u83 105
 
106
	/* Initialize alignments */
7 7u83 107
	init_alignments();
2 7u83 108
    }
7 7u83 109
    return;
2 7u83 110
}
111
 
112
 
113
/*
114
    CREATE A NAT CORRESPONDING TO THE LENGTH OF STRING s
115
 
116
    This routine returns a nat giving the length of the string s or the
117
    null node if this cannot be found.
118
*/
119
 
7 7u83 120
node *
121
string_length(node *s)
2 7u83 122
{
7 7u83 123
    if (s->cons->encoding == ENC_make_string) {
124
	node *str = s->son;
125
	long n = str->cons->encoding;
126
	if (n == -1) {
127
	    str = str->son->bro;
128
	    n = str->cons->encoding;
2 7u83 129
	}
7 7u83 130
	return(make_nat(n));
2 7u83 131
    }
7 7u83 132
    return(null);
2 7u83 133
}
134
 
135
 
136
/*
137
    COPY A NODE
138
 
139
    This routine makes a copy of the node p.
140
*/
141
 
7 7u83 142
node *
143
copy_node(node *p)
2 7u83 144
{
7 7u83 145
    node *q;
146
    if (p == null) return(null);
147
    q = new_node();
148
    if (p->cons->alias) {
149
	q->cons = p->cons->alias;
2 7u83 150
    } else {
7 7u83 151
	q->cons = p->cons;
2 7u83 152
    }
7 7u83 153
    q->son = p->son;
154
    q->shape = p->shape;
155
    return(q);
2 7u83 156
}
157
 
158
 
159
/*
160
    FORM AN INTEGER SHAPE
161
 
162
    This routine creates an integer shape from a variety p.
163
*/
164
 
7 7u83 165
node *
166
sh_integer(node *p)
2 7u83 167
{
7 7u83 168
    node *q = new_node();
169
    q->cons = cons_no(SORT_shape, ENC_integer);
170
    q->son = new_node();
171
    if (p == null) {
172
	q->son->cons = &unknown_cons;
2 7u83 173
    } else {
7 7u83 174
	q->son->cons = p->cons;
175
	q->son->son = p->son;
2 7u83 176
    }
7 7u83 177
    return(q);
2 7u83 178
}
179
 
180
 
181
/*
182
    FORM A FLOATING SHAPE
183
 
184
    This routine creates a floating shape from a floating variety p.
185
*/
186
 
7 7u83 187
node *
188
sh_floating(node *p)
2 7u83 189
{
7 7u83 190
    node *q = new_node();
191
    q->cons = cons_no(SORT_shape, ENC_floating);
192
    q->son = new_node();
193
    if (p == null) {
194
	q->son->cons = &unknown_cons;
2 7u83 195
    } else {
7 7u83 196
	q->son->cons = p->cons;
197
	q->son->son = p->son;
2 7u83 198
    }
7 7u83 199
    return(q);
2 7u83 200
}
201
 
202
 
203
/*
204
    FORM A POINTER SHAPE
205
 
206
    This routine creates a pointer shape from an alignment p or a shape p.
207
*/
208
 
7 7u83 209
node *
210
sh_pointer(node *p)
2 7u83 211
{
7 7u83 212
    node *q = new_node();
213
    q->cons = cons_no(SORT_shape, ENC_pointer);
214
    q->son = new_node();
215
    p = al_shape(p);
216
    if (p == null) {
217
	q->son->cons = &unknown_cons;
2 7u83 218
    } else {
7 7u83 219
	q->son->cons = p->cons;
220
	q->son->son = p->son;
2 7u83 221
    }
7 7u83 222
    return(q);
2 7u83 223
}
224
 
225
 
226
/*
227
    FORM AN OFFSET SHAPE
228
 
229
    This routine creates an offset shape from the alignments p and q.
230
*/
231
 
7 7u83 232
node *
233
sh_offset(node *p, node *q)
2 7u83 234
{
7 7u83 235
    node *r = new_node();
236
    r->cons = cons_no(SORT_shape, ENC_offset);
237
    r->son = new_node();
238
    p = al_shape(p);
239
    q = al_shape(q);
240
    al_includes(p, q);
241
    if (p == null) {
242
	r->son->cons = &unknown_cons;
2 7u83 243
    } else {
7 7u83 244
	r->son->cons = p->cons;
245
	r->son->son = p->son;
2 7u83 246
    }
7 7u83 247
    r->son->bro = new_node();
248
    if (q == null) {
249
	r->son->bro->cons = &unknown_cons;
2 7u83 250
    } else {
7 7u83 251
	r->son->bro->cons = q->cons;
252
	r->son->bro->son = q->son;
2 7u83 253
    }
7 7u83 254
    return(r);
2 7u83 255
}
256
 
257
 
258
/*
259
    FORM AN ARRAY SHAPE
260
 
261
    This routine creates an array shape consisting of n copies of
262
    the shape p.
263
*/
264
 
7 7u83 265
node *
266
sh_nof(node *n, node *p)
2 7u83 267
{
7 7u83 268
    node *q = new_node();
269
    q->cons = cons_no(SORT_shape, ENC_nof);
270
    q->son = new_node();
271
    if (n == null) {
272
	q->son->cons = &unknown_cons;
2 7u83 273
    } else {
7 7u83 274
	q->son->cons = n->cons;
275
	q->son->son = n->son;
2 7u83 276
    }
7 7u83 277
    q->son->bro = new_node();
278
    if (p == null) {
279
	q->son->bro->cons = &unknown_cons;
2 7u83 280
    } else {
7 7u83 281
	q->son->bro->cons = p->cons;
282
	q->son->bro->son = p->son;
2 7u83 283
    }
7 7u83 284
    return(q);
2 7u83 285
}
286
 
287
 
288
/*
289
    FORM A BITFIELD SHAPE
290
 
291
    This routine creates a bitfield shape from a bitfield variety p.
292
*/
293
 
7 7u83 294
node *
295
sh_bitfield(node *p)
2 7u83 296
{
7 7u83 297
    node *q = new_node();
298
    q->cons = cons_no(SORT_shape, ENC_bitfield);
299
    q->son = new_node();
300
    if (p == null) {
301
	q->son->cons = &unknown_cons;
2 7u83 302
    } else {
7 7u83 303
	q->son->cons = p->cons;
304
	q->son->son = p->son;
2 7u83 305
    }
7 7u83 306
    return(q);
2 7u83 307
}
308
 
309
 
310
/*
311
    FORM A COMPOUND SHAPE
312
 
313
    This routine creates a compound shape from an expression p.
314
*/
315
 
7 7u83 316
node *
317
sh_compound(node *p)
2 7u83 318
{
7 7u83 319
    node *q = new_node();
320
    q->cons = cons_no(SORT_shape, ENC_compound);
321
    q->son = new_node();
322
    if (p == null) {
323
	q->son->cons = &unknown_cons;
2 7u83 324
    } else {
7 7u83 325
	q->son->cons = p->cons;
326
	q->son->son = p->son;
2 7u83 327
    }
7 7u83 328
    return(q);
2 7u83 329
}
330
 
331
 
332
/*
333
    FIND THE NORMALIZED VERSION OF A SHAPE
334
 
335
    This routine returns the normalized version of the shape p.
336
*/
337
 
7 7u83 338
node *
339
normalize(node *p)
2 7u83 340
{
7 7u83 341
    if (p == null) return(null);
342
    if (p->cons->sortnum == SORT_shape) {
343
	switch (p->cons->encoding) {
344
	    case ENC_shape_apply_token: {
345
		node *q = expand_tok(p);
346
		if (q) return(normalize(q));
347
		break;
2 7u83 348
	    }
7 7u83 349
	    case ENC_offset: {
350
		node *al1 = al_shape(p->son);
351
		node *al2 = al_shape(p->son->bro);
352
		return(sh_offset(al1, al2));
2 7u83 353
	    }
7 7u83 354
	    case ENC_pointer: {
355
		return(sh_pointer(al_shape(p->son)));
2 7u83 356
	    }
357
	}
358
    }
7 7u83 359
    return(copy_node(p));
2 7u83 360
}
361
 
362
 
363
/*
364
    EXPAND TOKEN APPLICATIONS
365
 
366
    If p is the application of a token it is replaced by the definition
367
    of that token.  If this is null, null is returned, otherwise the
368
    expansion continues until p is not a token application.
369
*/
370
 
7 7u83 371
node *
372
expand_tok(node *p)
2 7u83 373
{
7 7u83 374
    int count = 0;
375
    sortname s = p->cons->sortnum;
376
    while (p->cons->encoding == sort_tokens[s]) {
377
	tok_info *info = get_tok_info(p->son->cons);
378
	if (info->def) {
379
	    p = info->def;
380
	    if (p->cons->sortnum == SORT_completion)p = p->son;
2 7u83 381
	} else {
7 7u83 382
	    return(null);
2 7u83 383
	}
7 7u83 384
	if (++count > 100) return(null);
2 7u83 385
    }
7 7u83 386
    return(p);
2 7u83 387
}
388
 
389
 
390
/*
391
    CHECK THAT TWO SHAPES ARE COMPATIBLE
392
 
393
    This routine checks the nodes p and q, which consists of shapes
394
    or components of shapes, are compatible.  Its action depends on
395
    the value of tg.  If tg is 0 or 1 then, if the shapes are compatible
396
    or possible compatible either p or q (whichever is more useful) is
397
    returned; otherwise an error is reported.  If tg is 2, the routine
398
    returns sh_bottom if either p or q is the shape bottom, p if p and
399
    q are definitely compatible, null is they are possible compatible,
400
    and sh_top if they are definitely not compatible.
401
*/
402
 
7 7u83 403
node *
404
check_shapes(node *p, node *q, int tg)
2 7u83 405
{
7 7u83 406
    sortname s;
407
    long np, nq;
408
    boolean ok = 1;
409
    node *p0 = (tg == 2 ? null : p);
410
    node *q0 = (tg == 2 ? null : q);
411
    node *p1 = p;
412
    boolean check_further = 0;
2 7u83 413
 
414
    /* If one is unknown, return the other */
7 7u83 415
    if (p == null) return(q0);
416
    if (q == null) return(p0);
417
    if (p->cons->sortnum == SORT_unknown) return(q0);
418
    if (q->cons->sortnum == SORT_unknown) return(p0);
2 7u83 419
 
7 7u83 420
    s = p->cons->sortnum;
421
    np = p->cons->encoding;
422
    nq = q->cons->encoding;
2 7u83 423
 
424
    /* Check for tokens */
7 7u83 425
    if (np == sort_tokens[s]) {
426
	p = expand_tok(p);
427
	if (p == null) {
428
	    if (np == nq && p1->son->cons == q->son->cons) {
429
		if (p1->son->son == null) return(p1);
2 7u83 430
	    }
7 7u83 431
	    return(q0);
2 7u83 432
	}
7 7u83 433
	np = p->cons->encoding;
2 7u83 434
    }
7 7u83 435
    if (nq == sort_tokens[s]) {
436
	q = expand_tok(q);
437
	if (q == null) return(p0);
438
	nq = q->cons->encoding;
2 7u83 439
    }
440
 
7 7u83 441
    switch (s) {
2 7u83 442
 
7 7u83 443
	case SORT_shape: {
2 7u83 444
	    /* Check for bottoms */
7 7u83 445
	    if (tg == 2) {
446
		if (np == ENC_bottom) return(sh_bottom);
447
		if (nq == ENC_bottom) return(sh_bottom);
2 7u83 448
	    }
449
	    /* Don't know about or conditionals */
7 7u83 450
	    if (np == ENC_shape_cond) return(q0);
451
	    if (nq == ENC_shape_cond) return(p0);
452
	    if (np != nq) {
453
		ok = 0;
2 7u83 454
	    } else {
7 7u83 455
		switch (np) {
2 7u83 456
 
7 7u83 457
		    case ENC_bitfield:
458
		    case ENC_floating:
459
		    case ENC_integer:
460
		    case ENC_nof: {
2 7u83 461
			/* Some shapes are inspected closer */
7 7u83 462
			check_further = 1;
463
			break;
2 7u83 464
		    }
465
 
466
		    /* case ENC_pointer */
467
		    /* case ENC_offset */
468
 
7 7u83 469
		    case ENC_bottom:
470
		    case ENC_proc:
471
		    case ENC_top: {
2 7u83 472
			/* These are definitely compatible */
7 7u83 473
			if (tg == 2) return(p1);
474
			break;
2 7u83 475
		    }
476
		}
477
	    }
7 7u83 478
	    break;
2 7u83 479
	}
480
 
7 7u83 481
	case SORT_bitfield_variety: {
2 7u83 482
	    /* Don't know about conditionals */
7 7u83 483
	    if (np == ENC_bfvar_cond) return(q0);
484
	    if (nq == ENC_bfvar_cond) return(p0);
485
	    if (np != nq) {
486
		ok = 0;
2 7u83 487
	    } else {
488
		/* Simple bitfield varieties are inspected closer */
7 7u83 489
		if (np == ENC_bfvar_bits)check_further = 1;
2 7u83 490
	    }
7 7u83 491
	    break;
2 7u83 492
	}
493
 
7 7u83 494
	case SORT_bool: {
2 7u83 495
	    /* Don't know about conditionals */
7 7u83 496
	    if (np == ENC_bool_cond) return(q0);
497
	    if (nq == ENC_bool_cond) return(p0);
498
	    if (np != nq)ok = 0;
499
	    if (tg == 2) return(ok ? p1 : sh_top);
500
	    break;
2 7u83 501
	}
502
 
7 7u83 503
	case SORT_floating_variety: {
2 7u83 504
	    /* Don't know about conditionals */
7 7u83 505
	    if (np == ENC_flvar_cond) return(q0);
506
	    if (nq == ENC_flvar_cond) return(p0);
507
	    if (np != nq) {
508
		ok = 0;
2 7u83 509
	    } else {
510
		/* Simple floating varieties are inspected closer */
7 7u83 511
		if (np == ENC_flvar_parms)check_further = 1;
2 7u83 512
	    }
7 7u83 513
	    break;
2 7u83 514
	}
515
 
7 7u83 516
	case SORT_nat: {
2 7u83 517
	    /* Don't know about conditionals */
7 7u83 518
	    if (np == ENC_nat_cond) return(q0);
519
	    if (nq == ENC_nat_cond) return(p0);
520
	    if (np != nq) {
521
		ok = 0;
2 7u83 522
	    } else {
523
		/* Simple nats are checked */
7 7u83 524
		if (np == ENC_make_nat) {
525
		    if (!eq_node(p->son, q->son))ok = 0;
526
		    if (tg == 2) return(ok ? p1 : sh_top);
2 7u83 527
		}
528
	    }
7 7u83 529
	    break;
2 7u83 530
	}
531
 
7 7u83 532
	case SORT_signed_nat: {
2 7u83 533
	    /* Don't know about conditionals */
7 7u83 534
	    if (np == ENC_signed_nat_cond) return(q0);
535
	    if (nq == ENC_signed_nat_cond) return(p0);
536
	    if (np != nq) {
537
		ok = 0;
2 7u83 538
	    } else {
539
		/* Simple signed_nats are checked */
7 7u83 540
		if (np == ENC_make_signed_nat) {
541
		    if (!eq_node(p->son, q->son))ok = 0;
542
		    if (tg == 2) return(ok ? p1 : sh_top);
2 7u83 543
		}
544
	    }
7 7u83 545
	    break;
2 7u83 546
	}
547
 
7 7u83 548
	case SORT_variety: {
2 7u83 549
	    /* Don't know about conditionals */
7 7u83 550
	    if (np == ENC_var_cond) return(q0);
551
	    if (nq == ENC_var_cond) return(p0);
552
	    if (np != nq) {
553
		ok = 0;
2 7u83 554
	    } else {
555
		/* Simple varieties are inspected closer */
7 7u83 556
		if (np == ENC_var_limits)check_further = 1;
2 7u83 557
	    }
7 7u83 558
	    break;
2 7u83 559
	}
560
 
561
	default : {
7 7u83 562
	    is_fatal = 0;
563
	    input_error("Shouldn't be checking %s's", sort_name(s));
564
	    break;
2 7u83 565
	}
566
    }
567
 
568
    /* Check arguments if necessary */
7 7u83 569
    if (check_further) {
570
	node *xp = p->son;
571
	node *xq = q->son;
572
	while (xp && xq) {
573
	    node *c = check_shapes(xp, xq, tg);
574
	    if (tg == 2) {
575
		if (c == null) return(null);
576
		if (c == sh_top) return(sh_top);
2 7u83 577
	    }
7 7u83 578
	    xp = xp->bro;
579
	    xq = xq->bro;
2 7u83 580
	}
581
    } else {
7 7u83 582
	if (tg == 2) return(null);
2 7u83 583
    }
584
 
7 7u83 585
    if (!ok) {
2 7u83 586
	/* Definitely not compatible */
7 7u83 587
	if (tg == 2) return(sh_top);
588
	is_fatal = 0;
589
	if (tg) {
590
	    input_error("Shape of tag %s does not match declaration",
591
			  checking);
2 7u83 592
	} else {
7 7u83 593
	    input_error("Shape incompatibility in %s", checking);
2 7u83 594
	}
7 7u83 595
	return(null);
2 7u83 596
    }
7 7u83 597
    return(p1);
2 7u83 598
}
599
 
600
 
601
/*
602
    FIND THE LEAST UPPER BOUND OF TWO SHAPES
603
 
604
    This routine returns the least upper bound of the shapes p and q.
605
    A return value of null means that the result is unknown.
606
*/
607
 
7 7u83 608
node *
609
lub(node *p, node *q)
2 7u83 610
{
7 7u83 611
    return(check_shapes(p, q, 2));
2 7u83 612
}
613
 
614
 
615
/*
616
    CHECK THAT A SINGLE EXPRESSION HAS THE RIGHT FORM
617
 
618
    The shape of the expression p is checked to be of the form indicated
619
    by t.  If so (or possibly so) the shape is returned, otherwise an error
620
    is flagged and null is returned.
621
*/
622
 
7 7u83 623
node *
624
check1(int t, node *p)
2 7u83 625
{
7 7u83 626
    long n;
627
    char *nm = p->cons->name;
628
    node *s = p->shape, *s0 = s;
2 7u83 629
 
7 7u83 630
    if (s == null) return(null);
631
    if (s->cons->sortnum == SORT_unknown) return(s);
632
    if (t >= ENC_shape_none) return(s);
2 7u83 633
 
7 7u83 634
    n = s->cons->encoding;
635
    if (n == ENC_shape_apply_token) {
636
	s = expand_tok(s);
637
	if (s == null) return(s0);
638
	n = s->cons->encoding;
2 7u83 639
    }
640
 
7 7u83 641
    if (n == ENC_shape_cond) {
2 7u83 642
	/* Don't know about conditionals */
7 7u83 643
    } else if (n != (long)t) {
644
	char tbuff[1000];
645
	construct *c = cons_no(SORT_shape, t);
646
	if (p->cons->encoding == ENC_exp_apply_token) {
647
	    IGNORE sprintf(tbuff, "%s (%s)", nm, p->son->cons->name);
648
	    nm = tbuff;
2 7u83 649
	}
7 7u83 650
	is_fatal = 0;
651
	input_error("%s argument to %s should be of %s shape",
652
		      nm, checking, c->name);
653
	return(null);
2 7u83 654
    }
7 7u83 655
    return(normalize(s));
2 7u83 656
}
657
 
658
 
659
/*
660
    CHECK THAT TWO EXPRESSIONS HAVE THE RIGHT FORM
661
 
662
    The shapes of the expressions p and q are checked to be of the form
663
    indicated by t and to be compatible.  The shape or null is returned.
664
*/
665
 
7 7u83 666
node *
667
check2(int t, node *p, node *q)
2 7u83 668
{
7 7u83 669
    node *sp = check1(t, p);
670
    node *sq = check1(t, q);
2 7u83 671
 
7 7u83 672
    if (t == ENC_nof) {
2 7u83 673
	/* For arrays check for concat_nof */
7 7u83 674
	node *s = null;
675
	node *n = null;
676
	if (sp && sq) {
677
	    sp = expand_tok(sp);
678
	    sq = expand_tok(sq);
679
	    if (sp && sp->cons->encoding == ENC_nof &&
680
		 sq && sq->cons->encoding == ENC_nof) {
2 7u83 681
		/* Find base shape of array */
7 7u83 682
		s = check_shapes(sp->son->bro, sq->son->bro, 0);
683
		sp = expand_tok(sp->son);
684
		sq = expand_tok(sq->son);
685
		if (sp && sp->cons->encoding == ENC_make_nat &&
686
		     sq && sq->cons->encoding == ENC_make_nat) {
2 7u83 687
		    /* Arrays of known size - find concatenated size */
7 7u83 688
		    construct *np = sp->son->cons;
689
		    construct *nq = sp->son->cons;
690
		    if (np->sortnum == SORT_small_tdfint &&
691
			 nq->sortnum == SORT_small_tdfint) {
692
			long up = np->encoding;
693
			long uq = nq->encoding;
694
			long umax = ((long)1) << 24;
695
			if (up <= umax && uq <= umax) {
696
			    n = make_nat(up + uq);
2 7u83 697
			}
698
		    }
699
		}
700
	    }
701
	}
7 7u83 702
	return(sh_nof(n, s));
2 7u83 703
    }
704
 
7 7u83 705
    return(check_shapes(sp, sq, 0));
2 7u83 706
}
707
 
708
 
709
/*
710
    CHECK THAT A LIST OF EXPRESSIONS HAVE THE RIGHT FORM
711
 
712
    The shapes of the list of expressions given by p are checked to be
713
    of the form indicated by t and to be compatible.  The shape or
714
    null is returned.  If nz is true an error is flagged if p is the
715
    empty list.
716
*/
717
 
7 7u83 718
node *
719
checkn(int t, node *p, int nz)
2 7u83 720
{
7 7u83 721
    node *q, *r;
722
    if (p->cons->encoding == 0) {
723
	if (nz) {
724
	    is_fatal = 0;
725
	    input_error("Repeated statement in %s cannot be empty",
726
			  checking);
2 7u83 727
	}
7 7u83 728
	return(null);
2 7u83 729
    }
7 7u83 730
    q = p->son;
731
    r = check1(t, q);
732
    while (q = q->bro, q != null) {
733
	node *s = check1(t, q);
734
	r = check_shapes(r, s, 0);
2 7u83 735
    }
7 7u83 736
    return(r);
2 7u83 737
}
738
 
739
 
740
/*
741
    SET TOKEN ARGUMENTS
742
 
743
    This routine assigns the values given by p to the formal token
744
    arguments given in c.  It is a prelude to expanding token applications.
745
    Any missing arguments are set to null.  The routine returns the list
746
    of previous argument values if set is true.
747
*/
748
 
7 7u83 749
node *
750
set_token_args(construct **c, node *p, int set)
2 7u83 751
{
7 7u83 752
    node *q = null;
753
    node *aq = null;
754
    if (c) {
755
	while (*c) {
756
	    tok_info *info = get_tok_info(*c);
757
	    if (set) {
758
		node *r = info->def;
759
		if (r) {
760
		    r = copy_node(r);
761
		    if (aq == null) {
762
			q = r;
2 7u83 763
		    } else {
7 7u83 764
			aq->bro = r;
2 7u83 765
		    }
7 7u83 766
		    aq = r;
2 7u83 767
		}
768
	    }
7 7u83 769
	    info->def = copy_node(p);
770
	    if (p)p = p->bro;
771
	    c++;
2 7u83 772
	}
773
    }
7 7u83 774
    return(q);
2 7u83 775
}
776
 
777
 
778
/*
779
    DOES A CONSTRUCT INTRODUCE A TAG OR A LABEL?
780
 
781
    This routine checks whether the construct c introduces a local tag or
782
    label.
783
*/
784
 
7 7u83 785
static int
786
is_intro_exp(construct *c)
2 7u83 787
{
7 7u83 788
    if (c->sortnum == SORT_exp) {
789
	switch (c->encoding) {
790
	    case ENC_apply_general_proc:
791
	    case ENC_conditional:
792
	    case ENC_identify:
793
	    case ENC_labelled:
794
	    case ENC_make_general_proc:
795
	    case ENC_make_proc:
796
	    case ENC_repeat:
797
	    case ENC_variable: {
798
		return(1);
2 7u83 799
	    }
800
	}
801
    }
7 7u83 802
    return(0);
2 7u83 803
}
804
 
805
 
806
/*
807
    DOES A NODE CONTAIN DEFINED TOKENS?
808
 
809
    This routine returns 4 if p is itself an application of a token, 3 if
810
    it is a make_label construct which introduces a new label (the intro
811
    flag is used to determine this) or a make_tag construct which introduces
812
    a new tag, 2 if it is a use of such an introduced label or tag, 1 if
813
    some subnode returns at least tok, and 0 otherwise.
814
*/
815
 
7 7u83 816
static int
817
contains_tokens(node *p, int intro, int tok)
2 7u83 818
{
7 7u83 819
    long n;
820
    node *q;
821
    sortname s;
822
    if (p == null) return(0);
823
    s = p->cons->sortnum;
824
    n = p->cons->encoding;
825
    switch (s) {
826
	case SORT_al_tag: {
827
	    if (n == ENC_make_al_tag) return(0);
828
	    intro = 0;
829
	    break;
2 7u83 830
	}
7 7u83 831
	case SORT_label: {
832
	    if (n == ENC_make_label) {
833
		if (intro) {
834
		    p->cons->alias = p->cons;
835
		    return(3);
2 7u83 836
		}
7 7u83 837
		if (p->cons->alias) return(2);
838
		return(0);
2 7u83 839
	    }
7 7u83 840
	    intro = 0;
841
	    break;
2 7u83 842
	}
7 7u83 843
	case SORT_tag: {
844
	    if (n == ENC_make_tag) {
845
		if (intro) {
846
		    p->cons->alias = p->cons;
847
		    return(3);
2 7u83 848
		}
7 7u83 849
		if (p->cons->alias) return(2);
850
		return(0);
2 7u83 851
	    }
7 7u83 852
	    intro = 0;
853
	    break;
2 7u83 854
	}
7 7u83 855
	case SORT_token: {
856
	    if (n == ENC_make_tok) return(0);
857
	    intro = 0;
858
	    break;
2 7u83 859
	}
7 7u83 860
	case SORT_exp: {
861
	    intro = is_intro_exp(p->cons);
862
	    break;
2 7u83 863
	}
864
	default : {
7 7u83 865
	    if (s > 0)intro = 0;
866
	    break;
2 7u83 867
	}
868
    }
7 7u83 869
    if (p->cons == &shape_of) {
870
	tok_info *info = get_tok_info(p->son->cons);
871
	q = info->def;
872
	if (q && q->cons->sortnum == SORT_completion)q = q->son;
873
	if (q && q->shape) return(4);
874
	p = p->son;
2 7u83 875
    }
7 7u83 876
    if (s > 0 && n == sort_tokens[s]) {
877
	tok_info *info = get_tok_info(p->son->cons);
878
	q = info->def;
879
	if (q) return(4);
880
	p = p->son;
2 7u83 881
    }
7 7u83 882
    for (q = p->son; q; q = q->bro) {
883
	int c = contains_tokens(q, intro, tok);
884
	if (c == 1 || c >= tok) return(1);
2 7u83 885
    }
7 7u83 886
    return(0);
2 7u83 887
}
888
 
889
 
890
/*
891
    FULLY EXPAND A NODE
892
 
893
    The node p which has contains_tokens value c (see above) is expanded
894
    recursively.  def is true during the expansion of a token definition.
895
*/
896
 
7 7u83 897
static node *
898
expand_fully_aux(node *p, int c, int def)
2 7u83 899
{
7 7u83 900
    node *q;
901
    switch (c) {
902
	case 1: {
2 7u83 903
	    /* Expand arguments */
7 7u83 904
	    node *ap;
905
	    node *aq = null;
906
	    int intro = is_intro_exp(p->cons);
907
	    q = new_node();
908
	    q->cons = p->cons;
909
	    q->shape = p->shape;
910
	    for (ap = p->son; ap; ap = ap->bro) {
911
		node *a;
912
		c = contains_tokens(ap, intro, 2);
913
		a = expand_fully_aux(ap, c, def);
914
		if (aq) {
915
		    aq->bro = a;
2 7u83 916
		} else {
7 7u83 917
		    q->son = a;
2 7u83 918
		}
7 7u83 919
		aq = a;
2 7u83 920
	    }
7 7u83 921
	    break;
2 7u83 922
	}
7 7u83 923
	case 2: {
2 7u83 924
	    /* Tag or label usage */
7 7u83 925
	    q = copy_node(p);
926
	    q->son = copy_node(q->son);
927
	    break;
2 7u83 928
	}
7 7u83 929
	case 3: {
2 7u83 930
	    /* Tag or label declaration */
7 7u83 931
	    p->son->cons->alias = null;
932
	    if (def) {
933
		copy_construct(p->son->cons);
934
		q = copy_node(p);
935
		q->son = copy_node(q->son);
2 7u83 936
	    } else {
7 7u83 937
		q = copy_node(p);
2 7u83 938
	    }
7 7u83 939
	    break;
2 7u83 940
	}
7 7u83 941
	case 4: {
2 7u83 942
	    /* Token application */
7 7u83 943
	    construct *tok = p->son->cons;
944
	    tok_info *info = get_tok_info(tok);
945
	    q = info->def;
946
	    if (q) {
947
		if (info->depth < 100) {
948
		    node *prev;
949
		    info->depth++;
950
		    if (q->cons->sortnum == SORT_completion)q = q->son;
951
		    if (p->cons == &shape_of)q = q->shape;
952
		    prev = set_token_args(info->pars, p->son->son, 1);
953
		    c = contains_tokens(q, 0, 2);
954
		    q = expand_fully_aux(q, c, 1);
955
		    IGNORE set_token_args(info->pars, prev, 0);
956
		    info->depth--;
2 7u83 957
		} else {
7 7u83 958
		    is_fatal = 0;
959
		    input_error("Nested expansion of token %s", tok->name);
960
		    q = copy_node(p);
961
		    info->depth++;
2 7u83 962
		}
963
	    } else {
7 7u83 964
		q = copy_node(p);
965
		info->depth++;
2 7u83 966
	    }
7 7u83 967
	    break;
2 7u83 968
	}
969
	default : {
970
	    /* Simple construct */
7 7u83 971
	    q = copy_node(p);
972
	    break;
2 7u83 973
	}
974
    }
7 7u83 975
    return(q);
2 7u83 976
}
977
 
978
 
979
/*
980
    EXPAND A SHAPE RECURSIVELY
981
 
982
    All applications of tokens in p are expanded.
983
*/
984
 
7 7u83 985
node *
986
expand_fully(node *p)
2 7u83 987
{
7 7u83 988
    if (p) {
989
	int c = contains_tokens(p, 0, 4);
990
	if (c)p = expand_fully_aux(p, c, 0);
2 7u83 991
    }
7 7u83 992
    return(p);
2 7u83 993
}
994
 
995
 
996
/*
997
    EXPAND A TOKEN DEFINITION
998
 
999
    This routine expands all the token definitions in the definition of the
1000
    token p.
1001
*/
1002
 
7 7u83 1003
static void
1004
expand_tokdef(construct *p)
2 7u83 1005
{
7 7u83 1006
    if (p->encoding != -1) {
1007
	tok_info *info = get_tok_info(p);
1008
	IGNORE set_token_args(info->pars,(node *)null, 0);
1009
	info->def = expand_fully(info->def);
2 7u83 1010
    }
7 7u83 1011
    return;
2 7u83 1012
}
1013
 
1014
 
1015
/*
1016
    ELIMINATE A TOKEN DEFINITION
1017
 
1018
    This routine checks whether p is a local token all of whose uses have
1019
    been expanded.  If so it eliminates p.
1020
*/
1021
 
7 7u83 1022
static void
1023
elim_tokdef(construct *p)
2 7u83 1024
{
7 7u83 1025
    if (p->encoding != -1 && p->ename == null) {
1026
	tok_info *info = get_tok_info(p);
1027
	if (info->depth == 0) {
1028
	    remove_var_hash(p->name, SORT_token);
2 7u83 1029
	}
1030
    }
7 7u83 1031
    return;
2 7u83 1032
}
1033
 
1034
 
1035
/*
1036
    EXPAND AN ALIGNMENT TAG DEFINITION
1037
 
1038
    This routine expands all the token definitions in the definition of the
1039
    alignment tag p.
1040
*/
1041
 
7 7u83 1042
static void
1043
expand_aldef(construct *p)
2 7u83 1044
{
7 7u83 1045
    if (p->encoding != -1) {
1046
	al_tag_info *info = get_al_tag_info(p);
1047
	info->def = expand_fully(info->def);
2 7u83 1048
    }
7 7u83 1049
    return;
2 7u83 1050
}
1051
 
1052
 
1053
/*
1054
    EXPAND A TAG DECLARATION AND DEFINITION
1055
 
1056
    This routine expands all the token definitions in the declaration and
1057
    definition of the tag p.
1058
*/
1059
 
7 7u83 1060
static void
1061
expand_tagdef(construct *p)
2 7u83 1062
{
7 7u83 1063
    if (p->encoding != -1) {
1064
	tag_info *info = get_tag_info(p);
1065
	info->dec = expand_fully(info->dec);
1066
	info->def = expand_fully(info->def);
2 7u83 1067
    }
7 7u83 1068
    return;
2 7u83 1069
}
1070
 
1071
 
1072
/*
1073
    EXPAND ALL TOKEN DEFINITIONS
1074
 
1075
    This routine expands all defined tokens.
1076
*/
1077
 
7 7u83 1078
void
1079
expand_all(void)
2 7u83 1080
{
7 7u83 1081
    apply_to_all(expand_tokdef, SORT_token);
1082
    apply_to_all(expand_aldef, SORT_al_tag);
1083
    apply_to_all(expand_tagdef, SORT_tag);
1084
    apply_to_all(elim_tokdef, SORT_token);
1085
    removals = null;
1086
    return;
2 7u83 1087
}