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 "system.h"
|
|
|
33 |
#include "version.h"
|
|
|
34 |
#include "c_types.h"
|
|
|
35 |
#include "hashid_ops.h"
|
|
|
36 |
#include "id_ops.h"
|
|
|
37 |
#include "nspace_ops.h"
|
|
|
38 |
#include "error.h"
|
|
|
39 |
#include "catalog.h"
|
|
|
40 |
#include "option.h"
|
|
|
41 |
#include "buffer.h"
|
|
|
42 |
#include "char.h"
|
|
|
43 |
#include "dump.h"
|
|
|
44 |
#include "file.h"
|
|
|
45 |
#include "hash.h"
|
|
|
46 |
#include "lex.h"
|
|
|
47 |
#include "literal.h"
|
|
|
48 |
#include "macro.h"
|
|
|
49 |
#include "namespace.h"
|
|
|
50 |
#include "predict.h"
|
|
|
51 |
#include "preproc.h"
|
|
|
52 |
#include "print.h"
|
|
|
53 |
#include "symbols.h"
|
|
|
54 |
#include "syntax.h"
|
|
|
55 |
#include "ustring.h"
|
|
|
56 |
#include "xalloc.h"
|
|
|
57 |
|
|
|
58 |
|
|
|
59 |
/*
|
|
|
60 |
LIST OF FREE LEXICAL TOKENS
|
|
|
61 |
|
|
|
62 |
All the free lexical tokens are formed into a list.
|
|
|
63 |
*/
|
|
|
64 |
|
|
|
65 |
PPTOKEN *free_tokens = NULL ;
|
|
|
66 |
static LIST ( PPTOKEN_P ) alloc_tokens = NULL_list ( PPTOKEN_P ) ;
|
|
|
67 |
|
|
|
68 |
|
|
|
69 |
/*
|
|
|
70 |
ALLOCATE A NEW TOKEN
|
|
|
71 |
|
|
|
72 |
This routine allocates a new token from the list free_tokens.
|
|
|
73 |
*/
|
|
|
74 |
|
|
|
75 |
PPTOKEN *new_pptok
|
|
|
76 |
PROTO_Z ()
|
|
|
77 |
{
|
|
|
78 |
PPTOKEN *p = free_tokens ;
|
|
|
79 |
if ( p == NULL ) {
|
|
|
80 |
PPTOKEN *q ;
|
|
|
81 |
int i, n = 2000 ;
|
|
|
82 |
p = xmalloc_nof ( PPTOKEN, n ) ;
|
|
|
83 |
CONS_pptok ( p, alloc_tokens, alloc_tokens ) ;
|
|
|
84 |
q = p ;
|
|
|
85 |
for ( i = 1 ; i < n ; i++ ) {
|
|
|
86 |
q->next = q + 1 ;
|
|
|
87 |
q++ ;
|
|
|
88 |
}
|
|
|
89 |
q->next = NULL ;
|
|
|
90 |
}
|
|
|
91 |
free_tokens = p->next ;
|
|
|
92 |
p->pp_opts = real_opts ;
|
|
|
93 |
return ( p ) ;
|
|
|
94 |
}
|
|
|
95 |
|
|
|
96 |
|
|
|
97 |
/*
|
|
|
98 |
FREE A SINGLE TOKEN
|
|
|
99 |
|
|
|
100 |
This macro frees the single token P by adding it to the list of all
|
|
|
101 |
free tokens.
|
|
|
102 |
*/
|
|
|
103 |
|
|
|
104 |
#define free_pptok( P )\
|
|
|
105 |
{\
|
|
|
106 |
( P )->next = free_tokens ;\
|
|
|
107 |
free_tokens = ( P ) ;\
|
|
|
108 |
}
|
|
|
109 |
|
|
|
110 |
|
|
|
111 |
/*
|
|
|
112 |
FREE A LIST OF TOKENS
|
|
|
113 |
|
|
|
114 |
This routine adds the list of tokens p to the list of all free tokens.
|
|
|
115 |
*/
|
|
|
116 |
|
|
|
117 |
void free_tok_list
|
|
|
118 |
PROTO_N ( ( p ) )
|
|
|
119 |
PROTO_T ( PPTOKEN *p )
|
|
|
120 |
{
|
|
|
121 |
PPTOKEN *q = p ;
|
|
|
122 |
if ( q == NULL ) return ;
|
|
|
123 |
while ( q->next ) q = q->next ;
|
|
|
124 |
q->next = free_tokens ;
|
|
|
125 |
free_tokens = p ;
|
|
|
126 |
return ;
|
|
|
127 |
}
|
|
|
128 |
|
|
|
129 |
|
|
|
130 |
/*
|
|
|
131 |
FREE ALL ALLOCATED PREPROCESSING TOKENS
|
|
|
132 |
|
|
|
133 |
This routine frees all the space allocated for preprocessing tokens.
|
|
|
134 |
It should only be called after the input has been completely processed.
|
|
|
135 |
*/
|
|
|
136 |
|
|
|
137 |
void term_macros
|
|
|
138 |
PROTO_Z ()
|
|
|
139 |
{
|
|
|
140 |
LIST ( PPTOKEN_P ) p = alloc_tokens ;
|
|
|
141 |
while ( !IS_NULL_list ( p ) ) {
|
|
|
142 |
PPTOKEN *q ;
|
|
|
143 |
DESTROY_CONS_pptok ( destroy, q, p, p ) ;
|
|
|
144 |
xfree_nof ( q ) ;
|
|
|
145 |
}
|
|
|
146 |
alloc_tokens = p ;
|
|
|
147 |
free_tokens = NULL ;
|
|
|
148 |
return ;
|
|
|
149 |
}
|
|
|
150 |
|
|
|
151 |
|
|
|
152 |
/*
|
|
|
153 |
COPY A TOKEN
|
|
|
154 |
|
|
|
155 |
This macro copies the contents of the token with token value T and data
|
|
|
156 |
Q into P.
|
|
|
157 |
*/
|
|
|
158 |
|
|
|
159 |
#define copy_pptok( P, T, Q )\
|
|
|
160 |
{\
|
|
|
161 |
( P )->tok = ( T ) ;\
|
|
|
162 |
( P )->pp_data = ( Q )->pp_data ;\
|
|
|
163 |
( P )->pp_opts = ( Q )->pp_opts ;\
|
|
|
164 |
( P )->pp_space = ( Q )->pp_space ;\
|
|
|
165 |
}
|
|
|
166 |
|
|
|
167 |
|
|
|
168 |
/*
|
|
|
169 |
ASSIGN TOKEN COMPONENTS
|
|
|
170 |
|
|
|
171 |
This routine assigns the token components for the token t, which has
|
|
|
172 |
just been read from the input file (or faked on occasions - these are
|
|
|
173 |
indicated) into p. It is only necessary to call this routine is T is
|
|
|
174 |
less than or equal to LAST_COMPLEX_TOKEN (defined in symbols.h). If any
|
|
|
175 |
cases are added to this routine then it may be necessary to change the
|
|
|
176 |
value of this macro.
|
|
|
177 |
*/
|
|
|
178 |
|
|
|
179 |
void token_parts
|
|
|
180 |
PROTO_N ( ( t, p ) )
|
|
|
181 |
PROTO_T ( int t X PPTOKEN *p )
|
|
|
182 |
{
|
|
|
183 |
switch ( t ) {
|
|
|
184 |
case lex_identifier : {
|
|
|
185 |
/* Identifiers */
|
|
|
186 |
HASHID nm = token_hashid ;
|
|
|
187 |
IDENTIFIER id = DEREF_id ( hashid_id ( nm ) ) ;
|
|
|
188 |
p->pp_data.id.hash = nm ;
|
|
|
189 |
p->pp_data.id.use = id ;
|
|
|
190 |
break ;
|
|
|
191 |
}
|
|
|
192 |
case lex_char_Hlit :
|
|
|
193 |
case lex_string_Hlit :
|
|
|
194 |
case lex_wchar_Hlit :
|
|
|
195 |
case lex_wstring_Hlit : {
|
|
|
196 |
/* String and character literals */
|
|
|
197 |
string s1 = token_buff.start ;
|
|
|
198 |
gen_size n = ( gen_size ) ( token_buff.posn - s1 ) ;
|
|
|
199 |
string s2 ;
|
|
|
200 |
if ( n < 2 ) {
|
|
|
201 |
/* Optimise for small strings */
|
|
|
202 |
s2 = xustrcpy ( s1 ) ;
|
|
|
203 |
} else {
|
|
|
204 |
s2 = xustr ( n + 1 ) ;
|
|
|
205 |
xumemcpy ( s2, s1, n ) ;
|
|
|
206 |
s2 [n] = 0 ;
|
|
|
207 |
}
|
|
|
208 |
p->pp_data.str.start = s2 ;
|
|
|
209 |
p->pp_data.str.end = s2 + n ;
|
|
|
210 |
break ;
|
|
|
211 |
}
|
|
|
212 |
case lex_integer_Hlit : {
|
|
|
213 |
/* Integer and floating-point literals */
|
|
|
214 |
p->pp_data.text = xustrcpy ( token_buff.start ) ;
|
|
|
215 |
break ;
|
|
|
216 |
}
|
|
|
217 |
case lex_hash_Hif :
|
|
|
218 |
case lex_hash_Helif : {
|
|
|
219 |
/* Target dependent conditionals */
|
|
|
220 |
p->pp_data.exp = crt_hash_if_exp ;
|
|
|
221 |
break ;
|
|
|
222 |
}
|
|
|
223 |
case lex_unknown : {
|
|
|
224 |
/* Unknown characters */
|
|
|
225 |
int i ;
|
|
|
226 |
string s1 = token_buff.start ;
|
|
|
227 |
string s2 = p->pp_data.buff ;
|
|
|
228 |
ASSERT ( MULTI_WIDTH <= sizeof ( p->pp_data.buff ) ) ;
|
|
|
229 |
for ( i = 0 ; i < MULTI_WIDTH ; i++ ) s2 [i] = s1 [i] ;
|
|
|
230 |
break ;
|
|
|
231 |
}
|
|
|
232 |
}
|
|
|
233 |
return ;
|
|
|
234 |
}
|
|
|
235 |
|
|
|
236 |
|
|
|
237 |
/*
|
|
|
238 |
REMOVE ANY IGNORED TOKENS FROM A LIST
|
|
|
239 |
|
|
|
240 |
This routine removes any ignored tokens from the list tok, returning
|
|
|
241 |
the result.
|
|
|
242 |
*/
|
|
|
243 |
|
|
|
244 |
PPTOKEN *clean_tok_list
|
|
|
245 |
PROTO_N ( ( toks ) )
|
|
|
246 |
PROTO_T ( PPTOKEN *toks )
|
|
|
247 |
{
|
|
|
248 |
unsigned long sp = 0 ;
|
|
|
249 |
PPTOKEN p0, *p = &p0 ;
|
|
|
250 |
PPTOKEN *q ;
|
|
|
251 |
p->next = toks ;
|
|
|
252 |
while ( q = p->next, q != NULL ) {
|
|
|
253 |
if ( q->tok == lex_ignore_token ) {
|
|
|
254 |
sp |= q->pp_space ;
|
|
|
255 |
p->next = q->next ;
|
|
|
256 |
free_pptok ( q ) ;
|
|
|
257 |
q = p->next ;
|
|
|
258 |
if ( q == NULL ) break ;
|
|
|
259 |
} else {
|
|
|
260 |
if ( sp ) {
|
|
|
261 |
q->pp_space |= sp ;
|
|
|
262 |
sp = 0 ;
|
|
|
263 |
}
|
|
|
264 |
}
|
|
|
265 |
p = q ;
|
|
|
266 |
}
|
|
|
267 |
return ( p0.next ) ;
|
|
|
268 |
}
|
|
|
269 |
|
|
|
270 |
|
|
|
271 |
/*
|
|
|
272 |
READ A LINE OF TOKENS
|
|
|
273 |
|
|
|
274 |
This routine reads the sequence of preprocessing tokens comprising a
|
|
|
275 |
preprocessing directive (for example, a macro definition). If t1 is
|
|
|
276 |
not lex_ignore_token then it is taken to be the first token in the
|
|
|
277 |
definition, similarly tn gives the last token.
|
|
|
278 |
*/
|
|
|
279 |
|
|
|
280 |
PPTOKEN *read_line
|
|
|
281 |
PROTO_N ( ( t1, tn ) )
|
|
|
282 |
PROTO_T ( int t1 X int tn )
|
|
|
283 |
{
|
|
|
284 |
int t = t1 ;
|
|
|
285 |
unsigned long sp = 0 ;
|
|
|
286 |
PPTOKEN dummy_tok, *this_tok = &dummy_tok ;
|
|
|
287 |
if ( t == lex_ignore_token ) {
|
|
|
288 |
t = read_token () ;
|
|
|
289 |
update_column () ;
|
|
|
290 |
if ( in_preproc_dir ) preproc_loc = crt_loc ;
|
|
|
291 |
}
|
|
|
292 |
while ( t != lex_newline && t != lex_eof ) {
|
|
|
293 |
this_tok->next = new_pptok () ;
|
|
|
294 |
this_tok = this_tok->next ;
|
|
|
295 |
this_tok->tok = t ;
|
|
|
296 |
if ( t <= LAST_COMPLEX_TOKEN ) token_parts ( t, this_tok ) ;
|
|
|
297 |
this_tok->pp_space = ( sp & WHITE_MASK ) ;
|
|
|
298 |
sp = skip_white ( 0 ) ;
|
|
|
299 |
t = read_token () ;
|
|
|
300 |
update_column () ;
|
|
|
301 |
if ( in_preproc_dir ) preproc_loc = crt_loc ;
|
|
|
302 |
}
|
|
|
303 |
if ( tn != lex_ignore_token ) {
|
|
|
304 |
this_tok->next = new_pptok () ;
|
|
|
305 |
this_tok = this_tok->next ;
|
|
|
306 |
this_tok->tok = tn ;
|
|
|
307 |
token_parts ( tn, this_tok ) ;
|
|
|
308 |
this_tok->pp_space = ( sp & WHITE_MASK ) ;
|
|
|
309 |
}
|
|
|
310 |
this_tok->next = NULL ;
|
|
|
311 |
if ( in_preproc_dir ) IGNORE skip_to_end () ;
|
|
|
312 |
return ( dummy_tok.next ) ;
|
|
|
313 |
}
|
|
|
314 |
|
|
|
315 |
|
|
|
316 |
/*
|
|
|
317 |
COPY A LIST OF TOKENS
|
|
|
318 |
|
|
|
319 |
This routine copies the list of tokens toks, excluding any ignored
|
|
|
320 |
tokens.
|
|
|
321 |
*/
|
|
|
322 |
|
|
|
323 |
static PPTOKEN *copy_tok_list
|
|
|
324 |
PROTO_N ( ( toks ) )
|
|
|
325 |
PROTO_T ( PPTOKEN *toks )
|
|
|
326 |
{
|
|
|
327 |
PPTOKEN *ptr_tok ;
|
|
|
328 |
PPTOKEN dummy_tok, *this_tok = &dummy_tok ;
|
|
|
329 |
for ( ptr_tok = toks ; ptr_tok != NULL ; ptr_tok = ptr_tok->next ) {
|
|
|
330 |
int t = ptr_tok->tok ;
|
|
|
331 |
if ( t != lex_ignore_token ) {
|
|
|
332 |
this_tok->next = new_pptok () ;
|
|
|
333 |
this_tok = this_tok->next ;
|
|
|
334 |
copy_pptok ( this_tok, t, ptr_tok ) ;
|
|
|
335 |
}
|
|
|
336 |
}
|
|
|
337 |
this_tok->next = NULL ;
|
|
|
338 |
return ( dummy_tok.next ) ;
|
|
|
339 |
}
|
|
|
340 |
|
|
|
341 |
|
|
|
342 |
/*
|
|
|
343 |
STRINGISE A LIST OF TOKENS
|
|
|
344 |
|
|
|
345 |
This routine turns the list of tokens toks into a string. The result
|
|
|
346 |
is built up in token_buff. If esc is true then any '"' (or whatever
|
|
|
347 |
the value of quote is) and '\' characters in string and character
|
|
|
348 |
literals (including the initial and terminating quotes) are preceded
|
|
|
349 |
by a '\'. This routine is used in the implementation of the # operator,
|
|
|
350 |
in macro #include directives and a couple of other preprocessing
|
|
|
351 |
directives. It returns 1 to indicate a valid string.
|
|
|
352 |
*/
|
|
|
353 |
|
|
|
354 |
int quote_tok_list
|
|
|
355 |
PROTO_N ( ( toks, esc, quote ) )
|
|
|
356 |
PROTO_T ( PPTOKEN *toks X int esc X int quote )
|
|
|
357 |
{
|
|
|
358 |
int res = 1 ;
|
|
|
359 |
string st, se ;
|
|
|
360 |
int started = 0 ;
|
|
|
361 |
int escaped = 0 ;
|
|
|
362 |
PPTOKEN *ptr_tok ;
|
|
|
363 |
character qo = ( character ) quote ;
|
|
|
364 |
BUFFER *bf = clear_buffer ( &token_buff, NIL ( FILE ) ) ;
|
|
|
365 |
|
|
|
366 |
/* Scan through tokens */
|
|
|
367 |
for ( ptr_tok = toks ; ptr_tok != NULL ; ptr_tok = ptr_tok->next ) {
|
|
|
368 |
character p, q ;
|
|
|
369 |
int t = ptr_tok->tok ;
|
|
|
370 |
if ( t == lex_ignore_token ) continue ;
|
|
|
371 |
|
|
|
372 |
/* Print initial space if necessary */
|
|
|
373 |
if ( ptr_tok->pp_space && started ) bfputc ( bf, char_space ) ;
|
|
|
374 |
|
|
|
375 |
/* Find the token name */
|
|
|
376 |
switch ( t ) {
|
|
|
377 |
case lex_identifier : {
|
|
|
378 |
/* Identifiers */
|
|
|
379 |
HASHID nm = ptr_tok->pp_data.id.hash ;
|
|
|
380 |
st = DEREF_string ( hashid_name_etc_text ( nm ) ) ;
|
|
|
381 |
bfputs ( bf, st ) ;
|
|
|
382 |
break ;
|
|
|
383 |
}
|
|
|
384 |
case lex_integer_Hlit : {
|
|
|
385 |
/* Integer and floating-point literals */
|
|
|
386 |
st = ptr_tok->pp_data.text ;
|
|
|
387 |
bfputs ( bf, st ) ;
|
|
|
388 |
break ;
|
|
|
389 |
}
|
|
|
390 |
case lex_char_Hlit : {
|
|
|
391 |
/* Character literals */
|
|
|
392 |
p = 0 ;
|
|
|
393 |
q = char_single_quote ;
|
|
|
394 |
string_label : {
|
|
|
395 |
st = ptr_tok->pp_data.str.start ;
|
|
|
396 |
se = ptr_tok->pp_data.str.end ;
|
|
|
397 |
|
|
|
398 |
/* Prefix and opening quote */
|
|
|
399 |
if ( p ) bfputc ( bf, ( int ) p ) ;
|
|
|
400 |
if ( esc && q == qo ) bfputc ( bf, char_backslash ) ;
|
|
|
401 |
bfputc ( bf, ( int ) q ) ;
|
|
|
402 |
|
|
|
403 |
/* Copy string */
|
|
|
404 |
while ( st != se ) {
|
|
|
405 |
character c = *( st++ ) ;
|
|
|
406 |
if ( c == qo || c == char_backslash ) {
|
|
|
407 |
/* Escaped characters */
|
|
|
408 |
if ( esc ) bfputc ( bf, char_backslash ) ;
|
|
|
409 |
}
|
|
|
410 |
bfputc ( bf, ( int ) c ) ;
|
|
|
411 |
}
|
|
|
412 |
|
|
|
413 |
/* Closing quote */
|
|
|
414 |
if ( esc && q == qo ) bfputc ( bf, char_backslash ) ;
|
|
|
415 |
bfputc ( bf, ( int ) q ) ;
|
|
|
416 |
}
|
|
|
417 |
break ;
|
|
|
418 |
}
|
|
|
419 |
case lex_wchar_Hlit : {
|
|
|
420 |
/* Wide character literals */
|
|
|
421 |
p = char_L ;
|
|
|
422 |
q = char_single_quote ;
|
|
|
423 |
goto string_label ;
|
|
|
424 |
}
|
|
|
425 |
case lex_string_Hlit : {
|
|
|
426 |
/* String literals */
|
|
|
427 |
p = 0 ;
|
|
|
428 |
q = char_quote ;
|
|
|
429 |
goto string_label ;
|
|
|
430 |
}
|
|
|
431 |
case lex_wstring_Hlit : {
|
|
|
432 |
/* Wide string literals */
|
|
|
433 |
p = char_L ;
|
|
|
434 |
q = char_quote ;
|
|
|
435 |
goto string_label ;
|
|
|
436 |
}
|
|
|
437 |
case lex_unknown : {
|
|
|
438 |
/* Unknown characters */
|
|
|
439 |
unsigned long u ;
|
|
|
440 |
int ch = CHAR_SIMPLE ;
|
|
|
441 |
u = get_multi_char ( ptr_tok->pp_data.buff, &ch ) ;
|
|
|
442 |
if ( ch == CHAR_SIMPLE ) {
|
|
|
443 |
bfputc ( bf, ( int ) u ) ;
|
|
|
444 |
} else {
|
|
|
445 |
print_char ( u, ch, 0, bf ) ;
|
|
|
446 |
}
|
|
|
447 |
break ;
|
|
|
448 |
}
|
|
|
449 |
case lex_macro_Harg : {
|
|
|
450 |
/* Macro parameters */
|
|
|
451 |
HASHID nm = ptr_tok->pp_data.par.hash ;
|
|
|
452 |
st = DEREF_string ( hashid_name_etc_text ( nm ) ) ;
|
|
|
453 |
bfputs ( bf, st ) ;
|
|
|
454 |
break ;
|
|
|
455 |
}
|
|
|
456 |
default : {
|
|
|
457 |
/* Symbols */
|
|
|
458 |
st = token_name ( t ) ;
|
|
|
459 |
bfputs ( bf, st ) ;
|
|
|
460 |
break ;
|
|
|
461 |
}
|
|
|
462 |
}
|
|
|
463 |
started = 1 ;
|
|
|
464 |
}
|
|
|
465 |
|
|
|
466 |
/* End of string */
|
|
|
467 |
bfputc ( bf, 0 ) ;
|
|
|
468 |
bf->posn-- ;
|
|
|
469 |
|
|
|
470 |
/* Check for legal strings */
|
|
|
471 |
st = bf->start ;
|
|
|
472 |
se = bf->posn ;
|
|
|
473 |
while ( st != se ) {
|
|
|
474 |
if ( escaped ) {
|
|
|
475 |
escaped = 0 ;
|
|
|
476 |
} else {
|
|
|
477 |
character c = *st ;
|
|
|
478 |
if ( c == qo ) res = 0 ;
|
|
|
479 |
if ( c == char_backslash ) escaped = 1 ;
|
|
|
480 |
}
|
|
|
481 |
st++ ;
|
|
|
482 |
}
|
|
|
483 |
if ( escaped ) res = 0 ;
|
|
|
484 |
return ( res ) ;
|
|
|
485 |
}
|
|
|
486 |
|
|
|
487 |
|
|
|
488 |
/*
|
|
|
489 |
CONCATENATE TWO TOKENS
|
|
|
490 |
|
|
|
491 |
This routine concatenates the two tokens p and q into a single token.
|
|
|
492 |
This is used to implement the ## operator. If the result is a valid
|
|
|
493 |
preprocessing token then p is overwritten by the result and 1 is
|
|
|
494 |
returned. Otherwise p and q are unchanged and 0 is returned.
|
|
|
495 |
*/
|
|
|
496 |
|
|
|
497 |
static int concat_pptoks
|
|
|
498 |
PROTO_N ( ( p, q ) )
|
|
|
499 |
PROTO_T ( PPTOKEN *p X PPTOKEN *q )
|
|
|
500 |
{
|
|
|
501 |
int a = p->tok ;
|
|
|
502 |
int b = q->tok ;
|
|
|
503 |
unsigned long sa = p->pp_space ;
|
|
|
504 |
unsigned long sb = q->pp_space ;
|
|
|
505 |
p->pp_space = ( sa | sb ) ;
|
|
|
506 |
q->pp_space = 0 ;
|
|
|
507 |
if ( a >= FIRST_SYMBOL && a <= LAST_SYMBOL ) {
|
|
|
508 |
if ( b >= FIRST_SYMBOL && b <= LAST_SYMBOL ) {
|
|
|
509 |
/* Two symbols may combine to give another symbol */
|
|
|
510 |
int c ;
|
|
|
511 |
string s = token_buff.start ;
|
|
|
512 |
ustrcpy_v ( s, token_name ( a ) ) ;
|
|
|
513 |
ustrcpy_v ( s + ustrlen ( s ), token_name ( b ) ) ;
|
|
|
514 |
for ( c = FIRST_SYMBOL ; c <= LAST_SYMBOL ; c++ ) {
|
|
|
515 |
if ( ustreq ( s, token_name ( c ) ) ) {
|
|
|
516 |
/* Token found - check options */
|
|
|
517 |
p->tok = c ;
|
|
|
518 |
if ( c >= FIRST_C_SYMBOL && c <= LAST_C_SYMBOL ) {
|
|
|
519 |
return ( 1 ) ;
|
|
|
520 |
}
|
|
|
521 |
#if LANGUAGE_CPP
|
|
|
522 |
if ( c >= FIRST_CPP_SYMBOL && c <= LAST_CPP_SYMBOL ) {
|
|
|
523 |
return ( 1 ) ;
|
|
|
524 |
}
|
|
|
525 |
#endif
|
|
|
526 |
if ( c >= FIRST_EXTRA_SYMBOL && c <= LAST_EXTRA_SYMBOL ) {
|
|
|
527 |
if ( allow_extra_symbols ) return ( 1 ) ;
|
|
|
528 |
}
|
|
|
529 |
if ( c >= FIRST_DIGRAPH && c <= LAST_DIGRAPH ) {
|
|
|
530 |
if ( allow_digraphs ) return ( 1 ) ;
|
|
|
531 |
}
|
|
|
532 |
p->tok = a ;
|
|
|
533 |
}
|
|
|
534 |
}
|
|
|
535 |
return ( 0 ) ;
|
|
|
536 |
|
|
|
537 |
} else if ( a == lex_dot && b == lex_integer_Hlit ) {
|
|
|
538 |
/* A dot may start a number */
|
|
|
539 |
string s = q->pp_data.text ;
|
|
|
540 |
if ( s [0] == char_dot ) return ( 0 ) ;
|
|
|
541 |
p->tok = lex_integer_Hlit ;
|
|
|
542 |
p->pp_data.text = xustrcat ( token_name ( a ), s ) ;
|
|
|
543 |
return ( 1 ) ;
|
|
|
544 |
|
|
|
545 |
} else if ( a == lex_backslash && b == lex_identifier ) {
|
|
|
546 |
/* A backslash may start a universal character */
|
|
|
547 |
/* NOT YET IMPLEMENTED */
|
|
|
548 |
/* EMPTY */
|
|
|
549 |
}
|
|
|
550 |
|
|
|
551 |
} else if ( a == lex_identifier ) {
|
|
|
552 |
HASHID nm = p->pp_data.id.hash ;
|
|
|
553 |
string s = DEREF_string ( hashid_name_etc_text ( nm ) ) ;
|
|
|
554 |
if ( b == lex_identifier ) {
|
|
|
555 |
/* Two identifiers give another identifier */
|
|
|
556 |
HASHID nm2 = q->pp_data.id.hash ;
|
|
|
557 |
string s2 = DEREF_string ( hashid_name_etc_text ( nm2 ) ) ;
|
|
|
558 |
s = xustrcat ( s, s2 ) ;
|
|
|
559 |
nm = lookup_name ( s, hash ( s ), 2, lex_identifier ) ;
|
|
|
560 |
p->pp_data.id.hash = nm ;
|
|
|
561 |
p->pp_data.id.use = DEREF_id ( hashid_id ( nm ) ) ;
|
|
|
562 |
return ( 1 ) ;
|
|
|
563 |
|
|
|
564 |
} else if ( b == lex_integer_Hlit ) {
|
|
|
565 |
/* An identifier and a number may give an identifier */
|
|
|
566 |
character c ;
|
|
|
567 |
string n = q->pp_data.text ;
|
|
|
568 |
while ( c = *( n++ ), c != 0 ) {
|
|
|
569 |
if ( c == char_dot || c == char_plus || c == char_minus ) {
|
|
|
570 |
/* The number must be entirely alphanumeric */
|
|
|
571 |
return ( 0 ) ;
|
|
|
572 |
}
|
|
|
573 |
}
|
|
|
574 |
s = xustrcat ( s, q->pp_data.text ) ;
|
|
|
575 |
nm = lookup_name ( s, hash ( s ), 2, lex_identifier ) ;
|
|
|
576 |
p->pp_data.id.hash = nm ;
|
|
|
577 |
p->pp_data.id.use = DEREF_id ( hashid_id ( nm ) ) ;
|
|
|
578 |
return ( 1 ) ;
|
|
|
579 |
|
|
|
580 |
} else if ( s [0] == char_L && s [1] == 0 ) {
|
|
|
581 |
/* An L may start a wide character or string */
|
|
|
582 |
if ( b == lex_char_Hlit ) {
|
|
|
583 |
p->tok = lex_wchar_Hlit ;
|
|
|
584 |
p->pp_data.str.start = q->pp_data.str.start ;
|
|
|
585 |
p->pp_data.str.end = q->pp_data.str.end ;
|
|
|
586 |
return ( 1 ) ;
|
|
|
587 |
} else if ( b == lex_string_Hlit ) {
|
|
|
588 |
p->tok = lex_wstring_Hlit ;
|
|
|
589 |
p->pp_data.str.start = q->pp_data.str.start ;
|
|
|
590 |
p->pp_data.str.end = q->pp_data.str.end ;
|
|
|
591 |
return ( 1 ) ;
|
|
|
592 |
}
|
|
|
593 |
}
|
|
|
594 |
|
|
|
595 |
} else if ( a == lex_integer_Hlit ) {
|
|
|
596 |
string s = p->pp_data.text ;
|
|
|
597 |
if ( b == lex_identifier ) {
|
|
|
598 |
/* A number followed by an identifier is a number */
|
|
|
599 |
HASHID nm = q->pp_data.id.hash ;
|
|
|
600 |
string s2 = DEREF_string ( hashid_name_etc_text ( nm ) ) ;
|
|
|
601 |
p->pp_data.text = xustrcat ( s, s2 ) ;
|
|
|
602 |
return ( 1 ) ;
|
|
|
603 |
|
|
|
604 |
} else if ( b == lex_integer_Hlit ) {
|
|
|
605 |
/* Two numbers form another number */
|
|
|
606 |
string s2 = q->pp_data.text ;
|
|
|
607 |
p->pp_data.text = xustrcat ( s, s2 ) ;
|
|
|
608 |
return ( 1 ) ;
|
|
|
609 |
|
|
|
610 |
} else if ( b == lex_dot || b == lex_ellipsis ) {
|
|
|
611 |
/* A number followed by a sequence of dots is a number */
|
|
|
612 |
p->pp_data.text = xustrcat ( s, token_name ( b ) ) ;
|
|
|
613 |
return ( 1 ) ;
|
|
|
614 |
|
|
|
615 |
} else if ( b == lex_plus || b == lex_minus ) {
|
|
|
616 |
/* A sign may terminate a number after e or E */
|
|
|
617 |
unsigned n = ( unsigned ) ustrlen ( s ) - 1 ;
|
|
|
618 |
if ( s [n] == char_e || s [n] == char_E ) {
|
|
|
619 |
p->pp_data.text = xustrcat ( s, token_name ( b ) ) ;
|
|
|
620 |
return ( 1 ) ;
|
|
|
621 |
}
|
|
|
622 |
}
|
|
|
623 |
}
|
|
|
624 |
return ( 0 ) ;
|
|
|
625 |
}
|
|
|
626 |
|
|
|
627 |
|
|
|
628 |
/*
|
|
|
629 |
DUMMY LOCATION FOR INPUT FILE
|
|
|
630 |
|
|
|
631 |
This dummy location represents tokens read directly from the input file.
|
|
|
632 |
If present, it will always be the last element of a list of token
|
|
|
633 |
locations.
|
|
|
634 |
*/
|
|
|
635 |
|
|
|
636 |
static PPTOKEN *dummy_loc_toks = NULL ;
|
|
|
637 |
static TOKEN_LOC dummy_loc = { &dummy_loc_toks, NULL } ;
|
|
|
638 |
TOKEN_LOC *file_loc = &dummy_loc ;
|
|
|
639 |
|
|
|
640 |
|
|
|
641 |
/*
|
|
|
642 |
FORWARD DECLARATION
|
|
|
643 |
|
|
|
644 |
The functions expand_macro, expand_toks and expand_tok_list are defined
|
|
|
645 |
recursively. This gives the necessary forward declarations.
|
|
|
646 |
*/
|
|
|
647 |
|
|
|
648 |
static PPTOKEN *expand_toks PROTO_S ( ( PPTOKEN *, TOKEN_LOC *, int ) ) ;
|
|
|
649 |
|
|
|
650 |
|
|
|
651 |
/*
|
|
|
652 |
HANDLE OLD STYLE STRINGISING
|
|
|
653 |
|
|
|
654 |
This routine handles the old style stringising for the definition defn
|
|
|
655 |
for the given macro. Argument replacement has already been performed
|
|
|
656 |
on defn. If this facility is enabled then in macro definitions of the
|
|
|
657 |
form:
|
|
|
658 |
|
|
|
659 |
#define f( X ) "X"
|
|
|
660 |
|
|
|
661 |
quotes are classified as unknown characters rather than string
|
|
|
662 |
terminators. This means that the X is recognised as a macro parameter
|
|
|
663 |
and is replaced during argument replacement. The job of this routine
|
|
|
664 |
is to spot these unrecognised quotes and turn them into proper strings.
|
|
|
665 |
*/
|
|
|
666 |
|
|
|
667 |
PPTOKEN *recognise_strings
|
|
|
668 |
PROTO_N ( ( defn, macro, act ) )
|
|
|
669 |
PROTO_T ( PPTOKEN *defn X HASHID macro X int act )
|
|
|
670 |
{
|
|
|
671 |
PPTOKEN *this_tok = defn ;
|
|
|
672 |
PPTOKEN *last_tok = defn ;
|
|
|
673 |
while ( this_tok != NULL ) {
|
|
|
674 |
if ( this_tok->tok == lex_unknown ) {
|
|
|
675 |
unsigned long u ;
|
|
|
676 |
int ch = CHAR_SIMPLE ;
|
|
|
677 |
character qo = char_question ;
|
|
|
678 |
u = get_multi_char ( this_tok->pp_data.buff, &ch ) ;
|
|
|
679 |
if ( ch == CHAR_SIMPLE ) qo = ( character ) u ;
|
|
|
680 |
if ( qo == char_quote || qo == char_single_quote ) {
|
|
|
681 |
/* Start of string */
|
|
|
682 |
int t ;
|
|
|
683 |
int escaped = 0 ;
|
|
|
684 |
PPTOKEN *next_tok = this_tok->next ;
|
|
|
685 |
PPTOKEN *ptr_tok = next_tok ;
|
|
|
686 |
while ( ptr_tok != NULL ) {
|
|
|
687 |
t = ptr_tok->tok ;
|
|
|
688 |
if ( t == lex_macro_Harg ) {
|
|
|
689 |
HASHID nm = ptr_tok->pp_data.par.hash ;
|
|
|
690 |
ERROR err = ERR_cpp_stringize_old ( nm, macro ) ;
|
|
|
691 |
report ( preproc_loc, err ) ;
|
|
|
692 |
}
|
|
|
693 |
if ( escaped ) {
|
|
|
694 |
escaped = 0 ;
|
|
|
695 |
} else if ( t == lex_unknown ) {
|
|
|
696 |
character qc = char_question ;
|
|
|
697 |
u = get_multi_char ( ptr_tok->pp_data.buff, &ch ) ;
|
|
|
698 |
if ( ch == CHAR_SIMPLE ) qc = ( character ) u ;
|
|
|
699 |
if ( qc == qo ) break ;
|
|
|
700 |
if ( qc == char_backslash ) escaped = 1 ;
|
|
|
701 |
}
|
|
|
702 |
ptr_tok = ptr_tok->next ;
|
|
|
703 |
}
|
|
|
704 |
if ( act ) {
|
|
|
705 |
if ( ptr_tok == NULL ) {
|
|
|
706 |
/* No closing quote */
|
|
|
707 |
report ( crt_loc, ERR_cpp_stringize_bad ( macro ) ) ;
|
|
|
708 |
this_tok->next = NULL ;
|
|
|
709 |
} else {
|
|
|
710 |
ptr_tok->tok = lex_ignore_token ;
|
|
|
711 |
this_tok->next = ptr_tok->next ;
|
|
|
712 |
ptr_tok->next = NULL ;
|
|
|
713 |
}
|
|
|
714 |
|
|
|
715 |
/* Form the string */
|
|
|
716 |
if ( !quote_tok_list ( next_tok, 0, ( int ) qo ) ) {
|
|
|
717 |
report ( crt_loc, ERR_cpp_stringize_bad ( macro ) ) ;
|
|
|
718 |
}
|
|
|
719 |
t = ( qo == char_quote ? lex_string_Hlit : lex_char_Hlit ) ;
|
|
|
720 |
this_tok->tok = t ;
|
|
|
721 |
token_parts ( t, this_tok ) ;
|
|
|
722 |
free_tok_list ( next_tok ) ;
|
|
|
723 |
|
|
|
724 |
/* Check for wide strings */
|
|
|
725 |
if ( last_tok->tok == lex_identifier ) {
|
|
|
726 |
string s ;
|
|
|
727 |
HASHID nm = last_tok->pp_data.id.hash ;
|
|
|
728 |
s = DEREF_string ( hashid_name_etc_text ( nm ) ) ;
|
|
|
729 |
if ( s [0] == char_L && s [1] == 0 ) {
|
|
|
730 |
if ( t == lex_string_Hlit ) {
|
|
|
731 |
t = lex_wstring_Hlit ;
|
|
|
732 |
} else {
|
|
|
733 |
t = lex_wchar_Hlit ;
|
|
|
734 |
}
|
|
|
735 |
copy_pptok ( last_tok, t, this_tok ) ;
|
|
|
736 |
last_tok->next = this_tok->next ;
|
|
|
737 |
free_pptok ( this_tok ) ;
|
|
|
738 |
this_tok = last_tok ;
|
|
|
739 |
}
|
|
|
740 |
}
|
|
|
741 |
}
|
|
|
742 |
}
|
|
|
743 |
}
|
|
|
744 |
last_tok = this_tok ;
|
|
|
745 |
this_tok = this_tok->next ;
|
|
|
746 |
}
|
|
|
747 |
return ( defn ) ;
|
|
|
748 |
}
|
|
|
749 |
|
|
|
750 |
|
|
|
751 |
/*
|
|
|
752 |
HANDLE TOKEN CONCATENATION
|
|
|
753 |
|
|
|
754 |
This routine handles any ## operators in the definition defn of the
|
|
|
755 |
given macro. Note that any initial or terminal ## operators have
|
|
|
756 |
already been reported.
|
|
|
757 |
*/
|
|
|
758 |
|
|
|
759 |
static PPTOKEN *process_concat
|
|
|
760 |
PROTO_N ( ( defn, macro ) )
|
|
|
761 |
PROTO_T ( PPTOKEN *defn X HASHID macro )
|
|
|
762 |
{
|
|
|
763 |
PPTOKEN *this_tok ;
|
|
|
764 |
while ( defn && defn->tok == lex_hash_Hhash_Hop ) {
|
|
|
765 |
/* Check for initial ## */
|
|
|
766 |
this_tok = defn ;
|
|
|
767 |
defn = defn->next ;
|
|
|
768 |
free_pptok ( this_tok ) ;
|
|
|
769 |
}
|
|
|
770 |
this_tok = defn ;
|
|
|
771 |
while ( this_tok != NULL ) {
|
|
|
772 |
PPTOKEN *next_tok = this_tok->next ;
|
|
|
773 |
if ( next_tok == NULL ) break ;
|
|
|
774 |
if ( next_tok->tok == lex_hash_Hhash_Hop ) {
|
|
|
775 |
/* Delete the ## */
|
|
|
776 |
this_tok->next = next_tok->next ;
|
|
|
777 |
free_pptok ( next_tok ) ;
|
|
|
778 |
|
|
|
779 |
/* Check for terminal ## */
|
|
|
780 |
if ( this_tok->next == NULL ) break ;
|
|
|
781 |
|
|
|
782 |
/* Do the token concatenation */
|
|
|
783 |
if ( concat_pptoks ( this_tok, this_tok->next ) ) {
|
|
|
784 |
/* Delete the second argument if successful */
|
|
|
785 |
next_tok = this_tok->next ;
|
|
|
786 |
this_tok->next = next_tok->next ;
|
|
|
787 |
free_pptok ( next_tok ) ;
|
|
|
788 |
} else {
|
|
|
789 |
report ( crt_loc, ERR_cpp_concat_bad ( macro ) ) ;
|
|
|
790 |
}
|
|
|
791 |
/* Now reprocess this_tok */
|
|
|
792 |
} else {
|
|
|
793 |
this_tok = next_tok ;
|
|
|
794 |
}
|
|
|
795 |
}
|
|
|
796 |
return ( defn ) ;
|
|
|
797 |
}
|
|
|
798 |
|
|
|
799 |
|
|
|
800 |
/*
|
|
|
801 |
MAXIMUM NUMBER OF MACRO PARAMETERS
|
|
|
802 |
|
|
|
803 |
This macro defines the maximum number of macro parameters which
|
|
|
804 |
expand_macro can handle without having to allocate temporary space
|
|
|
805 |
to hold them. With allocation the number of parameters is unlimited.
|
|
|
806 |
*/
|
|
|
807 |
|
|
|
808 |
#define MAX_MACRO_PARAMS 256
|
|
|
809 |
|
|
|
810 |
|
|
|
811 |
/*
|
|
|
812 |
EXPAND A MACRO DEFINITION
|
|
|
813 |
|
|
|
814 |
This routine expands the macro given by the hash table entry macro.
|
|
|
815 |
The argument locs gives a list of locations where macro arguments can
|
|
|
816 |
be read from. locs will never be NULL. The argument complete is true
|
|
|
817 |
to indicate that this is a complete macro expansion, and that any
|
|
|
818 |
argument errors should be reported. If locs contains file_loc then
|
|
|
819 |
complete will always be true. When reading from file_loc we always
|
|
|
820 |
set in_preproc_dir to 2 to make read_token return lex_eof at the end
|
|
|
821 |
of each file, rather than automatically reverting to the including
|
|
|
822 |
file, and to cause it to ignore any preprocessing directives.
|
|
|
823 |
|
|
|
824 |
Note that the entry for the macro in the hash table is marked during
|
|
|
825 |
expansion to prevent recursive expansions. Several points concerning
|
|
|
826 |
macro expansion are undefined; in this implementation:
|
|
|
827 |
|
|
|
828 |
1. Firstly, # operators are evaluated from left to right;
|
|
|
829 |
2. Secondly, ## operators are evaluated from left to right;
|
|
|
830 |
3. If a ## b is not a valid preprocessing token then it is
|
|
|
831 |
resolved to a b;
|
|
|
832 |
4. A # operator in a function-like macro which is not followed
|
|
|
833 |
by a macro argument is ignored (it is left as # in object-like
|
|
|
834 |
macros of course);
|
|
|
835 |
5. A ## operator at the start or end of a macro is ignored;
|
|
|
836 |
6. Any preprocessing directives in the macro arguments are treated
|
|
|
837 |
as normal sequences of preprocessing tokens.
|
|
|
838 |
|
|
|
839 |
A further undefined area concerns the ban on recursive macro expansions.
|
|
|
840 |
This is extended from the macro definition itself to any extra tokens
|
|
|
841 |
which are read during the expansion of the macro definition. For
|
|
|
842 |
example, in:
|
|
|
843 |
|
|
|
844 |
#define f( a ) a * g
|
|
|
845 |
#define g( a ) f ( a )
|
|
|
846 |
f ( 2 ) ( 9 )
|
|
|
847 |
|
|
|
848 |
the result is '2 * f ( 9 )', rather than '2 * 9 * g'.
|
|
|
849 |
*/
|
|
|
850 |
|
|
|
851 |
PPTOKEN *expand_macro
|
|
|
852 |
PROTO_N ( ( macro, locs, complete ) )
|
|
|
853 |
PROTO_T ( HASHID macro X TOKEN_LOC *locs X int complete )
|
|
|
854 |
{
|
|
|
855 |
LOCATION loc ;
|
|
|
856 |
int state = 0 ;
|
|
|
857 |
PPTOKEN *defn ;
|
|
|
858 |
unsigned long sp = 0 ;
|
|
|
859 |
unsigned no_pars = 0 ;
|
|
|
860 |
int have_unknown = 0 ;
|
|
|
861 |
int have_hash_hash = 0 ;
|
|
|
862 |
unsigned long ws = crt_spaces ;
|
|
|
863 |
PPTOKEN dummy_tok, *this_tok = &dummy_tok ;
|
|
|
864 |
PPTOKEN *arg_array_base [ MAX_MACRO_PARAMS + 1 ] ;
|
|
|
865 |
PPTOKEN **arg_array = arg_array_base ;
|
|
|
866 |
|
|
|
867 |
/* Get the macro identifier */
|
|
|
868 |
IDENTIFIER id = DEREF_id ( hashid_id ( macro ) ) ;
|
|
|
869 |
unsigned tag = TAG_id ( id ) ;
|
|
|
870 |
DECL_SPEC ds = DEREF_dspec ( id_storage ( id ) ) ;
|
|
|
871 |
|
|
|
872 |
/* Mark the macro as being used */
|
|
|
873 |
loc = crt_loc ;
|
|
|
874 |
ds |= dspec_used ;
|
|
|
875 |
COPY_dspec ( id_storage ( id ), ds ) ;
|
|
|
876 |
if ( do_macro && do_usage ) dump_use ( id, &crt_loc, 1 ) ;
|
|
|
877 |
|
|
|
878 |
/* Get macro definition and other data */
|
|
|
879 |
if ( tag == id_obj_macro_tag ) {
|
|
|
880 |
/* Object-like macros */
|
|
|
881 |
defn = DEREF_pptok ( id_obj_macro_defn ( id ) ) ;
|
|
|
882 |
if ( defn == NULL ) return ( NULL ) ;
|
|
|
883 |
|
|
|
884 |
if ( ds & dspec_builtin ) {
|
|
|
885 |
/* Check built-in macros */
|
|
|
886 |
int t = defn->tok ;
|
|
|
887 |
if ( t == lex_builtin_Hline ) {
|
|
|
888 |
/* Construct an integer literal for __LINE__ */
|
|
|
889 |
BUFFER *bf = clear_buffer ( &token_buff, NIL ( FILE ) ) ;
|
|
|
890 |
bfprintf ( bf, "%lu", loc.line ) ;
|
|
|
891 |
bfputc ( bf, 0 ) ;
|
|
|
892 |
this_tok = new_pptok () ;
|
|
|
893 |
this_tok->tok = lex_integer_Hlit ;
|
|
|
894 |
this_tok->next = NULL ;
|
|
|
895 |
this_tok->pp_opts = NULL ;
|
|
|
896 |
this_tok->pp_space = 0 ;
|
|
|
897 |
token_parts ( lex_integer_Hlit, this_tok ) ;
|
|
|
898 |
return ( this_tok ) ;
|
|
|
899 |
}
|
|
|
900 |
|
|
|
901 |
if ( t == lex_builtin_Hfile ) {
|
|
|
902 |
/* Construct a string literal for __FILE__ */
|
|
|
903 |
character c ;
|
|
|
904 |
string fn = DEREF_string ( posn_file ( crt_loc.posn ) ) ;
|
|
|
905 |
BUFFER *bf = clear_buffer ( &token_buff, NIL ( FILE ) ) ;
|
|
|
906 |
while ( c = *( fn++ ), c != 0 ) {
|
|
|
907 |
if ( c == char_quote || c == char_backslash ) {
|
|
|
908 |
/* Escape quotes and backslashes */
|
|
|
909 |
bfputc ( bf, char_backslash ) ;
|
|
|
910 |
}
|
|
|
911 |
bfputc ( bf, ( int ) c ) ;
|
|
|
912 |
}
|
|
|
913 |
this_tok = new_pptok () ;
|
|
|
914 |
this_tok->tok = lex_string_Hlit ;
|
|
|
915 |
this_tok->next = NULL ;
|
|
|
916 |
this_tok->pp_opts = NULL ;
|
|
|
917 |
this_tok->pp_space = 0 ;
|
|
|
918 |
token_parts ( lex_string_Hlit, this_tok ) ;
|
|
|
919 |
return ( this_tok ) ;
|
|
|
920 |
}
|
|
|
921 |
}
|
|
|
922 |
|
|
|
923 |
} else {
|
|
|
924 |
/* Function-like macros */
|
|
|
925 |
int t ;
|
|
|
926 |
unsigned n ;
|
|
|
927 |
TOKEN_LOC *lc ;
|
|
|
928 |
int brackets = 0 ;
|
|
|
929 |
unsigned no_args = 0 ;
|
|
|
930 |
PPTOKEN *ptr_tok = NULL ;
|
|
|
931 |
TOKEN_LOC *ptr_loc = locs ;
|
|
|
932 |
|
|
|
933 |
/* Check for following open bracket */
|
|
|
934 |
for ( ; ; ) {
|
|
|
935 |
if ( ptr_loc == file_loc ) {
|
|
|
936 |
/* Read token from input location */
|
|
|
937 |
int legal = 1 ;
|
|
|
938 |
sp = skip_white ( 1 ) ;
|
|
|
939 |
if ( peek_char ( char_open_round, &legal ) ) {
|
|
|
940 |
/* Next token in file is '(' */
|
|
|
941 |
update_column () ;
|
|
|
942 |
t = lex_open_Hround ;
|
|
|
943 |
} else {
|
|
|
944 |
/* Other cases */
|
|
|
945 |
t = lex_unknown ;
|
|
|
946 |
if ( sp ) patch_white ( sp ) ;
|
|
|
947 |
}
|
|
|
948 |
break ;
|
|
|
949 |
} else if ( ptr_loc == NULL ) {
|
|
|
950 |
/* No more locations */
|
|
|
951 |
t = lex_eof ;
|
|
|
952 |
break ;
|
|
|
953 |
} else {
|
|
|
954 |
/* Read token from current location */
|
|
|
955 |
ptr_tok = ( *( ptr_loc->toks ) )->next ;
|
|
|
956 |
while ( ptr_tok && ptr_tok->tok == lex_ignore_token ) {
|
|
|
957 |
/* Step over any ignored tokens */
|
|
|
958 |
ptr_tok = ptr_tok->next ;
|
|
|
959 |
}
|
|
|
960 |
if ( ptr_tok != NULL ) {
|
|
|
961 |
/* Return the next token */
|
|
|
962 |
t = ptr_tok->tok ;
|
|
|
963 |
ptr_tok = ptr_tok->next ;
|
|
|
964 |
break ;
|
|
|
965 |
}
|
|
|
966 |
/* Move on to next location */
|
|
|
967 |
ptr_loc = ptr_loc->next ;
|
|
|
968 |
}
|
|
|
969 |
}
|
|
|
970 |
|
|
|
971 |
/* Next token is not an open bracket */
|
|
|
972 |
if ( t != lex_open_Hround ) {
|
|
|
973 |
if ( complete ) {
|
|
|
974 |
report ( loc, ERR_cpp_replace_arg_none ( macro ) ) ;
|
|
|
975 |
}
|
|
|
976 |
incomplete_macro : {
|
|
|
977 |
/* Return macro identifier */
|
|
|
978 |
this_tok = new_pptok () ;
|
|
|
979 |
this_tok->tok = lex_identifier ;
|
|
|
980 |
this_tok->next = NULL ;
|
|
|
981 |
this_tok->pp_space = 0 ;
|
|
|
982 |
this_tok->pp_data.id.hash = macro ;
|
|
|
983 |
this_tok->pp_data.id.use = id ;
|
|
|
984 |
return ( this_tok ) ;
|
|
|
985 |
}
|
|
|
986 |
}
|
|
|
987 |
|
|
|
988 |
/* Check argument array size */
|
|
|
989 |
no_pars = DEREF_unsigned ( id_func_macro_no_params ( id ) ) ;
|
|
|
990 |
if ( no_pars > MAX_MACRO_PARAMS ) {
|
|
|
991 |
arg_array = xmalloc_nof ( PPTOKEN *, no_pars + 1 ) ;
|
|
|
992 |
}
|
|
|
993 |
|
|
|
994 |
/* Scan macro arguments */
|
|
|
995 |
for ( ; ; ) {
|
|
|
996 |
/* Get the next token */
|
|
|
997 |
int refill = 0 ;
|
|
|
998 |
for ( ; ; ) {
|
|
|
999 |
if ( ptr_loc == file_loc ) {
|
|
|
1000 |
/* Read token from file location */
|
|
|
1001 |
sp = skip_white ( 1 ) ;
|
|
|
1002 |
in_preproc_dir = 2 ;
|
|
|
1003 |
t = read_token () ;
|
|
|
1004 |
update_column () ;
|
|
|
1005 |
if ( t == lex_hash_H1 || t == lex_hash_H2 ) {
|
|
|
1006 |
if ( sp & WHITE_NEWLINE ) {
|
|
|
1007 |
/* Looks like preprocessing directive */
|
|
|
1008 |
ERROR err = ERR_cpp_replace_arg_ppdir ( macro ) ;
|
|
|
1009 |
report ( crt_loc, err ) ;
|
|
|
1010 |
}
|
|
|
1011 |
}
|
|
|
1012 |
break ;
|
|
|
1013 |
} else if ( ptr_loc == NULL ) {
|
|
|
1014 |
/* No more locations to read token from */
|
|
|
1015 |
t = lex_eof ;
|
|
|
1016 |
break ;
|
|
|
1017 |
} else {
|
|
|
1018 |
/* Read token from next location */
|
|
|
1019 |
if ( refill ) ptr_tok = ( *( ptr_loc->toks ) )->next ;
|
|
|
1020 |
if ( ptr_tok != NULL ) {
|
|
|
1021 |
t = ptr_tok->tok ;
|
|
|
1022 |
break ;
|
|
|
1023 |
}
|
|
|
1024 |
ptr_loc = ptr_loc->next ;
|
|
|
1025 |
refill = 1 ;
|
|
|
1026 |
}
|
|
|
1027 |
}
|
|
|
1028 |
|
|
|
1029 |
/* Examine this token */
|
|
|
1030 |
if ( t == lex_open_Hround ) {
|
|
|
1031 |
brackets++ ;
|
|
|
1032 |
} else if ( t == lex_close_Hround ) {
|
|
|
1033 |
/* Close brackets mark the end of the argument list */
|
|
|
1034 |
if ( brackets == 0 ) break ;
|
|
|
1035 |
brackets-- ;
|
|
|
1036 |
} else if ( t == lex_comma ) {
|
|
|
1037 |
/* Commas mark the end of an argument */
|
|
|
1038 |
if ( brackets == 0 ) {
|
|
|
1039 |
this_tok->next = NULL ;
|
|
|
1040 |
no_args++ ;
|
|
|
1041 |
if ( dummy_tok.next ) {
|
|
|
1042 |
dummy_tok.next->pp_space = 0 ;
|
|
|
1043 |
} else if ( complete ) {
|
|
|
1044 |
ERROR err ;
|
|
|
1045 |
err = ERR_cpp_replace_arg_empty ( no_args, macro ) ;
|
|
|
1046 |
report ( crt_loc, err ) ;
|
|
|
1047 |
}
|
|
|
1048 |
if ( no_args <= no_pars ) {
|
|
|
1049 |
arg_array [ no_args ] = dummy_tok.next ;
|
|
|
1050 |
} else {
|
|
|
1051 |
free_tok_list ( dummy_tok.next ) ;
|
|
|
1052 |
}
|
|
|
1053 |
if ( ptr_tok ) ptr_tok = ptr_tok->next ;
|
|
|
1054 |
this_tok = &dummy_tok ;
|
|
|
1055 |
continue ;
|
|
|
1056 |
}
|
|
|
1057 |
} else if ( t == lex_eof ) {
|
|
|
1058 |
break ;
|
|
|
1059 |
}
|
|
|
1060 |
|
|
|
1061 |
/* Build up current argument */
|
|
|
1062 |
this_tok->next = new_pptok () ;
|
|
|
1063 |
this_tok = this_tok->next ;
|
|
|
1064 |
if ( ptr_tok ) {
|
|
|
1065 |
copy_pptok ( this_tok, t, ptr_tok ) ;
|
|
|
1066 |
ptr_tok = ptr_tok->next ;
|
|
|
1067 |
} else {
|
|
|
1068 |
this_tok->tok = t ;
|
|
|
1069 |
if ( t <= LAST_COMPLEX_TOKEN ) token_parts ( t, this_tok ) ;
|
|
|
1070 |
this_tok->pp_space = ( sp & WHITE_MASK ) ;
|
|
|
1071 |
}
|
|
|
1072 |
}
|
|
|
1073 |
|
|
|
1074 |
/* Create last argument */
|
|
|
1075 |
in_preproc_dir = 0 ;
|
|
|
1076 |
this_tok->next = NULL ;
|
|
|
1077 |
if ( no_args || dummy_tok.next ) {
|
|
|
1078 |
no_args++ ;
|
|
|
1079 |
if ( dummy_tok.next ) {
|
|
|
1080 |
dummy_tok.next->pp_space = 0 ;
|
|
|
1081 |
} else if ( complete ) {
|
|
|
1082 |
ERROR err = ERR_cpp_replace_arg_empty ( no_args, macro ) ;
|
|
|
1083 |
report ( crt_loc, err ) ;
|
|
|
1084 |
}
|
|
|
1085 |
if ( no_args <= no_pars ) {
|
|
|
1086 |
arg_array [ no_args ] = dummy_tok.next ;
|
|
|
1087 |
} else {
|
|
|
1088 |
free_tok_list ( dummy_tok.next ) ;
|
|
|
1089 |
}
|
|
|
1090 |
}
|
|
|
1091 |
if ( sp ) patch_white ( sp ) ;
|
|
|
1092 |
this_tok = &dummy_tok ;
|
|
|
1093 |
|
|
|
1094 |
/* Check for incomplete argument lists */
|
|
|
1095 |
if ( t == lex_eof ) {
|
|
|
1096 |
if ( complete ) {
|
|
|
1097 |
/* Report error, but carry on */
|
|
|
1098 |
report ( loc, ERR_cpp_replace_arg_eof ( macro ) ) ;
|
|
|
1099 |
} else {
|
|
|
1100 |
/* Free those arguments actually read */
|
|
|
1101 |
for ( n = 1 ; n <= no_args && n <= no_pars ; n++ ) {
|
|
|
1102 |
free_tok_list ( arg_array [n] ) ;
|
|
|
1103 |
}
|
|
|
1104 |
if ( arg_array != arg_array_base ) xfree_nof ( arg_array ) ;
|
|
|
1105 |
goto incomplete_macro ;
|
|
|
1106 |
}
|
|
|
1107 |
}
|
|
|
1108 |
|
|
|
1109 |
/* Update location pointers */
|
|
|
1110 |
if ( ptr_loc ) *( ptr_loc )->toks = ptr_tok ;
|
|
|
1111 |
for ( lc = locs ; lc != ptr_loc ; lc = lc->next ) {
|
|
|
1112 |
*( lc )->toks = NULL ;
|
|
|
1113 |
}
|
|
|
1114 |
|
|
|
1115 |
/* Check that argument and parameter lists match */
|
|
|
1116 |
if ( no_pars != no_args ) {
|
|
|
1117 |
ERROR err ;
|
|
|
1118 |
n = no_args ;
|
|
|
1119 |
err = ERR_cpp_replace_arg_number ( macro, n, n, no_pars ) ;
|
|
|
1120 |
report ( crt_loc, err ) ;
|
|
|
1121 |
|
|
|
1122 |
/* Add extra arguments if there are not enough */
|
|
|
1123 |
for ( n = no_args + 1 ; n <= no_pars ; n++ ) {
|
|
|
1124 |
arg_array [n] = NULL ;
|
|
|
1125 |
}
|
|
|
1126 |
}
|
|
|
1127 |
IGNORE check_value ( OPT_VAL_macro_args, ( ulong ) no_args ) ;
|
|
|
1128 |
|
|
|
1129 |
/* Get the macro definition */
|
|
|
1130 |
defn = DEREF_pptok ( id_func_macro_defn ( id ) ) ;
|
|
|
1131 |
}
|
|
|
1132 |
crt_spaces = ws ;
|
|
|
1133 |
|
|
|
1134 |
/* Copy the definition, expanding macro arguments */
|
|
|
1135 |
while ( defn != NULL ) {
|
|
|
1136 |
int t = defn->tok ;
|
|
|
1137 |
|
|
|
1138 |
if ( t == lex_macro_Harg ) {
|
|
|
1139 |
/* Macro argument - identified by argument number */
|
|
|
1140 |
unsigned long n = defn->pp_data.par.no ;
|
|
|
1141 |
PPTOKEN *arg = arg_array [n] ;
|
|
|
1142 |
|
|
|
1143 |
if ( state == 0 ) {
|
|
|
1144 |
if ( defn->next && defn->next->tok == lex_hash_Hhash_Hop ) {
|
|
|
1145 |
/* Preceding ##, just copy argument */
|
|
|
1146 |
this_tok->next = copy_tok_list ( arg ) ;
|
|
|
1147 |
} else {
|
|
|
1148 |
/* Normal argument expansion */
|
|
|
1149 |
TOKEN_LOC *arg_locs = NULL ;
|
|
|
1150 |
this_tok->next = expand_toks ( arg, arg_locs, 0 ) ;
|
|
|
1151 |
}
|
|
|
1152 |
|
|
|
1153 |
} else if ( state == 1 ) {
|
|
|
1154 |
/* Following #, fake reading a string literal */
|
|
|
1155 |
this_tok->next = new_pptok () ;
|
|
|
1156 |
if ( !quote_tok_list ( arg, 1, char_quote ) ) {
|
|
|
1157 |
report ( crt_loc, ERR_cpp_stringize_bad ( macro ) ) ;
|
|
|
1158 |
}
|
|
|
1159 |
this_tok->next->tok = lex_string_Hlit ;
|
|
|
1160 |
token_parts ( lex_string_Hlit, this_tok->next ) ;
|
|
|
1161 |
this_tok->next->next = NULL ;
|
|
|
1162 |
this_tok->next->pp_space = 0 ;
|
|
|
1163 |
|
|
|
1164 |
} else {
|
|
|
1165 |
/* Following ##, just copy argument */
|
|
|
1166 |
this_tok->next = copy_tok_list ( arg ) ;
|
|
|
1167 |
}
|
|
|
1168 |
|
|
|
1169 |
sp = defn->pp_space ;
|
|
|
1170 |
if ( sp && this_tok->next ) {
|
|
|
1171 |
this_tok->next->pp_space = sp ;
|
|
|
1172 |
sp = 0 ;
|
|
|
1173 |
}
|
|
|
1174 |
while ( this_tok->next ) this_tok = this_tok->next ;
|
|
|
1175 |
state = 0 ;
|
|
|
1176 |
|
|
|
1177 |
} else if ( t == lex_hash_Hop ) {
|
|
|
1178 |
/* Check for # operator */
|
|
|
1179 |
state = 1 ;
|
|
|
1180 |
|
|
|
1181 |
} else if ( t != lex_ignore_token ) {
|
|
|
1182 |
/* Copy other tokens */
|
|
|
1183 |
this_tok->next = new_pptok () ;
|
|
|
1184 |
this_tok = this_tok->next ;
|
|
|
1185 |
copy_pptok ( this_tok, t, defn ) ;
|
|
|
1186 |
if ( sp ) {
|
|
|
1187 |
this_tok->pp_space = sp ;
|
|
|
1188 |
sp = 0 ;
|
|
|
1189 |
}
|
|
|
1190 |
if ( t == lex_hash_Hhash_Hop ) {
|
|
|
1191 |
/* Check for ## operator */
|
|
|
1192 |
have_hash_hash = 1 ;
|
|
|
1193 |
state = 2 ;
|
|
|
1194 |
} else {
|
|
|
1195 |
if ( t == lex_unknown ) have_unknown = 1 ;
|
|
|
1196 |
state = 0 ;
|
|
|
1197 |
}
|
|
|
1198 |
}
|
|
|
1199 |
defn = defn->next ;
|
|
|
1200 |
}
|
|
|
1201 |
this_tok->next = NULL ;
|
|
|
1202 |
defn = dummy_tok.next ;
|
|
|
1203 |
|
|
|
1204 |
/* Allow for argument expansion in strings */
|
|
|
1205 |
if ( have_unknown ) defn = recognise_strings ( defn, macro, 1 ) ;
|
|
|
1206 |
|
|
|
1207 |
/* Rescan for ## directives */
|
|
|
1208 |
if ( have_hash_hash ) defn = process_concat ( defn, macro ) ;
|
|
|
1209 |
|
|
|
1210 |
/* Rescan for further expansion (but not expanding macro) */
|
|
|
1211 |
COPY_dspec ( id_storage ( id ), ( ds | dspec_temp ) ) ;
|
|
|
1212 |
this_tok = expand_toks ( defn, locs, complete ) ;
|
|
|
1213 |
free_tok_list ( defn ) ;
|
|
|
1214 |
defn = this_tok ;
|
|
|
1215 |
COPY_dspec ( id_storage ( id ), ds ) ;
|
|
|
1216 |
|
|
|
1217 |
/* Clean up after macro expansion */
|
|
|
1218 |
if ( tag == id_func_macro_tag ) {
|
|
|
1219 |
/* Free the macro arguments */
|
|
|
1220 |
unsigned n ;
|
|
|
1221 |
for ( n = 1 ; n <= no_pars ; n++ ) free_tok_list ( arg_array [n] ) ;
|
|
|
1222 |
if ( arg_array != arg_array_base ) xfree_nof ( arg_array ) ;
|
|
|
1223 |
}
|
|
|
1224 |
|
|
|
1225 |
/* Return the result */
|
|
|
1226 |
return ( defn ) ;
|
|
|
1227 |
}
|
|
|
1228 |
|
|
|
1229 |
|
|
|
1230 |
/*
|
|
|
1231 |
EXPAND A LIST OF TOKENS
|
|
|
1232 |
|
|
|
1233 |
This is the main macro expansion routine. It expands the list of macros
|
|
|
1234 |
tok, returning the result. If toks ends in an unterminated function-like
|
|
|
1235 |
macro then further tokens may be read from the locations given in locs.
|
|
|
1236 |
The complete argument is as in expand_macro.
|
|
|
1237 |
*/
|
|
|
1238 |
|
|
|
1239 |
static PPTOKEN *expand_toks
|
|
|
1240 |
PROTO_N ( ( toks, locs, complete ) )
|
|
|
1241 |
PROTO_T ( PPTOKEN *toks X TOKEN_LOC *locs X int complete )
|
|
|
1242 |
{
|
|
|
1243 |
PPTOKEN *ptr_tok ;
|
|
|
1244 |
unsigned long sp = 0 ;
|
|
|
1245 |
PPTOKEN dummy_tok, *this_tok = &dummy_tok ;
|
|
|
1246 |
|
|
|
1247 |
/* Copy list of tokens */
|
|
|
1248 |
for ( ptr_tok = toks ; ptr_tok != NULL ; ptr_tok = ptr_tok->next ) {
|
|
|
1249 |
int t = ptr_tok->tok ;
|
|
|
1250 |
if ( t == lex_ignore_token ) {
|
|
|
1251 |
sp |= ptr_tok->pp_space ;
|
|
|
1252 |
continue ;
|
|
|
1253 |
}
|
|
|
1254 |
this_tok->next = new_pptok () ;
|
|
|
1255 |
this_tok = this_tok->next ;
|
|
|
1256 |
copy_pptok ( this_tok, t, ptr_tok ) ;
|
|
|
1257 |
if ( sp ) {
|
|
|
1258 |
this_tok->pp_space |= sp ;
|
|
|
1259 |
sp = 0 ;
|
|
|
1260 |
}
|
|
|
1261 |
|
|
|
1262 |
/* Check for macros */
|
|
|
1263 |
if ( t == lex_identifier ) {
|
|
|
1264 |
HASHID m = ptr_tok->pp_data.id.hash ;
|
|
|
1265 |
IDENTIFIER id = DEREF_id ( hashid_id ( m ) ) ;
|
|
|
1266 |
unsigned tag = TAG_id ( id ) ;
|
|
|
1267 |
switch ( tag ) {
|
|
|
1268 |
case id_obj_macro_tag :
|
|
|
1269 |
case id_func_macro_tag : {
|
|
|
1270 |
DECL_SPEC ds ;
|
|
|
1271 |
TOKEN_LOC tloc ;
|
|
|
1272 |
|
|
|
1273 |
/* Check for non-expanding tokens */
|
|
|
1274 |
if ( IS_NULL_id ( this_tok->pp_data.id.use ) ) {
|
|
|
1275 |
break ;
|
|
|
1276 |
}
|
|
|
1277 |
|
|
|
1278 |
/* Check for recursive macro definitions */
|
|
|
1279 |
ds = DEREF_dspec ( id_storage ( id ) ) ;
|
|
|
1280 |
if ( ds & dspec_temp ) {
|
|
|
1281 |
/* Mark this token as non-expanding */
|
|
|
1282 |
ERROR err = ERR_cpp_rescan_recursive ( m ) ;
|
|
|
1283 |
report ( crt_loc, err ) ;
|
|
|
1284 |
this_tok->pp_data.id.use = NULL_id ;
|
|
|
1285 |
break ;
|
|
|
1286 |
}
|
|
|
1287 |
|
|
|
1288 |
/* Expand the macro using an extra location */
|
|
|
1289 |
tloc.toks = &ptr_tok ;
|
|
|
1290 |
tloc.next = locs ;
|
|
|
1291 |
this_tok->tok = lex_ignore_token ;
|
|
|
1292 |
this_tok->next = expand_macro ( m, &tloc, complete ) ;
|
|
|
1293 |
while ( this_tok->next ) this_tok = this_tok->next ;
|
|
|
1294 |
break ;
|
|
|
1295 |
}
|
|
|
1296 |
}
|
|
|
1297 |
if ( ptr_tok == NULL ) break ;
|
|
|
1298 |
}
|
|
|
1299 |
}
|
|
|
1300 |
this_tok->next = NULL ;
|
|
|
1301 |
return ( dummy_tok.next ) ;
|
|
|
1302 |
}
|
|
|
1303 |
|
|
|
1304 |
|
|
|
1305 |
/*
|
|
|
1306 |
EXPAND A SIMPLE LIST OF TOKENS
|
|
|
1307 |
|
|
|
1308 |
This routine is the simplest form of expand_toks, where toks is a
|
|
|
1309 |
complete list, with no locations for reading further tokens.
|
|
|
1310 |
*/
|
|
|
1311 |
|
|
|
1312 |
PPTOKEN *expand_tok_list
|
|
|
1313 |
PROTO_N ( ( toks ) )
|
|
|
1314 |
PROTO_T ( PPTOKEN *toks )
|
|
|
1315 |
{
|
|
|
1316 |
return ( expand_toks ( toks, NIL ( TOKEN_LOC ), 1 ) ) ;
|
|
|
1317 |
}
|
|
|
1318 |
|
|
|
1319 |
|
|
|
1320 |
/*
|
|
|
1321 |
ASSERTION NAMESPACE
|
|
|
1322 |
|
|
|
1323 |
The assertions occupy a namespace distinct from all other namespaces,
|
|
|
1324 |
including the macro namespace.
|
|
|
1325 |
*/
|
|
|
1326 |
|
|
|
1327 |
NAMESPACE assert_namespace ;
|
|
|
1328 |
|
|
|
1329 |
|
|
|
1330 |
/*
|
|
|
1331 |
CREATE A BUILT-IN MACRO
|
|
|
1332 |
|
|
|
1333 |
This routine creates a built-in macro named nm defined by a single
|
|
|
1334 |
preprocessing token with token type t and associated data d.
|
|
|
1335 |
*/
|
|
|
1336 |
|
|
|
1337 |
static void builtin_macro
|
|
|
1338 |
PROTO_N ( ( nm, t, d ) )
|
|
|
1339 |
PROTO_T ( CONST char *nm X int t X CONST char *d )
|
|
|
1340 |
{
|
|
|
1341 |
if ( d ) {
|
|
|
1342 |
IDENTIFIER id ;
|
|
|
1343 |
string s = ustrlit ( nm ) ;
|
|
|
1344 |
unsigned long h = hash ( s ) ;
|
|
|
1345 |
HASHID macro = lookup_name ( s, h, 0, lex_identifier ) ;
|
|
|
1346 |
IDENTIFIER pid = DEREF_id ( hashid_id ( macro ) ) ;
|
|
|
1347 |
DECL_SPEC ds = ( dspec_defn | dspec_builtin ) ;
|
|
|
1348 |
|
|
|
1349 |
/* Set up the token definition */
|
|
|
1350 |
PPTOKEN *p = new_pptok () ;
|
|
|
1351 |
p->tok = t ;
|
|
|
1352 |
p->pp_space = 0 ;
|
|
|
1353 |
p->pp_opts = NULL ;
|
|
|
1354 |
p->next = NULL ;
|
|
|
1355 |
if ( t == lex_integer_Hlit ) {
|
|
|
1356 |
/* Set up associated integer data */
|
|
|
1357 |
string c = xustrcpy ( ustrlit ( d ) ) ;
|
|
|
1358 |
p->pp_data.text = c ;
|
|
|
1359 |
} else if ( t == lex_string_Hlit ) {
|
|
|
1360 |
/* Set up associated string data */
|
|
|
1361 |
string c = xustrcpy ( ustrlit ( d ) ) ;
|
|
|
1362 |
p->pp_data.str.start = c ;
|
|
|
1363 |
p->pp_data.str.end = c + ustrlen ( c ) ;
|
|
|
1364 |
} else if ( t == lex_builtin_Hline || t == lex_builtin_Hfile ) {
|
|
|
1365 |
/* Set up associated location data */
|
|
|
1366 |
p->pp_space = crt_loc.column ;
|
|
|
1367 |
p->pp_data.loc.line = crt_loc.line ;
|
|
|
1368 |
p->pp_data.loc.posn = crt_loc.posn ;
|
|
|
1369 |
}
|
|
|
1370 |
|
|
|
1371 |
/* Define the macro */
|
|
|
1372 |
MAKE_id_obj_macro ( macro, ds, NULL_nspace, crt_loc, p, id ) ;
|
|
|
1373 |
COPY_id ( id_alias ( id ), pid ) ;
|
|
|
1374 |
COPY_id ( hashid_id ( macro ), id ) ;
|
|
|
1375 |
if ( do_macro ) dump_declare ( id, &crt_loc, 1 ) ;
|
|
|
1376 |
}
|
|
|
1377 |
return ;
|
|
|
1378 |
}
|
|
|
1379 |
|
|
|
1380 |
|
|
|
1381 |
/*
|
|
|
1382 |
INITIALISE BUILT-IN MACROS
|
|
|
1383 |
|
|
|
1384 |
This routine initialises the built-in macros, and sets up the assertion
|
|
|
1385 |
namespace.
|
|
|
1386 |
*/
|
|
|
1387 |
|
|
|
1388 |
void init_macros
|
|
|
1389 |
PROTO_N ( ( m, a ) )
|
|
|
1390 |
PROTO_T ( int m X int a )
|
|
|
1391 |
{
|
|
|
1392 |
CONST char *d = find_date ( "%s %2d %d" ) ;
|
|
|
1393 |
CONST char *t = find_time ( "%.2d:%.2d:%.2d" ) ;
|
|
|
1394 |
if ( m ) {
|
|
|
1395 |
/* Define built-in macros */
|
|
|
1396 |
builtin_macro ( "__LINE__", lex_builtin_Hline, "1" ) ;
|
|
|
1397 |
builtin_macro ( "__FILE__", lex_builtin_Hfile, "<unknown>" ) ;
|
|
|
1398 |
builtin_macro ( "__DATE__", lex_string_Hlit, d ) ;
|
|
|
1399 |
builtin_macro ( "__TIME__", lex_string_Hlit, t ) ;
|
|
|
1400 |
builtin_macro ( "__STDC__", lex_integer_Hlit, C_VERSION ) ;
|
|
|
1401 |
builtin_macro ( "__STDC_VERSION__", lex_integer_Hlit, ISOC_VERSION ) ;
|
|
|
1402 |
#if LANGUAGE_CPP
|
|
|
1403 |
builtin_macro ( "__cplusplus", lex_integer_Hlit, CPP_VERSION ) ;
|
|
|
1404 |
builtin_macro ( "__tcpplus", lex_integer_Hlit, "1" ) ;
|
|
|
1405 |
#else
|
|
|
1406 |
builtin_macro ( "__tcpplus", lex_integer_Hlit, "0" ) ;
|
|
|
1407 |
#endif
|
|
|
1408 |
}
|
|
|
1409 |
assert_namespace = make_global_nspace ( "<assert>", 20 ) ;
|
|
|
1410 |
if ( a ) {
|
|
|
1411 |
/* Define built-in assertions */
|
|
|
1412 |
IGNORE make_assert ( KEYWORD ( lex_include ), lex_include ) ;
|
|
|
1413 |
IGNORE make_assert ( KEYWORD ( lex_keyword ), lex_keyword ) ;
|
|
|
1414 |
IGNORE make_assert ( KEYWORD ( lex_option ), lex_option ) ;
|
|
|
1415 |
}
|
|
|
1416 |
return ;
|
|
|
1417 |
}
|