main.c revision 1.1
1/*- 2 * Copyright (c) 2010 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by David A. Holland. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include <stdbool.h> 31#include <stdio.h> 32#include <stdarg.h> 33#include <stdlib.h> 34#include <string.h> 35#include <errno.h> 36 37#include "version.h" 38#include "config.h" 39#include "utils.h" 40#include "array.h" 41#include "mode.h" 42#include "place.h" 43#include "files.h" 44#include "directive.h" 45#include "macro.h" 46 47struct mode mode = { 48 .werror = false, 49 50 .input_allow_dollars = false, 51 .input_tabstop = 8, 52 53 .do_stdinc = true, 54 .do_stddef = true, 55 56 .do_output = true, 57 .output_linenumbers = true, 58 .output_retain_comments = false, 59 .output_file = NULL, 60 61 .do_depend = false, 62 .depend_report_system = false, 63 .depend_assume_generated = false, 64 .depend_issue_fakerules = false, 65 .depend_quote_target = true, 66 .depend_target = NULL, 67 .depend_file = NULL, 68 69 .do_macrolist = false, 70 .macrolist_include_stddef = false, 71 .macrolist_include_expansions = false, 72 73 .do_trace = false, 74 .trace_namesonly = false, 75 .trace_indented = false, 76}; 77 78struct warns warns = { 79 .endiflabels = true, 80 .nestcomment = false, 81 .undef = false, 82 .unused = false, 83}; 84 85//////////////////////////////////////////////////////////// 86// commandline macros 87 88struct commandline_macro { 89 struct place where; 90 struct place where2; 91 const char *macro; 92 const char *expansion; 93}; 94 95static struct array commandline_macros; 96 97static 98void 99commandline_macros_init(void) 100{ 101 array_init(&commandline_macros); 102} 103 104static 105void 106commandline_macros_cleanup(void) 107{ 108 unsigned i, num; 109 struct commandline_macro *cm; 110 111 num = array_num(&commandline_macros); 112 for (i=0; i<num; i++) { 113 cm = array_get(&commandline_macros, i); 114 dofree(cm, sizeof(*cm)); 115 } 116 array_setsize(&commandline_macros, 0); 117 118 array_cleanup(&commandline_macros); 119} 120 121static 122void 123commandline_macro_add(const struct place *p, const char *macro, 124 const struct place *p2, const char *expansion) 125{ 126 struct commandline_macro *cm; 127 128 cm = domalloc(sizeof(*cm)); 129 cm->where = *p; 130 cm->where2 = *p2; 131 cm->macro = macro; 132 cm->expansion = expansion; 133 134 array_add(&commandline_macros, cm, NULL); 135} 136 137static 138void 139commandline_def(const struct place *p, char *str) 140{ 141 struct place p2; 142 char *val; 143 144 if (*str == '\0') { 145 complain(NULL, "-D: macro name expected"); 146 die(); 147 } 148 149 val = strchr(str, '='); 150 if (val != NULL) { 151 *val = '\0'; 152 val++; 153 } 154 155 if (val) { 156 p2 = *p; 157 p2.column += strlen(str); 158 } else { 159 place_setbuiltin(&p2, 1); 160 } 161 commandline_macro_add(p, str, &p2, val ? val : "1"); 162} 163 164static 165void 166commandline_undef(const struct place *p, char *str) 167{ 168 if (*str == '\0') { 169 complain(NULL, "-D: macro name expected"); 170 die(); 171 } 172 commandline_macro_add(p, str, p, NULL); 173} 174 175static 176void 177apply_commandline_macros(void) 178{ 179 struct commandline_macro *cm; 180 unsigned i, num; 181 182 num = array_num(&commandline_macros); 183 for (i=0; i<num; i++) { 184 cm = array_get(&commandline_macros, i); 185 if (cm->expansion != NULL) { 186 macro_define_plain(&cm->where, cm->macro, 187 &cm->where2, cm->expansion); 188 } else { 189 macro_undef(cm->macro); 190 } 191 dofree(cm, sizeof(*cm)); 192 } 193 array_setsize(&commandline_macros, 0); 194} 195 196static 197void 198apply_builtin_macro(unsigned num, const char *name, const char *val) 199{ 200 struct place p; 201 202 place_setbuiltin(&p, num); 203 macro_define_plain(&p, name, &p, val); 204} 205 206static 207void 208apply_builtin_macros(void) 209{ 210 unsigned n = 1; 211 212#ifdef CONFIG_OS 213 apply_builtin_macro(n++, CONFIG_OS, "1"); 214#endif 215#ifdef CONFIG_OS_2 216 apply_builtin_macro(n++, CONFIG_OS_2, "1"); 217#endif 218 219#ifdef CONFIG_CPU 220 apply_builtin_macro(n++, CONFIG_CPU, "1"); 221#endif 222#ifdef CONFIG_CPU_2 223 apply_builtin_macro(n++, CONFIG_CPU_2, "1"); 224#endif 225 226#ifdef CONFIG_SIZE 227 apply_builtin_macro(n++, CONFIG_SIZE, "1"); 228#endif 229#ifdef CONFIG_BINFMT 230 apply_builtin_macro(n++, CONFIG_BINFMT, "1"); 231#endif 232 233#ifdef CONFIG_COMPILER 234 apply_builtin_macro(n++, CONFIG_COMPILER, VERSION_MAJOR); 235 apply_builtin_macro(n++, CONFIG_COMPILER_MINOR, VERSION_MINOR); 236 apply_builtin_macro(n++, "__VERSION__", VERSION_LONG); 237#endif 238} 239 240//////////////////////////////////////////////////////////// 241// extra included files 242 243struct commandline_file { 244 struct place where; 245 char *name; 246 bool suppress_output; 247}; 248 249static struct array commandline_files; 250 251static 252void 253commandline_files_init(void) 254{ 255 array_init(&commandline_files); 256} 257 258static 259void 260commandline_files_cleanup(void) 261{ 262 unsigned i, num; 263 struct commandline_file *cf; 264 265 num = array_num(&commandline_files); 266 for (i=0; i<num; i++) { 267 cf = array_get(&commandline_files, i); 268 if (cf != NULL) { 269 dofree(cf, sizeof(*cf)); 270 } 271 } 272 array_setsize(&commandline_files, 0); 273 274 array_cleanup(&commandline_files); 275} 276 277static 278void 279commandline_addfile(const struct place *p, char *name, bool suppress_output) 280{ 281 struct commandline_file *cf; 282 283 cf = domalloc(sizeof(*cf)); 284 cf->where = *p; 285 cf->name = name; 286 cf->suppress_output = suppress_output; 287 array_add(&commandline_files, cf, NULL); 288} 289 290static 291void 292commandline_addfile_output(const struct place *p, char *name) 293{ 294 commandline_addfile(p, name, false); 295} 296 297static 298void 299commandline_addfile_nooutput(const struct place *p, char *name) 300{ 301 commandline_addfile(p, name, true); 302} 303 304static 305void 306read_commandline_files(void) 307{ 308 struct commandline_file *cf; 309 unsigned i, num; 310 bool save = false; 311 312 num = array_num(&commandline_files); 313 for (i=0; i<num; i++) { 314 cf = array_get(&commandline_files, i); 315 array_set(&commandline_files, i, NULL); 316 if (cf->suppress_output) { 317 save = mode.do_output; 318 mode.do_output = false; 319 file_readquote(&cf->where, cf->name); 320 mode.do_output = save; 321 } else { 322 file_readquote(&cf->where, cf->name); 323 } 324 dofree(cf, sizeof(*cf)); 325 } 326 array_setsize(&commandline_files, 0); 327} 328 329//////////////////////////////////////////////////////////// 330// include path accumulation 331 332static struct stringarray incpath_quote; 333static struct stringarray incpath_user; 334static struct stringarray incpath_system; 335static struct stringarray incpath_late; 336static const char *sysroot; 337 338static 339void 340incpath_init(void) 341{ 342 stringarray_init(&incpath_quote); 343 stringarray_init(&incpath_user); 344 stringarray_init(&incpath_system); 345 stringarray_init(&incpath_late); 346} 347 348static 349void 350incpath_cleanup(void) 351{ 352 stringarray_setsize(&incpath_quote, 0); 353 stringarray_setsize(&incpath_user, 0); 354 stringarray_setsize(&incpath_system, 0); 355 stringarray_setsize(&incpath_late, 0); 356 357 stringarray_cleanup(&incpath_quote); 358 stringarray_cleanup(&incpath_user); 359 stringarray_cleanup(&incpath_system); 360 stringarray_cleanup(&incpath_late); 361} 362 363static 364void 365commandline_isysroot(const struct place *p, char *dir) 366{ 367 (void)p; 368 sysroot = dir; 369} 370 371static 372void 373commandline_addincpath(struct stringarray *arr, char *s) 374{ 375 if (*s == '\0') { 376 complain(NULL, "Empty include directory"); 377 die(); 378 } 379 stringarray_add(arr, s, NULL); 380} 381 382static 383void 384commandline_addincpath_quote(const struct place *p, char *dir) 385{ 386 (void)p; 387 commandline_addincpath(&incpath_quote, dir); 388} 389 390static 391void 392commandline_addincpath_user(const struct place *p, char *dir) 393{ 394 (void)p; 395 commandline_addincpath(&incpath_user, dir); 396} 397 398static 399void 400commandline_addincpath_system(const struct place *p, char *dir) 401{ 402 (void)p; 403 commandline_addincpath(&incpath_system, dir); 404} 405 406static 407void 408commandline_addincpath_late(const struct place *p, char *dir) 409{ 410 (void)p; 411 commandline_addincpath(&incpath_late, dir); 412} 413 414static 415void 416loadincludepath(void) 417{ 418 unsigned i, num; 419 const char *dir; 420 char *t; 421 422 num = stringarray_num(&incpath_quote); 423 for (i=0; i<num; i++) { 424 dir = stringarray_get(&incpath_quote, i); 425 files_addquotepath(dir, false); 426 } 427 files_addquotepath(NULL, false); 428 429 num = stringarray_num(&incpath_user); 430 for (i=0; i<num; i++) { 431 dir = stringarray_get(&incpath_user, i); 432 files_addquotepath(dir, false); 433 files_addbracketpath(dir, false); 434 } 435 436 if (mode.do_stdinc) { 437 if (sysroot != NULL) { 438 t = dostrdup3(sysroot, "/", CONFIG_LOCALINCLUDE); 439 freestringlater(t); 440 dir = t; 441 } else { 442 dir = CONFIG_LOCALINCLUDE; 443 } 444 files_addquotepath(dir, true); 445 files_addbracketpath(dir, true); 446 447 if (sysroot != NULL) { 448 t = dostrdup3(sysroot, "/", CONFIG_SYSTEMINCLUDE); 449 freestringlater(t); 450 dir = t; 451 } else { 452 dir = CONFIG_SYSTEMINCLUDE; 453 } 454 files_addquotepath(dir, true); 455 files_addbracketpath(dir, true); 456 } 457 458 num = stringarray_num(&incpath_system); 459 for (i=0; i<num; i++) { 460 dir = stringarray_get(&incpath_system, i); 461 files_addquotepath(dir, true); 462 files_addbracketpath(dir, true); 463 } 464 465 num = stringarray_num(&incpath_late); 466 for (i=0; i<num; i++) { 467 dir = stringarray_get(&incpath_late, i); 468 files_addquotepath(dir, false); 469 files_addbracketpath(dir, false); 470 } 471} 472 473//////////////////////////////////////////////////////////// 474// silly commandline stuff 475 476static const char *commandline_prefix; 477 478static 479void 480commandline_setprefix(const struct place *p, char *prefix) 481{ 482 (void)p; 483 commandline_prefix = prefix; 484} 485 486static 487void 488commandline_addincpath_user_withprefix(const struct place *p, char *dir) 489{ 490 char *s; 491 492 if (commandline_prefix == NULL) { 493 complain(NULL, "-iprefix needed"); 494 die(); 495 } 496 s = dostrdup3(commandline_prefix, "/", dir); 497 freestringlater(s); 498 commandline_addincpath_user(p, s); 499} 500 501static 502void 503commandline_addincpath_late_withprefix(const struct place *p, char *dir) 504{ 505 char *s; 506 507 if (commandline_prefix == NULL) { 508 complain(NULL, "-iprefix needed"); 509 die(); 510 } 511 s = dostrdup3(commandline_prefix, "/", dir); 512 freestringlater(s); 513 commandline_addincpath_late(p, s); 514} 515 516static 517void 518commandline_setstd(const struct place *p, char *std) 519{ 520 (void)p; 521 522 if (!strcmp(std, "krc")) { 523 return; 524 } 525 complain(NULL, "Standard %s not supported by this preprocessor", std); 526 die(); 527} 528 529static 530void 531commandline_setlang(const struct place *p, char *lang) 532{ 533 (void)p; 534 535 if (!strcmp(lang, "c") || !strcmp(lang, "assembler-with-cpp")) { 536 return; 537 } 538 complain(NULL, "Language %s not supported by this preprocessor", lang); 539 die(); 540} 541 542//////////////////////////////////////////////////////////// 543// complex modes 544 545DEAD static 546void 547commandline_iremap(const struct place *p, char *str) 548{ 549 (void)p; 550 /* XXX */ 551 (void)str; 552 complain(NULL, "-iremap not supported"); 553 die(); 554} 555 556static 557void 558commandline_tabstop(const struct place *p, char *s) 559{ 560 char *t; 561 unsigned long val; 562 563 (void)p; 564 565 t = strchr(s, '='); 566 if (t == NULL) { 567 /* should not happen */ 568 complain(NULL, "Invalid tabstop"); 569 die(); 570 } 571 t++; 572 errno = 0; 573 val = strtoul(t, &t, 10); 574 if (errno || *t != '\0') { 575 complain(NULL, "Invalid tabstop"); 576 die(); 577 } 578 if (val > 64) { 579 complain(NULL, "Preposterously large tabstop"); 580 die(); 581 } 582 mode.input_tabstop = val; 583} 584 585/* 586 * macrolist 587 */ 588 589static 590void 591commandline_dD(void) 592{ 593 mode.do_macrolist = true; 594 mode.macrolist_include_stddef = false; 595 mode.macrolist_include_expansions = true; 596} 597 598static 599void 600commandline_dM(void) 601{ 602 mode.do_macrolist = true; 603 mode.macrolist_include_stddef = true; 604 mode.macrolist_include_expansions = true; 605 mode.do_output = false; 606} 607 608static 609void 610commandline_dN(void) 611{ 612 mode.do_macrolist = true; 613 mode.macrolist_include_stddef = false; 614 mode.macrolist_include_expansions = false; 615} 616 617/* 618 * include trace 619 */ 620 621static 622void 623commandline_dI(void) 624{ 625 mode.do_trace = true; 626 mode.trace_namesonly = false; 627 mode.trace_indented = false; 628} 629 630static 631void 632commandline_H(void) 633{ 634 mode.do_trace = true; 635 mode.trace_namesonly = true; 636 mode.trace_indented = true; 637} 638 639/* 640 * depend 641 */ 642 643static 644void 645commandline_setdependtarget(const struct place *p, char *str) 646{ 647 (void)p; 648 mode.depend_target = str; 649 mode.depend_quote_target = false; 650} 651 652static 653void 654commandline_setdependtarget_quoted(const struct place *p, char *str) 655{ 656 (void)p; 657 mode.depend_target = str; 658 mode.depend_quote_target = true; 659} 660 661static 662void 663commandline_setdependoutput(const struct place *p, char *str) 664{ 665 (void)p; 666 mode.depend_file = str; 667} 668 669static 670void 671commandline_M(void) 672{ 673 mode.do_depend = true; 674 mode.depend_report_system = true; 675 mode.do_output = false; 676} 677 678static 679void 680commandline_MM(void) 681{ 682 mode.do_depend = true; 683 mode.depend_report_system = false; 684 mode.do_output = false; 685} 686 687static 688void 689commandline_MD(void) 690{ 691 mode.do_depend = true; 692 mode.depend_report_system = true; 693} 694 695static 696void 697commandline_MMD(void) 698{ 699 mode.do_depend = true; 700 mode.depend_report_system = false; 701} 702 703static 704void 705commandline_wall(void) 706{ 707 warns.nestcomment = true; 708 warns.undef = true; 709 warns.unused = true; 710} 711 712static 713void 714commandline_wnoall(void) 715{ 716 warns.nestcomment = false; 717 warns.undef = false; 718 warns.unused = false; 719} 720 721static 722void 723commandline_wnone(void) 724{ 725 warns.nestcomment = false; 726 warns.endiflabels = false; 727 warns.undef = false; 728 warns.unused = false; 729} 730 731//////////////////////////////////////////////////////////// 732// options 733 734struct ignore_option { 735 const char *string; 736}; 737 738struct flag_option { 739 const char *string; 740 bool *flag; 741 bool setto; 742}; 743 744struct act_option { 745 const char *string; 746 void (*func)(void); 747}; 748 749struct prefix_option { 750 const char *string; 751 void (*func)(const struct place *, char *); 752}; 753 754struct arg_option { 755 const char *string; 756 void (*func)(const struct place *, char *); 757}; 758 759static const struct ignore_option ignore_options[] = { 760 { "m32" }, 761 { "traditional" }, 762}; 763static const unsigned num_ignore_options = HOWMANY(ignore_options); 764 765static const struct flag_option flag_options[] = { 766 { "C", &mode.output_retain_comments, true }, 767 { "CC", &mode.output_retain_comments, true }, 768 { "MG", &mode.depend_assume_generated, true }, 769 { "MP", &mode.depend_issue_fakerules, true }, 770 { "P", &mode.output_linenumbers, false }, 771 { "Wcomment", &warns.nestcomment, true }, 772 { "Wendif-labels", &warns.endiflabels, true }, 773 { "Werror", &mode.werror, true }, 774 { "Wno-comment", &warns.nestcomment, false }, 775 { "Wno-endif-labels", &warns.endiflabels, false }, 776 { "Wno-error", &mode.werror, false }, 777 { "Wno-undef", &warns.undef, false }, 778 { "Wno-unused-macros", &warns.unused, false }, 779 { "Wundef", &warns.undef, true }, 780 { "Wunused-macros", &warns.unused, true }, 781 { "fdollars-in-identifiers", &mode.input_allow_dollars, true }, 782 { "fno-dollars-in-identifiers", &mode.input_allow_dollars, false }, 783 { "nostdinc", &mode.do_stdinc, false }, 784 { "undef", &mode.do_stddef, false }, 785}; 786static const unsigned num_flag_options = HOWMANY(flag_options); 787 788static const struct act_option act_options[] = { 789 { "H", commandline_H }, 790 { "M", commandline_M }, 791 { "MD", commandline_MD }, 792 { "MM", commandline_MM }, 793 { "MMD", commandline_MMD }, 794 { "Wall", commandline_wall }, 795 { "Wno-all", commandline_wnoall }, 796 { "dD", commandline_dD }, 797 { "dI", commandline_dI }, 798 { "dM", commandline_dM }, 799 { "dN", commandline_dN }, 800 { "w", commandline_wnone }, 801}; 802static const unsigned num_act_options = HOWMANY(act_options); 803 804static const struct prefix_option prefix_options[] = { 805 { "D", commandline_def }, 806 { "I", commandline_addincpath_user }, 807 { "U", commandline_undef }, 808 { "ftabstop=", commandline_tabstop }, 809 { "std=", commandline_setstd }, 810}; 811static const unsigned num_prefix_options = HOWMANY(prefix_options); 812 813static const struct arg_option arg_options[] = { 814 { "MF", commandline_setdependoutput }, 815 { "MQ", commandline_setdependtarget_quoted }, 816 { "MT", commandline_setdependtarget }, 817 { "idirafter", commandline_addincpath_late }, 818 { "imacros", commandline_addfile_nooutput }, 819 { "include", commandline_addfile_output }, 820 { "iprefix", commandline_setprefix }, 821 { "iquote", commandline_addincpath_quote }, 822 { "iremap", commandline_iremap }, 823 { "isysroot", commandline_isysroot }, 824 { "isystem", commandline_addincpath_system }, 825 { "iwithprefix", commandline_addincpath_late_withprefix }, 826 { "iwithprefixbefore", commandline_addincpath_user_withprefix }, 827 { "x", commandline_setlang }, 828}; 829static const unsigned num_arg_options = HOWMANY(arg_options); 830 831static 832bool 833check_ignore_option(const char *opt) 834{ 835 unsigned i; 836 int r; 837 838 for (i=0; i<num_ignore_options; i++) { 839 r = strcmp(opt, ignore_options[i].string); 840 if (r == 0) { 841 return true; 842 } 843 if (r < 0) { 844 break; 845 } 846 } 847 return false; 848} 849 850static 851bool 852check_flag_option(const char *opt) 853{ 854 unsigned i; 855 int r; 856 857 for (i=0; i<num_flag_options; i++) { 858 r = strcmp(opt, flag_options[i].string); 859 if (r == 0) { 860 *flag_options[i].flag = flag_options[i].setto; 861 return true; 862 } 863 if (r < 0) { 864 break; 865 } 866 } 867 return false; 868} 869 870static 871bool 872check_act_option(const char *opt) 873{ 874 unsigned i; 875 int r; 876 877 for (i=0; i<num_act_options; i++) { 878 r = strcmp(opt, act_options[i].string); 879 if (r == 0) { 880 act_options[i].func(); 881 return true; 882 } 883 if (r < 0) { 884 break; 885 } 886 } 887 return false; 888} 889 890static 891bool 892check_prefix_option(const struct place *p, char *opt) 893{ 894 unsigned i, len; 895 int r; 896 897 for (i=0; i<num_prefix_options; i++) { 898 len = strlen(prefix_options[i].string); 899 r = strncmp(opt, prefix_options[i].string, len); 900 if (r == 0) { 901 prefix_options[i].func(p, opt + len); 902 return true; 903 } 904 if (r < 0) { 905 break; 906 } 907 } 908 return false; 909} 910 911static 912bool 913check_arg_option(const char *opt, const struct place *argplace, char *arg) 914{ 915 unsigned i; 916 int r; 917 918 for (i=0; i<num_arg_options; i++) { 919 r = strcmp(opt, arg_options[i].string); 920 if (r == 0) { 921 if (arg == NULL) { 922 complain(NULL, 923 "Option -%s requires an argument", 924 opt); 925 die(); 926 } 927 arg_options[i].func(argplace, arg); 928 return true; 929 } 930 if (r < 0) { 931 break; 932 } 933 } 934 return false; 935} 936 937DEAD static 938void 939usage(const char *progname, const char *fmt, ...) 940{ 941 va_list ap; 942 943 fprintf(stderr, "%s: ", progname); 944 va_start(ap, fmt); 945 vfprintf(stderr, fmt, ap); 946 va_end(ap); 947 fprintf(stderr, "\n"); 948 949 fprintf(stderr, "Usage: %s [options] [infile [outfile]]\n", progname); 950 fprintf(stderr, "Common options:\n"); 951 fprintf(stderr, " -C Retain comments\n"); 952 fprintf(stderr, " -Dmacro[=def] Predefine macro\n"); 953 fprintf(stderr, " -Idir Add to include path\n"); 954 fprintf(stderr, " -M Issue depend info\n"); 955 fprintf(stderr, " -MD Issue depend info and output\n"); 956 fprintf(stderr, " -MM -M w/o system headers\n"); 957 fprintf(stderr, " -MMD -MD w/o system headers\n"); 958 fprintf(stderr, " -nostdinc Drop default include path\n"); 959 fprintf(stderr, " -Umacro Undefine macro\n"); 960 fprintf(stderr, " -undef Undefine everything\n"); 961 fprintf(stderr, " -Wall Enable all warnings\n"); 962 fprintf(stderr, " -Werror Make warnings into errors\n"); 963 fprintf(stderr, " -w Disable all warnings\n"); 964 die(); 965} 966 967//////////////////////////////////////////////////////////// 968// exit and cleanup 969 970static struct stringarray freestrings; 971 972static 973void 974init(void) 975{ 976 stringarray_init(&freestrings); 977 978 incpath_init(); 979 commandline_macros_init(); 980 commandline_files_init(); 981 982 place_init(); 983 files_init(); 984 directive_init(); 985 macros_init(); 986} 987 988static 989void 990cleanup(void) 991{ 992 unsigned i, num; 993 994 macros_cleanup(); 995 directive_cleanup(); 996 files_cleanup(); 997 place_cleanup(); 998 999 commandline_files_cleanup(); 1000 commandline_macros_cleanup(); 1001 incpath_cleanup(); 1002 1003 num = stringarray_num(&freestrings); 1004 for (i=0; i<num; i++) { 1005 dostrfree(stringarray_get(&freestrings, i)); 1006 } 1007 stringarray_setsize(&freestrings, 0); 1008 stringarray_cleanup(&freestrings); 1009} 1010 1011void 1012die(void) 1013{ 1014 cleanup(); 1015 exit(EXIT_FAILURE); 1016} 1017 1018void 1019freestringlater(char *s) 1020{ 1021 stringarray_add(&freestrings, s, NULL); 1022} 1023 1024//////////////////////////////////////////////////////////// 1025// main 1026 1027int 1028main(int argc, char *argv[]) 1029{ 1030 const char *progname; 1031 const char *inputfile = NULL; 1032 const char *outputfile = NULL; 1033 struct place cmdplace; 1034 int i; 1035 1036 progname = strrchr(argv[0], '/'); 1037 progname = progname == NULL ? argv[0] : progname + 1; 1038 complain_init(progname); 1039 1040 init(); 1041 1042 for (i=1; i<argc; i++) { 1043 if (argv[i][0] != '-') { 1044 break; 1045 } 1046 place_setcommandline(&cmdplace, i, 1); 1047 if (check_ignore_option(argv[i]+1)) { 1048 continue; 1049 } 1050 if (check_flag_option(argv[i]+1)) { 1051 continue; 1052 } 1053 if (check_act_option(argv[i]+1)) { 1054 continue; 1055 } 1056 if (check_prefix_option(&cmdplace, argv[i]+1)) { 1057 continue; 1058 } 1059 place_setcommandline(&cmdplace, i+1, 1); 1060 if (check_arg_option(argv[i]+1, &cmdplace, argv[i+1])) { 1061 i++; 1062 continue; 1063 } 1064 usage(progname, "Invalid option %s", argv[i]); 1065 } 1066 if (i < argc) { 1067 inputfile = argv[i++]; 1068 } 1069 if (i < argc) { 1070 outputfile = argv[i++]; 1071 } 1072 if (i < argc) { 1073 usage(progname, "Extra non-option argument %s", argv[i]); 1074 } 1075 1076 mode.output_file = outputfile; 1077 1078 loadincludepath(); 1079 apply_builtin_macros(); 1080 apply_commandline_macros(); 1081 read_commandline_files(); 1082 place_setnowhere(&cmdplace); 1083 file_readabsolute(&cmdplace, inputfile); 1084 1085 cleanup(); 1086 if (complain_failed()) { 1087 return EXIT_FAILURE; 1088 } 1089 return EXIT_SUCCESS; 1090} 1091