Mercurial > hg > index.cgi
annotate lwcc/preproc.c @ 300:8d6c47395653 ccdev
Implemented #include and #line
Theoretically, directives are now implemented.
author | William Astle <lost@l-w.ca> |
---|---|
date | Sun, 15 Sep 2013 13:49:00 -0600 |
parents | 856caf91ffaa |
children | 6f7fe78bb868 |
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 | |
51 if (ct -> ttype == TOK_HASH && pp -> eolseen == 1) | |
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); | |
708 static long preproc_numval(struct token *); | |
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: | |
786 return preproc_numval(ct); | |
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 | |
933 /* convert a numeric string to a number */ | |
934 long preproc_numval(struct token *t) | |
935 { | |
936 return 0; | |
937 } | |
938 | |
939 /* | |
940 Below here is the logic for expanding a macro | |
941 */ | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
942 static char *stringify(struct token_list *tli) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
943 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
944 struct strbuf *s; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
945 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
|
946 struct token *tl = tli -> head; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
947 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
948 s = strbuf_new(); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
949 strbuf_add(s, '"'); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
950 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
951 while (tl && tl -> ttype == TOK_WSPACE) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
952 tl = tl -> next; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
953 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
954 for (; tl; tl = tl -> next) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
955 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
956 if (tl -> ttype == TOK_WSPACE) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
957 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
958 ws = 1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
959 continue; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
960 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
961 if (ws) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
962 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
963 strbuf_add(s, ' '); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
964 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
965 for (ws = 0; tl -> strval[ws]; ws++) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
966 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
967 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
|
968 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
969 if (tl -> strval[ws] == '"' || tl -> strval[ws] == '\\') |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
970 strbuf_add(s, '\\'); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
971 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
972 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
973 ws = 0; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
974 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
975 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
976 strbuf_add(s, '"'); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
977 return strbuf_end(s); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
978 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
979 |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
980 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
|
981 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
982 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
|
983 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
|
984 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
|
985 else |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
986 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
|
987 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
|
988 break; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
989 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
|
990 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
|
991 return -1; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
992 return i; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
993 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
994 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
995 /* 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
|
996 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
|
997 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
998 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
|
999 struct token_list *right; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1000 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
|
1001 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
|
1002 int i; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1003 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1004 if (t1 -> ttype == TOK_IDENT) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1005 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1006 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
|
1007 if (i == -1) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1008 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1009 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
|
1010 token_list_append(left, token_dup(t1)); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1011 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1012 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1013 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1014 left = token_list_dup(arglist[i]); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1015 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1016 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1017 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1018 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1019 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
|
1020 token_list_append(left, token_dup(t1)); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1021 } |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1022 // 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
|
1023 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
|
1024 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1025 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
|
1026 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1027 |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1028 if (t2 -> ttype == TOK_IDENT) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1029 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1030 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
|
1031 if (i == -1) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1032 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1033 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
|
1034 token_list_append(right, token_dup(t2)); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1035 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1036 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1037 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1038 right = token_list_dup(arglist[i]); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1039 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1040 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1041 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1042 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1043 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
|
1044 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
|
1045 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1046 // 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
|
1047 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
|
1048 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1049 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
|
1050 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1051 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1052 // 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
|
1053 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
|
1054 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1055 // 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
|
1056 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
|
1057 return left; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1058 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1059 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
|
1060 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1061 // 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
|
1062 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
|
1063 return right; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1064 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1065 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
|
1066 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1067 // 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
|
1068 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
|
1069 return left; |
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 |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1072 // 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
|
1073 // 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
|
1074 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
|
1075 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
|
1076 strcat(tstr, right -> head -> strval); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1077 |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1078 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
|
1079 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
|
1080 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1081 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
|
1082 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
|
1083 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1084 // 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
|
1085 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
|
1086 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
|
1087 token_list_append(left, token_dup(ttok)); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1088 } |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1089 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
|
1090 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
|
1091 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
|
1092 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
|
1093 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1094 token_list_append(left, token_dup(ttok)); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1095 } |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1096 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
|
1097 return left; |
298
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 |
296 | 1100 static int expand_macro(struct preproc_info *pp, char *mname) |
1101 { | |
1102 struct symtab_e *s; | |
1103 struct token *t, *t2, *t3; | |
1104 int nargs = 0; | |
1105 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
|
1106 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
|
1107 struct token_list **arglist = NULL; |
296 | 1108 int i; |
297
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1109 int pcount; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1110 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
|
1111 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
|
1112 int repl; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1113 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
|
1114 |
296 | 1115 s = symtab_find(pp, mname); |
1116 if (!s) | |
1117 return 0; | |
1118 | |
1119 for (e = pp -> expand_list; e; e = e -> next) | |
1120 { | |
1121 /* don't expand if we're already expanding the same macro */ | |
1122 if (e -> s == s) | |
1123 return 0; | |
1124 } | |
1125 | |
1126 if (s -> nargs == -1) | |
1127 { | |
1128 /* short circuit NULL expansion */ | |
1129 if (s -> tl == NULL) | |
1130 return 1; | |
1131 | |
1132 goto expandmacro; | |
1133 } | |
1134 | |
1135 // look for opening paren after optional whitespace | |
1136 t2 = NULL; | |
1137 t = NULL; | |
1138 for (;;) | |
1139 { | |
1140 t = preproc_next_token(pp); | |
1141 if (t -> ttype != TOK_WSPACE && t -> ttype != TOK_EOL) | |
1142 break; | |
1143 t -> next = t2; | |
1144 t2 = t2; | |
1145 } | |
1146 if (t -> ttype != TOK_OPAREN) | |
1147 { | |
1148 // not a function-like invocation | |
1149 while (t2) | |
1150 { | |
1151 t = t2 -> next; | |
1152 preproc_unget_token(pp, t2); | |
1153 t2 = t; | |
1154 } | |
1155 return 0; | |
1156 } | |
1157 | |
1158 // parse parameters here | |
1159 t = preproc_next_token_nws(pp); | |
1160 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
|
1161 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
|
1162 arglist[0] = token_list_create(); |
296 | 1163 t2 = NULL; |
1164 | |
1165 while (t -> ttype != TOK_CPAREN) | |
1166 { | |
297
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1167 pcount = 0; |
296 | 1168 if (t -> ttype == TOK_EOF) |
1169 { | |
1170 preproc_throw_error(pp, "Unexpected EOF in macro call"); | |
1171 break; | |
1172 } | |
1173 if (t -> ttype == TOK_EOL) | |
1174 continue; | |
297
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1175 if (t -> ttype == TOK_OPAREN) |
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1176 pcount++; |
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1177 else if (t -> ttype == TOK_CPAREN && pcount) |
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1178 pcount--; |
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1179 if (t -> ttype == TOK_COMMA && pcount == 0) |
296 | 1180 { |
1181 if (!(s -> vargs) || (nargs > s -> nargs)) | |
1182 { | |
1183 nargs++; | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1184 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
|
1185 arglist[nargs - 1] = token_list_create(); |
296 | 1186 t2 = NULL; |
1187 continue; | |
1188 } | |
1189 } | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1190 token_list_append(arglist[nargs - 1], token_dup(t)); |
296 | 1191 } |
1192 | |
1193 if (s -> vargs) | |
1194 { | |
1195 if (nargs <= s -> nargs) | |
1196 { | |
1197 preproc_throw_error(pp, "Wrong number of arguments (%d) for variadic macro %s which takes %d arguments", nargs, mname, s -> nargs); | |
1198 } | |
1199 } | |
1200 else | |
1201 { | |
1202 if (s -> nargs != nargs && !(s -> nargs == 0 && nargs == 1 && arglist[nargs - 1])) | |
1203 { | |
1204 preproc_throw_error(pp, "Wrong number of arguments (%d) for macro %s which takes %d arguments", nargs, mname, s -> nargs); | |
1205 } | |
1206 } | |
1207 | |
1208 /* 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
|
1209 exparglist = lw_alloc(nargs * sizeof(struct token_list *)); |
296 | 1210 for (i = 0; i < nargs; i++) |
1211 { | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1212 exparglist[i] = token_list_create(); |
296 | 1213 // 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
|
1214 if (arglist[i] == NULL || arglist[i] -> head == NULL) |
296 | 1215 continue; |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1216 pp -> sourcelist = arglist[i]->head; |
296 | 1217 for (;;) |
1218 { | |
1219 t = preproc_next_processed_token(pp); | |
1220 if (t -> ttype == TOK_EOF) | |
1221 break; | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1222 token_list_append(exparglist[i], token_dup(t)); |
296 | 1223 } |
1224 } | |
1225 | |
1226 expandmacro: | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1227 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
|
1228 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1229 // 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
|
1230 repl = 0; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1231 while (repl == 0) |
296 | 1232 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1233 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
|
1234 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1235 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
|
1236 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1237 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
|
1238 if (i != -1) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1239 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1240 repl = 1; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1241 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
|
1242 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
|
1243 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
|
1244 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
|
1245 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
|
1246 break; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1247 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1248 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1249 } |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1250 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1251 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1252 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1253 // scan for concatenation and handle it |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1254 |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1255 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
|
1256 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1257 if (t -> ttype == TOK_DBLHASH) |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1258 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1259 // 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
|
1260 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
|
1261 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1262 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
|
1263 break; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1264 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1265 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
|
1266 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1267 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
|
1268 break; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1269 } |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1270 // 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
|
1271 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
|
1272 continue; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1273 // 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
|
1274 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
|
1275 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
|
1276 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
|
1277 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
|
1278 // 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
|
1279 // 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
|
1280 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
|
1281 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1282 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
|
1283 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
|
1284 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
|
1285 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
|
1286 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
|
1287 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
|
1288 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1289 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
|
1290 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1291 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
|
1292 token_list_destroy(rtl); |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1293 } |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1294 } |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1295 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1296 // 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
|
1297 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
|
1298 { |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1299 again: |
296 | 1300 if (t -> ttype == TOK_IDENT) |
1301 { | |
1302 /* 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
|
1303 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
|
1304 if (i != -1) |
296 | 1305 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1306 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
|
1307 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
|
1308 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
|
1309 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
|
1310 t = t3; |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1311 goto again; |
296 | 1312 } |
1313 } | |
1314 } | |
1315 | |
1316 /* put the new expansion in front of the input, if relevant; if we | |
1317 expanded to nothing, no need to create an expansion record or | |
1318 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
|
1319 if (expand_list -> head) |
296 | 1320 { |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1321 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
|
1322 |
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1323 // 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
|
1324 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
|
1325 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
|
1326 |
296 | 1327 /* set up expansion record */ |
1328 e = lw_alloc(sizeof(struct expand_e)); | |
1329 e -> next = pp -> expand_list; | |
1330 pp -> expand_list = e; | |
1331 e -> s = s; | |
1332 } | |
1333 | |
1334 /* 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
|
1335 token_list_destroy(expand_list); |
296 | 1336 for (i = 0; i < nargs; i++) |
1337 { | |
299
856caf91ffaa
Added token list structure and switched some stuff to use it
William Astle <lost@l-w.ca>
parents:
298
diff
changeset
|
1338 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
|
1339 token_list_destroy(exparglist[i]); |
296 | 1340 } |
1341 lw_free(arglist); | |
1342 lw_free(exparglist); | |
1343 | |
1344 return 1; | |
1345 } |