1 // SPDX-License-Identifier: MIT
3 * 'sparse' library helper routines.
5 * Copyright (C) 2003 Transmeta Corp.
6 * 2003-2004 Linus Torvalds
7 * 2017-2020 Luc Van Oostenryck
22 # define __GNUC_MINOR__ 95
23 # define __GNUC_PATCHLEVEL__ 0
34 int gcc_major
= __GNUC__
;
35 int gcc_minor
= __GNUC_MINOR__
;
36 int gcc_patchlevel
= __GNUC_PATCHLEVEL__
;
44 #define CMDLINE_INCLUDE 20
45 int cmdline_include_nr
= 0;
46 char *cmdline_include
[CMDLINE_INCLUDE
];
48 const char *base_filename
;
49 const char *diag_prefix
= "";
50 const char *gcc_base_dir
= GCC_BASE
;
51 const char *multiarch_dir
= MULTIARCH_TRIPLET
;
52 const char *outfile
= NULL
;
54 enum standard standard
= STANDARD_GNU89
;
56 int arch_big_endian
= ARCH_BIG_ENDIAN
;
57 int arch_cmodel
= CMODEL_UNKNOWN
;
58 int arch_fp_abi
= FP_ABI_NATIVE
;
59 int arch_m64
= ARCH_M64_DEFAULT
;
60 int arch_msize_long
= 0;
61 int arch_os
= OS_NATIVE
;
68 int dbg_postorder
= 0;
70 int dump_macro_defs
= 0;
71 int dump_macros_only
= 0;
73 int dissect_show_all_symbols
= 0;
75 unsigned long fdump_ir
;
77 unsigned int fmax_errors
= 100;
78 unsigned int fmax_warnings
= 100;
80 unsigned long long fmemcpy_max_count
= 100000;
81 unsigned long fpasses
= ~0UL;
85 int funsigned_bitfields
= 0;
86 int funsigned_char
= 0;
89 int Waddress_space
= 1;
91 int Wbitwise_pointer
= 0;
92 int Wcast_from_as
= 0;
94 int Wcast_truncate
= 1;
95 int Wconstant_suffix
= 0;
96 int Wconstexpr_not_const
= 0;
99 int Wdeclarationafterstatement
= -1;
100 int Wdefault_bitfield_sign
= 0;
101 int Wdesignated_init
= 1;
103 int Wenum_mismatch
= 1;
104 int Wexternal_function_has_definition
= 1;
105 int Wflexible_array_array
= 1;
106 int Wflexible_array_nested
= 0;
107 int Wflexible_array_sizeof
= 0;
108 int Wflexible_array_union
= 0;
109 int Wimplicit_int
= 1;
110 int Winit_cstring
= 0;
111 int Wint_to_pointer_cast
= 1;
112 int Wmemcpy_max_count
= 1;
113 int Wnewline_eof
= 1;
114 int Wnon_pointer_null
= 1;
115 int Wold_initializer
= 1;
116 int Wold_style_definition
= 1;
117 int Wone_bit_signed_bitfield
= 1;
118 int Woverride_init
= 1;
119 int Woverride_init_all
= 0;
120 int Woverride_init_whole_range
= 0;
121 int Wparen_string
= 0;
122 int Wpast_deep_designator
= 0;
124 int Wpointer_arith
= 0;
125 int Wpointer_to_int_cast
= 1;
126 int Wptr_subtraction_blows
= 0;
127 int Wreturn_void
= 0;
129 int Wshift_count_negative
= 1;
130 int Wshift_count_overflow
= 1;
131 int Wsizeof_bool
= 0;
132 int Wsparse_error
= FLAG_FORCE_OFF
;
133 int Wstrict_prototypes
= 1;
134 int Wtautological_compare
= 0;
135 int Wtransparent_union
= 0;
138 int Wuninitialized
= 1;
140 int Wuniversal_initializer
= 0;
141 int Wunknown_attribute
= 0;
144 ////////////////////////////////////////////////////////////////////////////////
145 // Helpers for option parsing
147 static const char *match_option(const char *arg
, const char *prefix
)
149 unsigned int n
= strlen(prefix
);
150 if (strncmp(arg
, prefix
, n
) == 0)
161 static int handle_subopt_val(const char *opt
, const char *arg
, const struct val_map
*map
, int *flag
)
166 die("missing argument for option '%s'", opt
);
167 for (;(name
= map
->name
); map
++) {
168 if (strcmp(name
, arg
) == 0 || strcmp(name
, "*") == 0) {
172 if (strcmp(name
, "?") == 0)
173 die("invalid argument '%s' in option '%s'", arg
, opt
);
184 static int apply_mask(unsigned long *val
, const char *str
, unsigned len
, const struct mask_map
*map
, int neg
)
188 for (;(name
= map
->name
); map
++) {
189 if (!strncmp(name
, str
, len
) && !name
[len
]) {
200 static int handle_suboption_mask(const char *arg
, const char *opt
, const struct mask_map
*map
, unsigned long *flag
)
203 apply_mask(flag
, "", 0, map
, 0);
209 unsigned int len
= strcspn(opt
, ",+");
213 if (!strncmp(opt
, "no-", 3)) {
218 if (apply_mask(flag
, opt
, len
, map
, neg
))
219 die("error: wrong option '%.*s' for \'%s\'", len
, opt
, arg
);
230 #define OPT_INVERSE 1
235 int (*fun
)(const char *arg
, const char *opt
, const struct flag
*, int options
);
240 static int handle_switches(const char *ori
, const char *opt
, const struct flag
*flags
)
242 const char *arg
= opt
;
245 // Prefixe "no-" mean to turn flag off.
246 if (strncmp(arg
, "no-", 3) == 0) {
251 for (; flags
->name
; flags
++) {
252 const char *opt
= match_option(arg
, flags
->name
);
261 options
|= OPT_INVERSE
;
262 if ((rc
= flags
->fun(ori
, opt
, flags
, options
)))
267 if (opt
[0] == '\0' && flags
->flag
) {
268 if (flags
->mask
& OPT_VAL
)
270 if (flags
->mask
& OPT_INVERSE
)
281 static char **handle_onoff_switch(char *arg
, char **next
, const struct flag flags
[])
287 // Prefixes "no" and "no-" mean to turn warning off.
288 if (p
[0] == 'n' && p
[1] == 'o') {
292 flag
= FLAG_FORCE_OFF
;
295 for (i
= 0; flags
[i
].name
; i
++) {
296 if (!strcmp(p
,flags
[i
].name
)) {
297 *flags
[i
].flag
= flag
;
306 static void handle_onoff_switch_finalize(const struct flag flags
[])
310 for (i
= 0; flags
[i
].name
; i
++) {
311 if (*flags
[i
].flag
== FLAG_FORCE_OFF
)
312 *flags
[i
].flag
= FLAG_OFF
;
316 static int handle_switch_setval(const char *arg
, const char *opt
, const struct flag
*flag
, int options
)
318 *(flag
->flag
) = flag
->mask
;
323 #define OPTNUM_ZERO_IS_INF 1
324 #define OPTNUM_UNLIMITED 2
326 #define OPT_NUMERIC(NAME, TYPE, FUNCTION) \
327 static int opt_##NAME(const char *arg, const char *opt, TYPE *ptr, int flag) \
332 val = FUNCTION(opt, &end, 0); \
333 if (*end != '\0' || end == opt) { \
334 if ((flag & OPTNUM_UNLIMITED) && !strcmp(opt, "unlimited")) \
337 die("error: wrong argument to \'%s\'", arg); \
339 if ((flag & OPTNUM_ZERO_IS_INF) && val == 0) \
345 OPT_NUMERIC(ullong
, unsigned long long, strtoull
)
346 OPT_NUMERIC(uint
, unsigned int, strtoul
)
348 ////////////////////////////////////////////////////////////////////////////////
351 static char **handle_switch_a(char *arg
, char **next
)
353 if (!strcmp(arg
, "ansi"))
354 standard
= STANDARD_C89
;
359 static char **handle_switch_D(char *arg
, char **next
)
361 const char *name
= arg
+ 1;
362 const char *value
= "1";
367 die("argument to `-D' is missing");
382 add_pre_buffer("#define %s %s\n", name
, value
);
386 static char **handle_switch_d(char *arg
, char **next
)
388 char *arg_char
= arg
+ 1;
391 * -d<CHARS>, where <CHARS> is a sequence of characters, not preceded
392 * by a space. If you specify characters whose behaviour conflicts,
393 * the result is undefined.
397 case 'M': /* dump just the macro definitions */
398 dump_macros_only
= 1;
401 case 'D': /* like 'M', but also output pre-processed text */
403 dump_macros_only
= 0;
405 case 'N': /* like 'D', but only output macro names not bodies */
407 case 'I': /* like 'D', but also output #include directives */
409 case 'U': /* like 'D', but only output expanded macros */
417 static char **handle_switch_E(char *arg
, char **next
)
424 static int handle_ftabstop(const char *arg
, const char *opt
, const struct flag
*flag
, int options
)
430 die("error: missing argument to \"%s\"", arg
);
432 /* we silently ignore silly values */
433 val
= strtoul(opt
, &end
, 10);
434 if (*end
== '\0' && 1 <= val
&& val
<= 100)
440 static int handle_fpasses(const char *arg
, const char *opt
, const struct flag
*flag
, int options
)
446 if (options
& OPT_INVERSE
)
452 if (options
& OPT_INVERSE
)
454 if (!strcmp(opt
, "-enable")) {
458 if (!strcmp(opt
, "-disable")) {
462 if (!strcmp(opt
, "=last")) {
463 // clear everything above
471 static int handle_fdiagnostic_prefix(const char *arg
, const char *opt
, const struct flag
*flag
, int options
)
475 diag_prefix
= "sparse: ";
478 diag_prefix
= xasprintf("%s: ", opt
+1);
485 static int handle_fdump_ir(const char *arg
, const char *opt
, const struct flag
*flag
, int options
)
487 static const struct mask_map dump_ir_options
[] = {
488 { "", PASS_LINEARIZE
},
489 { "linearize", PASS_LINEARIZE
},
490 { "mem2reg", PASS_MEM2REG
},
491 { "final", PASS_FINAL
},
495 return handle_suboption_mask(arg
, opt
, dump_ir_options
, &fdump_ir
);
498 static int handle_fmemcpy_max_count(const char *arg
, const char *opt
, const struct flag
*flag
, int options
)
500 opt_ullong(arg
, opt
, &fmemcpy_max_count
, OPTNUM_ZERO_IS_INF
|OPTNUM_UNLIMITED
);
504 static int handle_fmax_errors(const char *arg
, const char *opt
, const struct flag
*flag
, int options
)
506 opt_uint(arg
, opt
, &fmax_errors
, OPTNUM_UNLIMITED
);
510 static int handle_fmax_warnings(const char *arg
, const char *opt
, const struct flag
*flag
, int options
)
512 opt_uint(arg
, opt
, &fmax_warnings
, OPTNUM_UNLIMITED
);
516 static struct flag fflags
[] = {
517 { "diagnostic-prefix", NULL
, handle_fdiagnostic_prefix
},
518 { "dump-ir", NULL
, handle_fdump_ir
},
519 { "freestanding", &fhosted
, NULL
, OPT_INVERSE
},
520 { "hosted", &fhosted
},
521 { "linearize", NULL
, handle_fpasses
, PASS_LINEARIZE
},
522 { "max-errors=", NULL
, handle_fmax_errors
},
523 { "max-warnings=", NULL
, handle_fmax_warnings
},
524 { "mem-report", &fmem_report
},
525 { "memcpy-max-count=", NULL
, handle_fmemcpy_max_count
},
526 { "tabstop=", NULL
, handle_ftabstop
},
527 { "mem2reg", NULL
, handle_fpasses
, PASS_MEM2REG
},
528 { "optim", NULL
, handle_fpasses
, PASS_OPTIM
},
529 { "pic", &fpic
, handle_switch_setval
, 1 },
530 { "PIC", &fpic
, handle_switch_setval
, 2 },
531 { "pie", &fpie
, handle_switch_setval
, 1 },
532 { "PIE", &fpie
, handle_switch_setval
, 2 },
533 { "signed-bitfields", &funsigned_bitfields
, NULL
, OPT_INVERSE
},
534 { "unsigned-bitfields", &funsigned_bitfields
, NULL
, },
535 { "signed-char", &funsigned_char
, NULL
, OPT_INVERSE
},
536 { "short-wchar", &fshort_wchar
},
537 { "unsigned-char", &funsigned_char
, NULL
, },
541 static char **handle_switch_f(char *arg
, char **next
)
543 if (handle_switches(arg
-1, arg
+1, fflags
))
549 static char **handle_switch_G(char *arg
, char **next
)
551 if (!strcmp(arg
, "G") && *next
)
552 return next
+ 1; // "-G 0"
554 return next
; // "-G0" or (bogus) terminal "-G"
557 static char **handle_base_dir(char *arg
, char **next
)
559 gcc_base_dir
= *++next
;
561 die("missing argument for -gcc-base-dir option");
565 static char **handle_switch_g(char *arg
, char **next
)
567 if (!strcmp(arg
, "gcc-base-dir"))
568 return handle_base_dir(arg
, next
);
573 static char **handle_switch_I(char *arg
, char **next
)
579 add_pre_buffer("#split_include\n");
582 case '\0': /* Plain "-I" */
585 die("missing argument for -I option");
588 add_pre_buffer("#add_include \"%s/\"\n", path
);
593 static void add_cmdline_include(char *filename
)
595 if (cmdline_include_nr
>= CMDLINE_INCLUDE
)
596 die("too many include files for %s\n", filename
);
597 cmdline_include
[cmdline_include_nr
++] = filename
;
600 static char **handle_switch_i(char *arg
, char **next
)
602 if (*next
&& !strcmp(arg
, "include"))
603 add_cmdline_include(*++next
);
604 else if (*next
&& !strcmp(arg
, "imacros"))
605 add_cmdline_include(*++next
);
606 else if (*next
&& !strcmp(arg
, "isystem")) {
607 char *path
= *++next
;
609 die("missing argument for -isystem option");
610 add_pre_buffer("#add_isystem \"%s/\"\n", path
);
611 } else if (*next
&& !strcmp(arg
, "idirafter")) {
612 char *path
= *++next
;
614 die("missing argument for -idirafter option");
615 add_pre_buffer("#add_dirafter \"%s/\"\n", path
);
620 static char **handle_switch_M(char *arg
, char **next
)
622 if (!strcmp(arg
, "MF") || !strcmp(arg
,"MQ") || !strcmp(arg
,"MT")) {
624 die("missing argument for -%s option", arg
);
630 static int handle_march(const char *opt
, const char *arg
, const struct flag
*flag
, int options
)
632 if (arch_target
->parse_march
)
633 arch_target
->parse_march(arg
);
637 static int handle_mcmodel(const char *opt
, const char *arg
, const struct flag
*flag
, int options
)
639 static const struct val_map cmodels
[] = {
640 { "kernel", CMODEL_KERNEL
},
641 { "large", CMODEL_LARGE
},
642 { "medany", CMODEL_MEDANY
},
643 { "medium", CMODEL_MEDIUM
},
644 { "medlow", CMODEL_MEDLOW
},
645 { "small", CMODEL_SMALL
},
646 { "tiny", CMODEL_TINY
},
649 return handle_subopt_val(opt
, arg
, cmodels
, flag
->flag
);
652 static int handle_mfloat_abi(const char *opt
, const char *arg
, const struct flag
*flag
, int options
) {
653 static const struct val_map fp_abis
[] = {
654 { "hard", FP_ABI_HARD
},
655 { "soft", FP_ABI_SOFT
},
656 { "softfp", FP_ABI_HYBRID
},
659 return handle_subopt_val(opt
, arg
, fp_abis
, flag
->flag
);
662 static char **handle_multiarch_dir(char *arg
, char **next
)
664 multiarch_dir
= *++next
;
666 die("missing argument for -multiarch-dir option");
670 static const struct flag mflags
[] = {
671 { "64", &arch_m64
, NULL
, OPT_VAL
, ARCH_LP64
},
672 { "32", &arch_m64
, NULL
, OPT_VAL
, ARCH_LP32
},
673 { "31", &arch_m64
, NULL
, OPT_VAL
, ARCH_LP32
},
674 { "16", &arch_m64
, NULL
, OPT_VAL
, ARCH_LP32
},
675 { "x32",&arch_m64
, NULL
, OPT_VAL
, ARCH_X32
},
676 { "size-llp64", &arch_m64
, NULL
, OPT_VAL
, ARCH_LLP64
},
677 { "size-long", &arch_msize_long
},
678 { "arch=", NULL
, handle_march
},
679 { "big-endian", &arch_big_endian
, NULL
},
680 { "little-endian", &arch_big_endian
, NULL
, OPT_INVERSE
},
681 { "cmodel", &arch_cmodel
, handle_mcmodel
},
682 { "float-abi", &arch_fp_abi
, handle_mfloat_abi
},
683 { "hard-float", &arch_fp_abi
, NULL
, OPT_VAL
, FP_ABI_HARD
},
684 { "soft-float", &arch_fp_abi
, NULL
, OPT_VAL
, FP_ABI_SOFT
},
688 static char **handle_switch_m(char *arg
, char **next
)
690 if (!strcmp(arg
, "meabi") && next
[1] && next
[1][0] != '-') {
691 // clang has such an option with syntax: -meabi <arg>
692 // It's used by the kernel for armv7.
693 // GCC has the same option but with no argument.
694 // Parse it here to consume the possible argument.
695 static const char *valid
[] = { "gnu", "4", "5", "default", NULL
};
697 for (i
= 0; valid
[i
]; i
++) {
698 if (!strcmp(next
[1], valid
[i
]))
703 if (!strcmp(arg
, "multiarch-dir")) {
704 return handle_multiarch_dir(arg
, next
);
706 handle_switches(arg
-1, arg
+1, mflags
);
712 static char **handle_nostdinc(char *arg
, char **next
)
714 add_pre_buffer("#nostdinc\n");
718 static char **handle_switch_n(char *arg
, char **next
)
720 if (!strcmp(arg
, "nostdinc"))
721 return handle_nostdinc(arg
, next
);
726 static char **handle_switch_O(char *arg
, char **next
)
729 if (arg
[1] >= '0' && arg
[1] <= '9')
730 level
= arg
[1] - '0';
731 optimize_level
= level
;
732 optimize_size
= arg
[1] == 's';
736 static char **handle_switch_o(char *arg
, char **next
)
738 if (!strcmp(arg
, "o")) { // "-o foo"
740 die("argument to '-o' is missing");
748 static const struct flag pflags
[] = {
749 { "pedantic", &Wpedantic
, NULL
, OPT_VAL
, FLAG_ON
},
753 static char **handle_switch_p(char *arg
, char **next
)
755 handle_switches(arg
-1, arg
, pflags
);
759 static char **handle_switch_s(const char *arg
, char **next
)
761 if ((arg
= match_option(arg
, "std="))) {
762 if (!strcmp(arg
, "c89") ||
763 !strcmp(arg
, "iso9899:1990"))
764 standard
= STANDARD_C89
;
766 else if (!strcmp(arg
, "iso9899:199409"))
767 standard
= STANDARD_C94
;
769 else if (!strcmp(arg
, "c99") ||
770 !strcmp(arg
, "c9x") ||
771 !strcmp(arg
, "iso9899:1999") ||
772 !strcmp(arg
, "iso9899:199x"))
773 standard
= STANDARD_C99
;
775 else if (!strcmp(arg
, "gnu89"))
776 standard
= STANDARD_GNU89
;
778 else if (!strcmp(arg
, "gnu99") || !strcmp(arg
, "gnu9x"))
779 standard
= STANDARD_GNU99
;
781 else if (!strcmp(arg
, "c11") ||
782 !strcmp(arg
, "c1x") ||
783 !strcmp(arg
, "iso9899:2011"))
784 standard
= STANDARD_C11
;
786 else if (!strcmp(arg
, "gnu11"))
787 standard
= STANDARD_GNU11
;
789 else if (!strcmp(arg
, "c17") ||
790 !strcmp(arg
, "c18") ||
791 !strcmp(arg
, "iso9899:2017") ||
792 !strcmp(arg
, "iso9899:2018"))
793 standard
= STANDARD_C17
;
794 else if (!strcmp(arg
, "gnu17") ||
795 !strcmp(arg
, "gnu18"))
796 standard
= STANDARD_GNU17
;
799 die("Unsupported C dialect");
805 static char **handle_switch_U(char *arg
, char **next
)
807 const char *name
= arg
+ 1;
812 die("argument to `-U' is missing");
814 add_pre_buffer("#undef %s\n", name
);
818 static struct flag debugs
[] = {
819 { "compound", &dbg_compound
},
820 { "dead", &dbg_dead
},
821 { "domtree", &dbg_domtree
},
822 { "entry", &dbg_entry
},
824 { "postorder", &dbg_postorder
},
828 static char **handle_switch_v(char *arg
, char **next
)
830 char ** ret
= handle_onoff_switch(arg
, next
, debugs
);
837 } while (*++arg
== 'v');
841 static void handle_switch_v_finalize(void)
843 handle_onoff_switch_finalize(debugs
);
846 static const struct flag warnings
[] = {
847 { "address", &Waddress
},
848 { "address-space", &Waddress_space
},
849 { "bitwise", &Wbitwise
},
850 { "bitwise-pointer", &Wbitwise_pointer
},
851 { "cast-from-as", &Wcast_from_as
},
852 { "cast-to-as", &Wcast_to_as
},
853 { "cast-truncate", &Wcast_truncate
},
854 { "constant-suffix", &Wconstant_suffix
},
855 { "constexpr-not-const", &Wconstexpr_not_const
},
856 { "context", &Wcontext
},
858 { "declaration-after-statement", &Wdeclarationafterstatement
},
859 { "default-bitfield-sign", &Wdefault_bitfield_sign
},
860 { "designated-init", &Wdesignated_init
},
861 { "do-while", &Wdo_while
},
862 { "enum-mismatch", &Wenum_mismatch
},
863 { "external-function-has-definition", &Wexternal_function_has_definition
},
864 { "flexible-array-array", &Wflexible_array_array
},
865 { "flexible-array-nested", &Wflexible_array_nested
},
866 { "flexible-array-sizeof", &Wflexible_array_sizeof
},
867 { "flexible-array-union", &Wflexible_array_union
},
868 { "implicit-int", &Wimplicit_int
},
869 { "init-cstring", &Winit_cstring
},
870 { "int-to-pointer-cast", &Wint_to_pointer_cast
},
871 { "memcpy-max-count", &Wmemcpy_max_count
},
872 { "non-pointer-null", &Wnon_pointer_null
},
873 { "newline-eof", &Wnewline_eof
},
874 { "old-initializer", &Wold_initializer
},
875 { "old-style-definition", &Wold_style_definition
},
876 { "one-bit-signed-bitfield", &Wone_bit_signed_bitfield
},
877 { "override-init", &Woverride_init
},
878 { "override-init-all", &Woverride_init_all
},
879 { "paren-string", &Wparen_string
},
880 { "past-deep-designator", &Wpast_deep_designator
},
881 { "pedantic", &Wpedantic
},
882 { "pointer-to-int-cast", &Wpointer_to_int_cast
},
883 { "ptr-subtraction-blows", &Wptr_subtraction_blows
},
884 { "return-void", &Wreturn_void
},
885 { "shadow", &Wshadow
},
886 { "shift-count-negative", &Wshift_count_negative
},
887 { "shift-count-overflow", &Wshift_count_overflow
},
888 { "sizeof-bool", &Wsizeof_bool
},
889 { "strict-prototypes", &Wstrict_prototypes
},
890 { "pointer-arith", &Wpointer_arith
},
891 { "sparse-error", &Wsparse_error
},
892 { "tautological-compare", &Wtautological_compare
},
893 { "transparent-union", &Wtransparent_union
},
894 { "typesign", &Wtypesign
},
895 { "undef", &Wundef
},
896 { "uninitialized", &Wuninitialized
},
897 { "union-cast", &Wunion_cast
},
898 { "universal-initializer", &Wuniversal_initializer
},
899 { "unknown-attribute", &Wunknown_attribute
},
904 static char **handle_switch_W(char *arg
, char **next
)
906 char ** ret
= handle_onoff_switch(arg
, next
, warnings
);
910 if (!strcmp(arg
, "Wsparse-all")) {
912 for (i
= 0; warnings
[i
].name
; i
++) {
913 if (*warnings
[i
].flag
!= FLAG_FORCE_OFF
)
914 *warnings
[i
].flag
= FLAG_ON
;
922 static void handle_switch_W_finalize(void)
924 handle_onoff_switch_finalize(warnings
);
926 /* default Wdeclarationafterstatement based on the C dialect */
927 if (-1 == Wdeclarationafterstatement
) {
931 Wdeclarationafterstatement
= 1;
934 Wdeclarationafterstatement
= 0;
940 static char **handle_switch_x(char *arg
, char **next
)
943 die("missing argument for -x option");
948 static char **handle_arch(char *arg
, char **next
)
953 die("missing argument for --arch option");
955 mach
= target_parse(arg
);
956 if (mach
!= MACH_UNKNOWN
)
962 static char **handle_param(char *arg
, char **next
)
966 /* For now just skip any '--param=*' or '--param *' */
969 } else if (isspace((unsigned char)*arg
) || *arg
== '=') {
974 die("missing argument for --param option");
976 if (!strcmp(value
, "dissect-show-all-symbols"))
977 dissect_show_all_symbols
= 1;
982 static char **handle_os(char *arg
, char **next
)
985 die("missing argument for --os option");
992 static char **handle_version(char *arg
, char **next
)
994 printf("%s\n", sparse_version
);
1000 char **(*fn
)(char *, char **);
1001 unsigned int prefix
:1;
1004 static char **handle_long_options(char *arg
, char **next
)
1006 static struct switches cmd
[] = {
1007 { "arch", handle_arch
, 1 },
1008 { "os", handle_os
, 1 },
1009 { "param", handle_param
, 1 },
1010 { "version", handle_version
},
1013 struct switches
*s
= cmd
;
1016 int optlen
= strlen(s
->name
);
1017 if (!strncmp(s
->name
, arg
, optlen
+ !s
->prefix
))
1018 return s
->fn(arg
+ optlen
, next
);
1024 char **handle_switch(char *arg
, char **next
)
1027 case 'a': return handle_switch_a(arg
, next
);
1028 case 'D': return handle_switch_D(arg
, next
);
1029 case 'd': return handle_switch_d(arg
, next
);
1030 case 'E': return handle_switch_E(arg
, next
);
1031 case 'f': return handle_switch_f(arg
, next
);
1032 case 'g': return handle_switch_g(arg
, next
);
1033 case 'G': return handle_switch_G(arg
, next
);
1034 case 'I': return handle_switch_I(arg
, next
);
1035 case 'i': return handle_switch_i(arg
, next
);
1036 case 'M': return handle_switch_M(arg
, next
);
1037 case 'm': return handle_switch_m(arg
, next
);
1038 case 'n': return handle_switch_n(arg
, next
);
1039 case 'o': return handle_switch_o(arg
, next
);
1040 case 'O': return handle_switch_O(arg
, next
);
1041 case 'p': return handle_switch_p(arg
, next
);
1042 case 's': return handle_switch_s(arg
, next
);
1043 case 'U': return handle_switch_U(arg
, next
);
1044 case 'v': return handle_switch_v(arg
, next
);
1045 case 'W': return handle_switch_W(arg
, next
);
1046 case 'x': return handle_switch_x(arg
, next
);
1047 case '-': return handle_long_options(arg
+ 1, next
);
1053 * Ignore unknown command line options:
1054 * they're probably gcc switches
1059 void handle_switch_finalize(void)
1061 handle_switch_v_finalize();
1062 handle_switch_W_finalize();