Subversion Repositories tendra.SVN

Rev

Rev 5 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5 Rev 6
Line -... Line 1...
-
 
1
/*
-
 
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
 */
1
/*
31
/*
2
    		 Crown Copyright (c) 1997
32
    		 Crown Copyright (c) 1997
3
    
33
 
4
    This TenDRA(r) Computer Program is subject to Copyright
34
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
35
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
36
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
37
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
38
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
39
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
40
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
41
    shall be deemed to be acceptance of the following conditions:-
12
    
42
 
13
        (1) Its Recipients shall ensure that this Notice is
43
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
44
        reproduced upon any copies or amended versions of it;
15
    
45
 
16
        (2) Any amended version of it shall be clearly marked to
46
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
47
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
48
        for the relevant amendment or amendments;
19
    
49
 
20
        (3) Its onward transfer from a recipient to another
50
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
51
        party shall be deemed to be that party's acceptance of
22
        these conditions;
52
        these conditions;
23
    
53
 
24
        (4) DERA gives no warranty or assurance as to its
54
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
55
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
56
        no liability whatsoever in relation to any use to which
27
        it may be put.
57
        it may be put.
28
*/
58
*/
Line 38... Line 68...
38
 
68
 
39
/*
69
/*
40
    INPUT FILE
70
    INPUT FILE
41
 
71
 
42
    This is the file from which the lexical routine read their input.
72
    This is the file from which the lexical routine read their input.
43
*/
73
*/
44
 
74
 
45
static FILE *lex_input ;
75
static FILE *lex_input;
46
 
76
 
47
 
77
 
48
/*
78
/*
49
    PENDING BUFFER
79
    PENDING BUFFER
50
 
80
 
Line 53... Line 83...
53
    characters pending, otherwise the pending characters are stored in
83
    characters pending, otherwise the pending characters are stored in
54
    the buffer.  The buffer may need increasing in size if the look-ahead
84
    the buffer.  The buffer may need increasing in size if the look-ahead
55
    required by the lexical analyser increases.
85
    required by the lexical analyser increases.
56
*/
86
*/
57
 
87
 
58
static int pending_buff [12] = { '?' } ;
88
static int pending_buff[12] = {'?'};
59
static int *pending = pending_buff ;
89
static int *pending = pending_buff;
60
 
90
 
61
 
91
 
62
/*
92
/*
63
    MAPPINGS AND DECLARATIONS FOR AUTOMATICALLY GENERATED SECTION
93
    MAPPINGS AND DECLARATIONS FOR AUTOMATICALLY GENERATED SECTION
64
 
94
 
65
    These macros give the mappings between the actions used in the
95
    These macros give the mappings between the actions used in the
66
    automatically generated lexical analyser and the routines defined
96
    automatically generated lexical analyser and the routines defined
67
    in this file.
97
    in this file.
68
*/
98
*/
69
 
99
 
70
static int read_char PROTO_S ( ( void ) ) ;
100
static int read_char(void);
71
static int read_comment PROTO_S ( ( void ) ) ;
101
static int read_comment(void);
72
static int read_identifier PROTO_S ( ( int ) ) ;
102
static int read_identifier(int);
73
static int read_string PROTO_S ( ( void ) ) ;
103
static int read_string(void);
74
 
104
 
75
#define get_comment( A, B )	read_comment ()
105
#define get_comment(A, B)	read_comment()
76
#define get_identifier( A )	read_identifier ( ( A ) )
106
#define get_identifier(A)	read_identifier((A))
77
#define get_string( A )		read_string ()
107
#define get_string(A)		read_string()
78
#define unknown_token( A )	lex_unknown
108
#define unknown_token(A)	lex_unknown
79
#define unread_char( A )	*( ++pending ) = ( A )
109
#define unread_char(A)		*(++pending) = (A)
80
 
110
 
81
 
111
 
82
/*
112
/*
83
    AUTOMATICALLY GENERATED SECTION
113
    AUTOMATICALLY GENERATED SECTION
84
 
114
 
Line 93... Line 123...
93
 
123
 
94
    This routine reads the next character, either from the pending buffer
124
    This routine reads the next character, either from the pending buffer
95
    or from the input file.
125
    or from the input file.
96
*/
126
*/
97
 
127
 
98
static int read_char
128
static int
99
    PROTO_Z ()
129
read_char(void)
100
{
130
{
101
    int c ;
131
	int c;
102
    if ( pending != pending_buff ) {
132
	if (pending != pending_buff) {
103
	c = *( pending-- ) ;
133
		c = *(pending--);
104
    } else {
134
	} else {
105
	c = fgetc ( lex_input ) ;
135
		c = fgetc(lex_input);
106
	if ( c == '\n' ) crt_line_no++ ;
136
		if (c == '\n') {
-
 
137
			crt_line_no++;
-
 
138
		}
-
 
139
		if (c == EOF) {
107
	if ( c == EOF ) return ( LEX_EOF ) ;
140
			return (LEX_EOF);
-
 
141
		}
108
	c &= 0xff ;
142
		c &= 0xff;
109
    }
143
	}
110
    return ( c ) ;
144
	return (c);
111
}
145
}
112
 
146
 
113
 
147
 
114
/*
148
/*
115
    TOKEN BUFFER
149
    TOKEN BUFFER
116
 
150
 
117
    This buffer is used by read_token to hold the values of identifiers
151
    This buffer is used by read_token to hold the values of identifiers
118
    and strings.
152
    and strings.
119
*/
153
*/
120
 
154
 
121
char token_buff [2000] ;
155
char token_buff[2000];
122
static char *token_end = token_buff + sizeof ( token_buff ) ;
156
static char *token_end = token_buff + sizeof(token_buff);
123
char *first_comment = NULL ;
157
char *first_comment = NULL;
124
 
158
 
125
 
159
 
126
/*
160
/*
127
    READ AN IDENTIFIER
161
    READ AN IDENTIFIER
128
 
162
 
129
    This routine reads an identifier beginning with a, returning the
163
    This routine reads an identifier beginning with a, returning the
130
    corresponding lexical token.  Keywords are dealt with locally.
164
    corresponding lexical token.  Keywords are dealt with locally.
131
*/
165
*/
132
 
166
 
133
static int read_identifier
167
static int
134
    PROTO_N ( ( a ) )
-
 
135
    PROTO_T ( int a )
168
read_identifier(int a)
136
{
169
{
137
    int c = a, cl ;
170
	int c = a, cl;
138
    char *t = token_buff ;
171
	char *t = token_buff;
139
    do {
172
	do {
140
	*( t++ ) = ( char ) c ;
173
		*(t++) = (char) c;
-
 
174
		if (t == token_end) {
141
	if ( t == token_end ) error ( ERROR_FATAL, "Buffer overflow" ) ;
175
			error(ERROR_FATAL, "Buffer overflow");
-
 
176
		}
142
	c = read_char () ;
177
		c = read_char();
143
	cl = lookup_char ( c ) ;
178
		cl = lookup_char(c);
144
    } while ( is_alphanum ( cl ) ) ;
179
	} while (is_alphanum(cl));
145
    *t = 0 ;
180
	*t = 0;
146
    unread_char ( c ) ;
181
	unread_char(c);
147
 
182
 
148
    /* Deal with keywords */
183
	/* Deal with keywords */
149
    t = token_buff ;
184
	t = token_buff;
150
#define MAKE_KEYWORD( A, B )\
185
#define MAKE_KEYWORD(A, B)\
151
    if ( streq ( t, ( A ) ) ) return ( B ) ;
186
	if (streq(t,(A))) return (B);
152
#include "keyword.h"
187
#include "keyword.h"
153
    return ( lex_identifier ) ;
188
	return (lex_identifier);
154
}
189
}
155
 
190
 
156
 
191
 
157
/*
192
/*
158
    READ A STRING
193
    READ A STRING
159
 
194
 
160
    This routine reads a string.  It is entered after the initial quote has
195
    This routine reads a string.  It is entered after the initial quote has
161
    been read.  Note that new line characters are allowed in strings.
196
    been read.  Note that new line characters are allowed in strings.
162
*/
197
*/
163
 
-
 
164
static int read_string
-
 
165
    PROTO_Z ()
-
 
166
{
-
 
167
    int c ;
-
 
168
    int escaped = 0 ;
-
 
169
    char *t = token_buff ;
-
 
170
    while ( c = read_char (), ( c != '"' || escaped ) ) {
-
 
171
	if ( c == LEX_EOF ) {
-
 
172
	    error ( ERROR_SERIOUS, "Unexpected end of string" ) ;
-
 
173
	    break ;
-
 
174
	}
-
 
175
	*( t++ ) = ( char ) c ;
-
 
176
	if ( t == token_end ) error ( ERROR_FATAL, "Buffer overflow" ) ;
-
 
177
	if ( escaped ) {
-
 
178
	    escaped = 0 ;
-
 
179
	} else {
-
 
180
	    if ( c == '\\' ) escaped = 1 ;
-
 
181
	}
-
 
182
    }
-
 
183
    *t = 0 ;
-
 
184
    return ( lex_string ) ;
-
 
185
}
-
 
186
 
-
 
187
 
-
 
188
/*
-
 
189
    READ A COMMENT
-
 
190
 
198
 
191
    This routine reads a C style comment, returning the lexical token
-
 
192
    immediately following.  It is entered after the first two characters
-
 
193
    have been read.
-
 
194
*/
-
 
195
 
-
 
196
static int read_comment
199
static int
197
    PROTO_Z ()
200
read_string(void)
198
{
201
{
-
 
202
	int c;
199
    int state = 0 ;
203
	int escaped = 0;
200
    char *t = token_buff ;
204
	char *t = token_buff;
201
    *( t++ ) = '/' ;
-
 
202
    *( t++ ) = '*' ;
-
 
203
    while ( state != 2 ) {
-
 
204
	int c = read_char () ;
205
	while (c = read_char(),(c != '"' || escaped)) {
205
	if ( c == LEX_EOF ) {
206
		if (c == LEX_EOF) {
206
	    error ( ERROR_SERIOUS, "End of file in comment" ) ;
207
			error(ERROR_SERIOUS, "Unexpected end of string");
207
	    return ( lex_eof ) ;
208
			break;
208
	}
209
		}
209
	if ( c == '*' ) {
210
		*(t++) = (char) c;
210
	    state = 1 ;
211
		if (t == token_end) {
211
	} else if ( state == 1 && c == '/' ) {
212
			error(ERROR_FATAL, "Buffer overflow");
-
 
213
		}
-
 
214
		if (escaped) {
212
	    state = 2 ;
215
			escaped = 0;
213
	} else {
216
		} else {
-
 
217
			if (c == '\\') {
214
	    state = 0 ;
218
				escaped = 1;
-
 
219
			}
-
 
220
		}
215
	}
221
	}
-
 
222
	*t = 0;
-
 
223
	return (lex_string);
-
 
224
}
-
 
225
 
-
 
226
 
-
 
227
/*
-
 
228
    READ A COMMENT
-
 
229
 
-
 
230
    This routine reads a C style comment, returning the lexical token
-
 
231
    immediately following.  It is entered after the first two characters
-
 
232
    have been read.
-
 
233
*/
-
 
234
 
-
 
235
static int
-
 
236
read_comment(void)
-
 
237
{
-
 
238
	int state = 0;
-
 
239
	char *t = token_buff;
-
 
240
	*(t++) = '/';
-
 
241
	*(t++) = '*';
-
 
242
	while (state != 2) {
-
 
243
		int c = read_char();
-
 
244
		if (c == LEX_EOF) {
-
 
245
			error(ERROR_SERIOUS, "End of file in comment");
-
 
246
			return (lex_eof);
-
 
247
		}
-
 
248
		if (c == '*') {
-
 
249
			state = 1;
-
 
250
		} else if (state == 1 && c == '/') {
-
 
251
			state = 2;
-
 
252
		} else {
-
 
253
			state = 0;
-
 
254
		}
216
	*( t++ ) = ( char ) c ;
255
		*(t++) = (char) c;
217
	if ( t == token_end ) t = token_buff + 2 ;
256
		if (t == token_end) {
-
 
257
			t = token_buff + 2;
218
    }
258
		}
-
 
259
	}
-
 
260
	if (first_comment == NULL) {
219
    if ( first_comment == NULL ) first_comment = xstrcpy ( token_buff ) ;
261
		first_comment = xstrcpy(token_buff);
-
 
262
	}
220
    return ( read_token () ) ;
263
	return (read_token());
221
}
264
}
222
 
265
 
223
 
266
 
224
/*
267
/*
225
    CURRENT TOKEN
268
    CURRENT TOKEN
226
 
269
 
227
    These variables are used by the parser to hold the current and former
270
    These variables are used by the parser to hold the current and former
228
    lexical tokens.
271
    lexical tokens.
229
*/
272
*/
230
 
273
 
231
int crt_lex_token ;
274
int crt_lex_token;
232
int saved_lex_token ;
275
int saved_lex_token;
233
 
276
 
234
 
277
 
235
/*
278
/*
236
    PROCESS FILE
279
    PROCESS FILE
237
 
280
 
238
    This routine processes the input file nm.  If nm is the null string
281
    This routine processes the input file nm.  If nm is the null string
239
    then the standard input is used.
282
    then the standard input is used.
240
*/
283
*/
241
 
284
 
242
void process_file
285
void
243
    PROTO_N ( ( nm ) )
-
 
244
    PROTO_T ( char *nm )
286
process_file(char *nm)
245
{
287
{
246
    crt_line_no = 1 ;
288
	crt_line_no = 1;
247
    if ( nm == NULL || streq ( nm, "-" ) ) {
289
	if (nm == NULL || streq(nm, "-")) {
248
	crt_file_name = "stdin" ;
290
		crt_file_name = "stdin";
249
	lex_input = stdin ;
291
		lex_input = stdin;
250
	nm = NULL ;
292
		nm = NULL;
251
    } else {
293
	} else {
252
	crt_file_name = nm ;
294
		crt_file_name = nm;
253
	lex_input = fopen ( nm, "r" ) ;
295
		lex_input = fopen(nm, "r");
254
	if ( lex_input == NULL ) {
296
		if (lex_input == NULL) {
255
	    error ( ERROR_SERIOUS, "Can't open input file, '%s'", nm ) ;
297
			error(ERROR_SERIOUS, "Can't open input file, '%s'", nm);
256
	    return ;
298
			return;
-
 
299
		}
-
 
300
	}
-
 
301
	ADVANCE_LEXER;
-
 
302
	read_errors();
-
 
303
	if (nm != NULL) {
-
 
304
		fclose_v(lex_input);
257
	}
305
	}
258
    }
-
 
259
    ADVANCE_LEXER ;
-
 
260
    read_errors () ;
-
 
261
    if ( nm != NULL ) fclose_v ( lex_input ) ;
-
 
262
    return ;
306
	return;
263
}
307
}