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 <limits.h>
63
#include "system.h"
64
#include "c_types.h"
65
#include "hashid_ops.h"
66
#include "error.h"
67
#include "catalog.h"
68
#include "option.h"
69
#include "char.h"
70
#include "file.h"
71
#include "inttype.h"
72
#include "lex.h"
73
#include "literal.h"
74
#include "macro.h"
75
#include "preproc.h"
76
#include "syntax.h"
77
#include "table.h"
78
#include "ustring.h"
79
 
80
 
81
/*
82
    PORTABILITY TABLE ENTRIES
83
 
84
    This table describes the portability table entries.  The entries need
85
    to be keep in one-to-one correspondence with the PORT_* macros defined
86
    in table.h.
87
*/
88
 
7 7u83 89
PORT_ENTRY port_entry[] = {
90
	{ "char_bits", 0, 0, btype_none },		/* 0 */
91
	{ "short_bits", 0, 0, btype_none },		/* 1 */
92
	{ "int_bits", 0, 0, btype_none },		/* 2 */
93
	{ "long_bits", 0, 0, btype_none },		/* 3 */
94
	{ "longlong_bits", 1, 0, btype_none },		/* 4 */
95
	{ "max_bits", 1, UINT_MAX, btype_none },	/* 5 */
96
	{ "signed_range", 0, 0, btype_none },		/* 6 */
97
	{ "char_type", 0, 0, btype_none },		/* 7 */
98
	{ "exact_range", 1, 0, btype_none },		/* 8 */
99
	{ "ptr_int", 1, 0, btype_none },		/* 9 */
100
	{ "ptr_fn", 1, 0, btype_none },			/* 10 */
101
	{ "non_prototype_checks", 1, 0, btype_none },	/* 11 */
102
	{ "multibyte", 1, 0, btype_none }		/* 12 */
103
};
2 7u83 104
 
105
 
106
/*
107
    PARSE A PORTABILITY TABLE
108
 
109
    This routine parses and processes the portability table.  It returns
110
    the last token read.
111
*/
112
 
7 7u83 113
static int
114
parse_table(void)
2 7u83 115
{
7 7u83 116
	int t;
117
	PORT_ENTRY *p = port_entry;
118
	while (t = read_token(), t == lex_identifier) {
119
		int i;
120
		unsigned n = 0;
121
		HASHID nm = token_hashid;
122
		BASE_TYPE bt = btype_none;
123
		string us = DEREF_string(hashid_name_etc_text(nm));
124
		update_column();
2 7u83 125
 
7 7u83 126
		/* Check through table entries */
127
		for (i = 0; i < PORT_size; i++) {
128
			string ut = ustrlit(p[i].name);
129
			if (ustreq(us, ut)) {
130
				/* Entry found */
131
				if (p[i].set == 2) {
132
					report(crt_loc,
133
					       ERR_port_entry_redef(ut));
134
				}
135
				p[i].set = 2;
136
				break;
137
			}
2 7u83 138
		}
139
 
7 7u83 140
		/* Perform appropriate action */
141
		switch (i) {
2 7u83 142
 
7 7u83 143
		case PORT_char_bits:
144
		case PORT_short_bits:
145
		case PORT_int_bits:
146
		case PORT_long_bits:
147
		case PORT_llong_bits:
148
		case PORT_max_bits:
149
		case PORT_multibyte: {
150
			/* Deal with integral values */
151
			unsigned err = 0;
152
			t = read_token();
153
			update_column();
154
			if (t != lex_integer_Hlit) {
155
				return(t);
156
			}
157
			us = token_buff.start;
158
			n = (unsigned)eval_line_digits(us, &err);
159
			if (err) {
160
				report(crt_loc, ERR_lex_literal_bad(us));
161
			}
162
			break;
2 7u83 163
		}
164
 
7 7u83 165
		case PORT_signed_range:
166
			/* Deal with range values */
167
			t = read_token();
168
			update_column();
169
			if (t != lex_identifier) {
170
				return(t);
171
			}
172
			nm = token_hashid;
173
			us = DEREF_string(hashid_name_etc_text(nm));
174
			if (ustrseq(us, "maximum")) {
175
				bt = (btype_signed | btype_long);
176
			} else if (ustrseq(us, "symmetric")) {
177
				bt = btype_signed;
178
			} else {
179
				return(t);
180
			}
181
			break;
2 7u83 182
 
7 7u83 183
		case PORT_char_type:
184
			/* Deal with sign values */
185
			t = read_token();
186
			update_column();
187
			if (t != lex_identifier) {
188
				return(t);
189
			}
190
			nm = token_hashid;
191
			us = DEREF_string(hashid_name_etc_text(nm));
192
			if (ustrseq(us, "signed")) {
193
				bt = btype_signed;
194
			} else if (ustrseq(us, "unsigned")) {
195
				bt = btype_unsigned;
196
			} else if (ustrseq(us, "either")) {
197
				bt = btype_none;
198
			} else {
199
				return(t);
200
			}
201
			break;
2 7u83 202
 
7 7u83 203
		case PORT_ptr_int:
204
			/* Deal with type values */
205
			t = read_token();
206
			update_column();
207
			if (t != lex_identifier) {
208
				return(t);
209
			}
210
			nm = token_hashid;
211
			us = DEREF_string(hashid_name_etc_text(nm));
212
			if (ustrseq(us, "char")) {
213
				bt = btype_char;
214
			} else if (ustrseq(us, "short")) {
215
				bt = btype_short;
216
			} else if (ustrseq(us, "int")) {
217
				bt = btype_int;
218
			} else if (ustrseq(us, "long")) {
219
				bt = btype_long;
220
			} else if (ustrseq(us, "none")) {
221
				bt = btype_none;
222
			} else {
223
				return(t);
224
			}
225
			break;
226
 
227
		case PORT_exact_range:
228
		case PORT_ptr_fn:
229
		case PORT_non_proto:
230
			/* Deal with boolean values */
231
			t = read_token();
232
			update_column();
233
			if (t != lex_identifier) {
234
				return(t);
235
			}
236
			nm = token_hashid;
237
			us = DEREF_string(hashid_name_etc_text(nm));
238
			if (ustrseq(us, "no")) {
239
				n = 0;
240
			} else if (ustrseq(us, "yes")) {
241
				n = 1;
242
			} else {
243
				return(t);
244
			}
245
			break;
246
 
247
		default:
248
			/* Unknown entry identifier */
249
			return(t);
2 7u83 250
		}
7 7u83 251
		p[i].value = n;
252
		p[i].type = bt;
2 7u83 253
	}
7 7u83 254
	return(t);
2 7u83 255
}
256
 
257
 
258
/*
259
    READ THE PORTABILITY TABLE
260
 
261
    This routine reads and processes the portability table given by nm.
262
*/
263
 
7 7u83 264
void
265
read_table(string nm)
2 7u83 266
{
7 7u83 267
	int set = 0;
268
	PORT_ENTRY *p = port_entry;
2 7u83 269
 
7 7u83 270
	/* Read table */
271
	if (nm) {
272
		int i, t;
273
		input_name = nm;
274
		if (!open_input(text_mode)) {
275
			/* Can't open portability table */
276
			fail(ERR_fail_port(nm));
277
		} else {
278
			/* Read portability table */
279
			set = 1;
280
			pragma_number = 1;
281
			no_preproc_dir = 1;
282
			crt_buff_no = 0;
283
			IGNORE init_buffer(crt_buff_no);
284
			unread_char(char_newline);
285
			crt_loc.line--;
286
			t = parse_table();
287
			update_column();
288
			if (t != lex_eof) {
289
				/* Parse error in portability table */
290
				PPTOKEN *r = new_pptok();
291
				r->tok = t;
292
				token_parts(t, r);
293
				report(crt_loc, ERR_lex_parse(r));
294
				set = 0;
295
			} else {
296
				/* Check for undefined values */
297
				for (i = 0; i < PORT_size; i++) {
298
					if (p[i].set == 0) {
299
						string nt = ustrlit(p[i].name);
300
						report(crt_loc, ERR_port_entry_undef(nt));
301
						set = 0;
302
					}
303
				}
304
			}
305
			no_preproc_dir = 0;
306
			pragma_number = 0;
307
			close_input();
2 7u83 308
		}
309
	}
310
 
7 7u83 311
	/* Set values from table */
312
	if (set) {
313
		unsigned m;
314
		unsigned long n;
315
		BASE_INFO *q = basetype_info;
316
		set_char_sign(p[PORT_char_type].type);
317
		if (p[PORT_llong_bits].set == 2) {
318
			/* 'long long' types are allowed */
319
			set_option(OPT_longlong, (unsigned)OPTION_ALLOW);
320
			m = p[PORT_llong_bits].value;
321
		} else {
322
			/* 'long long' types are not allowed */
323
			m = p[PORT_long_bits].value;
324
			p[PORT_llong_bits].value = m;
2 7u83 325
		}
7 7u83 326
		if (p[PORT_exact_range].value == 0) {
327
			/* Find maximum number of bits in an integer */
328
			m = p[PORT_max_bits].value;
2 7u83 329
		}
7 7u83 330
		for (n = 0; n < ORDER_ntype; n++) {
331
			unsigned exact = p[PORT_exact_range].value;
332
			switch (n) {
333
			case ntype_char:
334
			case ntype_schar:
335
			case ntype_uchar:
336
				q[n].min_bits = p[PORT_char_bits].value;
337
				q[n].max_bits = m;
338
				break;
339
			case ntype_sshort:
340
			case ntype_ushort:
341
				q[n].min_bits = p[PORT_short_bits].value;
342
				q[n].max_bits = m;
343
				break;
344
			case ntype_sint:
345
			case ntype_uint:
346
			case ntype_none:
347
				q[n].min_bits = p[PORT_int_bits].value;
348
				q[n].max_bits = m;
349
				break;
350
			case ntype_slong:
351
			case ntype_ulong:
352
				q[n].min_bits = p[PORT_long_bits].value;
353
				q[n].max_bits = m;
354
				break;
355
			case ntype_sllong:
356
			case ntype_ullong:
357
				q[n].min_bits = p[PORT_llong_bits].value;
358
				q[n].max_bits = m;
359
				break;
360
			case ntype_ptrdiff_t:
361
			case ntype_size_t:
362
				q[n].min_bits = p[PORT_int_bits].value;
363
				q[n].max_bits = m;
364
				exact = 0;
365
				break;
366
			case ntype_wchar_t:
367
			case ntype_ellipsis:
368
				q[n].min_bits = p[PORT_char_bits].value;
369
				q[n].max_bits = m;
370
				exact = 0;
371
				break;
372
			}
373
			if (exact) {
374
				/* Exact integer range known */
375
				q[n].max_bits = q[n].min_bits;
376
			}
377
			if (q[n].sign & btype_signed) {
378
				/* Set signed type range */
379
				q[n].sign = p[PORT_signed_range].type;
380
			}
2 7u83 381
		}
7 7u83 382
		if (p[PORT_exact_range].value) {
383
			/* Set exact type ranges */
384
			set_exact_types();
2 7u83 385
		}
386
	}
7 7u83 387
	return;
2 7u83 388
}