travis: update
[m6w6/ext-psi] / src / cpp_tokiter.c
1 /*******************************************************************************
2 Copyright (c) 2017, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #else
29 # include "php_config.h"
30 #endif
31
32 #include "cpp.h"
33 #include "parser.h"
34
35 void psi_cpp_tokiter_dump(struct psi_dump *dump, struct psi_cpp *cpp);
36 void psi_cpp_tokiter_dump(struct psi_dump *dump, struct psi_cpp *cpp)
37 {
38 size_t i = cpp->index;
39 struct psi_token *T;
40
41 if (i > 40) {
42 i -= 40;
43 } else {
44 i = 0;
45 }
46 while (psi_plist_get(cpp->tokens.iter, i, &T)) {
47 PSI_DUMP(dump, "PSI: CPP tokens %5zu %c ", i, cpp->index == i ? '*' : ' ');
48 psi_token_dump(dump, T);
49 if (i >= cpp->index + 40) {
50 PSI_DUMP(dump, "PSI: CPP tokens .....\n");
51 break;
52 }
53 ++i;
54 }
55 }
56
57 void psi_cpp_tokiter_reset(struct psi_cpp *cpp)
58 {
59 cpp->index = 0;
60 cpp->expanded = 0;
61 cpp->skip = 0;
62 cpp->seen = 0;
63 cpp->level = 0;
64 cpp->do_cpp = false;
65
66 if (cpp->tokens.next) {
67 psi_plist_free(cpp->tokens.iter);
68 cpp->tokens.iter = cpp->tokens.next;
69 }
70 cpp->tokens.next = psi_plist_init((psi_plist_dtor) psi_token_free);
71 if (cpp->tokens.exec) {
72 assert(!psi_plist_count(cpp->tokens.exec));
73 psi_plist_clean(cpp->tokens.exec);
74 } else {
75 cpp->tokens.exec = psi_plist_init((psi_plist_dtor) psi_token_free);
76 }
77 #if PSI_CPP_DEBUG
78 PSI_DEBUG_PRINT(cpp->parser,
79 "PSI: CPP reset -> iter.count=%zu, next.count=%zu, exec.count=%zu\n",
80 psi_plist_count(cpp->tokens.iter),
81 psi_plist_count(cpp->tokens.next),
82 psi_plist_count(cpp->tokens.exec));
83 # if PSI_CPP_DEBUG > 1
84 PSI_DEBUG_DUMP(cpp->parser, psi_cpp_tokiter_dump, cpp);
85 # endif
86 #endif
87 }
88
89 bool psi_cpp_tokiter_seek(struct psi_cpp *cpp, size_t index)
90 {
91 if (index < psi_plist_count(cpp->tokens.iter)) {
92 cpp->index = index;
93 return true;
94 }
95 return false;
96 }
97
98 struct psi_token *psi_cpp_tokiter_current(struct psi_cpp *cpp)
99 {
100 struct psi_token *current = NULL;
101 bool found = psi_plist_get(cpp->tokens.iter, cpp->index, &current);
102
103 assert(found);
104
105 return current;
106 }
107
108 size_t psi_cpp_tokiter_index(struct psi_cpp *cpp)
109 {
110 return cpp->index;
111 }
112
113 bool psi_cpp_tokiter_add_cur(struct psi_cpp *cpp)
114 {
115 struct psi_token *cur = NULL;
116
117 if (psi_plist_get(cpp->tokens.iter, cpp->index, &cur)) {
118 psi_plist_unset(cpp->tokens.iter, cpp->index);
119 if (cpp->do_cpp) {
120 cpp->tokens.exec = psi_plist_add(cpp->tokens.exec, &cur);
121 } else {
122 cpp->tokens.next = psi_plist_add(cpp->tokens.next, &cur);
123 }
124
125 #if PSI_CPP_DEBUG
126 PSI_DEBUG_PRINT(cpp->parser,
127 "PSI: CPP add_cur -> index=%zu, iter.count=%zu, next.count=%zu, exec.count=%zu ",
128 cpp->index, psi_plist_count(cpp->tokens.iter), psi_plist_count(cpp->tokens.next),
129 psi_plist_count(cpp->tokens.exec));
130 PSI_DEBUG_DUMP(cpp->parser, psi_token_dump, cur);
131 #endif
132
133 return true;
134 }
135
136 return false;
137 }
138
139 bool psi_cpp_tokiter_add(struct psi_cpp *cpp, struct psi_token *tok)
140 {
141 if (cpp->do_cpp) {
142 cpp->tokens.exec = psi_plist_add(cpp->tokens.exec, &tok);
143 } else {
144 cpp->tokens.next = psi_plist_add(cpp->tokens.next, &tok);
145 }
146
147 #if PSI_CPP_DEBUG
148 PSI_DEBUG_PRINT(cpp->parser,
149 "PSI: CPP add -> index=%zu, iter.count=%zu, next.count=%zu, exec.count=%zu ",
150 cpp->index, psi_plist_count(cpp->tokens.iter), psi_plist_count(cpp->tokens.next),
151 psi_plist_count(cpp->tokens.exec));
152 PSI_DEBUG_DUMP(cpp->parser, psi_token_dump, tok);
153 #endif
154
155 return true;
156 }
157
158
159 bool psi_cpp_tokiter_add_range(struct psi_cpp *cpp, size_t num_eles, void **eles)
160 {
161 if (!num_eles) {
162 return true;
163 }
164
165 if (cpp->do_cpp) {
166 cpp->tokens.exec = psi_plist_add_r(cpp->tokens.exec, num_eles, eles);
167 } else {
168 cpp->tokens.next = psi_plist_add_r(cpp->tokens.next, num_eles, eles);
169 }
170
171 #if PSI_CPP_DEBUG
172 PSI_DEBUG_PRINT(cpp->parser,
173 "PSI: CPP add_range -> index=%zu, num_eles=%zu, iter.count=%zu, next.count=%zu, exec.count=%zu\n",
174 cpp->index, num_eles, psi_plist_count(cpp->tokens.iter), psi_plist_count(cpp->tokens.next),
175 psi_plist_count(cpp->tokens.exec));
176 #endif
177
178 return true;
179 }
180
181
182 void psi_cpp_tokiter_next(struct psi_cpp *cpp)
183 {
184 #if 0 && PSI_CPP_DEBUG
185 PSI_DEBUG_PRINT(cpp->parser, "PSI: CPP next -> index=%zu -> index=%zu\n",
186 cpp->index, cpp->index+1);
187 #endif
188 ++cpp->index;
189 }
190
191 bool psi_cpp_tokiter_valid(struct psi_cpp *cpp)
192 {
193 #if PSI_CPP_DEBUG > 1
194 PSI_DEBUG_PRINT(cpp->parser, "PSI: CPP valid -> index=%zu -> %s\n",
195 cpp->index, cpp->index < psi_plist_count(cpp->tokens.iter)
196 ? "true" : "false");
197 #endif
198 return cpp->index < psi_plist_count(cpp->tokens.iter);
199 }
200
201 bool psi_cpp_tokiter_del_prev(struct psi_cpp *cpp, bool free_token)
202 {
203 struct psi_token *cur = NULL;
204
205 #if PSI_CPP_DEBUG
206 PSI_DEBUG_PRINT(cpp->parser,
207 "PSI: CPP del_prev -> index=%zu, iter.count=%zu, next.count=%zu, exec.count=%zu\n",
208 cpp->index, psi_plist_count(cpp->tokens.iter), psi_plist_count(cpp->tokens.next),
209 psi_plist_count(cpp->tokens.exec));
210 #endif
211
212 if (cpp->do_cpp) {
213 if (!psi_plist_pop(cpp->tokens.exec, &cur)) {
214 return false;
215 }
216 } else if (!psi_plist_pop(cpp->tokens.next, &cur)) {
217 return false;
218 }
219 if (free_token && cur) {
220 psi_token_free(&cur);
221 }
222 return true;
223 }
224
225 bool psi_cpp_tokiter_del_cur(struct psi_cpp *cpp, bool free_token)
226 {
227 struct psi_token *cur = NULL;
228
229 #if PSI_CPP_DEBUG
230 PSI_DEBUG_PRINT(cpp->parser,
231 "PSI: CPP del_cur -> index=%zu, iter.count=%zu, next.count=%zu, exec.count=%zu ",
232 cpp->index, psi_plist_count(cpp->tokens.iter), psi_plist_count(cpp->tokens.next),
233 psi_plist_count(cpp->tokens.exec));
234 #endif
235
236 if (psi_plist_get(cpp->tokens.iter, cpp->index, &cur)) {
237 #if PSI_CPP_DEBUG
238 PSI_DEBUG_DUMP(cpp->parser, psi_token_dump, cur);
239 #endif
240 if (cpp->index == psi_plist_count(cpp->tokens.iter) - 1) {
241 psi_plist_pop(cpp->tokens.iter, NULL);
242 } else {
243 psi_plist_unset(cpp->tokens.iter, cpp->index);
244 }
245 if (free_token && cur) {
246 psi_token_free(&cur);
247 }
248 ++cpp->index;
249 return true;
250 }
251
252 return false;
253 }
254
255 bool psi_cpp_tokiter_del_range(struct psi_cpp *cpp, size_t offset, size_t num_eles, bool free_tokens)
256 {
257 struct psi_token *ptr;
258 size_t i;
259
260 #if PSI_CPP_DEBUG
261 PSI_DEBUG_PRINT(cpp->parser,
262 "PSI: CPP del_range -> index=%zu, offset=%zu, num_eles=%zu, iter.count=%zu, next.count=%zu, exec.count=%zu\n",
263 cpp->index, offset, num_eles, psi_plist_count(cpp->tokens.iter), psi_plist_count(cpp->tokens.next),
264 psi_plist_count(cpp->tokens.exec));
265 #endif
266
267 for (i = offset; i < offset + num_eles; ++i) {
268 if (!psi_plist_get(cpp->tokens.iter, i, &ptr)) {
269 return false;
270 }
271 #if PSI_CPP_DEBUG
272 PSI_DEBUG_LOCK(cpp->parser,
273 PSI_DEBUG_PRINT(cpp->parser, "PSI: CPP del_range -> ");
274 PSI_DEBUG_DUMP(cpp->parser, psi_token_dump, ptr);
275 );
276 #endif
277 psi_plist_unset(cpp->tokens.iter, i);
278 if (free_tokens && ptr) {
279 psi_token_free(&ptr);
280 }
281 }
282
283 cpp->index = i;
284 return true;
285 }
286
287 bool psi_cpp_tokiter_defined(struct psi_cpp *cpp)
288 {
289 if (psi_cpp_tokiter_valid(cpp)) {
290 struct psi_token *current = psi_cpp_tokiter_current(cpp);
291
292 return psi_cpp_defined(cpp, current);
293 }
294
295 return false;
296 }
297
298 static inline size_t psi_cpp_tokiter_expand_tokens(struct psi_cpp *cpp,
299 struct psi_token *target, struct psi_plist *tokens)
300 {
301 size_t i = 0, n = 0;
302 bool stringify = false, paste = false;
303 struct psi_token *tok;
304 struct psi_plist *exp;
305
306 if (!psi_plist_count(tokens)) {
307 return 0;
308 }
309
310 exp = psi_plist_init(NULL);
311 while (psi_plist_get(tokens, i++, &tok)) {
312 struct psi_token *new_tok;
313
314 if (tok->type == PSI_T_EOL) {
315 continue;
316 }
317 if (tok->type == PSI_T_HASH) {
318 stringify = true;
319 continue;
320 }
321 if (tok->type == PSI_T_CPP_PASTE) {
322 paste = true;
323 continue;
324 }
325
326 if (paste && psi_plist_count(exp)) {
327 struct psi_token *old_tok;
328 struct psi_parser_input *toscan;
329
330 psi_plist_pop(exp, &old_tok);
331 new_tok = psi_token_cat(NULL, 2, old_tok, tok);
332
333 /* reclassify token(s) */
334 if ((toscan = psi_parser_open_string(cpp->parser, new_tok->text->val, new_tok->text->len))) {
335 struct psi_plist *scanned;
336
337 scanned = psi_parser_scan(cpp->parser, toscan);
338 if (psi_plist_count(scanned)) {
339 size_t i = 0;
340 struct psi_token *tmp_tok;
341
342 exp = psi_plist_add_r(exp, psi_plist_count(scanned), psi_plist_eles(scanned));
343
344 /* fix meta info */
345 while (psi_plist_get(scanned, i++, &tmp_tok)) {
346 zend_string_release(tmp_tok->file);
347 tmp_tok->file = zend_string_copy(new_tok->file);
348 tmp_tok->line = new_tok->line;
349 tmp_tok->col = new_tok->col;
350 }
351
352 psi_token_free(&new_tok);
353 psi_plist_top(scanned, &new_tok);
354 } else {
355 exp = psi_plist_add(exp, &new_tok);
356 }
357 if (scanned) {
358 free(scanned);
359 }
360 psi_parser_input_free(&toscan);
361 } else {
362 exp = psi_plist_add(exp, &new_tok);
363 }
364
365 psi_token_free(&old_tok);
366 } else {
367 new_tok = psi_token_init(stringify ? PSI_T_QUOTED_STRING : tok->type,
368 tok->text->val, tok->text->len, target->col, target->line,
369 target->file ?: zend_empty_string);
370
371 exp = psi_plist_add(exp, &new_tok);
372 }
373
374 #if PSI_CPP_DEBUG
375 PSI_DEBUG_PRINT(cpp->parser, "PSI: CPP expand > ");
376 PSI_DEBUG_DUMP(cpp->parser, psi_token_dump, new_tok);
377 #endif
378
379 paste = false;
380 stringify = false;
381 }
382
383 bool processed = psi_cpp_process(cpp, &exp, target);
384 assert(processed);
385
386 n = psi_plist_count(exp);
387 psi_cpp_tokiter_add_range(cpp, n, psi_plist_eles(exp));
388 free(exp);
389
390 return n;
391 }
392
393 static inline void psi_cpp_tokiter_free_call_tokens(
394 struct psi_plist **arg_tokens_list, size_t arg_count, bool free_tokens)
395 {
396 size_t i;
397
398 for (i = 0; i < arg_count; ++i) {
399 if (arg_tokens_list[i]) {
400 if (free_tokens) {
401 struct psi_token *tok;
402
403 while (psi_plist_pop(arg_tokens_list[i], &tok)) {
404 psi_token_free(&tok);
405 }
406 }
407 psi_plist_free(arg_tokens_list[i]);
408 }
409 }
410 free(arg_tokens_list);
411 }
412
413 static inline struct psi_plist **psi_cpp_tokiter_read_call_tokens(
414 struct psi_cpp *cpp, size_t arg_count)
415 {
416 size_t arg_index = 0, lparens = 1, rparens = 0, start = psi_cpp_tokiter_index(cpp);
417 struct psi_plist **arg_tokens = pecalloc(arg_count, sizeof(*arg_tokens), 1);
418 struct psi_plist *free_tokens = psi_plist_init((psi_plist_dtor) psi_token_free);
419 struct psi_token *tok;
420
421 arg_tokens[0] = psi_plist_init(NULL);
422
423 /* next token must be a LPAREN for a macro call */
424 psi_cpp_tokiter_next(cpp);
425 tok = psi_cpp_tokiter_current(cpp);
426 if (!psi_cpp_tokiter_valid(cpp) || tok->type != PSI_T_LPAREN) {
427 goto fail;
428 }
429
430 /* free LPAREN on success */
431 free_tokens = psi_plist_add(free_tokens, &tok);
432
433 while (lparens > rparens) {
434 psi_cpp_tokiter_next(cpp);
435 if (!psi_cpp_tokiter_valid(cpp)) {
436 goto fail;
437 }
438 tok = psi_cpp_tokiter_current(cpp);
439
440 switch (tok->type) {
441 case PSI_T_LPAREN:
442 ++lparens;
443 arg_tokens[arg_index] = psi_plist_add(arg_tokens[arg_index], &tok);
444 break;
445 case PSI_T_RPAREN:
446 if (++rparens == lparens) {
447 /* closing RPAREN */
448 if (arg_index + 1 < arg_count) {
449 goto fail;
450 }
451 free_tokens = psi_plist_add(free_tokens, &tok);
452 } else {
453 arg_tokens[arg_index] = psi_plist_add(arg_tokens[arg_index], &tok);
454 }
455 break;
456 case PSI_T_COMMA:
457 if (1 == (lparens - rparens)) {
458 /* too many commas? */
459 if (++arg_index >= arg_count) {
460 goto fail;
461 }
462 free_tokens = psi_plist_add(free_tokens, &tok);
463 /* next arg */
464 arg_tokens[arg_index] = psi_plist_init(NULL);
465 } else {
466 arg_tokens[arg_index] = psi_plist_add(arg_tokens[arg_index], &tok);
467 }
468 break;
469 default:
470 arg_tokens[arg_index] = psi_plist_add(arg_tokens[arg_index], &tok);
471 }
472 }
473
474 /* ditch arg tokens */
475 psi_cpp_tokiter_del_range(cpp, start, psi_cpp_tokiter_index(cpp) - start + 1, false);
476 psi_plist_free(free_tokens);
477
478 return arg_tokens;
479
480 fail:
481 psi_cpp_tokiter_free_call_tokens(arg_tokens, arg_count, false);
482 return NULL;
483 }
484
485 static inline void psi_cpp_tokiter_expand_call_tokens(struct psi_cpp *cpp,
486 struct psi_token *target, struct psi_cpp_macro_decl *macro,
487 struct psi_plist **arg_tokens_list)
488 {
489 size_t i;
490 struct psi_token *tok;
491 struct psi_plist *tokens = psi_plist_init(NULL);
492 bool prescan = true;
493
494 for (i = 0; psi_plist_get(macro->tokens, i, &tok); ++i) {
495 struct psi_plist *arg_tokens = NULL;
496
497 if (tok->type == PSI_T_HASH || tok->type == PSI_T_CPP_PASTE) {
498 prescan = false;
499 } else if (tok->type == PSI_T_NAME) {
500 size_t s;
501 struct psi_token *arg_name;
502
503 for (s = 0; psi_plist_get(macro->sig, s, &arg_name); ++s) {
504 if (zend_string_equals(arg_name->text, tok->text)) {
505 if (prescan) {
506 bool processed = psi_cpp_process(cpp,
507 &arg_tokens_list[s], target);
508
509 assert(processed);
510 }
511 arg_tokens = arg_tokens_list[s];
512 break;
513 }
514 }
515 }
516
517 if (arg_tokens) {
518 tokens = psi_plist_add_r(tokens, psi_plist_count(arg_tokens), psi_plist_eles(arg_tokens));
519 } else {
520 tokens = psi_plist_add(tokens, &tok);
521 }
522 }
523
524 psi_cpp_tokiter_expand_tokens(cpp, target, tokens);
525 psi_plist_free(tokens);
526 }
527
528 static inline bool psi_cpp_tokiter_expand_call(struct psi_cpp *cpp,
529 struct psi_token *target, struct psi_cpp_macro_decl *macro)
530 {
531 /* function-like macro
532 * #define FOO(a,b) a>b // macro->sig == {a, b}, macro->tokens = {a, >, b}
533 * # if FOO(1,2) // expands to if 1 > 2
534 */
535 size_t start = psi_cpp_tokiter_index(cpp), argc = psi_plist_count(macro->sig);
536 struct psi_plist **arg_tokens_list;
537
538
539 /* read in tokens, until we have balanced parens */
540 arg_tokens_list = psi_cpp_tokiter_read_call_tokens(cpp, argc);
541 if (!arg_tokens_list) {
542 psi_cpp_tokiter_seek(cpp, start);
543 return false;
544 }
545
546 /* insert and expand macro tokens */
547 psi_cpp_tokiter_expand_call_tokens(cpp, target, macro, arg_tokens_list);
548 psi_cpp_tokiter_free_call_tokens(arg_tokens_list, argc, true);
549
550 psi_token_free(&target);
551 ++cpp->expanded;
552 return true;
553 }
554
555 static inline void psi_cpp_tokiter_expand_builtin_tokens(struct psi_cpp *cpp,
556 struct psi_token *target, struct psi_builtin *builtin,
557 struct psi_plist **arg_tokens_list)
558 {
559 size_t s;
560 struct psi_plist *res = NULL;
561 size_t argc = psi_plist_count(builtin->decl->sig);
562
563 /* prescan */
564 for (s = 0; s < argc; ++s) {
565 bool processed = psi_cpp_process(cpp, &arg_tokens_list[s],
566 target);
567 assert(processed);
568 }
569
570 /* insert and expand macro tokens */
571 if (!builtin->func(cpp, target, arg_tokens_list, &res)) {
572 struct psi_token *zero = psi_token_init(PSI_T_NUMBER, "0", 1,
573 target->col, target->line, target->file);
574 psi_cpp_tokiter_add(cpp, zero);
575 } else if (!res) {
576 struct psi_token *one = psi_token_init(PSI_T_NUMBER, "1", 1,
577 target->col, target->line, target->file);
578 psi_cpp_tokiter_add(cpp, one);
579 } else {
580 psi_cpp_tokiter_expand_tokens(cpp, target, res);
581 psi_plist_free(res);
582 }
583 }
584
585 static inline bool psi_cpp_tokiter_expand_builtin(struct psi_cpp *cpp,
586 struct psi_token *target, struct psi_builtin *builtin)
587 {
588 size_t start = psi_cpp_tokiter_index(cpp), argc = 0;
589 struct psi_plist **arg_tokens_list = NULL;
590
591 if (builtin->decl->sig) {
592 argc = psi_plist_count(builtin->decl->sig);
593 /* read in tokens, until we have balanced parens */
594 arg_tokens_list = psi_cpp_tokiter_read_call_tokens(cpp, argc);
595 if (!arg_tokens_list) {
596 psi_cpp_tokiter_seek(cpp, start);
597 return false;
598 }
599 } else {
600 psi_cpp_tokiter_del_cur(cpp, false);
601 }
602
603 psi_cpp_tokiter_expand_builtin_tokens(cpp, target, builtin, arg_tokens_list);
604 if (arg_tokens_list) {
605 psi_cpp_tokiter_free_call_tokens(arg_tokens_list, argc, true);
606 }
607
608 psi_token_free(&target);
609 ++cpp->expanded;
610 return true;
611 }
612
613
614 static inline bool psi_cpp_tokiter_expand_def(struct psi_cpp *cpp,
615 struct psi_token *target, struct psi_cpp_macro_decl *macro)
616 {
617 if (macro->tokens) {
618 struct psi_plist *tokens = psi_plist_copy(macro->tokens,
619 (void (*)(void *)) psi_token_copy_ctor);
620 bool processed = psi_cpp_process(cpp, &tokens, target);
621
622 if (processed) {
623 /* replace with tokens from macro */
624 psi_cpp_tokiter_expand_tokens(cpp, target, tokens);
625 }
626 psi_plist_free(tokens);
627 ++cpp->expanded;
628 }
629
630 psi_cpp_tokiter_del_cur(cpp, true);
631 return true;
632 }
633
634 static inline int psi_cpp_tokiter_expand_cmp(struct psi_token *t,
635 struct psi_cpp_macro_decl *m)
636 {
637 if (psi_plist_count(m->tokens) == 1) {
638 struct psi_token *r;
639
640 if (psi_plist_get(m->tokens, 0, &r) && r->text) {
641 return !zend_string_equals(r->text, t->text);
642 }
643 }
644 return -1;
645 }
646
647 static inline bool psi_cpp_tokiter_expand_decl(struct psi_cpp *cpp,
648 struct psi_token *target, struct psi_cpp_macro_decl *macro)
649 {
650 if (!macro) {
651 return false;
652 }
653
654 if (macro->sig) {
655 return psi_cpp_tokiter_expand_call(cpp, target, macro);
656 } else if (psi_cpp_tokiter_expand_cmp(target, macro)) {
657 return psi_cpp_tokiter_expand_def(cpp, target, macro);
658 } else {
659 return false;
660 }
661 }
662
663 bool psi_cpp_tokiter_expand(struct psi_cpp *cpp)
664 {
665 struct psi_token *current;
666
667 if (!psi_cpp_tokiter_valid(cpp)) {
668 return false;
669 }
670
671 current = psi_cpp_tokiter_current(cpp);
672 if (!current) {
673 return false;
674 }
675 #if PSI_CPP_DEBUG
676 PSI_DEBUG_PRINT(cpp->parser, "PSI: CPP expand < ");
677 PSI_DEBUG_DUMP(cpp->parser, psi_token_dump, current);
678 #endif
679
680 if (psi_builtin_exists(current->text)) {
681 return psi_cpp_tokiter_expand_builtin(cpp, current,
682 psi_builtin_get(current->text));
683 } else {
684 return psi_cpp_tokiter_expand_decl(cpp, current,
685 zend_hash_find_ptr(&cpp->defs, current->text));
686 }
687 }