move parser/generator to tccgen.c
[tinycc/kirr.git] / tccpp.c
blob6bc78141a7c8d649caa2bcc0b9d0b0f1affff6bf
1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /* fill input buffer and peek next char */
22 static int tcc_peekc_slow(BufferedFile *bf)
24 int len;
25 /* only tries to read if really end of buffer */
26 if (bf->buf_ptr >= bf->buf_end) {
27 if (bf->fd != -1) {
28 #if defined(PARSE_DEBUG)
29 len = 8;
30 #else
31 len = IO_BUF_SIZE;
32 #endif
33 len = read(bf->fd, bf->buffer, len);
34 if (len < 0)
35 len = 0;
36 } else {
37 len = 0;
39 total_bytes += len;
40 bf->buf_ptr = bf->buffer;
41 bf->buf_end = bf->buffer + len;
42 *bf->buf_end = CH_EOB;
44 if (bf->buf_ptr < bf->buf_end) {
45 return bf->buf_ptr[0];
46 } else {
47 bf->buf_ptr = bf->buf_end;
48 return CH_EOF;
52 /* return the current character, handling end of block if necessary
53 (but not stray) */
54 static int handle_eob(void)
56 return tcc_peekc_slow(file);
59 /* read next char from current input file and handle end of input buffer */
60 static inline void inp(void)
62 ch = *(++(file->buf_ptr));
63 /* end of buffer/file handling */
64 if (ch == CH_EOB)
65 ch = handle_eob();
68 /* handle '\[\r]\n' */
69 static int handle_stray_noerror(void)
71 while (ch == '\\') {
72 inp();
73 if (ch == '\n') {
74 file->line_num++;
75 inp();
76 } else if (ch == '\r') {
77 inp();
78 if (ch != '\n')
79 goto fail;
80 file->line_num++;
81 inp();
82 } else {
83 fail:
84 return 1;
87 return 0;
90 static void handle_stray(void)
92 if (handle_stray_noerror())
93 error("stray '\\' in program");
96 /* skip the stray and handle the \\n case. Output an error if
97 incorrect char after the stray */
98 static int handle_stray1(uint8_t *p)
100 int c;
102 if (p >= file->buf_end) {
103 file->buf_ptr = p;
104 c = handle_eob();
105 p = file->buf_ptr;
106 if (c == '\\')
107 goto parse_stray;
108 } else {
109 parse_stray:
110 file->buf_ptr = p;
111 ch = *p;
112 handle_stray();
113 p = file->buf_ptr;
114 c = *p;
116 return c;
119 /* handle just the EOB case, but not stray */
120 #define PEEKC_EOB(c, p)\
122 p++;\
123 c = *p;\
124 if (c == '\\') {\
125 file->buf_ptr = p;\
126 c = handle_eob();\
127 p = file->buf_ptr;\
131 /* handle the complicated stray case */
132 #define PEEKC(c, p)\
134 p++;\
135 c = *p;\
136 if (c == '\\') {\
137 c = handle_stray1(p);\
138 p = file->buf_ptr;\
142 /* input with '\[\r]\n' handling. Note that this function cannot
143 handle other characters after '\', so you cannot call it inside
144 strings or comments */
145 static void minp(void)
147 inp();
148 if (ch == '\\')
149 handle_stray();
153 /* single line C++ comments */
154 static uint8_t *parse_line_comment(uint8_t *p)
156 int c;
158 p++;
159 for(;;) {
160 c = *p;
161 redo:
162 if (c == '\n' || c == CH_EOF) {
163 break;
164 } else if (c == '\\') {
165 file->buf_ptr = p;
166 c = handle_eob();
167 p = file->buf_ptr;
168 if (c == '\\') {
169 PEEKC_EOB(c, p);
170 if (c == '\n') {
171 file->line_num++;
172 PEEKC_EOB(c, p);
173 } else if (c == '\r') {
174 PEEKC_EOB(c, p);
175 if (c == '\n') {
176 file->line_num++;
177 PEEKC_EOB(c, p);
180 } else {
181 goto redo;
183 } else {
184 p++;
187 return p;
190 /* C comments */
191 static uint8_t *parse_comment(uint8_t *p)
193 int c;
195 p++;
196 for(;;) {
197 /* fast skip loop */
198 for(;;) {
199 c = *p;
200 if (c == '\n' || c == '*' || c == '\\')
201 break;
202 p++;
203 c = *p;
204 if (c == '\n' || c == '*' || c == '\\')
205 break;
206 p++;
208 /* now we can handle all the cases */
209 if (c == '\n') {
210 file->line_num++;
211 p++;
212 } else if (c == '*') {
213 p++;
214 for(;;) {
215 c = *p;
216 if (c == '*') {
217 p++;
218 } else if (c == '/') {
219 goto end_of_comment;
220 } else if (c == '\\') {
221 file->buf_ptr = p;
222 c = handle_eob();
223 p = file->buf_ptr;
224 if (c == '\\') {
225 /* skip '\[\r]\n', otherwise just skip the stray */
226 while (c == '\\') {
227 PEEKC_EOB(c, p);
228 if (c == '\n') {
229 file->line_num++;
230 PEEKC_EOB(c, p);
231 } else if (c == '\r') {
232 PEEKC_EOB(c, p);
233 if (c == '\n') {
234 file->line_num++;
235 PEEKC_EOB(c, p);
237 } else {
238 goto after_star;
242 } else {
243 break;
246 after_star: ;
247 } else {
248 /* stray, eob or eof */
249 file->buf_ptr = p;
250 c = handle_eob();
251 p = file->buf_ptr;
252 if (c == CH_EOF) {
253 error("unexpected end of file in comment");
254 } else if (c == '\\') {
255 p++;
259 end_of_comment:
260 p++;
261 return p;
264 #define cinp minp
266 /* space exlcuding newline */
267 static inline int is_space(int ch)
269 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
272 static inline void skip_spaces(void)
274 while (is_space(ch))
275 cinp();
278 static inline int check_space(int t, int *spc)
280 if (is_space(t)) {
281 if (*spc)
282 return 1;
283 *spc = 1;
284 } else
285 *spc = 0;
286 return 0;
289 /* parse a string without interpreting escapes */
290 static uint8_t *parse_pp_string(uint8_t *p,
291 int sep, CString *str)
293 int c;
294 p++;
295 for(;;) {
296 c = *p;
297 if (c == sep) {
298 break;
299 } else if (c == '\\') {
300 file->buf_ptr = p;
301 c = handle_eob();
302 p = file->buf_ptr;
303 if (c == CH_EOF) {
304 unterminated_string:
305 /* XXX: indicate line number of start of string */
306 error("missing terminating %c character", sep);
307 } else if (c == '\\') {
308 /* escape : just skip \[\r]\n */
309 PEEKC_EOB(c, p);
310 if (c == '\n') {
311 file->line_num++;
312 p++;
313 } else if (c == '\r') {
314 PEEKC_EOB(c, p);
315 if (c != '\n')
316 expect("'\n' after '\r'");
317 file->line_num++;
318 p++;
319 } else if (c == CH_EOF) {
320 goto unterminated_string;
321 } else {
322 if (str) {
323 cstr_ccat(str, '\\');
324 cstr_ccat(str, c);
326 p++;
329 } else if (c == '\n') {
330 file->line_num++;
331 goto add_char;
332 } else if (c == '\r') {
333 PEEKC_EOB(c, p);
334 if (c != '\n') {
335 if (str)
336 cstr_ccat(str, '\r');
337 } else {
338 file->line_num++;
339 goto add_char;
341 } else {
342 add_char:
343 if (str)
344 cstr_ccat(str, c);
345 p++;
348 p++;
349 return p;
352 /* skip block of text until #else, #elif or #endif. skip also pairs of
353 #if/#endif */
354 void preprocess_skip(void)
356 int a, start_of_line, c, in_warn_or_error;
357 uint8_t *p;
359 p = file->buf_ptr;
360 a = 0;
361 redo_start:
362 start_of_line = 1;
363 in_warn_or_error = 0;
364 for(;;) {
365 redo_no_start:
366 c = *p;
367 switch(c) {
368 case ' ':
369 case '\t':
370 case '\f':
371 case '\v':
372 case '\r':
373 p++;
374 goto redo_no_start;
375 case '\n':
376 file->line_num++;
377 p++;
378 goto redo_start;
379 case '\\':
380 file->buf_ptr = p;
381 c = handle_eob();
382 if (c == CH_EOF) {
383 expect("#endif");
384 } else if (c == '\\') {
385 ch = file->buf_ptr[0];
386 handle_stray_noerror();
388 p = file->buf_ptr;
389 goto redo_no_start;
390 /* skip strings */
391 case '\"':
392 case '\'':
393 if (in_warn_or_error)
394 goto _default;
395 p = parse_pp_string(p, c, NULL);
396 break;
397 /* skip comments */
398 case '/':
399 if (in_warn_or_error)
400 goto _default;
401 file->buf_ptr = p;
402 ch = *p;
403 minp();
404 p = file->buf_ptr;
405 if (ch == '*') {
406 p = parse_comment(p);
407 } else if (ch == '/') {
408 p = parse_line_comment(p);
410 break;
411 case '#':
412 p++;
413 if (start_of_line) {
414 file->buf_ptr = p;
415 next_nomacro();
416 p = file->buf_ptr;
417 if (a == 0 &&
418 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
419 goto the_end;
420 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
421 a++;
422 else if (tok == TOK_ENDIF)
423 a--;
424 else if( tok == TOK_ERROR || tok == TOK_WARNING)
425 in_warn_or_error = 1;
427 break;
428 _default:
429 default:
430 p++;
431 break;
433 start_of_line = 0;
435 the_end: ;
436 file->buf_ptr = p;
439 /* ParseState handling */
441 /* XXX: currently, no include file info is stored. Thus, we cannot display
442 accurate messages if the function or data definition spans multiple
443 files */
445 /* save current parse state in 's' */
446 void save_parse_state(ParseState *s)
448 s->line_num = file->line_num;
449 s->macro_ptr = macro_ptr;
450 s->tok = tok;
451 s->tokc = tokc;
454 /* restore parse state from 's' */
455 void restore_parse_state(ParseState *s)
457 file->line_num = s->line_num;
458 macro_ptr = s->macro_ptr;
459 tok = s->tok;
460 tokc = s->tokc;
463 /* return the number of additional 'ints' necessary to store the
464 token */
465 static inline int tok_ext_size(int t)
467 switch(t) {
468 /* 4 bytes */
469 case TOK_CINT:
470 case TOK_CUINT:
471 case TOK_CCHAR:
472 case TOK_LCHAR:
473 case TOK_CFLOAT:
474 case TOK_LINENUM:
475 return 1;
476 case TOK_STR:
477 case TOK_LSTR:
478 case TOK_PPNUM:
479 error("unsupported token");
480 return 1;
481 case TOK_CDOUBLE:
482 case TOK_CLLONG:
483 case TOK_CULLONG:
484 return 2;
485 case TOK_CLDOUBLE:
486 return LDOUBLE_SIZE / 4;
487 default:
488 return 0;
492 /* token string handling */
494 static inline void tok_str_new(TokenString *s)
496 s->str = NULL;
497 s->len = 0;
498 s->allocated_len = 0;
499 s->last_line_num = -1;
502 static void tok_str_free(int *str)
504 tcc_free(str);
507 static int *tok_str_realloc(TokenString *s)
509 int *str, len;
511 if (s->allocated_len == 0) {
512 len = 8;
513 } else {
514 len = s->allocated_len * 2;
516 str = tcc_realloc(s->str, len * sizeof(int));
517 if (!str)
518 error("memory full");
519 s->allocated_len = len;
520 s->str = str;
521 return str;
524 static void tok_str_add(TokenString *s, int t)
526 int len, *str;
528 len = s->len;
529 str = s->str;
530 if (len >= s->allocated_len)
531 str = tok_str_realloc(s);
532 str[len++] = t;
533 s->len = len;
536 static void tok_str_add2(TokenString *s, int t, CValue *cv)
538 int len, *str;
540 len = s->len;
541 str = s->str;
543 /* allocate space for worst case */
544 if (len + TOK_MAX_SIZE > s->allocated_len)
545 str = tok_str_realloc(s);
546 str[len++] = t;
547 switch(t) {
548 case TOK_CINT:
549 case TOK_CUINT:
550 case TOK_CCHAR:
551 case TOK_LCHAR:
552 case TOK_CFLOAT:
553 case TOK_LINENUM:
554 str[len++] = cv->tab[0];
555 break;
556 case TOK_PPNUM:
557 case TOK_STR:
558 case TOK_LSTR:
560 int nb_words;
561 CString *cstr;
563 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
564 while ((len + nb_words) > s->allocated_len)
565 str = tok_str_realloc(s);
566 cstr = (CString *)(str + len);
567 cstr->data = NULL;
568 cstr->size = cv->cstr->size;
569 cstr->data_allocated = NULL;
570 cstr->size_allocated = cstr->size;
571 memcpy((char *)cstr + sizeof(CString),
572 cv->cstr->data, cstr->size);
573 len += nb_words;
575 break;
576 case TOK_CDOUBLE:
577 case TOK_CLLONG:
578 case TOK_CULLONG:
579 #if LDOUBLE_SIZE == 8
580 case TOK_CLDOUBLE:
581 #endif
582 str[len++] = cv->tab[0];
583 str[len++] = cv->tab[1];
584 break;
585 #if LDOUBLE_SIZE == 12
586 case TOK_CLDOUBLE:
587 str[len++] = cv->tab[0];
588 str[len++] = cv->tab[1];
589 str[len++] = cv->tab[2];
590 #elif LDOUBLE_SIZE == 16
591 case TOK_CLDOUBLE:
592 str[len++] = cv->tab[0];
593 str[len++] = cv->tab[1];
594 str[len++] = cv->tab[2];
595 str[len++] = cv->tab[3];
596 #elif LDOUBLE_SIZE != 8
597 #error add long double size support
598 #endif
599 break;
600 default:
601 break;
603 s->len = len;
606 /* add the current parse token in token string 's' */
607 static void tok_str_add_tok(TokenString *s)
609 CValue cval;
611 /* save line number info */
612 if (file->line_num != s->last_line_num) {
613 s->last_line_num = file->line_num;
614 cval.i = s->last_line_num;
615 tok_str_add2(s, TOK_LINENUM, &cval);
617 tok_str_add2(s, tok, &tokc);
620 #if LDOUBLE_SIZE == 16
621 #define LDOUBLE_GET(p, cv) \
622 cv.tab[0] = p[0]; \
623 cv.tab[1] = p[1]; \
624 cv.tab[2] = p[2]; \
625 cv.tab[3] = p[3];
626 #elif LDOUBLE_SIZE == 12
627 #define LDOUBLE_GET(p, cv) \
628 cv.tab[0] = p[0]; \
629 cv.tab[1] = p[1]; \
630 cv.tab[2] = p[2];
631 #elif LDOUBLE_SIZE == 8
632 #define LDOUBLE_GET(p, cv) \
633 cv.tab[0] = p[0]; \
634 cv.tab[1] = p[1];
635 #else
636 #error add long double size support
637 #endif
640 /* get a token from an integer array and increment pointer
641 accordingly. we code it as a macro to avoid pointer aliasing. */
642 #define TOK_GET(t, p, cv) \
644 t = *p++; \
645 switch(t) { \
646 case TOK_CINT: \
647 case TOK_CUINT: \
648 case TOK_CCHAR: \
649 case TOK_LCHAR: \
650 case TOK_CFLOAT: \
651 case TOK_LINENUM: \
652 cv.tab[0] = *p++; \
653 break; \
654 case TOK_STR: \
655 case TOK_LSTR: \
656 case TOK_PPNUM: \
657 cv.cstr = (CString *)p; \
658 cv.cstr->data = (char *)p + sizeof(CString);\
659 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
660 break; \
661 case TOK_CDOUBLE: \
662 case TOK_CLLONG: \
663 case TOK_CULLONG: \
664 cv.tab[0] = p[0]; \
665 cv.tab[1] = p[1]; \
666 p += 2; \
667 break; \
668 case TOK_CLDOUBLE: \
669 LDOUBLE_GET(p, cv); \
670 p += LDOUBLE_SIZE / 4; \
671 break; \
672 default: \
673 break; \
677 /* defines handling */
678 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
680 Sym *s;
682 s = sym_push2(&define_stack, v, macro_type, (long)str);
683 s->next = first_arg;
684 table_ident[v - TOK_IDENT]->sym_define = s;
687 /* undefined a define symbol. Its name is just set to zero */
688 static void define_undef(Sym *s)
690 int v;
691 v = s->v;
692 if (v >= TOK_IDENT && v < tok_ident)
693 table_ident[v - TOK_IDENT]->sym_define = NULL;
694 s->v = 0;
697 static inline Sym *define_find(int v)
699 v -= TOK_IDENT;
700 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
701 return NULL;
702 return table_ident[v]->sym_define;
705 /* free define stack until top reaches 'b' */
706 static void free_defines(Sym *b)
708 Sym *top, *top1;
709 int v;
711 top = define_stack;
712 while (top != b) {
713 top1 = top->prev;
714 /* do not free args or predefined defines */
715 if (top->c)
716 tok_str_free((int *)top->c);
717 v = top->v;
718 if (v >= TOK_IDENT && v < tok_ident)
719 table_ident[v - TOK_IDENT]->sym_define = NULL;
720 sym_free(top);
721 top = top1;
723 define_stack = b;
726 /* label lookup */
727 static Sym *label_find(int v)
729 v -= TOK_IDENT;
730 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
731 return NULL;
732 return table_ident[v]->sym_label;
735 static Sym *label_push(Sym **ptop, int v, int flags)
737 Sym *s, **ps;
738 s = sym_push2(ptop, v, 0, 0);
739 s->r = flags;
740 ps = &table_ident[v - TOK_IDENT]->sym_label;
741 if (ptop == &global_label_stack) {
742 /* modify the top most local identifier, so that
743 sym_identifier will point to 's' when popped */
744 while (*ps != NULL)
745 ps = &(*ps)->prev_tok;
747 s->prev_tok = *ps;
748 *ps = s;
749 return s;
752 /* pop labels until element last is reached. Look if any labels are
753 undefined. Define symbols if '&&label' was used. */
754 static void label_pop(Sym **ptop, Sym *slast)
756 Sym *s, *s1;
757 for(s = *ptop; s != slast; s = s1) {
758 s1 = s->prev;
759 if (s->r == LABEL_DECLARED) {
760 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
761 } else if (s->r == LABEL_FORWARD) {
762 error("label '%s' used but not defined",
763 get_tok_str(s->v, NULL));
764 } else {
765 if (s->c) {
766 /* define corresponding symbol. A size of
767 1 is put. */
768 put_extern_sym(s, cur_text_section, (long)s->next, 1);
771 /* remove label */
772 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
773 sym_free(s);
775 *ptop = slast;
778 /* eval an expression for #if/#elif */
779 static int expr_preprocess(void)
781 int c, t;
782 TokenString str;
784 tok_str_new(&str);
785 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
786 next(); /* do macro subst */
787 if (tok == TOK_DEFINED) {
788 next_nomacro();
789 t = tok;
790 if (t == '(')
791 next_nomacro();
792 c = define_find(tok) != 0;
793 if (t == '(')
794 next_nomacro();
795 tok = TOK_CINT;
796 tokc.i = c;
797 } else if (tok >= TOK_IDENT) {
798 /* if undefined macro */
799 tok = TOK_CINT;
800 tokc.i = 0;
802 tok_str_add_tok(&str);
804 tok_str_add(&str, -1); /* simulate end of file */
805 tok_str_add(&str, 0);
806 /* now evaluate C constant expression */
807 macro_ptr = str.str;
808 next();
809 c = expr_const();
810 macro_ptr = NULL;
811 tok_str_free(str.str);
812 return c != 0;
815 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
816 static void tok_print(int *str)
818 int t;
819 CValue cval;
821 printf("<");
822 while (1) {
823 TOK_GET(t, str, cval);
824 if (!t)
825 break;
826 printf("%s", get_tok_str(t, &cval));
828 printf(">\n");
830 #endif
832 /* parse after #define */
833 static void parse_define(void)
835 Sym *s, *first, **ps;
836 int v, t, varg, is_vaargs, spc;
837 TokenString str;
839 v = tok;
840 if (v < TOK_IDENT)
841 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
842 /* XXX: should check if same macro (ANSI) */
843 first = NULL;
844 t = MACRO_OBJ;
845 /* '(' must be just after macro definition for MACRO_FUNC */
846 next_nomacro_spc();
847 if (tok == '(') {
848 next_nomacro();
849 ps = &first;
850 while (tok != ')') {
851 varg = tok;
852 next_nomacro();
853 is_vaargs = 0;
854 if (varg == TOK_DOTS) {
855 varg = TOK___VA_ARGS__;
856 is_vaargs = 1;
857 } else if (tok == TOK_DOTS && gnu_ext) {
858 is_vaargs = 1;
859 next_nomacro();
861 if (varg < TOK_IDENT)
862 error("badly punctuated parameter list");
863 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
864 *ps = s;
865 ps = &s->next;
866 if (tok != ',')
867 break;
868 next_nomacro();
870 if (tok == ')')
871 next_nomacro_spc();
872 t = MACRO_FUNC;
874 tok_str_new(&str);
875 spc = 2;
876 /* EOF testing necessary for '-D' handling */
877 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
878 /* remove spaces around ## and after '#' */
879 if (TOK_TWOSHARPS == tok) {
880 if (1 == spc)
881 --str.len;
882 spc = 2;
883 } else if ('#' == tok) {
884 spc = 2;
885 } else if (check_space(tok, &spc)) {
886 goto skip;
888 tok_str_add2(&str, tok, &tokc);
889 skip:
890 next_nomacro_spc();
892 if (spc == 1)
893 --str.len; /* remove trailing space */
894 tok_str_add(&str, 0);
895 #ifdef PP_DEBUG
896 printf("define %s %d: ", get_tok_str(v, NULL), t);
897 tok_print(str.str);
898 #endif
899 define_push(v, t, str.str, first);
902 static inline int hash_cached_include(int type, const char *filename)
904 const unsigned char *s;
905 unsigned int h;
907 h = TOK_HASH_INIT;
908 h = TOK_HASH_FUNC(h, type);
909 s = filename;
910 while (*s) {
911 h = TOK_HASH_FUNC(h, *s);
912 s++;
914 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
915 return h;
918 /* XXX: use a token or a hash table to accelerate matching ? */
919 static CachedInclude *search_cached_include(TCCState *s1,
920 int type, const char *filename)
922 CachedInclude *e;
923 int i, h;
924 h = hash_cached_include(type, filename);
925 i = s1->cached_includes_hash[h];
926 for(;;) {
927 if (i == 0)
928 break;
929 e = s1->cached_includes[i - 1];
930 if (e->type == type && !PATHCMP(e->filename, filename))
931 return e;
932 i = e->hash_next;
934 return NULL;
937 static inline void add_cached_include(TCCState *s1, int type,
938 const char *filename, int ifndef_macro)
940 CachedInclude *e;
941 int h;
943 if (search_cached_include(s1, type, filename))
944 return;
945 #ifdef INC_DEBUG
946 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
947 #endif
948 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
949 if (!e)
950 return;
951 e->type = type;
952 strcpy(e->filename, filename);
953 e->ifndef_macro = ifndef_macro;
954 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
955 /* add in hash table */
956 h = hash_cached_include(type, filename);
957 e->hash_next = s1->cached_includes_hash[h];
958 s1->cached_includes_hash[h] = s1->nb_cached_includes;
961 static void pragma_parse(TCCState *s1)
963 int val;
965 next();
966 if (tok == TOK_pack) {
968 This may be:
969 #pragma pack(1) // set
970 #pragma pack() // reset to default
971 #pragma pack(push,1) // push & set
972 #pragma pack(pop) // restore previous
974 next();
975 skip('(');
976 if (tok == TOK_ASM_pop) {
977 next();
978 if (s1->pack_stack_ptr <= s1->pack_stack) {
979 stk_error:
980 error("out of pack stack");
982 s1->pack_stack_ptr--;
983 } else {
984 val = 0;
985 if (tok != ')') {
986 if (tok == TOK_ASM_push) {
987 next();
988 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
989 goto stk_error;
990 s1->pack_stack_ptr++;
991 skip(',');
993 if (tok != TOK_CINT) {
994 pack_error:
995 error("invalid pack pragma");
997 val = tokc.i;
998 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
999 goto pack_error;
1000 next();
1002 *s1->pack_stack_ptr = val;
1003 skip(')');
1008 /* is_bof is true if first non space token at beginning of file */
1009 static void preprocess(int is_bof)
1011 TCCState *s1 = tcc_state;
1012 int size, i, c, n, saved_parse_flags;
1013 char buf[1024], *q;
1014 char buf1[1024];
1015 BufferedFile *f;
1016 Sym *s;
1017 CachedInclude *e;
1019 saved_parse_flags = parse_flags;
1020 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
1021 PARSE_FLAG_LINEFEED;
1022 next_nomacro();
1023 redo:
1024 switch(tok) {
1025 case TOK_DEFINE:
1026 next_nomacro();
1027 parse_define();
1028 break;
1029 case TOK_UNDEF:
1030 next_nomacro();
1031 s = define_find(tok);
1032 /* undefine symbol by putting an invalid name */
1033 if (s)
1034 define_undef(s);
1035 break;
1036 case TOK_INCLUDE:
1037 case TOK_INCLUDE_NEXT:
1038 ch = file->buf_ptr[0];
1039 /* XXX: incorrect if comments : use next_nomacro with a special mode */
1040 skip_spaces();
1041 if (ch == '<') {
1042 c = '>';
1043 goto read_name;
1044 } else if (ch == '\"') {
1045 c = ch;
1046 read_name:
1047 inp();
1048 q = buf;
1049 while (ch != c && ch != '\n' && ch != CH_EOF) {
1050 if ((q - buf) < sizeof(buf) - 1)
1051 *q++ = ch;
1052 if (ch == '\\') {
1053 if (handle_stray_noerror() == 0)
1054 --q;
1055 } else
1056 inp();
1058 *q = '\0';
1059 minp();
1060 #if 0
1061 /* eat all spaces and comments after include */
1062 /* XXX: slightly incorrect */
1063 while (ch1 != '\n' && ch1 != CH_EOF)
1064 inp();
1065 #endif
1066 } else {
1067 /* computed #include : either we have only strings or
1068 we have anything enclosed in '<>' */
1069 next();
1070 buf[0] = '\0';
1071 if (tok == TOK_STR) {
1072 while (tok != TOK_LINEFEED) {
1073 if (tok != TOK_STR) {
1074 include_syntax:
1075 error("'#include' expects \"FILENAME\" or <FILENAME>");
1077 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
1078 next();
1080 c = '\"';
1081 } else {
1082 int len;
1083 while (tok != TOK_LINEFEED) {
1084 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
1085 next();
1087 len = strlen(buf);
1088 /* check syntax and remove '<>' */
1089 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
1090 goto include_syntax;
1091 memmove(buf, buf + 1, len - 2);
1092 buf[len - 2] = '\0';
1093 c = '>';
1097 e = search_cached_include(s1, c, buf);
1098 if (e && define_find(e->ifndef_macro)) {
1099 /* no need to parse the include because the 'ifndef macro'
1100 is defined */
1101 #ifdef INC_DEBUG
1102 printf("%s: skipping %s\n", file->filename, buf);
1103 #endif
1104 } else {
1105 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
1106 error("#include recursion too deep");
1107 /* push current file in stack */
1108 /* XXX: fix current line init */
1109 *s1->include_stack_ptr++ = file;
1111 /* check absolute include path */
1112 if (IS_ABSPATH(buf)) {
1113 f = tcc_open(s1, buf);
1114 if (f)
1115 goto found;
1117 if (c == '\"') {
1118 /* first search in current dir if "header.h" */
1119 size = tcc_basename(file->filename) - file->filename;
1120 if (size > sizeof(buf1) - 1)
1121 size = sizeof(buf1) - 1;
1122 memcpy(buf1, file->filename, size);
1123 buf1[size] = '\0';
1124 pstrcat(buf1, sizeof(buf1), buf);
1125 f = tcc_open(s1, buf1);
1126 if (f) {
1127 if (tok == TOK_INCLUDE_NEXT)
1128 tok = TOK_INCLUDE;
1129 else
1130 goto found;
1133 /* now search in all the include paths */
1134 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
1135 for(i = 0; i < n; i++) {
1136 const char *path;
1137 if (i < s1->nb_include_paths)
1138 path = s1->include_paths[i];
1139 else
1140 path = s1->sysinclude_paths[i - s1->nb_include_paths];
1141 pstrcpy(buf1, sizeof(buf1), path);
1142 pstrcat(buf1, sizeof(buf1), "/");
1143 pstrcat(buf1, sizeof(buf1), buf);
1144 f = tcc_open(s1, buf1);
1145 if (f) {
1146 if (tok == TOK_INCLUDE_NEXT)
1147 tok = TOK_INCLUDE;
1148 else
1149 goto found;
1152 --s1->include_stack_ptr;
1153 error("include file '%s' not found", buf);
1154 break;
1155 found:
1156 #ifdef INC_DEBUG
1157 printf("%s: including %s\n", file->filename, buf1);
1158 #endif
1159 f->inc_type = c;
1160 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
1161 file = f;
1162 /* add include file debug info */
1163 if (do_debug) {
1164 put_stabs(file->filename, N_BINCL, 0, 0, 0);
1166 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
1167 ch = file->buf_ptr[0];
1168 goto the_end;
1170 break;
1171 case TOK_IFNDEF:
1172 c = 1;
1173 goto do_ifdef;
1174 case TOK_IF:
1175 c = expr_preprocess();
1176 goto do_if;
1177 case TOK_IFDEF:
1178 c = 0;
1179 do_ifdef:
1180 next_nomacro();
1181 if (tok < TOK_IDENT)
1182 error("invalid argument for '#if%sdef'", c ? "n" : "");
1183 if (is_bof) {
1184 if (c) {
1185 #ifdef INC_DEBUG
1186 printf("#ifndef %s\n", get_tok_str(tok, NULL));
1187 #endif
1188 file->ifndef_macro = tok;
1191 c = (define_find(tok) != 0) ^ c;
1192 do_if:
1193 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
1194 error("memory full");
1195 *s1->ifdef_stack_ptr++ = c;
1196 goto test_skip;
1197 case TOK_ELSE:
1198 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
1199 error("#else without matching #if");
1200 if (s1->ifdef_stack_ptr[-1] & 2)
1201 error("#else after #else");
1202 c = (s1->ifdef_stack_ptr[-1] ^= 3);
1203 goto test_skip;
1204 case TOK_ELIF:
1205 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
1206 error("#elif without matching #if");
1207 c = s1->ifdef_stack_ptr[-1];
1208 if (c > 1)
1209 error("#elif after #else");
1210 /* last #if/#elif expression was true: we skip */
1211 if (c == 1)
1212 goto skip;
1213 c = expr_preprocess();
1214 s1->ifdef_stack_ptr[-1] = c;
1215 test_skip:
1216 if (!(c & 1)) {
1217 skip:
1218 preprocess_skip();
1219 is_bof = 0;
1220 goto redo;
1222 break;
1223 case TOK_ENDIF:
1224 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
1225 error("#endif without matching #if");
1226 s1->ifdef_stack_ptr--;
1227 /* '#ifndef macro' was at the start of file. Now we check if
1228 an '#endif' is exactly at the end of file */
1229 if (file->ifndef_macro &&
1230 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
1231 file->ifndef_macro_saved = file->ifndef_macro;
1232 /* need to set to zero to avoid false matches if another
1233 #ifndef at middle of file */
1234 file->ifndef_macro = 0;
1235 while (tok != TOK_LINEFEED)
1236 next_nomacro();
1237 tok_flags |= TOK_FLAG_ENDIF;
1238 goto the_end;
1240 break;
1241 case TOK_LINE:
1242 next();
1243 if (tok != TOK_CINT)
1244 error("#line");
1245 file->line_num = tokc.i - 1; /* the line number will be incremented after */
1246 next();
1247 if (tok != TOK_LINEFEED) {
1248 if (tok != TOK_STR)
1249 error("#line");
1250 pstrcpy(file->filename, sizeof(file->filename),
1251 (char *)tokc.cstr->data);
1253 break;
1254 case TOK_ERROR:
1255 case TOK_WARNING:
1256 c = tok;
1257 ch = file->buf_ptr[0];
1258 skip_spaces();
1259 q = buf;
1260 while (ch != '\n' && ch != CH_EOF) {
1261 if ((q - buf) < sizeof(buf) - 1)
1262 *q++ = ch;
1263 if (ch == '\\') {
1264 if (handle_stray_noerror() == 0)
1265 --q;
1266 } else
1267 inp();
1269 *q = '\0';
1270 if (c == TOK_ERROR)
1271 error("#error %s", buf);
1272 else
1273 warning("#warning %s", buf);
1274 break;
1275 case TOK_PRAGMA:
1276 pragma_parse(s1);
1277 break;
1278 default:
1279 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
1280 /* '!' is ignored to allow C scripts. numbers are ignored
1281 to emulate cpp behaviour */
1282 } else {
1283 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
1284 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
1286 break;
1288 /* ignore other preprocess commands or #! for C scripts */
1289 while (tok != TOK_LINEFEED)
1290 next_nomacro();
1291 the_end:
1292 parse_flags = saved_parse_flags;
1295 /* evaluate escape codes in a string. */
1296 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
1298 int c, n;
1299 const uint8_t *p;
1301 p = buf;
1302 for(;;) {
1303 c = *p;
1304 if (c == '\0')
1305 break;
1306 if (c == '\\') {
1307 p++;
1308 /* escape */
1309 c = *p;
1310 switch(c) {
1311 case '0': case '1': case '2': case '3':
1312 case '4': case '5': case '6': case '7':
1313 /* at most three octal digits */
1314 n = c - '0';
1315 p++;
1316 c = *p;
1317 if (isoct(c)) {
1318 n = n * 8 + c - '0';
1319 p++;
1320 c = *p;
1321 if (isoct(c)) {
1322 n = n * 8 + c - '0';
1323 p++;
1326 c = n;
1327 goto add_char_nonext;
1328 case 'x':
1329 case 'u':
1330 case 'U':
1331 p++;
1332 n = 0;
1333 for(;;) {
1334 c = *p;
1335 if (c >= 'a' && c <= 'f')
1336 c = c - 'a' + 10;
1337 else if (c >= 'A' && c <= 'F')
1338 c = c - 'A' + 10;
1339 else if (isnum(c))
1340 c = c - '0';
1341 else
1342 break;
1343 n = n * 16 + c;
1344 p++;
1346 c = n;
1347 goto add_char_nonext;
1348 case 'a':
1349 c = '\a';
1350 break;
1351 case 'b':
1352 c = '\b';
1353 break;
1354 case 'f':
1355 c = '\f';
1356 break;
1357 case 'n':
1358 c = '\n';
1359 break;
1360 case 'r':
1361 c = '\r';
1362 break;
1363 case 't':
1364 c = '\t';
1365 break;
1366 case 'v':
1367 c = '\v';
1368 break;
1369 case 'e':
1370 if (!gnu_ext)
1371 goto invalid_escape;
1372 c = 27;
1373 break;
1374 case '\'':
1375 case '\"':
1376 case '\\':
1377 case '?':
1378 break;
1379 default:
1380 invalid_escape:
1381 if (c >= '!' && c <= '~')
1382 warning("unknown escape sequence: \'\\%c\'", c);
1383 else
1384 warning("unknown escape sequence: \'\\x%x\'", c);
1385 break;
1388 p++;
1389 add_char_nonext:
1390 if (!is_long)
1391 cstr_ccat(outstr, c);
1392 else
1393 cstr_wccat(outstr, c);
1395 /* add a trailing '\0' */
1396 if (!is_long)
1397 cstr_ccat(outstr, '\0');
1398 else
1399 cstr_wccat(outstr, '\0');
1402 /* we use 64 bit numbers */
1403 #define BN_SIZE 2
1405 /* bn = (bn << shift) | or_val */
1406 void bn_lshift(unsigned int *bn, int shift, int or_val)
1408 int i;
1409 unsigned int v;
1410 for(i=0;i<BN_SIZE;i++) {
1411 v = bn[i];
1412 bn[i] = (v << shift) | or_val;
1413 or_val = v >> (32 - shift);
1417 void bn_zero(unsigned int *bn)
1419 int i;
1420 for(i=0;i<BN_SIZE;i++) {
1421 bn[i] = 0;
1425 /* parse number in null terminated string 'p' and return it in the
1426 current token */
1427 void parse_number(const char *p)
1429 int b, t, shift, frac_bits, s, exp_val, ch;
1430 char *q;
1431 unsigned int bn[BN_SIZE];
1432 double d;
1434 /* number */
1435 q = token_buf;
1436 ch = *p++;
1437 t = ch;
1438 ch = *p++;
1439 *q++ = t;
1440 b = 10;
1441 if (t == '.') {
1442 goto float_frac_parse;
1443 } else if (t == '0') {
1444 if (ch == 'x' || ch == 'X') {
1445 q--;
1446 ch = *p++;
1447 b = 16;
1448 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
1449 q--;
1450 ch = *p++;
1451 b = 2;
1454 /* parse all digits. cannot check octal numbers at this stage
1455 because of floating point constants */
1456 while (1) {
1457 if (ch >= 'a' && ch <= 'f')
1458 t = ch - 'a' + 10;
1459 else if (ch >= 'A' && ch <= 'F')
1460 t = ch - 'A' + 10;
1461 else if (isnum(ch))
1462 t = ch - '0';
1463 else
1464 break;
1465 if (t >= b)
1466 break;
1467 if (q >= token_buf + STRING_MAX_SIZE) {
1468 num_too_long:
1469 error("number too long");
1471 *q++ = ch;
1472 ch = *p++;
1474 if (ch == '.' ||
1475 ((ch == 'e' || ch == 'E') && b == 10) ||
1476 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
1477 if (b != 10) {
1478 /* NOTE: strtox should support that for hexa numbers, but
1479 non ISOC99 libcs do not support it, so we prefer to do
1480 it by hand */
1481 /* hexadecimal or binary floats */
1482 /* XXX: handle overflows */
1483 *q = '\0';
1484 if (b == 16)
1485 shift = 4;
1486 else
1487 shift = 2;
1488 bn_zero(bn);
1489 q = token_buf;
1490 while (1) {
1491 t = *q++;
1492 if (t == '\0') {
1493 break;
1494 } else if (t >= 'a') {
1495 t = t - 'a' + 10;
1496 } else if (t >= 'A') {
1497 t = t - 'A' + 10;
1498 } else {
1499 t = t - '0';
1501 bn_lshift(bn, shift, t);
1503 frac_bits = 0;
1504 if (ch == '.') {
1505 ch = *p++;
1506 while (1) {
1507 t = ch;
1508 if (t >= 'a' && t <= 'f') {
1509 t = t - 'a' + 10;
1510 } else if (t >= 'A' && t <= 'F') {
1511 t = t - 'A' + 10;
1512 } else if (t >= '0' && t <= '9') {
1513 t = t - '0';
1514 } else {
1515 break;
1517 if (t >= b)
1518 error("invalid digit");
1519 bn_lshift(bn, shift, t);
1520 frac_bits += shift;
1521 ch = *p++;
1524 if (ch != 'p' && ch != 'P')
1525 expect("exponent");
1526 ch = *p++;
1527 s = 1;
1528 exp_val = 0;
1529 if (ch == '+') {
1530 ch = *p++;
1531 } else if (ch == '-') {
1532 s = -1;
1533 ch = *p++;
1535 if (ch < '0' || ch > '9')
1536 expect("exponent digits");
1537 while (ch >= '0' && ch <= '9') {
1538 exp_val = exp_val * 10 + ch - '0';
1539 ch = *p++;
1541 exp_val = exp_val * s;
1543 /* now we can generate the number */
1544 /* XXX: should patch directly float number */
1545 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
1546 d = ldexp(d, exp_val - frac_bits);
1547 t = toup(ch);
1548 if (t == 'F') {
1549 ch = *p++;
1550 tok = TOK_CFLOAT;
1551 /* float : should handle overflow */
1552 tokc.f = (float)d;
1553 } else if (t == 'L') {
1554 ch = *p++;
1555 tok = TOK_CLDOUBLE;
1556 /* XXX: not large enough */
1557 tokc.ld = (long double)d;
1558 } else {
1559 tok = TOK_CDOUBLE;
1560 tokc.d = d;
1562 } else {
1563 /* decimal floats */
1564 if (ch == '.') {
1565 if (q >= token_buf + STRING_MAX_SIZE)
1566 goto num_too_long;
1567 *q++ = ch;
1568 ch = *p++;
1569 float_frac_parse:
1570 while (ch >= '0' && ch <= '9') {
1571 if (q >= token_buf + STRING_MAX_SIZE)
1572 goto num_too_long;
1573 *q++ = ch;
1574 ch = *p++;
1577 if (ch == 'e' || ch == 'E') {
1578 if (q >= token_buf + STRING_MAX_SIZE)
1579 goto num_too_long;
1580 *q++ = ch;
1581 ch = *p++;
1582 if (ch == '-' || ch == '+') {
1583 if (q >= token_buf + STRING_MAX_SIZE)
1584 goto num_too_long;
1585 *q++ = ch;
1586 ch = *p++;
1588 if (ch < '0' || ch > '9')
1589 expect("exponent digits");
1590 while (ch >= '0' && ch <= '9') {
1591 if (q >= token_buf + STRING_MAX_SIZE)
1592 goto num_too_long;
1593 *q++ = ch;
1594 ch = *p++;
1597 *q = '\0';
1598 t = toup(ch);
1599 errno = 0;
1600 if (t == 'F') {
1601 ch = *p++;
1602 tok = TOK_CFLOAT;
1603 tokc.f = strtof(token_buf, NULL);
1604 } else if (t == 'L') {
1605 ch = *p++;
1606 tok = TOK_CLDOUBLE;
1607 tokc.ld = strtold(token_buf, NULL);
1608 } else {
1609 tok = TOK_CDOUBLE;
1610 tokc.d = strtod(token_buf, NULL);
1613 } else {
1614 unsigned long long n, n1;
1615 int lcount, ucount;
1617 /* integer number */
1618 *q = '\0';
1619 q = token_buf;
1620 if (b == 10 && *q == '0') {
1621 b = 8;
1622 q++;
1624 n = 0;
1625 while(1) {
1626 t = *q++;
1627 /* no need for checks except for base 10 / 8 errors */
1628 if (t == '\0') {
1629 break;
1630 } else if (t >= 'a') {
1631 t = t - 'a' + 10;
1632 } else if (t >= 'A') {
1633 t = t - 'A' + 10;
1634 } else {
1635 t = t - '0';
1636 if (t >= b)
1637 error("invalid digit");
1639 n1 = n;
1640 n = n * b + t;
1641 /* detect overflow */
1642 /* XXX: this test is not reliable */
1643 if (n < n1)
1644 error("integer constant overflow");
1647 /* XXX: not exactly ANSI compliant */
1648 if ((n & 0xffffffff00000000LL) != 0) {
1649 if ((n >> 63) != 0)
1650 tok = TOK_CULLONG;
1651 else
1652 tok = TOK_CLLONG;
1653 } else if (n > 0x7fffffff) {
1654 tok = TOK_CUINT;
1655 } else {
1656 tok = TOK_CINT;
1658 lcount = 0;
1659 ucount = 0;
1660 for(;;) {
1661 t = toup(ch);
1662 if (t == 'L') {
1663 if (lcount >= 2)
1664 error("three 'l's in integer constant");
1665 lcount++;
1666 if (lcount == 2) {
1667 if (tok == TOK_CINT)
1668 tok = TOK_CLLONG;
1669 else if (tok == TOK_CUINT)
1670 tok = TOK_CULLONG;
1672 ch = *p++;
1673 } else if (t == 'U') {
1674 if (ucount >= 1)
1675 error("two 'u's in integer constant");
1676 ucount++;
1677 if (tok == TOK_CINT)
1678 tok = TOK_CUINT;
1679 else if (tok == TOK_CLLONG)
1680 tok = TOK_CULLONG;
1681 ch = *p++;
1682 } else {
1683 break;
1686 if (tok == TOK_CINT || tok == TOK_CUINT)
1687 tokc.ui = n;
1688 else
1689 tokc.ull = n;
1691 if (ch)
1692 error("invalid number\n");
1696 #define PARSE2(c1, tok1, c2, tok2) \
1697 case c1: \
1698 PEEKC(c, p); \
1699 if (c == c2) { \
1700 p++; \
1701 tok = tok2; \
1702 } else { \
1703 tok = tok1; \
1705 break;
1707 /* return next token without macro substitution */
1708 static inline void next_nomacro1(void)
1710 int t, c, is_long;
1711 TokenSym *ts;
1712 uint8_t *p, *p1;
1713 unsigned int h;
1715 p = file->buf_ptr;
1716 redo_no_start:
1717 c = *p;
1718 switch(c) {
1719 case ' ':
1720 case '\t':
1721 tok = c;
1722 p++;
1723 goto keep_tok_flags;
1724 case '\f':
1725 case '\v':
1726 case '\r':
1727 p++;
1728 goto redo_no_start;
1729 case '\\':
1730 /* first look if it is in fact an end of buffer */
1731 if (p >= file->buf_end) {
1732 file->buf_ptr = p;
1733 handle_eob();
1734 p = file->buf_ptr;
1735 if (p >= file->buf_end)
1736 goto parse_eof;
1737 else
1738 goto redo_no_start;
1739 } else {
1740 file->buf_ptr = p;
1741 ch = *p;
1742 handle_stray();
1743 p = file->buf_ptr;
1744 goto redo_no_start;
1746 parse_eof:
1748 TCCState *s1 = tcc_state;
1749 if ((parse_flags & PARSE_FLAG_LINEFEED)
1750 && !(tok_flags & TOK_FLAG_EOF)) {
1751 tok_flags |= TOK_FLAG_EOF;
1752 tok = TOK_LINEFEED;
1753 goto keep_tok_flags;
1754 } else if (s1->include_stack_ptr == s1->include_stack ||
1755 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
1756 /* no include left : end of file. */
1757 tok = TOK_EOF;
1758 } else {
1759 tok_flags &= ~TOK_FLAG_EOF;
1760 /* pop include file */
1762 /* test if previous '#endif' was after a #ifdef at
1763 start of file */
1764 if (tok_flags & TOK_FLAG_ENDIF) {
1765 #ifdef INC_DEBUG
1766 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
1767 #endif
1768 add_cached_include(s1, file->inc_type, file->inc_filename,
1769 file->ifndef_macro_saved);
1772 /* add end of include file debug info */
1773 if (do_debug) {
1774 put_stabd(N_EINCL, 0, 0);
1776 /* pop include stack */
1777 tcc_close(file);
1778 s1->include_stack_ptr--;
1779 file = *s1->include_stack_ptr;
1780 p = file->buf_ptr;
1781 goto redo_no_start;
1784 break;
1786 case '\n':
1787 file->line_num++;
1788 tok_flags |= TOK_FLAG_BOL;
1789 p++;
1790 if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
1791 goto redo_no_start;
1792 tok = TOK_LINEFEED;
1793 goto keep_tok_flags;
1795 case '#':
1796 /* XXX: simplify */
1797 PEEKC(c, p);
1798 if ((tok_flags & TOK_FLAG_BOL) &&
1799 (parse_flags & PARSE_FLAG_PREPROCESS)) {
1800 file->buf_ptr = p;
1801 preprocess(tok_flags & TOK_FLAG_BOF);
1802 p = file->buf_ptr;
1803 goto redo_no_start;
1804 } else {
1805 if (c == '#') {
1806 p++;
1807 tok = TOK_TWOSHARPS;
1808 } else {
1809 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
1810 p = parse_line_comment(p - 1);
1811 goto redo_no_start;
1812 } else {
1813 tok = '#';
1817 break;
1819 case 'a': case 'b': case 'c': case 'd':
1820 case 'e': case 'f': case 'g': case 'h':
1821 case 'i': case 'j': case 'k': case 'l':
1822 case 'm': case 'n': case 'o': case 'p':
1823 case 'q': case 'r': case 's': case 't':
1824 case 'u': case 'v': case 'w': case 'x':
1825 case 'y': case 'z':
1826 case 'A': case 'B': case 'C': case 'D':
1827 case 'E': case 'F': case 'G': case 'H':
1828 case 'I': case 'J': case 'K':
1829 case 'M': case 'N': case 'O': case 'P':
1830 case 'Q': case 'R': case 'S': case 'T':
1831 case 'U': case 'V': case 'W': case 'X':
1832 case 'Y': case 'Z':
1833 case '_':
1834 parse_ident_fast:
1835 p1 = p;
1836 h = TOK_HASH_INIT;
1837 h = TOK_HASH_FUNC(h, c);
1838 p++;
1839 for(;;) {
1840 c = *p;
1841 if (!isidnum_table[c-CH_EOF])
1842 break;
1843 h = TOK_HASH_FUNC(h, c);
1844 p++;
1846 if (c != '\\') {
1847 TokenSym **pts;
1848 int len;
1850 /* fast case : no stray found, so we have the full token
1851 and we have already hashed it */
1852 len = p - p1;
1853 h &= (TOK_HASH_SIZE - 1);
1854 pts = &hash_ident[h];
1855 for(;;) {
1856 ts = *pts;
1857 if (!ts)
1858 break;
1859 if (ts->len == len && !memcmp(ts->str, p1, len))
1860 goto token_found;
1861 pts = &(ts->hash_next);
1863 ts = tok_alloc_new(pts, p1, len);
1864 token_found: ;
1865 } else {
1866 /* slower case */
1867 cstr_reset(&tokcstr);
1869 while (p1 < p) {
1870 cstr_ccat(&tokcstr, *p1);
1871 p1++;
1873 p--;
1874 PEEKC(c, p);
1875 parse_ident_slow:
1876 while (isidnum_table[c-CH_EOF]) {
1877 cstr_ccat(&tokcstr, c);
1878 PEEKC(c, p);
1880 ts = tok_alloc(tokcstr.data, tokcstr.size);
1882 tok = ts->tok;
1883 break;
1884 case 'L':
1885 t = p[1];
1886 if (t != '\\' && t != '\'' && t != '\"') {
1887 /* fast case */
1888 goto parse_ident_fast;
1889 } else {
1890 PEEKC(c, p);
1891 if (c == '\'' || c == '\"') {
1892 is_long = 1;
1893 goto str_const;
1894 } else {
1895 cstr_reset(&tokcstr);
1896 cstr_ccat(&tokcstr, 'L');
1897 goto parse_ident_slow;
1900 break;
1901 case '0': case '1': case '2': case '3':
1902 case '4': case '5': case '6': case '7':
1903 case '8': case '9':
1905 cstr_reset(&tokcstr);
1906 /* after the first digit, accept digits, alpha, '.' or sign if
1907 prefixed by 'eEpP' */
1908 parse_num:
1909 for(;;) {
1910 t = c;
1911 cstr_ccat(&tokcstr, c);
1912 PEEKC(c, p);
1913 if (!(isnum(c) || isid(c) || c == '.' ||
1914 ((c == '+' || c == '-') &&
1915 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
1916 break;
1918 /* We add a trailing '\0' to ease parsing */
1919 cstr_ccat(&tokcstr, '\0');
1920 tokc.cstr = &tokcstr;
1921 tok = TOK_PPNUM;
1922 break;
1923 case '.':
1924 /* special dot handling because it can also start a number */
1925 PEEKC(c, p);
1926 if (isnum(c)) {
1927 cstr_reset(&tokcstr);
1928 cstr_ccat(&tokcstr, '.');
1929 goto parse_num;
1930 } else if (c == '.') {
1931 PEEKC(c, p);
1932 if (c != '.')
1933 expect("'.'");
1934 PEEKC(c, p);
1935 tok = TOK_DOTS;
1936 } else {
1937 tok = '.';
1939 break;
1940 case '\'':
1941 case '\"':
1942 is_long = 0;
1943 str_const:
1945 CString str;
1946 int sep;
1948 sep = c;
1950 /* parse the string */
1951 cstr_new(&str);
1952 p = parse_pp_string(p, sep, &str);
1953 cstr_ccat(&str, '\0');
1955 /* eval the escape (should be done as TOK_PPNUM) */
1956 cstr_reset(&tokcstr);
1957 parse_escape_string(&tokcstr, str.data, is_long);
1958 cstr_free(&str);
1960 if (sep == '\'') {
1961 int char_size;
1962 /* XXX: make it portable */
1963 if (!is_long)
1964 char_size = 1;
1965 else
1966 char_size = sizeof(nwchar_t);
1967 if (tokcstr.size <= char_size)
1968 error("empty character constant");
1969 if (tokcstr.size > 2 * char_size)
1970 warning("multi-character character constant");
1971 if (!is_long) {
1972 tokc.i = *(int8_t *)tokcstr.data;
1973 tok = TOK_CCHAR;
1974 } else {
1975 tokc.i = *(nwchar_t *)tokcstr.data;
1976 tok = TOK_LCHAR;
1978 } else {
1979 tokc.cstr = &tokcstr;
1980 if (!is_long)
1981 tok = TOK_STR;
1982 else
1983 tok = TOK_LSTR;
1986 break;
1988 case '<':
1989 PEEKC(c, p);
1990 if (c == '=') {
1991 p++;
1992 tok = TOK_LE;
1993 } else if (c == '<') {
1994 PEEKC(c, p);
1995 if (c == '=') {
1996 p++;
1997 tok = TOK_A_SHL;
1998 } else {
1999 tok = TOK_SHL;
2001 } else {
2002 tok = TOK_LT;
2004 break;
2006 case '>':
2007 PEEKC(c, p);
2008 if (c == '=') {
2009 p++;
2010 tok = TOK_GE;
2011 } else if (c == '>') {
2012 PEEKC(c, p);
2013 if (c == '=') {
2014 p++;
2015 tok = TOK_A_SAR;
2016 } else {
2017 tok = TOK_SAR;
2019 } else {
2020 tok = TOK_GT;
2022 break;
2024 case '&':
2025 PEEKC(c, p);
2026 if (c == '&') {
2027 p++;
2028 tok = TOK_LAND;
2029 } else if (c == '=') {
2030 p++;
2031 tok = TOK_A_AND;
2032 } else {
2033 tok = '&';
2035 break;
2037 case '|':
2038 PEEKC(c, p);
2039 if (c == '|') {
2040 p++;
2041 tok = TOK_LOR;
2042 } else if (c == '=') {
2043 p++;
2044 tok = TOK_A_OR;
2045 } else {
2046 tok = '|';
2048 break;
2050 case '+':
2051 PEEKC(c, p);
2052 if (c == '+') {
2053 p++;
2054 tok = TOK_INC;
2055 } else if (c == '=') {
2056 p++;
2057 tok = TOK_A_ADD;
2058 } else {
2059 tok = '+';
2061 break;
2063 case '-':
2064 PEEKC(c, p);
2065 if (c == '-') {
2066 p++;
2067 tok = TOK_DEC;
2068 } else if (c == '=') {
2069 p++;
2070 tok = TOK_A_SUB;
2071 } else if (c == '>') {
2072 p++;
2073 tok = TOK_ARROW;
2074 } else {
2075 tok = '-';
2077 break;
2079 PARSE2('!', '!', '=', TOK_NE)
2080 PARSE2('=', '=', '=', TOK_EQ)
2081 PARSE2('*', '*', '=', TOK_A_MUL)
2082 PARSE2('%', '%', '=', TOK_A_MOD)
2083 PARSE2('^', '^', '=', TOK_A_XOR)
2085 /* comments or operator */
2086 case '/':
2087 PEEKC(c, p);
2088 if (c == '*') {
2089 p = parse_comment(p);
2090 goto redo_no_start;
2091 } else if (c == '/') {
2092 p = parse_line_comment(p);
2093 goto redo_no_start;
2094 } else if (c == '=') {
2095 p++;
2096 tok = TOK_A_DIV;
2097 } else {
2098 tok = '/';
2100 break;
2102 /* simple tokens */
2103 case '(':
2104 case ')':
2105 case '[':
2106 case ']':
2107 case '{':
2108 case '}':
2109 case ',':
2110 case ';':
2111 case ':':
2112 case '?':
2113 case '~':
2114 case '$': /* only used in assembler */
2115 case '@': /* dito */
2116 tok = c;
2117 p++;
2118 break;
2119 default:
2120 error("unrecognized character \\x%02x", c);
2121 break;
2123 tok_flags = 0;
2124 keep_tok_flags:
2125 file->buf_ptr = p;
2126 #if defined(PARSE_DEBUG)
2127 printf("token = %s\n", get_tok_str(tok, &tokc));
2128 #endif
2131 /* return next token without macro substitution. Can read input from
2132 macro_ptr buffer */
2133 static void next_nomacro_spc(void)
2135 if (macro_ptr) {
2136 redo:
2137 tok = *macro_ptr;
2138 if (tok) {
2139 TOK_GET(tok, macro_ptr, tokc);
2140 if (tok == TOK_LINENUM) {
2141 file->line_num = tokc.i;
2142 goto redo;
2145 } else {
2146 next_nomacro1();
2150 static void next_nomacro(void)
2152 do {
2153 next_nomacro_spc();
2154 } while (is_space(tok));
2157 /* substitute args in macro_str and return allocated string */
2158 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
2160 int *st, last_tok, t, spc;
2161 Sym *s;
2162 CValue cval;
2163 TokenString str;
2164 CString cstr;
2166 tok_str_new(&str);
2167 last_tok = 0;
2168 while(1) {
2169 TOK_GET(t, macro_str, cval);
2170 if (!t)
2171 break;
2172 if (t == '#') {
2173 /* stringize */
2174 TOK_GET(t, macro_str, cval);
2175 if (!t)
2176 break;
2177 s = sym_find2(args, t);
2178 if (s) {
2179 cstr_new(&cstr);
2180 st = (int *)s->c;
2181 spc = 0;
2182 while (*st) {
2183 TOK_GET(t, st, cval);
2184 if (!check_space(t, &spc))
2185 cstr_cat(&cstr, get_tok_str(t, &cval));
2187 cstr.size -= spc;
2188 cstr_ccat(&cstr, '\0');
2189 #ifdef PP_DEBUG
2190 printf("stringize: %s\n", (char *)cstr.data);
2191 #endif
2192 /* add string */
2193 cval.cstr = &cstr;
2194 tok_str_add2(&str, TOK_STR, &cval);
2195 cstr_free(&cstr);
2196 } else {
2197 tok_str_add2(&str, t, &cval);
2199 } else if (t >= TOK_IDENT) {
2200 s = sym_find2(args, t);
2201 if (s) {
2202 st = (int *)s->c;
2203 /* if '##' is present before or after, no arg substitution */
2204 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
2205 /* special case for var arg macros : ## eats the
2206 ',' if empty VA_ARGS variable. */
2207 /* XXX: test of the ',' is not 100%
2208 reliable. should fix it to avoid security
2209 problems */
2210 if (gnu_ext && s->type.t &&
2211 last_tok == TOK_TWOSHARPS &&
2212 str.len >= 2 && str.str[str.len - 2] == ',') {
2213 if (*st == 0) {
2214 /* suppress ',' '##' */
2215 str.len -= 2;
2216 } else {
2217 /* suppress '##' and add variable */
2218 str.len--;
2219 goto add_var;
2221 } else {
2222 int t1;
2223 add_var:
2224 for(;;) {
2225 TOK_GET(t1, st, cval);
2226 if (!t1)
2227 break;
2228 tok_str_add2(&str, t1, &cval);
2231 } else {
2232 /* NOTE: the stream cannot be read when macro
2233 substituing an argument */
2234 macro_subst(&str, nested_list, st, NULL);
2236 } else {
2237 tok_str_add(&str, t);
2239 } else {
2240 tok_str_add2(&str, t, &cval);
2242 last_tok = t;
2244 tok_str_add(&str, 0);
2245 return str.str;
2248 static char const ab_month_name[12][4] =
2250 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
2251 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
2254 /* do macro substitution of current token with macro 's' and add
2255 result to (tok_str,tok_len). 'nested_list' is the list of all
2256 macros we got inside to avoid recursing. Return non zero if no
2257 substitution needs to be done */
2258 static int macro_subst_tok(TokenString *tok_str,
2259 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
2261 Sym *args, *sa, *sa1;
2262 int mstr_allocated, parlevel, *mstr, t, t1, *p, spc;
2263 TokenString str;
2264 char *cstrval;
2265 CValue cval;
2266 CString cstr;
2267 char buf[32];
2269 /* if symbol is a macro, prepare substitution */
2270 /* special macros */
2271 if (tok == TOK___LINE__) {
2272 snprintf(buf, sizeof(buf), "%d", file->line_num);
2273 cstrval = buf;
2274 t1 = TOK_PPNUM;
2275 goto add_cstr1;
2276 } else if (tok == TOK___FILE__) {
2277 cstrval = file->filename;
2278 goto add_cstr;
2279 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
2280 time_t ti;
2281 struct tm *tm;
2283 time(&ti);
2284 tm = localtime(&ti);
2285 if (tok == TOK___DATE__) {
2286 snprintf(buf, sizeof(buf), "%s %2d %d",
2287 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
2288 } else {
2289 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
2290 tm->tm_hour, tm->tm_min, tm->tm_sec);
2292 cstrval = buf;
2293 add_cstr:
2294 t1 = TOK_STR;
2295 add_cstr1:
2296 cstr_new(&cstr);
2297 cstr_cat(&cstr, cstrval);
2298 cstr_ccat(&cstr, '\0');
2299 cval.cstr = &cstr;
2300 tok_str_add2(tok_str, t1, &cval);
2301 cstr_free(&cstr);
2302 } else {
2303 mstr = (int *)s->c;
2304 mstr_allocated = 0;
2305 if (s->type.t == MACRO_FUNC) {
2306 /* NOTE: we do not use next_nomacro to avoid eating the
2307 next token. XXX: find better solution */
2308 redo:
2309 if (macro_ptr) {
2310 p = macro_ptr;
2311 while (is_space(t = *p) || TOK_LINEFEED == t)
2312 ++p;
2313 if (t == 0 && can_read_stream) {
2314 /* end of macro stream: we must look at the token
2315 after in the file */
2316 struct macro_level *ml = *can_read_stream;
2317 macro_ptr = NULL;
2318 if (ml)
2320 macro_ptr = ml->p;
2321 ml->p = NULL;
2322 *can_read_stream = ml -> prev;
2324 goto redo;
2326 } else {
2327 /* XXX: incorrect with comments */
2328 ch = file->buf_ptr[0];
2329 while (is_space(ch) || ch == '\n')
2330 cinp();
2331 t = ch;
2333 if (t != '(') /* no macro subst */
2334 return -1;
2336 /* argument macro */
2337 next_nomacro();
2338 next_nomacro();
2339 args = NULL;
2340 sa = s->next;
2341 /* NOTE: empty args are allowed, except if no args */
2342 for(;;) {
2343 /* handle '()' case */
2344 if (!args && !sa && tok == ')')
2345 break;
2346 if (!sa)
2347 error("macro '%s' used with too many args",
2348 get_tok_str(s->v, 0));
2349 tok_str_new(&str);
2350 parlevel = spc = 0;
2351 /* NOTE: non zero sa->t indicates VA_ARGS */
2352 while ((parlevel > 0 ||
2353 (tok != ')' &&
2354 (tok != ',' || sa->type.t))) &&
2355 tok != -1) {
2356 if (tok == '(')
2357 parlevel++;
2358 else if (tok == ')')
2359 parlevel--;
2360 if (tok == TOK_LINEFEED)
2361 tok = ' ';
2362 if (!check_space(tok, &spc))
2363 tok_str_add2(&str, tok, &tokc);
2364 next_nomacro_spc();
2366 str.len -= spc;
2367 tok_str_add(&str, 0);
2368 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str);
2369 sa = sa->next;
2370 if (tok == ')') {
2371 /* special case for gcc var args: add an empty
2372 var arg argument if it is omitted */
2373 if (sa && sa->type.t && gnu_ext)
2374 continue;
2375 else
2376 break;
2378 if (tok != ',')
2379 expect(",");
2380 next_nomacro();
2382 if (sa) {
2383 error("macro '%s' used with too few args",
2384 get_tok_str(s->v, 0));
2387 /* now subst each arg */
2388 mstr = macro_arg_subst(nested_list, mstr, args);
2389 /* free memory */
2390 sa = args;
2391 while (sa) {
2392 sa1 = sa->prev;
2393 tok_str_free((int *)sa->c);
2394 sym_free(sa);
2395 sa = sa1;
2397 mstr_allocated = 1;
2399 sym_push2(nested_list, s->v, 0, 0);
2400 macro_subst(tok_str, nested_list, mstr, can_read_stream);
2401 /* pop nested defined symbol */
2402 sa1 = *nested_list;
2403 *nested_list = sa1->prev;
2404 sym_free(sa1);
2405 if (mstr_allocated)
2406 tok_str_free(mstr);
2408 return 0;
2411 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
2412 return the resulting string (which must be freed). */
2413 static inline int *macro_twosharps(const int *macro_str)
2415 TokenSym *ts;
2416 const int *ptr, *saved_macro_ptr;
2417 int t;
2418 const char *p1, *p2;
2419 CValue cval;
2420 TokenString macro_str1;
2421 CString cstr;
2423 /* we search the first '##' */
2424 for(ptr = macro_str;;) {
2425 TOK_GET(t, ptr, cval);
2426 if (t == TOK_TWOSHARPS)
2427 break;
2428 /* nothing more to do if end of string */
2429 if (t == 0)
2430 return NULL;
2433 /* we saw '##', so we need more processing to handle it */
2434 cstr_new(&cstr);
2435 tok_str_new(&macro_str1);
2436 saved_macro_ptr = macro_ptr;
2437 /* XXX: get rid of the use of macro_ptr here */
2438 macro_ptr = (int *)macro_str;
2439 for(;;) {
2440 next_nomacro_spc();
2441 if (tok == 0)
2442 break;
2443 if (tok == TOK_TWOSHARPS)
2444 continue;
2445 while (*macro_ptr == TOK_TWOSHARPS) {
2446 t = *++macro_ptr;
2447 if (t && t != TOK_TWOSHARPS) {
2448 TOK_GET(t, macro_ptr, cval);
2449 /* We concatenate the two tokens if we have an
2450 identifier or a preprocessing number */
2451 cstr_reset(&cstr);
2452 p1 = get_tok_str(tok, &tokc);
2453 cstr_cat(&cstr, p1);
2454 p2 = get_tok_str(t, &cval);
2455 cstr_cat(&cstr, p2);
2456 cstr_ccat(&cstr, '\0');
2458 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
2459 (t >= TOK_IDENT || t == TOK_PPNUM)) {
2460 if (tok == TOK_PPNUM) {
2461 /* if number, then create a number token */
2462 /* NOTE: no need to allocate because
2463 tok_str_add2() does it */
2464 cstr_reset(&tokcstr);
2465 tokcstr = cstr;
2466 cstr_new(&cstr);
2467 tokc.cstr = &tokcstr;
2468 } else {
2469 /* if identifier, we must do a test to
2470 validate we have a correct identifier */
2471 if (t == TOK_PPNUM) {
2472 const char *p;
2473 int c;
2475 p = p2;
2476 for(;;) {
2477 c = *p;
2478 if (c == '\0')
2479 break;
2480 p++;
2481 if (!isnum(c) && !isid(c))
2482 goto error_pasting;
2485 ts = tok_alloc(cstr.data, strlen(cstr.data));
2486 tok = ts->tok; /* modify current token */
2488 } else {
2489 const char *str = cstr.data;
2490 const unsigned char *q;
2492 /* we look for a valid token */
2493 /* XXX: do more extensive checks */
2494 if (!strcmp(str, ">>=")) {
2495 tok = TOK_A_SAR;
2496 } else if (!strcmp(str, "<<=")) {
2497 tok = TOK_A_SHL;
2498 } else if (strlen(str) == 2) {
2499 /* search in two bytes table */
2500 q = tok_two_chars;
2501 for(;;) {
2502 if (!*q)
2503 goto error_pasting;
2504 if (q[0] == str[0] && q[1] == str[1])
2505 break;
2506 q += 3;
2508 tok = q[2];
2509 } else {
2510 error_pasting:
2511 /* NOTE: because get_tok_str use a static buffer,
2512 we must save it */
2513 cstr_reset(&cstr);
2514 p1 = get_tok_str(tok, &tokc);
2515 cstr_cat(&cstr, p1);
2516 cstr_ccat(&cstr, '\0');
2517 p2 = get_tok_str(t, &cval);
2518 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
2519 /* cannot merge tokens: just add them separately */
2520 tok_str_add2(&macro_str1, tok, &tokc);
2521 /* XXX: free associated memory ? */
2522 tok = t;
2523 tokc = cval;
2528 tok_str_add2(&macro_str1, tok, &tokc);
2530 macro_ptr = (int *)saved_macro_ptr;
2531 cstr_free(&cstr);
2532 tok_str_add(&macro_str1, 0);
2533 return macro_str1.str;
2537 /* do macro substitution of macro_str and add result to
2538 (tok_str,tok_len). 'nested_list' is the list of all macros we got
2539 inside to avoid recursing. */
2540 static void macro_subst(TokenString *tok_str, Sym **nested_list,
2541 const int *macro_str, struct macro_level ** can_read_stream)
2543 Sym *s;
2544 int *macro_str1;
2545 const int *ptr;
2546 int t, ret, spc;
2547 CValue cval;
2548 struct macro_level ml;
2550 /* first scan for '##' operator handling */
2551 ptr = macro_str;
2552 macro_str1 = macro_twosharps(ptr);
2553 if (macro_str1)
2554 ptr = macro_str1;
2555 spc = 0;
2556 while (1) {
2557 /* NOTE: ptr == NULL can only happen if tokens are read from
2558 file stream due to a macro function call */
2559 if (ptr == NULL)
2560 break;
2561 TOK_GET(t, ptr, cval);
2562 if (t == 0)
2563 break;
2564 s = define_find(t);
2565 if (s != NULL) {
2566 /* if nested substitution, do nothing */
2567 if (sym_find2(*nested_list, t))
2568 goto no_subst;
2569 ml.p = macro_ptr;
2570 if (can_read_stream)
2571 ml.prev = *can_read_stream, *can_read_stream = &ml;
2572 macro_ptr = (int *)ptr;
2573 tok = t;
2574 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
2575 ptr = (int *)macro_ptr;
2576 macro_ptr = ml.p;
2577 if (can_read_stream && *can_read_stream == &ml)
2578 *can_read_stream = ml.prev;
2579 if (ret != 0)
2580 goto no_subst;
2581 } else {
2582 no_subst:
2583 if (!check_space(t, &spc))
2584 tok_str_add2(tok_str, t, &cval);
2587 if (macro_str1)
2588 tok_str_free(macro_str1);
2591 /* return next token with macro substitution */
2592 static void next(void)
2594 Sym *nested_list, *s;
2595 TokenString str;
2596 struct macro_level *ml;
2598 redo:
2599 if (parse_flags & PARSE_FLAG_SPACES)
2600 next_nomacro_spc();
2601 else
2602 next_nomacro();
2603 if (!macro_ptr) {
2604 /* if not reading from macro substituted string, then try
2605 to substitute macros */
2606 if (tok >= TOK_IDENT &&
2607 (parse_flags & PARSE_FLAG_PREPROCESS)) {
2608 s = define_find(tok);
2609 if (s) {
2610 /* we have a macro: we try to substitute */
2611 tok_str_new(&str);
2612 nested_list = NULL;
2613 ml = NULL;
2614 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
2615 /* substitution done, NOTE: maybe empty */
2616 tok_str_add(&str, 0);
2617 macro_ptr = str.str;
2618 macro_ptr_allocated = str.str;
2619 goto redo;
2623 } else {
2624 if (tok == 0) {
2625 /* end of macro or end of unget buffer */
2626 if (unget_buffer_enabled) {
2627 macro_ptr = unget_saved_macro_ptr;
2628 unget_buffer_enabled = 0;
2629 } else {
2630 /* end of macro string: free it */
2631 tok_str_free(macro_ptr_allocated);
2632 macro_ptr = NULL;
2634 goto redo;
2638 /* convert preprocessor tokens into C tokens */
2639 if (tok == TOK_PPNUM &&
2640 (parse_flags & PARSE_FLAG_TOK_NUM)) {
2641 parse_number((char *)tokc.cstr->data);
2645 /* push back current token and set current token to 'last_tok'. Only
2646 identifier case handled for labels. */
2647 static inline void unget_tok(int last_tok)
2649 int i, n;
2650 int *q;
2651 unget_saved_macro_ptr = macro_ptr;
2652 unget_buffer_enabled = 1;
2653 q = unget_saved_buffer;
2654 macro_ptr = q;
2655 *q++ = tok;
2656 n = tok_ext_size(tok) - 1;
2657 for(i=0;i<n;i++)
2658 *q++ = tokc.tab[i];
2659 *q = 0; /* end of token string */
2660 tok = last_tok;