Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | 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 "de_types.h"
34
#include "de_unit.h"
35
#include "decode.h"
36
#include "fetch.h"
37
#include "names.h"
38
#include "node.h"
39
#include "table.h"
40
#include "tdf.h"
41
#include "utility.h"
42
 
43
 
44
/*
45
    FLAG : DECODE STATUS
46
 
47
    A value of 0 indicates that we are decoding the names at the start
48
    of the capsule, 1 that we are decoding the linkage information, and
49
    2 that we are decoding a main equation body.
50
*/
51
 
52
int decode_status = -1 ;
53
 
54
 
55
/*
56
    FLAG : ONLY DECODE TOKEN DECLARATIONS
57
 
58
    This flag is true if we are only interested in the token
59
    declarations in a capsule.
60
*/
61
 
62
boolean extract_tokdecs = 0 ;
63
 
64
 
65
/*
66
    THE ARRAY OF ALL VARIABLE SORTS
67
 
68
    The array vars of size no_var gives all variable sorts.  The
69
    indexes in this array of the alignment tags, tags and tokens are
70
    given by al_tag_var, tag_var, tok_var respectively.
71
*/
72
 
73
static long no_var ;
74
static var_sort *vars ;
75
long al_tag_var, tag_var, tok_var ;
76
 
77
 
78
/*
79
    LIST OF UNUSED CONSTRUCTS
80
 
81
    All unused constructs in a capsule are formed into a list for
82
    later reuse.
83
*/
84
 
85
static construct *garbage = null ;
86
 
87
 
88
/*
89
    CURRENT BINDINGS
90
 
91
    The current bindings are held in crt_binding.  spare_binding, if not
92
    null, contains a binding suitable for reuse.
93
*/
94
 
95
binding *crt_binding ;
96
static binding *spare_binding = null ;
97
 
98
 
99
/*
100
    CREATE A NEW BINDING
101
 
102
    A new binding with space for no_var variable sorts is created and
103
    cleared.
104
*/
105
 
106
static binding *new_binding
107
    PROTO_Z ()
108
{
109
    binding *b ;
110
    long i, n = no_var ;
111
    if ( n == 0 ) return ( null ) ;
112
    if ( spare_binding ) {
113
	b = spare_binding ;
114
	spare_binding = null ;
115
	for ( i = 0 ; i < n ; i++ ) b [i].max_no = 0 ;
116
	return ( b ) ;
117
    }
118
    b = alloc_nof ( binding, n ) ;
119
    for ( i = 0 ; i < n ; i++ ) {
120
	b [i].max_no = 0 ;
121
	b [i].sz = 0 ;
122
	b [i].table = null ;
123
    }
124
    return ( b ) ;
125
}
126
 
127
 
128
/*
129
    FREE A BINDING
130
 
131
    The binding b is returned to free.
132
*/
133
 
134
static void free_binding
135
    PROTO_N ( ( b ) )
136
    PROTO_T ( binding *b )
137
{
138
    spare_binding = b ;
139
    return ;
140
}
141
 
142
 
143
/*
144
    SET THE SIZE OF AN ENTRY IN A BINDING
145
 
146
    The size of the table of the vth variable sort in the binding bt
147
    is set to n.
148
*/
149
 
150
static void set_binding_size
151
    PROTO_N ( ( bt, v, n ) )
152
    PROTO_T ( binding *bt X long v X long n )
153
{
154
    binding *b ;
155
    construct **p ;
156
    long i, m = n + 10 ;
157
    if ( v < 0 || v >= no_var ) {
158
	input_error ( "Illegal binding sort" ) ;
159
	return ;
160
    }
161
    b = bt + v ;
162
    b->max_no = n ;
163
    if ( b->sz < m ) {
164
	p = realloc_nof ( b->table, construct *, m ) ;
165
	b->sz = m ;
166
	b->table = p ;
167
    } else {
168
	p = b->table ;
169
    }
170
    for ( i = 0 ; i < b->sz ; i++ ) p [i] = null ;
171
    return ;
172
}
173
 
174
 
175
/*
176
    COMPLETE A BINDING
177
 
178
    The unused entries in the binding b are filled in.
179
*/
180
 
181
static void complete_binding
182
    PROTO_N ( ( b ) )
183
    PROTO_T ( binding *b )
184
{
185
    long v ;
186
    for ( v = 0 ; v < no_var ; v++ ) {
187
	long i ;
188
	binding *bv = b + v ;
189
	sortname s = vars [v].sortnum ;
190
	for ( i = 0 ; i < bv->max_no ; i++ ) {
191
	    if ( bv->table [i] == null ) {
192
		construct *p = make_construct ( s ) ;
193
		if ( extract_tokdecs ) {
194
		    /* This construct is unused - free it */
195
		    ( sort_count [s] )-- ;
196
		    p->next = garbage ;
197
		    garbage = p ;
198
		} else {
199
		    /* Make up an internal name */
200
		    long n = p->encoding ;
201
		    char *nm = alloc_nof ( char, 32 ) ;
202
		    IGNORE sprintf ( nm, "~~%s_%ld", vars [v].name, n ) ;
203
		    p->name = nm ;
204
		    if ( add_to_var_hash ( p, s ) ) {
205
			input_error ( "%s has already been defined", nm ) ;
206
		    }
207
		}
208
		bv->table [i] = p ;
209
	    }
210
	}
211
    }
212
    return ;
213
}
214
 
215
 
216
/*
217
    SET AN ENTRY IN A BINDING
218
 
219
    The nth entry of the vth variable sort of the binding bt is set to
220
    the construct p.
221
*/
222
 
223
static void set_binding
224
    PROTO_N ( ( bt, v, n, p ) )
225
    PROTO_T ( binding *bt X long v X long n X construct *p )
226
{
227
    binding *b ;
228
    if ( v < 0 || v >= no_var ) {
229
	input_error ( "Illegal binding sort" ) ;
230
	return ;
231
    }
232
    b = bt + v ;
233
    if ( n >= b->max_no || n < 0 ) {
234
	input_error ( "Object number %ld (%s) too big", n, vars [v].name ) ;
235
	return ;
236
    }
237
    if ( b->table [n] ) {
238
	input_error ( "Object %ld (%s) already bound", n, vars [v].name ) ;
239
	return ;
240
    }
241
    b->table [n] = p ;
242
    return ;
243
}
244
 
245
 
246
/*
247
    FIND AN ENTRY IN A BINDING
248
 
249
    The nth entry of the vth variable sort of the binding bt is returned.
250
*/
251
 
252
construct *find_binding
253
    PROTO_N ( ( bt, v, n ) )
254
    PROTO_T ( binding *bt X long v X long n )
255
{
256
    binding *b ;
257
    if ( v < 0 || v >= no_var ) {
258
	input_error ( "Illegal binding sort" ) ;
259
	return ( null ) ;
260
    }
261
    b = bt + v ;
262
    if ( n >= b->max_no || n < 0 ) {
263
	input_error ( "Object number %ld (%s) too big", n, vars [v].name ) ;
264
	return ( null ) ;
265
    }
266
    return ( b->table [n] ) ;
267
}
268
 
269
 
270
/*
271
    DECODE AN ALIGNED STRING
272
 
273
    An aligned string (in an external name) is decoded and returned
274
    as an array of characters.
275
*/
276
 
277
char *de_aligned_string
278
    PROTO_Z ()
279
{
280
    char *p ;
281
    long i, n = tdf_int () ;
282
    if ( n != 8 ) input_error ( "Only 8-bit strings allowed" ) ;
283
    n = tdf_int () ;
284
    byte_align () ;
285
    p = alloc_nof ( char, n + 1 ) ;
286
    for ( i = 0 ; i < n ; i++ ) p [i] = ( char ) fetch ( 8 ) /* LINT */ ;
287
    p [n] = 0 ;
288
    byte_align () ;
289
    return ( p ) ;
290
}
291
 
292
 
293
/*
294
    FLAG INDICATING SKIP PASS
295
 
296
    This flag is true if we are in the skip pass of a set of equations
297
    (primarily token definitions).
298
*/
299
 
300
boolean in_skip_pass = 0 ;
301
 
302
 
303
/*
304
    DECODE A SET OF EQUATIONS
305
 
306
    A set of equations with decoding routine f is decoded.  If f is null
307
    the equations are stepped over, otherwise they are decoded.
308
*/
309
 
310
typedef void ( *equation_func ) PROTO_S ( ( void ) ) ;
311
 
312
static void de_equation
313
    PROTO_N ( ( f ) )
314
    PROTO_T ( equation_func f )
315
{
316
    long i, n ;
317
    binding *old_binding = null ;
318
 
319
    /* Read new bindings */
320
    n = tdf_int () ;
321
    if ( n ) {
322
	if ( n != no_var ) input_error ( "Number of local variables wrong" ) ;
323
	old_binding = crt_binding ;
324
	crt_binding = new_binding () ;
325
	for ( i = 0 ; i < n ; i++ ) {
326
	    long sz = tdf_int () ;
327
	    set_binding_size ( crt_binding, i, sz ) ;
328
	}
329
	n = tdf_int () ;
330
	if ( n != no_var ) input_error ( "Number of linkage units wrong" ) ;
331
	for ( i = 0 ; i < n ; i++ ) {
332
	    long j, no_links = tdf_int () ;
333
	    for ( j = 0 ; j < no_links ; j++ ) {
334
		long inner = tdf_int () ;
335
		long outer = tdf_int () ;
336
		construct *p = find_binding ( old_binding, i, outer ) ;
337
		set_binding ( crt_binding, i, inner, p ) ;
338
	    }
339
	}
340
	complete_binding ( crt_binding ) ;
341
    } else {
342
	n = tdf_int () ;
343
	if ( n ) input_error ( "Number of linkage units wrong" ) ;
344
    }
345
 
346
    /* Read the actual equation */
347
    n = BYTESIZE * tdf_int () ;
348
    byte_align () ;
349
    if ( f == null ) {
350
	input_skip ( n ) ;
351
    } else {
352
	long end_posn = input_posn () + n ;
353
	decode_status = 2 ;
354
	( *f ) () ;
355
	byte_align () ;
356
	decode_status = 1 ;
357
	if ( input_posn () != end_posn ) input_error ( "Unit length wrong" ) ;
358
    }
359
 
360
    /* Restore the old bindings */
361
    if ( old_binding ) {
362
	free_binding ( crt_binding ) ;
363
	crt_binding = old_binding ;
364
    }
365
    return ;
366
}
367
 
368
 
369
/*
370
    DECODE A CAPSULE
371
 
372
    An entire TDF capsule is decoded.
373
*/
374
 
375
void de_capsule
376
    PROTO_Z ()
377
{
378
    long i, n ;
379
    long no_eqn ;
380
    char **eqns ;
381
 
382
    /* Reset variables */
383
    al_tag_var = -1 ;
384
    tag_var = -2 ;
385
    tok_var = -3 ;
386
    spare_binding = null ;
387
    have_version = 0 ;
388
    decode_status = 0 ;
389
 
390
    /* Read magic number */
391
    de_magic ( MAGIC_NUMBER ) ;
392
 
393
    /* Read equation names */
394
    no_eqn = tdf_int () ;
395
    eqns = alloc_nof ( char *, no_eqn ) ;
396
    for ( i = 0 ; i < no_eqn ; i++ ) eqns [i] = de_aligned_string () ;
397
 
398
    /* Read variable sort names */
399
    no_var = tdf_int () ;
400
    vars = alloc_nof ( var_sort, no_var ) ;
401
    crt_binding = new_binding () ;
402
    for ( i = 0 ; i < no_var ; i++ ) {
403
	char *s = de_aligned_string () ;
404
	long sz = tdf_int () ;
405
	vars [i].name = s ;
406
	if ( streq ( s, LINK_al_tag ) ) {
407
	    vars [i].sortnum = SORT_al_tag ;
408
	    al_tag_var = i ;
409
	} else if ( streq ( s, LINK_tag ) ) {
410
	    vars [i].sortnum = SORT_tag ;
411
	    tag_var = i ;
412
	} else if ( streq ( s, LINK_token ) ) {
413
	    vars [i].sortnum = SORT_token ;
414
	    tok_var = i ;
415
	} else {
416
	    vars [i].sortnum = SORT_unknown ;
417
	}
418
	set_binding_size ( crt_binding, i, sz ) ;
419
    }
420
 
421
    /* Read external names */
422
    decode_status = 1 ;
423
    n = tdf_int () ;
424
    if ( n != no_var ) input_error ( "Number of variable sorts wrong" ) ;
425
    for ( i = 0 ; i < no_var ; i++ ) {
426
	static int un = 0 ;
427
	sortname si = vars [i].sortnum ;
428
	long j, no_links = tdf_int () ;
429
	boolean reject = 0 ;
430
	if ( extract_tokdecs && i != tok_var ) reject = 1 ;
431
	for ( j = 0 ; j < no_links ; j++ ) {
432
	    construct *p, *q ;
433
	    long id = tdf_int () ;
434
	    n = de_external_bits () ;
435
	    byte_align () ;
436
	    p = make_construct ( si ) ;
437
	    if ( extract_tokdecs ) {
438
		( sort_count [ si ] )-- ;
439
		p->encoding = -1 ;
440
	    }
441
 
442
	    if ( n == ENC_string_extern ) {
443
		/* Simple external name */
444
		boolean name_ok = 1 ;
445
		node *ns = de_node ( "=" ) ;
446
		if ( reject ) {
447
		    free_node ( ns ) ;
448
		} else {
449
		    /* Check that name is a valid identifier */
450
		    char *nm = ns->cons->name ;
451
		    if ( alpha ( *nm ) ) {
452
			long k ;
453
			for ( k = 1 ; k < ns->cons->encoding ; k++ ) {
454
			    char c = nm [k] ;
455
			    if ( !alphanum ( c ) ) name_ok = 0 ;
456
			}
457
		    } else {
458
			name_ok = 0 ;
459
		    }
460
		    if ( name_ok ) {
461
			/* Use external name as internal name */
462
			p->name = nm ;
463
			if ( !is_local_name ( nm ) ) {
464
			    p->ename = new_node () ;
465
			    p->ename->cons = &false_cons ;
466
			}
467
		    } else {
468
			/* Make up internal name */
469
			p->name = alloc_nof ( char, 32 ) ;
470
			IGNORE sprintf ( p->name, "~~extern_%d", un++ ) ;
471
			if ( !is_local_name ( nm ) ) {
472
			    p->ename = new_node () ;
473
			    p->ename->cons = &true_cons ;
474
			    p->ename->son = ns ;
475
			}
476
		    }
477
		}
478
	    } else if ( n == ENC_unique_extern ) {
479
		/* Unique external name */
480
		node *nu = de_node ( "%[=]" ) ;
481
		if ( reject ) {
482
		    free_node ( nu ) ;
483
		} else {
484
		    /* Make up internal name */
485
		    p->name = alloc_nof ( char, 32 ) ;
486
		    IGNORE sprintf ( p->name, "~~extern_%d", un++ ) ;
487
		    p->ename = new_node () ;
488
		    p->ename->cons = &true_cons ;
489
		    p->ename->son = nu ;
490
		}
491
	    } else if ( n == ENC_chain_extern ) {
492
		/* Chain external name */
493
		node *nc = de_node ( "=i" ) ;
494
		if ( reject ) {
495
		    free_node ( nc ) ;
496
		} else {
497
		    /* Make up internal name */
498
		    p->name = alloc_nof ( char, 32 ) ;
499
		    IGNORE sprintf ( p->name, "~~extern_%d", un++ ) ;
500
		    p->ename = new_node () ;
501
		    p->ename->cons = &true_cons ;
502
		    p->ename->son = nc ;
503
		}
504
	    } else {
505
		input_error ( "Illegal EXTERN value, %ld", n ) ;
506
	    }
507
 
508
	    /* Add construct to tables */
509
	    if ( reject ) {
510
		set_binding ( crt_binding, i, id, p ) ;
511
		p->next = garbage ;
512
		garbage = p ;
513
	    } else {
514
		q = add_to_var_hash ( p, si ) ;
515
		if ( q ) {
516
		    if ( !extract_tokdecs ) {
517
			( sort_count [ si ] )-- ;
518
			if ( q->encoding == -1 ) {
519
			    q->encoding = ( sort_count [ si ] )++ ;
520
			}
521
		    }
522
		    set_binding ( crt_binding, i, id, q ) ;
523
		    p->next = garbage ;
524
		    garbage = p ;
525
		} else {
526
		    set_binding ( crt_binding, i, id, p ) ;
527
		}
528
	    }
529
	}
530
    }
531
 
532
    /* Complete the bindings */
533
    complete_binding ( crt_binding ) ;
534
 
535
    /* Read the equations */
536
    n = tdf_int () ;
537
    if ( n != no_eqn ) input_error ( "Number of equations wrong" ) ;
538
    for ( i = 0 ; i < no_eqn ; i++ ) {
539
	char *eq = eqns [i] ;
540
	long j, no_units = tdf_int () ;
541
	if ( no_units ) {
542
	    boolean skip_pass = 0 ;
543
	    equation_func f = null ;
544
 
545
	    /* Find equation decoding routine */
546
	    if ( extract_tokdecs ) {
547
		if ( streq ( eq, LINK_tokdec_props ) ) {
548
		    f = de_tokdec ;
549
		} else if ( streq ( eq, LINK_tokdef_props ) ) {
550
		    f = de_tokdef ;
551
		    in_skip_pass = 1 ;
552
		}
553
	    } else {
554
		if ( streq ( eq, LINK_al_tagdef_props ) ) {
555
		    f = de_aldef ;
556
		} else if ( streq ( eq, LINK_tagdec_props ) ) {
557
		    f = de_tagdec ;
558
		} else if ( streq ( eq, LINK_tagdef_props ) ) {
559
		    f = de_tagdef ;
560
		} else if ( streq ( eq, LINK_tokdec_props ) ) {
561
		    f = de_tokdec ;
562
		} else if ( streq ( eq, LINK_tokdef_props ) ) {
563
		    f = de_tokdef ;
564
		    skip_pass = 1 ;
565
		} else if ( streq ( eq, LINK_version_props ) ) {
566
		    f = de_version ;
567
		}
568
	    }
569
 
570
	    /* Skip pass */
571
	    if ( skip_pass ) {
572
		long old_posn = input_posn () ;
573
		in_skip_pass = 1 ;
574
		for ( j = 0 ; j < no_units ; j++ ) de_equation ( f ) ;
575
		in_skip_pass = 0 ;
576
		input_goto ( old_posn ) ;
577
	    }
578
 
579
	    /* Main pass */
580
	    for ( j = 0 ; j < no_units ; j++ ) de_equation ( f ) ;
581
	    in_skip_pass = 0 ;
582
	}
583
    }
584
 
585
    /* Free unused constructs */
586
    free_construct ( &garbage ) ;
587
    return ;
588
}
589
 
590
 
591
/*
592
    NAME OF CURRENT CAPSULE
593
 
594
    The current capsule of a library is recorded to use in error messages.
595
*/
596
 
597
char *capname = null ;
598
 
599
 
600
/*
601
    DECODE A TDF LIBRARY
602
*/
603
 
604
void de_library
605
    PROTO_Z ()
606
{
607
    long old_posn ;
608
    long i, no_cap ;
609
    boolean old_extract = extract_tokdecs ;
610
 
611
    de_magic ( MAGIC_LINK_NUMBER ) ;
612
    IGNORE tdf_int () ;
613
    no_cap = tdf_int () ;
614
    old_posn = input_posn () ;
615
 
616
    /* First pass - extract all token declaration */
617
    extract_tokdecs = 1 ;
618
    for ( i = 0 ; i < no_cap ; i++ ) {
619
	long end_posn ;
620
	long j, n ;
621
	decode_status = 0 ;
622
	n = tdf_int () ;
623
	if ( n != 8 ) input_error ( "Only 8-bit strings allowed" ) ;
624
	n = tdf_int () ;
625
	byte_align () ;
626
	capname = alloc_nof ( char, n + 1 ) ;
627
	for ( j = 0 ; j < n ; j++ ) {
628
	    capname [j] = ( char ) fetch ( 8 ) ; /* LINT */
629
	}
630
	capname [n] = 0 ;
631
	n = BYTESIZE * tdf_int () ;
632
	byte_align () ;
633
	end_posn = input_posn () + n ;
634
	de_capsule () ;
635
	byte_align () ;
636
	if ( input_posn () != end_posn ) {
637
	    input_error ( "Capsule length wrong" ) ;
638
	}
639
	capname = null ;
640
    }
641
 
642
    /* Second pass - if the first pass didn't do everything */
643
    extract_tokdecs = old_extract ;
644
    if ( extract_tokdecs ) return ;
645
    input_goto ( old_posn ) ;
646
    for ( i = 0 ; i < no_cap ; i++ ) {
647
	long end_posn ;
648
	long j, n ;
649
	decode_status = 0 ;
650
	n = tdf_int () ;
651
	if ( n != 8 ) input_error ( "Only 8-bit strings allowed" ) ;
652
	n = tdf_int () ;
653
	byte_align () ;
654
	capname = alloc_nof ( char, n + 1 ) ;
655
	for ( j = 0 ; j < n ; j++ ) {
656
	    capname [j] = ( char ) fetch ( 8 ) ; /* LINT */
657
	}
658
	capname [n] = 0 ;
659
	n = BYTESIZE * tdf_int () ;
660
	byte_align () ;
661
	end_posn = input_posn () + n ;
662
	de_capsule () ;
663
	byte_align () ;
664
	if ( input_posn () != end_posn ) {
665
	    input_error ( "Capsule length wrong" ) ;
666
	}
667
	capname = null ;
668
    }
669
    return ;
670
}