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
/*
7 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
7 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:-
7 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
7 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;
7 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;
7 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 "errors.h"
63
#include "error.h"
64
#include "lex.h"
65
#include "syntax.h"
66
#include "xalloc.h"
67
 
68
 
69
/*
70
    INPUT FILE
71
 
72
    This is the file from which the lexical routine read their input.
73
*/
74
 
7 7u83 75
static FILE *lex_input;
2 7u83 76
 
77
 
78
/*
79
    PENDING BUFFER
80
 
81
    Pending characters are dealt with by means of this buffer.  pending
82
    is set to the start of the buffer to indicate that there are no
83
    characters pending, otherwise the pending characters are stored in
84
    the buffer.  The buffer may need increasing in size if the look-ahead
85
    required by the lexical analyser increases.
86
*/
87
 
7 7u83 88
static int pending_buff[12] = {'?'};
89
static int *pending = pending_buff;
2 7u83 90
 
91
 
92
/*
93
    MAPPINGS AND DECLARATIONS FOR AUTOMATICALLY GENERATED SECTION
94
 
95
    These macros give the mappings between the actions used in the
96
    automatically generated lexical analyser and the routines defined
97
    in this file.
98
*/
99
 
7 7u83 100
static int read_char(void);
101
static int read_comment(void);
102
static int read_identifier(int);
103
static int read_string(void);
2 7u83 104
 
7 7u83 105
#define get_comment(A, B)	read_comment()
106
#define get_identifier(A)	read_identifier((A))
107
#define get_string(A)		read_string()
108
#define unknown_token(A)	lex_unknown
109
#define unread_char(A)		*(++pending) = (A)
2 7u83 110
 
111
 
112
/*
113
    AUTOMATICALLY GENERATED SECTION
114
 
115
    The main body of the lexical analyser is automatically generated.
116
*/
117
 
118
#include "lexer.h"
119
 
120
 
121
/*
122
    GET THE NEXT CHARACTER
123
 
124
    This routine reads the next character, either from the pending buffer
125
    or from the input file.
126
*/
127
 
7 7u83 128
static int
129
read_char(void)
2 7u83 130
{
7 7u83 131
	int c;
132
	if (pending != pending_buff) {
133
		c = *(pending--);
134
	} else {
135
		c = fgetc(lex_input);
136
		if (c == '\n') {
137
			crt_line_no++;
138
		}
139
		if (c == EOF) {
140
			return (LEX_EOF);
141
		}
142
		c &= 0xff;
143
	}
144
	return (c);
2 7u83 145
}
146
 
147
 
148
/*
149
    TOKEN BUFFER
150
 
151
    This buffer is used by read_token to hold the values of identifiers
152
    and strings.
153
*/
154
 
7 7u83 155
char token_buff[2000];
156
static char *token_end = token_buff + sizeof(token_buff);
157
char *first_comment = NULL;
2 7u83 158
 
159
 
160
/*
161
    READ AN IDENTIFIER
162
 
163
    This routine reads an identifier beginning with a, returning the
164
    corresponding lexical token.  Keywords are dealt with locally.
165
*/
166
 
7 7u83 167
static int
168
read_identifier(int a)
2 7u83 169
{
7 7u83 170
	int c = a, cl;
171
	char *t = token_buff;
172
	do {
173
		*(t++) = (char) c;
174
		if (t == token_end) {
175
			error(ERROR_FATAL, "Buffer overflow");
176
		}
177
		c = read_char();
178
		cl = lookup_char(c);
179
	} while (is_alphanum(cl));
180
	*t = 0;
181
	unread_char(c);
2 7u83 182
 
7 7u83 183
	/* Deal with keywords */
184
	t = token_buff;
185
#define MAKE_KEYWORD(A, B)\
186
	if (streq(t,(A))) return (B);
2 7u83 187
#include "keyword.h"
7 7u83 188
	return (lex_identifier);
2 7u83 189
}
190
 
191
 
192
/*
193
    READ A STRING
194
 
195
    This routine reads a string.  It is entered after the initial quote has
196
    been read.  Note that new line characters are allowed in strings.
197
*/
198
 
7 7u83 199
static int
200
read_string(void)
2 7u83 201
{
7 7u83 202
	int c;
203
	int escaped = 0;
204
	char *t = token_buff;
205
	while (c = read_char(),(c != '"' || escaped)) {
206
		if (c == LEX_EOF) {
207
			error(ERROR_SERIOUS, "Unexpected end of string");
208
			break;
209
		}
210
		*(t++) = (char) c;
211
		if (t == token_end) {
212
			error(ERROR_FATAL, "Buffer overflow");
213
		}
214
		if (escaped) {
215
			escaped = 0;
216
		} else {
217
			if (c == '\\') {
218
				escaped = 1;
219
			}
220
		}
2 7u83 221
	}
7 7u83 222
	*t = 0;
223
	return (lex_string);
2 7u83 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
 
7 7u83 235
static int
236
read_comment(void)
2 7u83 237
{
7 7u83 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
		}
255
		*(t++) = (char) c;
256
		if (t == token_end) {
257
			t = token_buff + 2;
258
		}
2 7u83 259
	}
7 7u83 260
	if (first_comment == NULL) {
261
		first_comment = xstrcpy(token_buff);
2 7u83 262
	}
7 7u83 263
	return (read_token());
2 7u83 264
}
265
 
266
 
267
/*
268
    CURRENT TOKEN
269
 
270
    These variables are used by the parser to hold the current and former
271
    lexical tokens.
272
*/
273
 
7 7u83 274
int crt_lex_token;
275
int saved_lex_token;
2 7u83 276
 
277
 
278
/*
279
    PROCESS FILE
280
 
281
    This routine processes the input file nm.  If nm is the null string
282
    then the standard input is used.
283
*/
284
 
7 7u83 285
void
286
process_file(char *nm)
2 7u83 287
{
7 7u83 288
	crt_line_no = 1;
289
	if (nm == NULL || streq(nm, "-")) {
290
		crt_file_name = "stdin";
291
		lex_input = stdin;
292
		nm = NULL;
293
	} else {
294
		crt_file_name = nm;
295
		lex_input = fopen(nm, "r");
296
		if (lex_input == NULL) {
297
			error(ERROR_SERIOUS, "Can't open input file, '%s'", nm);
298
			return;
299
		}
2 7u83 300
	}
7 7u83 301
	ADVANCE_LEXER;
302
	read_errors();
303
	if (nm != NULL) {
304
		fclose_v(lex_input);
305
	}
306
	return;
2 7u83 307
}