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