Print this page
new smatch


  32 #include <string.h>
  33 #include <ctype.h>
  34 #include <unistd.h>
  35 #include <fcntl.h>
  36 #include <limits.h>
  37 #include <time.h>
  38 #include <dirent.h>
  39 #include <sys/stat.h>
  40 
  41 #include "lib.h"
  42 #include "allocate.h"
  43 #include "parse.h"
  44 #include "token.h"
  45 #include "symbol.h"
  46 #include "expression.h"
  47 #include "scope.h"
  48 
  49 static struct ident_list *macros;       // only needed for -dD
  50 static int false_nesting = 0;
  51 static int counter_macro = 0;           // __COUNTER__ expansion

  52 
  53 #define INCLUDEPATHS 300
  54 const char *includepath[INCLUDEPATHS+1] = {
  55         "",
  56         "/usr/include",
  57         "/usr/local/include",
  58         NULL
  59 };
  60 
  61 static const char **quote_includepath = includepath;
  62 static const char **angle_includepath = includepath + 1;
  63 static const char **isys_includepath   = includepath + 1;
  64 static const char **sys_includepath   = includepath + 1;
  65 static const char **dirafter_includepath = includepath + 3;
  66 
  67 #define dirty_stream(stream)                            \
  68         do {                                            \
  69                 if (!stream->dirty) {                        \
  70                         stream->dirty = 1;           \
  71                         if (!stream->ifndef)         \


 130         if (sym && sym->namespace != NS_MACRO)
 131                 sym = NULL;
 132         return sym;
 133 }
 134 
 135 static int token_defined(struct token *token)
 136 {
 137         if (token_type(token) == TOKEN_IDENT) {
 138                 struct symbol *sym = lookup_macro(token->ident);
 139                 if (sym) {
 140                         sym->used_in = file_scope;
 141                         return 1;
 142                 }
 143                 return 0;
 144         }
 145 
 146         sparse_error(token->pos, "expected preprocessor identifier");
 147         return 0;
 148 }
 149 
 150 static void replace_with_defined(struct token *token)
 151 {
 152         static const char *string[] = { "0", "1" };
 153         int defined = token_defined(token);
 154 
 155         token_type(token) = TOKEN_NUMBER;
 156         token->number = string[defined];
 157 }
 158 
 159 static int expand_one_symbol(struct token **list)
 160 {
 161         struct token *token = *list;
 162         struct symbol *sym;
 163         static char buffer[12]; /* __DATE__: 3 + ' ' + 2 + ' ' + 4 + '\0' */
 164         static time_t t = 0;
 165 
 166         if (token->pos.noexpand)
 167                 return 1;



 168 
 169         sym = lookup_macro(token->ident);
 170         if (sym) {
 171                 store_macro_pos(token);
 172                 sym->used_in = file_scope;
 173                 return expand(list, sym);
 174         }
 175         if (token->ident == &__LINE___ident) {

 176                 replace_with_integer(token, token->pos.line);
 177         } else if (token->ident == &__FILE___ident) {



 178                 replace_with_string(token, stream_name(token->pos.stream));
 179         } else if (token->ident == &__DATE___ident) {











 180                 if (!t)
 181                         time(&t);
 182                 strftime(buffer, 12, "%b %e %Y", localtime(&t));
 183                 replace_with_string(token, buffer);
 184         } else if (token->ident == &__TIME___ident) {





 185                 if (!t)
 186                         time(&t);
 187                 strftime(buffer, 9, "%T", localtime(&t));
 188                 replace_with_string(token, buffer);
 189         } else if (token->ident == &__COUNTER___ident) {



 190                 replace_with_integer(token, counter_macro++);
 191         }












 192         return 1;












 193 }
 194 
 195 static inline struct token *scan_next(struct token **where)
 196 {
 197         struct token *token = *where;
 198         if (token_type(token) != TOKEN_UNTAINT)
 199                 return token;
 200         do {
 201                 token->ident->tainted = 0;
 202                 token = token->next;
 203         } while (token_type(token) == TOKEN_UNTAINT);
 204         *where = token;
 205         return token;
 206 }
 207 
 208 static void expand_list(struct token **list)
 209 {
 210         struct token *next;
 211         while (!eof_token(next = scan_next(list))) {
 212                 if (token_type(next) != TOKEN_IDENT || expand_one_symbol(list))


 497         }
 498 
 499         if (p[0] == '.' && isdigit((unsigned char)p[1]))
 500                 return TOKEN_NUMBER;
 501 
 502         return TOKEN_SPECIAL;
 503 }
 504 
 505 static int merge(struct token *left, struct token *right)
 506 {
 507         static char buffer[512];
 508         enum token_type res = combine(left, right, buffer);
 509         int n;
 510 
 511         switch (res) {
 512         case TOKEN_IDENT:
 513                 left->ident = built_in_ident(buffer);
 514                 left->pos.noexpand = 0;
 515                 return 1;
 516 
 517         case TOKEN_NUMBER: {
 518                 char *number = __alloc_bytes(strlen(buffer) + 1);
 519                 memcpy(number, buffer, strlen(buffer) + 1);
 520                 token_type(left) = TOKEN_NUMBER;        /* could be . + num */
 521                 left->number = number;
 522                 return 1;
 523         }
 524 
 525         case TOKEN_SPECIAL:
 526                 if (buffer[2] && buffer[3])
 527                         break;
 528                 for (n = SPECIAL_BASE; n < SPECIAL_ARG_SEPARATOR; n++) {
 529                         if (!memcmp(buffer, combinations[n-SPECIAL_BASE], 3)) {
 530                                 left->special = n;
 531                                 return 1;
 532                         }
 533                 }
 534                 break;
 535 
 536         case TOKEN_WIDE_CHAR:
 537         case TOKEN_WIDE_STRING:
 538                 token_type(left) = res;
 539                 left->pos.noexpand = 0;
 540                 left->string = right->string;
 541                 return 1;
 542 
 543         case TOKEN_WIDE_CHAR_EMBEDDED_0 ... TOKEN_WIDE_CHAR_EMBEDDED_3:


 834 
 835 static void set_stream_include_path(struct stream *stream)
 836 {
 837         const char *path = stream->path;
 838         if (!path) {
 839                 const char *p = strrchr(stream->name, '/');
 840                 path = "";
 841                 if (p) {
 842                         int len = p - stream->name + 1;
 843                         char *m = malloc(len+1);
 844                         /* This includes the final "/" */
 845                         memcpy(m, stream->name, len);
 846                         m[len] = 0;
 847                         path = m;
 848                 }
 849                 stream->path = path;
 850         }
 851         includepath[0] = path;
 852 }
 853 




 854 static int try_include(const char *path, const char *filename, int flen, struct token **where, const char **next_path)
 855 {
 856         int fd;
 857         int plen = strlen(path);
 858         static char fullname[PATH_MAX];
 859 
 860         memcpy(fullname, path, plen);
 861         if (plen && path[plen-1] != '/') {
 862                 fullname[plen] = '/';
 863                 plen++;
 864         }
 865         memcpy(fullname+plen, filename, flen);
 866         if (already_tokenized(fullname))
 867                 return 1;
 868         fd = open(fullname, O_RDONLY);
 869         if (fd >= 0) {
 870                 char * streamname = __alloc_bytes(plen + flen);
 871                 memcpy(streamname, fullname, plen + flen);
 872                 *where = tokenize(streamname, fd, *where, next_path);
 873                 close(fd);
 874                 return 1;
 875         }
 876         return 0;
 877 }
 878 
 879 static int do_include_path(const char **pptr, struct token **list, struct token *token, const char *filename, int flen)
 880 {
 881         const char *path;
 882 
 883         while ((path = *pptr++) != NULL) {
 884                 if (!try_include(path, filename, flen, list, pptr))
 885                         continue;
 886                 return 1;
 887         }
 888         return 0;
 889 }
 890 
 891 static int free_preprocessor_line(struct token *token)


 895                 token = token->next;
 896                 __free_token(free);
 897         };
 898         return 1;
 899 }
 900 
 901 const char *find_include(const char *skip, const char *look_for)
 902 {
 903         DIR *dp;
 904         struct dirent *entry;
 905         struct stat statbuf;
 906         const char *ret;
 907         char cwd[PATH_MAX];
 908         static char buf[PATH_MAX + 1];
 909 
 910         dp = opendir(".");
 911         if (!dp)
 912                 return NULL;
 913 
 914         if (!getcwd(cwd, sizeof(cwd)))
 915                 return NULL;
 916 
 917         while ((entry = readdir(dp))) {
 918                 lstat(entry->d_name, &statbuf);
 919 
 920                 if (strcmp(entry->d_name, look_for) == 0) {
 921                         snprintf(buf, sizeof(buf), "%s/%s", cwd, entry->d_name);

 922                         return buf;
 923                 }
 924 
 925                 if (S_ISDIR(statbuf.st_mode)) {
 926                         /* Found a directory, but ignore . and .. */
 927                         if (strcmp(".", entry->d_name) == 0 ||
 928                             strcmp("..", entry->d_name) == 0 ||
 929                             strcmp(skip, entry->d_name) == 0)
 930                                 continue;
 931 
 932                         chdir(entry->d_name);
 933                         ret = find_include("", look_for);
 934                         chdir("..");
 935                         if (ret)

 936                                 return ret;
 937                 }
 938         }


 939         closedir(dp);
 940 
 941         return NULL;
 942 }
 943 
 944 const char *search_dir(const char *stop, const char *look_for)
 945 {
 946         char cwd[PATH_MAX];
 947         int len;
 948         const char *ret;
 949         int cnt = 0;
 950 
 951         if (!getcwd(cwd, sizeof(cwd)))
 952                 return NULL;
 953 
 954         len = strlen(cwd);
 955         while (len >= 0) {
 956                 ret = find_include(cnt++ ? cwd + len + 1 : "", look_for);
 957                 if (ret)
 958                         return ret;


 965                         return NULL;
 966 
 967                 while (--len >= 0) {
 968                         if (cwd[len] == '/') {
 969                                 cwd[len] = '\0';
 970                                 break;
 971                         }
 972                 }
 973 
 974                 chdir("..");
 975         }
 976         return NULL;
 977 }
 978 
 979 static void use_best_guess_header_file(struct token *token, const char *filename, struct token **list)
 980 {
 981         char cwd[PATH_MAX];
 982         char dir_part[PATH_MAX];
 983         const char *file_part;
 984         const char *include_name;

 985         int len;
 986 




 987         if (!filename || filename[0] == '\0')
 988                 return;
 989 
 990         file_part = filename;
 991         while ((filename = strchr(filename, '/'))) {
 992                 ++filename;
 993                 if (filename[0])
 994                         file_part = filename;
 995         }
 996 
 997         snprintf(dir_part, sizeof(dir_part), "%s", stream_name(token->pos.stream));
 998         len = strlen(dir_part);
 999         while (--len >= 0) {
1000                 if (dir_part[len] == '/') {
1001                         dir_part[len] = '\0';
1002                         break;
1003                 }
1004         }
1005         if (len < 0)
1006                 sprintf(dir_part, ".");


1403                 case TOKEN_WIDE_STRING:
1404                         token->string->immutable = 1;
1405                         break;
1406                 }
1407         }
1408         token = alloc_token(&expansion->pos);
1409         token_type(token) = TOKEN_UNTAINT;
1410         token->ident = name;
1411         token->next = *p;
1412         *p = token;
1413         return expansion;
1414 
1415 Econcat:
1416         sparse_error(token->pos, "'##' cannot appear at the ends of macro expansion");
1417         return NULL;
1418 Earg:
1419         sparse_error(token->pos, "too many instances of argument in body");
1420         return NULL;
1421 }
1422 
1423 static int do_handle_define(struct stream *stream, struct token **line, struct token *token, int attr)

1424 {
1425         struct token *arglist, *expansion;
1426         struct token *left = token->next;
1427         struct symbol *sym;
1428         struct ident *name;
1429         int ret;
1430 
1431         if (token_type(left) != TOKEN_IDENT) {
1432                 sparse_error(token->pos, "expected identifier to 'define'");
1433                 return 1;
1434         }
1435 
1436         name = left->ident;
1437 
1438         arglist = NULL;
1439         expansion = left->next;
1440         if (!expansion->pos.whitespace) {
1441                 if (match_op(expansion, '(')) {
1442                         arglist = expansion;
1443                         expansion = parse_arguments(expansion);
1444                         if (!expansion)
1445                                 return 1;
1446                 } else if (!eof_token(expansion)) {
1447                         warning(expansion->pos,
1448                                 "no whitespace before object-like macro body");
1449                 }
1450         }
1451 
1452         expansion = parse_expansion(expansion, arglist, name);
1453         if (!expansion)
1454                 return 1;
1455 
1456         ret = 1;
1457         sym = lookup_symbol(name, NS_MACRO | NS_UNDEF);
1458         if (sym) {
1459                 int clean;
1460 
1461                 if (attr < sym->attr)
1462                         goto out;
1463 
1464                 clean = (attr == sym->attr && sym->namespace == NS_MACRO);
1465 
1466                 if (token_list_different(sym->expansion, expansion) ||
1467                     token_list_different(sym->arglist, arglist)) {
1468                         ret = 0;
1469                         if ((clean && attr == SYM_ATTR_NORMAL)
1470                                         || sym->used_in == file_scope) {
1471                                 warning(left->pos, "preprocessor token %.*s redefined",
1472                                                 name->len, name->name);
1473                                 info(sym->pos, "this was the original definition");
1474                         }
1475                 } else if (clean)
1476                         goto out;
1477         }
1478 
1479         if (!sym || sym->scope != file_scope) {
1480                 sym = alloc_symbol(left->pos, SYM_NODE);
1481                 bind_symbol(sym, name, NS_MACRO);
1482                 add_ident(&macros, name);
1483                 ret = 0;
1484         }
1485 
1486         if (!ret) {
1487                 sym->expansion = expansion;
1488                 sym->arglist = arglist;
1489                 __free_token(token);    /* Free the "define" token, but not the rest of the line */

1490         }
1491 
1492         sym->namespace = NS_MACRO;
1493         sym->used_in = NULL;
1494         sym->attr = attr;
1495 out:
1496         return ret;
1497 }
1498 




































































1499 static int handle_define(struct stream *stream, struct token **line, struct token *token)
1500 {
1501         return do_handle_define(stream, line, token, SYM_ATTR_NORMAL);
1502 }
1503 
1504 static int handle_weak_define(struct stream *stream, struct token **line, struct token *token)
1505 {
1506         return do_handle_define(stream, line, token, SYM_ATTR_WEAK);
1507 }
1508 
1509 static int handle_strong_define(struct stream *stream, struct token **line, struct token *token)
1510 {
1511         return do_handle_define(stream, line, token, SYM_ATTR_STRONG);
1512 }
1513 
1514 static int do_handle_undef(struct stream *stream, struct token **line, struct token *token, int attr)
1515 {
1516         struct token *left = token->next;
1517         struct symbol *sym;
1518 


1535                 bind_symbol(sym, left->ident, NS_MACRO);
1536         }
1537 
1538         sym->namespace = NS_UNDEF;
1539         sym->used_in = NULL;
1540         sym->attr = attr;
1541 
1542         return 1;
1543 }
1544 
1545 static int handle_undef(struct stream *stream, struct token **line, struct token *token)
1546 {
1547         return do_handle_undef(stream, line, token, SYM_ATTR_NORMAL);
1548 }
1549 
1550 static int handle_strong_undef(struct stream *stream, struct token **line, struct token *token)
1551 {
1552         return do_handle_undef(stream, line, token, SYM_ATTR_STRONG);
1553 }
1554 
1555 static int preprocessor_if(struct stream *stream, struct token *token, int true)
1556 {
1557         token_type(token) = false_nesting ? TOKEN_SKIP_GROUPS : TOKEN_IF;
1558         free_preprocessor_line(token->next);
1559         token->next = stream->top_if;
1560         stream->top_if = token;
1561         if (false_nesting || true != 1)
1562                 false_nesting++;
1563         return 0;
1564 }
1565 
1566 static int handle_ifdef(struct stream *stream, struct token **line, struct token *token)
1567 {
1568         struct token *next = token->next;
1569         int arg;
1570         if (token_type(next) == TOKEN_IDENT) {
1571                 arg = token_defined(next);
1572         } else {
1573                 dirty_stream(stream);
1574                 if (!false_nesting)
1575                         sparse_error(token->pos, "expected preprocessor identifier");
1576                 arg = -1;
1577         }
1578         return preprocessor_if(stream, token, arg);
1579 }
1580 
1581 static int handle_ifndef(struct stream *stream, struct token **line, struct token *token)


1609  * Expression handling for #if and #elif; it differs from normal expansion
1610  * due to special treatment of "defined".
1611  */
1612 static int expression_value(struct token **where)
1613 {
1614         struct expression *expr;
1615         struct token *p;
1616         struct token **list = where, **beginning = NULL;
1617         long long value;
1618         int state = 0;
1619 
1620         while (!eof_token(p = scan_next(list))) {
1621                 switch (state) {
1622                 case 0:
1623                         if (token_type(p) != TOKEN_IDENT)
1624                                 break;
1625                         if (p->ident == &defined_ident) {
1626                                 state = 1;
1627                                 beginning = list;
1628                                 break;








1629                         }
1630                         if (!expand_one_symbol(list))
1631                                 continue;
1632                         if (token_type(p) != TOKEN_IDENT)
1633                                 break;
1634                         token_type(p) = TOKEN_ZERO_IDENT;
1635                         break;
1636                 case 1:
1637                         if (match_op(p, '(')) {
1638                                 state = 2;
1639                         } else {
1640                                 state = 0;
1641                                 replace_with_defined(p);
1642                                 *beginning = p;
1643                         }
1644                         break;
1645                 case 2:
1646                         if (token_type(p) == TOKEN_IDENT)
1647                                 state = 3;
1648                         else
1649                                 state = 0;
1650                         replace_with_defined(p);
1651                         *beginning = p;
1652                         break;
1653                 case 3:
1654                         state = 0;
1655                         if (!match_op(p, ')'))
1656                                 sparse_error(p->pos, "missing ')' after \"defined\"");
1657                         *list = p->next;
1658                         continue;









1659                 }























1660                 list = &p->next;
1661         }
1662 
1663         p = constant_expression(*where, &expr);
1664         if (!eof_token(p))
1665                 sparse_error(p->pos, "garbage at end: %s", show_token_sequence(p, 0));
1666         value = get_expression_value(expr);
1667         return value != 0;
1668 }
1669 
1670 static int handle_if(struct stream *stream, struct token **line, struct token *token)
1671 {
1672         int value = 0;
1673         if (!false_nesting)
1674                 value = expression_value(&token->next);
1675 
1676         dirty_stream(stream);
1677         return preprocessor_if(stream, token, value);
1678 }
1679 


1952                 stream->once = 1;
1953                 return 1;
1954         }
1955         token->ident = &pragma_ident;
1956         token->pos.newline = 1;
1957         token->pos.whitespace = 1;
1958         token->pos.pos = 1;
1959         *line = token;
1960         token->next = next;
1961         return 0;
1962 }
1963 
1964 /*
1965  * We ignore #line for now.
1966  */
1967 static int handle_line(struct stream *stream, struct token **line, struct token *token)
1968 {
1969         return 1;
1970 }
1971 
1972 /*
1973  * Ignore "#ident".
1974  */
1975 static int handle_ident(struct stream *stream, struct token **line, struct token *token)
1976 {
1977         return 1;
1978 }
1979 
1980 static int handle_nondirective(struct stream *stream, struct token **line, struct token *token)
1981 {
1982         sparse_error(token->pos, "unrecognized preprocessor line '%s'", show_token_sequence(token, 0));
1983         return 1;
1984 }
1985 
1986 
1987 static void init_preprocessor(void)
1988 {
1989         int i;
1990         int stream = init_stream("preprocessor", -1, includepath);
1991         static struct {
1992                 const char *name;
1993                 int (*handler)(struct stream *, struct token **, struct token *);
1994         } normal[] = {


2004                 { "pragma",             handle_pragma },
2005                 { "line",               handle_line },
2006                 { "ident",              handle_ident },
2007 
2008                 // our internal preprocessor tokens
2009                 { "nostdinc",      handle_nostdinc },
2010                 { "add_include",   handle_add_include },
2011                 { "add_isystem",   handle_add_isystem },
2012                 { "add_system",    handle_add_system },
2013                 { "add_dirafter",  handle_add_dirafter },
2014                 { "split_include", handle_split_include },
2015                 { "argv_include",  handle_argv_include },
2016         }, special[] = {
2017                 { "ifdef",      handle_ifdef },
2018                 { "ifndef",     handle_ifndef },
2019                 { "else",       handle_else },
2020                 { "endif",      handle_endif },
2021                 { "if",         handle_if },
2022                 { "elif",       handle_elif },
2023         };












2024 
2025         for (i = 0; i < ARRAY_SIZE(normal); i++) {
2026                 struct symbol *sym;
2027                 sym = create_symbol(stream, normal[i].name, SYM_PREPROCESSOR, NS_PREPROCESSOR);
2028                 sym->handler = normal[i].handler;
2029                 sym->normal = 1;
2030         }
2031         for (i = 0; i < ARRAY_SIZE(special); i++) {
2032                 struct symbol *sym;
2033                 sym = create_symbol(stream, special[i].name, SYM_PREPROCESSOR, NS_PREPROCESSOR);
2034                 sym->handler = special[i].handler;
2035                 sym->normal = 0;
2036         }





2037 
2038         counter_macro = 0;
2039 }
2040 
2041 static void handle_preprocessor_line(struct stream *stream, struct token **line, struct token *start)
2042 {
2043         int (*handler)(struct stream *, struct token **, struct token *);
2044         struct token *token = start->next;
2045         int is_normal = 1;
2046 
2047         if (eof_token(token))
2048                 return;
2049 
2050         if (token_type(token) == TOKEN_IDENT) {
2051                 struct symbol *sym = lookup_symbol(token->ident, NS_PREPROCESSOR);
2052                 if (sym) {
2053                         handler = sym->handler;
2054                         is_normal = sym->normal;
2055                 } else {
2056                         handler = handle_nondirective;


2098 
2099                 if (next->pos.newline && match_op(next, '#')) {
2100                         if (!next->pos.noexpand) {
2101                                 preprocessor_line(stream, list);
2102                                 __free_token(next);     /* Free the '#' token */
2103                                 continue;
2104                         }
2105                 }
2106 
2107                 switch (token_type(next)) {
2108                 case TOKEN_STREAMEND:
2109                         if (stream->top_if) {
2110                                 nesting_error(stream);
2111                                 sparse_error(stream->top_if->pos, "unterminated preprocessor conditional");
2112                                 stream->top_if = NULL;
2113                                 false_nesting = 0;
2114                         }
2115                         if (!stream->dirty)
2116                                 stream->constant = CONSTANT_FILE_YES;
2117                         *list = next->next;

2118                         continue;
2119                 case TOKEN_STREAMBEGIN:
2120                         *list = next->next;

2121                         continue;
2122 
2123                 default:
2124                         dirty_stream(stream);
2125                         if (false_nesting) {
2126                                 *list = next->next;
2127                                 __free_token(next);
2128                                 continue;
2129                         }
2130 
2131                         if (token_type(next) != TOKEN_IDENT ||
2132                             expand_one_symbol(list))
2133                                 list = &next->next;
2134                 }
2135         }
2136 }
2137 
2138 void init_include_path(void)
2139 {
2140         FILE *fp;


2162         strcpy(os, "linux-gnu");
2163 
2164         snprintf(path, sizeof(path), "/usr/include/%s-%s/", arch, os);
2165         add_pre_buffer("#add_system \"%s/\"\n", path);
2166 }
2167 
2168 struct token * preprocess(struct token *token)
2169 {
2170         preprocessing = 1;
2171         init_preprocessor();
2172         do_preprocess(&token);
2173 
2174         // Drop all expressions from preprocessing, they're not used any more.
2175         // This is not true when we have multiple files, though ;/
2176         // clear_expression_alloc();
2177         preprocessing = 0;
2178 
2179         return token;
2180 }
2181 






2182 static void dump_macro(struct symbol *sym)
2183 {
2184         int nargs = sym->arglist ? sym->arglist->count.normal : 0;
2185         struct token *args[nargs];
2186         struct token *token;
2187 
2188         printf("#define %s", show_ident(sym->ident));
2189         token = sym->arglist;
2190         if (token) {
2191                 const char *sep = "";
2192                 int narg = 0;
2193                 putchar('(');
2194                 for (; !eof_token(token); token = token->next) {
2195                         if (token_type(token) == TOKEN_ARG_COUNT)
2196                                 continue;



2197                         printf("%s%s", sep, show_token(token));
2198                         args[narg++] = token;
2199                         sep = ", ";
2200                 }
2201                 putchar(')');
2202         }
2203         putchar(' ');
2204 
2205         token = sym->expansion;
2206         while (!eof_token(token)) {
2207                 struct token *next = token->next;


2208                 switch (token_type(token)) {
2209                 case TOKEN_UNTAINT:

2210                         break;




2211                 case TOKEN_MACRO_ARGUMENT:
2212                         token = args[token->argnum];
2213                         /* fall-through */
2214                 default:
2215                         printf("%s", show_token(token));
2216                         if (next->pos.whitespace)
2217                                 putchar(' ');
2218                 }
2219                 token = next;
2220         }
2221         putchar('\n');
2222 }
2223 
2224 void dump_macro_definitions(void)
2225 {
2226         struct ident *name;
2227 
2228         FOR_EACH_PTR(macros, name) {
2229                 struct symbol *sym = lookup_macro(name);
2230                 if (sym)
2231                         dump_macro(sym);
2232         } END_FOR_EACH_PTR(name);
2233 }


  32 #include <string.h>
  33 #include <ctype.h>
  34 #include <unistd.h>
  35 #include <fcntl.h>
  36 #include <limits.h>
  37 #include <time.h>
  38 #include <dirent.h>
  39 #include <sys/stat.h>
  40 
  41 #include "lib.h"
  42 #include "allocate.h"
  43 #include "parse.h"
  44 #include "token.h"
  45 #include "symbol.h"
  46 #include "expression.h"
  47 #include "scope.h"
  48 
  49 static struct ident_list *macros;       // only needed for -dD
  50 static int false_nesting = 0;
  51 static int counter_macro = 0;           // __COUNTER__ expansion
  52 static int include_level = 0;
  53 
  54 #define INCLUDEPATHS 300
  55 const char *includepath[INCLUDEPATHS+1] = {
  56         "",
  57         "/usr/include",
  58         "/usr/local/include",
  59         NULL
  60 };
  61 
  62 static const char **quote_includepath = includepath;
  63 static const char **angle_includepath = includepath + 1;
  64 static const char **isys_includepath   = includepath + 1;
  65 static const char **sys_includepath   = includepath + 1;
  66 static const char **dirafter_includepath = includepath + 3;
  67 
  68 #define dirty_stream(stream)                            \
  69         do {                                            \
  70                 if (!stream->dirty) {                        \
  71                         stream->dirty = 1;           \
  72                         if (!stream->ifndef)         \


 131         if (sym && sym->namespace != NS_MACRO)
 132                 sym = NULL;
 133         return sym;
 134 }
 135 
 136 static int token_defined(struct token *token)
 137 {
 138         if (token_type(token) == TOKEN_IDENT) {
 139                 struct symbol *sym = lookup_macro(token->ident);
 140                 if (sym) {
 141                         sym->used_in = file_scope;
 142                         return 1;
 143                 }
 144                 return 0;
 145         }
 146 
 147         sparse_error(token->pos, "expected preprocessor identifier");
 148         return 0;
 149 }
 150 
 151 static void replace_with_bool(struct token *token, bool val)
 152 {
 153         static const char *string[] = { "0", "1" };

 154 
 155         token_type(token) = TOKEN_NUMBER;
 156         token->number = string[val];
 157 }
 158 
 159 static void replace_with_defined(struct token *token)
 160 {
 161         replace_with_bool(token, token_defined(token));
 162 }


 163 
 164 static void replace_with_has_builtin(struct token *token)
 165 {
 166         struct symbol *sym = lookup_symbol(token->ident, NS_SYMBOL);
 167         replace_with_bool(token, sym && sym->builtin);
 168 }
 169 
 170 static void replace_with_has_attribute(struct token *token)
 171 {
 172         struct symbol *sym = lookup_symbol(token->ident, NS_KEYWORD);
 173         replace_with_bool(token, sym && sym->op && sym->op->attribute);
 174 }
 175 
 176 static void expand_line(struct token *token)
 177 {
 178         replace_with_integer(token, token->pos.line);
 179 }
 180 
 181 static void expand_file(struct token *token)
 182 {
 183         replace_with_string(token, stream_name(token->pos.stream));
 184 }
 185 
 186 static void expand_basefile(struct token *token)
 187 {
 188         replace_with_string(token, base_filename);
 189 }
 190 
 191 static time_t t = 0;
 192 static void expand_date(struct token *token)
 193 {
 194         static char buffer[12]; /* __DATE__: 3 + ' ' + 2 + ' ' + 4 + '\0' */
 195 
 196         if (!t)
 197                 time(&t);
 198         strftime(buffer, 12, "%b %e %Y", localtime(&t));
 199         replace_with_string(token, buffer);
 200 }
 201 
 202 static void expand_time(struct token *token)
 203 {
 204         static char buffer[9]; /* __TIME__: 2 + ':' + 2 + ':' + 2 + '\0' */
 205 
 206         if (!t)
 207                 time(&t);
 208         strftime(buffer, 9, "%T", localtime(&t));
 209         replace_with_string(token, buffer);
 210 }
 211 
 212 static void expand_counter(struct token *token)
 213 {
 214         replace_with_integer(token, counter_macro++);
 215 }
 216 
 217 static void expand_include_level(struct token *token)
 218 {
 219         replace_with_integer(token, include_level - 1);
 220 }
 221 
 222 static int expand_one_symbol(struct token **list)
 223 {
 224         struct token *token = *list;
 225         struct symbol *sym;
 226 
 227         if (token->pos.noexpand)
 228                 return 1;
 229 
 230         sym = lookup_macro(token->ident);
 231         if (!sym)
 232                 return 1;
 233         store_macro_pos(token);
 234         if (sym->expander) {
 235                 sym->expander(token);
 236                 return 1;
 237         } else {
 238                 sym->used_in = file_scope;
 239                 return expand(list, sym);
 240         }
 241 }
 242 
 243 static inline struct token *scan_next(struct token **where)
 244 {
 245         struct token *token = *where;
 246         if (token_type(token) != TOKEN_UNTAINT)
 247                 return token;
 248         do {
 249                 token->ident->tainted = 0;
 250                 token = token->next;
 251         } while (token_type(token) == TOKEN_UNTAINT);
 252         *where = token;
 253         return token;
 254 }
 255 
 256 static void expand_list(struct token **list)
 257 {
 258         struct token *next;
 259         while (!eof_token(next = scan_next(list))) {
 260                 if (token_type(next) != TOKEN_IDENT || expand_one_symbol(list))


 545         }
 546 
 547         if (p[0] == '.' && isdigit((unsigned char)p[1]))
 548                 return TOKEN_NUMBER;
 549 
 550         return TOKEN_SPECIAL;
 551 }
 552 
 553 static int merge(struct token *left, struct token *right)
 554 {
 555         static char buffer[512];
 556         enum token_type res = combine(left, right, buffer);
 557         int n;
 558 
 559         switch (res) {
 560         case TOKEN_IDENT:
 561                 left->ident = built_in_ident(buffer);
 562                 left->pos.noexpand = 0;
 563                 return 1;
 564 
 565         case TOKEN_NUMBER:


 566                 token_type(left) = TOKEN_NUMBER;        /* could be . + num */
 567                 left->number = xstrdup(buffer);
 568                 return 1;

 569 
 570         case TOKEN_SPECIAL:
 571                 if (buffer[2] && buffer[3])
 572                         break;
 573                 for (n = SPECIAL_BASE; n < SPECIAL_ARG_SEPARATOR; n++) {
 574                         if (!memcmp(buffer, combinations[n-SPECIAL_BASE], 3)) {
 575                                 left->special = n;
 576                                 return 1;
 577                         }
 578                 }
 579                 break;
 580 
 581         case TOKEN_WIDE_CHAR:
 582         case TOKEN_WIDE_STRING:
 583                 token_type(left) = res;
 584                 left->pos.noexpand = 0;
 585                 left->string = right->string;
 586                 return 1;
 587 
 588         case TOKEN_WIDE_CHAR_EMBEDDED_0 ... TOKEN_WIDE_CHAR_EMBEDDED_3:


 879 
 880 static void set_stream_include_path(struct stream *stream)
 881 {
 882         const char *path = stream->path;
 883         if (!path) {
 884                 const char *p = strrchr(stream->name, '/');
 885                 path = "";
 886                 if (p) {
 887                         int len = p - stream->name + 1;
 888                         char *m = malloc(len+1);
 889                         /* This includes the final "/" */
 890                         memcpy(m, stream->name, len);
 891                         m[len] = 0;
 892                         path = m;
 893                 }
 894                 stream->path = path;
 895         }
 896         includepath[0] = path;
 897 }
 898 
 899 #ifndef PATH_MAX
 900 #define PATH_MAX 4096   // for Hurd where it's not defined
 901 #endif
 902 
 903 static int try_include(const char *path, const char *filename, int flen, struct token **where, const char **next_path)
 904 {
 905         int fd;
 906         int plen = strlen(path);
 907         static char fullname[PATH_MAX];
 908 
 909         memcpy(fullname, path, plen);
 910         if (plen && path[plen-1] != '/') {
 911                 fullname[plen] = '/';
 912                 plen++;
 913         }
 914         memcpy(fullname+plen, filename, flen);
 915         if (already_tokenized(fullname))
 916                 return 1;
 917         fd = open(fullname, O_RDONLY);
 918         if (fd >= 0) {
 919                 char *streamname = xmemdup(fullname, plen + flen);

 920                 *where = tokenize(streamname, fd, *where, next_path);
 921                 close(fd);
 922                 return 1;
 923         }
 924         return 0;
 925 }
 926 
 927 static int do_include_path(const char **pptr, struct token **list, struct token *token, const char *filename, int flen)
 928 {
 929         const char *path;
 930 
 931         while ((path = *pptr++) != NULL) {
 932                 if (!try_include(path, filename, flen, list, pptr))
 933                         continue;
 934                 return 1;
 935         }
 936         return 0;
 937 }
 938 
 939 static int free_preprocessor_line(struct token *token)


 943                 token = token->next;
 944                 __free_token(free);
 945         };
 946         return 1;
 947 }
 948 
 949 const char *find_include(const char *skip, const char *look_for)
 950 {
 951         DIR *dp;
 952         struct dirent *entry;
 953         struct stat statbuf;
 954         const char *ret;
 955         char cwd[PATH_MAX];
 956         static char buf[PATH_MAX + 1];
 957 
 958         dp = opendir(".");
 959         if (!dp)
 960                 return NULL;
 961 
 962         if (!getcwd(cwd, sizeof(cwd)))
 963                 goto close;
 964 
 965         while ((entry = readdir(dp))) {
 966                 lstat(entry->d_name, &statbuf);
 967 
 968                 if (strcmp(entry->d_name, look_for) == 0) {
 969                         snprintf(buf, sizeof(buf), "%s/%s", cwd, entry->d_name);
 970                         closedir(dp);
 971                         return buf;
 972                 }
 973 
 974                 if (S_ISDIR(statbuf.st_mode)) {
 975                         /* Found a directory, but ignore . and .. */
 976                         if (strcmp(".", entry->d_name) == 0 ||
 977                             strcmp("..", entry->d_name) == 0 ||
 978                             strcmp(skip, entry->d_name) == 0)
 979                                 continue;
 980 
 981                         chdir(entry->d_name);
 982                         ret = find_include("", look_for);
 983                         chdir("..");
 984                         if (ret) {
 985                                 closedir(dp);
 986                                 return ret;
 987                         }
 988                 }
 989         }
 990 close:
 991         closedir(dp);
 992 
 993         return NULL;
 994 }
 995 
 996 const char *search_dir(const char *stop, const char *look_for)
 997 {
 998         char cwd[PATH_MAX];
 999         int len;
1000         const char *ret;
1001         int cnt = 0;
1002 
1003         if (!getcwd(cwd, sizeof(cwd)))
1004                 return NULL;
1005 
1006         len = strlen(cwd);
1007         while (len >= 0) {
1008                 ret = find_include(cnt++ ? cwd + len + 1 : "", look_for);
1009                 if (ret)
1010                         return ret;


1017                         return NULL;
1018 
1019                 while (--len >= 0) {
1020                         if (cwd[len] == '/') {
1021                                 cwd[len] = '\0';
1022                                 break;
1023                         }
1024                 }
1025 
1026                 chdir("..");
1027         }
1028         return NULL;
1029 }
1030 
1031 static void use_best_guess_header_file(struct token *token, const char *filename, struct token **list)
1032 {
1033         char cwd[PATH_MAX];
1034         char dir_part[PATH_MAX];
1035         const char *file_part;
1036         const char *include_name;
1037         static int cnt;
1038         int len;
1039 
1040         /* Avoid guessing includes recursively. */
1041         if (cnt++ > 1000)
1042                 return;
1043 
1044         if (!filename || filename[0] == '\0')
1045                 return;
1046 
1047         file_part = filename;
1048         while ((filename = strchr(filename, '/'))) {
1049                 ++filename;
1050                 if (filename[0])
1051                         file_part = filename;
1052         }
1053 
1054         snprintf(dir_part, sizeof(dir_part), "%s", stream_name(token->pos.stream));
1055         len = strlen(dir_part);
1056         while (--len >= 0) {
1057                 if (dir_part[len] == '/') {
1058                         dir_part[len] = '\0';
1059                         break;
1060                 }
1061         }
1062         if (len < 0)
1063                 sprintf(dir_part, ".");


1460                 case TOKEN_WIDE_STRING:
1461                         token->string->immutable = 1;
1462                         break;
1463                 }
1464         }
1465         token = alloc_token(&expansion->pos);
1466         token_type(token) = TOKEN_UNTAINT;
1467         token->ident = name;
1468         token->next = *p;
1469         *p = token;
1470         return expansion;
1471 
1472 Econcat:
1473         sparse_error(token->pos, "'##' cannot appear at the ends of macro expansion");
1474         return NULL;
1475 Earg:
1476         sparse_error(token->pos, "too many instances of argument in body");
1477         return NULL;
1478 }
1479 
1480 static int do_define(struct position pos, struct token *token, struct ident *name,
1481                      struct token *arglist, struct token *expansion, int attr)
1482 {


1483         struct symbol *sym;
1484         int ret = 1;

1485 





















1486         expansion = parse_expansion(expansion, arglist, name);
1487         if (!expansion)
1488                 return 1;
1489 

1490         sym = lookup_symbol(name, NS_MACRO | NS_UNDEF);
1491         if (sym) {
1492                 int clean;
1493 
1494                 if (attr < sym->attr)
1495                         goto out;
1496 
1497                 clean = (attr == sym->attr && sym->namespace == NS_MACRO);
1498 
1499                 if (token_list_different(sym->expansion, expansion) ||
1500                     token_list_different(sym->arglist, arglist)) {
1501                         ret = 0;
1502                         if ((clean && attr == SYM_ATTR_NORMAL)
1503                                         || sym->used_in == file_scope) {
1504                                 warning(pos, "preprocessor token %.*s redefined",
1505                                                 name->len, name->name);
1506                                 info(sym->pos, "this was the original definition");
1507                         }
1508                 } else if (clean)
1509                         goto out;
1510         }
1511 
1512         if (!sym || sym->scope != file_scope) {
1513                 sym = alloc_symbol(pos, SYM_NODE);
1514                 bind_symbol(sym, name, NS_MACRO);
1515                 add_ident(&macros, name);
1516                 ret = 0;
1517         }
1518 
1519         if (!ret) {
1520                 sym->expansion = expansion;
1521                 sym->arglist = arglist;
1522                 if (token) /* Free the "define" token, but not the rest of the line */
1523                         __free_token(token);
1524         }
1525 
1526         sym->namespace = NS_MACRO;
1527         sym->used_in = NULL;
1528         sym->attr = attr;
1529 out:
1530         return ret;
1531 }
1532 
1533 ///
1534 // predefine a macro with a printf-formatted value
1535 // @name: the name of the macro
1536 // @weak: 0/1 for a normal or a weak define
1537 // @fmt: the printf format followed by it's arguments.
1538 //
1539 // The type of the value is automatically infered:
1540 // TOKEN_NUMBER if it starts by a digit, TOKEN_IDENT otherwise.
1541 // If @fmt is null or empty, the macro is defined with an empty definition.
1542 void predefine(const char *name, int weak, const char *fmt, ...)
1543 {
1544         struct ident *ident = built_in_ident(name);
1545         struct token *value = &eof_token_entry;
1546         int attr = weak ? SYM_ATTR_WEAK : SYM_ATTR_NORMAL;
1547 
1548         if (fmt && fmt[0]) {
1549                 static char buf[256];
1550                 va_list ap;
1551 
1552                 va_start(ap, fmt);
1553                 vsnprintf(buf, sizeof(buf), fmt, ap);
1554                 va_end(ap);
1555 
1556                 value = __alloc_token(0);
1557                 if (isdigit(buf[0])) {
1558                         token_type(value) = TOKEN_NUMBER;
1559                         value->number = xstrdup(buf);
1560                 } else {
1561                         token_type(value) = TOKEN_IDENT;
1562                         value->ident = built_in_ident(buf);
1563                 }
1564                 value->pos.whitespace = 1;
1565                 value->next = &eof_token_entry;
1566         }
1567 
1568         do_define(value->pos, NULL, ident, NULL, value, attr);
1569 }
1570 
1571 static int do_handle_define(struct stream *stream, struct token **line, struct token *token, int attr)
1572 {
1573         struct token *arglist, *expansion;
1574         struct token *left = token->next;
1575         struct ident *name;
1576 
1577         if (token_type(left) != TOKEN_IDENT) {
1578                 sparse_error(token->pos, "expected identifier to 'define'");
1579                 return 1;
1580         }
1581 
1582         name = left->ident;
1583 
1584         arglist = NULL;
1585         expansion = left->next;
1586         if (!expansion->pos.whitespace) {
1587                 if (match_op(expansion, '(')) {
1588                         arglist = expansion;
1589                         expansion = parse_arguments(expansion);
1590                         if (!expansion)
1591                                 return 1;
1592                 } else if (!eof_token(expansion)) {
1593                         warning(expansion->pos,
1594                                 "no whitespace before object-like macro body");
1595                 }
1596         }
1597 
1598         return do_define(left->pos, token, name, arglist, expansion, attr);
1599 }
1600 
1601 static int handle_define(struct stream *stream, struct token **line, struct token *token)
1602 {
1603         return do_handle_define(stream, line, token, SYM_ATTR_NORMAL);
1604 }
1605 
1606 static int handle_weak_define(struct stream *stream, struct token **line, struct token *token)
1607 {
1608         return do_handle_define(stream, line, token, SYM_ATTR_WEAK);
1609 }
1610 
1611 static int handle_strong_define(struct stream *stream, struct token **line, struct token *token)
1612 {
1613         return do_handle_define(stream, line, token, SYM_ATTR_STRONG);
1614 }
1615 
1616 static int do_handle_undef(struct stream *stream, struct token **line, struct token *token, int attr)
1617 {
1618         struct token *left = token->next;
1619         struct symbol *sym;
1620 


1637                 bind_symbol(sym, left->ident, NS_MACRO);
1638         }
1639 
1640         sym->namespace = NS_UNDEF;
1641         sym->used_in = NULL;
1642         sym->attr = attr;
1643 
1644         return 1;
1645 }
1646 
1647 static int handle_undef(struct stream *stream, struct token **line, struct token *token)
1648 {
1649         return do_handle_undef(stream, line, token, SYM_ATTR_NORMAL);
1650 }
1651 
1652 static int handle_strong_undef(struct stream *stream, struct token **line, struct token *token)
1653 {
1654         return do_handle_undef(stream, line, token, SYM_ATTR_STRONG);
1655 }
1656 
1657 static int preprocessor_if(struct stream *stream, struct token *token, int cond)
1658 {
1659         token_type(token) = false_nesting ? TOKEN_SKIP_GROUPS : TOKEN_IF;
1660         free_preprocessor_line(token->next);
1661         token->next = stream->top_if;
1662         stream->top_if = token;
1663         if (false_nesting || cond != 1)
1664                 false_nesting++;
1665         return 0;
1666 }
1667 
1668 static int handle_ifdef(struct stream *stream, struct token **line, struct token *token)
1669 {
1670         struct token *next = token->next;
1671         int arg;
1672         if (token_type(next) == TOKEN_IDENT) {
1673                 arg = token_defined(next);
1674         } else {
1675                 dirty_stream(stream);
1676                 if (!false_nesting)
1677                         sparse_error(token->pos, "expected preprocessor identifier");
1678                 arg = -1;
1679         }
1680         return preprocessor_if(stream, token, arg);
1681 }
1682 
1683 static int handle_ifndef(struct stream *stream, struct token **line, struct token *token)


1711  * Expression handling for #if and #elif; it differs from normal expansion
1712  * due to special treatment of "defined".
1713  */
1714 static int expression_value(struct token **where)
1715 {
1716         struct expression *expr;
1717         struct token *p;
1718         struct token **list = where, **beginning = NULL;
1719         long long value;
1720         int state = 0;
1721 
1722         while (!eof_token(p = scan_next(list))) {
1723                 switch (state) {
1724                 case 0:
1725                         if (token_type(p) != TOKEN_IDENT)
1726                                 break;
1727                         if (p->ident == &defined_ident) {
1728                                 state = 1;
1729                                 beginning = list;
1730                                 break;
1731                         } else if (p->ident == &__has_builtin_ident) {
1732                                 state = 4;
1733                                 beginning = list;
1734                                 break;
1735                         } else if (p->ident == &__has_attribute_ident) {
1736                                 state = 6;
1737                                 beginning = list;
1738                                 break;
1739                         }
1740                         if (!expand_one_symbol(list))
1741                                 continue;
1742                         if (token_type(p) != TOKEN_IDENT)
1743                                 break;
1744                         token_type(p) = TOKEN_ZERO_IDENT;
1745                         break;
1746                 case 1:
1747                         if (match_op(p, '(')) {
1748                                 state = 2;
1749                         } else {
1750                                 state = 0;
1751                                 replace_with_defined(p);
1752                                 *beginning = p;
1753                         }
1754                         break;
1755                 case 2:
1756                         if (token_type(p) == TOKEN_IDENT)
1757                                 state = 3;
1758                         else
1759                                 state = 0;
1760                         replace_with_defined(p);
1761                         *beginning = p;
1762                         break;
1763                 case 3:
1764                         state = 0;
1765                         if (!match_op(p, ')'))
1766                                 sparse_error(p->pos, "missing ')' after \"defined\"");
1767                         *list = p->next;
1768                         continue;
1769 
1770                 // __has_builtin(x) or __has_attribute(x)
1771                 case 4: case 6:
1772                         if (match_op(p, '(')) {
1773                                 state++;
1774                         } else {
1775                                 sparse_error(p->pos, "missing '(' after \"__has_%s\"",
1776                                         state == 4 ? "builtin" : "attribute");
1777                                 state = 0;
1778                         }
1779                         *beginning = p;
1780                         break;
1781                 case 5: case 7:
1782                         if (token_type(p) != TOKEN_IDENT) {
1783                                 sparse_error(p->pos, "identifier expected");
1784                                 state = 0;
1785                                 break;
1786                         }
1787                         if (!match_op(p->next, ')'))
1788                                 sparse_error(p->pos, "missing ')' after \"__has_%s\"",
1789                                         state == 5 ? "builtin" : "attribute");
1790                         if (state == 5)
1791                                 replace_with_has_builtin(p);
1792                         else
1793                                 replace_with_has_attribute(p);
1794                         state = 8;
1795                         *beginning = p;
1796                         break;
1797                 case 8:
1798                         state = 0;
1799                         *list = p->next;
1800                         continue;
1801                 }
1802                 list = &p->next;
1803         }
1804 
1805         p = constant_expression(*where, &expr);
1806         if (!eof_token(p))
1807                 sparse_error(p->pos, "garbage at end: %s", show_token_sequence(p, 0));
1808         value = get_expression_value(expr);
1809         return value != 0;
1810 }
1811 
1812 static int handle_if(struct stream *stream, struct token **line, struct token *token)
1813 {
1814         int value = 0;
1815         if (!false_nesting)
1816                 value = expression_value(&token->next);
1817 
1818         dirty_stream(stream);
1819         return preprocessor_if(stream, token, value);
1820 }
1821 


2094                 stream->once = 1;
2095                 return 1;
2096         }
2097         token->ident = &pragma_ident;
2098         token->pos.newline = 1;
2099         token->pos.whitespace = 1;
2100         token->pos.pos = 1;
2101         *line = token;
2102         token->next = next;
2103         return 0;
2104 }
2105 
2106 /*
2107  * We ignore #line for now.
2108  */
2109 static int handle_line(struct stream *stream, struct token **line, struct token *token)
2110 {
2111         return 1;
2112 }
2113 



2114 static int handle_ident(struct stream *stream, struct token **line, struct token *token)
2115 {
2116         return 1;
2117 }
2118 
2119 static int handle_nondirective(struct stream *stream, struct token **line, struct token *token)
2120 {
2121         sparse_error(token->pos, "unrecognized preprocessor line '%s'", show_token_sequence(token, 0));
2122         return 1;
2123 }
2124 
2125 
2126 static void init_preprocessor(void)
2127 {
2128         int i;
2129         int stream = init_stream("preprocessor", -1, includepath);
2130         static struct {
2131                 const char *name;
2132                 int (*handler)(struct stream *, struct token **, struct token *);
2133         } normal[] = {


2143                 { "pragma",             handle_pragma },
2144                 { "line",               handle_line },
2145                 { "ident",              handle_ident },
2146 
2147                 // our internal preprocessor tokens
2148                 { "nostdinc",      handle_nostdinc },
2149                 { "add_include",   handle_add_include },
2150                 { "add_isystem",   handle_add_isystem },
2151                 { "add_system",    handle_add_system },
2152                 { "add_dirafter",  handle_add_dirafter },
2153                 { "split_include", handle_split_include },
2154                 { "argv_include",  handle_argv_include },
2155         }, special[] = {
2156                 { "ifdef",      handle_ifdef },
2157                 { "ifndef",     handle_ifndef },
2158                 { "else",       handle_else },
2159                 { "endif",      handle_endif },
2160                 { "if",         handle_if },
2161                 { "elif",       handle_elif },
2162         };
2163         static struct {
2164                 const char *name;
2165                 void (*expander)(struct token *);
2166         } dynamic[] = {
2167                 { "__LINE__",           expand_line },
2168                 { "__FILE__",           expand_file },
2169                 { "__BASE_FILE__",      expand_basefile },
2170                 { "__DATE__",           expand_date },
2171                 { "__TIME__",           expand_time },
2172                 { "__COUNTER__",        expand_counter },
2173                 { "__INCLUDE_LEVEL__",  expand_include_level },
2174         };
2175 
2176         for (i = 0; i < ARRAY_SIZE(normal); i++) {
2177                 struct symbol *sym;
2178                 sym = create_symbol(stream, normal[i].name, SYM_PREPROCESSOR, NS_PREPROCESSOR);
2179                 sym->handler = normal[i].handler;
2180                 sym->normal = 1;
2181         }
2182         for (i = 0; i < ARRAY_SIZE(special); i++) {
2183                 struct symbol *sym;
2184                 sym = create_symbol(stream, special[i].name, SYM_PREPROCESSOR, NS_PREPROCESSOR);
2185                 sym->handler = special[i].handler;
2186                 sym->normal = 0;
2187         }
2188         for (i = 0; i < ARRAY_SIZE(dynamic); i++) {
2189                 struct symbol *sym;
2190                 sym = create_symbol(stream, dynamic[i].name, SYM_NODE, NS_MACRO);
2191                 sym->expander = dynamic[i].expander;
2192         }
2193 
2194         counter_macro = 0;
2195 }
2196 
2197 static void handle_preprocessor_line(struct stream *stream, struct token **line, struct token *start)
2198 {
2199         int (*handler)(struct stream *, struct token **, struct token *);
2200         struct token *token = start->next;
2201         int is_normal = 1;
2202 
2203         if (eof_token(token))
2204                 return;
2205 
2206         if (token_type(token) == TOKEN_IDENT) {
2207                 struct symbol *sym = lookup_symbol(token->ident, NS_PREPROCESSOR);
2208                 if (sym) {
2209                         handler = sym->handler;
2210                         is_normal = sym->normal;
2211                 } else {
2212                         handler = handle_nondirective;


2254 
2255                 if (next->pos.newline && match_op(next, '#')) {
2256                         if (!next->pos.noexpand) {
2257                                 preprocessor_line(stream, list);
2258                                 __free_token(next);     /* Free the '#' token */
2259                                 continue;
2260                         }
2261                 }
2262 
2263                 switch (token_type(next)) {
2264                 case TOKEN_STREAMEND:
2265                         if (stream->top_if) {
2266                                 nesting_error(stream);
2267                                 sparse_error(stream->top_if->pos, "unterminated preprocessor conditional");
2268                                 stream->top_if = NULL;
2269                                 false_nesting = 0;
2270                         }
2271                         if (!stream->dirty)
2272                                 stream->constant = CONSTANT_FILE_YES;
2273                         *list = next->next;
2274                         include_level--;
2275                         continue;
2276                 case TOKEN_STREAMBEGIN:
2277                         *list = next->next;
2278                         include_level++;
2279                         continue;
2280 
2281                 default:
2282                         dirty_stream(stream);
2283                         if (false_nesting) {
2284                                 *list = next->next;
2285                                 __free_token(next);
2286                                 continue;
2287                         }
2288 
2289                         if (token_type(next) != TOKEN_IDENT ||
2290                             expand_one_symbol(list))
2291                                 list = &next->next;
2292                 }
2293         }
2294 }
2295 
2296 void init_include_path(void)
2297 {
2298         FILE *fp;


2320         strcpy(os, "linux-gnu");
2321 
2322         snprintf(path, sizeof(path), "/usr/include/%s-%s/", arch, os);
2323         add_pre_buffer("#add_system \"%s/\"\n", path);
2324 }
2325 
2326 struct token * preprocess(struct token *token)
2327 {
2328         preprocessing = 1;
2329         init_preprocessor();
2330         do_preprocess(&token);
2331 
2332         // Drop all expressions from preprocessing, they're not used any more.
2333         // This is not true when we have multiple files, though ;/
2334         // clear_expression_alloc();
2335         preprocessing = 0;
2336 
2337         return token;
2338 }
2339 
2340 static int is_VA_ARGS_token(struct token *token)
2341 {
2342         return (token_type(token) == TOKEN_IDENT) &&
2343                 (token->ident == &__VA_ARGS___ident);
2344 }
2345 
2346 static void dump_macro(struct symbol *sym)
2347 {
2348         int nargs = sym->arglist ? sym->arglist->count.normal : 0;
2349         struct token *args[nargs];
2350         struct token *token;
2351 
2352         printf("#define %s", show_ident(sym->ident));
2353         token = sym->arglist;
2354         if (token) {
2355                 const char *sep = "";
2356                 int narg = 0;
2357                 putchar('(');
2358                 for (; !eof_token(token); token = token->next) {
2359                         if (token_type(token) == TOKEN_ARG_COUNT)
2360                                 continue;
2361                         if (is_VA_ARGS_token(token))
2362                                 printf("%s...", sep);
2363                         else
2364                                 printf("%s%s", sep, show_token(token));
2365                         args[narg++] = token;
2366                         sep = ",";
2367                 }
2368                 putchar(')');
2369         }

2370 
2371         token = sym->expansion;
2372         while (token_type(token) != TOKEN_UNTAINT) {
2373                 struct token *next = token->next;
2374                 if (token->pos.whitespace)
2375                         putchar(' ');
2376                 switch (token_type(token)) {
2377                 case TOKEN_CONCAT:
2378                         printf("##");
2379                         break;
2380                 case TOKEN_STR_ARGUMENT:
2381                         printf("#");
2382                         /* fall-through */
2383                 case TOKEN_QUOTED_ARGUMENT:
2384                 case TOKEN_MACRO_ARGUMENT:
2385                         token = args[token->argnum];
2386                         /* fall-through */
2387                 default:
2388                         printf("%s", show_token(token));


2389                 }
2390                 token = next;
2391         }
2392         putchar('\n');
2393 }
2394 
2395 void dump_macro_definitions(void)
2396 {
2397         struct ident *name;
2398 
2399         FOR_EACH_PTR(macros, name) {
2400                 struct symbol *sym = lookup_macro(name);
2401                 if (sym)
2402                         dump_macro(sym);
2403         } END_FOR_EACH_PTR(name);
2404 }