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