Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | 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 "tdf.h"
33
#include "cons_ops.h"
34
#include "info_ops.h"
35
#include "link_ops.h"
36
#include "par_ops.h"
37
#include "sort_ops.h"
38
#include "error.h"
39
#include "input.h"
40
#include "xalloc.h"
41
 
42
 
43
/*
44
    ARRAY OF KNOWN SORT NAMES
45
 
46
    This table gives the mapping from sort names to sort codes.  Sorts
47
    not in this list, or with a sort code of zero, have sort codes
48
    automatically generated for them.
49
*/
50
 
51
static struct {
52
    char *name ;
53
    int code ;
54
} sort_names [] = {
55
    /* Built-in sorts */
56
    { "tdfint", 'i' },
57
    { "tdfstring", '$' },
58
    { "tdfident", '=' },
59
    { "tdfbool", 'j' },
60
    { "bitstream", '@' },
61
    { "bytestream", '#' },
62
 
63
    /* Basic sorts */
64
    { "access", 'u' },
65
    { "alignment", 'a' },
66
    { "al_tag", 'A' },
67
    { "bitfield_variety", 'B' },
68
    { "bool", 'b' },
69
    { "callees", 'q' },
70
    { "error_code", 'c' },
71
    { "error_treatment", 'e' },
72
    { "exp", 'x' },
73
    { "floating_variety", 'f' },
74
    { "label", 'l' },
75
    { "nat", 'n' },
76
    { "ntest", 'N' },
77
    { "procprops", 'P' },
78
    { "rounding_mode", 'r' },
79
    { "shape", 'S' },
80
    { "signed_nat", 's' },
81
    { "string", 'X' },
82
    { "tag", 't' },
83
    { "token", 'T' },
84
    { "transfer_mode", 'm' },
85
    { "variety", 'v' },
86
 
87
    /* Unit sorts */
88
    { "al_tagdef", 0 },
89
    { "diag_tagdef", 0 },
90
    { "external", 0 },
91
    { "sortname", '~' },
92
    { "tagdec", 0 },
93
    { "tagdef", 0 },
94
    { "tokdec", 0 },
95
    { "tokdef", 0 },
96
 
97
    /* Diagnostic and linkage sorts */
98
    { "diag_descriptor", 'D' },
99
    { "diag_tag", 'I' },
100
    { "diag_tq", 'g' },
101
    { "diag_type", 'd' },
102
    { "filename", 'Q' },
103
    { "linkinfo", 'L' },
104
    { "sourcemark", 'M' },
105
    { "version", 'V' },
106
 
107
    /* New diagnostic sorts */
108
    { "dg", 'G' },
109
    { "dg_accessibility", 'o' },
110
    { "dg_append", 'H' },
111
    { "dg_bound", 'w' },
112
    { "dg_classmem", 'z' },
113
    { "dg_class_base", 'y' },
114
    { "dg_compilation", 'C' },
115
    { "dg_dim", 'O' },
116
    { "dg_discrim", 'K' },
117
    { "dg_enum", 'E' },
118
    { "dg_field", 'R' },
119
    { "dg_filename", 'U' },
120
    { "dg_idname", 'Y' },
121
    { "dg_macro", 'Z' },
122
    { "dg_name", 'h' },
123
    { "dg_namelist", 'k' },
124
    { "dg_param", 'p' },
125
    { "dg_param_mode", 0 },
126
    { "dg_qualifier", 0 },
127
    { "dg_sourcepos", 'W' },
128
    { "dg_tag", 'J' },
129
    { "dg_type", 0 },
130
    { "dg_variant", 0 },
131
    { "dg_varpart", 0 },
132
    { "dg_virtuality", 0 }
133
} ;
134
 
135
#define NO_BUILTIN_SORTS	6
136
#define NO_SORTS		array_size ( sort_names )
137
 
138
 
139
/*
140
    LIST OF ALL SORTS
141
 
142
    A list of all sorts (in alphabetical order) is maintained.
143
*/
144
 
145
static LIST ( SORT ) all_sorts = NULL_list ( SORT ) ;
146
 
147
 
148
/*
149
    DEFINE A SORT
150
 
151
    This routine defines the sort s to be info.
152
*/
153
 
154
static void define_sort
155
    PROTO_N ( ( s, info, code ) )
156
    PROTO_T ( SORT s X SORT_INFO info X int code )
157
{
158
    static int next_code = 1 ;
159
    SORT_INFO old = DEREF_info ( sort_info ( s ) ) ;
160
    if ( !IS_NULL_info ( old ) ) {
161
	string nm = DEREF_string ( sort_name ( s ) ) ;
162
	error ( ERROR_SERIOUS, "Sort '%s' already defined", nm ) ;
163
    }
164
    COPY_info ( sort_info ( s ), info ) ;
165
    if ( code == 0 ) code = next_code++ ;
166
    COPY_int ( sort_code ( s ), code ) ;
167
    return ;
168
}
169
 
170
 
171
/*
172
    FIND A SORT
173
 
174
    This routine looks up a sort named nm, creating it if it does not
175
    already exist if create is true.
176
*/
177
 
178
SORT find_sort
179
    PROTO_N ( ( nm, create ) )
180
    PROTO_T ( string nm X int create )
181
{
182
    SORT s ;
183
    string cnm ;
184
    SORT_INFO info = NULL_info ;
185
    LIST ( SORT ) p = all_sorts ;
186
    LIST ( SORT ) q = NULL_list ( SORT ) ;
187
    while ( !IS_NULL_list ( p ) ) {
188
	int cmp ;
189
	string n ;
190
	s = DEREF_sort ( HEAD_list ( p ) ) ;
191
	n = DEREF_string ( sort_name ( s ) ) ;
192
	cmp = strcmp ( n, nm ) ;
193
	if ( cmp == 0 ) return ( s ) ;
194
	if ( cmp > 0 ) break ;
195
	q = p ;
196
	p = TAIL_list ( p ) ;
197
    }
198
    cnm = to_capitals ( nm ) ;
199
    MAKE_sort_basic ( nm, cnm, NULL, NULL, 0, 0, 0, 0, info, s ) ;
200
    if ( !create ) {
201
	error ( ERROR_SERIOUS, "Sort '%s' not defined", nm ) ;
202
	MAKE_info_builtin ( nm, info ) ;
203
	define_sort ( s, info, 0 ) ;
204
    }
205
    CONS_sort ( s, p, p ) ;
206
    if ( IS_NULL_list ( q ) ) {
207
	all_sorts = p ;
208
    } else {
209
	COPY_list ( PTR_TAIL_list ( q ), p ) ;
210
    }
211
    return ( s ) ;
212
}
213
 
214
 
215
/*
216
    MARK A CONSTRUCT AS USED
217
 
218
    This routine marks the parameter sorts of the constructs c with the
219
    value m.
220
*/
221
 
222
void mark_construct
223
    PROTO_N ( ( c, m ) )
224
    PROTO_T ( CONSTRUCT c X int m )
225
{
226
    if ( !IS_NULL_cons ( c ) ) {
227
	LIST ( PARAMETER ) p = DEREF_list ( cons_pars ( c ) ) ;
228
	while ( !IS_NULL_list ( p ) ) {
229
	    PARAMETER a = DEREF_par ( HEAD_list ( p ) ) ;
230
	    SORT s = DEREF_sort ( par_type ( a ) ) ;
231
	    mark_sort ( s, m ) ;
232
	    p = TAIL_list ( p ) ;
233
	}
234
    }
235
    return ;
236
}
237
 
238
 
239
/*
240
    MARK A SORT AS USED
241
 
242
    This routine marks the sort s and all its constructs with the value m.
243
*/
244
 
245
void mark_sort
246
    PROTO_N ( ( s, m ) )
247
    PROTO_T ( SORT s X int m )
248
{
249
    int mark = DEREF_int ( sort_mark ( s ) ) ;
250
    if ( mark != m ) {
251
	SORT_INFO info = DEREF_info ( sort_info ( s ) ) ;
252
	COPY_int ( sort_mark ( s ), m ) ;
253
	if ( !IS_NULL_info ( info ) ) {
254
	    switch ( TAG_info ( info ) ) {
255
		case info_basic_tag : {
256
		    LIST ( CONSTRUCT ) p ;
257
		    p = DEREF_list ( info_basic_cons ( info ) ) ;
258
		    while ( !IS_NULL_list ( p ) ) {
259
			CONSTRUCT c = DEREF_cons ( HEAD_list ( p ) ) ;
260
			mark_construct ( c, m ) ;
261
			p = TAIL_list ( p ) ;
262
		    }
263
		    break ;
264
		}
265
		case info_dummy_tag : {
266
		    CONSTRUCT c = DEREF_cons ( info_dummy_cons ( info ) ) ;
267
		    mark_construct ( c, m ) ;
268
		    break ;
269
		}
270
		case info_clist_tag :
271
		case info_slist_tag :
272
		case info_option_tag : {
273
		    SORT p = DEREF_sort ( info_clist_etc_arg ( info ) ) ;
274
		    mark_sort ( p, m ) ;
275
		    break ;
276
		}
277
	    }
278
	}
279
    }
280
    return ;
281
}
282
 
283
 
284
/*
285
    MARK ALL SORTS AS USED
286
 
287
    This routine marks all sorts with the value m.
288
*/
289
 
290
void mark_all_sorts
291
    PROTO_N ( ( m ) )
292
    PROTO_T ( int m )
293
{
294
    LIST ( SORT ) p = all_sorts ;
295
    while ( !IS_NULL_list ( p ) ) {
296
	SORT s = DEREF_sort ( HEAD_list ( p ) ) ;
297
	COPY_int ( sort_mark ( s ), m ) ;
298
	p = TAIL_list ( p ) ;
299
    }
300
    return ;
301
}
302
 
303
 
304
/*
305
    DOES A STRING HAVE A GIVEN ENDING?
306
 
307
    This routine checks whether the string s ends in the string e.  If so
308
    it returns a copy of s with this ending removed.  Otherwise it returns
309
    the null string.
310
*/
311
 
312
string ends_in
313
    PROTO_N ( ( s, e ) )
314
    PROTO_T ( string s X string e )
315
{
316
    unsigned n = ( unsigned ) strlen ( s ) ;
317
    unsigned m = ( unsigned ) strlen ( e ) ;
318
    if ( n >= m ) {
319
	unsigned d = n - m ;
320
	if ( streq ( s + d, e ) ) {
321
	    s = xstrcpy ( s ) ;
322
	    s [d] = 0 ;
323
	    return ( s ) ;
324
	}
325
    }
326
    return ( NULL ) ;
327
}
328
 
329
 
330
/*
331
    CONVERT A STRING TO CAPITALS
332
 
333
    This routine returns a copy of the string s with all the lower case
334
    letters converted to upper case.
335
*/
336
 
337
string to_capitals
338
    PROTO_N ( ( s ) )
339
    PROTO_T ( string s )
340
{
341
    char c ;
342
    string t ;
343
    s = xstrcpy ( s ) ;
344
    t = s ;
345
    while ( c = *t, c != 0 ) {
346
	if ( c >= 'a' && c <= 'z' ) {
347
	    *t = ( char ) ( 'A' + ( c - 'a' ) ) ;
348
	}
349
	t++ ;
350
    }
351
    return ( s ) ;
352
}
353
 
354
 
355
/*
356
    DEFINE A BASIC SORT
357
 
358
    This routine defines the basic sort s to have b bits (extended if e
359
    is true) and constructs p.
360
*/
361
 
362
void basic_sort
363
    PROTO_N ( ( s, b, e, p ) )
364
    PROTO_T ( SORT s X unsigned b X unsigned e X LIST ( CONSTRUCT ) p )
365
{
366
    int code = 0 ;
367
    SORT_INFO info ;
368
    string n = DEREF_string ( sort_name ( s ) ) ;
369
    if ( b == 0 && e == 0 && LENGTH_list ( p ) == 1 ) {
370
	/* Dummy sort */
371
	CONSTRUCT c = DEREF_cons ( HEAD_list ( p ) ) ;
372
	MAKE_info_dummy ( n, c, info ) ;
373
	code = 'F' ;
374
    } else {
375
	int i ;
376
	for ( i = NO_BUILTIN_SORTS ; i < NO_SORTS ; i++ ) {
377
	    if ( streq ( n, sort_names [i].name ) ) {
378
		code = sort_names [i].code ;
379
		break ;
380
	    }
381
	}
382
	MAKE_info_basic ( n, b, e, 0, p, NULL_cons, info ) ;
383
    }
384
    define_sort ( s, info, code ) ;
385
    return ;
386
}
387
 
388
 
389
/*
390
    CREATE A CONSTRUCT
391
 
392
    This routine creates a construct named nm with result sort s, parameter
393
    sorts p and encoding e.
394
*/
395
 
396
CONSTRUCT make_construct
397
    PROTO_N ( ( nm, e, s, p ) )
398
    PROTO_T ( string nm X unsigned e X SORT s X LIST ( PARAMETER ) p )
399
{
400
    CONSTRUCT c ;
401
    unsigned kind = KIND_simple ;
402
    if ( ends_in ( nm, "_apply_token" ) ) kind = KIND_token ;
403
    if ( ends_in ( nm, "_cond" ) ) kind = KIND_cond ;
404
    MAKE_cons_basic ( nm, e, s, p, kind, c ) ;
405
    return ( c ) ;
406
}
407
 
408
 
409
/*
410
    DEFINE A COMPOUND SORT
411
 
412
    This routine defines the compound sort s with standard suffix suff
413
    and sort type tag.
414
*/
415
 
416
void compound_sort
417
    PROTO_N ( ( s, suff, tag, code ) )
418
    PROTO_T ( SORT s X string suff X unsigned tag X int code )
419
{
420
    string nm = DEREF_string ( sort_name ( s ) ) ;
421
    string snm = ends_in ( nm, suff ) ;
422
    if ( snm ) {
423
	SORT_INFO info ;
424
	SORT t = find_sort ( snm, 1 ) ;
425
	MAKE_info_clist_etc ( tag, nm, t, info ) ;
426
	define_sort ( s, info, code ) ;
427
    } else {
428
	error ( ERROR_SERIOUS, "Sort '%s' doesn't end in '%s'", nm, suff ) ;
429
    }
430
    return ;
431
}
432
 
433
 
434
/*
435
    FIND A CONSTRUCT
436
 
437
    This routine searches for a construct named c in the sort s.
438
*/
439
 
440
CONSTRUCT find_construct
441
    PROTO_N ( ( s, c ) )
442
    PROTO_T ( SORT s X string c )
443
{
444
    SORT_INFO info = DEREF_info ( sort_info ( s ) ) ;
445
    if ( !IS_NULL_info ( info ) && IS_info_basic ( info ) ) {
446
	LIST ( CONSTRUCT ) p = DEREF_list ( info_basic_cons ( info ) ) ;
447
	while ( !IS_NULL_list ( p ) ) {
448
	    CONSTRUCT a = DEREF_cons ( HEAD_list ( p ) ) ;
449
	    string b = DEREF_string ( cons_name ( a ) ) ;
450
	    if ( streq ( b, c ) ) return ( a ) ;
451
	    p = TAIL_list ( p ) ;
452
	}
453
    }
454
    return ( NULL_cons ) ;
455
}
456
 
457
 
458
/*
459
    SET A CONSTRUCT KIND
460
 
461
    This routine sets the kind of the construct c of sort s to be kind.
462
*/
463
 
464
void set_special
465
    PROTO_N ( ( s, c, kind ) )
466
    PROTO_T ( SORT s X string c X unsigned kind )
467
{
468
    CONSTRUCT a = find_construct ( s, c ) ;
469
    if ( !IS_NULL_cons ( a ) ) {
470
	COPY_unsigned ( cons_kind ( a ), kind ) ;
471
    } else {
472
	string nm = DEREF_string ( sort_name ( s ) ) ;
473
	error ( ERROR_SERIOUS, "Can't find construct '%s' for sort '%s'",
474
		c, nm ) ;
475
    }
476
    return ;
477
}
478
 
479
 
480
/*
481
    FIND A CONSTRUCT OF A GIVEN KIND
482
 
483
    This routine searches for a construct of the sort s of the given kind.
484
*/
485
 
486
CONSTRUCT get_special
487
    PROTO_N ( ( s, kind ) )
488
    PROTO_T ( SORT s X unsigned kind )
489
{
490
    SORT_INFO info = DEREF_info ( sort_info ( s ) ) ;
491
    if ( !IS_NULL_info ( info ) && IS_info_basic ( info ) ) {
492
	LIST ( CONSTRUCT ) p = DEREF_list ( info_basic_cons ( info ) ) ;
493
	while ( !IS_NULL_list ( p ) ) {
494
	    CONSTRUCT a = DEREF_cons ( HEAD_list ( p ) ) ;
495
	    unsigned b = DEREF_unsigned ( cons_kind ( a ) ) ;
496
	    if ( b == kind ) return ( a ) ;
497
	    p = TAIL_list ( p ) ;
498
	}
499
    }
500
    return ( NULL_cons ) ;
501
}
502
 
503
 
504
/*
505
    DEFINE THE BUILT-IN SORTS
506
 
507
    This routine defines the built-in sorts.
508
*/
509
 
510
void builtin_sorts
511
    PROTO_Z ()
512
{
513
    int i ;
514
    for ( i = 0 ; i < NO_BUILTIN_SORTS ; i++ ) {
515
	SORT_INFO info ;
516
	char *nm = sort_names [i].name ;
517
	SORT s = find_sort ( nm, 1 ) ;
518
	MAKE_info_builtin ( nm, info ) ;
519
	define_sort ( s, info, sort_names [i].code ) ;
520
    }
521
    return ;
522
}
523
 
524
 
525
/*
526
    CHECK THE LIST OF ALL SORTS
527
 
528
    This routine checks the list of all sorts for undefined sorts,
529
    returning the reordered list.
530
*/
531
 
532
LIST ( SORT ) check_sorts
533
    PROTO_Z ()
534
{
535
    LIST ( SORT ) p = all_sorts ;
536
    while ( !IS_NULL_list ( p ) ) {
537
	SORT s = DEREF_sort ( HEAD_list ( p ) ) ;
538
	SORT_INFO info = DEREF_info ( sort_info ( s ) ) ;
539
	if ( IS_NULL_info ( info ) ) {
540
	    string nm = DEREF_string ( sort_name ( s ) ) ;
541
	    error ( ERROR_SERIOUS, "Sort '%s' not defined", nm ) ;
542
	    MAKE_info_builtin ( nm, info ) ;
543
	    define_sort ( s, info, 0 ) ;
544
	}
545
	if ( IS_info_basic ( info ) ) {
546
	    unsigned m = 0 ;
547
	    LIST ( CONSTRUCT ) q = DEREF_list ( info_basic_cons ( info ) ) ;
548
	    while ( !IS_NULL_list ( q ) ) {
549
		CONSTRUCT a = DEREF_cons ( HEAD_list ( q ) ) ;
550
		unsigned n = DEREF_unsigned ( cons_encode ( a ) ) ;
551
		if ( n > m ) m = n ;
552
		q = TAIL_list ( q ) ;
553
	    }
554
	    COPY_unsigned ( info_basic_max ( info ), m ) ;
555
	}
556
	p = TAIL_list ( p ) ;
557
    }
558
    return ( all_sorts ) ;
559
}
560
 
561
 
562
/*
563
    FIND FOREIGN SORTS
564
 
565
    This routine finds all the foreign sorts.
566
*/
567
 
568
LIST ( LINKAGE ) foreign_sorts
569
    PROTO_Z ()
570
{
571
    unsigned e = 0 ;
572
    LIST ( SORT ) p = all_sorts ;
573
    LIST ( LINKAGE ) q = NULL_list ( LINKAGE ) ;
574
    LIST ( PARAMETER ) pars = NULL_list ( PARAMETER ) ;
575
    SORT t = find_sort ( "sortname", 0 ) ;
576
    SORT_INFO info = DEREF_info ( sort_info ( t ) ) ;
577
    if ( IS_info_basic ( info ) ) {
578
	e = DEREF_unsigned ( info_basic_max ( info ) ) ;
579
    }
580
    while ( !IS_NULL_list ( p ) ) {
581
	SORT s = DEREF_sort ( HEAD_list ( p ) ) ;
582
	info = DEREF_info ( sort_info ( s ) ) ;
583
	if ( IS_info_basic ( info ) ) {
584
	    string nm = DEREF_string ( sort_name ( s ) ) ;
585
	    CONSTRUCT c = get_special ( s, KIND_token ) ;
586
	    if ( !IS_NULL_cons ( c ) ) {
587
		/* Sort can be tokenised */
588
		string snm = nm ;
589
		if ( streq ( nm, "alignment" ) ) {
590
		    snm = "alignment_sort" ;
591
		}
592
		c = find_construct ( t, snm ) ;
593
		if ( IS_NULL_cons ( c ) ) {
594
		    /* Doesn't have a sort name */
595
		    LINKAGE a ;
596
		    if ( streq ( nm, "diag_type" ) ) {
597
			snm = "diag_type" ;
598
		    } else if ( streq ( nm, "filename" ) ) {
599
			snm = "~diag_file" ;
600
		    } else {
601
			snm = to_capitals ( nm ) ;
602
		    }
603
		    MAKE_cons_basic ( snm, ++e, t, pars, KIND_foreign, c ) ;
604
		    MAKE_link_basic ( snm, s, a ) ;
605
		    CONS_link ( a, q, q ) ;
606
		}
607
	    } else {
608
		MAKE_cons_basic ( nm, ++e, t, pars, KIND_dummy, c ) ;
609
	    }
610
	    COPY_cons ( info_basic_sortname ( info ), c ) ;
611
	}
612
	p = TAIL_list ( p ) ;
613
    }
614
    q = REVERSE_list ( q ) ;
615
    return ( q ) ;
616
}
617
 
618
 
619
/*
620
    FIND A PARAMETER
621
 
622
    This routine returns the nth parameter of the construct c.
623
*/
624
 
625
PARAMETER find_param
626
    PROTO_N ( ( c, n ) )
627
    PROTO_T ( CONSTRUCT c X unsigned n )
628
{
629
    LIST ( PARAMETER ) p = DEREF_list ( cons_pars ( c ) ) ;
630
    while ( n ) {
631
	if ( IS_NULL_list ( p ) ) {
632
	    string nm = DEREF_string ( cons_name ( c ) ) ;
633
	    error ( ERROR_SERIOUS, "Bad parameter number for '%s'", nm ) ;
634
	    return ( NULL_par ) ;
635
	}
636
	p = TAIL_list ( p ) ;
637
	n-- ;
638
    }
639
    return ( DEREF_par ( HEAD_list ( p ) ) ) ;
640
}