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 "node.h"
34
#include "table.h"
35
#include "tdf.h"
36
#include "utility.h"
37
 
38
 
39
/*
40
    LIST OF FREE NODES
41
 
42
    Nodes are allocated from this list.
43
*/
44
 
45
static node *free_nodes = null ;
46
 
47
 
48
/*
49
    CREATE A NEW NODE
50
 
51
    A new node is created and its fields cleared.
52
*/
53
 
54
node *new_node
55
    PROTO_Z ()
56
{
57
    node *p = free_nodes ;
58
    if ( p == null ) {
59
	int i, m = 1000 ;
60
	p = alloc_nof ( node, m ) ;
61
	for ( i = 0 ; i < m - 1 ; i++ ) {
62
	    ( p + i )->bro = p + ( i + 1 ) ;
63
	    ( p + i )->son = null ;
64
	}
65
	( p + ( m - 1 ) )->bro = null ;
66
	( p + ( m - 1 ) )->son = null ;
67
	free_nodes = p ;
68
    }
69
    free_nodes = p->bro ;
70
    p->cons = null ;
71
    p->son = null ;
72
    p->bro = null ;
73
    p->shape = null ;
74
    return ( p ) ;
75
}
76
 
77
 
78
/*
79
    FREE A NODE
80
 
81
    The node p is recursively returned to the free list.
82
*/
83
 
84
void free_node
85
    PROTO_N ( ( p ) )
86
    PROTO_T ( node *p )
87
{
88
    while ( p ) {
89
	node *q = p->bro ;
90
	if ( p->son ) free_node ( p->son ) ;
91
	p->bro = free_nodes ;
92
	free_nodes = p ;
93
	p = q ;
94
    }
95
    return ;
96
}
97
 
98
 
99
/*
100
    FORM THE COMPLETION OF A NODE
101
 
102
    The completion of the node p is created.  This consists of p itself
103
    and the list of all local variable sorts created during the
104
    construction of p, as recorded by the removals list.
105
*/
106
 
107
node *completion
108
    PROTO_N ( ( p ) )
109
    PROTO_T ( node *p )
110
{
111
    node *q = new_node () ;
112
    construct *v = make_construct ( SORT_completion ) ;
113
    v->next = removals ;
114
    removals = null ;
115
    q->cons = v ;
116
    q->son = p ;
117
    return ( q ) ;
118
}
119
 
120
 
121
/*
122
    AUXILIARY EQUALITY ROUTINE
123
 
124
    This routine checks the nodes p and q for equality modulo the
125
    lists of local variables ap and aq (which are known to correspond).
126
*/
127
 
128
static boolean eq_node_aux
129
    PROTO_N ( ( p, q, ap, aq, args ) )
130
    PROTO_T ( node *p X node *q X construct *ap X construct *aq X int args )
131
{
132
    while ( p != null && q != null ) {
133
	if ( p->cons != q->cons ) {
134
	    sortname s = p->cons->sortnum ;
135
	    if ( s != q->cons->sortnum ) return ( 0 ) ;
136
	    switch ( s ) {
137
 
138
		case SORT_bytestream :
139
		case SORT_option : {
140
		    /* Just check son */
141
		    break ;
142
		}
143
 
144
		case SORT_tdfbool :
145
		case SORT_small_tdfint :
146
		case SORT_repeat : {
147
		    /* Check value or number of repeats */
148
		    if ( p->cons->encoding != q->cons->encoding ) {
149
			return ( 0 ) ;
150
		    }
151
		    break ;
152
		}
153
 
154
		case SORT_tdfint :
155
		case SORT_tdfstring : {
156
		    /* Check value */
157
		    if ( !streq ( p->cons->name, q->cons->name ) ) {
158
			return ( 0 ) ;
159
		    }
160
		    break ;
161
		}
162
 
163
		default : {
164
		    /* Check lists of local variables */
165
		    boolean ok = 0 ;
166
		    construct *xp = ap ;
167
		    construct *xq = aq ;
168
		    while ( xp && !ok ) {
169
			if ( xp == p->cons && xq == q->cons ) ok = 1 ;
170
			xp = xp->next ;
171
			xq = xq->next ;
172
		    }
173
		    if ( !ok ) return ( 0 ) ;
174
		    break ;
175
		}
176
	    }
177
	}
178
	if ( !eq_node_aux ( p->son, q->son, ap, aq, 1 ) ) return ( 0 ) ;
179
	if ( !args ) return ( 1 ) ;
180
	p = p->bro ;
181
	q = q->bro ;
182
    }
183
    if ( p == q ) return ( 1 ) ;
184
    return ( 0 ) ;
185
}
186
 
187
 
188
/*
189
    CHECK TWO LISTS OF CONSTRUCTS
190
 
191
    The lists of local variables ap and aq are checked to have the
192
    same length and corresponds sorts in each position.
193
*/
194
 
195
static boolean eq_cons_list
196
    PROTO_N ( ( ap, aq ) )
197
    PROTO_T ( construct *ap X construct *aq )
198
{
199
    while ( ap != null && aq != null ) {
200
	if ( ap->sortnum != aq->sortnum ) return ( 0 ) ;
201
	ap = ap->next ;
202
	aq = aq->next ;
203
    }
204
    if ( ap == aq ) return ( 1 ) ;
205
    return ( 0 ) ;
206
}
207
 
208
 
209
/*
210
    FLAG : SHOULD WE CHECK EQUALITY OF NODES?
211
 
212
    This should be set to 1 to suppress the check in eq_node.
213
*/
214
 
215
boolean dont_check = 0 ;
216
 
217
 
218
/*
219
    ARE TWO NODES EQUAL?
220
 
221
    The nodes p and q are checked for equality.
222
*/
223
 
224
boolean eq_node
225
    PROTO_N ( ( p, q ) )
226
    PROTO_T ( node *p X node *q )
227
{
228
    construct *ap = null ;
229
    construct *aq = null ;
230
    if ( dont_check ) return ( 1 ) ;
231
    if ( p == q ) return ( 1 ) ;
232
    if ( p == null || q == null ) return ( 0 ) ;
233
    if ( p->cons->sortnum == SORT_completion ) {
234
	ap = p->cons->next ;
235
	p = p->son ;
236
    }
237
    if ( q->cons->sortnum == SORT_completion ) {
238
	aq = q->cons->next ;
239
	q = q->son ;
240
    }
241
    if ( !eq_cons_list ( ap, aq ) ) return ( 0 ) ;
242
    return ( eq_node_aux ( p, q, ap, aq, 0 ) ) ;
243
}
244
 
245
 
246
/*
247
    LIST OF FREE CONSTRUCTS
248
 
249
    Constructs are allocated from this list.
250
*/
251
 
252
static construct *free_constructs = null ;
253
 
254
 
255
/*
256
    CREATE A NEW CONSTRUCT
257
 
258
    A new construct is allocated.  Its fields are not initialized.
259
*/
260
 
261
construct *new_construct
262
    PROTO_Z ()
263
{
264
    construct *p = free_constructs ;
265
    if ( p == null ) {
266
	int i, m = 100 ;
267
	p = alloc_nof ( construct, m ) ;
268
	for ( i = 0 ; i < m - 1 ; i++ ) ( p + i )->next = p + ( i + 1 ) ;
269
	( p + ( m - 1 ) )->next = null ;
270
	free_constructs = p ;
271
    }
272
    free_constructs = p->next ;
273
    p->alias = null ;
274
    p->next = null ;
275
    return ( p ) ;
276
}
277
 
278
 
279
/*
280
    CREATE A NEW CONSTRUCT OF A GIVEN SORT
281
 
282
    A new construct is allocated.  Its fields are initialized for a
283
    construct of sort s.
284
*/
285
 
286
construct *make_construct
287
    PROTO_N ( ( s ) )
288
    PROTO_T ( sortname s )
289
{
290
    construct *p = new_construct () ;
291
    p->sortnum = s ;
292
    if ( s >= 0 ) {
293
	p->encoding = ( sort_count [s] )++ ;
294
    } else {
295
	p->encoding = 0 ;
296
    }
297
    p->name = null ;
298
    p->ename = null ;
299
    p->next = null ;
300
    switch ( s ) {
301
 
302
	case SORT_al_tag : {
303
	    /* Initialize alignment tag */
304
	    al_tag_info *q = get_al_tag_info ( p ) ;
305
	    q->def = null ;
306
	    break ;
307
	}
308
 
309
	case SORT_tag : {
310
	    /* Initialize tag */
311
	    tag_info *q = get_tag_info ( p ) ;
312
	    q->var = 3 ;
313
	    q->vis = 0 ;
314
	    q->dec = null ;
315
	    q->def = null ;
316
	    break ;
317
	}
318
 
319
	case SORT_token : {
320
	    /* Initialize token */
321
	    tok_info *q = get_tok_info ( p ) ;
322
	    q->dec = 0 ;
323
	    q->res = SORT_unknown ;
324
	    q->args = null ;
325
	    q->sig = null ;
326
	    q->def = null ;
327
	    q->pars = null ;
328
	    q->depth = 0 ;
329
	    break ;
330
	}
331
    }
332
    return ( p ) ;
333
}
334
 
335
 
336
/*
337
    FREE A LIST OF CONSTRUCTS
338
 
339
    The list of constructed pointed to by p is returned to free.
340
*/
341
 
342
void free_construct
343
    PROTO_N ( ( p ) )
344
    PROTO_T ( construct **p )
345
{
346
    construct *q = *p ;
347
    if ( q ) {
348
	while ( q->next ) q = q->next ;
349
	q->next = free_constructs ;
350
	free_constructs = *p ;
351
    }
352
    *p = null ;
353
    return ;
354
}
355
 
356
 
357
/*
358
    SET THE SORT OF A TOKEN
359
 
360
    The token construct p is set to have result sort rs and argument
361
    sorts args.
362
*/
363
 
364
void set_token_sort
365
    PROTO_N ( ( p, rs, args, sig ) )
366
    PROTO_T ( construct *p X sortname rs X char *args X node *sig )
367
{
368
    tok_info *info = get_tok_info ( p ) ;
369
    if ( info->res != SORT_unknown ) {
370
	boolean error = 0 ;
371
	if ( info->res != rs ) error = 1 ;
372
	if ( args ) {
373
	    if ( info->args == null || !streq ( args, info->args ) ) {
374
		error = 1 ;
375
	    }
376
	} else {
377
	    if ( info->args ) error = 1 ;
378
	}
379
	if ( error ) {
380
	    is_fatal = 0 ;
381
	    input_error ( "Token %s declared inconsistently", p->name ) ;
382
	}
383
    }
384
    info->res = rs ;
385
    info->args = args ;
386
    info->sig = sig ;
387
    return ;
388
}
389
 
390
 
391
/*
392
    SET TAG TYPE
393
 
394
    The tag construct p is set to be a variable or an identity, depending
395
    on the flag is_var.
396
*/
397
 
398
void set_tag_type
399
    PROTO_N ( ( p, is_var ) )
400
    PROTO_T ( construct *p X int is_var )
401
{
402
    tag_info *info = get_tag_info ( p ) ;
403
    if ( info->var != 3 ) {
404
	if ( info->var != is_var ) {
405
	    is_fatal = 0 ;
406
	    input_error ( "Tag %s declared inconsistently", p->name ) ;
407
	}
408
    }
409
#if 0
410
    info->var = is_var ;
411
#endif
412
    return ;
413
}
414
 
415
 
416
/*
417
    CREATE A COPY OF A CONSTRUCT
418
 
419
    This routine creates a copy of the construct p.  This is used during
420
    token expansion to ensure that tags and labels which are local to a
421
    token definition are handled correctly.
422
*/
423
 
424
void copy_construct
425
    PROTO_N ( ( p ) )
426
    PROTO_T ( construct *p )
427
{
428
    sortname s = p->sortnum ;
429
    construct *q = make_construct ( s ) ;
430
    if ( s == SORT_tag ) {
431
	tag_info *pi = get_tag_info ( p ) ;
432
	tag_info *qi = get_tag_info ( q ) ;
433
	qi->var = pi->var ;
434
	qi->vis = pi->vis ;
435
    }
436
    q->name = p->name ;
437
    p->alias = q ;
438
    ( sort_removed [s] )++ ;
439
    return ;
440
}
441
 
442
 
443
/*
444
    SKIP TEXT ENCLOSED IN SQUARE BRACKETS
445
 
446
    The decode string s is analysed and a pointer to the first ']'
447
    which is not balanced by a '[' is returned.
448
*/
449
 
450
char *skip_text
451
    PROTO_N ( ( s ) )
452
    PROTO_T ( char *s )
453
{
454
    int n = 0 ;
455
    while ( *s ) {
456
	if ( *s == '[' ) n++ ;
457
	if ( *s == ']' ) {
458
	    if ( n == 0 ) return ( s ) ;
459
	    n-- ;
460
	}
461
	s++ ;
462
    }
463
    fatal_error ( "Illegal decoding string" ) ;
464
    return ( s ) ;
465
}
466
 
467
 
468
/*
469
    LOCAL IDENTIFIER PREFIX
470
 
471
    All tag, token and alignment tags with this prefix are treated as if
472
    they were declared local.
473
*/
474
 
475
char *local_prefix = "<none>" ;
476
 
477
 
478
/*
479
    IS AN IDENTIFIER LOCAL?
480
 
481
    This routine checks whether the identifier name s begins with the
482
    local identifier prefix above.
483
*/
484
 
485
boolean is_local_name
486
    PROTO_N ( ( s ) )
487
    PROTO_T ( char *s )
488
{
489
    char *t = local_prefix ;
490
    while ( *s == *t ) {
491
	s++ ;
492
	t++ ;
493
    }
494
    if ( *t == 0 ) return ( 1 ) ;
495
    return ( 0 ) ;
496
}