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