Subversion Repositories tendra.SVN

Rev

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

Rev 2 Rev 7
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
*/
29
 
59
 
30
 
60
 
31
#include "config.h"
61
#include "config.h"
32
#include "char.h"
62
#include "char.h"
33
#include "error.h"
63
#include "error.h"
-
 
64
#include "tendra.h"
34
#include "xalloc.h"
65
#include "xalloc.h"
35
 
66
 
36
 
67
 
37
/*
68
/*
38
    WHITE SPACE CHARACTERS
69
    WHITE SPACE CHARACTERS
39
 
70
 
40
    This variable holds all the white space characters.
71
    This variable holds all the white space characters.
41
*/
72
*/
42
 
73
 
43
letter *white_space = NULL ;
74
letter *white_space = NULL;
44
 
75
 
45
 
76
 
46
/*
77
/*
47
    LEXICAL PASS REPRESENTATIONS
78
    LEXICAL PASS REPRESENTATIONS
48
 
79
 
49
    These variables describe the various lexical passes.
80
    These variables describe the various lexical passes.
50
*/
81
*/
51
 
82
 
52
static character passes [2] = {
83
static character passes [2] = {
53
    { LAST_LETTER, NULL, NULL, NULL },
84
    { LAST_LETTER, NULL, NULL, NULL, NULL, NULL },
54
    { LAST_LETTER, NULL, NULL, NULL }
85
    { LAST_LETTER, NULL, NULL, NULL, NULL, NULL }
55
} ;
86
};
56
 
87
 
57
character *pre_pass = passes ;
88
character *pre_pass = passes;
58
character *main_pass = passes + 1 ;
89
character *main_pass = passes + 1;
59
 
90
 
60
 
91
 
61
/*
92
/*
62
    ALLOCATE A NEW CHARACTER
93
    ALLOCATE A NEW CHARACTER
63
 
94
 
64
    This routine allocates a new character with value c.
95
    This routine allocates a new character with value c.
65
*/
96
*/
66
 
97
 
67
static character *new_char
98
static character *
68
    PROTO_N ( ( c ) )
-
 
69
    PROTO_T ( letter c )
99
new_char(letter c)
70
{
100
{
71
    character *p ;
101
    character *p;
72
    static int chars_left = 0 ;
102
    static int chars_left = 0;
73
    static character *chars_free = NULL ;
103
    static character *chars_free = NULL;
74
    if ( chars_left == 0 ) {
104
    if (chars_left == 0) {
75
	chars_left = 100 ;
105
	chars_left = 100;
76
	chars_free = xmalloc_nof ( character, chars_left ) ;
106
	chars_free = xmalloc_nof(character, chars_left);
77
    }
107
    }
78
    p = chars_free + ( --chars_left ) ;
108
    p = chars_free + (--chars_left);
79
    p->ch = c ;
109
    p->ch = c;
80
    p->defn = NULL ;
110
    p->defn = NULL;
81
    p->cond = NULL ;
111
    p->cond = NULL;
82
    p->opt = NULL ;
112
    p->opt = NULL;
83
    p->next = NULL ;
113
    p->next = NULL;
84
    return ( p ) ;
114
    return(p);
85
}
115
}
86
 
116
 
87
 
117
 
88
/*
118
/*
89
    ADD A CHARACTER
119
    ADD A CHARACTER
90
 
120
 
91
    This routine adds the string s (defined using data) to the lexical
121
    This routine adds the string s (defined using data) to the lexical
92
    pass p.
122
    pass p.
93
*/
123
*/
94
 
124
 
95
void add_char
125
void
96
    PROTO_N ( ( p, s, data ) )
-
 
97
    PROTO_T ( character *p X letter *s X char **data )
126
add_char(character *p, letter *s, char **data)
98
{
127
{
99
    character *q ;
128
    character *q;
100
    letter c = *s ;
129
    letter c = *s;
101
    if ( p->next == NULL ) {
130
    if (p->next == NULL) {
102
	q = new_char ( c ) ;
131
	q = new_char(c);
103
	p->next = q ;
132
	p->next = q;
104
    } else {
133
    } else {
105
	character *r = NULL ;
134
	character *r = NULL;
106
	for ( q = p->next ; q && ( q->ch < c ) ; q = q->opt ) r = q ;
135
	for (q = p->next; q && (q->ch < c); q = q->opt)r = q;
107
	if ( q && q->ch == c ) {
136
	if (q && q->ch == c) {
108
	    /* already exists */
137
	    /* already exists */
109
	} else {
138
	} else {
110
	    q = new_char ( c ) ;
139
	    q = new_char(c);
111
	    if ( r == NULL ) {
140
	    if (r == NULL) {
112
		q->opt = p->next ;
141
		q->opt = p->next;
113
		p->next = q ;
142
		p->next = q;
114
	    } else {
143
	    } else {
115
		q->opt = r->opt ;
144
		q->opt = r->opt;
116
		r->opt = q ;
145
		r->opt = q;
117
	    }
146
	    }
118
	}
147
	}
119
    }
148
    }
120
    if ( c == LAST_LETTER ) {
149
    if (c == LAST_LETTER) {
121
	if ( q->defn ) {
150
	if (q->defn) {
122
	    error ( ERROR_SERIOUS,
151
	    error(ERROR_SERIOUS,
123
		    "String for '%s' has already been defined to give '%s'",
152
		    "String for '%s' has already been defined to give '%s'",
124
		    data [0], q->defn ) ;
153
		    data [0], q->defn);
125
	}
154
	}
126
	q->defn = data [0] ;
155
	q->defn = data [0];
127
	q->args = data [1] ;
156
	q->args = data [1];
128
	q->cond = data [2] ;
157
	q->cond = data [2];
129
    } else {
158
    } else {
130
	add_char ( q, s + 1, data ) ;
159
	add_char(q, s + 1, data);
131
    }
160
    }
132
    return ;
161
    return;
133
}
162
}
134
 
163
 
135
 
164
 
136
/*
165
/*
137
    ARRAY OF ALL GROUPS
166
    ARRAY OF ALL GROUPS
138
 
167
 
139
    This array gives all the character groups.
168
    This array gives all the character groups.
140
*/
169
*/
141
 
170
 
142
char_group groups [ MAX_GROUPS ] ;
171
char_group groups [ MAX_GROUPS ];
143
int no_groups = 0 ;
172
int no_groups = 0;
144
 
173
 
145
 
174
 
146
/*
175
/*
147
    CREATE A NEW GROUP
176
    CREATE A NEW GROUP
148
 
177
 
149
    This routine creates a new character group with name nm and
178
    This routine creates a new character group with name nm and
150
    definition s.
179
    definition s.
151
*/
180
*/
152
 
181
 
153
void make_group
182
void
154
    PROTO_N ( ( nm, s ) )
-
 
155
    PROTO_T ( char *nm X letter *s )
183
make_group(char *nm, letter *s)
156
{
184
{
157
    int i, n = no_groups ;
185
    int i, n = no_groups;
158
    for ( i = 0 ; i < n ; i++ ) {
186
    for (i = 0; i < n; i++) {
159
	if ( streq ( nm, groups [i].name ) ) {
187
	if (streq(nm, groups [i].name)) {
160
	    error ( ERROR_SERIOUS, "Group '%s' already defined", nm ) ;
188
	    error(ERROR_SERIOUS, "Group '%s' already defined", nm);
161
	    return ;
189
	    return;
162
	}
190
	}
163
    }
191
    }
164
    if ( n >= MAX_GROUPS ) {
192
    if (n >= MAX_GROUPS) {
165
	error ( ERROR_SERIOUS, "Too many groups defined (%d)", n ) ;
193
	error(ERROR_SERIOUS, "Too many groups defined (%d)", n);
166
	return ;
194
	return;
167
    }
195
    }
168
    groups [n].name = nm ;
196
    groups [n].name = nm;
169
    groups [n].defn = s ;
197
    groups [n].defn = s;
170
    no_groups = n + 1 ;
198
    no_groups = n + 1;
171
    return ;
199
    return;
172
}
200
}
173
 
201
 
174
 
202
 
175
/*
203
/*
176
    IS A LETTER IN A GROUP?
204
    IS A LETTER IN A GROUP?
177
 
205
 
178
    This routine checks whether the letter c is in the list p.
206
    This routine checks whether the letter c is in the list p.
179
*/
207
*/
180
 
208
 
181
int in_group
209
int
182
    PROTO_N ( ( p, c ) )
-
 
183
    PROTO_T ( letter *p X letter c )
210
in_group(letter *p, letter c)
184
{
211
{
185
    letter a ;
212
    letter a;
186
    if ( p == NULL ) return ( 0 ) ;
213
    if (p == NULL) return(0);
187
    while ( a = *( p++ ), a != LAST_LETTER ) {
214
    while (a = *(p++), a != LAST_LETTER) {
188
	if ( a == c ) {
215
	if (a == c) {
189
	    return ( 1 ) ;
216
	    return(1);
190
	} else if ( a == WHITE_LETTER ) {
217
	} else if (a == WHITE_LETTER) {
191
	    if ( in_group ( white_space, c ) ) return ( 1 ) ;
218
	    if (in_group(white_space, c)) return(1);
192
	} else if ( a >= GROUP_LETTER ) {
219
	} else if (a >= GROUP_LETTER) {
193
	    int n = ( int ) ( a - GROUP_LETTER ) ;
220
	    int n = (int)(a - GROUP_LETTER);
194
	    if ( in_group ( groups [n].defn, c ) ) return ( 1 ) ;
221
	    if (in_group(groups [n].defn, c)) return(1);
195
	}
222
	}
196
    }
223
    }
197
    return ( 0 ) ;
224
    return(0);
198
}
225
}
199
 
226
 
200
 
227
 
201
/*
228
/*
202
    FIND AN ESCAPE SEQUENCE
229
    FIND AN ESCAPE SEQUENCE
203
 
230
 
204
    This routine finds the character corresponding to the escape sequence c.
231
    This routine finds the character corresponding to the escape sequence c.
205
*/
232
*/
206
 
233
 
207
letter find_escape
234
letter
208
    PROTO_N ( ( c ) )
-
 
209
    PROTO_T ( int c )
235
find_escape(int c)
210
{
236
{
211
    letter a ;
237
    letter a;
212
    switch ( c ) {
238
    switch (c) {
213
	case 'n' : a = '\n' ; break ;
239
	case 'n': a = '\n'; break;
214
	case 't' : a = '\t' ; break ;
240
	case 't': a = '\t'; break;
215
	case 'v' : a = '\v' ; break ;
241
	case 'v': a = '\v'; break;
216
	case 'f' : a = '\f' ; break ;
242
	case 'f': a = '\f'; break;
217
	case 'r' : a = '\r' ; break ;
243
	case 'r': a = '\r'; break;
218
	case '?' : a = '?' ; break ;
244
	case '?': a = '?'; break;
219
	case '"' : a = '"' ; break ;
245
	case '"': a = '"'; break;
220
	case '[' : a = '[' ; break ;
246
	case '[': a = '['; break;
221
	case '\\' : a = '\\' ; break ;
247
	case '\\': a = '\\'; break;
222
	case '\'' : a = '\'' ; break ;
248
	case '\'': a = '\''; break;
223
	case 'e' : a = EOF_LETTER ; break ;
249
	case 'e': a = EOF_LETTER; break;
224
	default : {
250
	default : {
225
	    error ( ERROR_SERIOUS, "Unknown escape sequence, '\\%c'",
251
	    error(ERROR_SERIOUS, "Unknown escape sequence, '\\%c'",
226
		    ( unsigned char ) c ) ;
252
		   (unsigned char)c);
227
	    a = ( letter ) ( c & 0xff ) ;
253
	    a = (letter)(c & 0xff);
228
	    break ;
254
	    break;
229
	}
255
	}
230
    }
256
    }
231
    return ( a ) ;
257
    return(a);
232
}
258
}
233
 
259
 
234
 
260
 
235
/*
261
/*
236
    TRANSLATE A STRING INTO A CHARACTER STRING
262
    TRANSLATE A STRING INTO A CHARACTER STRING
237
 
263
 
238
    This routine translates the string s into an array of letters.
264
    This routine translates the string s into an array of letters.
239
*/
265
*/
240
 
266
 
241
letter *make_string
267
letter *
242
    PROTO_N ( ( s ) )
-
 
243
    PROTO_T ( char *s )
268
make_string(char *s)
244
{
269
{
245
    int i = 0, n = ( int ) strlen ( s )  ;
270
    int i = 0, n = (int)strlen(s);
246
    letter *p = xmalloc_nof ( letter, n + 1 ) ;
271
    letter *p = xmalloc_nof(letter, n + 1);
247
    while ( *s ) {
272
    while (*s) {
248
	letter a ;
273
	letter a;
249
	char c = *( s++ ) ;
274
	char c = *(s++);
250
	if ( c == '\\' ) {
275
	if (c == '\\') {
251
	    c = *( s++ ) ;
276
	    c = *(s++);
252
	    a = find_escape ( c ) ;
277
	    a = find_escape(c);
253
	} else if ( c == '[' ) {
278
	} else if (c == '[') {
254
	    int j ;
279
	    int j;
255
	    size_t glen ;
280
	    size_t glen;
256
	    char *gnm = s ;
281
	    char *gnm = s;
257
	    while ( *s && *s != ']' ) s++ ;
282
	    while (*s && *s != ']')s++;
258
	    glen = ( size_t ) ( s - gnm ) ;
283
	    glen = (size_t)(s - gnm);
259
	    if ( *s ) {
284
	    if (*s) {
260
		s++ ;
285
		s++;
261
	    } else {
286
	    } else {
262
		error ( ERROR_SERIOUS,
287
		error(ERROR_SERIOUS,
263
			"Unterminated character group name, '%s'", gnm ) ;
288
			"Unterminated character group name, '%s'", gnm);
264
	    }
289
	    }
265
	    for ( j = 0 ; j < no_groups ; j++ ) {
290
	    for (j = 0; j < no_groups; j++) {
266
		if ( strncmp ( gnm, groups [j].name, glen ) == 0 ) {
291
		if (strncmp(gnm, groups [j].name, glen) == 0) {
267
		    a = GROUP_LETTER + j ;
292
		    a = GROUP_LETTER + j;
268
		    break ;
293
		    break;
269
		}
294
		}
270
	    }
295
	    }
271
	    if ( j == no_groups ) {
296
	    if (j == no_groups) {
272
		if ( strncmp ( gnm, "white", glen ) == 0 ) {
297
		if (strncmp(gnm, "white", glen) == 0) {
273
		    a = WHITE_LETTER ;
298
		    a = WHITE_LETTER;
274
		} else {
299
		} else {
275
		    error ( ERROR_SERIOUS, "Unknown character group, '%.*s'",
300
		    error(ERROR_SERIOUS, "Unknown character group, '%.*s'",
276
			    ( int ) glen, gnm ) ;
301
			   (int)glen, gnm);
277
		    a = '?' ;
302
		    a = '?';
278
		}
303
		}
279
	    }
304
	    }
280
	    SET ( a ) ;
305
	    SET(a);
281
	} else {
306
	} else {
282
	    a = ( letter ) ( c & 0xff ) ;
307
	    a = (letter)(c & 0xff);
283
	}
308
	}
284
	p [i] = a ;
309
	p [i] = a;
285
	i++ ;
310
	i++;
286
    }
311
    }
287
    p [i] = LAST_LETTER ;
312
    p [i] = LAST_LETTER;
288
    return ( p ) ;
313
    return(p);
289
}
314
}
290
 
315
 
291
 
316
 
292
/*
317
/*
293
    LIST OF ALL KEYWORDS
318
    LIST OF ALL KEYWORDS
294
 
319
 
295
    This variable gives a list of all the keywords.
320
    This variable gives a list of all the keywords.
296
*/
321
*/
297
 
322
 
298
keyword *keywords = NULL ;
323
keyword *keywords = NULL;
299
 
324
 
300
 
325
 
301
/*
326
/*
302
    ADD A KEYWORD
327
    ADD A KEYWORD
303
 
328
 
304
    This routine adds the keyword nm with its associated data to the list
329
    This routine adds the keyword nm with its associated data to the list
305
    of all keywords.
330
    of all keywords.
306
*/
331
*/
307
 
332
 
308
void add_keyword
333
void
309
    PROTO_N ( ( nm, data ) )
-
 
310
    PROTO_T ( char *nm X char **data )
334
add_keyword(char *nm, char **data)
311
{
335
{
312
    static int keywords_left = 0 ;
336
    static int keywords_left = 0;
313
    static keyword *keywords_free = NULL ;
337
    static keyword *keywords_free = NULL;
314
    keyword *p = keywords, *q = NULL ;
338
    keyword *p = keywords, *q = NULL;
315
    while ( p ) {
339
    while (p) {
316
	int c = strcmp ( nm, p->name ) ;
340
	int c = strcmp(nm, p->name);
317
	if ( c == 0 ) {
341
	if (c == 0) {
318
	    error ( ERROR_SERIOUS, "Keyword '%s' already defined", nm ) ;
342
	    error(ERROR_SERIOUS, "Keyword '%s' already defined", nm);
319
	    return ;
343
	    return;
320
	}
344
	}
321
	if ( c < 0 ) break ;
345
	if (c < 0)break;
322
	q = p ;
346
	q = p;
323
	p = p->next ;
347
	p = p->next;
324
    }
348
    }
325
    if ( keywords_left == 0 ) {
349
    if (keywords_left == 0) {
326
	keywords_left = 100 ;
350
	keywords_left = 100;
327
	keywords_free = xmalloc_nof ( keyword, keywords_left ) ;
351
	keywords_free = xmalloc_nof(keyword, keywords_left);
328
    }
352
    }
329
    p = keywords_free + ( --keywords_left ) ;
353
    p = keywords_free + (--keywords_left);
330
    p->name = nm ;
354
    p->name = nm;
331
    p->defn = data [0] ;
355
    p->defn = data [0];
332
    p->args = data [1] ;
356
    p->args = data [1];
333
    p->cond = data [2] ;
357
    p->cond = data [2];
334
    p->done = 0 ;
358
    p->done = 0;
335
    if ( q == NULL ) {
359
    if (q == NULL) {
336
	p->next = keywords ;
360
	p->next = keywords;
337
	keywords = p ;
361
	keywords = p;
338
    } else {
362
    } else {
339
	p->next = q->next ;
363
	p->next = q->next;
340
	q->next = p ;
364
	q->next = p;
341
    }
365
    }
342
    return ;
366
    return;
343
}
367
}