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