Mercurial > hg > index.cgi
annotate lwcc/preproc.c @ 298:6112c67728ba ccdev
Add stringification and token concatenation
Add support for # and ## in macro expansion by the preprocessor
(stringification and token concatenation). Totally untested.
author | William Astle <lost@l-w.ca> |
---|---|
date | Sat, 14 Sep 2013 22:42:53 -0600 |
parents | 310df72c641d |
children | 856caf91ffaa |
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 | |
22 #include <string.h> | |
23 | |
24 #include <lw_alloc.h> | |
25 #include <lw_string.h> | |
26 | |
27 #include "cpp.h" | |
28 #include "strbuf.h" | |
29 #include "symbol.h" | |
30 #include "token.h" | |
31 | |
32 static int expand_macro(struct preproc_info *, char *); | |
33 static void process_directive(struct preproc_info *); | |
34 static long eval_expr(struct preproc_info *); | |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
35 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
|
36 |
296 | 37 |
38 struct token *preproc_next_processed_token(struct preproc_info *pp) | |
39 { | |
40 struct token *ct; | |
41 | |
42 again: | |
43 ct = preproc_next_token(pp); | |
44 if (ct -> ttype == TOK_EOF) | |
45 return ct; | |
46 if (ct -> ttype == TOK_EOL) | |
47 pp -> ppeolseen = 1; | |
48 | |
49 if (ct -> ttype == TOK_HASH && pp -> eolseen == 1) | |
50 { | |
51 // preprocessor directive | |
52 process_directive(pp); | |
53 } | |
54 // if we're in a false section, don't return the token; keep scanning | |
55 if (pp -> skip_level) | |
56 goto again; | |
57 | |
58 if (ct -> ttype != TOK_WSPACE) | |
59 pp -> ppeolseen = 0; | |
60 | |
61 if (ct -> ttype == TOK_IDENT) | |
62 { | |
63 // possible macro expansion | |
64 if (expand_macro(pp, ct -> strval)) | |
65 goto again; | |
66 } | |
67 | |
68 return ct; | |
69 } | |
70 | |
71 static struct token *preproc_next_processed_token_nws(struct preproc_info *pp) | |
72 { | |
73 struct token *t; | |
74 | |
75 do | |
76 { | |
77 t = preproc_next_processed_token(pp); | |
78 } while (t -> ttype == TOK_WSPACE); | |
79 return t; | |
80 } | |
81 | |
82 static struct token *preproc_next_token_nws(struct preproc_info *pp) | |
83 { | |
84 struct token *t; | |
85 | |
86 do | |
87 { | |
88 t = preproc_next_token(pp); | |
89 } while (t -> ttype == TOK_WSPACE); | |
90 return t; | |
91 } | |
92 | |
93 static void skip_eol(struct preproc_info *pp) | |
94 { | |
95 struct token *t; | |
96 | |
97 if (pp -> curtok && pp -> curtok -> ttype == TOK_EOL) | |
98 return; | |
99 do | |
100 { | |
101 t = preproc_next_token(pp); | |
102 } while (t -> ttype != TOK_EOL); | |
103 } | |
104 | |
105 static void check_eol(struct preproc_info *pp) | |
106 { | |
107 struct token *t; | |
108 | |
109 t = preproc_next_token(pp); | |
110 if (t -> ttype != TOK_EOL) | |
111 preproc_throw_warning(pp, "Extra text after preprocessor directive"); | |
112 skip_eol(pp); | |
113 } | |
114 | |
115 static void dir_ifdef(struct preproc_info *pp) | |
116 { | |
117 struct token *ct; | |
118 | |
119 if (pp -> skip_level) | |
120 { | |
121 pp -> skip_level++; | |
122 skip_eol(pp); | |
123 return; | |
124 } | |
125 | |
126 do | |
127 { | |
128 ct = preproc_next_token(pp); | |
129 } while (ct -> ttype == TOK_WSPACE); | |
130 | |
131 if (ct -> ttype != TOK_IDENT) | |
132 { | |
133 preproc_throw_error(pp, "Bad #ifdef"); | |
134 skip_eol(pp); | |
135 } | |
136 | |
137 if (symtab_find(pp, ct -> strval) == NULL) | |
138 { | |
139 pp -> skip_level++; | |
140 } | |
141 else | |
142 { | |
143 pp -> found_level++; | |
144 } | |
145 check_eol(pp); | |
146 } | |
147 | |
148 static void dir_ifndef(struct preproc_info *pp) | |
149 { | |
150 struct token *ct; | |
151 | |
152 if (pp -> skip_level) | |
153 { | |
154 pp -> skip_level++; | |
155 skip_eol(pp); | |
156 return; | |
157 } | |
158 | |
159 do | |
160 { | |
161 ct = preproc_next_token(pp); | |
162 } while (ct -> ttype == TOK_WSPACE); | |
163 | |
164 if (ct -> ttype != TOK_IDENT) | |
165 { | |
166 preproc_throw_error(pp, "Bad #ifdef"); | |
167 skip_eol(pp); | |
168 } | |
169 | |
170 if (symtab_find(pp, ct -> strval) != NULL) | |
171 { | |
172 pp -> skip_level++; | |
173 } | |
174 else | |
175 { | |
176 pp -> found_level++; | |
177 } | |
178 check_eol(pp); | |
179 } | |
180 | |
181 static void dir_if(struct preproc_info *pp) | |
182 { | |
183 if (pp -> skip_level || !eval_expr(pp)) | |
184 pp -> skip_level++; | |
185 else | |
186 pp -> found_level++; | |
187 } | |
188 | |
189 static void dir_elif(struct preproc_info *pp) | |
190 { | |
191 if (pp -> skip_level == 0) | |
192 pp -> else_skip_level = pp -> found_level; | |
193 if (pp -> skip_level) | |
194 { | |
195 if (pp -> else_skip_level > pp -> found_level) | |
196 ; | |
197 else if (--(pp -> skip_level) != 0) | |
198 pp -> skip_level++; | |
199 else if (eval_expr(pp)) | |
200 pp -> found_level++; | |
201 else | |
202 pp -> skip_level++; | |
203 } | |
204 else if (pp -> found_level) | |
205 { | |
206 pp -> skip_level++; | |
207 pp -> found_level--; | |
208 } | |
209 else | |
210 preproc_throw_error(pp, "#elif in non-conditional section"); | |
211 } | |
212 | |
213 static void dir_else(struct preproc_info *pp) | |
214 { | |
215 if (pp -> skip_level) | |
216 { | |
217 if (pp -> else_skip_level > pp -> found_level) | |
218 ; | |
219 else if (--(pp -> skip_level) != 0) | |
220 pp -> skip_level++; | |
221 else | |
222 pp -> found_level++; | |
223 } | |
224 else if (pp -> found_level) | |
225 { | |
226 pp -> skip_level++; | |
227 pp -> found_level--; | |
228 } | |
229 else | |
230 { | |
231 preproc_throw_error(pp, "#else in non-conditional section"); | |
232 } | |
233 if (pp -> else_level == pp -> found_level + pp -> skip_level) | |
234 { | |
235 preproc_throw_error(pp, "Too many #else"); | |
236 } | |
237 pp -> else_level = pp -> found_level + pp -> skip_level; | |
238 check_eol(pp); | |
239 } | |
240 | |
241 static void dir_endif(struct preproc_info *pp) | |
242 { | |
243 if (pp -> skip_level) | |
244 pp -> skip_level--; | |
245 else if (pp -> found_level) | |
246 pp -> found_level--; | |
247 else | |
248 preproc_throw_error(pp, "#endif in non-conditional section"); | |
249 if (pp -> skip_level == 0) | |
250 pp -> else_skip_level = 0; | |
251 pp -> else_level = 0; | |
252 check_eol(pp); | |
253 } | |
254 | |
255 static void dir_define(struct preproc_info *pp) | |
256 { | |
257 struct token *tl = NULL; | |
258 struct token *ttl; | |
259 struct token *ct; | |
260 int nargs = -1; | |
261 int vargs = 0; | |
262 char *mname = NULL; | |
263 | |
264 char **arglist = NULL; | |
265 | |
266 if (pp -> skip_level) | |
267 { | |
268 skip_eol(pp); | |
269 return; | |
270 } | |
271 | |
272 ct = preproc_next_token_nws(pp); | |
273 if (ct -> ttype != TOK_IDENT) | |
274 goto baddefine; | |
275 | |
276 mname = lw_strdup(ct -> strval); | |
277 ct = preproc_next_token(pp); | |
278 | |
279 if (ct -> ttype == TOK_WSPACE) | |
280 { | |
281 /* object like macro */ | |
282 } | |
283 else if (ct -> ttype == TOK_EOL) | |
284 { | |
285 /* object like macro - empty value */ | |
286 goto out; | |
287 } | |
288 else if (ct -> ttype == TOK_OPAREN) | |
289 { | |
290 /* function like macro - parse args */ | |
291 nargs = 0; | |
292 vargs = 0; | |
293 for (;;) | |
294 { | |
295 ct = preproc_next_token_nws(pp); | |
296 if (ct -> ttype == TOK_EOL) | |
297 { | |
298 goto baddefine; | |
299 } | |
300 if (ct -> ttype == TOK_CPAREN) | |
301 break; | |
302 | |
303 if (ct -> ttype == TOK_IDENT) | |
304 { | |
305 /* parameter name */ | |
306 nargs++; | |
307 /* record argument name */ | |
308 arglist = lw_realloc(arglist, sizeof(char *) * nargs); | |
309 arglist[nargs - 1] = lw_strdup(ct -> strval); | |
310 | |
311 /* check for end of args or comma */ | |
312 ct = preproc_next_token_nws(pp); | |
313 if (ct -> ttype == TOK_CPAREN) | |
314 break; | |
315 else if (ct -> ttype == TOK_COMMA) | |
316 continue; | |
317 else | |
318 goto baddefine; | |
319 } | |
320 else if (ct -> ttype == TOK_ELLIPSIS) | |
321 { | |
322 /* variadic macro */ | |
323 vargs = 1; | |
324 ct = preproc_next_token_nws(pp); | |
325 if (ct -> ttype != TOK_CPAREN) | |
326 goto baddefine; | |
327 break; | |
328 } | |
329 else | |
330 goto baddefine; | |
331 } | |
332 } | |
333 else | |
334 { | |
335 baddefine: | |
336 preproc_throw_error(pp, "bad #define"); | |
337 baddefine2: | |
338 skip_eol(pp); | |
339 lw_free(mname); | |
340 while (nargs > 0) | |
341 lw_free(arglist[--nargs]); | |
342 lw_free(arglist); | |
343 return; | |
344 } | |
345 | |
346 for (;;) | |
347 { | |
348 ct = preproc_next_token(pp); | |
349 if (ct -> ttype == TOK_EOL) | |
350 break; | |
351 if (!tl) | |
352 tl = ct; | |
353 else | |
354 ttl -> next = ct; | |
355 ttl = ct; | |
356 pp -> curtok = NULL; // tell *_next_token* not to clobber token | |
357 } | |
358 out: | |
359 if (strcmp(mname, "defined") == 0) | |
360 { | |
361 preproc_throw_warning(pp, "attempt to define 'defined' as a macro not allowed"); | |
362 goto baddefine2; | |
363 } | |
364 else if (symtab_find(pp, mname) != NULL) | |
365 { | |
366 /* need to do a token compare between the old value and the new value | |
367 to decide whether to complain */ | |
368 preproc_throw_warning(pp, "%s previous defined", mname); | |
369 symtab_undef(pp, mname); | |
370 } | |
371 symtab_define(pp, mname, tl, nargs, arglist, vargs); | |
372 lw_free(mname); | |
373 while (nargs > 0) | |
374 lw_free(arglist[--nargs]); | |
375 lw_free(arglist); | |
376 /* no need to check for EOL here */ | |
377 } | |
378 | |
379 static void dir_undef(struct preproc_info *pp) | |
380 { | |
381 struct token *ct; | |
382 if (pp -> skip_level) | |
383 { | |
384 skip_eol(pp); | |
385 return; | |
386 } | |
387 | |
388 do | |
389 { | |
390 ct = preproc_next_token(pp); | |
391 } while (ct -> ttype == TOK_WSPACE); | |
392 | |
393 if (ct -> ttype != TOK_IDENT) | |
394 { | |
395 preproc_throw_error(pp, "Bad #undef"); | |
396 skip_eol(pp); | |
397 } | |
398 | |
399 symtab_undef(pp, ct -> strval); | |
400 check_eol(pp); | |
401 } | |
402 | |
403 char *streol(struct preproc_info *pp) | |
404 { | |
405 struct strbuf *s; | |
406 struct token *ct; | |
407 int i; | |
408 | |
409 s = strbuf_new(); | |
410 do | |
411 { | |
412 ct = preproc_next_token(pp); | |
413 } while (ct -> ttype == TOK_WSPACE); | |
414 | |
415 while (ct -> ttype != TOK_EOL) | |
416 { | |
417 for (i = 0; ct -> strval[i]; i++) | |
418 strbuf_add(s, ct -> strval[i]); | |
419 ct = preproc_next_token(pp); | |
420 } | |
421 return strbuf_end(s); | |
422 } | |
423 | |
424 static void dir_error(struct preproc_info *pp) | |
425 { | |
426 char *s; | |
427 | |
428 if (pp -> skip_level) | |
429 { | |
430 skip_eol(pp); | |
431 return; | |
432 } | |
433 | |
434 s = streol(pp); | |
435 preproc_throw_error(pp, "%s", s); | |
436 lw_free(s); | |
437 } | |
438 | |
439 static void dir_warning(struct preproc_info *pp) | |
440 { | |
441 char *s; | |
442 | |
443 if (pp -> skip_level) | |
444 { | |
445 skip_eol(pp); | |
446 return; | |
447 } | |
448 | |
449 s = streol(pp); | |
450 preproc_throw_warning(pp, "%s", s); | |
451 lw_free(s); | |
452 } | |
453 | |
454 static void dir_include(struct preproc_info *pp) | |
455 { | |
456 } | |
457 | |
458 static void dir_line(struct preproc_info *pp) | |
459 { | |
460 } | |
461 | |
462 static void dir_pragma(struct preproc_info *pp) | |
463 { | |
464 if (pp -> skip_level) | |
465 { | |
466 skip_eol(pp); | |
467 return; | |
468 } | |
469 | |
470 preproc_throw_warning(pp, "Unsupported #pragma"); | |
471 skip_eol(pp); | |
472 } | |
473 | |
474 struct { char *name; void (*fn)(struct preproc_info *); } dirlist[] = | |
475 { | |
476 { "ifdef", dir_ifdef }, | |
477 { "ifndef", dir_ifndef }, | |
478 { "if", dir_if }, | |
479 { "else", dir_else }, | |
480 { "elif", dir_elif }, | |
481 { "endif", dir_endif }, | |
482 { "define", dir_define }, | |
483 { "undef", dir_undef }, | |
484 { "include", dir_include }, | |
485 { "error", dir_error }, | |
486 { "warning", dir_warning }, | |
487 { "line", dir_line }, | |
488 { "pragma", dir_pragma }, | |
489 { NULL, NULL } | |
490 }; | |
491 | |
492 static void process_directive(struct preproc_info *pp) | |
493 { | |
494 struct token *ct; | |
495 int i; | |
496 | |
497 do | |
498 { | |
499 ct = preproc_next_token(pp); | |
500 } while (ct -> ttype == TOK_WSPACE); | |
501 | |
502 // NULL directive | |
503 if (ct -> ttype == TOK_EOL) | |
504 return; | |
505 | |
506 if (ct -> ttype != TOK_IDENT) | |
507 goto baddir; | |
508 | |
509 for (i = 0; dirlist[i].name; i++) | |
510 { | |
511 if (strcmp(dirlist[i].name, ct -> strval) == 0) | |
512 { | |
513 (*(dirlist[i].fn))(pp); | |
514 return; | |
515 } | |
516 } | |
517 baddir: | |
518 preproc_throw_error(pp, "Bad preprocessor directive"); | |
519 while (ct -> ttype != TOK_EOL) | |
520 ct = preproc_next_token(pp); | |
521 return; | |
522 } | |
523 | |
524 /* | |
525 Evaluate a preprocessor expression | |
526 */ | |
527 | |
528 /* same as skip_eol() but the EOL token is not consumed */ | |
529 static void skip_eoe(struct preproc_info *pp) | |
530 { | |
531 skip_eol(pp); | |
532 preproc_unget_token(pp, pp -> curtok); | |
533 } | |
534 | |
535 static long eval_expr_real(struct preproc_info *, int); | |
536 static long preproc_numval(struct token *); | |
537 | |
538 static long eval_term_real(struct preproc_info *pp) | |
539 { | |
540 long tval = 0; | |
541 struct token *ct; | |
542 | |
543 eval_next: | |
544 ct = preproc_next_processed_token_nws(pp); | |
545 if (ct -> ttype == TOK_EOL) | |
546 { | |
547 preproc_throw_error(pp, "Bad expression"); | |
548 return 0; | |
549 } | |
550 | |
551 switch (ct -> ttype) | |
552 { | |
553 case TOK_OPAREN: | |
554 tval = eval_expr_real(pp, 0); | |
555 ct = preproc_next_processed_token_nws(pp); | |
556 if (ct -> ttype != ')') | |
557 { | |
558 preproc_throw_error(pp, "Unbalanced () in expression"); | |
559 skip_eoe(pp); | |
560 return 0; | |
561 } | |
562 return tval; | |
563 | |
564 case TOK_ADD: // unary + | |
565 goto eval_next; | |
566 | |
567 case TOK_SUB: // unary - | |
568 tval = eval_expr_real(pp, 200); | |
569 return -tval; | |
570 | |
571 /* NOTE: we should only get "TOK_IDENT" from an undefined macro */ | |
572 case TOK_IDENT: // some sort of function, symbol, etc. | |
573 if (strcmp(ct -> strval, "defined")) | |
574 { | |
575 /* the defined operator */ | |
576 /* any number in the "defined" bit will be | |
577 treated as a defined symbol, even zero */ | |
578 ct = preproc_next_token_nws(pp); | |
579 if (ct -> ttype == TOK_OPAREN) | |
580 { | |
581 ct = preproc_next_token_nws(pp); | |
582 if (ct -> ttype != TOK_IDENT) | |
583 { | |
584 preproc_throw_error(pp, "Bad expression"); | |
585 skip_eoe(pp); | |
586 return 0; | |
587 } | |
588 if (symtab_find(pp, ct -> strval) == NULL) | |
589 tval = 0; | |
590 else | |
591 tval = 1; | |
592 ct = preproc_next_token_nws(pp); | |
593 if (ct -> ttype != TOK_CPAREN) | |
594 { | |
595 preproc_throw_error(pp, "Bad expression"); | |
596 skip_eoe(pp); | |
597 return 0; | |
598 } | |
599 return tval; | |
600 } | |
601 else if (ct -> ttype == TOK_IDENT) | |
602 { | |
603 return (symtab_find(pp, ct -> strval) != NULL) ? 1 : 0; | |
604 } | |
605 preproc_throw_error(pp, "Bad expression"); | |
606 skip_eoe(pp); | |
607 return 0; | |
608 } | |
609 /* unknown identifier - it's zero */ | |
610 return 0; | |
611 | |
612 /* numbers */ | |
613 case TOK_NUMBER: | |
614 return preproc_numval(ct); | |
615 | |
616 default: | |
617 preproc_throw_error(pp, "Bad expression"); | |
618 skip_eoe(pp); | |
619 return 0; | |
620 } | |
621 return 0; | |
622 } | |
623 | |
624 static long eval_expr_real(struct preproc_info *pp, int p) | |
625 { | |
626 static const struct operinfo | |
627 { | |
628 int tok; | |
629 int prec; | |
630 } operators[] = | |
631 { | |
632 { TOK_ADD, 100 }, | |
633 { TOK_SUB, 100 }, | |
634 { TOK_STAR, 150 }, | |
635 { TOK_DIV, 150 }, | |
636 { TOK_MOD, 150 }, | |
637 { TOK_LT, 75 }, | |
638 { TOK_LE, 75 }, | |
639 { TOK_GT, 75 }, | |
640 { TOK_GE, 75 }, | |
641 { TOK_EQ, 70 }, | |
642 { TOK_NE, 70 }, | |
643 { TOK_BAND, 30 }, | |
644 { TOK_BOR, 25 }, | |
645 { TOK_NONE, 0 } | |
646 }; | |
647 | |
648 int op; | |
649 long term1, term2, term3; | |
650 struct token *ct; | |
651 | |
652 term1 = eval_term_real(pp); | |
653 eval_next: | |
654 ct = preproc_next_processed_token_nws(pp); | |
655 for (op = 0; operators[op].tok != TOK_NONE; op++) | |
656 { | |
657 if (operators[op].tok == ct -> ttype) | |
658 break; | |
659 } | |
660 /* if it isn't a recognized operator, assume end of expression */ | |
661 if (operators[op].tok == TOK_NONE) | |
662 { | |
663 preproc_unget_token(pp, ct); | |
664 return term1; | |
665 } | |
666 | |
667 /* if new operation is not higher than the current precedence, let the previous op finish */ | |
668 if (operators[op].prec <= p) | |
669 return term1; | |
670 | |
671 /* get the second term */ | |
672 term2 = eval_expr_real(pp, operators[op].prec); | |
673 | |
674 switch (operators[op].tok) | |
675 { | |
676 case TOK_ADD: | |
677 term3 = term1 + term2; | |
678 break; | |
679 | |
680 case TOK_SUB: | |
681 term3 = term1 - term2; | |
682 break; | |
683 | |
684 case TOK_STAR: | |
685 term3 = term1 * term2; | |
686 break; | |
687 | |
688 case TOK_DIV: | |
689 if (!term2) | |
690 { | |
691 preproc_throw_warning(pp, "Division by zero"); | |
692 term3 = 0; | |
693 break; | |
694 } | |
695 term3 = term1 / term2; | |
696 break; | |
697 | |
698 case TOK_MOD: | |
699 if (!term2) | |
700 { | |
701 preproc_throw_warning(pp, "Division by zero"); | |
702 term3 = 0; | |
703 break; | |
704 } | |
705 term3 = term1 % term2; | |
706 break; | |
707 | |
708 case TOK_BAND: | |
709 term3 = (term1 && term2); | |
710 break; | |
711 | |
712 case TOK_BOR: | |
713 term3 = (term1 || term2); | |
714 break; | |
715 | |
716 case TOK_EQ: | |
717 term3 = (term1 == term2); | |
718 break; | |
719 | |
720 case TOK_NE: | |
721 term3 = (term1 != term2); | |
722 break; | |
723 | |
724 case TOK_GT: | |
725 term3 = (term1 > term2); | |
726 break; | |
727 | |
728 case TOK_GE: | |
729 term3 = (term1 >= term2); | |
730 break; | |
731 | |
732 case TOK_LT: | |
733 term3 = (term1 < term2); | |
734 break; | |
735 | |
736 case TOK_LE: | |
737 term3 = (term1 <= term2); | |
738 break; | |
739 | |
740 default: | |
741 term3 = 0; | |
742 break; | |
743 } | |
744 term1 = term3; | |
745 goto eval_next; | |
746 } | |
747 | |
748 static long eval_expr(struct preproc_info *pp) | |
749 { | |
750 long rv; | |
751 | |
752 rv = eval_expr_real(pp, 0); | |
753 if (pp -> curtok -> ttype != TOK_EOL) | |
754 { | |
755 preproc_throw_error(pp, "Bad expression"); | |
756 skip_eol(pp); | |
757 } | |
758 return rv; | |
759 } | |
760 | |
761 /* convert a numeric string to a number */ | |
762 long preproc_numval(struct token *t) | |
763 { | |
764 return 0; | |
765 } | |
766 | |
767 /* | |
768 Below here is the logic for expanding a macro | |
769 */ | |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
770 static char *stringify(struct token *tl) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
771 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
772 struct strbuf *s; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
773 int ws = 0; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
774 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
775 s = strbuf_new(); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
776 strbuf_add(s, '"'); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
777 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
778 while (tl && tl -> ttype == TOK_WSPACE) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
779 tl = tl -> next; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
780 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
781 for (; tl; tl = tl -> next) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
782 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
783 if (tl -> ttype == TOK_WSPACE) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
784 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
785 ws = 1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
786 continue; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
787 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
788 if (ws) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
789 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
790 strbuf_add(s, ' '); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
791 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
792 for (ws = 0; tl -> strval[ws]; ws++) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
793 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
794 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
|
795 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
796 if (tl -> strval[ws] == '"' || tl -> strval[ws] == '\\') |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
797 strbuf_add(s, '\\'); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
798 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
799 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
800 ws = 0; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
801 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
802 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
803 strbuf_add(s, '"'); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
804 return strbuf_end(s); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
805 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
806 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
807 /* return list to tokens as a result of ## expansion */ |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
808 static struct token *paste_tokens(struct preproc_info *pp, struct symtab_e *s, struct token **arglist, struct token *t1, struct token *t2) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
809 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
810 struct token *rl = NULL, *rlt; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
811 struct token *s1, *s2; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
812 struct token *ws; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
813 int i; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
814 char *tstr; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
815 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
816 if (t1 -> ttype == TOK_IDENT) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
817 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
818 if (strcmp(t1 -> strval, "__VA_ARGS__") == 0) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
819 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
820 i = s -> nargs; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
821 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
822 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
823 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
824 for (i = 0; i < s -> nargs; i++) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
825 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
826 if (strcmp(s -> params[i], t1 -> strval) == 0) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
827 break; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
828 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
829 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
830 if ((i == s -> nargs) && !(s -> vargs)) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
831 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
832 s1 = token_dup(t1); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
833 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
834 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
835 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
836 /* find last non-whitespace token */ |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
837 ws = NULL; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
838 for (t1 = s -> tl; t1; t1 = t1 -> next) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
839 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
840 if (t1 -> ttype != TOK_WSPACE) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
841 ws = t1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
842 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
843 if (!ws) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
844 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
845 s1 = NULL; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
846 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
847 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
848 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
849 if (ws != s -> tl) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
850 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
851 /* output extra tokens */ |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
852 for (t1 = s -> tl; t1 -> next != ws; t1 = t1 -> next) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
853 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
854 if (!rl) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
855 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
856 rl = token_dup(t1); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
857 rlt = rl; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
858 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
859 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
860 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
861 rlt -> next = token_dup(t1); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
862 rlt = rlt -> next; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
863 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
864 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
865 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
866 s1 = token_dup(ws); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
867 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
868 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
869 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
870 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
871 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
872 s1 = token_dup(t1); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
873 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
874 if (t2 -> ttype == TOK_IDENT) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
875 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
876 if (strcmp(t1 -> strval, "__VA_ARGS__") == 0) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
877 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
878 i = s -> nargs; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
879 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
880 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
881 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
882 for (i = 0; i < s -> nargs; i++) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
883 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
884 if (strcmp(s -> params[i], t1 -> strval) == 0) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
885 break; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
886 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
887 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
888 if ((i == s -> nargs) && !(s -> vargs)) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
889 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
890 s2 = token_dup(t2); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
891 t2 = NULL; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
892 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
893 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
894 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
895 /* find last non-whitespace token */ |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
896 ws = NULL; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
897 for (t2 = s -> tl; t2; t2 = t2 -> next) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
898 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
899 if (t2 -> ttype != TOK_WSPACE) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
900 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
901 ws = t2; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
902 t2 = t2 -> next; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
903 break; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
904 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
905 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
906 if (!ws) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
907 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
908 s2 = NULL; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
909 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
910 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
911 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
912 s2 = token_dup(ws); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
913 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
914 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
915 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
916 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
917 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
918 s2 = token_dup(t2); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
919 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
920 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
921 /* here, s1 is NULL if no left operand or a duplicated token for the actual left operand */ |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
922 /* here, s2 is NULL if no right operand or a duplicated token for the actual right operand */ |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
923 /* here, t2 points to a possibly empty list of extra tokens to output after the concatenated tokens */ |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
924 /* here, rl,rlt is a possibly non-empty list of tokens preceding the concatenation */ |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
925 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
926 /* tokens combine if the combination exactly matches "combinelist", in which case the string values are |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
927 concatenated and the new token type is used to create a new token. If the tokens do not combine, |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
928 s1 and s2 are returned in sequence. */ |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
929 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
930 if (!s1 && s2) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
931 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
932 if (!rl) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
933 rl = s2; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
934 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
935 rlt -> next = s2; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
936 rlt = s2; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
937 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
938 else if (s1 && !s2) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
939 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
940 if (!rl) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
941 rl = s1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
942 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
943 rlt -> next = s1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
944 rlt = s1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
945 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
946 else if (s1 && s2) |
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 tstr = lw_alloc(strlen(s1 -> strval) + strlen(s2 -> strval) + 1); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
949 strcpy(tstr, s1 -> strval); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
950 strcat(tstr, s2 -> strval); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
951 /* now try to lex the string */ |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
952 pp -> lexstr = tstr; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
953 pp -> lexstrloc = 0; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
954 t1 = preproc_lex_next_token(pp); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
955 if (pp -> lexstr[pp -> lexstrloc]) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
956 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
957 // doesn't make a new token - pass through the original two |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
958 if (!rl) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
959 rl = s1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
960 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
961 rlt -> next = s1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
962 s1 -> next = s2; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
963 rlt = s2; |
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 else |
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 // does make a new token |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
968 t1 -> fn = s1 -> fn; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
969 t1 -> column = s1 -> column; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
970 t1 -> lineno = s1 -> lineno; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
971 if (!rl) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
972 rl = t1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
973 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
974 rlt -> next = t1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
975 rlt = t1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
976 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
977 lw_free(tstr); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
978 pp -> lexstr = NULL; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
979 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
980 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
981 /* add in any extra tokens */ |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
982 while (t2) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
983 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
984 if (!rl) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
985 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
986 rl = token_dup(t2); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
987 rlt = rl; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
988 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
989 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
990 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
991 rlt -> next = token_dup(t2); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
992 rlt = rlt -> next; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
993 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
994 t2 = t2 -> next; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
995 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
996 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
997 return rl; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
998 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
999 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1000 |
296 | 1001 static int expand_macro(struct preproc_info *pp, char *mname) |
1002 { | |
1003 struct symtab_e *s; | |
1004 struct token *t, *t2, *t3; | |
1005 struct token **arglist = NULL; | |
1006 int nargs = 0; | |
1007 struct expand_e *e; | |
1008 struct token **exparglist = NULL; | |
1009 int i; | |
297
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1010 int pcount; |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1011 char *tstr; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1012 |
296 | 1013 s = symtab_find(pp, mname); |
1014 if (!s) | |
1015 return 0; | |
1016 | |
1017 for (e = pp -> expand_list; e; e = e -> next) | |
1018 { | |
1019 /* don't expand if we're already expanding the same macro */ | |
1020 if (e -> s == s) | |
1021 return 0; | |
1022 } | |
1023 | |
1024 if (s -> nargs == -1) | |
1025 { | |
1026 /* short circuit NULL expansion */ | |
1027 if (s -> tl == NULL) | |
1028 return 1; | |
1029 | |
1030 goto expandmacro; | |
1031 } | |
1032 | |
1033 // look for opening paren after optional whitespace | |
1034 t2 = NULL; | |
1035 t = NULL; | |
1036 for (;;) | |
1037 { | |
1038 t = preproc_next_token(pp); | |
1039 if (t -> ttype != TOK_WSPACE && t -> ttype != TOK_EOL) | |
1040 break; | |
1041 t -> next = t2; | |
1042 t2 = t2; | |
1043 } | |
1044 if (t -> ttype != TOK_OPAREN) | |
1045 { | |
1046 // not a function-like invocation | |
1047 while (t2) | |
1048 { | |
1049 t = t2 -> next; | |
1050 preproc_unget_token(pp, t2); | |
1051 t2 = t; | |
1052 } | |
1053 return 0; | |
1054 } | |
1055 | |
1056 // parse parameters here | |
1057 t = preproc_next_token_nws(pp); | |
1058 nargs = 1; | |
1059 arglist = lw_alloc(sizeof(struct token *)); | |
1060 arglist[0] = NULL; | |
1061 t2 = NULL; | |
1062 | |
1063 while (t -> ttype != TOK_CPAREN) | |
1064 { | |
297
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1065 pcount = 0; |
296 | 1066 if (t -> ttype == TOK_EOF) |
1067 { | |
1068 preproc_throw_error(pp, "Unexpected EOF in macro call"); | |
1069 break; | |
1070 } | |
1071 if (t -> ttype == TOK_EOL) | |
1072 continue; | |
297
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1073 if (t -> ttype == TOK_OPAREN) |
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1074 pcount++; |
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1075 else if (t -> ttype == TOK_CPAREN && pcount) |
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1076 pcount--; |
310df72c641d
Handle () surrounding macro args on invocation
William Astle <lost@l-w.ca>
parents:
296
diff
changeset
|
1077 if (t -> ttype == TOK_COMMA && pcount == 0) |
296 | 1078 { |
1079 if (!(s -> vargs) || (nargs > s -> nargs)) | |
1080 { | |
1081 nargs++; | |
1082 arglist = lw_realloc(arglist, sizeof(struct token *) * nargs); | |
1083 arglist[nargs - 1] = NULL; | |
1084 t2 = NULL; | |
1085 continue; | |
1086 } | |
1087 } | |
1088 if (t2) | |
1089 { | |
1090 t2 -> next = token_dup(t); | |
1091 t2 = t2 -> next; | |
1092 } | |
1093 else | |
1094 { | |
1095 t2 = token_dup(t); | |
1096 arglist[nargs - 1] = t2; | |
1097 } | |
1098 } | |
1099 | |
1100 if (s -> vargs) | |
1101 { | |
1102 if (nargs <= s -> nargs) | |
1103 { | |
1104 preproc_throw_error(pp, "Wrong number of arguments (%d) for variadic macro %s which takes %d arguments", nargs, mname, s -> nargs); | |
1105 } | |
1106 } | |
1107 else | |
1108 { | |
1109 if (s -> nargs != nargs && !(s -> nargs == 0 && nargs == 1 && arglist[nargs - 1])) | |
1110 { | |
1111 preproc_throw_error(pp, "Wrong number of arguments (%d) for macro %s which takes %d arguments", nargs, mname, s -> nargs); | |
1112 } | |
1113 } | |
1114 | |
1115 /* now calculate the pre-expansions of the arguments */ | |
1116 exparglist = lw_alloc(nargs); | |
1117 for (i = 0; i < nargs; i++) | |
1118 { | |
1119 t2 = NULL; | |
1120 exparglist[i] = NULL; | |
1121 // NOTE: do nothing if empty argument | |
1122 if (arglist[i] == NULL) | |
1123 continue; | |
1124 pp -> sourcelist = arglist[i]; | |
1125 for (;;) | |
1126 { | |
1127 t = preproc_next_processed_token(pp); | |
1128 if (t -> ttype == TOK_EOF) | |
1129 break; | |
1130 if (t2) | |
1131 { | |
1132 t2 -> next = token_dup(t); | |
1133 t2 = t2 -> next; | |
1134 } | |
1135 else | |
1136 { | |
1137 t2 = token_dup(t); | |
1138 exparglist[i] = t2; | |
1139 } | |
1140 } | |
1141 } | |
1142 | |
1143 expandmacro: | |
1144 t2 = NULL; | |
1145 t3 = NULL; | |
1146 | |
1147 for (t = s -> tl; t; t = t -> next) | |
1148 { | |
298
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1149 again: |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1150 if (t -> ttype != TOK_WSPACE && t -> next) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1151 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1152 struct token *ct1, *ct2; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1153 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1154 for (ct1 = t -> next; ct1 && ct1 -> ttype == TOK_WSPACE; ct1 = ct1 -> next) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1155 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1156 if (ct1 -> ttype == TOK_DBLHASH) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1157 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1158 // possible concatenation here |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1159 for (ct2 = ct1 -> next; ct2 && ct2 -> ttype == TOK_WSPACE; ct2 = ct2 -> next) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1160 /* do nothing */ ; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1161 if (ct2) |
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 // we have concatenation here so we paste str1 and str2 together and see what we get |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1164 // if we get NULL, the past didn't make a valid token |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1165 ct1 = paste_tokens(pp, s, arglist, t, ct2); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1166 if (ct1) |
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 if (t2) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1169 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1170 t2 -> next = ct1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1171 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1172 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1173 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1174 t3 = ct1; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1175 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1176 for (t2 = ct1; t2 -> next; t2 = t2 -> next) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1177 /* do nothing */ ; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1178 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1179 /* because of the level of control structures, move to next token and restart loop */ |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1180 t = ct2 -> next; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1181 goto again; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1182 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1183 goto nopaste; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1184 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1185 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1186 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1187 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1188 |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1189 nopaste: |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1190 if (t -> ttype == TOK_HASH) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1191 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1192 if (t -> next && t -> next -> ttype == TOK_IDENT) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1193 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1194 if (strcmp(t -> next -> strval, "__VA_ARGS__") == 0) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1195 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1196 i = nargs; |
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 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1199 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1200 for (i = 0; i < nargs; i++) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1201 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1202 if (strcmp(t -> next -> strval, s -> params[i]) == 0) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1203 break; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1204 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1205 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1206 if (!((i == s -> nargs) && !(s -> vargs))) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1207 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1208 // we have a stringification here |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1209 t = t -> next; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1210 tstr = stringify(arglist[i]); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1211 if (t2) |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1212 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1213 t2 = token_create(TOK_STRING, tstr, t -> lineno, t -> column, t -> fn); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1214 t2 = t2 -> next; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1215 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1216 else |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1217 { |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1218 t3 = token_create(TOK_STRING, tstr, t -> lineno, t -> column, t -> fn); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1219 t2 = t3; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1220 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1221 lw_free(tstr); |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1222 continue; |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1223 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1224 } |
6112c67728ba
Add stringification and token concatenation
William Astle <lost@l-w.ca>
parents:
297
diff
changeset
|
1225 } |
296 | 1226 if (t -> ttype == TOK_IDENT) |
1227 { | |
1228 /* identifiers might need expansion to arguments */ | |
1229 if (strcmp(t -> strval, "__VA_ARGS__") == 0) | |
1230 { | |
1231 i = s -> nargs; | |
1232 } | |
1233 else | |
1234 { | |
1235 for (i = 0; i < nargs; i++) | |
1236 { | |
1237 if (strcmp(t -> strval, s -> params[i]) == 0) | |
1238 break; | |
1239 } | |
1240 } | |
1241 if ((i == s -> nargs) && !(s -> vargs)) | |
1242 { | |
1243 struct token *te; | |
1244 // expand argument | |
1245 for (te = exparglist[i]; te; te = te -> next) | |
1246 { | |
1247 if (t2) | |
1248 { | |
1249 t2 -> next = token_dup(te); | |
1250 t2 = t2 -> next; | |
1251 } | |
1252 else | |
1253 { | |
1254 t3 = token_dup(te); | |
1255 t2 = t2; | |
1256 } | |
1257 } | |
1258 continue; | |
1259 } | |
1260 } | |
1261 if (t2) | |
1262 { | |
1263 t2 -> next = token_dup(t); | |
1264 t2 = t2 -> next; | |
1265 } | |
1266 else | |
1267 { | |
1268 t3 = token_dup(t); | |
1269 t2 = t3; | |
1270 } | |
1271 } | |
1272 | |
1273 /* put the new expansion in front of the input, if relevant; if we | |
1274 expanded to nothing, no need to create an expansion record or | |
1275 put anything into the input queue */ | |
1276 if (t3) | |
1277 { | |
1278 t2 -> next = token_create(TOK_ENDEXPAND, "", -1, -1, ""); | |
1279 t2 -> next -> next = pp -> tokqueue; | |
1280 pp -> tokqueue = t3; | |
1281 | |
1282 /* set up expansion record */ | |
1283 e = lw_alloc(sizeof(struct expand_e)); | |
1284 e -> next = pp -> expand_list; | |
1285 pp -> expand_list = e; | |
1286 e -> s = s; | |
1287 } | |
1288 | |
1289 /* now clean up */ | |
1290 for (i = 0; i < nargs; i++) | |
1291 { | |
1292 lw_free(arglist[i]); | |
1293 lw_free(exparglist[i]); | |
1294 } | |
1295 lw_free(arglist); | |
1296 lw_free(exparglist); | |
1297 | |
1298 return 1; | |
1299 } |