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