Converted tabs to spaces, build into build/ dir
[mcc.git] / cpp.c
blobd1a5082fbb59fa229425bc5689c7a2360ab0c95d
1 #include "cpp.h"
2 #include "errors.h"
3 #include "stdlib.h"
4 #include "stdio.h"
5 #include "string.h"
6 #include "bstr.h"
7 #include "stdarg.h"
8 #include "stdbool.h"
9 #include "ctype.h"
10 #include "sys/types.h"
11 #include "sys/stat.h"
12 #include "assert.h"
14 #define CONFIG_INCLUDE_DIRS "/usr/include"
16 //#define trace(...) fprintf(stderr, __VA_ARGS__)
17 #define trace(...)
19 // A value from an expression
20 // (in #if etc.)
21 struct exprval {
22 int value;
25 void cpp_delete_macro(struct cpp *cpp, struct macro *m);
26 void cpp_lex(struct cpp *cpp);
28 int cpp_get_col(struct cpp *cpp, char *p)
30 return p + 1 - cpp->line_buf;
33 #define cpp_error(cpp, p, ...) cpp_message(cpp, p, NULL, "error: " __VA_ARGS__)
34 #define cpp_warning(cpp, p, ...) cpp_message(cpp, p, NULL, "warning: " __VA_ARGS__)
35 #define cpp_error_loc(cpp, sloc, ...) cpp_message(cpp, NULL, sloc, "error: " __VA_ARGS__)
36 #define cpp_warning_loc(cpp, sloc, ...) cpp_message(cpp, NULL, sloc, "warning: " __VA_ARGS__)
37 void cpp_message(struct cpp *cpp, char *p, struct sloc *sloc, const char *fmt, ...)
39 va_list ap;
40 struct sloc my_sloc;
41 if (!sloc){
42 my_sloc = cpp->line_loc;
43 my_sloc.col = cpp_get_col(cpp, p);
44 sloc = &my_sloc;
46 fprintf(stderr, "%s:%d: ",
47 sloc->name,
48 sloc->line/*,
49 sloc->col*/);
50 // NOTE: don't print col number, because after macro substitution,
51 // the column number becomes incorrect. Fix=???
52 va_start(ap, fmt);
53 vfprintf(stderr, fmt, ap);
54 va_end(ap);
55 fputc('\n', stderr);
58 void cpp_init(struct cpp *cpp)
60 cpp->include_top = NULL;
61 cpp->stale_files = NULL;
62 cpp->line_buf = NULL;
63 cpp->macros = NULL;
64 cpp->include_dirs = estrdup(CONFIG_INCLUDE_DIRS);
67 void cpp_delete(struct cpp *cpp)
69 struct incfile *incf, *incf_prev;
70 incf = cpp->include_top;
71 while (incf){
72 incf_prev = incf->prev;
73 free(incf);
74 incf = incf_prev;
76 incf = cpp->stale_files;
77 while (incf){
78 incf_prev = incf->prev;
79 free(incf);
80 incf = incf_prev;
82 free(cpp->line_buf);
83 free(cpp->include_dirs);
84 while (cpp->macros){
85 cpp_delete_macro(cpp, cpp->macros);
89 struct macro *cpp_create_macro(const char *name)
91 struct macro *m;
92 m = emalloc(sizeof(struct macro) + strlen(name));
93 m->next = NULL;
94 m->args = NULL;
95 m->has_args = false;
96 m->text = NULL;
97 strcpy(m->name, name);
98 return m;
101 struct macro *cpp_create_push_macro(struct cpp *cpp, const char *name)
103 struct macro *m;
104 m = cpp_create_macro(name);
105 m->next = cpp->macros;
106 cpp->macros = m;
107 return m;
110 struct macro *cpp_find_macro(struct cpp *cpp, const char *name)
112 struct macro *m;
113 m = cpp->macros;
114 while (m && strcmp(m->name, name)){
115 m = m->next;
117 return m;
120 struct macro *cpp_find_macro_arg(struct macro *m, const char *name)
122 struct macro *m_arg;
123 m_arg = m->args;
124 while (m_arg && strcmp(m_arg->name, name)){
125 m_arg = m_arg->next;
127 return m_arg;
130 static int macro_count_args(struct macro *m)
132 struct macro *m_arg;
133 int n;
134 m_arg = m->args;
135 n = 0;
136 while (m_arg){
137 n++;
138 m_arg = m_arg->next;
140 return n;
143 void cpp_delete_macro(struct cpp *cpp, struct macro *m)
145 struct macro *m_i, *m_arg, *m_arg_next;
146 m_i = cpp->macros;
147 if (m_i == m){
148 cpp->macros = m->next;
149 } else {
150 while (m_i && m_i->next != m){
151 m_i = m_i->next;
153 if (m_i){
154 m_i->next = m->next;
157 m_arg = m->args;
158 while (m_arg){
159 m_arg_next = m_arg->next;
160 free(m_arg->text);
161 free(m_arg);
162 m_arg = m_arg_next;
164 free(m->text);
165 free(m);
169 // push a file on the include stack
170 void cpp_include_file(struct cpp *cpp, const char *name, FILE *f, bool must_close)
172 struct incfile *incf;
173 incf = emalloc(sizeof(struct incfile) + strlen(name));
174 incf->f = f;
175 strcpy(incf->name, name);
176 incf->line = 0;
177 incf->must_close = must_close;
178 incf->eof = false;
179 incf->cond_d = incf->cond_td = 0;
180 // push on include stack
181 incf->prev = cpp->include_top;
182 cpp->include_top = incf;
185 static bool get_dir(char **dirlist, char **output)
187 if (**dirlist){
188 char *p = strchrnul(*dirlist, ':');
189 strdncpy(output, *dirlist, p - *dirlist);
190 *dirlist = p;
191 return true;
192 } else {
193 return false;
197 // open a file and push it on the include stack
198 bool cpp_open_include_file(struct cpp *cpp, const char *name)
200 FILE *f;
201 char *dirlist, *attempt_file = NULL;
202 struct stat stat_struct;
204 // try current directory
205 if (!stat(name, &stat_struct)){
206 f = fopen(name, "r");
207 assert(f != NULL);
208 cpp_include_file(cpp, name, f, true);
209 return true;
212 // try include dirs
213 dirlist = cpp->include_dirs;
214 while (get_dir(&dirlist, &attempt_file)){
215 strdcatc(&attempt_file, '/');
216 strdcat(&attempt_file, name);
217 if (!stat(attempt_file, &stat_struct)){
218 f = fopen(attempt_file, "r");
219 assert(f != NULL);
220 cpp_include_file(cpp, attempt_file, f, true);
221 free(attempt_file);
222 return true;
225 free(attempt_file);
226 return false;
229 void cpp_pop_include(struct cpp *cpp)
231 struct incfile *incf;
232 incf = cpp->include_top;
233 if (incf){
234 cpp->include_top = incf->prev;
235 incf->prev = cpp->stale_files;
236 cpp->stale_files = incf;
237 if (incf->must_close == true){
238 fclose(incf->f);
243 void cpp_clear_line(struct cpp *cpp)
245 if (cpp->line_buf)
246 strdcpy(&cpp->line_buf, "");
249 void cpp_delete_line(struct cpp *cpp)
251 // TODO: can we, erm, keep the buffer?!
252 free(cpp->line_buf);
253 cpp->line_buf = NULL;
256 void cpp_read_line(struct cpp *cpp)
258 struct incfile *incf;
259 char **pstr = &cpp->line_buf;
260 int ch;
262 incf = cpp->include_top;
263 if (incf && incf->eof){
264 cpp_pop_include(cpp);
265 incf = cpp->include_top;
267 if (incf){
268 strdcpy(pstr, "");
269 do {
270 ch = fgetc(incf->f);
271 if (ch == EOF){
272 incf->eof = true;
273 } else if (ch == '\\'){
274 // backslashed newline?
275 ch = fgetc(incf->f);
276 if (ch == '\n'){
277 // yes
278 incf->line++;
279 strdcatc(pstr, ' '); // insert a space to ensure token separation
280 ch = '@'; // this could be anything
281 } else {
282 // no
283 strdcatc(pstr, '\\');
284 strdcatc(pstr, ch);
286 } else if (ch != '\n'){
287 strdcatc(pstr, ch);
289 } while (ch != EOF && ch != '\n');
290 incf->line++;
291 cpp->line_loc.name = incf->name;
292 cpp->line_loc.line = incf->line;
293 } else {
294 cpp_delete_line(cpp);
298 // read another line and stick it on the end of the buffer
299 void cpp_append_line(struct cpp *cpp)
301 char *old_buf;
302 old_buf = cpp->line_buf;
303 cpp->line_buf = NULL;
304 cpp_read_line(cpp);
305 if (cpp->line_buf){
306 strdcatc(&old_buf, ' ');
307 strdcat(&old_buf, cpp->line_buf);
308 free(cpp->line_buf);
310 cpp->line_buf = old_buf;
313 static void white(char **p, char *set)
315 while (**p && strchr(set, **p)){
316 (*p)++;
320 // read a number
321 bool cpp_lex_number(struct cpp *cpp, char **p_start, char **output)
323 char *p = *p_start;
325 if (*p == '0'){
326 // octal or hexadecimal
327 p++;
328 if (tolower(*p) == 'x'){
329 // hexadecimal
330 p++;
331 while (isdigit(*p) || (tolower(*p) >= 'a' && tolower(*p) <= 'f')){
332 p++;
334 } else {
335 // octal
336 p++;
337 while (*p >= '0' && *p <= '7'){
338 p++;
341 } else if (*p >= '0' && *p <= '9'){
342 // decimal
343 while (*p >= '0' && *p <= '9'){
344 p++;
346 if (*p == '.'){
347 // decimal part
348 p++;
349 while (*p >= '0' && *p <= '9'){
350 p++;
353 if (tolower(*p) == 'e'){
354 // exponent part
355 p++;
356 while (*p >= '0' && *p <= '9'){
357 p++;
360 } else {
361 // not a number at all
362 return false;
364 strdncat(output, *p_start, p - *p_start);
365 *p_start = p;
366 return true;
369 // read a string literal
370 bool cpp_lex_string(struct cpp *cpp, char *quotes, char **p_start, char **output)
372 char *p = *p_start, quote;
373 char *p_last_start;
374 if (*p && strchr(quotes, *p)){
375 quote = *p;
376 p_last_start = *p_start;
377 p++;
378 if (output){
379 strdcpy(output, "");
381 while (*p && *p != quote){
382 if (*p == '\\'){
383 if (p[1] == quote || p[1] == '\\'){
384 // escaped quotation mark or backslash
385 p += 2;
386 if (output){
387 strdncat(output, p_last_start, p - p_last_start);
389 p_last_start = p;
390 } else {
391 p++;
393 } else {
394 p++;
397 if (*p != quote){
398 cpp_error(cpp, *p_start, "unterminated %s literal",
399 (quote == '\'') ? "character" : "string");
400 } else {
401 p++;
403 if (output){
404 strdncat(output, p_last_start, p - p_last_start);
406 *p_start = p;
407 return true;
408 } else {
409 return false;
413 // read an identifier
414 bool cpp_lex_ident(struct cpp *cpp, char **p_start, char **output)
416 char *p = *p_start;
417 if (*p && (isalpha(*p) || *p == '_')){
418 while (*p && (isalnum(*p) || *p == '_')){
419 p++;
421 strdncpy(output, *p_start, p - *p_start);
422 *p_start = p;
423 return true;
424 } else {
425 return false;
429 bool cpp_muted(struct cpp *cpp)
431 struct incfile *incf;
432 incf = cpp->include_top;
433 if (incf){
434 if (incf->cond_d > incf->cond_td){
435 return true;
438 return false;
441 void cpp_parse_include(struct cpp *cpp, char *p, char *p_start)
443 char *inc_str = NULL, *p_str_start;
444 white(&p, " \t");
445 p_str_start = p;
446 if (cpp_lex_string(cpp, "<\"", &p, &inc_str)){
447 white(&p, " \t");
448 if (*p){
449 cpp_warning(cpp, p, "junk at end of #include directive");
451 if (strlen(inc_str) == 2){
452 cpp_error(cpp, p_str_start, "empty filename in #include");
453 } else {
454 inc_str[strlen(inc_str) - 1] = '\0';
455 if (!cpp_open_include_file(cpp, inc_str + 1)){
456 cpp_error(cpp, p_str_start, "%s: no such file or directory", inc_str + 1);
458 free(inc_str);
460 cpp_clear_line(cpp);
461 } else {
462 cpp_error(cpp, p_start, "#include expects \"FILENAME\" or <FILENAME>");
466 bool cpp_parse_macro_param(struct cpp *cpp, char **p, struct macro *m, struct macro ***p_next)
468 char *param_name = NULL;
469 struct sloc arg_loc;
470 struct macro *m_arg;
471 bool result;
473 arg_loc = cpp->line_loc;
474 arg_loc.col = cpp_get_col(cpp, *p);
475 if (cpp_lex_ident(cpp, p, &param_name)){
476 m_arg = cpp_find_macro_arg(m, param_name);
477 if (m_arg){
478 cpp_error_loc(cpp, &arg_loc, "repeated macro parameter \"%s\"", param_name);
479 } else {
480 m_arg = cpp_create_macro(param_name);
481 **p_next = m_arg;
482 *p_next = &m_arg->next;
484 result = true;
485 } else {
486 result = false;
488 free(param_name);
489 return result;
492 void cpp_parse_define(struct cpp *cpp, char *p, char *p_start)
494 char *macro_name = NULL;
495 struct macro *m, **p_next;
496 struct sloc name_sloc;
497 bool failed = false;
499 white(&p, " \t");
500 name_sloc = cpp->line_loc;
501 name_sloc.col = cpp_get_col(cpp, p);
502 if (cpp_lex_ident(cpp, &p, &macro_name)){
503 m = cpp_find_macro(cpp, macro_name);
504 if (m){
505 cpp_warning_loc(cpp, &name_sloc, "\"%s\" redefined", macro_name);
506 cpp_warning_loc(cpp, &m->sloc, "previous definition was here");
507 cpp_delete_macro(cpp, m);
509 m = cpp_create_push_macro(cpp, macro_name);
510 free(macro_name);
511 m->sloc = name_sloc;
512 if (*p == '('){
513 // macro has parameters
514 m->has_args = true;
515 p++;
516 p_next = &m->args;
517 white(&p, " \t");
518 if (*p != ')'){
519 do {
520 if (!strncmp(p, "...", 3)){
521 // variadic macro
522 struct macro *m_arg = cpp_create_macro("__VA_ARGS__");
523 *p_next = m_arg;
524 p_next = &m_arg->next;
525 p += 3;
526 white(&p, " \t");
527 break;
528 } else if (!cpp_parse_macro_param(cpp, &p, m, &p_next)){
529 failed = true;
531 white(&p, " \t");
532 } while ((*p == ',') ? (
533 p++,
534 white(&p, " \t"),
535 true) : false);
537 *p_next = NULL;
538 if (*p == ')'){
539 p++;
540 } else {
541 cpp_error(cpp, p, "missing ')' in macro parameter list");
544 white(&p, " \t");
545 strdcpy(&m->text, p);
546 cpp_clear_line(cpp);
547 if (failed){
548 cpp_delete_macro(cpp, m);
550 } else {
551 cpp_error(cpp, p_start, "no macro name given in #define directive");
555 void cpp_parse_undef(struct cpp *cpp, char *p, char *p_start)
557 char *tok = NULL;
558 struct macro *m;
559 white(&p, " \t");
560 if (cpp_lex_ident(cpp, &p, &tok)){
561 white(&p, " \t");
562 if (*p){
563 cpp_warning(cpp, p, "junk at end of #undef directive");
565 m = cpp_find_macro(cpp, tok);
566 if (m){
567 cpp_delete_macro(cpp, m);
569 free(tok);
570 cpp_clear_line(cpp);
571 } else {
572 cpp_error(cpp, p_start, "no macro name given in #undef directive");
576 void cpp_do_condition(struct cpp *cpp, bool condition)
578 if (!cpp_muted(cpp) && condition){
579 cpp->include_top->cond_td++;
581 cpp->include_top->cond_d++;
582 cpp_clear_line(cpp);
585 void cpp_parse_ifdef(struct cpp *cpp, char *p, char *p_start)
587 char *tok = NULL;
588 white(&p, " \t");
589 if (cpp_lex_ident(cpp, &p, &tok)){
590 white(&p, " \t");
591 if (*p){
592 cpp_warning(cpp, p, "junk at end of #ifdef directive");
594 cpp_do_condition(cpp, !!cpp_find_macro(cpp, tok));
595 free(tok);
596 } else {
597 cpp_error(cpp, p_start, "no macro name given in #ifdef directive");
601 // parse a C number - oct, hex or dec
602 static void parse_cnumber(const char *str, struct exprval *presult)
604 unsigned long long result = 0;
605 const char *p = str;
606 if (*p == '0'){
607 // octal or hexadecimal
608 p++;
609 if (tolower(*p) == 'x'){
610 // hexadecimal
611 p++;
612 while (isdigit(*p) || (tolower(*p) >= 'a' && tolower(*p) <= 'f')){
613 if (isdigit(*p)){
614 result = (result << 4) | (*p - '0');
615 } else {
616 result = (result << 4) | ((tolower(*p) - 'a') + 10);
618 p++;
620 } else {
621 // octal
622 p++;
623 while (*p >= '0' && *p <= '7'){
624 result = (result << 3) | (*p - '0');
625 p++;
628 } else if (*p >= '0' && *p <= '9'){
629 // decimal
630 while (*p >= '0' && *p <= '9'){
631 result = (result * 10) + (*p - '0');
632 p++;
634 if (*p == '.'){
635 // decimal part
636 p++;
637 while (*p >= '0' && *p <= '9'){
638 // TODO: use value (floats, etc.)
639 p++;
642 if (tolower(*p) == 'e'){
643 // exponent part
644 p++;
645 while (*p >= '0' && *p <= '9'){
646 // TODO: use value (floats, etc.)
647 p++;
651 presult->value = result;
654 void cpp_factor(struct cpp *cpp, char **p, struct exprval *result)
656 char *factor_str = NULL;
658 if(cpp_lex_number(cpp, p, &factor_str)){
659 // it's a number
660 parse_cnumber(factor_str, result);
661 free(factor_str);
662 } else if (**p == '!'){
663 // logical not
664 (*p)++;
665 cpp_factor(cpp, p, result);
666 result->value = !result->value;
667 } else if (!strncmp(*p, "defined", 7)){
668 // eg. #if defined(FOO)
669 char *macro_name = NULL;
670 struct macro *m;
671 (*p) += 7;
672 white(p, " \t");
673 if (**p != '('){
674 cpp_error(cpp, *p, "'(' expected");
675 } else {
676 (*p)++;
678 white(p, " \t");
679 if (cpp_lex_ident(cpp, p, &macro_name)){
680 m = cpp_find_macro(cpp, macro_name);
681 result->value = !!m;
682 free(macro_name);
683 } else {
684 cpp_error(cpp, *p, "identifier (macro name, for \"defined\") expected");
686 white(p, " \t");
687 if (**p != ')'){
688 cpp_error(cpp, *p, "')' expected");
689 } else {
690 (*p)++;
692 } else {
693 cpp_error(cpp, *p, "expression expected");
697 void cpp_and_expr(struct cpp *cpp, char **p, struct exprval *result)
699 cpp_factor(cpp, p, result);
700 white(p, " \t");
701 while ((*p)[0] == '&' && (*p)[1] == '&'){
702 struct exprval rhs;
703 (*p) += 2;
704 white(p, " \t");
705 cpp_factor(cpp, p, &rhs);
706 white(p, " \t");
707 result->value = result->value && rhs.value;
711 void cpp_or_expr(struct cpp *cpp, char **p, struct exprval *result)
713 cpp_and_expr(cpp, p, result);
714 white(p, " \t");
715 while ((*p)[0] == '|' && (*p)[1] == '|'){
716 struct exprval rhs;
717 (*p) += 2;
718 white(p, " \t");
719 cpp_and_expr(cpp, p, &rhs);
720 white(p, " \t");
721 result->value = result->value || rhs.value;
725 void cpp_expr(struct cpp *cpp, char **p, struct exprval *result)
727 cpp_or_expr(cpp, p, result);
730 void cpp_parse_if(struct cpp *cpp, char *p, char *p_start)
732 struct exprval result;
733 white(&p, " \t");
734 cpp_expr(cpp, &p, &result);
735 cpp_do_condition(cpp, !!result.value);
738 void cpp_parse_ifndef(struct cpp *cpp, char *p, char *p_start)
740 char *tok = NULL;
741 white(&p, " \t");
742 if (cpp_lex_ident(cpp, &p, &tok)){
743 white(&p, " \t");
744 if (*p){
745 cpp_warning(cpp, p, "junk at end of #ifdef directive");
747 cpp_do_condition(cpp, !cpp_find_macro(cpp, tok));
748 free(tok);
749 } else {
750 cpp_error(cpp, p_start, "no macro name given in #ifdef directive");
754 void cpp_parse_else(struct cpp *cpp, char *p, char *p_start)
756 white(&p, " \t");
757 if (!cpp_muted(cpp) && *p){
758 cpp_warning(cpp, p, "junk at end of #else directive");
760 if (cpp->include_top->cond_d == 0){
761 cpp_error(cpp, p_start, "#else without matching #if or #ifdef");
762 } else {
763 if (cpp->include_top->cond_d == cpp->include_top->cond_td + 1){
764 // false -> true
765 cpp->include_top->cond_td++;
766 } else if (!cpp_muted(cpp)){
767 // true -> false
768 cpp->include_top->cond_td--;
771 cpp_delete_line(cpp);
774 void cpp_parse_endif(struct cpp *cpp, char *p, char *p_start)
776 white(&p, " \t");
777 if (!cpp_muted(cpp) && *p){
778 cpp_warning(cpp, p, "junk at end of #endif directive");
780 if (cpp->include_top->cond_d == 0){
781 cpp_error(cpp, p_start, "#endif without matching #if or #ifdef");
782 } else {
783 if (!cpp_muted(cpp)){
784 cpp->include_top->cond_td--;
786 cpp->include_top->cond_d--;
788 if (cpp_muted(cpp))
789 cpp_delete_line(cpp);
790 else
791 cpp_clear_line(cpp);
794 static struct {
795 bool conditional_related;
796 const char *str;
797 void (* func)(struct cpp *cpp, char *p, char *p_start);
798 } directives[] = {
799 {false, "define", cpp_parse_define},
800 {false, "undef", cpp_parse_undef},
801 {false, "include", cpp_parse_include},
802 {true, "if", cpp_parse_if},
803 {true, "ifdef", cpp_parse_ifdef},
804 {true, "ifndef", cpp_parse_ifndef},
805 {true, "else", cpp_parse_else},
806 {true, "endif", cpp_parse_endif},
809 bool cpp_macro_args(struct cpp *cpp, char **line_buf, char **p, struct macro *m)
811 const char *p_start;
812 struct macro *m_arg;
813 int n, depth, p_n, p_start_n;
814 if (m->has_args){
815 white(p, " \t");
816 if (**p != '('){
817 return false; // give up
819 (*p)++;
821 // read arguments
822 m_arg = m->args;
823 n = 0;
824 while (m_arg){
825 white(p, " \t");
826 p_start = *p;
827 depth = 1;
828 if (!strcmp(m_arg->name, "__VA_ARGS__")){
829 // XXX: it's silly having this here - it's almost the same
830 // as the one further down
831 while (**p != '\0' && depth > 0){
832 if (cpp_lex_string(cpp, "\"'", p, NULL)){
833 // it's a string - let's not interpret '(' and ')' in strings!
834 } else if (**p == '('){
835 depth++;
836 } else if (**p == ')'){
837 depth--;
839 if (depth > 0){
840 (*p)++;
843 } else {
844 for (;;){
845 while (**p != '\0' && depth > 0 && (**p != ',' || depth > 1)){
846 if (cpp_lex_string(cpp, "\"'", p, NULL)){
847 // it's a string - let's not interpret '(' and ')' in strings!
848 } else if (**p == '('){
849 depth++;
850 } else if (**p == ')'){
851 depth--;
853 if (depth > 0){
854 (*p)++;
857 if (**p == '\0' && cpp->include_top){
858 // there's a line break in the middle of it
859 p_n = *p - *line_buf;
860 p_start_n = p_start - *line_buf;
861 cpp_append_line(cpp);
862 *p = *line_buf + p_n;
863 p_start = *line_buf + p_start_n;
864 } else {
865 break;
869 strdncpy(&m_arg->text, p_start, *p - p_start);
870 //printf("arg=%s\n", m_arg->text);
871 if (*p > p_start){
872 n++;
874 if ((**p == ')' && m_arg->next)
875 || (**p == ',' && !m_arg->next)){
876 cpp_error(cpp, *p, "macro \"%s\" requires %d arguments, but only %d given", m->name, macro_count_args(m), n);
877 break;
878 } else if (**p == '\0'){
879 if (cpp->include_top){
880 } else {
881 cpp_error(cpp, *p, "unterminated argument list invoking macro \"%s\"", m->name);
882 break;
884 } else if (**p == ','){
885 (*p)++;
887 m_arg = m_arg->next;
889 (*p)++;
890 return true;
891 } else {
892 return true;
896 // the spaghetti code is served
897 char *cpp_macro_arg_subst(struct cpp *cpp, struct macro *m)
899 char *result = NULL, *s = NULL, *p, *p0, *p_before, *sp;
900 struct macro *m_arg;
901 int stringize = 0;
903 p = m->text;
904 p0 = p;
905 while (*p){
906 if (*p == '#'){
907 if (p[1] == '#'){
908 // token-paste
909 if (p > p0){
910 strdncat(&result, p0, p - 1 - p0);
912 p += 2;
913 while (*p == ' ' || *p == '\t'){
914 p++;
916 p0 = p;
917 // remove whitespace after previous tok
918 sp = result + strlen(result);
919 while (sp > result && (sp[-1] == ' ' || sp[-1] == '\t')){
920 sp--;
922 *sp = '\0';
923 } else {
924 // stringize
925 if (p > p0){
926 strdncat(&result, p0, p - p0);
928 stringize = 1;
929 p++;
930 p0 = p;
931 while (*p == ' ' || *p == '\t'){
932 p++;
934 if (isalpha(*p) || *p == '_'){
935 goto identifier;
936 } else {
937 cpp_error_loc(cpp, &m->sloc, "'#' not followed by macro-argument");
938 stringize = 0;
941 } else if (isalpha(*p) || *p == '_'){
942 // identifier - macro arg name?
943 identifier:
944 p_before = p;
945 p++;
946 while (isalnum(*p) || isdigit(*p) || *p == '_'){
947 p++;
949 strdncpy(&s, p_before, p - p_before);
950 m_arg = cpp_find_macro_arg(m, s);
951 if (!m_arg){
952 if (stringize){
953 cpp_error_loc(cpp, &m->sloc, "'#' not followed by macro-argument");
954 stringize = 0;
956 continue;
958 // macro-arg substitution
959 if (p_before > p0){
960 strdncat(&result, p0, p_before - p0);
962 strdcatc(&result, ' ');
963 if (stringize){
964 strdcatc(&result, '"');
966 if (m_arg->text)
967 strdcat(&result, m_arg->text);
968 if (stringize){
969 strdcatc(&result, '"');
970 stringize = 0;
972 p0 = p;
973 } else {
974 p++;
977 if (stringize){
978 cpp_error_loc(cpp, &m->sloc, "'#' not followed by macro-argument");
980 strdncat(&result, p0, p - p0);
981 free(s);
982 return result;
985 struct macro_stack {
986 struct macro_stack *prev;
987 struct macro *m;
990 void cpp_substitute_macros(struct cpp *cpp, char **line_buf, struct macro_stack *ms)
992 char *p, *p_start, *ident = NULL;
993 char *substituted_text, *new_line_buf = NULL;
994 struct macro *m;
995 struct macro_stack stack_item, *ms_ptr;
996 int p_start_n, p_end_n;
997 p = *line_buf;
998 while (*p){
999 p_start = p;
1000 if (cpp_lex_ident(cpp, &p, &ident)){
1001 // is it a macro?
1002 m = cpp_find_macro(cpp, ident);
1003 // is it in the stack?
1004 if (m){
1005 ms_ptr = ms;
1006 while (ms_ptr && ms_ptr->m != m){
1007 ms_ptr = ms_ptr->prev;
1009 if (ms_ptr){
1010 m = NULL; // yes it is. Let's forget about it.
1013 p_start_n = p_start - *line_buf;
1014 if (m && cpp_macro_args(cpp, line_buf, &p, m)){
1015 p_start = *line_buf + p_start_n;
1016 substituted_text = cpp_macro_arg_subst(cpp, m);
1017 // now we have to substitute the substituted text
1018 stack_item.prev = ms;
1019 stack_item.m = m;
1020 cpp_substitute_macros(cpp, &substituted_text, &stack_item);
1021 strdncat(&new_line_buf, *line_buf, p_start - *line_buf);
1022 strdcat(&new_line_buf, substituted_text);
1023 free(substituted_text);
1024 p_end_n = strlen(new_line_buf); // de-pointerize p_start
1025 strdcat(&new_line_buf, p);
1026 // replace the line buffer with our new one (with the substitution)
1027 free(*line_buf);
1028 *line_buf = new_line_buf;
1029 new_line_buf = NULL;
1030 p = *line_buf + p_end_n;
1032 } else if (cpp_lex_string(cpp, "\"'", &p, &ident)){
1033 // nothing needs to be done
1034 // but at least we've passed the string, so we
1035 // won't expand macros in it
1036 } else {
1037 p++;
1040 free(ident);
1043 void cpp_remove_comments(struct cpp *cpp)
1045 char *p = cpp->line_buf, *p_start;
1046 int p_start_n, p_n;
1047 while (*p){
1048 if (p[0] == '/' && p[1] == '/'){
1049 // single-line comment
1050 memset(p, ' ', strlen(p));
1051 p += strlen(p);
1052 } else if (p[0] == '/' && p[1] == '*'){
1053 // multi-line comment
1054 p_start = p;
1055 p += 2;
1056 for (;;){
1057 if (p[0] == '*' && p[1] == '/'){
1058 // end of comment
1059 p += 2;
1060 memset(p_start, ' ', p - p_start);
1061 break;
1062 } else if (*p == '\0'){
1063 // we need to read another line!
1064 // as you can see, this isn't very elegant
1065 p_start_n = p_start - cpp->line_buf;
1066 p_n = p - cpp->line_buf;
1067 cpp_append_line(cpp);
1068 p_start = cpp->line_buf + p_start_n;
1069 p = cpp->line_buf + p_n;
1070 } else {
1071 p++;
1074 } else {
1075 p++;
1080 void cpp_process_line(struct cpp *cpp)
1082 char *p, *tok = NULL, *p_start;
1083 int i;
1084 bool done;
1085 if (!cpp->line_buf)
1086 return;
1087 cpp_remove_comments(cpp);
1088 p = cpp->line_buf;
1089 white(&p, " \t");
1090 if (*p == '#'){
1091 // preprocessor directive
1092 p_start = p;
1093 p++;
1094 white(&p, " \t");
1095 done = false;
1096 cpp_lex_ident(cpp, &p, &tok);
1097 if (tok){
1098 for (i=0; i<(sizeof directives/sizeof *directives); i++){
1099 if (!strcmp(tok, directives[i].str)){
1100 if (!cpp_muted(cpp) || directives[i].conditional_related){
1101 directives[i].func(cpp, p, p_start);
1103 done = true;
1106 if (!done && !cpp_muted(cpp)){
1107 cpp_error(cpp, p_start, "invalid preprocessing directive #%s", tok);
1109 } else {
1110 cpp_clear_line(cpp);
1112 free(tok);
1113 } else {
1114 if (!cpp_muted(cpp)){
1115 cpp_substitute_macros(cpp, &cpp->line_buf, NULL);
1118 if (cpp_muted(cpp)){
1119 cpp_delete_line(cpp);