Mercurial > hg > index.cgi
annotate lwcc/preproc.c @ 305:54f213c8fb81 ccdev
Various bugfixes and output tuning
Tuned output of preprocessor to include line markers similar to the ones
added by the gcc preprocessor.
Also, many fixes for various bits of dumbosity leading to misbehaviour and
crashing.
author | William Astle <lost@l-w.ca> |
---|---|
date | Wed, 18 Sep 2013 19:17:52 -0600 |
parents | d85d173ba120 |
children | b08787e5b9f3 |
rev | line source |
---|---|
296 | 1 /* |
2 lwcc/preproc.c | |
3 | |
4 Copyright © 2013 William Astle | |
5 | |
6 This file is part of LWTOOLS. | |
7 | |
8 LWTOOLS is free software: you can redistribute it and/or modify it under the | |
9 terms of the GNU General Public License as published by the Free Software | |
10 Foundation, either version 3 of the License, or (at your option) any later | |
11 version. | |
12 | |
13 This program is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
16 more details. | |
17 | |
18 You should have received a copy of the GNU General Public License along with | |
19 this program. If not, see <http://www.gnu.org/licenses/>. | |
20 */ | |
21 | |
300 | 22 #include <stdio.h> |
23 #include <stdlib.h> | |
296 | 24 #include <string.h> |
25 | |
26 #include <lw_alloc.h> | |
27 #include <lw_string.h> | |
28 | |
29 #include "cpp.h" | |
30 #include "strbuf.h" | |
31 #include "symbol.h" | |
32 #include "token.h" | |
33 | |
34 static int expand_macro(struct preproc_info *, char *); | |
35 static void process_directive(struct preproc_info *); | |
36 static long eval_expr(struct preproc_info *); | |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
37 extern struct token *preproc_lex_next_token(struct preproc_info *); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
38 |
296 | 39 |
40 struct token *preproc_next_processed_token(struct preproc_info *pp) | |
41 { | |
42 struct token *ct; | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
43 |
296 | 44 again: |
45 ct = preproc_next_token(pp); | |
46 if (ct -> ttype == TOK_EOF) | |
47 return ct; | |
48 if (ct -> ttype == TOK_EOL) | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
49 { |
296 | 50 pp -> ppeolseen = 1; |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
51 return ct; |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
52 } |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
53 |
304
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
301
diff
changeset
|
54 if (ct -> ttype == TOK_HASH && pp -> ppeolseen == 1) |
296 | 55 { |
56 // preprocessor directive | |
57 process_directive(pp); | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
58 goto again; |
296 | 59 } |
60 // if we're in a false section, don't return the token; keep scanning | |
61 if (pp -> skip_level) | |
62 goto again; | |
63 | |
64 if (ct -> ttype != TOK_WSPACE) | |
65 pp -> ppeolseen = 0; | |
66 | |
67 if (ct -> ttype == TOK_IDENT) | |
68 { | |
69 // possible macro expansion | |
70 if (expand_macro(pp, ct -> strval)) | |
71 goto again; | |
72 } | |
73 | |
74 return ct; | |
75 } | |
76 | |
77 static struct token *preproc_next_processed_token_nws(struct preproc_info *pp) | |
78 { | |
79 struct token *t; | |
80 | |
81 do | |
82 { | |
83 t = preproc_next_processed_token(pp); | |
84 } while (t -> ttype == TOK_WSPACE); | |
85 return t; | |
86 } | |
87 | |
88 static struct token *preproc_next_token_nws(struct preproc_info *pp) | |
89 { | |
90 struct token *t; | |
91 | |
92 do | |
93 { | |
94 t = preproc_next_token(pp); | |
95 } while (t -> ttype == TOK_WSPACE); | |
96 return t; | |
97 } | |
98 | |
99 static void skip_eol(struct preproc_info *pp) | |
100 { | |
101 struct token *t; | |
102 | |
103 if (pp -> curtok && pp -> curtok -> ttype == TOK_EOL) | |
104 return; | |
105 do | |
106 { | |
107 t = preproc_next_token(pp); | |
108 } while (t -> ttype != TOK_EOL); | |
109 } | |
110 | |
111 static void check_eol(struct preproc_info *pp) | |
112 { | |
113 struct token *t; | |
114 | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
115 t = preproc_next_token_nws(pp); |
296 | 116 if (t -> ttype != TOK_EOL) |
117 preproc_throw_warning(pp, "Extra text after preprocessor directive"); | |
118 skip_eol(pp); | |
119 } | |
120 | |
121 static void dir_ifdef(struct preproc_info *pp) | |
122 { | |
123 struct token *ct; | |
124 | |
125 if (pp -> skip_level) | |
126 { | |
127 pp -> skip_level++; | |
128 skip_eol(pp); | |
129 return; | |
130 } | |
131 | |
132 do | |
133 { | |
134 ct = preproc_next_token(pp); | |
135 } while (ct -> ttype == TOK_WSPACE); | |
136 | |
137 if (ct -> ttype != TOK_IDENT) | |
138 { | |
139 preproc_throw_error(pp, "Bad #ifdef"); | |
140 skip_eol(pp); | |
141 } | |
142 | |
143 if (symtab_find(pp, ct -> strval) == NULL) | |
144 { | |
145 pp -> skip_level++; | |
146 } | |
147 else | |
148 { | |
149 pp -> found_level++; | |
150 } | |
151 check_eol(pp); | |
152 } | |
153 | |
154 static void dir_ifndef(struct preproc_info *pp) | |
155 { | |
156 struct token *ct; | |
157 | |
158 if (pp -> skip_level) | |
159 { | |
160 pp -> skip_level++; | |
161 skip_eol(pp); | |
162 return; | |
163 } | |
164 | |
165 do | |
166 { | |
167 ct = preproc_next_token(pp); | |
168 } while (ct -> ttype == TOK_WSPACE); | |
169 | |
170 if (ct -> ttype != TOK_IDENT) | |
171 { | |
172 preproc_throw_error(pp, "Bad #ifdef"); | |
173 skip_eol(pp); | |
174 } | |
175 | |
176 if (symtab_find(pp, ct -> strval) != NULL) | |
177 { | |
178 pp -> skip_level++; | |
179 } | |
180 else | |
181 { | |
182 pp -> found_level++; | |
183 } | |
184 check_eol(pp); | |
185 } | |
186 | |
187 static void dir_if(struct preproc_info *pp) | |
188 { | |
189 if (pp -> skip_level || !eval_expr(pp)) | |
190 pp -> skip_level++; | |
191 else | |
192 pp -> found_level++; | |
193 } | |
194 | |
195 static void dir_elif(struct preproc_info *pp) | |
196 { | |
197 if (pp -> skip_level == 0) | |
198 pp -> else_skip_level = pp -> found_level; | |
199 if (pp -> skip_level) | |
200 { | |
201 if (pp -> else_skip_level > pp -> found_level) | |
202 ; | |
203 else if (--(pp -> skip_level) != 0) | |
204 pp -> skip_level++; | |
205 else if (eval_expr(pp)) | |
206 pp -> found_level++; | |
207 else | |
208 pp -> skip_level++; | |
209 } | |
210 else if (pp -> found_level) | |
211 { | |
212 pp -> skip_level++; | |
213 pp -> found_level--; | |
214 } | |
215 else | |
216 preproc_throw_error(pp, "#elif in non-conditional section"); | |
217 } | |
218 | |
219 static void dir_else(struct preproc_info *pp) | |
220 { | |
221 if (pp -> skip_level) | |
222 { | |
223 if (pp -> else_skip_level > pp -> found_level) | |
224 ; | |
225 else if (--(pp -> skip_level) != 0) | |
226 pp -> skip_level++; | |
227 else | |
228 pp -> found_level++; | |
229 } | |
230 else if (pp -> found_level) | |
231 { | |
232 pp -> skip_level++; | |
233 pp -> found_level--; | |
234 } | |
235 else | |
236 { | |
237 preproc_throw_error(pp, "#else in non-conditional section"); | |
238 } | |
239 if (pp -> else_level == pp -> found_level + pp -> skip_level) | |
240 { | |
241 preproc_throw_error(pp, "Too many #else"); | |
242 } | |
243 pp -> else_level = pp -> found_level + pp -> skip_level; | |
244 check_eol(pp); | |
245 } | |
246 | |
247 static void dir_endif(struct preproc_info *pp) | |
248 { | |
249 if (pp -> skip_level) | |
250 pp -> skip_level--; | |
251 else if (pp -> found_level) | |
252 pp -> found_level--; | |
253 else | |
254 preproc_throw_error(pp, "#endif in non-conditional section"); | |
255 if (pp -> skip_level == 0) | |
256 pp -> else_skip_level = 0; | |
257 pp -> else_level = 0; | |
258 check_eol(pp); | |
259 } | |
260 | |
261 static void dir_define(struct preproc_info *pp) | |
262 { | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
263 struct token_list *tl = NULL; |
296 | 264 struct token *ct; |
265 int nargs = -1; | |
266 int vargs = 0; | |
267 char *mname = NULL; | |
268 | |
269 char **arglist = NULL; | |
270 | |
271 if (pp -> skip_level) | |
272 { | |
273 skip_eol(pp); | |
274 return; | |
275 } | |
276 | |
277 ct = preproc_next_token_nws(pp); | |
278 if (ct -> ttype != TOK_IDENT) | |
279 goto baddefine; | |
280 | |
281 mname = lw_strdup(ct -> strval); | |
282 ct = preproc_next_token(pp); | |
283 | |
284 if (ct -> ttype == TOK_WSPACE) | |
285 { | |
286 /* object like macro */ | |
287 } | |
288 else if (ct -> ttype == TOK_EOL) | |
289 { | |
290 /* object like macro - empty value */ | |
291 goto out; | |
292 } | |
293 else if (ct -> ttype == TOK_OPAREN) | |
294 { | |
295 /* function like macro - parse args */ | |
296 nargs = 0; | |
297 vargs = 0; | |
298 for (;;) | |
299 { | |
300 ct = preproc_next_token_nws(pp); | |
301 if (ct -> ttype == TOK_EOL) | |
302 { | |
303 goto baddefine; | |
304 } | |
305 if (ct -> ttype == TOK_CPAREN) | |
306 break; | |
307 | |
308 if (ct -> ttype == TOK_IDENT) | |
309 { | |
310 /* parameter name */ | |
311 nargs++; | |
312 /* record argument name */ | |
313 arglist = lw_realloc(arglist, sizeof(char *) * nargs); | |
314 arglist[nargs - 1] = lw_strdup(ct -> strval); | |
315 | |
316 /* check for end of args or comma */ | |
317 ct = preproc_next_token_nws(pp); | |
318 if (ct -> ttype == TOK_CPAREN) | |
319 break; | |
320 else if (ct -> ttype == TOK_COMMA) | |
321 continue; | |
322 else | |
323 goto baddefine; | |
324 } | |
325 else if (ct -> ttype == TOK_ELLIPSIS) | |
326 { | |
327 /* variadic macro */ | |
328 vargs = 1; | |
329 ct = preproc_next_token_nws(pp); | |
330 if (ct -> ttype != TOK_CPAREN) | |
331 goto baddefine; | |
332 break; | |
333 } | |
334 else | |
335 goto baddefine; | |
336 } | |
337 } | |
338 else | |
339 { | |
340 baddefine: | |
341 preproc_throw_error(pp, "bad #define"); | |
342 baddefine2: | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
343 token_list_destroy(tl); |
296 | 344 skip_eol(pp); |
345 lw_free(mname); | |
346 while (nargs > 0) | |
347 lw_free(arglist[--nargs]); | |
348 lw_free(arglist); | |
349 return; | |
350 } | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
351 |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
352 tl = token_list_create(); |
296 | 353 for (;;) |
354 { | |
355 ct = preproc_next_token(pp); | |
356 if (ct -> ttype == TOK_EOL) | |
357 break; | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
358 token_list_append(tl, token_dup(ct)); |
296 | 359 } |
360 out: | |
361 if (strcmp(mname, "defined") == 0) | |
362 { | |
363 preproc_throw_warning(pp, "attempt to define 'defined' as a macro not allowed"); | |
364 goto baddefine2; | |
365 } | |
366 else if (symtab_find(pp, mname) != NULL) | |
367 { | |
368 /* need to do a token compare between the old value and the new value | |
369 to decide whether to complain */ | |
370 preproc_throw_warning(pp, "%s previous defined", mname); | |
371 symtab_undef(pp, mname); | |
372 } | |
373 symtab_define(pp, mname, tl, nargs, arglist, vargs); | |
374 lw_free(mname); | |
375 while (nargs > 0) | |
376 lw_free(arglist[--nargs]); | |
377 lw_free(arglist); | |
378 /* no need to check for EOL here */ | |
379 } | |
380 | |
381 static void dir_undef(struct preproc_info *pp) | |
382 { | |
383 struct token *ct; | |
384 if (pp -> skip_level) | |
385 { | |
386 skip_eol(pp); | |
387 return; | |
388 } | |
389 | |
390 do | |
391 { | |
392 ct = preproc_next_token(pp); | |
393 } while (ct -> ttype == TOK_WSPACE); | |
394 | |
395 if (ct -> ttype != TOK_IDENT) | |
396 { | |
397 preproc_throw_error(pp, "Bad #undef"); | |
398 skip_eol(pp); | |
399 } | |
400 | |
401 symtab_undef(pp, ct -> strval); | |
402 check_eol(pp); | |
403 } | |
404 | |
405 char *streol(struct preproc_info *pp) | |
406 { | |
407 struct strbuf *s; | |
408 struct token *ct; | |
409 int i; | |
410 | |
411 s = strbuf_new(); | |
412 do | |
413 { | |
414 ct = preproc_next_token(pp); | |
415 } while (ct -> ttype == TOK_WSPACE); | |
416 | |
417 while (ct -> ttype != TOK_EOL) | |
418 { | |
419 for (i = 0; ct -> strval[i]; i++) | |
420 strbuf_add(s, ct -> strval[i]); | |
421 ct = preproc_next_token(pp); | |
422 } | |
423 return strbuf_end(s); | |
424 } | |
425 | |
426 static void dir_error(struct preproc_info *pp) | |
427 { | |
428 char *s; | |
429 | |
430 if (pp -> skip_level) | |
431 { | |
432 skip_eol(pp); | |
433 return; | |
434 } | |
435 | |
436 s = streol(pp); | |
437 preproc_throw_error(pp, "%s", s); | |
438 lw_free(s); | |
439 } | |
440 | |
441 static void dir_warning(struct preproc_info *pp) | |
442 { | |
443 char *s; | |
444 | |
445 if (pp -> skip_level) | |
446 { | |
447 skip_eol(pp); | |
448 return; | |
449 } | |
450 | |
451 s = streol(pp); | |
452 preproc_throw_warning(pp, "%s", s); | |
453 lw_free(s); | |
454 } | |
455 | |
456 static void dir_include(struct preproc_info *pp) | |
457 { | |
300 | 458 FILE *fp; |
459 struct token *ct; | |
460 int sys = 0; | |
461 char *fn; | |
462 struct strbuf *strbuf; | |
463 int i; | |
464 struct preproc_info *fs; | |
465 | |
466 ct = preproc_next_token_nws(pp); | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
467 if (ct -> ttype == TOK_STR_LIT) |
300 | 468 { |
469 usrinc: | |
470 sys = strlen(ct -> strval); | |
471 fn = lw_alloc(sys - 1); | |
472 memcpy(fn, ct -> strval + 1, sys - 2); | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
473 fn[sys - 2] = 0; |
300 | 474 sys = 0; |
475 goto doinc; | |
476 } | |
477 else if (ct -> ttype == TOK_LT) | |
478 { | |
479 strbuf = strbuf_new(); | |
480 for (;;) | |
481 { | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
482 int c; |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
483 c = preproc_lex_fetch_byte(pp); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
484 if (c == CPP_EOL) |
300 | 485 { |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
486 preproc_lex_unfetch_byte(pp, c); |
300 | 487 preproc_throw_error(pp, "Bad #include"); |
488 lw_free(strbuf_end(strbuf)); | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
489 break; |
300 | 490 } |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
491 if (c == '>') |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
492 break; |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
493 strbuf_add(strbuf, c); |
300 | 494 } |
495 ct = preproc_next_token_nws(pp); | |
496 if (ct -> ttype != TOK_EOL) | |
497 { | |
498 preproc_throw_error(pp, "Bad #include"); | |
499 skip_eol(pp); | |
500 lw_free(strbuf_end(strbuf)); | |
501 return; | |
502 } | |
503 sys = 1; | |
504 fn = strbuf_end(strbuf); | |
505 goto doinc; | |
506 } | |
507 else | |
508 { | |
509 preproc_unget_token(pp, ct); | |
510 // computed include | |
511 ct = preproc_next_processed_token_nws(pp); | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
512 if (ct -> ttype == TOK_STR_LIT) |
300 | 513 goto usrinc; |
514 else if (ct -> ttype == TOK_LT) | |
515 { | |
516 strbuf = strbuf_new(); | |
517 for (;;) | |
518 { | |
519 ct = preproc_next_processed_token(pp); | |
520 if (ct -> ttype == TOK_GT) | |
521 break; | |
522 if (ct -> ttype == TOK_EOL) | |
523 { | |
524 preproc_throw_error(pp, "Bad #include"); | |
525 lw_free(strbuf_end(strbuf)); | |
526 return; | |
527 } | |
528 for (i = 0; ct -> strval[i]; ct++) | |
529 { | |
530 strbuf_add(strbuf, ct -> strval[i]); | |
531 } | |
532 } | |
533 ct = preproc_next_processed_token_nws(pp); | |
534 if (ct -> ttype != TOK_EOL) | |
535 { | |
536 preproc_throw_error(pp, "Bad #include"); | |
537 skip_eol(pp); | |
538 lw_free(strbuf_end(strbuf)); | |
539 return; | |
540 } | |
541 sys = 1; | |
542 fn = strbuf_end(strbuf); | |
543 goto doinc; | |
544 } | |
545 else | |
546 { | |
547 skip_eol(pp); | |
548 preproc_throw_error(pp, "Bad #include"); | |
549 return; | |
550 } | |
551 } | |
552 doinc: | |
553 // fn = preproc_find_file(pp, fn, sys); | |
554 fp = fopen(fn, "rb"); | |
555 if (!fp) | |
556 { | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
557 preproc_throw_error(pp, "Cannot open #include file %s - this is fatal", fn); |
300 | 558 exit(1); |
559 } | |
560 | |
561 /* save the current include file state, etc. */ | |
562 fs = lw_alloc(sizeof(struct preproc_info)); | |
563 *fs = *pp; | |
564 fs -> n = pp -> filestack; | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
565 pp -> curtok = NULL; |
300 | 566 pp -> filestack = fs; |
567 pp -> fn = fn; | |
568 pp -> fp = fp; | |
569 pp -> ra = CPP_NOUNG; | |
570 pp -> ppeolseen = 1; | |
571 pp -> eolstate = 0; | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
572 pp -> lineno = 1; |
300 | 573 pp -> column = 0; |
574 pp -> qseen = 0; | |
575 pp -> ungetbufl = 0; | |
576 pp -> ungetbufs = 0; | |
577 pp -> ungetbuf = NULL; | |
578 pp -> unget = 0; | |
579 pp -> eolseen = 0; | |
580 pp -> nlseen = 0; | |
581 pp -> skip_level = 0; | |
582 pp -> found_level = 0; | |
583 pp -> else_level = 0; | |
584 pp -> else_skip_level = 0; | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
585 pp -> tokqueue = NULL; |
300 | 586 // now get on with processing |
296 | 587 } |
588 | |
589 static void dir_line(struct preproc_info *pp) | |
590 { | |
300 | 591 struct token *ct; |
592 long lineno; | |
593 char *estr; | |
594 | |
595 lineno = -1; | |
596 | |
597 ct = preproc_next_processed_token_nws(pp); | |
598 if (ct -> ttype == TOK_NUMBER) | |
599 { | |
600 lineno = strtoul(ct -> strval, &estr, 10); | |
601 if (*estr) | |
602 { | |
603 preproc_throw_error(pp, "Bad #line"); | |
604 skip_eol(pp); | |
605 return; | |
606 } | |
607 } | |
608 else | |
609 { | |
610 preproc_throw_error(pp, "Bad #line"); | |
611 skip_eol(pp); | |
612 return; | |
613 } | |
614 ct = preproc_next_processed_token_nws(pp); | |
615 if (ct -> ttype == TOK_EOL) | |
616 { | |
617 pp -> lineno = lineno; | |
618 return; | |
619 } | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
620 if (ct -> ttype != TOK_STR_LIT) |
300 | 621 { |
622 preproc_throw_error(pp, "Bad #line"); | |
623 skip_eol(pp); | |
624 return; | |
625 } | |
626 estr = lw_strdup(ct -> strval); | |
627 ct = preproc_next_processed_token_nws(pp); | |
628 if (ct -> ttype != TOK_EOL) | |
629 { | |
630 preproc_throw_error(pp, "Bad #line"); | |
631 skip_eol(pp); | |
632 lw_free(estr); | |
633 return; | |
634 } | |
635 pp -> fn = estr; | |
636 pp -> lineno = lineno; | |
296 | 637 } |
638 | |
639 static void dir_pragma(struct preproc_info *pp) | |
640 { | |
641 if (pp -> skip_level) | |
642 { | |
643 skip_eol(pp); | |
644 return; | |
645 } | |
646 | |
647 preproc_throw_warning(pp, "Unsupported #pragma"); | |
648 skip_eol(pp); | |
649 } | |
650 | |
651 struct { char *name; void (*fn)(struct preproc_info *); } dirlist[] = | |
652 { | |
653 { "ifdef", dir_ifdef }, | |
654 { "ifndef", dir_ifndef }, | |
655 { "if", dir_if }, | |
656 { "else", dir_else }, | |
657 { "elif", dir_elif }, | |
658 { "endif", dir_endif }, | |
659 { "define", dir_define }, | |
660 { "undef", dir_undef }, | |
661 { "include", dir_include }, | |
662 { "error", dir_error }, | |
663 { "warning", dir_warning }, | |
664 { "line", dir_line }, | |
665 { "pragma", dir_pragma }, | |
666 { NULL, NULL } | |
667 }; | |
668 | |
669 static void process_directive(struct preproc_info *pp) | |
670 { | |
671 struct token *ct; | |
672 int i; | |
673 | |
674 do | |
675 { | |
676 ct = preproc_next_token(pp); | |
677 } while (ct -> ttype == TOK_WSPACE); | |
678 | |
679 // NULL directive | |
680 if (ct -> ttype == TOK_EOL) | |
681 return; | |
682 | |
683 if (ct -> ttype != TOK_IDENT) | |
684 goto baddir; | |
685 | |
686 for (i = 0; dirlist[i].name; i++) | |
687 { | |
688 if (strcmp(dirlist[i].name, ct -> strval) == 0) | |
689 { | |
690 (*(dirlist[i].fn))(pp); | |
691 return; | |
692 } | |
693 } | |
694 baddir: | |
695 preproc_throw_error(pp, "Bad preprocessor directive"); | |
696 while (ct -> ttype != TOK_EOL) | |
697 ct = preproc_next_token(pp); | |
698 return; | |
699 } | |
700 | |
701 /* | |
702 Evaluate a preprocessor expression | |
703 */ | |
704 | |
705 /* same as skip_eol() but the EOL token is not consumed */ | |
706 static void skip_eoe(struct preproc_info *pp) | |
707 { | |
708 skip_eol(pp); | |
709 preproc_unget_token(pp, pp -> curtok); | |
710 } | |
711 | |
712 static long eval_expr_real(struct preproc_info *, int); | |
301
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
713 static long preproc_numval(struct preproc_info *, struct token *); |
296 | 714 |
715 static long eval_term_real(struct preproc_info *pp) | |
716 { | |
717 long tval = 0; | |
718 struct token *ct; | |
719 | |
720 eval_next: | |
721 ct = preproc_next_processed_token_nws(pp); | |
722 if (ct -> ttype == TOK_EOL) | |
723 { | |
724 preproc_throw_error(pp, "Bad expression"); | |
725 return 0; | |
726 } | |
727 | |
728 switch (ct -> ttype) | |
729 { | |
730 case TOK_OPAREN: | |
731 tval = eval_expr_real(pp, 0); | |
732 ct = preproc_next_processed_token_nws(pp); | |
733 if (ct -> ttype != ')') | |
734 { | |
735 preproc_throw_error(pp, "Unbalanced () in expression"); | |
736 skip_eoe(pp); | |
737 return 0; | |
738 } | |
739 return tval; | |
740 | |
741 case TOK_ADD: // unary + | |
742 goto eval_next; | |
743 | |
744 case TOK_SUB: // unary - | |
745 tval = eval_expr_real(pp, 200); | |
746 return -tval; | |
747 | |
748 /* NOTE: we should only get "TOK_IDENT" from an undefined macro */ | |
749 case TOK_IDENT: // some sort of function, symbol, etc. | |
750 if (strcmp(ct -> strval, "defined")) | |
751 { | |
752 /* the defined operator */ | |
753 /* any number in the "defined" bit will be | |
754 treated as a defined symbol, even zero */ | |
755 ct = preproc_next_token_nws(pp); | |
756 if (ct -> ttype == TOK_OPAREN) | |
757 { | |
758 ct = preproc_next_token_nws(pp); | |
759 if (ct -> ttype != TOK_IDENT) | |
760 { | |
761 preproc_throw_error(pp, "Bad expression"); | |
762 skip_eoe(pp); | |
763 return 0; | |
764 } | |
765 if (symtab_find(pp, ct -> strval) == NULL) | |
766 tval = 0; | |
767 else | |
768 tval = 1; | |
769 ct = preproc_next_token_nws(pp); | |
770 if (ct -> ttype != TOK_CPAREN) | |
771 { | |
772 preproc_throw_error(pp, "Bad expression"); | |
773 skip_eoe(pp); | |
774 return 0; | |
775 } | |
776 return tval; | |
777 } | |
778 else if (ct -> ttype == TOK_IDENT) | |
779 { | |
780 return (symtab_find(pp, ct -> strval) != NULL) ? 1 : 0; | |
781 } | |
782 preproc_throw_error(pp, "Bad expression"); | |
783 skip_eoe(pp); | |
784 return 0; | |
785 } | |
786 /* unknown identifier - it's zero */ | |
787 return 0; | |
788 | |
789 /* numbers */ | |
790 case TOK_NUMBER: | |
301
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
791 return preproc_numval(pp, ct); |
296 | 792 |
793 default: | |
794 preproc_throw_error(pp, "Bad expression"); | |
795 skip_eoe(pp); | |
796 return 0; | |
797 } | |
798 return 0; | |
799 } | |
800 | |
801 static long eval_expr_real(struct preproc_info *pp, int p) | |
802 { | |
803 static const struct operinfo | |
804 { | |
805 int tok; | |
806 int prec; | |
807 } operators[] = | |
808 { | |
809 { TOK_ADD, 100 }, | |
810 { TOK_SUB, 100 }, | |
811 { TOK_STAR, 150 }, | |
812 { TOK_DIV, 150 }, | |
813 { TOK_MOD, 150 }, | |
814 { TOK_LT, 75 }, | |
815 { TOK_LE, 75 }, | |
816 { TOK_GT, 75 }, | |
817 { TOK_GE, 75 }, | |
818 { TOK_EQ, 70 }, | |
819 { TOK_NE, 70 }, | |
820 { TOK_BAND, 30 }, | |
821 { TOK_BOR, 25 }, | |
822 { TOK_NONE, 0 } | |
823 }; | |
824 | |
825 int op; | |
826 long term1, term2, term3; | |
827 struct token *ct; | |
828 | |
829 term1 = eval_term_real(pp); | |
830 eval_next: | |
831 ct = preproc_next_processed_token_nws(pp); | |
832 for (op = 0; operators[op].tok != TOK_NONE; op++) | |
833 { | |
834 if (operators[op].tok == ct -> ttype) | |
835 break; | |
836 } | |
837 /* if it isn't a recognized operator, assume end of expression */ | |
838 if (operators[op].tok == TOK_NONE) | |
839 { | |
840 preproc_unget_token(pp, ct); | |
841 return term1; | |
842 } | |
843 | |
844 /* if new operation is not higher than the current precedence, let the previous op finish */ | |
845 if (operators[op].prec <= p) | |
846 return term1; | |
847 | |
848 /* get the second term */ | |
849 term2 = eval_expr_real(pp, operators[op].prec); | |
850 | |
851 switch (operators[op].tok) | |
852 { | |
853 case TOK_ADD: | |
854 term3 = term1 + term2; | |
855 break; | |
856 | |
857 case TOK_SUB: | |
858 term3 = term1 - term2; | |
859 break; | |
860 | |
861 case TOK_STAR: | |
862 term3 = term1 * term2; | |
863 break; | |
864 | |
865 case TOK_DIV: | |
866 if (!term2) | |
867 { | |
868 preproc_throw_warning(pp, "Division by zero"); | |
869 term3 = 0; | |
870 break; | |
871 } | |
872 term3 = term1 / term2; | |
873 break; | |
874 | |
875 case TOK_MOD: | |
876 if (!term2) | |
877 { | |
878 preproc_throw_warning(pp, "Division by zero"); | |
879 term3 = 0; | |
880 break; | |
881 } | |
882 term3 = term1 % term2; | |
883 break; | |
884 | |
885 case TOK_BAND: | |
886 term3 = (term1 && term2); | |
887 break; | |
888 | |
889 case TOK_BOR: | |
890 term3 = (term1 || term2); | |
891 break; | |
892 | |
893 case TOK_EQ: | |
894 term3 = (term1 == term2); | |
895 break; | |
896 | |
897 case TOK_NE: | |
898 term3 = (term1 != term2); | |
899 break; | |
900 | |
901 case TOK_GT: | |
902 term3 = (term1 > term2); | |
903 break; | |
904 | |
905 case TOK_GE: | |
906 term3 = (term1 >= term2); | |
907 break; | |
908 | |
909 case TOK_LT: | |
910 term3 = (term1 < term2); | |
911 break; | |
912 | |
913 case TOK_LE: | |
914 term3 = (term1 <= term2); | |
915 break; | |
916 | |
917 default: | |
918 term3 = 0; | |
919 break; | |
920 } | |
921 term1 = term3; | |
922 goto eval_next; | |
923 } | |
924 | |
925 static long eval_expr(struct preproc_info *pp) | |
926 { | |
927 long rv; | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
928 struct token *t; |
296 | 929 |
930 rv = eval_expr_real(pp, 0); | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
931 t = preproc_next_token_nws(pp); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
932 if (t -> ttype != TOK_EOL) |
296 | 933 { |
934 preproc_throw_error(pp, "Bad expression"); | |
935 skip_eol(pp); | |
936 } | |
937 return rv; | |
938 } | |
939 | |
301
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
940 static int eval_escape(char **t) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
941 { |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
942 int c; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
943 int c2; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
944 |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
945 if (**t == 0) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
946 return 0; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
947 c = *(*t)++; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
948 int rv = 0; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
949 |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
950 switch (c) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
951 { |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
952 case 'n': |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
953 return 10; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
954 case 'r': |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
955 return 13; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
956 case 'b': |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
957 return 8; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
958 case 'e': |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
959 return 27; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
960 case 'f': |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
961 return 12; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
962 case 't': |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
963 return 9; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
964 case 'v': |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
965 return 11; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
966 case 'a': |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
967 return 7; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
968 case '0': case '1': case '2': case '3': case '4': |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
969 case '5': case '6': case '7': |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
970 // octal constant |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
971 rv = c - '0'; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
972 c2 = 1; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
973 for (; c2 < 3; c2++) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
974 { |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
975 c = *(*t)++; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
976 if (c < '0' || c > '7') |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
977 break; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
978 rv = (rv << 3) | (c - '0'); |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
979 } |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
980 return rv; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
981 case 'x': |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
982 // hex constant |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
983 for (;;) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
984 { |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
985 c = *(*t)++; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
986 if (c < '0' || (c > '9' && c < 'A') || (c > 'F' && c < 'a') || c > 'f') |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
987 break; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
988 c = c - '0'; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
989 if (c > 9) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
990 c -= 7; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
991 if (c > 15) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
992 c -= 32; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
993 rv = (rv << 4) | c; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
994 } |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
995 return rv & 0xff; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
996 default: |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
997 return c; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
998 } |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
999 } |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1000 |
296 | 1001 /* convert a numeric string to a number */ |
301
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1002 long preproc_numval(struct preproc_info *pp, struct token *t) |
296 | 1003 { |
301
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1004 unsigned long long rv = 0; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1005 unsigned long long rv2 = 0; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1006 char *tstr = t -> strval; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1007 int radix = 10; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1008 int c; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1009 int ovf = 0; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1010 union { long sv; unsigned long uv; } tv; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1011 |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1012 if (t -> ttype == TOK_CHR_LIT) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1013 { |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1014 tstr++; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1015 while (*tstr && *tstr != '\'') |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1016 { |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1017 if (*tstr == '\\') |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1018 { |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1019 tstr++; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1020 c = eval_escape(&tstr); |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1021 } |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1022 else |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1023 c = *tstr++; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1024 rv = (rv << 8) | c; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1025 if (rv / radix < rv2) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1026 ovf = 1; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1027 rv2 = rv; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1028 |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1029 } |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1030 goto done; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1031 } |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1032 |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1033 |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1034 if (*tstr == '0') |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1035 { |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1036 radix = 8; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1037 tstr++; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1038 if (*tstr == 'x') |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1039 { |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1040 radix = 16; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1041 tstr++; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1042 } |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1043 } |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1044 while (*tstr) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1045 { |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1046 c = *tstr++; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1047 if (c < '0' || (c > '9' && c < 'A') || (c > 'F' && c < 'a') || c > 'f') |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1048 break; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1049 c -= '0'; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1050 if (c > 9) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1051 c -= 7; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1052 if (c > 15) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1053 c -= 32; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1054 if (c >= radix) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1055 break; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1056 rv = rv * radix + c; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1057 if (rv / radix < rv2) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1058 ovf = 1; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1059 rv2 = rv; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1060 } |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1061 tstr--; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1062 while (*tstr == 'l' || *tstr == 'L') |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1063 tstr++; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1064 tv.uv = rv; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1065 if (tv.sv < 0 && radix == 10) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1066 ovf = 1; |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1067 done: |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1068 if (ovf) |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1069 preproc_throw_error(pp, "Constant out of range: %s", t -> strval); |
6f7fe78bb868
Add string -> number conversion for preproc expression evaluator
William Astle <lost@l-w.ca>
parents:
300
diff
changeset
|
1070 return rv; |
296 | 1071 } |
1072 | |
1073 /* | |
1074 Below here is the logic for expanding a macro | |
1075 */ | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1076 static char *stringify(struct token_list *tli) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1077 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1078 struct strbuf *s; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1079 int ws = 0; |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1080 struct token *tl = tli -> head; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1081 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1082 s = strbuf_new(); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1083 strbuf_add(s, '"'); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1084 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1085 while (tl && tl -> ttype == TOK_WSPACE) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1086 tl = tl -> next; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1087 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1088 for (; tl; tl = tl -> next) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1089 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1090 if (tl -> ttype == TOK_WSPACE) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1091 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1092 ws = 1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1093 continue; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1094 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1095 if (ws) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1096 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1097 strbuf_add(s, ' '); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1098 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1099 for (ws = 0; tl -> strval[ws]; ws++) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1100 { |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
1101 if (tl -> ttype == TOK_STR_LIT || tl -> ttype == TOK_CHR_LIT) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1102 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1103 if (tl -> strval[ws] == '"' || tl -> strval[ws] == '\\') |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1104 strbuf_add(s, '\\'); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1105 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1106 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1107 ws = 0; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1108 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1109 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1110 strbuf_add(s, '"'); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1111 return strbuf_end(s); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1112 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1113 |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1114 static int macro_arg(struct symtab_e *s, char *str) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1115 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1116 int i; |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1117 if (strcmp(str, "__VA_ARGS__") == 0) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1118 i = s -> nargs; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1119 else |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1120 for (i = 0; i < s -> nargs; i++) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1121 if (strcmp(s -> params[i], str) == 0) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1122 break; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1123 if (i == s -> nargs) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1124 if (s -> vargs == 0) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1125 return -1; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1126 return i; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1127 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1128 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1129 /* return list to tokens as a result of ## expansion */ |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1130 static struct token_list *paste_tokens(struct preproc_info *pp, struct symtab_e *s, struct token_list **arglist, struct token *t1, struct token *t2) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1131 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1132 struct token_list *left; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1133 struct token_list *right; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1134 char *tstr; |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1135 struct token *ttok; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1136 int i; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1137 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1138 if (t1 -> ttype == TOK_IDENT) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1139 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1140 i = macro_arg(s, t1 -> strval); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1141 if (i == -1) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1142 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1143 left = token_list_create(); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1144 token_list_append(left, token_dup(t1)); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1145 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1146 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1147 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1148 left = token_list_dup(arglist[i]); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1149 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1150 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1151 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1152 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1153 left = token_list_create(); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1154 token_list_append(left, token_dup(t1)); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1155 } |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1156 // munch trailing white space |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1157 while (left -> tail && left -> tail -> ttype == TOK_WSPACE) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1158 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1159 token_list_remove(left -> tail); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1160 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1161 |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1162 if (t2 -> ttype == TOK_IDENT) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1163 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1164 i = macro_arg(s, t2 -> strval); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1165 if (i == -1) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1166 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1167 right = token_list_create(); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1168 token_list_append(right, token_dup(t2)); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1169 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1170 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1171 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1172 right = token_list_dup(arglist[i]); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1173 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1174 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1175 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1176 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1177 right = token_list_create(); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1178 token_list_append(right, token_dup(t2)); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1179 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1180 // munch leading white space |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1181 while (right -> head && right -> head -> ttype == TOK_WSPACE) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1182 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1183 token_list_remove(right -> head); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1184 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1185 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1186 // nothing to append at all |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1187 if (left -> head != NULL && right -> head == NULL) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1188 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1189 // right arg is empty - use left |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1190 token_list_destroy(right); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1191 return left; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1192 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1193 if (left -> head == NULL && right -> head != NULL) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1194 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1195 // left arg is empty, use right |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1196 token_list_destroy(left); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1197 return right; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1198 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1199 if (left -> head == NULL && right -> head == NULL) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1200 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1201 // both empty, use left |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1202 token_list_destroy(right); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1203 return left; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1204 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1205 |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1206 // both non-empty - past left tail with right head |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1207 // then past the right list onto the left |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1208 tstr = lw_alloc(strlen(left -> tail -> strval) + strlen(right -> head -> strval) + 1); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1209 strcpy(tstr, left -> tail -> strval); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1210 strcat(tstr, right -> head -> strval); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1211 |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1212 pp -> lexstr = tstr; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1213 pp -> lexstrloc = 0; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1214 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1215 ttok = preproc_lex_next_token(pp); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1216 if (ttok -> ttype != TOK_ERROR && pp -> lexstr[pp -> lexstrloc] == 0) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1217 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1218 // we have a new token here |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1219 token_list_remove(left -> tail); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1220 token_list_remove(right -> head); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1221 token_list_append(left, token_dup(ttok)); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1222 } |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1223 lw_free(tstr); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1224 pp -> lexstr = NULL; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1225 pp -> lexstrloc = 0; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1226 for (ttok = right -> head; ttok; ttok = ttok -> next) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1227 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1228 token_list_append(left, token_dup(ttok)); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1229 } |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1230 token_list_destroy(right); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1231 return left; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1232 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1233 |
296 | 1234 static int expand_macro(struct preproc_info *pp, char *mname) |
1235 { | |
1236 struct symtab_e *s; | |
1237 struct token *t, *t2, *t3; | |
1238 int nargs = 0; | |
1239 struct expand_e *e; | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1240 struct token_list **exparglist = NULL; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1241 struct token_list **arglist = NULL; |
296 | 1242 int i; |
297
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1243 int pcount; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1244 char *tstr; |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1245 struct token_list *expand_list; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1246 int repl; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1247 struct token_list *rtl; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1248 |
296 | 1249 s = symtab_find(pp, mname); |
1250 if (!s) | |
1251 return 0; | |
1252 | |
1253 for (e = pp -> expand_list; e; e = e -> next) | |
1254 { | |
1255 /* don't expand if we're already expanding the same macro */ | |
1256 if (e -> s == s) | |
1257 return 0; | |
1258 } | |
1259 | |
1260 if (s -> nargs == -1) | |
1261 { | |
1262 /* short circuit NULL expansion */ | |
1263 if (s -> tl == NULL) | |
1264 return 1; | |
1265 | |
1266 goto expandmacro; | |
1267 } | |
1268 | |
1269 // look for opening paren after optional whitespace | |
1270 t2 = NULL; | |
1271 t = NULL; | |
1272 for (;;) | |
1273 { | |
1274 t = preproc_next_token(pp); | |
1275 if (t -> ttype != TOK_WSPACE && t -> ttype != TOK_EOL) | |
1276 break; | |
1277 t -> next = t2; | |
1278 t2 = t2; | |
1279 } | |
1280 if (t -> ttype != TOK_OPAREN) | |
1281 { | |
1282 // not a function-like invocation | |
1283 while (t2) | |
1284 { | |
1285 t = t2 -> next; | |
1286 preproc_unget_token(pp, t2); | |
1287 t2 = t; | |
1288 } | |
1289 return 0; | |
1290 } | |
1291 | |
1292 // parse parameters here | |
1293 t = preproc_next_token_nws(pp); | |
1294 nargs = 1; | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1295 arglist = lw_alloc(sizeof(struct token_list *)); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1296 arglist[0] = token_list_create(); |
296 | 1297 t2 = NULL; |
1298 | |
1299 while (t -> ttype != TOK_CPAREN) | |
1300 { | |
297
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1301 pcount = 0; |
296 | 1302 if (t -> ttype == TOK_EOF) |
1303 { | |
1304 preproc_throw_error(pp, "Unexpected EOF in macro call"); | |
1305 break; | |
1306 } | |
1307 if (t -> ttype == TOK_EOL) | |
1308 continue; | |
297
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1309 if (t -> ttype == TOK_OPAREN) |
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1310 pcount++; |
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1311 else if (t -> ttype == TOK_CPAREN && pcount) |
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1312 pcount--; |
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1313 if (t -> ttype == TOK_COMMA && pcount == 0) |
296 | 1314 { |
1315 if (!(s -> vargs) || (nargs > s -> nargs)) | |
1316 { | |
1317 nargs++; | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1318 arglist = lw_realloc(arglist, sizeof(struct token_list *) * nargs); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1319 arglist[nargs - 1] = token_list_create(); |
296 | 1320 t2 = NULL; |
1321 continue; | |
1322 } | |
1323 } | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1324 token_list_append(arglist[nargs - 1], token_dup(t)); |
296 | 1325 } |
1326 | |
1327 if (s -> vargs) | |
1328 { | |
1329 if (nargs <= s -> nargs) | |
1330 { | |
1331 preproc_throw_error(pp, "Wrong number of arguments (%d) for variadic macro %s which takes %d arguments", nargs, mname, s -> nargs); | |
1332 } | |
1333 } | |
1334 else | |
1335 { | |
1336 if (s -> nargs != nargs && !(s -> nargs == 0 && nargs == 1 && arglist[nargs - 1])) | |
1337 { | |
1338 preproc_throw_error(pp, "Wrong number of arguments (%d) for macro %s which takes %d arguments", nargs, mname, s -> nargs); | |
1339 } | |
1340 } | |
1341 | |
1342 /* now calculate the pre-expansions of the arguments */ | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1343 exparglist = lw_alloc(nargs * sizeof(struct token_list *)); |
296 | 1344 for (i = 0; i < nargs; i++) |
1345 { | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1346 exparglist[i] = token_list_create(); |
296 | 1347 // NOTE: do nothing if empty argument |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1348 if (arglist[i] == NULL || arglist[i] -> head == NULL) |
296 | 1349 continue; |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1350 pp -> sourcelist = arglist[i]->head; |
296 | 1351 for (;;) |
1352 { | |
1353 t = preproc_next_processed_token(pp); | |
1354 if (t -> ttype == TOK_EOF) | |
1355 break; | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1356 token_list_append(exparglist[i], token_dup(t)); |
296 | 1357 } |
1358 } | |
1359 | |
1360 expandmacro: | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1361 expand_list = token_list_dup(s -> tl); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1362 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1363 // scan for stringification and handle it |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1364 repl = 0; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1365 while (repl == 0) |
296 | 1366 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1367 for (t = expand_list -> head; t; t = t -> next) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1368 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1369 if (t -> ttype == TOK_HASH && t -> next && t -> next -> ttype == TOK_IDENT) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1370 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1371 i = macro_arg(s, t -> next -> strval); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1372 if (i != -1) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1373 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1374 repl = 1; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1375 tstr = stringify(arglist[i]); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1376 token_list_remove(t -> next); |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
1377 token_list_insert(expand_list, t, token_create(TOK_STR_LIT, tstr, t -> lineno, t -> column, t -> fn)); |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1378 token_list_remove(t); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1379 lw_free(tstr); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1380 break; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1381 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1382 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1383 } |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
1384 repl = 1; |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1385 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1386 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1387 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1388 // scan for concatenation and handle it |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1389 |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1390 for (t = expand_list -> head; t; t = t -> next) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1391 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1392 if (t -> ttype == TOK_DBLHASH) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1393 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1394 // have a concatenation operator here |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1395 for (t2 = t -> prev; t2; t2 = t2 -> prev) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1396 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1397 if (t2 -> ttype != TOK_WSPACE) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1398 break; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1399 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1400 for (t3 = t -> next; t3; t3 = t3 -> next); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1401 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1402 if (t3 -> ttype != TOK_WSPACE) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1403 break; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1404 } |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1405 // if no non-whitespace before or after, ignore it |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1406 if (!t2 || !t3) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1407 continue; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1408 // eat the whitespace before and after |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1409 while (t -> prev != t2) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1410 token_list_remove(t -> prev); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1411 while (t -> next != t3) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1412 token_list_remove(t -> next); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1413 // now paste t -> prev with t -> next and replace t with the result |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1414 // continue scanning for ## at t -> next -> next |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1415 t3 = t -> next -> next; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1416 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1417 rtl = paste_tokens(pp, s, arglist, t -> prev, t -> next); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1418 token_list_remove(t -> next); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1419 token_list_remove(t -> prev); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1420 t2 = t -> prev; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1421 token_list_remove(t); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1422 for (t = rtl -> head; t; t = t -> next) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1423 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1424 token_list_insert(expand_list, t2, token_dup(t)); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1425 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1426 t = t3 -> prev; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1427 token_list_destroy(rtl); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1428 } |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1429 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1430 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1431 // now scan for arguments and expand them |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1432 for (t = expand_list -> head; t; t = t -> next) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1433 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1434 again: |
296 | 1435 if (t -> ttype == TOK_IDENT) |
1436 { | |
1437 /* identifiers might need expansion to arguments */ | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1438 i = macro_arg(s, t -> strval); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1439 if (i != -1) |
296 | 1440 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1441 t3 = t -> next; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1442 for (t2 = exparglist[i] -> tail; t2; t2 = t2 -> prev) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1443 token_list_insert(expand_list, t, token_dup(t2)); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1444 token_list_remove(t); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1445 t = t3; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1446 goto again; |
296 | 1447 } |
1448 } | |
1449 } | |
1450 | |
1451 /* put the new expansion in front of the input, if relevant; if we | |
1452 expanded to nothing, no need to create an expansion record or | |
1453 put anything into the input queue */ | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1454 if (expand_list -> head) |
296 | 1455 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1456 token_list_append(expand_list, token_create(TOK_ENDEXPAND, "", -1, -1, "")); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1457 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1458 // move the expanded list into the token queue |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1459 for (t = expand_list -> tail; t; t = t -> prev) |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1460 preproc_unget_token(pp, token_dup(t)); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1461 |
296 | 1462 /* set up expansion record */ |
1463 e = lw_alloc(sizeof(struct expand_e)); | |
1464 e -> next = pp -> expand_list; | |
1465 pp -> expand_list = e; | |
1466 e -> s = s; | |
1467 } | |
1468 | |
1469 /* now clean up */ | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1470 token_list_destroy(expand_list); |
296 | 1471 for (i = 0; i < nargs; i++) |
1472 { | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1473 token_list_destroy(arglist[i]); |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1474 token_list_destroy(exparglist[i]); |
296 | 1475 } |
1476 lw_free(arglist); | |
1477 lw_free(exparglist); | |
1478 | |
1479 return 1; | |
1480 } | |
304
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
301
diff
changeset
|
1481 |
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
301
diff
changeset
|
1482 struct token *preproc_next(struct preproc_info *pp) |
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
301
diff
changeset
|
1483 { |
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
301
diff
changeset
|
1484 struct token *t; |
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
301
diff
changeset
|
1485 |
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
301
diff
changeset
|
1486 t = preproc_next_processed_token(pp); |
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
301
diff
changeset
|
1487 pp -> curtok = NULL; |
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
301
diff
changeset
|
1488 return t; |
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
301
diff
changeset
|
1489 } |