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 "object.h"
63
#include "hash.h"
64
#include "type.h"
65
#include "utility.h"
66
 
67
 
68
/*
69
    FUNDAMENTAL TYPES
70
 
71
    These types represent the fundamental C types.
72
*/
73
 
7 7u83 74
#define BUILTIN(TYPE, NAME, VERS, ID)	type *TYPE
2 7u83 75
#include "builtin.h"
76
 
77
 
78
/*
79
    INITIALISE THE FUNDAMENTAL TYPES
80
 
81
    This routine initialises the fundamental C types.
82
*/
83
 
7 7u83 84
void
85
init_types(void)
2 7u83 86
{
7 7u83 87
#define BUILTIN(TYPE, NAME, VERS, ID)\
88
    TYPE = make_type(NAME, VERS, ID)
2 7u83 89
#include "builtin.h"
7 7u83 90
    return;
2 7u83 91
}
92
 
93
 
94
/*
95
    FIND THE NAMESPACE FOR A TYPE IDENTIFIER
96
 
97
    This routine returns the hash table for types with identifier id.  In
98
    most cases this is types, but it can be tags.  If flds is true the
99
    corresponding field hash table is returned.
100
*/
101
 
7 7u83 102
static hash_table *
103
find_namespace(int id, int fld)
2 7u83 104
{
7 7u83 105
    switch (id) {
106
	case TYPE_STRUCT_TAG:
107
	case TYPE_UNION_TAG:
108
	case TYPE_ENUM_TAG: {
109
	    return(fld ? tag_fields : tags);
2 7u83 110
	}
111
    }
7 7u83 112
    return(fld ? type_fields : types);
2 7u83 113
}
114
 
115
 
116
/*
117
    ALLOCATE A NEW TYPE
118
 
119
    This routine allocates space for a new type.
120
*/
121
 
7 7u83 122
static type *
123
new_type(void)
2 7u83 124
{
7 7u83 125
    type *t;
126
    alloc_variable(t, type, 1000);
127
    t->state = 0;
128
    return(t);
2 7u83 129
}
130
 
131
 
132
/*
133
    FIND A BASIC TYPE
134
 
135
    This routine maps the combination of basic type specifiers n to a
136
    type.
137
*/
138
 
7 7u83 139
type *
140
basic_type(unsigned n)
2 7u83 141
{
7 7u83 142
    type *t;
143
    switch (n) {
144
	case BTYPE_CHAR: {
145
	    t = type_char;
146
	    break;
2 7u83 147
	}
7 7u83 148
	case(BTYPE_SIGNED | BTYPE_CHAR): {
149
	    t = type_schar;
150
	    break;
2 7u83 151
	}
7 7u83 152
	case(BTYPE_UNSIGNED | BTYPE_CHAR): {
153
	    t = type_uchar;
154
	    break;
2 7u83 155
	}
7 7u83 156
	case BTYPE_SHORT:
157
	case(BTYPE_SHORT | BTYPE_INT): {
158
	    t = type_short;
159
	    break;
2 7u83 160
	}
7 7u83 161
	case(BTYPE_SIGNED | BTYPE_SHORT):
162
	case(BTYPE_SIGNED | BTYPE_SHORT | BTYPE_INT): {
163
	    t = type_sshort;
164
	    break;
2 7u83 165
	}
7 7u83 166
	case(BTYPE_UNSIGNED | BTYPE_SHORT):
167
	case(BTYPE_UNSIGNED | BTYPE_SHORT | BTYPE_INT): {
168
	    t = type_ushort;
169
	    break;
2 7u83 170
	}
7 7u83 171
	case BTYPE_INT: {
172
	    t = type_int;
173
	    break;
2 7u83 174
	}
7 7u83 175
	case BTYPE_SIGNED:
176
	case(BTYPE_SIGNED | BTYPE_INT): {
177
	    t = type_sint;
178
	    break;
2 7u83 179
	}
7 7u83 180
	case BTYPE_UNSIGNED:
181
	case(BTYPE_UNSIGNED | BTYPE_INT): {
182
	    t = type_uint;
183
	    break;
2 7u83 184
	}
7 7u83 185
	case BTYPE_LONG:
186
	case(BTYPE_LONG | BTYPE_INT): {
187
	    t = type_long;
188
	    break;
2 7u83 189
	}
7 7u83 190
	case(BTYPE_SIGNED | BTYPE_LONG):
191
	case(BTYPE_SIGNED | BTYPE_LONG | BTYPE_INT): {
192
	    t = type_slong;
193
	    break;
2 7u83 194
	}
7 7u83 195
	case(BTYPE_UNSIGNED | BTYPE_LONG):
196
	case(BTYPE_UNSIGNED | BTYPE_LONG | BTYPE_INT): {
197
	    t = type_ulong;
198
	    break;
2 7u83 199
	}
7 7u83 200
	case(BTYPE_LONG | BTYPE_LLONG):
201
	case(BTYPE_LONG | BTYPE_LLONG | BTYPE_INT): {
202
	    t = type_llong;
203
	    break;
2 7u83 204
	}
7 7u83 205
	case(BTYPE_SIGNED | BTYPE_LONG | BTYPE_LLONG):
206
	case(BTYPE_SIGNED | BTYPE_LONG | BTYPE_LLONG | BTYPE_INT): {
207
	    t = type_sllong;
208
	    break;
2 7u83 209
	}
7 7u83 210
	case(BTYPE_UNSIGNED | BTYPE_LONG | BTYPE_LLONG):
211
	case(BTYPE_UNSIGNED | BTYPE_LONG | BTYPE_LLONG | BTYPE_INT): {
212
	    t = type_ullong;
213
	    break;
2 7u83 214
	}
215
	default : {
7 7u83 216
	    if (n == BTYPE_FLOAT) {
217
		t = type_float;
218
	    } else if (n == BTYPE_DOUBLE) {
219
		t = type_double;
220
	    } else if (n == (BTYPE_LONG | BTYPE_DOUBLE)) {
221
		t = type_ldouble;
222
	    } else if (n == BTYPE_VOID) {
223
		t = type_void;
2 7u83 224
	    } else {
7 7u83 225
		error(ERR_SERIOUS, "Invalid type specifier");
226
		t = type_int;
2 7u83 227
	    }
7 7u83 228
	    break;
2 7u83 229
	}
230
    }
7 7u83 231
    return(t);
2 7u83 232
}
233
 
234
 
235
/*
236
    FIND A SPECIAL TYPE NAME
237
 
238
    This routine returns the special type described by the string s.
239
*/
240
 
7 7u83 241
type *
242
special_type(char *s)
2 7u83 243
{
7 7u83 244
    if (streq(s, "bottom")) return(type_bottom);
245
    if (streq(s, "printf")) return(type_printf);
246
    if (streq(s, "scanf")) return(type_scanf);
247
    error(ERR_SERIOUS, "Unknown special type '%s'", s);
248
    return(type_int);
2 7u83 249
}
250
 
251
 
252
/*
253
    MAKE A NEW TYPE
254
 
255
    This routine creates a type called nm (version vers) with identifier id.
256
*/
257
 
7 7u83 258
type *
259
make_type(char *nm, int vers, int id)
2 7u83 260
{
7 7u83 261
    type *t = new_type();
262
    object *p = make_object(nm, OBJ_TYPE);
263
    p->u.u_type = t;
264
    t->id = id;
265
    t->u.obj = p;
266
    t->v.obj2 = null;
267
    p = add_hash(find_namespace(id, 0), p, vers);
268
    return(p->u.u_type);
2 7u83 269
}
270
 
271
 
272
/*
273
    FIND A TYPE
274
 
275
    This routine looks up a type called nm (version vers) with identifier
276
    id.  If it does not exist then it creates one, also printing an error
277
    if force is true.
278
*/
279
 
7 7u83 280
type *
281
find_type(char *nm, int vers, int id, int force)
2 7u83 282
{
7 7u83 283
    type *t;
284
    object *p;
285
    hash_table *h = find_namespace(id, 0);
286
    p = search_hash(h, nm, vers);
287
    if (p == null) {
288
	if (force == 0) return(null);
289
	error(ERR_SERIOUS, "%s '%s' not defined", h->name, nm);
290
	return(make_type(nm, vers, id));
2 7u83 291
    }
7 7u83 292
    t = p->u.u_type;
293
    if (id != TYPE_GENERIC && id != t->id) {
294
	char *err = "%s '%s' used inconsistently (see %s, line %d)";
295
	error(ERR_SERIOUS, err, h->name, nm, p->filename, p->line_no);
2 7u83 296
    }
7 7u83 297
    return(t);
2 7u83 298
}
299
 
300
 
301
/*
302
    CREATE A NEW COMPOUND TYPE
303
 
304
    This routine creates a compound type with identifier id and subtype t.
305
*/
306
 
7 7u83 307
type *
308
make_subtype(type *t, int id)
2 7u83 309
{
7 7u83 310
    type *s = new_type();
311
    s->id = id;
312
    s->u.subtype = t;
313
    s->v.obj2 = null;
314
    return(s);
2 7u83 315
}
316
 
317
 
318
/*
319
    FORM A QUALIFIED TYPE
320
 
321
    This type forms a type from the incomplete type qualifier s and
322
    the type t.
323
*/
324
 
7 7u83 325
type *
326
inject_type(type *s, type *t)
2 7u83 327
{
7 7u83 328
    type *p = s;
329
    if (p == null) return(t);
330
    if (t) {
331
	while (p->u.subtype)p = p->u.subtype;
332
	p->u.subtype = t;
2 7u83 333
    }
7 7u83 334
    return(s);
2 7u83 335
}
336
 
337
 
338
/*
339
    CONSTRUCT A FIELD
340
 
341
    This routine creates a field called nm (version vers) which is a field
342
    of the structure of union s of type t.
343
*/
344
 
7 7u83 345
field *
346
make_field(char *nm, int vers, type *s, type *t)
2 7u83 347
{
7 7u83 348
    char *n;
349
    field *r;
350
    object *p = make_object(nm, OBJ_FIELD);
351
    alloc_variable(r, field, 1000);
352
    r->obj = p;
353
    r->stype = s;
354
    r->ftype = t;
355
    n = strchr(nm, '.');
356
    r->fname = (n ? n + 1 : nm);
357
    p->u.u_field = r;
358
    p = add_hash(find_namespace(s->id, 1), p, vers);
359
    return(p->u.u_field);
2 7u83 360
}
361
 
362
 
363
/*
364
    EXPAND A TYPE
365
 
366
    This routine expands the type t by replacing any typedefs by their
367
    definitions.
368
*/
369
 
7 7u83 370
type *
371
expand_type(type *t)
2 7u83 372
{
7 7u83 373
    while (t && t->id == TYPE_DEFINED) {
374
	t = t->v.next;
2 7u83 375
    }
7 7u83 376
    return(t);
2 7u83 377
}
378
 
379
 
380
/*
381
    AUXILIARY TYPE CHECKING ROUTINE
382
 
383
    This routine applies various checks to the type t.
384
*/
385
 
7 7u83 386
static type *
387
check_type_aux(type *t, int obj, int c, int ret)
2 7u83 388
{
7 7u83 389
    if (t == null) return(null);
390
    switch (t->id) {
391
	case TYPE_VOID: {
392
	    if ((obj || c) && !ret) {
393
		error(ERR_SERIOUS, "The type 'void' is incomplete");
2 7u83 394
	    }
7 7u83 395
	    break;
2 7u83 396
	}
7 7u83 397
	case TYPE_ARRAY: {
398
	    if (c && t->v.str [0] == 0) {
399
		error(ERR_SERIOUS, "Incomplete array type");
2 7u83 400
	    }
7 7u83 401
	    if (ret) {
402
		error(ERR_SERIOUS, "A function can't return an array");
2 7u83 403
	    }
7 7u83 404
	    t->u.subtype = check_type_aux(t->u.subtype, 1, 1, 0);
405
	    break;
2 7u83 406
	}
7 7u83 407
	case TYPE_BITFIELD: {
408
	    type *s = expand_type(t->u.subtype);
409
	    if (s) {
410
		switch (s->id) {
411
		    case TYPE_INT:
412
		    case TYPE_SIGNED:
413
		    case TYPE_UNSIGNED: {
414
			break;
2 7u83 415
		    }
416
		    default : {
7 7u83 417
			error(ERR_SERIOUS, "Non-integral bitfield type");
418
			break;
2 7u83 419
		    }
420
		}
421
	    }
7 7u83 422
	    break;
2 7u83 423
	}
7 7u83 424
	case TYPE_QUALIFIER: {
425
	    t->u.subtype = check_type_aux(t->u.subtype, obj, c, ret);
426
	    break;
2 7u83 427
	}
7 7u83 428
	case TYPE_LIST: {
429
	    t->u.subtype = check_type_aux(t->u.subtype, obj, c, ret);
430
	    t->v.next = check_type_aux(t->v.next, obj, c, ret);
431
	    break;
2 7u83 432
	}
7 7u83 433
	case TYPE_LVALUE: {
434
	    t->u.subtype = check_type_aux(t->u.subtype, 1, 0, ret);
435
	    break;
2 7u83 436
	}
7 7u83 437
	case TYPE_RVALUE: {
438
	    t->u.subtype = check_type_aux(t->u.subtype, 1, 1, ret);
439
	    break;
2 7u83 440
	}
7 7u83 441
	case TYPE_PROC: {
442
	    if (obj)error(ERR_SERIOUS, "Object type expected");
443
	    t->u.subtype = check_type_aux(t->u.subtype, 1, 1, 1);
444
	    if (t->v.next && t->v.next->v.next == null) {
2 7u83 445
		/* Check for '( void )' */
7 7u83 446
		type *s = t->v.next->u.subtype;
447
		if (s && s->id == TYPE_VOID)break;
2 7u83 448
	    }
7 7u83 449
	    t->v.next = check_type_aux(t->v.next, 1, 0, 0);
450
	    break;
2 7u83 451
	}
7 7u83 452
	case TYPE_PTR: {
453
	    t->u.subtype = check_type_aux(t->u.subtype, 0, 0, 0);
454
	    break;
2 7u83 455
	}
7 7u83 456
	case TYPE_DEFINED: {
457
	    t->v.next = check_type_aux(t->v.next, obj, c, ret);
458
	    break;
2 7u83 459
	}
460
    }
7 7u83 461
    return(t);
2 7u83 462
}
463
 
464
 
465
/*
466
    CHECK A TYPE
467
 
468
    This routine checks that the type t is a valid type for an object of
469
    type id.  It returns an equivalent type.
470
*/
471
 
7 7u83 472
type *
473
check_type(type *t, int id)
2 7u83 474
{
7 7u83 475
    if (t) {
476
	switch (id) {
477
	    case OBJ_EXP:
478
	    case OBJ_EXTERN: {
479
		t = check_type_aux(t, 1, 0, 0);
480
		break;
2 7u83 481
	    }
7 7u83 482
	    case OBJ_CONST:
483
	    case OBJ_FIELD: {
484
		t = check_type_aux(t, 1, 1, 0);
485
		break;
2 7u83 486
	    }
7 7u83 487
	    case OBJ_FUNC: {
488
		if (t->id != TYPE_PROC) {
489
		    error(ERR_SERIOUS, "Function type expected");
2 7u83 490
		}
7 7u83 491
		t = check_type_aux(t, 0, 0, 0);
492
		break;
2 7u83 493
	    }
7 7u83 494
	    case OBJ_TYPE:
495
	    case OBJ_MACRO:
496
	    case OBJ_STATEMENT: {
497
		t = check_type_aux(t, 0, 0, 0);
498
		break;
2 7u83 499
	    }
500
	}
501
    }
7 7u83 502
    return(t);
2 7u83 503
}