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 "types.h"
63
#include "read_types.h"
64
#include "analyser.h"
65
#include "file.h"
66
#include "names.h"
67
#include "utility.h"
68
 
69
 
70
/*
71
    CURRENT AND PREVIOUS LINE NUMBERS
72
 
73
    The current line in the file is recorded.  The previous line (where
74
    any errors were likely to have been) is also saved.
75
*/
76
 
6 7u83 77
long crt_line_no = 1;
78
long line_no = 1;
2 7u83 79
 
80
 
81
/*
82
    FORM OF INPUT
83
 
84
    This flag controls whether the input should be lisp-like (default)
85
    or c-like.
86
*/
87
 
6 7u83 88
boolean func_input = 0;
2 7u83 89
 
90
 
91
/*
92
    ANALYSE FLAGS
93
 
94
    The looked_ahead flag is true to indicate that the next word has
95
    already been read.  The really_analyse flag is false to indicate
96
    that the next word may be ignored.
97
*/
98
 
6 7u83 99
boolean looked_ahead = 0;
100
static boolean really_analyse = 1;
2 7u83 101
 
102
 
103
/*
104
    INPUT BUFFER
105
 
106
    The input is read into a buffer.
107
*/
108
 
109
#define BUFFSIZE	5000
6 7u83 110
static char word_buff[BUFFSIZE];
2 7u83 111
 
112
 
113
/*
114
    LAST WORD READ
115
 
116
    The word just read from the input file is word.  It has length
117
    word_length and input type word_type.
118
*/
119
 
6 7u83 120
char *word = "";
121
long word_length;
122
int word_type = INPUT_EOF;
2 7u83 123
 
124
 
125
/*
126
    PENDING CHARACTER
127
 
128
    In reading a word we almost always read one too many character.
129
    This is stored in pending.  A value of 0 indicates that there is
130
    no pending character.
131
*/
132
 
6 7u83 133
static int pending = 0;
2 7u83 134
 
135
 
136
/*
137
    READ THE NEXT WORD
138
 
139
    The next word is read from the input file.
140
*/
141
 
6 7u83 142
void
143
read_word(void)
2 7u83 144
{
6 7u83 145
    int c;
146
    char *p;
147
    int negate = 0;
148
    unsigned base = 10;
2 7u83 149
 
150
    /* If we have looked ahead one, return last value */
6 7u83 151
    if (looked_ahead) {
152
	looked_ahead = 0;
153
	return;
2 7u83 154
    }
155
 
156
    /* Get the first letter */
6 7u83 157
    if (pending) {
158
	c = pending;
159
	if (c == EOF) {
160
	    word_type = INPUT_EOF;
161
	    return;
2 7u83 162
	}
6 7u83 163
	pending = 0;
2 7u83 164
    } else {
6 7u83 165
	c = getc(input);
166
	if (c == '\n')crt_line_no++;
2 7u83 167
    }
168
 
169
    /* Step over any white space and comments */
6 7u83 170
    while (white_space(c) || c == '#') {
171
	if (c == '#') {
2 7u83 172
	    /* Comments go to the end of the line */
6 7u83 173
	    while (c = getc(input), c != '\n') {
174
		if (c == EOF) {
175
		    is_fatal = 0;
176
		    input_error("End of file in comment");
177
		    word_type = INPUT_EOF;
178
		    pending = EOF;
179
		    return;
2 7u83 180
		}
181
	    }
6 7u83 182
	    crt_line_no++;
2 7u83 183
	} else {
6 7u83 184
	    c = getc(input);
185
	    if (c == '\n')crt_line_no++;
2 7u83 186
	}
187
    }
6 7u83 188
    line_no = crt_line_no;
2 7u83 189
 
190
    /* Check for end of file */
6 7u83 191
    if (c == EOF) {
192
	word_type = INPUT_EOF;
193
	pending = EOF;
194
	return;
2 7u83 195
    }
196
 
197
    /* Check for open brackets */
6 7u83 198
    if (c == '(') {
199
	word = "(";
200
	word_type = INPUT_OPEN;
201
	return;
2 7u83 202
    }
203
 
204
    /* Check for close brackets */
6 7u83 205
    if (c == ')') {
206
	word = ")";
207
	word_type = INPUT_CLOSE;
208
	return;
2 7u83 209
    }
210
 
6 7u83 211
    if (func_input) {
2 7u83 212
	/* Check for commas (c-like input only) */
6 7u83 213
	if (c == ',') {
214
	    word = ",";
215
	    word_type = INPUT_COMMA;
216
	    return;
2 7u83 217
	}
218
 
219
	/* Check for semicolons (c-like input only) */
6 7u83 220
	if (c == ';') {
221
	    word = ";";
222
	    word_type = INPUT_SEMICOLON;
223
	    return;
2 7u83 224
	}
225
    }
226
 
227
    /* Check for strings */
6 7u83 228
    if (c == '"') {
229
	boolean escaped;
230
	p = word_buff;
2 7u83 231
	do {
6 7u83 232
	    boolean ignore = 0;
233
	    escaped = 0;
234
	    c = getc(input);
235
	    if (c == '\n') {
236
		is_fatal = 0;
237
		input_error("New line in string");
238
		crt_line_no++;
239
		line_no = crt_line_no;
240
		ignore = 1;
2 7u83 241
	    }
6 7u83 242
	    if (c == '\\') {
243
		escaped = 1;
244
		c = getc(input);
245
		if (c == '\n') {
246
		    crt_line_no++;
247
		    line_no = crt_line_no;
248
		    ignore = 1;
249
		} else if (c == 'n') {
250
		    c = '\n';
251
		} else if (c == 't') {
252
		    c = '\t';
253
		} else if (octal_digit(c)) {
254
		    int e = (c - '0');
255
		    c = getc(input);
256
		    if (!octal_digit(c)) {
257
			is_fatal = 0;
258
			input_error("Invalid escape sequence");
259
			c = '0';
2 7u83 260
		    }
6 7u83 261
		    e = 8 * e + (c - '0');
262
		    c = getc(input);
263
		    if (!octal_digit(c)) {
264
			is_fatal = 0;
265
			input_error("Invalid escape sequence");
266
			c = '0';
2 7u83 267
		    }
6 7u83 268
		    e = 8 * e + (c - '0');
269
		    c = e;
270
		    if (c >= 256) {
271
			is_fatal = 0;
272
			input_error("Invalid escape sequence");
273
			c = 0;
2 7u83 274
		    }
275
		}
276
	    }
6 7u83 277
	    if (c == EOF) {
278
		is_fatal = 0;
279
		input_error("End of file in string");
280
		word_type = INPUT_EOF;
281
		pending = EOF;
282
		return;
2 7u83 283
	    }
6 7u83 284
	    if (!ignore)*(p++) = (char)c;
285
	} while (c != '"' || escaped);
286
	*(--p) = 0;
2 7u83 287
#if 0
6 7u83 288
	c = getc(input);
289
	if (c == '\n')crt_line_no++;
290
	if (!terminator(c)) {
291
	    is_fatal = 0;
292
	    input_error("Terminator character expected");
2 7u83 293
	}
6 7u83 294
	pending = c;
2 7u83 295
#endif
6 7u83 296
	word = word_buff;
297
	word_length = (int)(p - word);
298
	word_type = INPUT_STRING;
299
	return;
2 7u83 300
    }
301
 
302
    /* Check for words */
6 7u83 303
    if (alpha(c)) {
304
	p = word_buff;
2 7u83 305
	do {
6 7u83 306
	    *(p++) = (char)c;
307
	    c = getc(input);
308
	    if (c == '\n')crt_line_no++;
309
	} while (alphanum(c));
310
	*p = 0;
311
	if (!terminator(c)) {
312
	    is_fatal = 0;
313
	    input_error("Terminator character expected");
2 7u83 314
	}
6 7u83 315
	pending = c;
316
	word = word_buff;
317
	word_type = INPUT_WORD;
318
	return;
2 7u83 319
    }
320
 
321
    /* Check for bars */
6 7u83 322
    if (c == '|') {
323
	c = getc(input);
324
	if (c == '\n')crt_line_no++;
325
	if (!terminator(c)) {
326
	    is_fatal = 0;
327
	    input_error("Terminator character expected");
2 7u83 328
	}
6 7u83 329
	pending = c;
330
	word = "|" ;
331
	word_type = INPUT_BAR;
332
	return;
2 7u83 333
    }
334
 
335
    /* Check for a single dash and arrow */
6 7u83 336
    if (c == '-') {
337
	c = getc(input);
338
	if (c == '\n')crt_line_no++;
339
	if (terminator(c)) {
340
	    pending = c;
341
	    word = "-" ;
342
	    word_type = INPUT_BLANK;
343
	    return;
2 7u83 344
	}
6 7u83 345
	if (func_input && c == '>') {
346
	    pending = 0;
347
	    word = "->";
348
	    word_type = INPUT_ARROW;
349
	    return;
2 7u83 350
	}
6 7u83 351
	negate = 1;
2 7u83 352
    }
353
 
354
    /* Step over any signs */
6 7u83 355
    while (c == '-' || c == '+') {
356
	if (c == '-')negate = 1 - negate;
357
	c = getc(input);
358
	if (c == '\n')crt_line_no++;
2 7u83 359
    }
360
 
361
    /* Check for numbers */
6 7u83 362
    if (c == '0') {
363
	base = 8;
364
	c = getc(input);
365
	if (c == '\n')crt_line_no++;
366
	if (terminator(c)) {
367
	    pending = c;
368
	    word = "0";
369
	    word_type = INPUT_NUMBER;
370
	    return;
2 7u83 371
	}
6 7u83 372
	if (c == 'x' || c == 'X') {
373
	    base = 16;
374
	    c = getc(input);
375
	    if (c == '\n')crt_line_no++;
2 7u83 376
	}
6 7u83 377
    } else if (!dec_digit(c)) {
378
	is_fatal = 0;
379
	input_error("Illegal character, %c",(unsigned char)c);
380
	pending = 0;
381
	read_word();
382
	return;
2 7u83 383
    }
384
 
385
    /* Set up buffer */
6 7u83 386
    p = word_buff + BUFFSIZE;
387
    *(--p) = 0;
388
    *(--p) = '0';
389
    *(--p) = 0;
2 7u83 390
 
391
    /* Read the number */
392
    do {
6 7u83 393
	unsigned n;
394
	if (dec_digit(c)) {
395
	    n = (unsigned)(c - '0');
396
	} else if (c >= 'A' && c <= 'F') {
397
	    n = 10 + (unsigned)(c - 'A');
398
	} else if (c >= 'a' && c <= 'f') {
399
	    n = 10 + (unsigned)(c - 'a');
2 7u83 400
	} else {
6 7u83 401
	    is_fatal = 0;
402
	    input_error("Illegal digit, %c",(unsigned char)c);
403
	    n = 0;
2 7u83 404
	}
6 7u83 405
	if (n >= base) {
406
	    is_fatal = 0;
407
	    input_error("Illegal digit, %c",(unsigned char)c);
408
	    n = 0;
2 7u83 409
	}
6 7u83 410
	if (really_analyse) {
411
	    p = word_buff + (BUFFSIZE - 2);
2 7u83 412
	    do {
6 7u83 413
		if (*p == 0) {
414
		    *(p - 1) = 0;
2 7u83 415
		} else {
6 7u83 416
		    n += base *(unsigned)(*p - '0');
2 7u83 417
		}
6 7u83 418
		*p = (char)('0' + (n & 7));
419
		n >>= 3;
420
		p--;
421
	    } while (n || *p);
2 7u83 422
	}
6 7u83 423
	c = getc(input);
424
	if (c == '\n')crt_line_no++;
425
    } while (!terminator(c));
2 7u83 426
 
427
    /* Find the start of the number */
6 7u83 428
    if (really_analyse) {
2 7u83 429
	for ( p = word_buff + ( BUFFSIZE - 2 ) ; *p ; p-- ) /* empty */ ;
6 7u83 430
	if (negate)*(p--) = '-';
2 7u83 431
    }
6 7u83 432
    pending = c;
433
    word = p + 1;
434
    if (streq(word, "-0"))word = "0";
435
    word_type = INPUT_NUMBER;
436
    return;
2 7u83 437
}
438
 
439
 
440
/*
441
    HOW MANY WORDS TO THE NEXT CLOSE BRACKET?
442
 
443
    This routine skips over the input until the first closing bracket
444
    unmatched by an open bracket is read.  The routine returns the
445
    number of word read at the highest bracket level.  (Not currently
446
    used.)
447
*/
448
 
6 7u83 449
long
450
skip_words(void)
2 7u83 451
{
6 7u83 452
    long n = 0;
453
    int level = 1;
454
    really_analyse = 0;
455
    while (level) {
456
	read_word();
457
	switch (word_type) {
458
	    case INPUT_OPEN: level++; break;
459
	    case INPUT_CLOSE: level--; break;
460
	    case INPUT_EOF: {
461
		input_error("Unexpected end of file");
462
		return(n);
2 7u83 463
	    }
464
	}
6 7u83 465
	if (level == 1)n++;
2 7u83 466
    }
6 7u83 467
    really_analyse = 1;
468
    return(n);
2 7u83 469
}
470
 
471
 
472
/*
473
    STORE THE CURRENT POSITION
474
 
475
    The current position in the input file is stored in p.
476
*/
477
 
6 7u83 478
void
479
store_position(position *p)
2 7u83 480
{
6 7u83 481
    p->line = crt_line_no;
482
    p->posn = ftell(input);
483
    p->pending = pending;
484
    p->ahead = looked_ahead;
485
    return;
2 7u83 486
}
487
 
488
 
489
/*
490
    SET THE CURRENT POSITION
491
 
492
    The position in the input file is set from p.
493
*/
494
 
6 7u83 495
void
496
set_position(position *p)
2 7u83 497
{
6 7u83 498
    crt_line_no = p->line;
499
    pending = p->pending;
500
    looked_ahead = p->ahead;
501
    if (fseek(input, p->posn, SEEK_SET)) {
502
	fatal_error("Illegal seek command");
2 7u83 503
    }
6 7u83 504
    return;
2 7u83 505
}