1 /*
   2  * 'sparse' library helper routines.
   3  *
   4  * Copyright (C) 2003 Transmeta Corp.
   5  *               2003-2004 Linus Torvalds
   6  *
   7  * Permission is hereby granted, free of charge, to any person obtaining a copy
   8  * of this software and associated documentation files (the "Software"), to deal
   9  * in the Software without restriction, including without limitation the rights
  10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11  * copies of the Software, and to permit persons to whom the Software is
  12  * furnished to do so, subject to the following conditions:
  13  *
  14  * The above copyright notice and this permission notice shall be included in
  15  * all copies or substantial portions of the Software.
  16  *
  17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23  * THE SOFTWARE.
  24  */
  25 #include <ctype.h>
  26 #include <errno.h>
  27 #include <fcntl.h>
  28 #include <stdarg.h>
  29 #include <stddef.h>
  30 #include <stdio.h>
  31 #include <stdlib.h>
  32 #include <string.h>
  33 #include <unistd.h>
  34 #include <assert.h>
  35 
  36 #include <sys/types.h>
  37 
  38 #include "lib.h"
  39 #include "allocate.h"
  40 #include "token.h"
  41 #include "parse.h"
  42 #include "symbol.h"
  43 #include "expression.h"
  44 #include "evaluate.h"
  45 #include "scope.h"
  46 #include "linearize.h"
  47 #include "target.h"
  48 #include "machine.h"
  49 #include "version.h"
  50 #include "bits.h"
  51 
  52 int verbose, optimize_level, optimize_size, preprocessing;
  53 int die_if_error = 0;
  54 int parse_error;
  55 int has_error = 0;
  56 int do_output = 0;
  57 
  58 #ifndef __GNUC__
  59 # define __GNUC__ 2
  60 # define __GNUC_MINOR__ 95
  61 # define __GNUC_PATCHLEVEL__ 0
  62 #endif
  63 
  64 int gcc_major = __GNUC__;
  65 int gcc_minor = __GNUC_MINOR__;
  66 int gcc_patchlevel = __GNUC_PATCHLEVEL__;
  67 
  68 const char *base_filename;
  69 
  70 static const char *diag_prefix = "";
  71 static const char *gcc_base_dir = GCC_BASE;
  72 static const char *multiarch_dir = MULTIARCH_TRIPLET;
  73 static const char *outfile = NULL;
  74 
  75 struct token *skip_to(struct token *token, int op)
  76 {
  77         while (!match_op(token, op) && !eof_token(token))
  78                 token = token->next;
  79         return token;
  80 }
  81 
  82 static struct token bad_token = { .pos.type = TOKEN_BAD };
  83 struct token *expect(struct token *token, int op, const char *where)
  84 {
  85         if (!match_op(token, op)) {
  86                 if (token != &bad_token) {
  87                         bad_token.next = token;
  88                         sparse_error(token->pos, "Expected %s %s", show_special(op), where);
  89                         sparse_error(token->pos, "got %s", show_token(token));
  90                 }
  91                 if (op == ';')
  92                         return skip_to(token, op);
  93                 return &bad_token;
  94         }
  95         return token->next;
  96 }
  97 
  98 ///
  99 // issue an error message on new parsing errors
 100 // @token: the current token
 101 // @errmsg: the error message
 102 // If the current token is from a previous error, an error message
 103 // has already been issued, so nothing more is done.
 104 // Otherwise, @errmsg is displayed followed by the current token.
 105 void unexpected(struct token *token, const char *errmsg)
 106 {
 107         if (token == &bad_token)
 108                 return;
 109         sparse_error(token->pos, "%s", errmsg);
 110         sparse_error(token->pos, "got %s", show_token(token));
 111 }
 112 
 113 unsigned int hexval(unsigned int c)
 114 {
 115         int retval = 256;
 116         switch (c) {
 117         case '0'...'9':
 118                 retval = c - '0';
 119                 break;
 120         case 'a'...'f':
 121                 retval = c - 'a' + 10;
 122                 break;
 123         case 'A'...'F':
 124                 retval = c - 'A' + 10;
 125                 break;
 126         }
 127         return retval;
 128 }
 129 
 130 static void do_warn(const char *type, struct position pos, const char * fmt, va_list args)
 131 {
 132         static char buffer[512];
 133         const char *name;
 134 
 135         /* Shut up warnings if position is bad_token.pos */
 136         if (pos.type == TOKEN_BAD)
 137                 return;
 138 
 139         vsprintf(buffer, fmt, args);    
 140         name = stream_name(pos.stream);
 141                 
 142         fflush(stdout);
 143         fprintf(stderr, "%s: %s:%d:%d: %s%s\n",
 144                 diag_prefix, name, pos.line, pos.pos, type, buffer);
 145 }
 146 
 147 unsigned int fmax_warnings = 100;
 148 static int show_info = 1;
 149 
 150 void info(struct position pos, const char * fmt, ...)
 151 {
 152         va_list args;
 153 
 154         if (!show_info)
 155                 return;
 156         va_start(args, fmt);
 157         do_warn("", pos, fmt, args);
 158         va_end(args);
 159 }
 160 
 161 static void do_error(struct position pos, const char * fmt, va_list args)
 162 {
 163         static int errors = 0;
 164 
 165         parse_error = 1;
 166         die_if_error = 1;
 167         show_info = 1;
 168         /* Shut up warnings if position is bad_token.pos */
 169         if (pos.type == TOKEN_BAD)
 170                 return;
 171         /* Shut up warnings after an error */
 172         has_error |= ERROR_CURR_PHASE;
 173         if (errors > 100) {
 174                 static int once = 0;
 175                 show_info = 0;
 176                 if (once)
 177                         return;
 178                 fmt = "too many errors";
 179                 once = 1;
 180         }
 181 
 182         do_warn("error: ", pos, fmt, args);
 183         errors++;
 184 }       
 185 
 186 void warning(struct position pos, const char * fmt, ...)
 187 {
 188         va_list args;
 189 
 190         if (Wsparse_error) {
 191                 va_start(args, fmt);
 192                 do_error(pos, fmt, args);
 193                 va_end(args);
 194                 return;
 195         }
 196 
 197         if (!fmax_warnings || has_error) {
 198                 show_info = 0;
 199                 return;
 200         }
 201 
 202         if (!--fmax_warnings) {
 203                 show_info = 0;
 204                 fmt = "too many warnings";
 205         }
 206 
 207         va_start(args, fmt);
 208         do_warn("warning: ", pos, fmt, args);
 209         va_end(args);
 210 }
 211 
 212 void sparse_error(struct position pos, const char * fmt, ...)
 213 {
 214         va_list args;
 215         va_start(args, fmt);
 216         do_error(pos, fmt, args);
 217         va_end(args);
 218 }
 219 
 220 void expression_error(struct expression *expr, const char *fmt, ...)
 221 {
 222         va_list args;
 223         va_start(args, fmt);
 224         do_error(expr->pos, fmt, args);
 225         va_end(args);
 226         expr->ctype = &bad_ctype;
 227 }
 228 
 229 NORETURN_ATTR
 230 void error_die(struct position pos, const char * fmt, ...)
 231 {
 232         va_list args;
 233         va_start(args, fmt);
 234         do_warn("error: ", pos, fmt, args);
 235         va_end(args);
 236         exit(1);
 237 }
 238 
 239 NORETURN_ATTR
 240 void die(const char *fmt, ...)
 241 {
 242         va_list args;
 243         static char buffer[512];
 244 
 245         va_start(args, fmt);
 246         vsnprintf(buffer, sizeof(buffer), fmt, args);
 247         va_end(args);
 248 
 249         fprintf(stderr, "%s: %s\n", diag_prefix, buffer);
 250         exit(1);
 251 }
 252 
 253 static struct token *pre_buffer_begin = NULL;
 254 static struct token *pre_buffer_end = NULL;
 255 
 256 int Waddress = 0;
 257 int Waddress_space = 1;
 258 int Wbitwise = 1;
 259 int Wbitwise_pointer = 0;
 260 int Wcast_from_as = 0;
 261 int Wcast_to_as = 0;
 262 int Wcast_truncate = 1;
 263 int Wconstant_suffix = 0;
 264 int Wconstexpr_not_const = 0;
 265 int Wcontext = 1;
 266 int Wdecl = 1;
 267 int Wdeclarationafterstatement = -1;
 268 int Wdefault_bitfield_sign = 0;
 269 int Wdesignated_init = 1;
 270 int Wdo_while = 0;
 271 int Wimplicit_int = 1;
 272 int Winit_cstring = 0;
 273 int Wint_to_pointer_cast = 1;
 274 int Wenum_mismatch = 1;
 275 int Wexternal_function_has_definition = 1;
 276 int Wsparse_error = 0;
 277 int Wmemcpy_max_count = 1;
 278 int Wnon_pointer_null = 1;
 279 int Wold_initializer = 1;
 280 int Wold_style_definition = 1;
 281 int Wone_bit_signed_bitfield = 1;
 282 int Woverride_init = 1;
 283 int Woverride_init_all = 0;
 284 int Woverride_init_whole_range = 0;
 285 int Wparen_string = 0;
 286 int Wpointer_arith = 0;
 287 int Wpointer_to_int_cast = 1;
 288 int Wptr_subtraction_blows = 0;
 289 int Wreturn_void = 0;
 290 int Wshadow = 0;
 291 int Wshift_count_negative = 1;
 292 int Wshift_count_overflow = 1;
 293 int Wsizeof_bool = 0;
 294 int Wstrict_prototypes = 1;
 295 int Wtautological_compare = 0;
 296 int Wtransparent_union = 0;
 297 int Wtypesign = 0;
 298 int Wundef = 0;
 299 int Wuninitialized = 1;
 300 int Wunknown_attribute = 0;
 301 int Wvla = 1;
 302 
 303 int dump_macro_defs = 0;
 304 int dump_macros_only = 0;
 305 
 306 int dbg_compound = 0;
 307 int dbg_dead = 0;
 308 int dbg_domtree = 0;
 309 int dbg_entry = 0;
 310 int dbg_ir = 0;
 311 int dbg_postorder = 0;
 312 
 313 unsigned long fdump_ir;
 314 int fmem_report = 0;
 315 unsigned long long fmemcpy_max_count = 100000;
 316 unsigned long fpasses = ~0UL;
 317 int funsigned_char = UNSIGNED_CHAR;
 318 
 319 int preprocess_only;
 320 
 321 enum standard standard = STANDARD_GNU89;
 322 
 323 int arch_m64 = ARCH_M64_DEFAULT;
 324 int arch_msize_long = 0;
 325 int arch_big_endian = ARCH_BIG_ENDIAN;
 326 int arch_mach = MACH_NATIVE;
 327 
 328 
 329 #define CMDLINE_INCLUDE 20
 330 static int cmdline_include_nr = 0;
 331 static char *cmdline_include[CMDLINE_INCLUDE];
 332 
 333 
 334 void add_pre_buffer(const char *fmt, ...)
 335 {
 336         va_list args;
 337         unsigned int size;
 338         struct token *begin, *end;
 339         char buffer[4096];
 340 
 341         va_start(args, fmt);
 342         size = vsnprintf(buffer, sizeof(buffer), fmt, args);
 343         va_end(args);
 344         begin = tokenize_buffer(buffer, size, &end);
 345         if (!pre_buffer_begin)
 346                 pre_buffer_begin = begin;
 347         if (pre_buffer_end)
 348                 pre_buffer_end->next = begin;
 349         pre_buffer_end = end;
 350 }
 351 
 352 static char **handle_switch_D(char *arg, char **next)
 353 {
 354         const char *name = arg + 1;
 355         const char *value = "1";
 356 
 357         if (!*name) {
 358                 arg = *++next;
 359                 if (!arg)
 360                         die("argument to `-D' is missing");
 361                 name = arg;
 362         }
 363 
 364         for (;;arg++) {
 365                 char c;
 366                 c = *arg;
 367                 if (!c)
 368                         break;
 369                 if (c == '=') {
 370                         *arg = '\0';
 371                         value = arg + 1;
 372                         break;
 373                 }
 374         }
 375         add_pre_buffer("#define %s %s\n", name, value);
 376         return next;
 377 }
 378 
 379 static char **handle_switch_E(char *arg, char **next)
 380 {
 381         if (arg[1] == '\0')
 382                 preprocess_only = 1;
 383         return next;
 384 }
 385 
 386 static char **handle_switch_I(char *arg, char **next)
 387 {
 388         char *path = arg+1;
 389 
 390         switch (arg[1]) {
 391         case '-':
 392                 add_pre_buffer("#split_include\n");
 393                 break;
 394 
 395         case '\0':      /* Plain "-I" */
 396                 path = *++next;
 397                 if (!path)
 398                         die("missing argument for -I option");
 399                 /* Fall through */
 400         default:
 401                 add_pre_buffer("#add_include \"%s/\"\n", path);
 402         }
 403         return next;
 404 }
 405 
 406 static void add_cmdline_include(char *filename)
 407 {
 408         if (cmdline_include_nr >= CMDLINE_INCLUDE)
 409                 die("too many include files for %s\n", filename);
 410         cmdline_include[cmdline_include_nr++] = filename;
 411 }
 412 
 413 static char **handle_switch_i(char *arg, char **next)
 414 {
 415         if (*next && !strcmp(arg, "include"))
 416                 add_cmdline_include(*++next);
 417         else if (*next && !strcmp(arg, "imacros"))
 418                 add_cmdline_include(*++next);
 419         else if (*next && !strcmp(arg, "isystem")) {
 420                 char *path = *++next;
 421                 if (!path)
 422                         die("missing argument for -isystem option");
 423                 add_pre_buffer("#add_isystem \"%s/\"\n", path);
 424         } else if (*next && !strcmp(arg, "idirafter")) {
 425                 char *path = *++next;
 426                 if (!path)
 427                         die("missing argument for -idirafter option");
 428                 add_pre_buffer("#add_dirafter \"%s/\"\n", path);
 429         }
 430         return next;
 431 }
 432 
 433 static char **handle_switch_M(char *arg, char **next)
 434 {
 435         if (!strcmp(arg, "MF") || !strcmp(arg,"MQ") || !strcmp(arg,"MT")) {
 436                 if (!*next)
 437                         die("missing argument for -%s option", arg);
 438                 return next + 1;
 439         }
 440         return next;
 441 }
 442 
 443 static char **handle_multiarch_dir(char *arg, char **next)
 444 {
 445         multiarch_dir = *++next;
 446         if (!multiarch_dir)
 447                 die("missing argument for -multiarch-dir option");
 448         return next;
 449 }
 450 
 451 static char **handle_switch_m(char *arg, char **next)
 452 {
 453         if (!strcmp(arg, "m64")) {
 454                 arch_m64 = ARCH_LP64;
 455         } else if (!strcmp(arg, "m32") || !strcmp(arg, "m16")) {
 456                 arch_m64 = ARCH_LP32;
 457         } else if (!strcmp(arg, "mx32")) {
 458                 arch_m64 = ARCH_X32;
 459         } else if (!strcmp(arg, "msize-llp64")) {
 460                 arch_m64 = ARCH_LLP64;
 461         } else if (!strcmp(arg, "msize-long")) {
 462                 arch_msize_long = 1;
 463         } else if (!strcmp(arg, "multiarch-dir")) {
 464                 return handle_multiarch_dir(arg, next);
 465         } else if (!strcmp(arg, "mbig-endian")) {
 466                 arch_big_endian = 1;
 467         } else if (!strcmp(arg, "mlittle-endian")) {
 468                 arch_big_endian = 0;
 469         }
 470         return next;
 471 }
 472 
 473 static void handle_arch_msize_long_finalize(void)
 474 {
 475         if (arch_msize_long) {
 476                 size_t_ctype = &ulong_ctype;
 477                 ssize_t_ctype = &long_ctype;
 478         }
 479 }
 480 
 481 static void handle_arch_finalize(void)
 482 {
 483         handle_arch_msize_long_finalize();
 484 }
 485 
 486 static const char *match_option(const char *arg, const char *prefix)
 487 {
 488         unsigned int n = strlen(prefix);
 489         if (strncmp(arg, prefix, n) == 0)
 490                 return arg + n;
 491         return NULL;
 492 }
 493 
 494 
 495 struct mask_map {
 496         const char *name;
 497         unsigned long mask;
 498 };
 499 
 500 static int apply_mask(unsigned long *val, const char *str, unsigned len, const struct mask_map *map, int neg)
 501 {
 502         const char *name;
 503 
 504         for (;(name = map->name); map++) {
 505                 if (!strncmp(name, str, len) && !name[len]) {
 506                         if (neg == 0)
 507                                 *val |= map->mask;
 508                         else
 509                                 *val &= ~map->mask;
 510                         return 0;
 511                 }
 512         }
 513         return 1;
 514 }
 515 
 516 static int handle_suboption_mask(const char *arg, const char *opt, const struct mask_map *map, unsigned long *flag)
 517 {
 518         if (*opt == '\0') {
 519                 apply_mask(flag, "", 0, map, 0);
 520                 return 1;
 521         }
 522         if (*opt++ != '=')
 523                 return 0;
 524         while (1) {
 525                 unsigned int len = strcspn(opt, ",+");
 526                 int neg = 0;
 527                 if (len == 0)
 528                         goto end;
 529                 if (!strncmp(opt, "no-", 3)) {
 530                         opt += 3;
 531                         len -= 3;
 532                         neg = 1;
 533                 }
 534                 if (apply_mask(flag, opt, len, map, neg))
 535                         die("error: wrong option '%.*s' for \'%s\'", len, opt, arg);
 536 
 537 end:
 538                 opt += len;
 539                 if (*opt++ == '\0')
 540                         break;
 541         }
 542         return 1;
 543 }
 544 
 545 
 546 #define OPT_INVERSE     1
 547 struct flag {
 548         const char *name;
 549         int *flag;
 550         int (*fun)(const char *arg, const char *opt, const struct flag *, int options);
 551         unsigned long mask;
 552 };
 553 
 554 static int handle_switches(const char *ori, const char *opt, const struct flag *flags)
 555 {
 556         const char *arg = opt;
 557         int val = 1;
 558 
 559         // Prefixe "no-" mean to turn flag off.
 560         if (strncmp(arg, "no-", 3) == 0) {
 561                 arg += 3;
 562                 val = 0;
 563         }
 564 
 565         for (; flags->name; flags++) {
 566                 const char *opt = match_option(arg, flags->name);
 567                 int rc;
 568 
 569                 if (!opt)
 570                         continue;
 571 
 572                 if (flags->fun) {
 573                         int options = 0;
 574                         if (!val)
 575                                 options |= OPT_INVERSE;
 576                         if ((rc = flags->fun(ori, opt, flags, options)))
 577                                 return rc;
 578                 }
 579 
 580                 // boolean flag
 581                 if (opt[0] == '\0' && flags->flag) {
 582                         if (flags->mask & OPT_INVERSE)
 583                                 val = !val;
 584                         *flags->flag = val;
 585                         return 1;
 586                 }
 587         }
 588 
 589         // not handled
 590         return 0;
 591 }
 592 
 593 
 594 #define OPTNUM_ZERO_IS_INF              1
 595 #define OPTNUM_UNLIMITED                2
 596 
 597 #define OPT_NUMERIC(NAME, TYPE, FUNCTION)       \
 598 static int opt_##NAME(const char *arg, const char *opt, TYPE *ptr, int flag)    \
 599 {                                                                       \
 600         char *end;                                                      \
 601         TYPE val;                                                       \
 602                                                                         \
 603         val = FUNCTION(opt, &end, 0);                                       \
 604         if (*end != '\0' || end == opt) {                               \
 605                 if ((flag & OPTNUM_UNLIMITED) && !strcmp(opt, "unlimited")) \
 606                         val = ~val;                                     \
 607                 else                                                    \
 608                         die("error: wrong argument to \'%s\'", arg);    \
 609         }                                                               \
 610         if ((flag & OPTNUM_ZERO_IS_INF) && val == 0)                        \
 611                 val = ~val;                                             \
 612         *ptr = val;                                                     \
 613         return 1;                                                       \
 614 }
 615 
 616 OPT_NUMERIC(ullong, unsigned long long, strtoull)
 617 OPT_NUMERIC(uint, unsigned int, strtoul)
 618 
 619 
 620 static char **handle_switch_o(char *arg, char **next)
 621 {
 622         if (!strcmp (arg, "o")) {       // "-o foo"
 623                 if (!*++next)
 624                         die("argument to '-o' is missing");
 625                 outfile = *next;
 626         }
 627         // else "-ofoo"
 628 
 629         return next;
 630 }
 631 
 632 static const struct flag warnings[] = {
 633         { "address", &Waddress },
 634         { "address-space", &Waddress_space },
 635         { "bitwise", &Wbitwise },
 636         { "bitwise-pointer", &Wbitwise_pointer},
 637         { "cast-from-as", &Wcast_from_as },
 638         { "cast-to-as", &Wcast_to_as },
 639         { "cast-truncate", &Wcast_truncate },
 640         { "constant-suffix", &Wconstant_suffix },
 641         { "constexpr-not-const", &Wconstexpr_not_const},
 642         { "context", &Wcontext },
 643         { "decl", &Wdecl },
 644         { "declaration-after-statement", &Wdeclarationafterstatement },
 645         { "default-bitfield-sign", &Wdefault_bitfield_sign },
 646         { "designated-init", &Wdesignated_init },
 647         { "do-while", &Wdo_while },
 648         { "enum-mismatch", &Wenum_mismatch },
 649         { "external-function-has-definition", &Wexternal_function_has_definition },
 650         { "implicit-int", &Wimplicit_int },
 651         { "init-cstring", &Winit_cstring },
 652         { "int-to-pointer-cast", &Wint_to_pointer_cast },
 653         { "memcpy-max-count", &Wmemcpy_max_count },
 654         { "non-pointer-null", &Wnon_pointer_null },
 655         { "old-initializer", &Wold_initializer },
 656         { "old-style-definition", &Wold_style_definition },
 657         { "one-bit-signed-bitfield", &Wone_bit_signed_bitfield },
 658         { "override-init", &Woverride_init },
 659         { "override-init-all", &Woverride_init_all },
 660         { "paren-string", &Wparen_string },
 661         { "pointer-to-int-cast", &Wpointer_to_int_cast },
 662         { "ptr-subtraction-blows", &Wptr_subtraction_blows },
 663         { "return-void", &Wreturn_void },
 664         { "shadow", &Wshadow },
 665         { "shift-count-negative", &Wshift_count_negative },
 666         { "shift-count-overflow", &Wshift_count_overflow },
 667         { "sizeof-bool", &Wsizeof_bool },
 668         { "strict-prototypes", &Wstrict_prototypes },
 669         { "pointer-arith", &Wpointer_arith },
 670         { "sparse-error", &Wsparse_error },
 671         { "tautological-compare", &Wtautological_compare },
 672         { "transparent-union", &Wtransparent_union },
 673         { "typesign", &Wtypesign },
 674         { "undef", &Wundef },
 675         { "uninitialized", &Wuninitialized },
 676         { "unknown-attribute", &Wunknown_attribute },
 677         { "vla", &Wvla },
 678 };
 679 
 680 enum {
 681         WARNING_OFF,
 682         WARNING_ON,
 683         WARNING_FORCE_OFF
 684 };
 685 
 686 
 687 static char **handle_onoff_switch(char *arg, char **next, const struct flag warnings[], int n)
 688 {
 689         int flag = WARNING_ON;
 690         char *p = arg + 1;
 691         unsigned i;
 692 
 693         if (!strcmp(p, "sparse-all")) {
 694                 for (i = 0; i < n; i++) {
 695                         if (*warnings[i].flag != WARNING_FORCE_OFF && warnings[i].flag != &Wsparse_error)
 696                                 *warnings[i].flag = WARNING_ON;
 697                 }
 698                 return NULL;
 699         }
 700 
 701         // Prefixes "no" and "no-" mean to turn warning off.
 702         if (p[0] == 'n' && p[1] == 'o') {
 703                 p += 2;
 704                 if (p[0] == '-')
 705                         p++;
 706                 flag = WARNING_FORCE_OFF;
 707         }
 708 
 709         for (i = 0; i < n; i++) {
 710                 if (!strcmp(p,warnings[i].name)) {
 711                         *warnings[i].flag = flag;
 712                         return next;
 713                 }
 714         }
 715 
 716         // Unknown.
 717         return NULL;
 718 }
 719 
 720 static char **handle_switch_W(char *arg, char **next)
 721 {
 722         char ** ret = handle_onoff_switch(arg, next, warnings, ARRAY_SIZE(warnings));
 723         if (ret)
 724                 return ret;
 725 
 726         // Unknown.
 727         return next;
 728 }
 729 
 730 static struct flag debugs[] = {
 731         { "compound", &dbg_compound},
 732         { "dead", &dbg_dead},
 733         { "domtree", &dbg_domtree},
 734         { "entry", &dbg_entry},
 735         { "ir", &dbg_ir},
 736         { "postorder", &dbg_postorder},
 737 };
 738 
 739 
 740 static char **handle_switch_v(char *arg, char **next)
 741 {
 742         char ** ret = handle_onoff_switch(arg, next, debugs, ARRAY_SIZE(debugs));
 743         if (ret)
 744                 return ret;
 745 
 746         // Unknown.
 747         do {
 748                 verbose++;
 749         } while (*++arg == 'v');
 750         return next;
 751 }
 752 
 753 static char **handle_switch_d(char *arg, char **next)
 754 {
 755         char *arg_char = arg + 1;
 756 
 757         /*
 758          * -d<CHARS>, where <CHARS> is a sequence of characters, not preceded
 759          * by a space. If you specify characters whose behaviour conflicts,
 760          * the result is undefined.
 761          */
 762         while (*arg_char) {
 763                 switch (*arg_char) {
 764                 case 'M': /* dump just the macro definitions */
 765                         dump_macros_only = 1;
 766                         dump_macro_defs = 0;
 767                         break;
 768                 case 'D': /* like 'M', but also output pre-processed text */
 769                         dump_macro_defs = 1;
 770                         dump_macros_only = 0;
 771                         break;
 772                 case 'N': /* like 'D', but only output macro names not bodies */
 773                         break;
 774                 case 'I': /* like 'D', but also output #include directives */
 775                         break;
 776                 case 'U': /* like 'D', but only output expanded macros */
 777                         break;
 778                 }
 779                 arg_char++;
 780         }
 781         return next;
 782 }
 783 
 784 
 785 static void handle_onoff_switch_finalize(const struct flag warnings[], int n)
 786 {
 787         unsigned i;
 788 
 789         for (i = 0; i < n; i++) {
 790                 if (*warnings[i].flag == WARNING_FORCE_OFF)
 791                         *warnings[i].flag = WARNING_OFF;
 792         }
 793 }
 794 
 795 static void handle_switch_W_finalize(void)
 796 {
 797         handle_onoff_switch_finalize(warnings, ARRAY_SIZE(warnings));
 798 
 799         /* default Wdeclarationafterstatement based on the C dialect */
 800         if (-1 == Wdeclarationafterstatement)
 801         {
 802                 switch (standard)
 803                 {
 804                         case STANDARD_C89:
 805                         case STANDARD_C94:
 806                                 Wdeclarationafterstatement = 1;
 807                                 break;
 808 
 809                         case STANDARD_C99:
 810                         case STANDARD_GNU89:
 811                         case STANDARD_GNU99:
 812                         case STANDARD_C11:
 813                         case STANDARD_GNU11:
 814                                 Wdeclarationafterstatement = 0;
 815                                 break;
 816 
 817                         default:
 818                                 assert (0);
 819                 }
 820 
 821         }
 822 }
 823 
 824 static void handle_switch_v_finalize(void)
 825 {
 826         handle_onoff_switch_finalize(debugs, ARRAY_SIZE(debugs));
 827 }
 828 
 829 static char **handle_switch_U(char *arg, char **next)
 830 {
 831         const char *name = arg + 1;
 832         if (*name == '\0')
 833                 name = *++next;
 834         add_pre_buffer ("#undef %s\n", name);
 835         return next;
 836 }
 837 
 838 static char **handle_switch_O(char *arg, char **next)
 839 {
 840         int level = 1;
 841         if (arg[1] >= '0' && arg[1] <= '9')
 842                 level = arg[1] - '0';
 843         optimize_level = level;
 844         optimize_size = arg[1] == 's';
 845         return next;
 846 }
 847 
 848 static int handle_ftabstop(const char *arg, const char *opt, const struct flag *flag, int options)
 849 {
 850         unsigned long val;
 851         char *end;
 852 
 853         if (*opt == '\0')
 854                 die("error: missing argument to \"%s\"", arg);
 855 
 856         /* we silently ignore silly values */
 857         val = strtoul(opt, &end, 10);
 858         if (*end == '\0' && 1 <= val && val <= 100)
 859                 tabstop = val;
 860 
 861         return 1;
 862 }
 863 
 864 static int handle_fpasses(const char *arg, const char *opt, const struct flag *flag, int options)
 865 {
 866         unsigned long mask;
 867 
 868         mask = flag->mask;
 869         if (*opt == '\0') {
 870                 if (options & OPT_INVERSE)
 871                         fpasses &= ~mask;
 872                 else
 873                         fpasses |=  mask;
 874                 return 1;
 875         }
 876         if (options & OPT_INVERSE)
 877                 return 0;
 878         if (!strcmp(opt, "-enable")) {
 879                 fpasses |= mask;
 880                 return 1;
 881         }
 882         if (!strcmp(opt, "-disable")) {
 883                 fpasses &= ~mask;
 884                 return 1;
 885         }
 886         if (!strcmp(opt, "=last")) {
 887                 // clear everything above
 888                 mask |= mask - 1;
 889                 fpasses &= mask;
 890                 return 1;
 891         }
 892         return 0;
 893 }
 894 
 895 static int handle_fdiagnostic_prefix(const char *arg, const char *opt, const struct flag *flag, int options)
 896 {
 897         switch (*opt) {
 898         case '\0':
 899                 diag_prefix = "sparse";
 900                 return 1;
 901         case '=':
 902                 diag_prefix = xasprintf("%s", opt+1);
 903                 return 1;
 904         default:
 905                 return 0;
 906         }
 907 }
 908 
 909 static int handle_fdump_ir(const char *arg, const char *opt, const struct flag *flag, int options)
 910 {
 911         static const struct mask_map dump_ir_options[] = {
 912                 { "",                   PASS_LINEARIZE },
 913                 { "linearize",          PASS_LINEARIZE },
 914                 { "mem2reg",            PASS_MEM2REG },
 915                 { "final",              PASS_FINAL },
 916                 { },
 917         };
 918 
 919         return handle_suboption_mask(arg, opt, dump_ir_options, &fdump_ir);
 920 }
 921 
 922 static int handle_fmemcpy_max_count(const char *arg, const char *opt, const struct flag *flag, int options)
 923 {
 924         opt_ullong(arg, opt, &fmemcpy_max_count, OPTNUM_ZERO_IS_INF|OPTNUM_UNLIMITED);
 925         return 1;
 926 }
 927 
 928 static int handle_fmax_warnings(const char *arg, const char *opt, const struct flag *flag, int options)
 929 {
 930         opt_uint(arg, opt, &fmax_warnings, OPTNUM_UNLIMITED);
 931         return 1;
 932 }
 933 
 934 static struct flag fflags[] = {
 935         { "diagnostic-prefix",  NULL,   handle_fdiagnostic_prefix },
 936         { "dump-ir",            NULL,   handle_fdump_ir },
 937         { "linearize",          NULL,   handle_fpasses, PASS_LINEARIZE },
 938         { "max-warnings=",      NULL,   handle_fmax_warnings },
 939         { "mem-report",         &fmem_report },
 940         { "memcpy-max-count=",  NULL,   handle_fmemcpy_max_count },
 941         { "tabstop=",           NULL,   handle_ftabstop },
 942         { "mem2reg",            NULL,   handle_fpasses, PASS_MEM2REG },
 943         { "optim",              NULL,   handle_fpasses, PASS_OPTIM },
 944         { "signed-char",        &funsigned_char, NULL,      OPT_INVERSE },
 945         { "unsigned-char",      &funsigned_char, NULL, },
 946         { },
 947 };
 948 
 949 static char **handle_switch_f(char *arg, char **next)
 950 {
 951         if (handle_switches(arg-1, arg+1, fflags))
 952                 return next;
 953 
 954         return next;
 955 }
 956 
 957 static char **handle_switch_G(char *arg, char **next)
 958 {
 959         if (!strcmp (arg, "G") && *next)
 960                 return next + 1; // "-G 0"
 961         else
 962                 return next;     // "-G0" or (bogus) terminal "-G"
 963 }
 964 
 965 static char **handle_switch_a(char *arg, char **next)
 966 {
 967         if (!strcmp (arg, "ansi"))
 968                 standard = STANDARD_C89;
 969 
 970         return next;
 971 }
 972 
 973 static char **handle_switch_s(const char *arg, char **next)
 974 {
 975         if ((arg = match_option(arg, "std="))) {
 976                 if (!strcmp (arg, "c89") ||
 977                     !strcmp (arg, "iso9899:1990"))
 978                         standard = STANDARD_C89;
 979 
 980                 else if (!strcmp (arg, "iso9899:199409"))
 981                         standard = STANDARD_C94;
 982 
 983                 else if (!strcmp (arg, "c99") ||
 984                          !strcmp (arg, "c9x") ||
 985                          !strcmp (arg, "iso9899:1999") ||
 986                          !strcmp (arg, "iso9899:199x"))
 987                         standard = STANDARD_C99;
 988 
 989                 else if (!strcmp (arg, "gnu89"))
 990                         standard = STANDARD_GNU89;
 991 
 992                 else if (!strcmp (arg, "gnu99") || !strcmp (arg, "gnu9x"))
 993                         standard = STANDARD_GNU99;
 994 
 995                 else if (!strcmp(arg, "c11") ||
 996                          !strcmp(arg, "c1x") ||
 997                          !strcmp(arg, "iso9899:2011"))
 998                         standard = STANDARD_C11;
 999 
1000                 else if (!strcmp(arg, "gnu11"))
1001                         standard = STANDARD_GNU11;
1002 
1003                 else
1004                         die ("Unsupported C dialect");
1005         }
1006 
1007         return next;
1008 }
1009 
1010 static char **handle_nostdinc(char *arg, char **next)
1011 {
1012         add_pre_buffer("#nostdinc\n");
1013         return next;
1014 }
1015 
1016 static char **handle_switch_n(char *arg, char **next)
1017 {
1018         if (!strcmp (arg, "nostdinc"))
1019                 return handle_nostdinc(arg, next);
1020 
1021         return next;
1022 }
1023 
1024 static char **handle_base_dir(char *arg, char **next)
1025 {
1026         gcc_base_dir = *++next;
1027         if (!gcc_base_dir)
1028                 die("missing argument for -gcc-base-dir option");
1029         return next;
1030 }
1031 
1032 static char **handle_no_lineno(char *arg, char **next)
1033 {
1034         no_lineno = 1;
1035         return next;
1036 }
1037 
1038 static char **handle_switch_g(char *arg, char **next)
1039 {
1040         if (!strcmp (arg, "gcc-base-dir"))
1041                 return handle_base_dir(arg, next);
1042 
1043         return next;
1044 }
1045 
1046 static char **handle_switch_x(char *arg, char **next)
1047 {
1048         if (!*++next)
1049                 die("missing argument for -x option");
1050         return next;
1051 }
1052 
1053 static char **handle_version(char *arg, char **next)
1054 {
1055         printf("%s\n", SPARSE_VERSION);
1056         exit(0);
1057 }
1058 
1059 static char **handle_param(char *arg, char **next)
1060 {
1061         char *value = NULL;
1062 
1063         /* Ignore smatch's --param-mapper */
1064         if (strcmp(arg, "-mapper") == 0)
1065                 return next;
1066 
1067         /* For now just skip any '--param=*' or '--param *' */
1068         if (*arg == '\0') {
1069                 value = *++next;
1070         } else if (isspace((unsigned char)*arg) || *arg == '=') {
1071                 value = ++arg;
1072         }
1073 
1074         if (!value)
1075                 die("missing argument for --param option");
1076 
1077         return next;
1078 }
1079 
1080 struct switches {
1081         const char *name;
1082         char **(*fn)(char *, char **);
1083         unsigned int prefix:1;
1084 };
1085 
1086 static char **handle_long_options(char *arg, char **next)
1087 {
1088         static struct switches cmd[] = {
1089                 { "param", handle_param, 1 },
1090                 { "version", handle_version },
1091                 { "nostdinc", handle_nostdinc },
1092                 { "gcc-base-dir", handle_base_dir},
1093                 { "no-lineno", handle_no_lineno},
1094                 { NULL, NULL }
1095         };
1096         struct switches *s = cmd;
1097 
1098         while (s->name) {
1099                 int optlen = strlen(s->name);
1100                 if (!strncmp(s->name, arg, optlen + !s->prefix))
1101                         return s->fn(arg + optlen, next);
1102                 s++;
1103         }
1104         return next;
1105 }
1106 
1107 static char **handle_switch(char *arg, char **next)
1108 {
1109         switch (*arg) {
1110         case 'a': return handle_switch_a(arg, next);
1111         case 'D': return handle_switch_D(arg, next);
1112         case 'd': return handle_switch_d(arg, next);
1113         case 'E': return handle_switch_E(arg, next);
1114         case 'f': return handle_switch_f(arg, next);
1115         case 'g': return handle_switch_g(arg, next);
1116         case 'G': return handle_switch_G(arg, next);
1117         case 'I': return handle_switch_I(arg, next);
1118         case 'i': return handle_switch_i(arg, next);
1119         case 'M': return handle_switch_M(arg, next);
1120         case 'm': return handle_switch_m(arg, next);
1121         case 'n': return handle_switch_n(arg, next);
1122         case 'o': return handle_switch_o(arg, next);
1123         case 'O': return handle_switch_O(arg, next);
1124         case 's': return handle_switch_s(arg, next);
1125         case 'U': return handle_switch_U(arg, next);
1126         case 'v': return handle_switch_v(arg, next);
1127         case 'W': return handle_switch_W(arg, next);
1128         case 'x': return handle_switch_x(arg, next);
1129         case '-': return handle_long_options(arg + 1, next);
1130         default:
1131                 break;
1132         }
1133 
1134         /*
1135          * Ignore unknown command line options:
1136          * they're probably gcc switches
1137          */
1138         return next;
1139 }
1140 
1141 #define PTYPE_SIZEOF    (1U << 0)
1142 #define PTYPE_T         (1U << 1)
1143 #define PTYPE_MAX       (1U << 2)
1144 #define PTYPE_MIN       (1U << 3)
1145 #define PTYPE_WIDTH     (1U << 4)
1146 #define PTYPE_TYPE      (1U << 5)
1147 #define PTYPE_ALL       (PTYPE_MAX|PTYPE_SIZEOF|PTYPE_WIDTH)
1148 #define PTYPE_ALL_T     (PTYPE_MAX|PTYPE_SIZEOF|PTYPE_WIDTH|PTYPE_T)
1149 
1150 static void predefined_sizeof(const char *name, const char *suffix, unsigned bits)
1151 {
1152         char buf[32];
1153 
1154         snprintf(buf, sizeof(buf), "__SIZEOF_%s%s__", name, suffix);
1155         predefine(buf, 1, "%d", bits/8);
1156 }
1157 
1158 static void predefined_width(const char *name, unsigned bits)
1159 {
1160         char buf[32];
1161 
1162         snprintf(buf, sizeof(buf), "__%s_WIDTH__", name);
1163         predefine(buf, 1, "%d", bits);
1164 }
1165 
1166 static void predefined_max(const char *name, struct symbol *type)
1167 {
1168         const char *suffix = builtin_type_suffix(type);
1169         unsigned bits = type->bit_size - is_signed_type(type);
1170         unsigned long long max = bits_mask(bits);
1171         char buf[32];
1172 
1173         snprintf(buf, sizeof(buf), "__%s_MAX__", name);
1174         predefine(buf, 1, "%#llx%s", max, suffix);
1175 }
1176 
1177 static void predefined_min(const char *name, struct symbol *type)
1178 {
1179         const char *suffix = builtin_type_suffix(type);
1180         char buf[32];
1181 
1182         snprintf(buf, sizeof(buf), "__%s_MIN__", name);
1183 
1184         if (is_signed_type(type))
1185                 predefine(buf, 1, "(-__%s_MAX__ - 1)", name);
1186         else
1187                 predefine(buf, 1, "0%s", suffix);
1188 }
1189 
1190 static void predefined_type(const char *name, struct symbol *type)
1191 {
1192         const char *typename = builtin_typename(type);
1193         add_pre_buffer("#weak_define __%s_TYPE__ %s\n", name, typename);
1194 }
1195 
1196 static void predefined_ctype(const char *name, struct symbol *type, int flags)
1197 {
1198         unsigned bits = type->bit_size;
1199 
1200         if (flags & PTYPE_SIZEOF) {
1201                 const char *suffix = (flags & PTYPE_T) ? "_T" : "";
1202                 predefined_sizeof(name, suffix, bits);
1203         }
1204         if (flags & PTYPE_MAX)
1205                 predefined_max(name, type);
1206         if (flags & PTYPE_MIN)
1207                 predefined_min(name, type);
1208         if (flags & PTYPE_TYPE)
1209                 predefined_type(name, type);
1210         if (flags & PTYPE_WIDTH)
1211                 predefined_width(name, bits);
1212 }
1213 
1214 static void predefined_macros(void)
1215 {
1216         predefine("__CHECKER__", 0, "1");
1217         predefine("__GNUC__", 1, "%d", gcc_major);
1218         predefine("__GNUC_MINOR__", 1, "%d", gcc_minor);
1219         predefine("__GNUC_PATCHLEVEL__", 1, "%d", gcc_patchlevel);
1220 
1221         predefine("__STDC__", 1, "1");
1222         switch (standard) {
1223         case STANDARD_C89:
1224                 predefine("__STRICT_ANSI__", 1, "1");
1225                 break;
1226 
1227         case STANDARD_C94:
1228                 predefine("__STDC_VERSION__", 1, "199409L");
1229                 predefine("__STRICT_ANSI__", 1, "1");
1230                 break;
1231 
1232         case STANDARD_C99:
1233                 predefine("__STDC_VERSION__", 1, "199901L");
1234                 predefine("__STRICT_ANSI__", 1, "1");
1235                 break;
1236 
1237         case STANDARD_GNU89:
1238         default:
1239                 break;
1240 
1241         case STANDARD_GNU99:
1242                 predefine("__STDC_VERSION__", 1, "199901L");
1243                 break;
1244 
1245         case STANDARD_C11:
1246                 predefine("__STRICT_ANSI__", 1, "1");
1247         case STANDARD_GNU11:
1248                 predefine("__STDC_NO_ATOMICS__", 1, "1");
1249                 predefine("__STDC_NO_COMPLEX__", 1, "1");
1250                 predefine("__STDC_NO_THREADS__", 1, "1");
1251                 predefine("__STDC_VERSION__", 1, "201112L");
1252                 break;
1253         }
1254 
1255         predefine("__CHAR_BIT__", 1, "%d", bits_in_char);
1256         if (funsigned_char)
1257                 predefine("__CHAR_UNSIGNED__", 1, "1");
1258 
1259         predefined_ctype("SHORT",     &short_ctype, PTYPE_SIZEOF);
1260         predefined_ctype("SHRT",      &short_ctype, PTYPE_MAX|PTYPE_WIDTH);
1261         predefined_ctype("SCHAR",     &schar_ctype, PTYPE_MAX|PTYPE_WIDTH);
1262         predefined_ctype("WCHAR",      wchar_ctype, PTYPE_ALL_T|PTYPE_MIN|PTYPE_TYPE);
1263         predefined_ctype("WINT",        wint_ctype, PTYPE_ALL_T|PTYPE_MIN|PTYPE_TYPE);
1264         predefined_ctype("CHAR16",   &ushort_ctype, PTYPE_TYPE);
1265         predefined_ctype("CHAR32",     &uint_ctype, PTYPE_TYPE);
1266 
1267         predefined_ctype("INT",         &int_ctype, PTYPE_ALL);
1268         predefined_ctype("LONG",       &long_ctype, PTYPE_ALL);
1269         predefined_ctype("LONG_LONG", &llong_ctype, PTYPE_ALL);
1270 
1271         predefined_ctype("INT8",      &schar_ctype, PTYPE_MAX|PTYPE_TYPE);
1272         predefined_ctype("UINT8",     &uchar_ctype, PTYPE_MAX|PTYPE_TYPE);
1273         predefined_ctype("INT16",     &short_ctype, PTYPE_MAX|PTYPE_TYPE);
1274         predefined_ctype("UINT16",   &ushort_ctype, PTYPE_MAX|PTYPE_TYPE);
1275         predefined_ctype("INT32",      int32_ctype, PTYPE_MAX|PTYPE_TYPE);
1276         predefined_ctype("UINT32",    uint32_ctype, PTYPE_MAX|PTYPE_TYPE);
1277         predefined_ctype("INT64",      int64_ctype, PTYPE_MAX|PTYPE_TYPE);
1278         predefined_ctype("UINT64",    uint64_ctype, PTYPE_MAX|PTYPE_TYPE);
1279 
1280         predefined_sizeof("INT128", "", 128);
1281 
1282         predefined_ctype("INTMAX",    intmax_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
1283         predefined_ctype("UINTMAX",  uintmax_ctype, PTYPE_MAX|PTYPE_TYPE);
1284         predefined_ctype("INTPTR",   ssize_t_ctype, PTYPE_MAX|PTYPE_TYPE|PTYPE_WIDTH);
1285         predefined_ctype("UINTPTR",   size_t_ctype, PTYPE_MAX|PTYPE_TYPE);
1286         predefined_ctype("PTRDIFF",  ssize_t_ctype, PTYPE_ALL_T|PTYPE_TYPE);
1287         predefined_ctype("SIZE",      size_t_ctype, PTYPE_ALL_T|PTYPE_TYPE);
1288         predefined_ctype("POINTER",     &ptr_ctype, PTYPE_SIZEOF);
1289 
1290         predefined_sizeof("FLOAT", "", bits_in_float);
1291         predefined_sizeof("DOUBLE", "", bits_in_double);
1292         predefined_sizeof("LONG_DOUBLE", "", bits_in_longdouble);
1293 
1294         predefine("__ORDER_LITTLE_ENDIAN__", 1, "1234");
1295         predefine("__ORDER_BIG_ENDIAN__", 1, "4321");
1296         predefine("__ORDER_PDP_ENDIAN__", 1, "3412");
1297         if (arch_big_endian) {
1298                 predefine("__BIG_ENDIAN__", 1, "1");
1299                 predefine("__BYTE_ORDER__", 1, "__ORDER_BIG_ENDIAN__");
1300         } else {
1301                 predefine("__LITTLE_ENDIAN__", 1, "1");
1302                 predefine("__BYTE_ORDER__", 1, "__ORDER_LITTLE_ENDIAN__");
1303         }
1304 
1305         if (optimize_level)
1306                 predefine("__OPTIMIZE__", 0, "1");
1307         if (optimize_size)
1308                 predefine("__OPTIMIZE_SIZE__", 0, "1");
1309 
1310         predefine("__PRAGMA_REDEFINE_EXTNAME", 1, "1");
1311 
1312         // Temporary hacks
1313         predefine("__extension__", 0, NULL);
1314         predefine("__pragma__", 0, NULL);
1315 
1316         switch (arch_m64) {
1317         case ARCH_LP32:
1318                 break;
1319         case ARCH_X32:
1320                 predefine("__ILP32__", 1, "1");
1321                 predefine("_ILP32", 1, "1");
1322                 break;
1323         case ARCH_LP64:
1324                 predefine("__LP64__", 1, "1");
1325                 predefine("_LP64", 1, "1");
1326                 break;
1327         case ARCH_LLP64:
1328                 predefine("__LLP64__", 1, "1");
1329                 break;
1330         }
1331 
1332         switch (arch_mach) {
1333         case MACH_ARM64:
1334                 predefine("__aarch64__", 1, "1");
1335                 break;
1336         case MACH_ARM:
1337                 predefine("__arm__", 1, "1");
1338                 break;
1339         case MACH_M68K:
1340                 predefine("__m68k__", 1, "1");
1341                 break;
1342         case MACH_MIPS64:
1343                 if (arch_m64 == ARCH_LP64)
1344                         predefine("__mips64", 1, "64");
1345                 /* fall-through */
1346         case MACH_MIPS32:
1347                 predefine("__mips", 1, "%d", ptr_ctype.bit_size);
1348                 predefine("_MIPS_SZINT", 1, "%d", int_ctype.bit_size);
1349                 predefine("_MIPS_SZLONG", 1, "%d", long_ctype.bit_size);
1350                 predefine("_MIPS_SZPTR", 1, "%d", ptr_ctype.bit_size);
1351                 break;
1352         case MACH_PPC64:
1353                 if (arch_m64 == ARCH_LP64) {
1354                         predefine("__powerpc64__", 1, "1");
1355                         predefine("__ppc64__", 1, "1");
1356                         predefine("__PPC64__", 1, "1");
1357                 }
1358                 /* fall-through */
1359         case MACH_PPC32:
1360                 predefine("__powerpc__", 1, "1");
1361                 predefine("__powerpc", 1, "1");
1362                 predefine("__ppc__", 1, "1");
1363                 predefine("__PPC__", 1, "1");
1364                 break;
1365         case MACH_RISCV64:
1366         case MACH_RISCV32:
1367                 predefine("__riscv", 1, "1");
1368                 predefine("__riscv_xlen", 1, "%d", ptr_ctype.bit_size);
1369                 break;
1370         case MACH_S390X:
1371                 predefine("__zarch__", 1, "1");
1372                 predefine("__s390x__", 1, "1");
1373                 predefine("__s390__", 1, "1");
1374                 break;
1375         case MACH_SPARC64:
1376                 if (arch_m64 == ARCH_LP64) {
1377                         predefine("__sparc_v9__", 1, "1");
1378                         predefine("__sparcv9__", 1, "1");
1379                         predefine("__sparcv9", 1, "1");
1380                         predefine("__sparc64__", 1, "1");
1381                         predefine("__arch64__", 1, "1");
1382                 }
1383                 /* fall-through */
1384         case MACH_SPARC32:
1385                 predefine("__sparc__", 1, "1");
1386                 predefine("__sparc", 1, "1");
1387                 predefine_nostd("sparc");
1388                 break;
1389         case MACH_X86_64:
1390                 if (arch_m64 != ARCH_LP32) {
1391                         predefine("__x86_64__", 1, "1");
1392                         predefine("__x86_64", 1, "1");
1393                         predefine("__amd64__", 1, "1");
1394                         predefine("__amd64", 1, "1");
1395                         break;
1396                 }
1397                 /* fall-through */
1398         case MACH_I386:
1399                 predefine("__i386__", 1, "1");
1400                 predefine("__i386", 1, "1");
1401                 predefine_nostd("i386");
1402                 break;
1403         }
1404 
1405 #if defined(__unix__)
1406         predefine("__unix__", 1, "1");
1407         predefine("__unix", 1, "1");
1408         predefine_nostd("unix");
1409 #endif
1410 
1411 
1412 #if defined(__sun__) || defined(__sun)
1413         predefine("__sun__", 1, "1");
1414         predefine("__sun", 1, "1");
1415         predefine_nostd("sun");
1416         predefine("__svr4__", 1, "1");
1417 #endif
1418 
1419 }
1420 
1421 static void create_builtin_stream(void)
1422 {
1423         // Temporary hack
1424         add_pre_buffer("#define _Pragma(x)\n");
1425 
1426         /* add the multiarch include directories, if any */
1427         if (multiarch_dir && *multiarch_dir) {
1428                 add_pre_buffer("#add_system \"/usr/include/%s\"\n", multiarch_dir);
1429                 add_pre_buffer("#add_system \"/usr/local/include/%s\"\n", multiarch_dir);
1430         }
1431 
1432         /* We add compiler headers path here because we have to parse
1433          * the arguments to get it, falling back to default. */
1434         add_pre_buffer("#add_system \"%s/include\"\n", gcc_base_dir);
1435         add_pre_buffer("#add_system \"%s/include-fixed\"\n", gcc_base_dir);
1436 
1437         add_pre_buffer("#define __has_builtin(x) 0\n");
1438         add_pre_buffer("#define __has_attribute(x) 0\n");
1439         add_pre_buffer("#define __builtin_stdarg_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
1440         add_pre_buffer("#define __builtin_va_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
1441         add_pre_buffer("#define __builtin_ms_va_start(a,b) ((a) = (__builtin_ms_va_list)(&(b)))\n");
1442         add_pre_buffer("#define __builtin_va_arg(arg,type)  ({ type __va_arg_ret = *(type *)(arg); arg += sizeof(type); __va_arg_ret; })\n");
1443         add_pre_buffer("#define __builtin_va_alist (*(void *)0)\n");
1444         add_pre_buffer("#define __builtin_va_arg_incr(x) ((x) + 1)\n");
1445         add_pre_buffer("#define __builtin_va_copy(dest, src) ({ dest = src; (void)0; })\n");
1446         add_pre_buffer("#define __builtin_ms_va_copy(dest, src) ({ dest = src; (void)0; })\n");
1447         add_pre_buffer("#define __builtin_va_end(arg)\n");
1448         add_pre_buffer("#define __builtin_ms_va_end(arg)\n");
1449         add_pre_buffer("#define __builtin_va_arg_pack()\n");
1450 }
1451 
1452 static struct symbol_list *sparse_tokenstream(struct token *token)
1453 {
1454         int builtin = token && !token->pos.stream;
1455 
1456         // Preprocess the stream
1457         token = preprocess(token);
1458 
1459         if (dump_macro_defs || dump_macros_only) {
1460                 if (!builtin)
1461                         dump_macro_definitions();
1462                 if (dump_macros_only)
1463                         return NULL;
1464         }
1465 
1466         if (preprocess_only) {
1467                 while (!eof_token(token)) {
1468                         int prec = 1;
1469                         struct token *next = token->next;
1470                         const char *separator = "";
1471                         if (next->pos.whitespace)
1472                                 separator = " ";
1473                         if (next->pos.newline) {
1474                                 separator = "\n\t\t\t\t\t";
1475                                 prec = next->pos.pos;
1476                                 if (prec > 4)
1477                                         prec = 4;
1478                         }
1479                         printf("%s%.*s", show_token(token), prec, separator);
1480                         token = next;
1481                 }
1482                 putchar('\n');
1483 
1484                 return NULL;
1485         }
1486 
1487         // Parse the resulting C code
1488         while (!eof_token(token))
1489                 token = external_declaration(token, &translation_unit_used_list, NULL);
1490         return translation_unit_used_list;
1491 }
1492 
1493 static struct symbol_list *sparse_file(const char *filename)
1494 {
1495         int fd;
1496         struct token *token;
1497 
1498         if (strcmp (filename, "-") == 0) {
1499                 fd = 0;
1500         } else {
1501                 fd = open(filename, O_RDONLY);
1502                 if (fd < 0)
1503                         die("No such file: %s", filename);
1504         }
1505         base_filename = filename;
1506 
1507         // Tokenize the input stream
1508         token = tokenize(filename, fd, NULL, includepath);
1509         store_all_tokens(token);
1510         close(fd);
1511 
1512         return sparse_tokenstream(token);
1513 }
1514 
1515 /*
1516  * This handles the "-include" directive etc: we're in global
1517  * scope, and all types/macros etc will affect all the following
1518  * files.
1519  *
1520  * NOTE NOTE NOTE! "#undef" of anything in this stage will
1521  * affect all subsequent files too, i.e. we can have non-local
1522  * behaviour between files!
1523  */
1524 static struct symbol_list *sparse_initial(void)
1525 {
1526         int i;
1527 
1528         // Prepend any "include" file to the stream.
1529         // We're in global scope, it will affect all files!
1530         for (i = 0; i < cmdline_include_nr; i++)
1531                 add_pre_buffer("#argv_include \"%s\"\n", cmdline_include[i]);
1532 
1533         return sparse_tokenstream(pre_buffer_begin);
1534 }
1535 
1536 static int endswith(const char *str, const char *suffix)
1537 {
1538         const char *found = strstr(str, suffix);
1539         return (found && strcmp(found, suffix) == 0);
1540 }
1541 
1542 struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list **filelist)
1543 {
1544         char **args;
1545         struct symbol_list *list;
1546 
1547         // Initialize symbol stream first, so that we can add defines etc
1548         init_symbols();
1549         init_include_path();
1550 
1551         diag_prefix = argv[0];
1552 
1553         args = argv;
1554         for (;;) {
1555                 char *arg = *++args;
1556                 if (!arg)
1557                         break;
1558 
1559                 if (arg[0] == '-' && arg[1]) {
1560                         args = handle_switch(arg+1, args);
1561                         continue;
1562                 }
1563 
1564                 if (endswith(arg, ".a") || endswith(arg, ".so") ||
1565                     endswith(arg, ".so.1") || endswith(arg, ".o"))
1566                         continue;
1567 
1568                 add_ptr_list(filelist, arg);
1569         }
1570         handle_switch_W_finalize();
1571         handle_switch_v_finalize();
1572 
1573         // Redirect stdout if needed
1574         if (dump_macro_defs || preprocess_only)
1575                 do_output = 1;
1576         if (do_output && outfile && strcmp(outfile, "-")) {
1577                 if (!freopen(outfile, "w", stdout))
1578                         die("error: cannot open %s: %s", outfile, strerror(errno));
1579         }
1580 
1581         if (fdump_ir == 0)
1582                 fdump_ir = PASS_FINAL;
1583 
1584         list = NULL;
1585         if (filelist) {
1586                 // Initialize type system
1587                 init_target();
1588                 handle_arch_finalize();
1589                 init_ctype();
1590 
1591                 predefined_macros();
1592                 create_builtin_stream();
1593                 declare_builtins();
1594 
1595                 list = sparse_initial();
1596 
1597                 /*
1598                  * Protect the initial token allocations, since
1599                  * they need to survive all the others
1600                  */
1601                 protect_token_alloc();
1602         }
1603         /*
1604          * Evaluate the complete symbol list
1605          * Note: This is not needed for normal cases.
1606          *       These symbols should only be predefined defines and
1607          *       declaratons which will be evaluated later, when needed.
1608          *       This is also the case when a file is directly included via
1609          *       '-include <file>' on the command line *AND* the file only
1610          *       contains defines, declarations and inline definitions.
1611          *       However, in the rare cases where the given file should
1612          *       contain some definitions, these will never be evaluated
1613          *       and thus won't be able to be linearized correctly.
1614          *       Hence the evaluate_symbol_list() here under.
1615          */
1616         evaluate_symbol_list(list);
1617         return list;
1618 }
1619 
1620 struct symbol_list * sparse_keep_tokens(char *filename)
1621 {
1622         struct symbol_list *res;
1623 
1624         /* Clear previous symbol list */
1625         translation_unit_used_list = NULL;
1626 
1627         new_file_scope();
1628         res = sparse_file(filename);
1629 
1630         /* And return it */
1631         return res;
1632 }
1633 
1634 
1635 struct symbol_list * __sparse(char *filename)
1636 {
1637         struct symbol_list *res;
1638 
1639         res = sparse_keep_tokens(filename);
1640 
1641         /* Drop the tokens for this file after parsing */
1642         clear_token_alloc();
1643 
1644         /* And return it */
1645         return res;
1646 }
1647 
1648 struct symbol_list * sparse(char *filename)
1649 {
1650         struct symbol_list *res = __sparse(filename);
1651 
1652         if (has_error & ERROR_CURR_PHASE)
1653                 has_error = ERROR_PREV_PHASE;
1654         /* Evaluate the complete symbol list */
1655         evaluate_symbol_list(res);
1656 
1657         return res;
1658 }