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