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 "error.h"
63
#include "lex.h"
64
#include "syntax.h"
65
#include "xalloc.h"
66
 
67
 
68
/*
69
    INPUT FILE
70
 
71
    This is the file from which the lexical routine read their input.
72
*/
73
 
6 7u83 74
static FILE *lex_input;
2 7u83 75
 
76
 
77
/*
78
    PENDING BUFFER
79
 
80
    Pending characters are dealt with by means of this buffer.  pending
81
    is set to the start of the buffer to indicate that there are no
82
    characters pending, otherwise the pending characters are stored in
83
    the buffer.  The buffer may need increasing in size if the look-ahead
84
    required by the lexical analyser increases.
85
*/
86
 
6 7u83 87
static int pending_buff [12] = { '?' };
88
static int *pending = pending_buff;
2 7u83 89
 
90
 
91
/*
92
    MAPPINGS AND DECLARATIONS FOR AUTOMATICALLY GENERATED SECTION
93
 
94
    These macros give the mappings between the actions used in the
95
    automatically generated lexical analyser and the routines defined
96
    in this file.
97
*/
98
 
6 7u83 99
static int read_char(void);
100
static int read_comment(void);
101
static int read_identifier(int, int);
102
static int read_string(void);
2 7u83 103
 
6 7u83 104
#define get_comment(A, B)	read_comment()
105
#define get_identifier(A)	read_identifier((A), 0)
106
#define get_sid_ident(A, B)	read_identifier((B), 1)
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
 
6 7u83 128
static int
129
read_char(void)
2 7u83 130
{
6 7u83 131
    int c;
132
    if (pending != pending_buff) {
133
	c = *(pending--);
2 7u83 134
    } else {
6 7u83 135
	c = fgetc(lex_input);
136
	if (c == '\n')crt_line_no++;
137
	if (c == EOF) return(LEX_EOF);
138
	c &= 0xff;
2 7u83 139
    }
6 7u83 140
    return(c);
2 7u83 141
}
142
 
143
 
144
/*
145
    TOKEN BUFFER
146
 
147
    This buffer is used by read_token to hold the values of identifiers
148
    and strings.
149
*/
150
 
6 7u83 151
char token_buff [2000];
152
static char *token_end = token_buff + sizeof(token_buff);
153
char *first_comment = NULL;
2 7u83 154
 
155
 
156
/*
157
    READ AN IDENTIFIER
158
 
159
    This routine reads an identifier beginning with a, returning the
160
    corresponding lexical token.  Keywords are dealt with locally.
161
    The sid flag indicates whether a sid-style identifier is expected.
162
*/
163
 
6 7u83 164
static int
165
read_identifier(int a, int sid)
2 7u83 166
{
6 7u83 167
    int c = a, cl;
168
    int e = (sid ? '-' : 'x');
169
    char *t = token_buff;
2 7u83 170
    do {
6 7u83 171
	*(t++) = (char)c;
172
	if (t == token_end)error(ERROR_FATAL, "Buffer overflow");
173
	c = read_char();
174
	cl = lookup_char(c);
175
    } while (is_alphanum(cl) || c == e);
176
    *t = 0;
177
    unread_char(c);
2 7u83 178
 
179
    /* Deal with keywords */
6 7u83 180
    if (sid) return(lex_sid_Hidentifier);
181
    t = token_buff;
182
#define MAKE_KEYWORD(A, B)\
183
    if (streq(t,(A))) return(B);
2 7u83 184
#include "keyword.h"
6 7u83 185
    return(lex_identifier);
2 7u83 186
}
187
 
188
 
189
/*
190
    READ A STRING
191
 
192
    This routine reads a string.  It is entered after the initial
193
    quote has been read.
194
*/
195
 
6 7u83 196
static int
197
read_string(void)
2 7u83 198
{
6 7u83 199
    int c;
200
    int escaped = 0;
201
    char *t = token_buff;
202
    while (c = read_char(), (c != '"' || escaped)) {
203
	if (c == '\n' || c == LEX_EOF) {
204
	    error(ERROR_SERIOUS, "Unexpected end of string");
205
	    break;
2 7u83 206
	}
6 7u83 207
	*(t++) = (char)c;
208
	if (t == token_end)error(ERROR_FATAL, "Buffer overflow");
209
	if (escaped) {
210
	    escaped = 0;
2 7u83 211
	} else {
6 7u83 212
	    if (c == '\\')escaped = 1;
2 7u83 213
	}
214
    }
6 7u83 215
    *t = 0;
216
    return(lex_string);
2 7u83 217
}
218
 
219
 
220
/*
221
    READ A COMMENT
222
 
223
    This routine reads a C style comment, returning the lexical token
224
    immediately following.  It is entered after the first two characters
225
    have been read.
226
*/
227
 
6 7u83 228
static int
229
read_comment(void)
2 7u83 230
{
6 7u83 231
    int state = 0;
232
    char *t = token_buff;
233
    *(t++) = '/';
234
    *(t++) = '*';
235
    while (state != 2) {
236
	int c = read_char();
237
	if (c == LEX_EOF) {
238
	    error(ERROR_SERIOUS, "End of file in comment");
239
	    return(lex_eof);
2 7u83 240
	}
6 7u83 241
	if (c == '*') {
242
	    state = 1;
243
	} else if (state == 1 && c == '/') {
244
	    state = 2;
2 7u83 245
	} else {
6 7u83 246
	    state = 0;
2 7u83 247
	}
6 7u83 248
	*(t++) = (char)c;
249
	if (t == token_end)t = token_buff + 2;
2 7u83 250
    }
6 7u83 251
    *t = 0;
252
    if (first_comment == NULL)first_comment = xstrcpy(token_buff);
253
    return(read_token());
2 7u83 254
}
255
 
256
 
257
/*
258
    CURRENT TOKEN
259
 
260
    These variables are used by the parser to hold the current and former
261
    lexical tokens.
262
*/
263
 
6 7u83 264
int crt_lex_token;
265
int saved_lex_token;
2 7u83 266
 
267
 
268
/*
269
    PROCESS FILE
270
 
271
    This routine processes the input file nm.
272
*/
273
 
6 7u83 274
void
275
process_file(char *nm)
2 7u83 276
{
6 7u83 277
    crt_line_no = 1;
278
    if (nm == NULL || streq(nm, "-")) {
279
	crt_file_name = "<stdin>";
280
	lex_input = stdin;
281
	nm = NULL;
2 7u83 282
    } else {
6 7u83 283
	crt_file_name = nm;
284
	lex_input = fopen(nm, "r");
285
	if (lex_input == NULL) {
286
	    error(ERROR_SERIOUS, "Can't open input file, '%s'", nm);
287
	    return;
2 7u83 288
	}
289
    }
6 7u83 290
    ADVANCE_LEXER;
291
    read_lex();
292
    if (nm)fclose_v(lex_input);
293
    return;
2 7u83 294
}