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