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-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 "read_types.h"
64
#include "analyser.h"
65
#include "check.h"
66
#include "de_types.h"
67
#include "de_capsule.h"
68
#include "file.h"
69
#include "high.h"
70
#include "names.h"
71
#include "node.h"
72
#include "read.h"
73
#include "read_cap.h"
74
#include "table.h"
75
#include "tdf.h"
76
#include "utility.h"
77
 
78
 
79
/*
80
    READ AN EXTERNAL NAME
81
 
82
    An external name representing an object of sort s is read from the
83
    input file.  If local is true this must just be an internal identifier.
84
*/
85
 
7 7u83 86
static construct *
87
read_external(sortname s, boolean local)
2 7u83 88
{
7 7u83 89
    construct *p;
90
    node *e = null;
91
    int estate = 0;
92
    position store;
93
    allow_multibyte = 0;
2 7u83 94
 
95
    /* Read identifier */
7 7u83 96
    store_position(&store);
97
    read_word();
2 7u83 98
 
99
    /* Check for external name */
7 7u83 100
    if (func_input) {
101
	if (word_type == INPUT_WORD) {
102
	    if (streq(word, MAKE_STRING_EXTERN)) {
103
		estate = 1;
104
	    } else if (streq(word, MAKE_UNIQUE_EXTERN)) {
105
		estate = 2;
106
	    } else if (streq(word, MAKE_CHAIN_EXTERN)) {
107
		estate = 3;
2 7u83 108
	    }
7 7u83 109
	    if (estate) {
110
		read_word();
111
		if (word_type != INPUT_OPEN) {
2 7u83 112
		    /* Go back and treat as identifier */
7 7u83 113
		    estate = 0;
114
		    set_position(&store);
115
		    read_word();
2 7u83 116
		}
117
	    }
118
	}
119
    } else {
7 7u83 120
	if (word_type == INPUT_OPEN) {
121
	    read_word();
122
	    if (word_type != INPUT_WORD) {
123
		input_error("External expected");
124
		return(null);
2 7u83 125
	    }
7 7u83 126
	    if (streq(word, MAKE_STRING_EXTERN)) {
127
		estate = 1;
128
	    } else if (streq(word, MAKE_UNIQUE_EXTERN)) {
129
		estate = 2;
130
	    } else if (streq(word, MAKE_CHAIN_EXTERN)) {
131
		estate = 3;
2 7u83 132
	    } else {
7 7u83 133
		input_error("Illegal external, %s", word);
134
		return(null);
2 7u83 135
	    }
136
	}
137
    }
138
 
7 7u83 139
    if (estate) {
2 7u83 140
	/* There is an external name */
7 7u83 141
	if (local) {
142
	    is_fatal = 0;
143
	    input_error("Can't have external name with local");
2 7u83 144
	}
7 7u83 145
	e = new_node();
146
	e->cons = &true_cons;
147
	if (estate == 1) {
148
	    e->son = read_node("$");
149
	} else if (estate == 2) {
150
	    e->son = read_node("*[$]");
2 7u83 151
	} else {
7 7u83 152
	    e->son = read_node("$i");
2 7u83 153
	}
7 7u83 154
	read_word();
155
	if (word_type != INPUT_CLOSE) {
156
	    is_fatal = 0;
157
	    input_error("End of external construct expected");
158
	    looked_ahead = 1;
2 7u83 159
	}
7 7u83 160
	read_word();
161
	if (func_input) {
162
	    if (word_type != INPUT_COMMA) {
163
		is_fatal = 0;
164
		input_error("Comma expected");
165
		looked_ahead = 1;
2 7u83 166
	    }
7 7u83 167
	    read_word();
2 7u83 168
	}
169
    } else {
170
	/* There is no external name */
7 7u83 171
	if (is_local_name(word))local = 1;
172
	if (!local) {
173
	    e = new_node();
174
	    e->cons = &false_cons;
2 7u83 175
	}
176
    }
177
 
178
    /* Check internal name */
7 7u83 179
    if (word_type != INPUT_WORD)input_error("Identifier expected");
180
    p = search_var_hash(word, s);
181
    if (p == null) {
2 7u83 182
	/* New object */
7 7u83 183
	p = make_construct(s);
184
	p->name = string_copy_aux(word);
185
	p->ename = e;
186
	IGNORE add_to_var_hash(p, s);
2 7u83 187
    } else {
188
	/* Existing object : check consistency */
7 7u83 189
	if (local) {
190
	    if (p->ename) {
191
		is_fatal = 0;
192
		input_error("Object %s previously declared global", word);
2 7u83 193
	    }
194
	} else {
7 7u83 195
	    if (p->ename) {
196
		if (e->son) {
197
		    is_fatal = 0;
198
		    input_error("External name of object %s given twice",
199
				  word);
2 7u83 200
		}
201
	    } else {
7 7u83 202
		is_fatal = 0;
203
		input_error("Object %s previously declared local", word);
2 7u83 204
	    }
205
	}
206
    }
7 7u83 207
    allow_multibyte = 1;
208
    return(p);
2 7u83 209
}
210
 
211
 
212
/*
213
    READ AN ALIGNMENT TAG DECLARATION
214
 
215
    An alignment tag declaration is read from the input file.
216
*/
217
 
7 7u83 218
static void
219
read_aldec(boolean local)
2 7u83 220
{
7 7u83 221
    IGNORE read_external(SORT_al_tag, local);
222
    return;
2 7u83 223
}
224
 
225
 
226
/*
227
    READ AN ALIGNMENT TAG DEFINITION
228
 
229
    An alignment tag definition is read from the input file.
230
*/
231
 
7 7u83 232
static void
233
read_aldef(boolean local)
2 7u83 234
{
7 7u83 235
    node *d;
236
    construct *p = read_external(SORT_al_tag, local);
237
    al_tag_info *info = get_al_tag_info(p);
2 7u83 238
 
239
    /* Check comma */
7 7u83 240
    if (func_input) {
241
	read_word();
242
	if (word_type != INPUT_COMMA) {
243
	    is_fatal = 0;
244
	    input_error("Comma expected");
245
	    looked_ahead = 1;
2 7u83 246
	}
247
    }
248
 
249
    /* Read the definition (an alignment) */
7 7u83 250
    d = completion(read_node("a"));
251
    if (info->def) {
252
	if (!eq_node(info->def, d)) {
253
	    is_fatal = 0;
254
	    input_error("Alignment tag %s defined inconsistently",
255
			  p->name);
2 7u83 256
	}
7 7u83 257
	free_node(d);
2 7u83 258
    } else {
7 7u83 259
	info->def = d;
2 7u83 260
    }
7 7u83 261
    return;
2 7u83 262
}
263
 
264
 
265
/*
266
    READ A TAG DECLARATION
267
 
268
    A tag declaration is read from the input file.  Whether it is a
269
    variable or an identity is indicated by the is_var flag.
270
*/
271
 
7 7u83 272
static void
273
read_tagdec(boolean local, int is_var)
2 7u83 274
{
7 7u83 275
    node *d;
276
    construct *p = read_external(SORT_tag, local);
277
    tag_info *info = get_tag_info(p);
278
    set_tag_type(p, is_var);
2 7u83 279
 
280
    /* Check comma */
7 7u83 281
    if (func_input) {
282
	read_word();
283
	if (word_type != INPUT_COMMA) {
284
	    is_fatal = 0;
285
	    input_error("Comma expected");
286
	    looked_ahead = 1;
2 7u83 287
	}
288
    }
289
 
290
    /* Declaration = optional access + optional string + shape from 4.0 */
7 7u83 291
    d = completion(read_node("?[u]?[X]S"));
292
    info->var = (boolean)is_var;
293
    if (info->dec) {
294
	if (!eq_node(info->dec, d)) {
295
	    is_fatal = 0;
296
	    input_error("Tag %s declared inconsistently", p->name);
2 7u83 297
	}
7 7u83 298
	free_node(d);
2 7u83 299
    } else {
7 7u83 300
	info->dec = d;
2 7u83 301
    }
7 7u83 302
    return;
2 7u83 303
}
304
 
305
 
306
/*
307
    READ A TAG DEFINITION
308
 
309
    A tag definition is read from the input file.  Whether it is a
310
    variable or an identity is indicated by the is_var flag.
311
*/
312
 
7 7u83 313
static void
314
read_tagdef(boolean local, int is_var)
2 7u83 315
{
7 7u83 316
    node *d;
317
    construct *p = read_external(SORT_tag, local);
318
    tag_info *info = get_tag_info(p);
2 7u83 319
 
320
    /* Set the tag type */
7 7u83 321
    if (info->dec == null && !do_check) {
322
	is_fatal = 0;
323
	input_error("Tag %s defined but not declared", word);
2 7u83 324
    }
7 7u83 325
    set_tag_type(p, is_var);
2 7u83 326
 
327
    /* Check comma */
7 7u83 328
    if (func_input) {
329
	read_word();
330
	if (word_type != INPUT_COMMA) {
331
	    is_fatal = 0;
332
	    input_error("Comma expected");
333
	    looked_ahead = 1;
2 7u83 334
	}
335
    }
336
 
337
    /* Definition - signature added in 4.0 */
7 7u83 338
    d = completion(read_node(is_var ? "?[u]?[X]x" : "?[X]x"));
339
    info->var = (boolean)is_var;
340
    if (info->def) {
341
	if (is_var == 2) {
342
	    node *dp = info->def;
343
	    while (dp->bro)dp = dp->bro;
344
	    dp->bro = d;
2 7u83 345
	} else {
7 7u83 346
	    if (!eq_node(info->def, d)) {
347
		is_fatal = 0;
348
		input_error("Tag %s defined inconsistently", p->name);
2 7u83 349
	    }
7 7u83 350
	    free_node(d);
2 7u83 351
	}
352
    } else {
7 7u83 353
	info->def = d;
354
	if (do_check)check_tagdef(p);
2 7u83 355
    }
7 7u83 356
    return;
2 7u83 357
}
358
 
359
 
360
/*
361
    READ A SORTNAME
362
 
363
    A sortname is read from the input file.
364
*/
365
 
7 7u83 366
static sortname
367
read_sortname(void)
2 7u83 368
{
7 7u83 369
    sortname s;
370
    if (word_type != INPUT_WORD) {
371
	is_fatal = 0;
372
	input_error("Sort name expected");
373
	return(SORT_unknown);
2 7u83 374
    }
7 7u83 375
    s = find_high_sort(word);
376
    if (s == SORT_unknown) {
377
	is_fatal = 0;
378
	input_error("Illegal sort name, %s", word);
2 7u83 379
    } else {
7 7u83 380
	if (s > SORT_max && s < SORT_no) {
381
	    is_fatal = 0;
382
	    input_error("Bad sort name, %s", word);
2 7u83 383
	}
384
    }
7 7u83 385
    return(s);
2 7u83 386
}
387
 
388
 
389
/*
390
    READ TOKEN SORT
391
 
392
    A token sort is read and the information is stored in info.  This
393
    can be a definition (with formal parameters) or a declaration
394
    (without) depending on the value of def.
395
*/
396
 
7 7u83 397
static void
398
read_toksort(tok_info *info, boolean def)
2 7u83 399
{
400
    /* Check comma */
7 7u83 401
    if (func_input) {
402
	read_word();
403
	if (word_type != INPUT_COMMA) {
404
	    is_fatal = 0;
405
	    input_error("Comma expected");
406
	    looked_ahead = 1;
2 7u83 407
	}
408
    }
409
 
410
    /* Initialize values */
7 7u83 411
    info->res = SORT_unknown;
412
    info->args = null;
413
    info->pars = null;
414
    info->sig = null;
2 7u83 415
 
416
    /* Read signature */
7 7u83 417
    info->sig = read_node("?[X]");
2 7u83 418
 
419
    /* Read argument sorts */
7 7u83 420
    read_word();
421
    if (word_type == INPUT_OPEN) {
422
	int no_args = 0;
423
	char arg_buff[100];
424
	char *a = arg_buff;
425
	construct *cons_buff[100];
426
	construct **c = cons_buff;
427
	while (read_word(), word_type != INPUT_CLOSE) {
428
	    sortname s = read_sortname();
429
	    if (is_high(s)) {
430
		sprint_high_sort(a, s);
431
		while (*a)a++;
2 7u83 432
	    } else {
7 7u83 433
		*(a++) = sort_letters[s];
2 7u83 434
	    }
7 7u83 435
	    if (def) {
2 7u83 436
		/* Read formal argument */
7 7u83 437
		construct *q;
438
		read_word();
439
		if (word_type != INPUT_WORD) {
440
		    input_error("Token identifier expected");
2 7u83 441
		}
7 7u83 442
		q = search_var_hash(word, SORT_token);
443
		if (q) {
444
		    input_error("Token %s already declared", word);
2 7u83 445
		}
7 7u83 446
		q = make_construct(SORT_token);
447
		q->name = string_copy_aux(word);
448
		IGNORE add_to_var_hash(q, SORT_token);
449
		set_token_sort(q, s,(char *)null,(node *)null);
450
		*(c++) = q;
2 7u83 451
	    }
452
	    /* Check comma */
7 7u83 453
	    if (func_input) {
454
		read_word();
455
		if (word_type == INPUT_CLOSE) {
456
		    looked_ahead = 1;
457
		} else if (word_type != INPUT_COMMA) {
458
		    is_fatal = 0;
459
		    input_error("Comma or close bracket expected");
460
		    looked_ahead = 1;
2 7u83 461
		}
462
	    }
7 7u83 463
	    no_args++;
2 7u83 464
	}
7 7u83 465
	*a = 0;
466
	if (*arg_buff) {
2 7u83 467
	    /* Store argument string */
7 7u83 468
	    info->args = string_copy_aux(arg_buff);
469
	    if (def) {
2 7u83 470
		/* Store formal arguments */
7 7u83 471
		int i, n = no_args;
472
		info->pars = alloc_nof(construct *, n + 1);
473
		for (i = 0; i < n; i++)info->pars[i] = cons_buff[i];
474
		info->pars[n] = null;
2 7u83 475
	    }
476
	}
7 7u83 477
	read_word();
478
	if (func_input) {
479
	    if (word_type != INPUT_ARROW) {
480
		is_fatal = 0;
481
		input_error("Arrow (->) expected");
482
		looked_ahead = 1;
2 7u83 483
	    }
7 7u83 484
	    read_word();
2 7u83 485
	}
486
    }
487
 
488
    /* Read result sort */
7 7u83 489
    info->res = read_sortname();
490
    if (is_high(info->res)) {
491
	input_error("Tokens cannot return high-level sorts");
2 7u83 492
    }
7 7u83 493
    return;
2 7u83 494
}
495
 
496
 
497
/*
498
    READ A TOKEN DECLARATION
499
 
500
    A token declaration is read from the input file.
501
*/
502
 
7 7u83 503
static void
504
read_tokdec(boolean local)
2 7u83 505
{
7 7u83 506
    tok_info store;
507
    construct *p = read_external(SORT_token, local);
508
    tok_info *info = get_tok_info(p);
2 7u83 509
 
510
    /* Get token sort */
7 7u83 511
    adjust_token(p);
512
    read_toksort(&store, 0);
513
    info->dec = 1;
514
    set_token_sort(p, store.res, store.args, store.sig);
515
    return;
2 7u83 516
}
517
 
518
 
519
/*
520
    READ A TOKEN DEFINITION
521
 
522
    A token definition is read from the input file.
523
*/
524
 
7 7u83 525
static void
526
read_tokdef(boolean local)
2 7u83 527
{
7 7u83 528
    node *d;
529
    char buff[2];
530
    tok_info store;
531
    construct *p = read_external(SORT_token, local);
532
    tok_info *info = get_tok_info(p);
533
    construct **old_pars = info->pars;
2 7u83 534
 
535
    /* Get token sort */
7 7u83 536
    adjust_token(p);
537
    read_toksort(&store, 1);
538
    info->dec = 1;
539
    info->pars = store.pars;
540
    set_token_sort(p, store.res, store.args, store.sig);
2 7u83 541
 
542
    /* Check comma */
7 7u83 543
    if (func_input) {
544
	read_word();
545
	if (word_type != INPUT_COMMA) {
546
	    is_fatal = 0;
547
	    input_error("Comma expected");
548
	    looked_ahead = 1;
2 7u83 549
	}
550
    }
551
 
552
    /* Read the definition */
7 7u83 553
    buff[0] = sort_letters[store.res];
554
    buff[1] = 0;
555
    d = read_node(buff);
2 7u83 556
 
557
    /* Free formal parameters */
7 7u83 558
    if (info->pars) {
559
	construct **ps;
560
	for (ps = info->pars; *ps; ps++) {
561
	    remove_var_hash((*ps) ->name, SORT_token);
2 7u83 562
	}
563
    }
564
 
565
    /* Check consistency */
7 7u83 566
    d = completion(d);
567
    if (info->def) {
568
	if (!eq_node(info->def, d)) {
569
	    is_fatal = 0;
570
	    input_error("Token %s defined inconsistently", p->name);
2 7u83 571
	}
7 7u83 572
	free_node(d);
573
	info->pars = old_pars;
2 7u83 574
    } else {
7 7u83 575
	info->def = d;
2 7u83 576
    }
7 7u83 577
    return;
2 7u83 578
}
579
 
580
 
581
/*
582
    READ A TOKEN SORT DEFINITION
583
 
584
    A token sort defintion is read from the input file.
585
*/
586
 
7 7u83 587
static void
588
read_sortdef(boolean local)
2 7u83 589
{
7 7u83 590
    char *nm;
591
    tok_info store;
2 7u83 592
 
593
    /* The local quantifier should not be used */
7 7u83 594
    if (local) {
595
	is_fatal = 0;
596
	input_error("Can't have local here");
2 7u83 597
    }
598
 
599
    /* Read the sort name */
7 7u83 600
    read_word();
601
    if (word_type != INPUT_WORD)input_error("Identifier expected");
602
    nm = string_copy_aux(word);
2 7u83 603
 
604
    /* Get sort definition */
7 7u83 605
    read_toksort(&store, 0);
606
    set_high_sort(nm, &store);
607
    return;
2 7u83 608
}
609
 
610
 
611
/*
612
    READ A SUBFILE
613
 
614
    A complete subfile is read.  ftype gives the type of the subfile :
615
 
616
    only the tokens should be read.
617
*/
618
 
7 7u83 619
static void
620
sub_file(int ftype, int ex)
2 7u83 621
{
7 7u83 622
    position store;
623
    boolean old_func_input = func_input;
624
    char *old_name = input_file, *new_name;
2 7u83 625
 
626
    /* Read the file name */
7 7u83 627
    allow_multibyte = 0;
628
    read_word();
629
    allow_multibyte = 1;
630
    if (word_type != INPUT_STRING) {
631
	is_fatal = 0;
632
	input_error("File name expected");
633
	return;
2 7u83 634
    }
7 7u83 635
    new_name = string_copy_aux(word);
2 7u83 636
 
637
    /* Save the position in the existing file */
7 7u83 638
    store_position(&store);
2 7u83 639
 
640
    /* Read the subfile */
7 7u83 641
    text_input = (boolean)(ftype == 0 ? 1 : 0);
642
    open_input(new_name, 1);
643
    if (ftype == 0) {
644
	read_capsule();
2 7u83 645
    } else {
7 7u83 646
	extract_tokdecs = (boolean)ex;
647
	if (ftype == 1) {
648
	    de_capsule();
2 7u83 649
	} else {
7 7u83 650
	    de_library();
2 7u83 651
	}
7 7u83 652
	extract_tokdecs = 0;
2 7u83 653
    }
654
 
655
    /* Restore the position in the old file */
7 7u83 656
    text_input = 1;
657
    open_input(old_name, 1);
658
    set_position(&store);
659
    func_input = old_func_input;
660
    return;
2 7u83 661
}
662
 
663
 
664
/*
665
    READ A CAPSULE
666
 
667
    A complete capsule is read from the input file.
668
*/
669
 
7 7u83 670
void
671
read_capsule(void)
2 7u83 672
{
7 7u83 673
    int starter;
674
    read_word();
675
    if (word_type == INPUT_OPEN) {
676
	if (func_input)warning("Switching input form");
677
	func_input = 0;
678
	starter = INPUT_OPEN;
2 7u83 679
    } else {
7 7u83 680
	if (!func_input)warning("Switching input form");
681
	func_input = 1;
682
	starter = INPUT_WORD;
2 7u83 683
    }
7 7u83 684
    looked_ahead = 1;
2 7u83 685
 
7 7u83 686
    while (read_word(), word_type == starter) {
687
	char *cmd;
688
	char *wtemp;
689
	boolean local = 0;
690
	if (!func_input) {
691
	    read_word();
692
	    if (word_type != INPUT_WORD) {
693
		input_error("Construct name expected");
2 7u83 694
	    }
695
	}
696
 
697
	/* Check for the local qualifier */
7 7u83 698
	if (streq(word, LOCAL_DECL)) {
699
	    local = 1;
700
	    read_word();
701
	    if (word_type != INPUT_WORD) {
702
		input_error("Construct name expected");
2 7u83 703
	    }
704
	}
705
 
706
	/* For functional input, expect an open bracket */
7 7u83 707
	if (func_input) {
708
	    wtemp = temp_copy(word);
709
	    read_word();
710
	    if (word_type != INPUT_OPEN) {
711
		is_fatal = 0;
712
		input_error("Open bracket expected");
713
		looked_ahead = 1;
2 7u83 714
	    }
715
	} else {
7 7u83 716
	    wtemp = word;
2 7u83 717
	}
718
 
719
	/* Macro to aid checking */
7 7u83 720
#define test_cmd(X, Y)\
721
	if (streq(wtemp, cmd = (X))) {\
2 7u83 722
	    Y ;\
723
	} else
724
 
725
	/* Check on the various possible constructs */
7 7u83 726
	test_cmd(MAKE_ALDEC, read_aldec(local))
727
	test_cmd(MAKE_ALDEF, read_aldef(local))
728
	test_cmd(MAKE_ID_TAGDEC, read_tagdec(local, 0))
729
	test_cmd(MAKE_VAR_TAGDEC, read_tagdec(local, 1))
730
	test_cmd(MAKE_ID_TAGDEF, read_tagdef(local, 0))
731
	test_cmd(MAKE_VAR_TAGDEF, read_tagdef(local, 1))
732
	test_cmd(MAKE_TOKDEC, read_tokdec(local))
733
	test_cmd(MAKE_TOKDEF, read_tokdef(local))
734
	test_cmd(COMMON_TAGDEC, read_tagdec(local, 2))
735
	test_cmd(COMMON_TAGDEF, read_tagdef(local, 2))
736
	test_cmd(MAKE_SORT, read_sortdef(local))
2 7u83 737
 
738
	{
739
	    /* Include constructs */
7 7u83 740
	    if (local) {
741
		is_fatal = 0;
742
		input_error("Can't have local here");
2 7u83 743
	    }
7 7u83 744
	    test_cmd(INCLUDE_TEXT, sub_file(0, 0))
745
	    test_cmd(INCLUDE_CODE, sub_file(1, 0))
746
	    test_cmd(USE_CODE, sub_file(1, 1))
747
	    test_cmd(INCLUDE_LIB, sub_file(2, 0))
748
	    test_cmd(USE_LIB, sub_file(2, 1))
2 7u83 749
	    {
750
		/* Illegal construct */
7 7u83 751
		input_error("Illegal construct name, %s", wtemp);
2 7u83 752
	    }
753
	}
754
 
755
	/* End of construct */
7 7u83 756
	read_word();
757
	if (word_type != INPUT_CLOSE) {
758
	    is_fatal = 0;
759
	    input_error("End of %s construct expected", cmd);
760
	    looked_ahead = 1;
2 7u83 761
	}
7 7u83 762
	if (func_input) {
763
	    read_word();
764
	    if (word_type != INPUT_SEMICOLON) {
765
		is_fatal = 0;
766
		input_error("End of %s construct expected", cmd);
767
		looked_ahead = 1;
2 7u83 768
	    }
769
	}
770
    }
7 7u83 771
    if (word_type != INPUT_EOF) {
772
	is_fatal = 0;
773
	input_error("Start of construct expected");
2 7u83 774
    }
7 7u83 775
    return;
2 7u83 776
}