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