Subversion Repositories tendra.SVN

Rev

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