Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
6 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
6 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:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 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;
6 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;
6 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 "calculus.h"
63
#include "error.h"
64
#include "lex.h"
65
#include "syntax.h"
66
#include "xalloc.h"
67
 
68
 
69
/*
6 7u83 70
 * INPUT FLAGS
71
 *
72
 * The flag new_format is set to true to indicate the new input format.
73
 * The flags allow_stack and allow_vec are set to false to suppress the
74
 * stack and vector operations respectively.
75
 */
2 7u83 76
 
6 7u83 77
int new_format = 1;
78
int allow_stack = 1;
79
int allow_vec = 1;
2 7u83 80
 
81
 
82
/*
6 7u83 83
 * CHECK STACK FLAG
84
 *
85
 * This routine is called if the STACK keyword is encountered to check the
86
 * value of allow_stack.
87
 */
2 7u83 88
 
6 7u83 89
static int
90
check_stack(int t)
2 7u83 91
{
6 7u83 92
    if (!allow_stack) {
93
	error(ERROR_SERIOUS, "Stack operations have been suppressed");
94
	allow_stack = 1;
2 7u83 95
    }
6 7u83 96
    return(t);
2 7u83 97
}
98
 
99
 
100
/*
6 7u83 101
 * CHECK VECTOR FLAG
102
 *
103
 * This routine is called if the VEC or VEC_PTR keywords are encountered
104
 * to check the value of allow_vec.
105
 */
2 7u83 106
 
6 7u83 107
static int
108
check_vec(int t)
2 7u83 109
{
6 7u83 110
    if (!allow_vec) {
111
	error(ERROR_SERIOUS, "Vector operations have been suppressed");
112
	allow_vec = 1;
2 7u83 113
    }
6 7u83 114
    return(t);
2 7u83 115
}
116
 
117
 
118
/*
6 7u83 119
 * INPUT FILE
120
 *
121
 * This is the file from which the lexical routine read their input.
122
 */
2 7u83 123
 
6 7u83 124
static FILE *lex_input;
2 7u83 125
 
126
 
127
/*
6 7u83 128
 * PENDING BUFFER
129
 *
130
 * Pending characters are dealt with by means of this buffer.  pending
131
 * is set to the start of the buffer to indicate that there are no
132
 * characters pending, otherwise the pending characters are stored in
133
 * the buffer.  The buffer may need increasing in size if the look-ahead
134
 * required by the lexical analyser increases.
135
 */
2 7u83 136
 
6 7u83 137
static int pending_buff[12] = { '?' };
138
static int *pending = pending_buff;
2 7u83 139
 
140
 
141
/*
6 7u83 142
 * MAPPINGS AND DECLARATIONS FOR AUTOMATICALLY GENERATED SECTION
143
 *
144
 * These macros give the mappings between the actions used in the
145
 * automatically generated lexical analyser and the routines defined
146
 * in this file.
147
 */
2 7u83 148
 
6 7u83 149
static int read_char(void);
150
static int read_comment(void);
151
static int read_hex(int);
152
static int read_identifier(int);
153
static int read_number(int);
154
static int read_string(void);
2 7u83 155
 
6 7u83 156
#define get_comment(A, B)	read_comment()
157
#define get_hex(A, B, C)	read_hex(C)
158
#define get_identifier(A)	read_identifier(A)
159
#define get_number(A)		read_number(A)
160
#define get_string(A)		read_string()
161
#define get_stack()		check_stack(lex_stack)
162
#define get_vec()		check_vec(lex_vec)
163
#define get_vec_ptr()		check_vec(lex_vec_Hptr)
164
#define unknown_token(A)	lex_unknown
165
#define unread_char(A)		*(++pending) = (A)
2 7u83 166
 
167
 
168
/*
6 7u83 169
 * AUTOMATICALLY GENERATED SECTION
170
 *
171
 * The main body of the lexical analyser is automatically generated.
172
 */
2 7u83 173
 
174
#include "lexer.h"
175
 
176
 
177
/*
6 7u83 178
 * GET THE NEXT CHARACTER
179
 *
180
 * This routine reads the next character, either from the pending buffer
181
 * or from the input file.
182
 */
2 7u83 183
 
6 7u83 184
static int
185
read_char(void)
2 7u83 186
{
6 7u83 187
    int c;
188
    if (pending != pending_buff) {
189
	c = *(pending--);
2 7u83 190
    } else {
6 7u83 191
	c = fgetc(lex_input);
192
	if (c == '\n')crt_line_no++;
193
	if (c == EOF) return(LEX_EOF);
194
	c &= 0xff;
2 7u83 195
    }
6 7u83 196
    return(c);
2 7u83 197
}
198
 
199
 
200
/*
6 7u83 201
 * TOKEN BUFFER
202
 *
203
 * This buffer is used by read_token to hold the values of identifiers
204
 * and strings.  The variable token_value is also used to hold the
205
 * values of numbers.
206
 */
2 7u83 207
 
6 7u83 208
char token_buff[2000];
209
static char *token_end = token_buff + sizeof(token_buff);
210
char *first_comment = NULL;
211
number token_value;
2 7u83 212
 
213
 
214
/*
6 7u83 215
 * READ AN IDENTIFIER
216
 *
217
 * This routine reads an identifier beginning with a, returning the
218
 * corresponding lexical token.  Keywords are dealt with locally.
219
 */
2 7u83 220
 
6 7u83 221
static int
222
read_identifier(int a)
2 7u83 223
{
6 7u83 224
    int c = a, cl;
225
    char *t = token_buff;
2 7u83 226
    do {
6 7u83 227
	*(t++) = (char)c;
228
	if (t == token_end) {
229
		error(ERROR_FATAL, "Buffer overflow");
230
	}
231
	c = read_char();
232
	cl = lookup_char(c);
233
    } while (is_alphanum(cl));
234
    *t = 0;
235
    unread_char(c);
2 7u83 236
 
237
    /* Check for keywords */
6 7u83 238
    t = token_buff;
239
#define MAKE_KEYWORD(A, B)\
240
    if (streq(t,(A))) return(B);
2 7u83 241
#include "keyword.h"
6 7u83 242
    return(lex_identifier);
2 7u83 243
}
244
 
245
 
246
/*
6 7u83 247
 * READ A NUMBER
248
 *
249
 * This routine reads a number beginning with a, returning the
250
 * corresponding lexical token.  The actual value of the number is built
251
 * up in token_value.
252
 */
2 7u83 253
 
6 7u83 254
static int
255
read_number(int a)
2 7u83 256
{
6 7u83 257
    int c = a, cl;
258
    number n = 0;
2 7u83 259
    do {
6 7u83 260
	n = 10 * n + (number)(c - '0');
261
	c = read_char();
262
	cl = lookup_char(c);
263
    } while (is_digit(cl));
264
    unread_char(c);
265
    token_value = n;
266
    return(lex_number);
2 7u83 267
}
268
 
269
 
270
/*
6 7u83 271
 * READ A HEXADECIMAL NUMBER
272
 *
273
 * This routine reads a hexadecimal number beginning with a, returning the
274
 * corresponding lexical token.  The actual value of the number is built
275
 * up in token_value.
276
 */
2 7u83 277
 
6 7u83 278
static int
279
read_hex(int a)
2 7u83 280
{
6 7u83 281
    int c = a, cl;
282
    number n = 0;
2 7u83 283
    do {
6 7u83 284
	number d;
285
	if (c >= '0' && c <= '9') {
286
	    d = (number )(c - '0');
287
	} else if (c >= 'A' && c <= 'Z') {
288
	    d = (number)(c - 'A') + 10;
2 7u83 289
	} else {
6 7u83 290
	    d = (number)(c - 'a') + 10;
2 7u83 291
	}
6 7u83 292
	n = 16 * n + d;
293
	c = read_char();
294
	cl = lookup_char(c);
295
    } while (is_hexdigit(cl));
296
    unread_char(c);
297
    token_value = n;
298
    return(lex_number);
2 7u83 299
}
300
 
301
 
302
/*
6 7u83 303
 * READ A STRING
304
 *
305
 * This routine reads a string.  It is entered after the initial
306
 * quote has been read.  Note that there are no escape sequences.
307
 */
2 7u83 308
 
6 7u83 309
static int
310
read_string(void)
2 7u83 311
{
6 7u83 312
    int c;
313
    char *t = token_buff;
314
    while (c = read_char(), c != '"') {
315
	if (c == '\n' || c == LEX_EOF) {
316
	    error(ERROR_SERIOUS, "Unexpected end of string");
317
	    break;
2 7u83 318
	}
6 7u83 319
	*(t++) = (char)c;
320
	if (t == token_end) {
321
		error(ERROR_FATAL, "Buffer overflow");
322
	}
2 7u83 323
    }
6 7u83 324
    *t = 0;
325
    return(lex_string);
2 7u83 326
}
327
 
328
 
329
/*
6 7u83 330
 * READ A COMMENT
331
 *
332
 * This routine reads a C style comment, returning the lexical token
333
 * immediately following.  It is entered after the first two characters
334
 * have been read.
335
 */
2 7u83 336
 
6 7u83 337
static int
338
read_comment(void)
2 7u83 339
{
6 7u83 340
    int state = 0;
341
    char *t = token_buff;
342
    *(t++) = '/';
343
    *(t++) = '*';
344
    while (state != 2) {
345
	int c = read_char();
346
	if (c == LEX_EOF) {
347
	    error(ERROR_SERIOUS, "End of file in comment");
348
	    return(lex_eof);
2 7u83 349
	}
6 7u83 350
	if (c == '*') {
351
	    state = 1;
352
	} else if (state == 1 && c == '/') {
353
	    state = 2;
2 7u83 354
	} else {
6 7u83 355
	    state = 0;
2 7u83 356
	}
6 7u83 357
	*(t++) = (char)c;
358
	if (t == token_end) {
359
		t = token_buff + 2;
360
	}
2 7u83 361
    }
6 7u83 362
    *t = 0;
363
    if (first_comment == NULL) {
364
	    first_comment = xstrcpy(token_buff);
365
    }
366
    return(read_token());
2 7u83 367
}
368
 
369
 
370
/*
6 7u83 371
 * CURRENT TOKEN
372
 *
373
 * These variables are used by the parser to hold the current and former
374
 * lexical tokens.
375
 */
2 7u83 376
 
6 7u83 377
int crt_lex_token;
378
int saved_lex_token;
2 7u83 379
 
380
 
381
/*
6 7u83 382
 * PROCESS FILE
383
 *
384
 * This routine processes the input file nm.  If r is true then it is
385
 * processed using read_calculus, otherwise extra_calculus is used.
386
 */
2 7u83 387
 
6 7u83 388
void
389
process_file(char *nm, int r)
2 7u83 390
{
6 7u83 391
    crt_line_no = 1;
392
    crt_file_name = nm;
393
    lex_input = fopen(nm, "r");
394
    if (lex_input == NULL) {
395
	error(ERROR_SERIOUS, "Can't open input file, '%s'", nm);
396
	return;
2 7u83 397
    }
6 7u83 398
    ADVANCE_LEXER;
399
    if (r) {
400
	read_calculus();
2 7u83 401
    } else {
6 7u83 402
	extra_calculus();
2 7u83 403
    }
6 7u83 404
    if (crt_lex_token != lex_eof) {
405
	error(ERROR_SERIOUS, "Terminating due to syntax error");
2 7u83 406
    }
6 7u83 407
    fclose_v(lex_input);
408
    return;
2 7u83 409
}