00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "version.h"
00025 #include "cppdefault.h"
00026 #include "tradcpp.h"
00027 #include "mkdeps.h"
00028 #include "intl.h"
00029
00030 typedef unsigned char U_CHAR;
00031
00032
00033
00034 static const char *progname;
00035
00036
00037
00038
00039 size_t max_include_len;
00040
00041
00042
00043 int put_out_comments = 0;
00044
00045
00046 struct deps *deps;
00047
00048
00049
00050
00051
00052 int print_deps = 0;
00053
00054
00055
00056 int print_deps_phony_targets = 0;
00057
00058
00059
00060 int deps_append = 0;
00061
00062
00063
00064
00065 const char *deps_file = 0;
00066
00067
00068
00069
00070 int deps_missing_files = 0;
00071
00072
00073
00074 int no_line_commands;
00075
00076
00077
00078
00079
00080 int dump_macros;
00081
00082
00083
00084 int inhibit_warnings = 0;
00085
00086
00087 int inhibit_output = 0;
00088
00089
00090 #if DEFAULT_SIGNED_CHAR
00091 int flag_signed_char = 1;
00092 #else
00093 int flag_signed_char = 0;
00094 #endif
00095
00096
00097
00098 int warn_comments;
00099
00100
00101
00102
00103
00104 int no_output;
00105
00106
00107
00108 static const char *user_label_prefix;
00109
00110
00111
00112
00113
00114
00115 #define INPUT_STACK_MAX 200
00116 struct file_name_list;
00117 struct file_buf {
00118 const char *fname;
00119 int lineno;
00120 int length;
00121 U_CHAR *buf;
00122 U_CHAR *bufp;
00123
00124
00125
00126 struct hashnode *macro;
00127
00128
00129 struct if_stack *if_stack;
00130
00131 U_CHAR *free_ptr;
00132
00133 struct file_name_list *next_header_dir;
00134 } instack[INPUT_STACK_MAX];
00135
00136 typedef struct file_buf FILE_BUF;
00137
00138
00139
00140 int indepth = -1;
00141 #define CHECK_DEPTH(code) \
00142 if (indepth >= (INPUT_STACK_MAX - 1)) \
00143 { \
00144 error_with_line (line_for_error (instack[indepth].lineno), \
00145 "macro or #include recursion too deep"); \
00146 code; \
00147 }
00148
00149
00150 int system_include_depth = 0;
00151
00152
00153
00154
00155
00156 #define OUTBUF_SIZE 10
00157 FILE_BUF outbuf;
00158
00159
00160
00161
00162 #define check_expand(OBUF, NEEDED) do { \
00163 if ((OBUF)->length - ((OBUF)->bufp - (OBUF)->buf) <= (NEEDED)) \
00164 grow_outbuf ((OBUF), (NEEDED)); \
00165 } while (0)
00166
00167 struct file_name_list
00168 {
00169 struct file_name_list *next;
00170 const char *fname;
00171 };
00172
00173 struct file_name_list *include = 0;
00174
00175 struct file_name_list *first_bracket_include = 0;
00176 struct file_name_list *last_include = 0;
00177
00178
00179 struct file_name_list *dont_repeat_files = 0;
00180
00181
00182 struct file_name_list *all_include_files = 0;
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 typedef struct definition DEFINITION;
00206 struct definition {
00207 int nargs;
00208 int length;
00209 U_CHAR *expansion;
00210 struct reflist {
00211 struct reflist *next;
00212 char stringify;
00213
00214 char raw_before;
00215 char raw_after;
00216 int nchars;
00217
00218 int argno;
00219 } *pattern;
00220
00221
00222
00223
00224 const U_CHAR *argnames;
00225 };
00226
00227
00228 struct answer
00229 {
00230 struct answer *next;
00231 const unsigned char *answer;
00232 size_t len;
00233 };
00234
00235
00236
00237 union hashval {
00238 const char *cpval;
00239 DEFINITION *defn;
00240 struct answer *answers;
00241 };
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 enum node_type {
00252 T_DEFINE = 1,
00253 T_INCLUDE,
00254 T_INCLUDE_NEXT,
00255 T_IFDEF,
00256 T_IFNDEF,
00257 T_IF,
00258 T_ELSE,
00259 T_ELIF,
00260 T_UNDEF,
00261 T_LINE,
00262 T_ENDIF,
00263 T_ERROR,
00264 T_WARNING,
00265 T_ASSERT,
00266 T_UNASSERT,
00267 T_SPECLINE,
00268 T_DATE,
00269 T_FILE,
00270 T_BASE_FILE,
00271 T_INCLUDE_LEVEL,
00272 T_VERSION,
00273 T_TIME,
00274 T_CONST,
00275 T_MACRO,
00276 T_SPEC_DEFINED,
00277 T_UNUSED
00278 };
00279
00280 struct hashnode {
00281 struct hashnode *next;
00282 struct hashnode *prev;
00283 struct hashnode **bucket_hdr;
00284
00285
00286 enum node_type type;
00287 int length;
00288 U_CHAR *name;
00289 union hashval value;
00290 };
00291
00292 typedef struct hashnode HASHNODE;
00293
00294 static HASHNODE *parse_assertion PARAMS ((const unsigned char *,
00295 const unsigned char *,
00296 struct answer **, int));
00297 static struct answer **find_answer PARAMS ((HASHNODE *,
00298 const struct answer *));
00299 static int parse_answer PARAMS ((const unsigned char *, const unsigned char *,
00300 struct answer **, int));
00301 static unsigned char *canonicalize_text PARAMS ((const unsigned char *,
00302 const unsigned char *,
00303 const unsigned char **));
00304
00305
00306
00307
00308
00309
00310
00311
00312 #define HASHSIZE 1403
00313 HASHNODE *hashtab[HASHSIZE];
00314 #define HASHSTEP(old, c) ((old << 2) + c)
00315 #define MAKE_POS(v) (v & 0x7fffffff)
00316
00317
00318
00319 struct directive {
00320 const int length;
00321 void (*const func) PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00322
00323 const char *const name;
00324 const enum node_type type;
00325 };
00326
00327
00328 enum file_change_code {same_file, enter_file, leave_file};
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 struct argdata {
00340 U_CHAR *raw, *expanded;
00341 int raw_length, expand_length;
00342 int stringified_length;
00343 U_CHAR *free1, *free2;
00344 char newlines;
00345 char comments;
00346 };
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 struct arglist {
00360 struct arglist *next;
00361 U_CHAR *name;
00362 int length;
00363 int argno;
00364 };
00365
00366
00367
00368 static void do_define PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00369 static void do_error PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00370 static void do_warning PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00371 static void do_line PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00372 static void do_include PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00373 static void do_include_next PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00374 static void do_undef PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00375 static void do_if PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00376 static void do_ifdef PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00377 static void do_ifndef PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00378 static void do_else PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00379 static void do_elif PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00380 static void do_endif PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00381 static void do_assert PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00382 static void do_unassert PARAMS ((U_CHAR *, U_CHAR *, FILE_BUF *));
00383 static void do_xifdef PARAMS ((U_CHAR *, U_CHAR *, enum node_type));
00384
00385 static struct hashnode *install PARAMS ((const U_CHAR *, int, enum node_type, int));
00386 static int hashf PARAMS ((const U_CHAR *, int, int));
00387 static int compare_defs PARAMS ((DEFINITION *, DEFINITION *));
00388 static int comp_def_part PARAMS ((int, const U_CHAR *, int,
00389 const U_CHAR *, int, int));
00390 static void delete_macro PARAMS ((HASHNODE *));
00391
00392
00393 enum msgtype { MT_WARNING = 0, MT_ERROR, MT_FATAL };
00394 static void v_message PARAMS ((enum msgtype mtype, int line,
00395 const char *msgid, va_list ap))
00396 ATTRIBUTE_PRINTF (3, 0);
00397
00398 static int line_for_error PARAMS ((int));
00399
00400
00401
00402 #undef abort
00403 #if (GCC_VERSION >= 2007)
00404 #define abort() fancy_abort(__LINE__, __FUNCTION__)
00405 #else
00406 #define abort() fancy_abort(__LINE__, 0);
00407 #endif
00408
00409 static void macroexpand PARAMS ((HASHNODE *, FILE_BUF *));
00410 static void special_symbol PARAMS ((HASHNODE *, FILE_BUF *));
00411 static void dump_all_macros PARAMS ((void));
00412 static void dump_defn_1 PARAMS ((const U_CHAR *, int, int));
00413 static void dump_arg_n PARAMS ((DEFINITION *, int));
00414 static void conditional_skip PARAMS ((FILE_BUF *, int, enum node_type));
00415 static void skip_if_group PARAMS ((FILE_BUF *, int));
00416 static void output_line_command PARAMS ((FILE_BUF *, FILE_BUF *,
00417 int, enum file_change_code));
00418
00419 static int eval_if_expression PARAMS ((const U_CHAR *, int));
00420
00421 static void output_deps PARAMS ((void));
00422 static void initialize_builtins PARAMS ((void));
00423 static void run_directive PARAMS ((const char *, size_t,
00424 enum node_type));
00425 static void make_definition PARAMS ((const char *));
00426 static void make_undef PARAMS ((const char *));
00427 static void make_assertion PARAMS ((const char *));
00428
00429 static void grow_outbuf PARAMS ((FILE_BUF *, int));
00430 static int handle_directive PARAMS ((FILE_BUF *, FILE_BUF *));
00431 static void process_include PARAMS ((struct file_name_list *,
00432 const U_CHAR *, int, int, FILE_BUF *));
00433 static void fixup_newlines PARAMS ((FILE_BUF *));
00434 static void finclude PARAMS ((int, const char *,
00435 struct file_name_list *, FILE_BUF *));
00436 static void init_dependency_output PARAMS ((void));
00437 static void rescan PARAMS ((FILE_BUF *, int));
00438 static void newline_fix PARAMS ((U_CHAR *));
00439 static void name_newline_fix PARAMS ((U_CHAR *));
00440 static U_CHAR *macarg1 PARAMS ((U_CHAR *, const U_CHAR *, int *,
00441 int *, int *));
00442 static const char *macarg PARAMS ((struct argdata *));
00443 static int discard_comments PARAMS ((U_CHAR *, int, int));
00444 static int file_size_and_mode PARAMS ((int, int *, long *));
00445
00446 static U_CHAR *skip_to_end_of_comment PARAMS ((FILE_BUF *, int *));
00447 static U_CHAR *skip_quoted_string PARAMS ((const U_CHAR *, const U_CHAR *,
00448 int, int *, int *, int *));
00449
00450 int main PARAMS ((int, char **));
00451
00452
00453 #define U (const unsigned char *)
00454
00455
00456
00457 static const struct directive directive_table[] = {
00458 { 6, do_define, "define", T_DEFINE },
00459 { 7, do_include, "include", T_INCLUDE },
00460 { 5, do_endif, "endif", T_ENDIF },
00461 { 5, do_ifdef, "ifdef", T_IFDEF },
00462 { 2, do_if, "if", T_IF, },
00463 { 4, do_else, "else", T_ELSE },
00464 { 6, do_ifndef, "ifndef", T_IFNDEF },
00465 { 5, do_undef, "undef", T_UNDEF },
00466 { 4, do_line, "line", T_LINE },
00467 { 4, do_elif, "elif", T_ELIF },
00468 { 5, do_error, "error", T_ERROR },
00469 { 7, do_warning, "warning", T_WARNING },
00470 { 12, do_include_next, "include_next", T_INCLUDE_NEXT },
00471 { 6, do_assert, "assert", T_ASSERT },
00472 { 8, do_unassert,"unassert",T_UNASSERT},
00473 { -1, 0, "", T_UNUSED},
00474 };
00475
00476 #define SKIP_WHITE_SPACE(p) do { while (is_nvspace(*p)) p++; } while (0)
00477 #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space(*p)) p++; } while (0)
00478
00479 int errors = 0;
00480
00481 static FILE_BUF expand_to_temp_buffer PARAMS ((const U_CHAR *, const U_CHAR *, int));
00482 static DEFINITION *collect_expansion PARAMS ((U_CHAR *, U_CHAR *, int,
00483 struct arglist *));
00484
00485
00486
00487
00488 struct if_stack {
00489 struct if_stack *next;
00490 const char *fname;
00491 int lineno;
00492 int if_succeeded;
00493
00494 enum node_type type;
00495 };
00496 typedef struct if_stack IF_STACK_FRAME;
00497 IF_STACK_FRAME *if_stack = NULL;
00498
00499
00500
00501 int ignore_srcdir;
00502
00503
00504 enum pending_dir_t {PD_NONE = 0, PD_DEFINE, PD_UNDEF, PD_ASSERTION, PD_FILE};
00505
00506 typedef struct pending_dir pending_dir;
00507 struct pending_dir
00508 {
00509 const char *arg;
00510 enum pending_dir_t type;
00511 };
00512
00513 int
00514 main (argc, argv)
00515 int argc;
00516 char **argv;
00517 {
00518 int st_mode;
00519 long st_size;
00520 const char *in_fname, *out_fname;
00521 int f, i;
00522 FILE_BUF *fp;
00523 pending_dir *pend = (pending_dir *) xcalloc (argc, sizeof (pending_dir));
00524 int no_standard_includes = 0;
00525
00526 hex_init ();
00527
00528 #ifdef RLIMIT_STACK
00529
00530 {
00531 struct rlimit rlim;
00532
00533
00534
00535 getrlimit (RLIMIT_STACK, &rlim);
00536 rlim.rlim_cur = rlim.rlim_max;
00537 setrlimit (RLIMIT_STACK, &rlim);
00538 }
00539 #endif
00540
00541 progname = argv[0];
00542
00543 in_fname = NULL;
00544 out_fname = NULL;
00545
00546 no_line_commands = 0;
00547 dump_macros = 0;
00548 no_output = 0;
00549
00550 max_include_len = cpp_GCC_INCLUDE_DIR_len + 7;
00551
00552 gcc_init_libintl ();
00553
00554
00555
00556 deps = deps_init ();
00557
00558
00559
00560 for (i = 1; i < argc; i++) {
00561 if (argv[i][0] != '-') {
00562 if (out_fname != NULL)
00563 fatal ("usage: %s [switches] input output", argv[0]);
00564 else if (in_fname != NULL)
00565 out_fname = argv[i];
00566 else
00567 in_fname = argv[i];
00568 } else {
00569 int c = argv[i][1];
00570
00571 switch (c) {
00572 case 'E':
00573 case '$':
00574 break;
00575
00576 case 'l':
00577 if (!strcmp (argv[i], "-lang-c++")
00578 || !strcmp (argv[i], "-lang-objc++"))
00579 fatal ("-traditional is not supported in C++");
00580 else if (!strcmp (argv[i], "-lang-c89"))
00581 fatal ("-traditional and -ansi are mutually exclusive");
00582 else if (!strcmp (argv[i], "-lang-objc"))
00583 pend[i].type = PD_DEFINE, pend[i].arg = "__OBJC__";
00584 else if (!strcmp (argv[i], "-lang-asm"))
00585 pend[i].type = PD_DEFINE, pend[i].arg = "__ASSEMBLER__";
00586 else if (!strcmp (argv[i], "-lang-fortran"))
00587 pend[i].type = PD_DEFINE, pend[i].arg = "_LANGUAGE_FORTRAN";
00588
00589 break;
00590
00591 case 'i':
00592 if (!strcmp (argv[i], "-include"))
00593 {
00594 if (i + 1 == argc)
00595 fatal ("filename missing after -i option");
00596 else
00597 pend[i].type = PD_FILE, pend[i].arg = argv[i + 1], i++;
00598 }
00599 else if (!strcmp (argv[i], "-iprefix"))
00600 i++;
00601 else if (!strcmp (argv[i], "-isystem")
00602 || !strcmp (argv[i], "-iwithprefix")
00603 || !strcmp (argv[i], "-iwithprefixbefore")
00604 || !strcmp (argv[i], "-idirafter"))
00605 goto add_include;
00606
00607 break;
00608
00609 case 'o':
00610 if (out_fname != NULL)
00611 fatal ("output filename specified twice");
00612 if (i + 1 == argc)
00613 fatal ("filename missing after -o option");
00614 out_fname = argv[++i];
00615 if (!strcmp (out_fname, "-"))
00616 out_fname = "";
00617 break;
00618
00619 case 'w':
00620 inhibit_warnings = 1;
00621 break;
00622
00623 case 'W':
00624 if (!strcmp (argv[i], "-Wcomments"))
00625 warn_comments = 1;
00626 else if (!strcmp (argv[i], "-Wcomment"))
00627 warn_comments = 1;
00628 else if (!strcmp (argv[i], "-Wall")) {
00629 warn_comments = 1;
00630 }
00631 break;
00632
00633 case 'f':
00634 if (!strcmp (argv[i], "-fleading-underscore"))
00635 user_label_prefix = "_";
00636 else if (!strcmp (argv[i], "-fno-leading-underscore"))
00637 user_label_prefix = "";
00638 else if (!strcmp (argv[i], "-fsigned-char"))
00639 flag_signed_char = 1;
00640 else if (!strcmp (argv[i], "-funsigned-char"))
00641 flag_signed_char = 0;
00642 break;
00643
00644 case 'M':
00645 {
00646 char *p = NULL;
00647
00648
00649
00650
00651
00652
00653
00654 if (!strncmp (argv[i], "-MD", 3)) {
00655 p = argv[i] + 3;
00656 print_deps = 2;
00657 } else if (!strncmp (argv[i], "-MMD", 4)) {
00658 p = argv[i] + 4;
00659 print_deps = 1;
00660 } else if (!strcmp (argv[i], "-M")) {
00661 print_deps = 2;
00662 } else if (!strcmp (argv[i], "-MM")) {
00663 print_deps = 1;
00664 } else if (!strcmp (argv[i], "-MG")) {
00665 deps_missing_files = 1;
00666 } else if (!strcmp (argv[i], "-MF")) {
00667 p = argv[i] + 3;
00668 } else if (!strcmp (argv[i], "-MP")) {
00669 print_deps_phony_targets = 1;
00670 } else if (!strcmp (argv[i], "-MQ") || !strcmp (argv[i], "-MT")) {
00671
00672 const char *tgt = argv[i] + 3;
00673 int quoted = argv[i][2] == 'Q';
00674
00675 if (*tgt == '\0' && i + 1 == argc)
00676 fatal ("target missing after %s option", argv[i]);
00677 else
00678 {
00679 if (*tgt == '\0')
00680 tgt = argv[++i];
00681
00682 deps_add_target (deps, tgt, quoted);
00683 }
00684 }
00685
00686 if (p) {
00687 if (*p)
00688 deps_file = p;
00689 else if (i + 1 == argc)
00690 fatal ("filename missing after %s option", argv[i]);
00691 else
00692 deps_file = argv[++i];
00693 }
00694 }
00695 break;
00696
00697 case 'd':
00698 dump_macros = 1;
00699 no_output = 1;
00700 break;
00701
00702 case 'v':
00703 fprintf (stderr, "GNU traditional CPP version %s\n", version_string);
00704 break;
00705
00706 case 'D':
00707 case 'U':
00708 case 'A':
00709 {
00710 char *p;
00711
00712 if (argv[i][2] != 0)
00713 p = argv[i] + 2;
00714 else if (i + 1 == argc)
00715 fatal ("macro name missing after -%c option", c);
00716 else
00717 p = argv[++i];
00718
00719 if (c == 'D')
00720 pend[i].type = PD_DEFINE;
00721 else if (c == 'U')
00722 pend[i].type = PD_UNDEF;
00723 else
00724 pend[i].type = PD_ASSERTION;
00725 pend[i].arg = p;
00726 }
00727 break;
00728
00729 case 'C':
00730 put_out_comments = 1;
00731 break;
00732
00733 case 'p':
00734 if (!strcmp (argv[i], "-pedantic"))
00735 fatal ("-pedantic and -traditional are mutually exclusive");
00736 break;
00737
00738 case 't':
00739 if (!strcmp (argv[i], "-trigraphs"))
00740 fatal ("-trigraphs and -traditional are mutually exclusive");
00741 break;
00742
00743 case 'P':
00744 no_line_commands = 1;
00745 break;
00746
00747 case 'I':
00748 add_include:
00749 {
00750 struct file_name_list *dirtmp;
00751
00752 if (! ignore_srcdir && !strcmp (argv[i] + 2, "-"))
00753 ignore_srcdir = 1;
00754 else {
00755 dirtmp = (struct file_name_list *)
00756 xmalloc (sizeof (struct file_name_list));
00757 dirtmp->next = 0;
00758 if (include == 0)
00759 include = dirtmp;
00760 else
00761 last_include->next = dirtmp;
00762 last_include = dirtmp;
00763 if (argv[i][1] == 'I' && argv[i][2] != 0)
00764 dirtmp->fname = argv[i] + 2;
00765 else if (i + 1 == argc)
00766 fatal ("directory name missing after -I option");
00767 else
00768 dirtmp->fname = argv[++i];
00769 if (strlen (dirtmp->fname) > max_include_len)
00770 max_include_len = strlen (dirtmp->fname);
00771 if (ignore_srcdir && first_bracket_include == 0)
00772 first_bracket_include = dirtmp;
00773 }
00774 }
00775 break;
00776
00777 case 'n':
00778
00779
00780 no_standard_includes = 1;
00781 break;
00782
00783 case '\0':
00784 if (in_fname == NULL) {
00785 in_fname = "";
00786 break;
00787 } else if (out_fname == NULL) {
00788 out_fname = "";
00789 break;
00790 }
00791
00792 default:
00793 fatal ("invalid option `%s'", argv[i]);
00794 }
00795 }
00796 }
00797
00798 init_dependency_output ();
00799
00800
00801
00802 if (print_deps == 0
00803 && (deps_missing_files || deps_file || print_deps_phony_targets))
00804 fatal ("you must additionally specify either -M or -MM");
00805
00806 if (user_label_prefix == 0)
00807 user_label_prefix = USER_LABEL_PREFIX;
00808
00809 if (print_deps)
00810 {
00811
00812
00813 deps_add_default_target (deps, in_fname);
00814
00815 deps_add_dep (deps, in_fname);
00816 }
00817
00818
00819 initialize_builtins ();
00820
00821
00822 for (i = 1; i < argc; i++)
00823 if (pend[i].type == PD_DEFINE)
00824 make_definition (pend[i].arg);
00825 else if (pend[i].type == PD_UNDEF)
00826 make_undef (pend[i].arg);
00827 else if (pend[i].type == PD_ASSERTION)
00828 make_assertion (pend[i].arg);
00829
00830
00831
00832 if (!no_standard_includes) {
00833 const struct default_include *di;
00834 struct file_name_list *old_last_include = last_include;
00835 struct file_name_list *dirtmp;
00836 for (di = cpp_include_defaults; di->fname; di++) {
00837 if (di->cplusplus)
00838 continue;
00839 dirtmp = (struct file_name_list *)
00840 xmalloc (sizeof (struct file_name_list));
00841 dirtmp->next = 0;
00842 if (include == 0)
00843 include = dirtmp;
00844 else
00845 last_include->next = dirtmp;
00846 last_include = dirtmp;
00847 dirtmp->fname = di->fname;
00848 if (strlen (dirtmp->fname) > max_include_len)
00849 max_include_len = strlen (dirtmp->fname);
00850 }
00851
00852 if (ignore_srcdir && first_bracket_include == 0)
00853 first_bracket_include = old_last_include->next;
00854 }
00855
00856
00857
00858 outbuf.buf = (U_CHAR *) xmalloc (OUTBUF_SIZE);
00859 outbuf.bufp = outbuf.buf;
00860 outbuf.length = OUTBUF_SIZE;
00861
00862
00863
00864
00865
00866 no_output++;
00867 indepth++;
00868 for (i = 1; i < argc; i++)
00869 if (pend[i].type == PD_FILE)
00870 {
00871 int fd = open (pend[i].arg, O_RDONLY, 0666);
00872 if (fd < 0)
00873 {
00874 perror_with_name (pend[i].arg);
00875 return FATAL_EXIT_CODE;
00876 }
00877
00878
00879 if (print_deps)
00880 deps_add_dep (deps, pend[i].arg);
00881
00882 finclude (fd, pend[i].arg, 0, &outbuf);
00883 }
00884 indepth--;
00885 no_output--;
00886
00887
00888 free ((PTR) pend);
00889
00890
00891
00892
00893 fp = &instack[++indepth];
00894
00895
00896 if (in_fname == NULL || *in_fname == 0) {
00897 in_fname = "";
00898 f = 0;
00899 } else if ((f = open (in_fname, O_RDONLY, 0666)) < 0)
00900 goto sys_error;
00901
00902 if (file_size_and_mode (f, &st_mode, &st_size))
00903 goto sys_error;
00904 fp->fname = in_fname;
00905 fp->lineno = 1;
00906
00907 if (!S_ISREG (st_mode)) {
00908
00909
00910
00911 int size;
00912 int bsize;
00913 int cnt;
00914 U_CHAR *bufp;
00915
00916 bsize = 2000;
00917 size = 0;
00918 fp->buf = (U_CHAR *) xmalloc (bsize + 2);
00919 bufp = fp->buf;
00920 for (;;) {
00921 cnt = read (f, bufp, bsize - size);
00922 if (cnt < 0) goto sys_error;
00923 if (cnt == 0) break;
00924 size += cnt;
00925 bufp += cnt;
00926 if (bsize == size) {
00927 bsize *= 2;
00928 fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
00929 bufp = fp->buf + size;
00930 }
00931 }
00932 fp->length = size;
00933 } else {
00934
00935
00936 long i;
00937 fp->length = 0;
00938 fp->buf = (U_CHAR *) xmalloc (st_size + 2);
00939
00940 while (st_size > 0) {
00941 i = read (f, fp->buf + fp->length, st_size);
00942 if (i <= 0) {
00943 if (i == 0) break;
00944 goto sys_error;
00945 }
00946 fp->length += i;
00947 st_size -= i;
00948 }
00949 }
00950 fp->bufp = fp->buf;
00951 fp->if_stack = if_stack;
00952 fixup_newlines (fp);
00953
00954
00955
00956 if (fp->length > 0 && fp->buf[fp->length-1] != '\n')
00957 fp->buf[fp->length++] = '\n';
00958 fp->buf[fp->length] = '\0';
00959
00960
00961
00962 if (!out_fname || !strcmp (out_fname, ""))
00963 out_fname = "stdout";
00964 else if (! freopen (out_fname, "w", stdout))
00965 pfatal_with_name (out_fname);
00966
00967 output_line_command (fp, &outbuf, 0, same_file);
00968
00969
00970
00971 rescan (&outbuf, 0);
00972
00973
00974
00975
00976
00977 if (dump_macros)
00978 dump_all_macros ();
00979 else if (! inhibit_output)
00980 if (write (fileno (stdout), outbuf.buf, outbuf.bufp - outbuf.buf) < 0)
00981 fatal ("I/O error on output");
00982
00983
00984 if (print_deps && errors == 0)
00985 output_deps ();
00986
00987
00988 deps_free (deps);
00989
00990 if (ferror (stdout))
00991 fatal ("I/O error on output");
00992
00993 if (errors)
00994 exit (FATAL_EXIT_CODE);
00995 exit (SUCCESS_EXIT_CODE);
00996
00997 sys_error:
00998 pfatal_with_name (in_fname);
00999 }
01000
01001
01002 static void
01003 init_dependency_output ()
01004 {
01005 char *spec, *s, *output_file;
01006
01007
01008
01009
01010
01011
01012 if (print_deps == 0)
01013 {
01014 spec = getenv ("DEPENDENCIES_OUTPUT");
01015 if (spec)
01016 print_deps = 1;
01017 else
01018 {
01019 spec = getenv ("SUNPRO_DEPENDENCIES");
01020 if (spec)
01021 print_deps = 2;
01022 else
01023 return;
01024 }
01025
01026
01027 s = strchr (spec, ' ');
01028 if (s)
01029 {
01030
01031 deps_add_target (deps, s + 1, 0);
01032 output_file = (char *) xmalloc (s - spec + 1);
01033 memcpy (output_file, spec, s - spec);
01034 output_file[s - spec] = 0;
01035 }
01036 else
01037 output_file = spec;
01038
01039
01040 if (deps_file == 0)
01041 deps_file = output_file;
01042 deps_append = 1;
01043 }
01044
01045
01046
01047
01048
01049 if (deps_file == 0 || deps_missing_files)
01050 inhibit_output = 1;
01051 }
01052
01053
01054 static void
01055 output_deps ()
01056 {
01057
01058 FILE *deps_stream = 0;
01059 const char *const deps_mode = deps_append ? "a" : "w";
01060
01061 if (deps_file == 0)
01062 deps_stream = stdout;
01063 else
01064 {
01065 deps_stream = fopen (deps_file, deps_mode);
01066 if (deps_stream == 0)
01067 {
01068 error_from_errno (deps_file);
01069 return;
01070 }
01071 }
01072
01073 deps_write (deps, deps_stream, 72);
01074
01075 if (print_deps_phony_targets)
01076 deps_phony_targets (deps, deps_stream);
01077
01078
01079 if (deps_file)
01080 {
01081 if (ferror (deps_stream) || fclose (deps_stream) != 0)
01082 fatal ("I/O error on output");
01083 }
01084 }
01085
01086
01087
01088
01089
01090
01091
01092 static void
01093 newline_fix (bp)
01094 U_CHAR *bp;
01095 {
01096 U_CHAR *p = bp;
01097 int count = 0;
01098
01099
01100
01101 while (*p++ == '\\' && *p++ == '\n')
01102 count++;
01103
01104 p = bp + count * 2;
01105
01106
01107
01108 if (count == 0 || (*p != '/' && *p != '*'))
01109 return;
01110
01111
01112
01113
01114
01115 while (*p == '*' || *p == '/')
01116 *bp++ = *p++;
01117
01118
01119 while (count-- > 0) {
01120 *bp++ = '\\';
01121 *bp++ = '\n';
01122 }
01123 }
01124
01125
01126
01127 static void
01128 name_newline_fix (bp)
01129 U_CHAR *bp;
01130 {
01131 U_CHAR *p = bp;
01132 int count = 0;
01133
01134
01135
01136 while (*p++ == '\\' && *p++ == '\n')
01137 count++;
01138
01139 p = bp + count * 2;
01140
01141
01142
01143 if (count == 0 || !is_idchar (*p))
01144 return;
01145
01146
01147
01148
01149
01150 while (is_idchar (*p))
01151 *bp++ = *p++;
01152
01153
01154 while (count-- > 0) {
01155 *bp++ = '\\';
01156 *bp++ = '\n';
01157 }
01158 }
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196 static void
01197 rescan (op, output_marks)
01198 FILE_BUF *op;
01199 int output_marks;
01200 {
01201
01202 U_CHAR c;
01203
01204
01205 int ident_length = 0;
01206
01207
01208 int hash = 0;
01209
01210
01211 FILE_BUF *ip;
01212
01213
01214 U_CHAR *ibp;
01215
01216
01217 U_CHAR *limit;
01218
01219
01220 U_CHAR *obp;
01221
01222
01223
01224
01225
01226
01227
01228 int redo_char = 0;
01229
01230
01231
01232 int concatenated = 0;
01233
01234
01235
01236 int start_line;
01237
01238
01239 U_CHAR *beg_of_line;
01240
01241
01242 U_CHAR *obufp_before_macroname = NULL;
01243
01244
01245
01246 #define POPMACRO \
01247 do { ip->macro->type = T_MACRO; \
01248 if (ip->free_ptr) free (ip->free_ptr); \
01249 --indepth; } while (0)
01250
01251
01252
01253
01254 #define RECACHE \
01255 do { ip = &instack[indepth]; \
01256 ibp = ip->bufp; \
01257 limit = ip->buf + ip->length; \
01258 op->bufp = obp; \
01259 check_expand (op, limit - ibp); \
01260 beg_of_line = 0; \
01261 obufp_before_macroname += op->bufp - obp; \
01262 obp = op->bufp; } while (0)
01263
01264 if (no_output && instack[indepth].fname != 0)
01265 skip_if_group (&instack[indepth], 1);
01266
01267 obp = op->bufp;
01268 RECACHE;
01269 beg_of_line = ibp;
01270
01271
01272
01273 if (*limit != 0)
01274 abort ();
01275
01276 while (1) {
01277 c = *ibp++;
01278 *obp++ = c;
01279
01280 switch (c) {
01281 case '\\':
01282 if (ibp >= limit)
01283 break;
01284 if (*ibp == '\n') {
01285
01286
01287 ++ibp;
01288 ++ip->lineno;
01289 --obp;
01290 break;
01291 }
01292
01293
01294
01295 if (ident_length > 0)
01296 goto specialchar;
01297 *obp++ = *ibp++;
01298 break;
01299
01300 case '#':
01301
01302
01303 if (ip->macro != 0)
01304 goto randomchar;
01305 if (ident_length)
01306 goto specialchar;
01307
01308
01309 if (beg_of_line == 0)
01310 goto randomchar;
01311 if (beg_of_line + 1 != ibp)
01312 goto randomchar;
01313
01314
01315
01316 --obp;
01317
01318 ip->bufp = ibp;
01319 op->bufp = obp;
01320 if (! handle_directive (ip, op)) {
01321 #ifdef USE_C_ALLOCA
01322 alloca (0);
01323 #endif
01324
01325
01326 if (no_output && instack[indepth].fname) {
01327
01328
01329
01330 skip_if_group (&instack[indepth], 1);
01331 RECACHE;
01332 beg_of_line = ibp;
01333 break;
01334 }
01335 ++obp;
01336 goto randomchar;
01337 }
01338 #ifdef USE_C_ALLOCA
01339 alloca (0);
01340 #endif
01341
01342
01343
01344 if (no_output && instack[indepth].fname)
01345 skip_if_group (&instack[indepth], 1);
01346 obp = op->bufp;
01347 RECACHE;
01348 beg_of_line = ibp;
01349 break;
01350
01351 case '\"':
01352 case '\'':
01353
01354
01355
01356 if (ident_length)
01357 goto specialchar;
01358
01359 start_line = ip->lineno;
01360
01361
01362
01363 while (1) {
01364 if (ibp >= limit) {
01365 if (ip->macro != 0) {
01366
01367 POPMACRO;
01368 RECACHE;
01369 continue;
01370 }
01371 break;
01372 }
01373 *obp++ = *ibp;
01374 switch (*ibp++) {
01375 case '\n':
01376 ++ip->lineno;
01377 ++op->lineno;
01378
01379
01380 beg_of_line = ibp;
01381 goto while2end;
01382
01383 case '\\':
01384 if (ibp >= limit)
01385 break;
01386 if (*ibp == '\n') {
01387
01388
01389 --obp;
01390 ++ibp;
01391 ++ip->lineno;
01392 } else {
01393
01394
01395 while (*ibp == '\\' && ibp[1] == '\n') {
01396 ibp += 2;
01397 ++ip->lineno;
01398 }
01399 *obp++ = *ibp++;
01400 }
01401 break;
01402
01403 case '\"':
01404 case '\'':
01405 if (ibp[-1] == c)
01406 goto while2end;
01407 break;
01408 }
01409 }
01410 while2end:
01411 break;
01412
01413 case '/':
01414 if (*ibp == '\\' && ibp[1] == '\n')
01415 newline_fix (ibp);
01416
01417 if (ip->macro != 0)
01418 goto randomchar;
01419
01420
01421 if (ident_length)
01422 goto specialchar;
01423
01424 if (*ibp != '*')
01425 goto randomchar;
01426
01427
01428
01429 start_line = ip->lineno;
01430
01431 ++ibp;
01432
01433
01434
01435 if (! put_out_comments)
01436 obp--;
01437 else
01438 *obp++ = '*';
01439
01440 {
01441 U_CHAR *before_bp = ibp;
01442
01443 while (ibp < limit) {
01444 switch (*ibp++) {
01445 case '/':
01446 if (warn_comments && ibp < limit && *ibp == '*')
01447 warning("`/*' within comment");
01448 break;
01449 case '*':
01450 if (*ibp == '\\' && ibp[1] == '\n')
01451 newline_fix (ibp);
01452 if (ibp >= limit || *ibp == '/')
01453 goto comment_end;
01454 break;
01455 case '\n':
01456 ++ip->lineno;
01457
01458
01459
01460 if (!put_out_comments)
01461 *obp++ = '\n';
01462 ++op->lineno;
01463 }
01464 }
01465 comment_end:
01466
01467 if (ibp >= limit)
01468 error_with_line (line_for_error (start_line),
01469 "unterminated comment");
01470 else {
01471 ibp++;
01472 if (put_out_comments) {
01473 memcpy (obp, before_bp, ibp - before_bp);
01474 obp += ibp - before_bp;
01475 }
01476 }
01477 }
01478 break;
01479
01480 case '0': case '1': case '2': case '3': case '4':
01481 case '5': case '6': case '7': case '8': case '9':
01482
01483
01484
01485
01486
01487
01488 if (ident_length == 0) {
01489 while (ibp < limit) {
01490 while (ibp < limit && ibp[0] == '\\' && ibp[1] == '\n') {
01491 ++ip->lineno;
01492 ibp += 2;
01493 }
01494 c = *ibp++;
01495 if (! ISIDNUM (c) && c != '.') {
01496 --ibp;
01497 break;
01498 }
01499 *obp++ = c;
01500
01501
01502 if (c == 'e' || c == 'E') {
01503 while (ibp < limit && ibp[0] == '\\' && ibp[1] == '\n') {
01504 ++ip->lineno;
01505 ibp += 2;
01506 }
01507 if (ibp < limit && (*ibp == '+' || *ibp == '-')) {
01508 *obp++ = *ibp++;
01509
01510 break;
01511 }
01512 }
01513 }
01514 break;
01515 }
01516
01517
01518 case '_':
01519 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
01520 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
01521 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
01522 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
01523 case 'y': case 'z':
01524 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
01525 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
01526 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
01527 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
01528 case 'Y': case 'Z':
01529 ident_length++;
01530
01531 hash = HASHSTEP (hash, c);
01532 break;
01533
01534 case '\n':
01535
01536 if (ip->macro != 0) {
01537
01538
01539
01540
01541
01542
01543 if (*ibp == '-') {
01544
01545
01546
01547 if (! concatenated) {
01548 ident_length = 0;
01549 hash = 0;
01550 }
01551 ibp++;
01552 if (!output_marks) {
01553 obp--;
01554 } else {
01555
01556 *obp++ = '-';
01557 }
01558 } else if (is_space (*ibp)) {
01559
01560
01561 if (ident_length > 0)
01562 goto specialchar;
01563
01564
01565 if (!output_marks) {
01566 obp[-1] = *ibp++;
01567
01568 if (obp[-1] == '\n')
01569 op->lineno++;
01570 } else {
01571
01572
01573 *obp++ = *ibp++;
01574 }
01575 } else abort ();
01576 break;
01577 }
01578
01579
01580 if (ident_length > 0)
01581 goto specialchar;
01582
01583 beg_of_line = ibp;
01584
01585
01586 ++ip->lineno;
01587 ++op->lineno;
01588 if (ip->lineno != op->lineno) {
01589 op->bufp = obp;
01590 output_line_command (ip, op, 1, same_file);
01591 check_expand (op, ip->length - (ip->bufp - ip->buf));
01592 obp = op->bufp;
01593 }
01594 break;
01595
01596
01597
01598 case 0:
01599 if (ibp <= limit)
01600
01601 goto randomchar;
01602
01603
01604 if (ip->macro != 0) {
01605 obp--;
01606 ibp--;
01607
01608
01609 if (ident_length && ! is_idchar (*instack[indepth - 1].bufp)) {
01610 redo_char = 1;
01611 goto randomchar;
01612 }
01613 POPMACRO;
01614 RECACHE;
01615 break;
01616 }
01617
01618
01619
01620 if (ident_length == 0) {
01621 obp--;
01622 ibp--;
01623 op->bufp = obp;
01624 ip->bufp = ibp;
01625 goto ending;
01626 }
01627
01628
01629
01630
01631
01632
01633
01634 specialchar:
01635
01636
01637
01638
01639
01640
01641 ibp--;
01642 obp--;
01643 redo_char = 1;
01644
01645 default:
01646
01647 randomchar:
01648
01649 if (ident_length > 0) {
01650 HASHNODE *hp;
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668 for (hp = hashtab[MAKE_POS (hash) % HASHSIZE]; hp != NULL;
01669 hp = hp->next) {
01670
01671 if (hp->length == ident_length) {
01672
01673
01674 int op_lineno_before_macroname;
01675 int i = ident_length;
01676 U_CHAR *p = hp->name;
01677 U_CHAR *q = obp - i;
01678
01679 if (! redo_char)
01680 q--;
01681
01682 do {
01683 if (*p++ != *q++)
01684 goto hashcollision;
01685 } while (--i);
01686
01687
01688
01689
01690
01691 if (! redo_char) {
01692 ibp--;
01693 obp--;
01694 }
01695
01696 obufp_before_macroname = obp - ident_length;
01697 op_lineno_before_macroname = op->lineno;
01698
01699
01700
01701
01702
01703 if (hp->type == T_MACRO && hp->value.defn->nargs >= 0)
01704 {
01705 while (1) {
01706
01707 if (ibp == limit && ip->macro != 0) {
01708 POPMACRO;
01709 RECACHE;
01710 }
01711
01712 else if (*ibp == '/' && ibp+1 != limit && ibp[1] == '*') {
01713 if (put_out_comments) {
01714 *obp++ = '/';
01715 *obp++ = '*';
01716 }
01717 ibp += 2;
01718 while (ibp + 1 != limit
01719 && !(ibp[0] == '*' && ibp[1] == '/')) {
01720
01721
01722 if (*ibp == '\n') {
01723
01724 ++ip->lineno;
01725 ++op->lineno;
01726 }
01727 if (put_out_comments)
01728 *obp++ = *ibp++;
01729 else
01730 ibp++;
01731 }
01732 ibp += 2;
01733 if (put_out_comments) {
01734 *obp++ = '*';
01735 *obp++ = '/';
01736 }
01737 }
01738 else if (is_space (*ibp)) {
01739 *obp++ = *ibp++;
01740 if (ibp[-1] == '\n') {
01741 if (ip->macro == 0) {
01742
01743 ++ip->lineno;
01744 ++op->lineno;
01745 } else if (!output_marks) {
01746
01747
01748
01749
01750 obp--;
01751 if (*ibp == '-')
01752 ibp++;
01753 else {
01754 if (*ibp == '\n')
01755 ++op->lineno;
01756 *obp++ = *ibp++;
01757 }
01758 } else {
01759
01760 *obp++ = *ibp++;
01761 }
01762 }
01763 }
01764 else break;
01765 }
01766 if (*ibp != '(')
01767 break;
01768 }
01769
01770
01771
01772
01773 obp = obufp_before_macroname;
01774 op->lineno = op_lineno_before_macroname;
01775
01776
01777
01778 ip->bufp = ibp;
01779 op->bufp = obp;
01780 macroexpand (hp, op);
01781
01782
01783
01784 obp = op->bufp;
01785 RECACHE;
01786 break;
01787 }
01788 hashcollision:
01789 ;
01790 }
01791 ident_length = hash = 0;
01792 redo_char = 0;
01793 concatenated = 0;
01794 }
01795 }
01796 }
01797
01798
01799
01800 ending:
01801 if (if_stack != ip->if_stack) {
01802 const char *str;
01803 switch (if_stack->type) {
01804 case T_IF:
01805 str = "if";
01806 break;
01807 case T_IFDEF:
01808 str = "ifdef";
01809 break;
01810 case T_IFNDEF:
01811 str = "ifndef";
01812 break;
01813 case T_ELSE:
01814 str = "else";
01815 break;
01816 case T_ELIF:
01817 str = "elif";
01818 break;
01819 default:
01820 abort ();
01821 }
01822 error_with_line (line_for_error (if_stack->lineno),
01823 "unterminated #%s conditional", str);
01824 }
01825 if_stack = ip->if_stack;
01826 }
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837 static FILE_BUF
01838 expand_to_temp_buffer (buf, limit, output_marks)
01839 const U_CHAR *buf, *limit;
01840 int output_marks;
01841 {
01842 FILE_BUF *ip;
01843 FILE_BUF obuf;
01844 int length = limit - buf;
01845 U_CHAR *buf1;
01846 int odepth = indepth;
01847
01848 if (length < 0)
01849 abort ();
01850
01851
01852
01853 buf1 = (U_CHAR *) alloca (length + 1);
01854 {
01855 const U_CHAR *p1 = buf;
01856 U_CHAR *p2 = buf1;
01857
01858 while (p1 != limit)
01859 *p2++ = *p1++;
01860 }
01861 buf1[length] = 0;
01862
01863
01864
01865 obuf.length = length * 2 + 100;
01866 obuf.bufp = obuf.buf = (U_CHAR *) xmalloc (obuf.length);
01867 obuf.fname = 0;
01868 obuf.macro = 0;
01869 obuf.free_ptr = 0;
01870
01871 CHECK_DEPTH ({return obuf;});
01872
01873 ++indepth;
01874
01875 ip = &instack[indepth];
01876 ip->fname = 0;
01877 ip->macro = 0;
01878 ip->free_ptr = 0;
01879 ip->length = length;
01880 ip->buf = ip->bufp = buf1;
01881 ip->if_stack = if_stack;
01882
01883 ip->lineno = obuf.lineno = 1;
01884
01885
01886
01887 rescan (&obuf, output_marks);
01888
01889
01890 --indepth;
01891
01892 if (indepth != odepth)
01893 abort ();
01894
01895
01896 obuf.length = obuf.bufp - obuf.buf;
01897
01898 return obuf;
01899 }
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915 static int
01916 handle_directive (ip, op)
01917 FILE_BUF *ip, *op;
01918 {
01919 U_CHAR *bp, *cp;
01920 const struct directive *kt;
01921 int ident_length;
01922 U_CHAR *resume_p;
01923
01924
01925
01926 int copy_command = 0;
01927
01928 U_CHAR *ident, *after_ident;
01929
01930 bp = ip->bufp;
01931
01932 while (1) {
01933 if (is_nvspace (*bp))
01934 bp++;
01935 else if (*bp == '/' && (newline_fix (bp + 1), bp[1]) == '*') {
01936 ip->bufp = bp;
01937 skip_to_end_of_comment (ip, &ip->lineno);
01938 bp = ip->bufp;
01939 } else if (*bp == '\\' && bp[1] == '\n') {
01940 bp += 2; ip->lineno++;
01941 } else break;
01942 }
01943
01944
01945
01946
01947
01948 cp = bp;
01949 while (1) {
01950 if (is_idchar (*cp))
01951 cp++;
01952 else {
01953 if (*cp == '\\' && cp[1] == '\n')
01954 name_newline_fix (cp);
01955 if (is_idchar (*cp))
01956 cp++;
01957 else break;
01958 }
01959 }
01960 ident_length = cp - bp;
01961 ident = bp;
01962 after_ident = cp;
01963
01964
01965
01966 if (ident_length == 0 && *after_ident == '\n') {
01967 ip->bufp = after_ident;
01968 return 1;
01969 }
01970
01971
01972
01973
01974
01975 for (kt = directive_table; kt->length > 0; kt++) {
01976 if (kt->length == ident_length
01977 && !strncmp (kt->name, (const char *)ident, ident_length)) {
01978 U_CHAR *buf;
01979 U_CHAR *limit = ip->buf + ip->length;
01980 int unterminated = 0;
01981
01982
01983
01984 int keep_comments = kt->type == T_DEFINE;
01985
01986
01987
01988
01989
01990
01991 buf = bp = after_ident;
01992 while (bp < limit) {
01993 U_CHAR c = *bp++;
01994 switch (c) {
01995 case '\\':
01996 if (bp < limit) {
01997 if (*bp == '\n') {
01998 ip->lineno++;
01999 copy_command = 1;
02000 }
02001 bp++;
02002 }
02003 break;
02004
02005 case '\'':
02006 case '\"':
02007 bp = skip_quoted_string (bp - 1, limit, ip->lineno, &ip->lineno, ©_command, &unterminated);
02008 if (unterminated) {
02009
02010 ip->bufp = bp;
02011 goto endloop1;
02012 }
02013 break;
02014
02015
02016 case '<':
02017 if (kt->type != T_INCLUDE)
02018 break;
02019 while (*bp && *bp != '>') bp++;
02020 break;
02021
02022 case '/':
02023 if (*bp == '\\' && bp[1] == '\n')
02024 newline_fix (bp);
02025 if (*bp == '*') {
02026 U_CHAR *obp = bp - 1;
02027 ip->bufp = bp + 1;
02028 skip_to_end_of_comment (ip, &ip->lineno);
02029 bp = ip->bufp;
02030
02031
02032 if (bp == limit || *bp == '\n') {
02033 bp = obp;
02034 goto endloop1;
02035 }
02036
02037 if (! keep_comments)
02038 copy_command++;
02039 }
02040 break;
02041
02042 case '\n':
02043 --bp;
02044 ip->bufp = bp;
02045 goto endloop1;
02046 }
02047 }
02048 ip->bufp = bp;
02049
02050 endloop1:
02051 resume_p = ip->bufp;
02052
02053
02054
02055
02056 if (copy_command) {
02057 U_CHAR *xp = buf;
02058
02059
02060 cp = (U_CHAR *) alloca (bp - buf + 5);
02061
02062 buf = cp;
02063
02064
02065
02066
02067 while (xp < bp) {
02068 U_CHAR c = *xp++;
02069 *cp++ = c;
02070
02071 switch (c) {
02072 case '\n':
02073 break;
02074
02075
02076 case '<':
02077 if (kt->type != T_INCLUDE)
02078 break;
02079 while (xp < bp && c != '>') {
02080 c = *xp++;
02081 if (c == '\\' && xp < bp && *xp == '\n')
02082 xp++, ip->lineno++;
02083 else
02084 *cp++ = c;
02085 }
02086 break;
02087
02088 case '\\':
02089 if (*xp == '\n') {
02090 xp++;
02091 cp--;
02092 if (cp != buf && is_space (cp[-1])) {
02093 while (cp != buf && is_space(cp[-1])) cp--;
02094 cp++;
02095 SKIP_WHITE_SPACE (xp);
02096 } else if (is_nvspace (*xp)) {
02097 *cp++ = *xp++;
02098 SKIP_WHITE_SPACE (xp);
02099 }
02100 } else {
02101 *cp++ = *xp++;
02102 }
02103 break;
02104
02105 case '\'':
02106 case '\"':
02107 {
02108 const U_CHAR *bp1
02109 = skip_quoted_string (xp - 1, limit, ip->lineno, 0, 0, 0);
02110 while (xp != bp1)
02111 *cp++ = *xp++;
02112 }
02113 break;
02114
02115 case '/':
02116 if (*xp == '*') {
02117 ip->bufp = xp + 1;
02118 skip_to_end_of_comment (ip, 0);
02119 if (keep_comments)
02120 while (xp != ip->bufp)
02121 *cp++ = *xp++;
02122
02123 else
02124 cp--;
02125 xp = ip->bufp;
02126 }
02127 }
02128 }
02129
02130
02131
02132 *cp = 0;
02133 }
02134 else
02135 cp = bp;
02136
02137 ip->bufp = resume_p;
02138
02139
02140
02141
02142
02143
02144 (*kt->func) (buf, cp, op);
02145 check_expand (op, ip->length - (ip->bufp - ip->buf));
02146
02147 return 1;
02148 }
02149 }
02150
02151 return 0;
02152 }
02153
02154 static const char *const
02155 monthnames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
02156 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
02157
02158
02159
02160
02161
02162 static void
02163 special_symbol (hp, op)
02164 HASHNODE *hp;
02165 FILE_BUF *op;
02166 {
02167 const char *buf;
02168 time_t t;
02169 int i, len;
02170 int true_indepth;
02171 FILE_BUF *ip = NULL;
02172 static struct tm *timebuf = NULL;
02173
02174 int paren = 0;
02175
02176 for (i = indepth; i >= 0; i--)
02177 if (instack[i].fname != NULL) {
02178 ip = &instack[i];
02179 break;
02180 }
02181 if (ip == NULL)
02182 fatal ("not in any file?!");
02183
02184 switch (hp->type) {
02185 case T_FILE:
02186 case T_BASE_FILE:
02187 {
02188 const char *string;
02189 if (hp->type == T_FILE)
02190 string = ip->fname;
02191 else
02192 string = instack[0].fname;
02193
02194 if (string)
02195 {
02196 char *tmp = (char *) alloca (3 + strlen (string));
02197 sprintf (tmp, "\"%s\"", string);
02198 buf = tmp;
02199 }
02200 else
02201 buf = "";
02202
02203 break;
02204 }
02205
02206 case T_INCLUDE_LEVEL:
02207 {
02208 char *tmp = (char *) alloca (8);
02209 true_indepth = 0;
02210 for (i = indepth; i >= 0; i--)
02211 if (instack[i].fname != NULL)
02212 true_indepth++;
02213
02214 sprintf (tmp, "%d", true_indepth - 1);
02215 buf = tmp;
02216 break;
02217 }
02218
02219 case T_VERSION:
02220 {
02221 char *tmp = (char *) alloca (3 + strlen (version_string));
02222 sprintf (tmp, "\"%s\"", version_string);
02223 buf = tmp;
02224 break;
02225 }
02226
02227 case T_CONST:
02228 buf = hp->value.cpval;
02229 break;
02230
02231 case T_SPECLINE:
02232 {
02233 char *tmp = (char *) alloca (10);
02234 sprintf (tmp, "%d", ip->lineno);
02235 buf = tmp;
02236 break;
02237 }
02238
02239 case T_DATE:
02240 case T_TIME:
02241 {
02242 char *tmp = (char *) alloca (20);
02243
02244 if (timebuf == NULL) {
02245 t = time (0);
02246 timebuf = localtime (&t);
02247 }
02248 if (hp->type == T_DATE)
02249 sprintf (tmp, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon],
02250 timebuf->tm_mday, timebuf->tm_year + 1900);
02251 else
02252 sprintf (tmp, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,
02253 timebuf->tm_sec);
02254 buf = tmp;
02255 break;
02256 }
02257
02258 case T_SPEC_DEFINED:
02259 buf = " 0 ";
02260 ip = &instack[indepth];
02261 SKIP_WHITE_SPACE (ip->bufp);
02262 if (*ip->bufp == '(') {
02263 paren++;
02264 ip->bufp++;
02265 SKIP_WHITE_SPACE (ip->bufp);
02266 }
02267
02268 if (!is_idstart (*ip->bufp))
02269 goto oops;
02270 {
02271 HASHNODE *hp = lookup (ip->bufp, -1, -1);
02272
02273 if (hp && hp->type != T_UNUSED && hp->type != T_SPEC_DEFINED)
02274 buf = " 1 ";
02275 }
02276 while (is_idchar (*ip->bufp))
02277 ++ip->bufp;
02278 SKIP_WHITE_SPACE (ip->bufp);
02279 if (paren) {
02280 if (*ip->bufp != ')')
02281 goto oops;
02282 ++ip->bufp;
02283 }
02284 break;
02285
02286 oops:
02287
02288 error ("`defined' must be followed by ident or (ident)");
02289 break;
02290
02291 default:
02292 error ("cccp error: invalid special hash type");
02293 abort ();
02294 }
02295 len = strlen (buf);
02296 check_expand (op, len);
02297 memcpy (op->bufp, buf, len);
02298 op->bufp += len;
02299 }
02300
02301
02302
02303
02304
02305
02306
02307
02308 static void
02309 do_include (buf, limit, op)
02310 U_CHAR *buf, *limit;
02311 FILE_BUF *op;
02312 {
02313 U_CHAR *fbeg, *fend;
02314
02315 struct file_name_list *stackp = include;
02316 struct file_name_list dsp[1];
02317 int flen;
02318
02319 int retried = 0;
02320
02321 FILE_BUF trybuf;
02322 int system_header_p = 0;
02323
02324 get_filename:
02325
02326 fbeg = buf;
02327 SKIP_WHITE_SPACE (fbeg);
02328
02329
02330 while (limit != fbeg && is_nvspace (limit[-1])) limit--;
02331
02332 switch (*fbeg++) {
02333 case '\"':
02334 fend = fbeg;
02335 while (fend != limit && *fend != '\"')
02336 fend++;
02337 if (*fend == '\"' && fend + 1 == limit) {
02338 FILE_BUF *fp;
02339
02340
02341
02342
02343
02344 if (ignore_srcdir) break;
02345
02346 for (fp = &instack[indepth]; fp >= instack; fp--)
02347 {
02348 size_t n;
02349 const char *ep, *nam;
02350
02351 if ((nam = fp->fname) != NULL) {
02352
02353
02354 dsp[0].next = stackp;
02355 stackp = dsp;
02356 ep = strrchr (nam, '/');
02357 if (ep != NULL) {
02358 char *f;
02359 n = ep - nam;
02360 f = (char *) alloca (n + 1);
02361 strncpy (f, nam, n);
02362 f[n] = '\0';
02363 dsp[0].fname = f;
02364 if (n > max_include_len) max_include_len = n;
02365 } else {
02366 dsp[0].fname = 0;
02367 }
02368 break;
02369 }
02370 }
02371 break;
02372 }
02373 goto fail;
02374
02375 case '<':
02376 fend = fbeg;
02377 while (fend != limit && *fend != '>') fend++;
02378 if (*fend == '>' && fend + 1 == limit) {
02379 system_header_p = 1;
02380
02381 if (first_bracket_include)
02382 stackp = first_bracket_include;
02383 break;
02384 }
02385 goto fail;
02386
02387 default:
02388 fail:
02389 if (retried) {
02390 error ("#include expects \"fname\" or <fname>");
02391 return;
02392 } else {
02393 trybuf = expand_to_temp_buffer (buf, limit, 0);
02394 buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1);
02395 memcpy (buf, trybuf.buf, trybuf.bufp - trybuf.buf);
02396 limit = buf + (trybuf.bufp - trybuf.buf);
02397 free (trybuf.buf);
02398 retried++;
02399 goto get_filename;
02400 }
02401 }
02402
02403 flen = fend - fbeg;
02404 process_include (stackp, fbeg, flen, system_header_p, op);
02405 }
02406
02407 static void
02408 do_include_next (buf, limit, op)
02409 U_CHAR *buf, *limit;
02410 FILE_BUF *op;
02411 {
02412 U_CHAR *fbeg, *fend;
02413
02414 struct file_name_list *stackp;
02415 int flen;
02416
02417 int retried = 0;
02418
02419 FILE_BUF trybuf;
02420 int system_header_p = 0;
02421
02422
02423
02424 stackp = instack[indepth].next_header_dir;
02425 if (stackp == 0)
02426 {
02427 do_include (buf, limit, op);
02428 return;
02429 }
02430
02431 get_filename:
02432
02433 fbeg = buf;
02434 SKIP_WHITE_SPACE (fbeg);
02435
02436
02437 while (limit != fbeg && is_nvspace (limit[-1])) limit--;
02438
02439 switch (*fbeg++) {
02440 case '\"':
02441 fend = fbeg;
02442 while (fend != limit && *fend != '\"')
02443 fend++;
02444 if (*fend == '\"' && fend + 1 == limit)
02445 break;
02446 goto fail;
02447
02448 case '<':
02449 fend = fbeg;
02450 while (fend != limit && *fend != '>') fend++;
02451 if (*fend == '>' && fend + 1 == limit) {
02452 system_header_p = 1;
02453 break;
02454 }
02455 goto fail;
02456
02457 default:
02458 fail:
02459 if (retried) {
02460 error ("#include expects \"fname\" or <fname>");
02461 return;
02462 } else {
02463 trybuf = expand_to_temp_buffer (buf, limit, 0);
02464 buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1);
02465 memcpy (buf, trybuf.buf, trybuf.bufp - trybuf.buf);
02466 limit = buf + (trybuf.bufp - trybuf.buf);
02467 free (trybuf.buf);
02468 retried++;
02469 goto get_filename;
02470 }
02471 }
02472
02473 flen = fend - fbeg;
02474 process_include (stackp, fbeg, flen, system_header_p, op);
02475 }
02476
02477 static void
02478 process_include (stackp, fbeg, flen, system_header_p, op)
02479 struct file_name_list *stackp;
02480 const U_CHAR *fbeg;
02481 int flen;
02482 int system_header_p;
02483 FILE_BUF *op;
02484 {
02485 char *fname;
02486 int f = -1;
02487
02488 fname = (char *) alloca (max_include_len + flen + 2);
02489
02490
02491
02492
02493 if (IS_ABSOLUTE_PATHNAME (fbeg)) {
02494 strncpy (fname, (const char *)fbeg, flen);
02495 fname[flen] = 0;
02496 f = open (fname, O_RDONLY, 0666);
02497 } else {
02498
02499
02500
02501 for (; stackp; stackp = stackp->next) {
02502 if (stackp->fname) {
02503 strcpy (fname, stackp->fname);
02504 strcat (fname, "/");
02505 fname[strlen (fname) + flen] = 0;
02506 } else {
02507 fname[0] = 0;
02508 }
02509 strncat (fname, (const char *)fbeg, flen);
02510 if ((f = open (fname, O_RDONLY, 0666)) >= 0)
02511 break;
02512 }
02513 }
02514
02515 if (f < 0) {
02516 strncpy (fname, (const char *)fbeg, flen);
02517 fname[flen] = 0;
02518 if (deps_missing_files
02519 && print_deps > (system_header_p || (system_include_depth > 0))) {
02520
02521
02522
02523 if (first_bracket_include)
02524 stackp = first_bracket_include;
02525 else
02526 stackp = include;
02527
02528 if (!system_header_p || IS_ABSOLUTE_PATHNAME (fbeg) || !stackp->fname)
02529 deps_add_dep (deps, fname);
02530 else {
02531 char *p;
02532 int len = strlen(stackp->fname);
02533
02534 p = (char *) alloca (len + flen + 2);
02535 memcpy (p, stackp->fname, len);
02536 p[len++] = '/';
02537 memcpy (p + len, fbeg, flen);
02538 len += flen;
02539 p[len] = '\0';
02540 deps_add_dep (deps, p);
02541 }
02542 } else if (print_deps
02543 && print_deps <= (system_header_p
02544 || (system_include_depth > 0)))
02545 warning ("no include path in which to find %.*s", flen, fbeg);
02546 else
02547 error_from_errno (fname);
02548
02549 } else {
02550
02551
02552
02553
02554 struct file_name_list* ptr;
02555
02556 for (ptr = dont_repeat_files; ptr; ptr = ptr->next) {
02557 if (!strcmp (ptr->fname, fname)) {
02558 close (f);
02559 return;
02560 }
02561 }
02562
02563 for (ptr = all_include_files; ptr; ptr = ptr->next) {
02564 if (!strcmp (ptr->fname, fname))
02565 break;
02566 }
02567
02568 if (ptr == 0) {
02569
02570
02571
02572 ptr = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
02573 ptr->next = all_include_files;
02574 all_include_files = ptr;
02575 ptr->fname = xstrdup (fname);
02576
02577
02578 if (print_deps > (system_header_p || (system_include_depth > 0)))
02579 deps_add_dep (deps, fname);
02580 }
02581
02582 if (system_header_p)
02583 system_include_depth++;
02584
02585
02586 finclude (f, fname, stackp->next, op);
02587
02588 if (system_header_p)
02589 system_include_depth--;
02590
02591 close (f);
02592 }
02593 }
02594
02595
02596
02597 static void
02598 fixup_newlines (fp)
02599 FILE_BUF *fp;
02600 {
02601 U_CHAR *p, *q, *end;
02602
02603 if (fp->length <= 0)
02604 return;
02605
02606 end = fp->buf + fp->length;
02607 p = (U_CHAR *) memchr ((const char *) fp->buf, '\r', fp->length);
02608 if (p == NULL)
02609 return;
02610
02611 if (p > fp->buf && p[-1] == '\n')
02612 p--;
02613 q = p;
02614 while (p < end)
02615 switch (*p)
02616 {
02617 default:
02618 *q++ = *p++;
02619 break;
02620 case '\n':
02621 case '\r':
02622 p += 1 + (p[0] + p[1] == '\n' + '\r');
02623 *q++ = '\n';
02624 break;
02625 }
02626
02627 fp->length = q - fp->buf;
02628 }
02629
02630
02631
02632
02633 static void
02634 finclude (f, fname, nhd, op)
02635 int f;
02636 const char *fname;
02637 struct file_name_list *nhd;
02638 FILE_BUF *op;
02639 {
02640 int st_mode;
02641 long st_size;
02642 long i;
02643 FILE_BUF *fp;
02644
02645 CHECK_DEPTH (return;);
02646
02647 if (file_size_and_mode (f, &st_mode, &st_size))
02648 goto nope;
02649
02650 fp = &instack[indepth + 1];
02651 memset (fp, 0, sizeof (FILE_BUF));
02652 fp->fname = fname;
02653 fp->length = 0;
02654 fp->lineno = 1;
02655 fp->if_stack = if_stack;
02656 fp->next_header_dir = nhd;
02657
02658 if (S_ISREG (st_mode)) {
02659 fp->buf = (U_CHAR *) xmalloc (st_size + 2);
02660 fp->bufp = fp->buf;
02661
02662
02663
02664 while (st_size > 0) {
02665 i = read (f, fp->buf + fp->length, st_size);
02666 if (i <= 0) {
02667 if (i == 0) break;
02668 goto nope;
02669 }
02670 fp->length += i;
02671 st_size -= i;
02672 }
02673 }
02674 else {
02675
02676
02677 U_CHAR *bufp;
02678 U_CHAR *basep;
02679 int bsize = 2000;
02680
02681 st_size = 0;
02682 basep = (U_CHAR *) xmalloc (bsize + 2);
02683 bufp = basep;
02684
02685 for (;;) {
02686 i = read (f, bufp, bsize - st_size);
02687 if (i < 0)
02688 goto nope;
02689 if (i == 0)
02690 break;
02691 st_size += i;
02692 bufp += i;
02693 if (bsize == st_size) {
02694 bsize *= 2;
02695 basep = (U_CHAR *) xrealloc (basep, bsize + 2);
02696 bufp = basep + st_size;
02697 }
02698 }
02699 fp->buf = basep;
02700 fp->bufp = fp->buf;
02701 fp->length = st_size;
02702 }
02703 close (f);
02704 fixup_newlines (fp);
02705
02706
02707
02708 if (fp->length > 0 && fp->buf[fp->length-1] != '\n')
02709 fp->buf[fp->length++] = '\n';
02710 fp->buf[fp->length] = '\0';
02711
02712 indepth++;
02713 output_line_command (fp, op, 0, enter_file);
02714 rescan (op, 0);
02715 indepth--;
02716 instack[indepth].lineno++;
02717 instack[indepth].bufp++;
02718 output_line_command (&instack[indepth], op, 0, leave_file);
02719 free (fp->buf);
02720 return;
02721
02722 nope:
02723 perror_with_name (fname);
02724 close (f);
02725 }
02726
02727
02728
02729
02730
02731
02732
02733 static void
02734 do_define (buf, limit, op)
02735 U_CHAR *buf, *limit;
02736 FILE_BUF *op ATTRIBUTE_UNUSED;
02737 {
02738 U_CHAR *bp;
02739 U_CHAR *symname;
02740 int sym_length;
02741
02742 DEFINITION *defn;
02743 int arglengths = 0;
02744
02745 int hashcode;
02746
02747 bp = buf;
02748
02749 while (is_nvspace (*bp))
02750 bp++;
02751
02752 symname = bp;
02753 while (is_idchar (*bp) && bp < limit) {
02754 bp++;
02755 }
02756 sym_length = bp - symname;
02757 if (sym_length == 0)
02758 {
02759 error ("invalid macro name");
02760 return;
02761 }
02762 else if (!is_idstart (*symname)) {
02763 U_CHAR *msg;
02764 msg = (U_CHAR *) alloca (sym_length + 1);
02765 memcpy (msg, symname, sym_length);
02766 msg[sym_length] = 0;
02767 error ("invalid macro name `%s'", msg);
02768 return;
02769 } else {
02770 if (! strncmp ((const char *)symname, "defined", 7) && sym_length == 7)
02771 {
02772 error ("\"defined\" cannot be used as a macro name");
02773 return;
02774 }
02775 }
02776
02777
02778
02779
02780
02781 if (*bp == '(') {
02782 struct arglist *arg_ptrs = NULL;
02783 int argno = 0;
02784
02785 bp++;
02786 SKIP_WHITE_SPACE (bp);
02787
02788
02789 while (*bp != ')') {
02790 struct arglist *temp;
02791
02792 temp = (struct arglist *) alloca (sizeof (struct arglist));
02793 temp->name = bp;
02794 temp->next = arg_ptrs;
02795 temp->argno = argno++;
02796 arg_ptrs = temp;
02797
02798 if (!is_idstart (*bp))
02799 warning ("parameter name starts with a digit in #define");
02800
02801
02802 while (is_idchar (*bp)) {
02803 bp++;
02804 }
02805 temp->length = bp - temp->name;
02806 arglengths += temp->length + 2;
02807 SKIP_WHITE_SPACE (bp);
02808 if (temp->length == 0 || (*bp != ',' && *bp != ')')) {
02809 error ("badly punctuated parameter list in #define");
02810 return;
02811 }
02812 if (*bp == ',') {
02813 bp++;
02814 SKIP_WHITE_SPACE (bp);
02815 }
02816 if (bp >= limit) {
02817 error ("unterminated parameter list in #define");
02818 return;
02819 }
02820 }
02821
02822 ++bp;
02823 while (is_nvspace (*bp) && bp < limit)
02824 ++bp;
02825
02826 defn = collect_expansion (bp, limit, argno, arg_ptrs);
02827
02828
02829
02830
02831 {
02832 struct arglist *temp;
02833 int i = 0;
02834 U_CHAR *tmp = (U_CHAR *) xmalloc (arglengths + 1);
02835
02836 for (temp = arg_ptrs; temp; temp = temp->next) {
02837 memcpy (&tmp[i], temp->name, temp->length);
02838 i += temp->length;
02839 if (temp->next != 0) {
02840 tmp[i++] = ',';
02841 tmp[i++] = ' ';
02842 }
02843 }
02844 tmp[i] = 0;
02845 defn->argnames = tmp;
02846
02847 }
02848 } else {
02849
02850 while (is_nvspace (*bp) && bp < limit)
02851 ++bp;
02852
02853 defn = collect_expansion (bp, limit, -1, 0);
02854 defn->argnames = (const U_CHAR *) "";
02855 }
02856
02857 hashcode = hashf (symname, sym_length, HASHSIZE);
02858
02859 {
02860 HASHNODE *hp;
02861 if ((hp = lookup (symname, sym_length, hashcode)) == NULL)
02862 hp = install (symname, sym_length, T_MACRO, hashcode);
02863 else {
02864 if (hp->type != T_MACRO || compare_defs (defn, hp->value.defn))
02865 warning ("\"%.*s\" redefined", sym_length, symname);
02866
02867
02868 hp->type = T_MACRO;
02869 }
02870
02871 hp->value.defn = defn;
02872 }
02873 }
02874
02875
02876
02877
02878 static int
02879 compare_defs (d1, d2)
02880 DEFINITION *d1, *d2;
02881 {
02882 struct reflist *a1, *a2;
02883 U_CHAR *p1 = d1->expansion;
02884 U_CHAR *p2 = d2->expansion;
02885 int first = 1;
02886
02887 if (d1->nargs != d2->nargs)
02888 return 1;
02889 if (strcmp ((const char *)d1->argnames, (const char *)d2->argnames))
02890 return 1;
02891 for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
02892 a1 = a1->next, a2 = a2->next) {
02893 if (!((a1->nchars == a2->nchars
02894 && ! strncmp ((const char *)p1, (const char *)p2, a1->nchars))
02895 || ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
02896 || a1->argno != a2->argno
02897 || a1->stringify != a2->stringify
02898 || a1->raw_before != a2->raw_before
02899 || a1->raw_after != a2->raw_after)
02900 return 1;
02901 first = 0;
02902 p1 += a1->nchars;
02903 p2 += a2->nchars;
02904 }
02905 if (a1 != a2)
02906 return 1;
02907 if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
02908 p2, d2->length - (p2 - d2->expansion), 1))
02909 return 1;
02910 return 0;
02911 }
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921 static int
02922 comp_def_part (first, beg1, len1, beg2, len2, last)
02923 int first;
02924 const U_CHAR *beg1, *beg2;
02925 int len1, len2;
02926 int last;
02927 {
02928 const U_CHAR *end1 = beg1 + len1;
02929 const U_CHAR *end2 = beg2 + len2;
02930 if (first) {
02931 while (beg1 != end1 && is_space (*beg1)) beg1++;
02932 while (beg2 != end2 && is_space (*beg2)) beg2++;
02933 }
02934 if (last) {
02935 while (beg1 != end1 && is_space (end1[-1])) end1--;
02936 while (beg2 != end2 && is_space (end2[-1])) end2--;
02937 }
02938 while (beg1 != end1 && beg2 != end2) {
02939 if (is_space (*beg1) && is_space (*beg2)) {
02940 while (beg1 != end1 && is_space (*beg1)) beg1++;
02941 while (beg2 != end2 && is_space (*beg2)) beg2++;
02942 } else if (*beg1 == *beg2) {
02943 beg1++; beg2++;
02944 } else break;
02945 }
02946 return (beg1 != end1) || (beg2 != end2);
02947 }
02948
02949
02950
02951
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966
02967
02968
02969
02970 static DEFINITION *
02971 collect_expansion (buf, end, nargs, arglist)
02972 U_CHAR *buf, *end;
02973 int nargs;
02974 struct arglist *arglist;
02975 {
02976 DEFINITION *defn;
02977 U_CHAR *p, *limit, *lastp, *exp_p;
02978 struct reflist *endpat = NULL;
02979
02980 U_CHAR *concat = 0;
02981
02982 U_CHAR *stringify = 0;
02983 int maxsize;
02984 int expected_delimiter = '\0';
02985
02986
02987
02988
02989
02990
02991 if (end < buf)
02992 abort ();
02993
02994
02995
02996 limit = end;
02997 p = buf;
02998 while (p < limit && is_space (limit[-1])) limit--;
02999 while (p < limit && is_space (*p)) p++;
03000
03001
03002
03003
03004
03005
03006 maxsize = (sizeof (DEFINITION)
03007 + 2 * (end - limit) + 2 * (p - buf)
03008 + (limit - p) + 3);
03009 defn = (DEFINITION *) xcalloc (1, maxsize);
03010
03011 defn->nargs = nargs;
03012 exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION);
03013 lastp = exp_p;
03014
03015 p = buf;
03016
03017
03018 while (p < limit && is_space (*p)) {
03019 *exp_p++ = '\n';
03020 *exp_p++ = *p++;
03021 }
03022
03023
03024 while (p < limit) {
03025 int skipped_arg = 0;
03026 U_CHAR c = *p++;
03027
03028 *exp_p++ = c;
03029
03030
03031
03032
03033
03034 switch (c) {
03035 case '\'':
03036 case '\"':
03037 if (expected_delimiter != '\0') {
03038 if (c == expected_delimiter)
03039 expected_delimiter = '\0';
03040 } else
03041 expected_delimiter = c;
03042 break;
03043
03044 case '\\':
03045
03046 if (expected_delimiter != 0 && p < limit
03047 && (*p == expected_delimiter || *p == '\\')) {
03048 *exp_p++ = *p++;
03049 continue;
03050 }
03051 break;
03052
03053 case '/':
03054 if (expected_delimiter != '\0')
03055 break;
03056 if (*p == '*') {
03057
03058
03059
03060 exp_p--;
03061 p += 1;
03062 while (p < limit && !(p[-2] == '*' && p[-1] == '/'))
03063 p++;
03064 }
03065 break;
03066 }
03067
03068 if (is_idchar (c) && nargs > 0) {
03069 U_CHAR *id_beg = p - 1;
03070 int id_len;
03071
03072 --exp_p;
03073 while (p != limit && is_idchar (*p)) p++;
03074 id_len = p - id_beg;
03075
03076 if (is_idstart (c)) {
03077 struct arglist *arg;
03078
03079 for (arg = arglist; arg != NULL; arg = arg->next) {
03080 struct reflist *tpat;
03081
03082 if (arg->name[0] == c
03083 && arg->length == id_len
03084 && strncmp ((const char *)arg->name,
03085 (const char *)id_beg, id_len) == 0) {
03086
03087
03088 tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
03089 tpat->next = NULL;
03090 tpat->raw_before = concat == id_beg;
03091 tpat->raw_after = 0;
03092 tpat->stringify = expected_delimiter != '\0';
03093
03094 if (endpat == NULL)
03095 defn->pattern = tpat;
03096 else
03097 endpat->next = tpat;
03098 endpat = tpat;
03099
03100 tpat->argno = arg->argno;
03101 tpat->nchars = exp_p - lastp;
03102 {
03103 U_CHAR *p1 = p;
03104 SKIP_WHITE_SPACE (p1);
03105 if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')
03106 tpat->raw_after = 1;
03107 }
03108 lastp = exp_p;
03109 skipped_arg = 1;
03110 break;
03111 }
03112 }
03113 }
03114
03115
03116 if (! skipped_arg) {
03117 U_CHAR *lim1 = p;
03118 p = id_beg;
03119 while (p != lim1)
03120 *exp_p++ = *p++;
03121 if (stringify == id_beg)
03122 error ("# operator should be followed by a macro argument name");
03123 }
03124 }
03125 }
03126
03127 if (limit < end) {
03128
03129 while (limit < end && is_space (*limit)) {
03130 *exp_p++ = '\n';
03131 *exp_p++ = *limit++;
03132 }
03133 }
03134 *exp_p = '\0';
03135
03136 defn->length = exp_p - defn->expansion;
03137
03138
03139 if (defn->length + 1 > maxsize)
03140 abort ();
03141
03142 return defn;
03143 }
03144
03145
03146
03147
03148
03149 #define FNAME_HASHSIZE 37
03150 static void
03151 do_line (buf, limit, op)
03152 U_CHAR *buf, *limit;
03153 FILE_BUF *op;
03154 {
03155 U_CHAR *bp;
03156 FILE_BUF *ip = &instack[indepth];
03157 FILE_BUF tem;
03158 int new_lineno;
03159 enum file_change_code file_change = same_file;
03160
03161
03162 tem = expand_to_temp_buffer (buf, limit, 0);
03163
03164
03165 bp = tem.buf;
03166 SKIP_WHITE_SPACE (bp);
03167
03168 if (!ISDIGIT (*bp)) {
03169 error ("invalid format #line command");
03170 return;
03171 }
03172
03173
03174
03175
03176 new_lineno = atoi ((const char *)bp);
03177
03178
03179 while (ISDIGIT (*bp))
03180 bp++;
03181
03182 SKIP_WHITE_SPACE (bp);
03183
03184 if (*bp == '\"') {
03185 static HASHNODE *fname_table[FNAME_HASHSIZE];
03186 HASHNODE *hp, **hash_bucket;
03187 U_CHAR *fname;
03188 int fname_length;
03189
03190 fname = ++bp;
03191
03192 while (*bp && *bp != '\"')
03193 bp++;
03194 if (*bp != '\"') {
03195 error ("invalid format #line command");
03196 return;
03197 }
03198
03199 fname_length = bp - fname;
03200
03201 bp++;
03202 SKIP_WHITE_SPACE (bp);
03203 if (*bp) {
03204 if (*bp == '1')
03205 file_change = enter_file;
03206 else if (*bp == '2')
03207 file_change = leave_file;
03208 else {
03209 error ("invalid format #line command");
03210 return;
03211 }
03212
03213 bp++;
03214 SKIP_WHITE_SPACE (bp);
03215 if (*bp) {
03216 error ("invalid format #line command");
03217 return;
03218 }
03219 }
03220
03221 hash_bucket =
03222 &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
03223 for (hp = *hash_bucket; hp != NULL; hp = hp->next)
03224 if (hp->length == fname_length &&
03225 strncmp (hp->value.cpval, (const char *)fname, fname_length) == 0) {
03226 ip->fname = hp->value.cpval;
03227 break;
03228 }
03229 if (hp == 0) {
03230 char *q;
03231
03232 hp = (HASHNODE *) xcalloc (1, sizeof (HASHNODE) + fname_length + 1);
03233 hp->next = *hash_bucket;
03234 *hash_bucket = hp;
03235
03236 hp->length = fname_length;
03237 ip->fname = hp->value.cpval = q = ((char *) hp) + sizeof (HASHNODE);
03238 memcpy (q, fname, fname_length);
03239 }
03240 } else if (*bp) {
03241 error ("invalid format #line command");
03242 return;
03243 }
03244
03245 ip->lineno = new_lineno;
03246 output_line_command (ip, op, 0, file_change);
03247 ip->bufp++;
03248 check_expand (op, ip->length - (ip->bufp - ip->buf));
03249 }
03250
03251
03252
03253
03254
03255
03256 static void
03257 do_undef (buf, limit, op)
03258 U_CHAR *buf;
03259 U_CHAR *limit ATTRIBUTE_UNUSED;
03260 FILE_BUF *op ATTRIBUTE_UNUSED;
03261 {
03262 HASHNODE *hp;
03263
03264 SKIP_WHITE_SPACE (buf);
03265
03266 if (! strncmp ((const char *)buf, "defined", 7) && ! is_idchar (buf[7]))
03267 warning ("undefining `defined'");
03268
03269 while ((hp = lookup (buf, -1, -1)) != NULL) {
03270 if (hp->type != T_MACRO)
03271 warning ("undefining `%s'", hp->name);
03272 delete_macro (hp);
03273 }
03274 }
03275
03276
03277
03278
03279
03280 static int
03281 parse_answer (buf, limit, answerp, type)
03282 const unsigned char *buf, *limit;
03283 struct answer **answerp;
03284 int type;
03285 {
03286 const unsigned char *start;
03287
03288
03289 if (buf < limit && *buf == ' ')
03290 buf++;
03291
03292
03293 if (buf == limit && type == T_UNASSERT)
03294 return 0;
03295
03296 if (buf == limit || *buf++ != '(')
03297 {
03298 if (type == T_IF)
03299 return 0;
03300
03301 error ("missing '(' after predicate");
03302 return 1;
03303 }
03304
03305
03306 while (buf < limit && *buf == ' ')
03307 buf++;
03308
03309 start = buf;
03310 while (buf < limit && *buf != ')')
03311 buf++;
03312
03313 if (buf == limit)
03314 {
03315 error ("missing ')' to complete answer");
03316 return 1;
03317 }
03318
03319 if (buf == start)
03320 {
03321 error ("predicate's answer is empty");
03322 return 1;
03323 }
03324
03325 if ((type == T_ASSERT || type == T_UNASSERT) && buf + 1 != limit)
03326 {
03327 error ("extra text at end of directive");
03328 return 1;
03329 }
03330
03331
03332 if (buf[-1] == ' ')
03333 buf--;
03334
03335 *answerp = (struct answer *) xmalloc (sizeof (struct answer));
03336 (*answerp)->answer = start;
03337 (*answerp)->len = buf - start;
03338
03339 return 0;
03340 }
03341
03342
03343
03344
03345 static HASHNODE *
03346 parse_assertion (buf, limit, answerp, type)
03347 const unsigned char *buf, *limit;
03348 struct answer **answerp;
03349 int type;
03350 {
03351 HASHNODE *result = 0;
03352 const unsigned char *climit;
03353 unsigned char *bp, *symname = canonicalize_text (buf, limit, &climit);
03354 unsigned int len;
03355
03356 bp = symname;
03357 if (bp < climit && is_idstart (*bp))
03358 {
03359 do
03360 bp++;
03361 while (bp < climit && is_idchar (*bp));
03362 }
03363 len = bp - symname;
03364
03365 *answerp = 0;
03366 if (len == 0)
03367 {
03368 if (symname == climit)
03369 error ("assertion without predicate");
03370 else
03371 error ("predicate must be an identifier");
03372 }
03373
03374
03375 else if (parse_answer (bp, climit, answerp, type) == 0)
03376 {
03377 unsigned char *sym = alloca (len + 1);
03378 int hashcode;
03379
03380
03381 sym[0] = '#';
03382 memcpy (sym + 1, symname, len);
03383
03384 hashcode = hashf (sym, len + 1, HASHSIZE);
03385 result = lookup (sym, len + 1, hashcode);
03386 if (result == 0)
03387 result = install (sym, len + 1, T_UNUSED, hashcode);
03388 }
03389
03390 return result;
03391 }
03392
03393
03394
03395 int
03396 test_assertion (pbuf)
03397 unsigned char **pbuf;
03398 {
03399 unsigned char *buf = *pbuf;
03400 unsigned char *limit = buf + strlen ((char *) buf);
03401 struct answer *answer;
03402 HASHNODE *node;
03403 int result = 0;
03404
03405 node = parse_assertion (buf, limit, &answer, T_IF);
03406 if (node)
03407 {
03408 result = (node->type == T_ASSERT &&
03409 (answer == 0 || *find_answer (node, answer) != 0));
03410
03411
03412
03413 if (is_space (*buf))
03414 buf++;
03415 while (is_idchar (*buf))
03416 buf++;
03417
03418 if (answer)
03419 while (*buf++ != ')')
03420 ;
03421 *pbuf = buf;
03422 }
03423
03424 return result;
03425 }
03426
03427
03428 static void
03429 do_error (buf, limit, op)
03430 U_CHAR *buf;
03431 U_CHAR *limit;
03432 FILE_BUF *op ATTRIBUTE_UNUSED;
03433 {
03434 error ("#error%.*s", (int) (limit - buf), buf);
03435 }
03436
03437
03438 static void
03439 do_warning (buf, limit, op)
03440 U_CHAR *buf;
03441 U_CHAR *limit;
03442 FILE_BUF *op ATTRIBUTE_UNUSED;
03443 {
03444 warning ("#warning%.*s", (int) (limit - buf), buf);
03445 }
03446
03447
03448 static void
03449 do_assert (buf, limit, op)
03450 U_CHAR *buf;
03451 U_CHAR *limit;
03452 FILE_BUF *op ATTRIBUTE_UNUSED;
03453 {
03454 struct answer *new_answer;
03455 HASHNODE *node;
03456
03457 node = parse_assertion (buf, limit, &new_answer, T_ASSERT);
03458 if (node)
03459 {
03460
03461
03462 new_answer->next = 0;
03463 if (node->type == T_ASSERT)
03464 {
03465 if (*find_answer (node, new_answer))
03466 {
03467 free (new_answer);
03468 warning ("\"%s\" re-asserted", node->name + 1);
03469 return;
03470 }
03471 new_answer->next = node->value.answers;
03472 }
03473 node->type = T_ASSERT;
03474 node->value.answers = new_answer;
03475 }
03476 }
03477
03478
03479 static void
03480 do_unassert (buf, limit, op)
03481 U_CHAR *buf;
03482 U_CHAR *limit;
03483 FILE_BUF *op ATTRIBUTE_UNUSED;
03484 {
03485 HASHNODE *node;
03486 struct answer *answer;
03487
03488 node = parse_assertion (buf, limit, &answer, T_UNASSERT);
03489
03490 if (node)
03491 {
03492 if (node->type == T_ASSERT)
03493 {
03494 if (answer)
03495 {
03496 struct answer **p = find_answer (node, answer), *temp;
03497
03498
03499 temp = *p;
03500 if (temp)
03501 *p = temp->next;
03502
03503
03504 if (node->value.answers == 0)
03505 delete_macro (node);
03506 }
03507 else
03508 delete_macro (node);
03509 }
03510
03511 free (answer);
03512 }
03513 }
03514
03515
03516
03517 static struct answer **
03518 find_answer (node, candidate)
03519 HASHNODE *node;
03520 const struct answer *candidate;
03521 {
03522 struct answer **result;
03523
03524 for (result = &node->value.answers; *result; result = &(*result)->next)
03525 {
03526 struct answer *answer = *result;
03527
03528 if (answer->len == candidate->len
03529 && !memcmp (answer->answer, candidate->answer, answer->len))
03530 break;
03531 }
03532
03533 return result;
03534 }
03535
03536
03537
03538
03539 static unsigned char *
03540 canonicalize_text (buf, limit, climit)
03541 const unsigned char *buf, *limit, **climit;
03542 {
03543 unsigned int len = limit - buf;
03544 unsigned char *result = (unsigned char *) xmalloc (len), *dest;
03545
03546 for (dest = result; buf < limit;)
03547 {
03548 if (! is_space (*buf))
03549 *dest++ = *buf++;
03550 else
03551 {
03552 while (++buf < limit && is_space (*buf))
03553 ;
03554 if (dest != result && buf != limit)
03555 *dest++ = ' ';
03556 }
03557 }
03558
03559 *climit = dest;
03560 return result;
03561 }
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572
03573
03574
03575 static void
03576 do_if (buf, limit, op)
03577 U_CHAR *buf, *limit;
03578 FILE_BUF *op ATTRIBUTE_UNUSED;
03579 {
03580 int value;
03581 FILE_BUF *ip = &instack[indepth];
03582
03583 value = eval_if_expression (buf, limit - buf);
03584 conditional_skip (ip, value == 0, T_IF);
03585 }
03586
03587
03588
03589
03590
03591 static void
03592 do_elif (buf, limit, op)
03593 U_CHAR *buf, *limit;
03594 FILE_BUF *op;
03595 {
03596 int value;
03597 FILE_BUF *ip = &instack[indepth];
03598
03599 if (if_stack == instack[indepth].if_stack) {
03600 error ("#elif not within a conditional");
03601 return;
03602 } else {
03603 if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
03604 error ("#elif after #else");
03605 fprintf (stderr, " (matches line %d", if_stack->lineno);
03606 if (if_stack->fname != NULL && ip->fname != NULL &&
03607 strcmp (if_stack->fname, ip->fname) != 0)
03608 fprintf (stderr, ", file %s", if_stack->fname);
03609 fprintf (stderr, ")\n");
03610 }
03611 if_stack->type = T_ELIF;
03612 }
03613
03614 if (if_stack->if_succeeded)
03615 skip_if_group (ip, 0);
03616 else {
03617 value = eval_if_expression (buf, limit - buf);
03618 if (value == 0)
03619 skip_if_group (ip, 0);
03620 else {
03621 ++if_stack->if_succeeded;
03622 output_line_command (ip, op, 1, same_file);
03623 }
03624 }
03625 }
03626
03627
03628
03629
03630
03631 static int
03632 eval_if_expression (buf, length)
03633 const U_CHAR *buf;
03634 int length;
03635 {
03636 FILE_BUF temp_obuf;
03637 HASHNODE *save_defined;
03638 int value;
03639
03640 save_defined = install (U"defined", -1, T_SPEC_DEFINED, -1);
03641 temp_obuf = expand_to_temp_buffer (buf, buf + length, 0);
03642 delete_macro (save_defined);
03643
03644 value = parse_c_expression ((const char *)temp_obuf.buf);
03645
03646 free (temp_obuf.buf);
03647
03648 return value;
03649 }
03650
03651
03652
03653
03654
03655
03656 static void
03657 do_xifdef (buf, limit, type)
03658 U_CHAR *buf, *limit;
03659 enum node_type type;
03660 {
03661 int skip;
03662 FILE_BUF *ip = &instack[indepth];
03663 U_CHAR *end;
03664
03665
03666 SKIP_WHITE_SPACE (buf);
03667 while (limit != buf && is_nvspace (limit[-1])) limit--;
03668
03669
03670 for (end = buf; is_idchar (*end); end++);
03671
03672 if (end == buf)
03673 skip = (type == T_IFDEF);
03674 else
03675 skip = (lookup (buf, end-buf, -1) == NULL) ^ (type == T_IFNDEF);
03676
03677 conditional_skip (ip, skip, T_IF);
03678 }
03679
03680 static void
03681 do_ifdef (buf, limit, op)
03682 U_CHAR *buf, *limit;
03683 FILE_BUF *op ATTRIBUTE_UNUSED;
03684 {
03685 do_xifdef (buf, limit, T_IFDEF);
03686 }
03687
03688 static void
03689 do_ifndef (buf, limit, op)
03690 U_CHAR *buf, *limit;
03691 FILE_BUF *op ATTRIBUTE_UNUSED;
03692 {
03693 do_xifdef (buf, limit, T_IFNDEF);
03694 }
03695
03696
03697
03698
03699 static void
03700 conditional_skip (ip, skip, type)
03701 FILE_BUF *ip;
03702 int skip;
03703 enum node_type type;
03704 {
03705 IF_STACK_FRAME *temp;
03706
03707 temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
03708 temp->fname = ip->fname;
03709 temp->lineno = ip->lineno;
03710 temp->next = if_stack;
03711 if_stack = temp;
03712
03713 if_stack->type = type;
03714
03715 if (skip != 0) {
03716 skip_if_group (ip, 0);
03717 return;
03718 } else {
03719 ++if_stack->if_succeeded;
03720 output_line_command (ip, &outbuf, 1, same_file);
03721 }
03722 }
03723
03724
03725
03726
03727
03728
03729 static void
03730 skip_if_group (ip, any)
03731 FILE_BUF *ip;
03732 int any;
03733 {
03734 U_CHAR *bp = ip->bufp, *cp;
03735 U_CHAR *endb = ip->buf + ip->length;
03736 const struct directive *kt;
03737 IF_STACK_FRAME *save_if_stack = if_stack;
03738 U_CHAR *beg_of_line = bp;
03739
03740 while (bp < endb) {
03741 switch (*bp++) {
03742 case '/':
03743 if (*bp == '\\' && bp[1] == '\n')
03744 newline_fix (bp);
03745 if (*bp == '*') {
03746 ip->bufp = ++bp;
03747 bp = skip_to_end_of_comment (ip, &ip->lineno);
03748 }
03749 break;
03750 case '\"':
03751 case '\'':
03752 bp = skip_quoted_string (bp - 1, endb, ip->lineno, &ip->lineno, 0, 0);
03753 break;
03754 case '\\':
03755
03756 if (bp < endb) {
03757 if (*bp == '\n')
03758 ++ip->lineno;
03759 bp++;
03760 }
03761 break;
03762 case '\n':
03763 ++ip->lineno;
03764 beg_of_line = bp;
03765 break;
03766 case '#':
03767 ip->bufp = bp - 1;
03768
03769
03770 if (beg_of_line == 0)
03771 break;
03772
03773
03774
03775 bp = beg_of_line;
03776 while (1) {
03777 if (is_nvspace (*bp))
03778 bp++;
03779 else if (*bp == '\\' && bp[1] == '\n')
03780 bp += 2;
03781 else if (*bp == '/' && bp[1] == '*') {
03782 bp += 2;
03783 while (!(*bp == '*' && bp[1] == '/')) {
03784 if (*bp == '\n')
03785 ip->lineno++;
03786 bp++;
03787 }
03788 bp += 2;
03789 }
03790 else break;
03791 }
03792 if (bp != ip->bufp) {
03793 bp = ip->bufp + 1;
03794 break;
03795 }
03796
03797 bp = ip->bufp + 1;
03798
03799
03800 while (1) {
03801 if (is_nvspace (*bp))
03802 bp++;
03803 else if (*bp == '\\' && bp[1] == '\n')
03804 bp += 2;
03805 else if (*bp == '/' && bp[1] == '*') {
03806 bp += 2;
03807 while (!(*bp == '*' && bp[1] == '/'))
03808 bp++;
03809 bp += 2;
03810 }
03811 else break;
03812 }
03813
03814 cp = bp;
03815
03816
03817
03818
03819
03820 while (1) {
03821 if (is_idchar (*bp))
03822 bp++;
03823 else {
03824 if (*bp == '\\' && bp[1] == '\n')
03825 name_newline_fix (bp);
03826 if (is_idchar (*bp))
03827 bp++;
03828 else break;
03829 }
03830 }
03831
03832 for (kt = directive_table; kt->length >= 0; kt++) {
03833 IF_STACK_FRAME *temp;
03834 if (strncmp ((const char *)cp, kt->name, kt->length) == 0
03835 && !is_idchar (cp[kt->length])) {
03836
03837
03838
03839 if (any)
03840 return;
03841
03842 switch (kt->type) {
03843 case T_IF:
03844 case T_IFDEF:
03845 case T_IFNDEF:
03846 temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
03847 temp->next = if_stack;
03848 if_stack = temp;
03849 temp->lineno = ip->lineno;
03850 temp->fname = ip->fname;
03851 temp->type = kt->type;
03852 break;
03853 case T_ELSE:
03854 case T_ENDIF:
03855 case T_ELIF:
03856 if (if_stack == instack[indepth].if_stack) {
03857 error ("#%s not within a conditional", kt->name);
03858 break;
03859 }
03860 else if (if_stack == save_if_stack)
03861 return;
03862
03863 if (kt->type != T_ENDIF) {
03864 if (if_stack->type == T_ELSE)
03865 error ("#else or #elif after #else");
03866 if_stack->type = kt->type;
03867 break;
03868 }
03869
03870 temp = if_stack;
03871 if_stack = if_stack->next;
03872 free (temp);
03873 break;
03874
03875 default:
03876
03877 break;
03878 }
03879 break;
03880 }
03881 }
03882 }
03883 }
03884 ip->bufp = bp;
03885
03886
03887
03888 }
03889
03890
03891
03892
03893
03894
03895
03896 static void
03897 do_else (buf, limit, op)
03898 U_CHAR *buf ATTRIBUTE_UNUSED;
03899 U_CHAR *limit ATTRIBUTE_UNUSED;
03900 FILE_BUF *op;
03901 {
03902 FILE_BUF *ip = &instack[indepth];
03903
03904 if (if_stack == instack[indepth].if_stack) {
03905 error ("#else not within a conditional");
03906 return;
03907 } else {
03908 if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
03909 error ("#else after #else");
03910 fprintf (stderr, " (matches line %d", if_stack->lineno);
03911 if (strcmp (if_stack->fname, ip->fname) != 0)
03912 fprintf (stderr, ", file %s", if_stack->fname);
03913 fprintf (stderr, ")\n");
03914 }
03915 if_stack->type = T_ELSE;
03916 }
03917
03918 if (if_stack->if_succeeded)
03919 skip_if_group (ip, 0);
03920 else {
03921 ++if_stack->if_succeeded;
03922 output_line_command (ip, op, 1, same_file);
03923 }
03924 }
03925
03926
03927
03928
03929 static void
03930 do_endif (buf, limit, op)
03931 U_CHAR *buf ATTRIBUTE_UNUSED;
03932 U_CHAR *limit ATTRIBUTE_UNUSED;
03933 FILE_BUF *op;
03934 {
03935 if (if_stack == instack[indepth].if_stack)
03936 error ("unbalanced #endif");
03937 else {
03938 IF_STACK_FRAME *temp = if_stack;
03939 if_stack = if_stack->next;
03940 free (temp);
03941 output_line_command (&instack[indepth], op, 1, same_file);
03942 }
03943 }
03944
03945
03946
03947
03948
03949
03950
03951
03952 static U_CHAR *
03953 skip_to_end_of_comment (ip, line_counter)
03954 FILE_BUF *ip;
03955 int *line_counter;
03956 {
03957 U_CHAR *limit = ip->buf + ip->length;
03958 U_CHAR *bp = ip->bufp;
03959 FILE_BUF *op = &outbuf;
03960 int output = put_out_comments && !line_counter;
03961
03962
03963
03964
03965 if (output) {
03966 *op->bufp++ = '/';
03967 *op->bufp++ = '*';
03968 }
03969 while (bp < limit) {
03970 if (output)
03971 *op->bufp++ = *bp;
03972 switch (*bp++) {
03973 case '/':
03974 if (warn_comments && bp < limit && *bp == '*')
03975 warning("`/*' within comment");
03976 break;
03977 case '\n':
03978 if (line_counter != NULL)
03979 ++*line_counter;
03980 if (output)
03981 ++op->lineno;
03982 break;
03983 case '*':
03984 if (*bp == '\\' && bp[1] == '\n')
03985 newline_fix (bp);
03986 if (*bp == '/') {
03987 if (output)
03988 *op->bufp++ = '/';
03989 ip->bufp = ++bp;
03990 return bp;
03991 }
03992 break;
03993 }
03994 }
03995 ip->bufp = bp;
03996 return bp;
03997 }
03998
03999
04000
04001
04002
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013
04014
04015 static U_CHAR *
04016 skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, eofp)
04017 const U_CHAR *bp;
04018 const U_CHAR *limit;
04019 int start_line;
04020 int *count_newlines;
04021 int *backslash_newlines_p;
04022 int *eofp;
04023 {
04024 U_CHAR c, match;
04025
04026 match = *bp++;
04027 while (1) {
04028 if (bp >= limit) {
04029 error_with_line (line_for_error (start_line),
04030 "unterminated string or character constant");
04031 if (eofp)
04032 *eofp = 1;
04033 break;
04034 }
04035 c = *bp++;
04036 if (c == '\\') {
04037 while (*bp == '\\' && bp[1] == '\n') {
04038 if (backslash_newlines_p)
04039 *backslash_newlines_p = 1;
04040 if (count_newlines)
04041 ++*count_newlines;
04042 bp += 2;
04043 }
04044 if (*bp == '\n' && count_newlines) {
04045 if (backslash_newlines_p)
04046 *backslash_newlines_p = 1;
04047 ++*count_newlines;
04048 }
04049 bp++;
04050 } else if (c == '\n') {
04051
04052 bp--;
04053 if (eofp)
04054 *eofp = 1;
04055 break;
04056 } else if (c == match)
04057 break;
04058 }
04059 return (U_CHAR *) bp;
04060 }
04061
04062
04063
04064
04065
04066
04067
04068
04069
04070 static void
04071 output_line_command (ip, op, conditional, file_change)
04072 FILE_BUF *ip, *op;
04073 int conditional;
04074 enum file_change_code file_change;
04075 {
04076 int len;
04077 char line_cmd_buf[500];
04078
04079 if (no_line_commands
04080 || ip->fname == NULL
04081 || no_output) {
04082 op->lineno = ip->lineno;
04083 return;
04084 }
04085
04086 if (conditional) {
04087 if (ip->lineno == op->lineno)
04088 return;
04089
04090
04091
04092 if (ip->lineno > op->lineno && ip->lineno < op->lineno + 8) {
04093 check_expand (op, 10);
04094 while (ip->lineno > op->lineno) {
04095 *op->bufp++ = '\n';
04096 op->lineno++;
04097 }
04098 return;
04099 }
04100 }
04101
04102 sprintf (line_cmd_buf, "# %d \"%s\"", ip->lineno, ip->fname);
04103 if (file_change != same_file)
04104 strcat (line_cmd_buf, file_change == enter_file ? " 1" : " 2");
04105 if (system_include_depth > (file_change == leave_file))
04106 strcat (line_cmd_buf, " 3");
04107 len = strlen (line_cmd_buf);
04108 line_cmd_buf[len++] = '\n';
04109 check_expand (op, len + 1);
04110 if (op->bufp > op->buf && op->bufp[-1] != '\n')
04111 *op->bufp++ = '\n';
04112 memcpy (op->bufp, line_cmd_buf, len);
04113 op->bufp += len;
04114 op->lineno = ip->lineno;
04115 }
04116
04117
04118
04119
04120
04121
04122
04123
04124
04125
04126 static void
04127 macroexpand (hp, op)
04128 HASHNODE *hp;
04129 FILE_BUF *op;
04130 {
04131 int nargs;
04132 DEFINITION *defn = hp->value.defn;
04133 U_CHAR *xbuf;
04134 int xbuf_len;
04135 int start_line = instack[indepth].lineno;
04136
04137 CHECK_DEPTH (return;);
04138
04139
04140 if (hp->type != T_MACRO) {
04141 special_symbol (hp, op);
04142 return;
04143 }
04144
04145 nargs = defn->nargs;
04146
04147 if (nargs >= 0) {
04148 int i;
04149 struct argdata *args;
04150 const char *parse_error = 0;
04151
04152 args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
04153
04154 for (i = 0; i < nargs; i++) {
04155 args[i].raw = args[i].expanded = (U_CHAR *) "";
04156 args[i].raw_length = args[i].expand_length
04157 = args[i].stringified_length = 0;
04158 args[i].free1 = args[i].free2 = 0;
04159 }
04160
04161
04162
04163
04164 i = 0;
04165 do {
04166
04167 ++instack[indepth].bufp;
04168 parse_error
04169 = macarg ((i < nargs || (nargs == 0 && i == 0)) ? &args[i] : 0);
04170 if (parse_error)
04171 {
04172 error_with_line (line_for_error (start_line), "%s", parse_error);
04173 break;
04174 }
04175 i++;
04176 } while (*instack[indepth].bufp != ')');
04177
04178
04179 if (i == 1) {
04180 const U_CHAR *bp = args[0].raw;
04181 const U_CHAR *lim = bp + args[0].raw_length;
04182 while (bp != lim && is_space (*bp)) bp++;
04183 if (bp == lim)
04184 i = 0;
04185 }
04186
04187 if (nargs == 0 && i > 0)
04188 error ("arguments given to macro `%s'", hp->name);
04189 else if (i < nargs) {
04190
04191 if (nargs == 1 && i == 0)
04192 ;
04193 else if (i == 0)
04194 error ("no args to macro `%s'", hp->name);
04195 else if (i == 1)
04196 error ("only 1 arg to macro `%s'", hp->name);
04197 else
04198 error ("only %d args to macro `%s'", i, hp->name);
04199 } else if (i > nargs)
04200 error ("too many (%d) args to macro `%s'", i, hp->name);
04201
04202
04203 ++instack[indepth].bufp;
04204
04205
04206
04207 if (nargs == 0) {
04208 xbuf = defn->expansion;
04209 xbuf_len = defn->length;
04210 } else {
04211 U_CHAR *exp = defn->expansion;
04212 int offset;
04213
04214 int totlen;
04215
04216 struct reflist *ap;
04217
04218
04219
04220
04221 xbuf_len = defn->length;
04222 for (ap = defn->pattern; ap != NULL; ap = ap->next) {
04223 if (ap->stringify)
04224 xbuf_len += args[ap->argno].stringified_length;
04225 else
04226 xbuf_len += args[ap->argno].raw_length;
04227 }
04228
04229 xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
04230
04231
04232
04233
04234
04235
04236 offset = totlen = 0;
04237 for (ap = defn->pattern; ap != NULL; ap = ap->next) {
04238 struct argdata *arg = &args[ap->argno];
04239
04240 for (i = 0; i < ap->nchars; i++)
04241 xbuf[totlen++] = exp[offset++];
04242
04243 if (ap->stringify != 0) {
04244 int arglen = arg->raw_length;
04245 int escaped = 0;
04246 int in_string = 0;
04247 int c;
04248 i = 0;
04249 while (i < arglen
04250 && (c = arg->raw[i], is_space (c)))
04251 i++;
04252 while (i < arglen
04253 && (c = arg->raw[arglen - 1], is_space (c)))
04254 arglen--;
04255 for (; i < arglen; i++) {
04256 c = arg->raw[i];
04257
04258
04259
04260 if (c == '\n' && arg->raw[i+1] != '\n') {
04261 i++;
04262 continue;
04263 }
04264
04265
04266
04267 if (! in_string
04268 && (c == '\n' ? arg->raw[i+1] == '\n' : is_space (c))) {
04269 while (1) {
04270
04271
04272 if (c == '\n' && is_space (arg->raw[i+1]))
04273 i += 2;
04274 else if (c != '\n' && is_space (c))
04275 i++;
04276 else break;
04277 c = arg->raw[i];
04278 }
04279 i--;
04280 c = ' ';
04281 }
04282
04283 if (escaped)
04284 escaped = 0;
04285 else {
04286 if (c == '\\')
04287 escaped = 1;
04288 if (in_string) {
04289 if (c == in_string)
04290 in_string = 0;
04291 } else if (c == '\"' || c == '\'')
04292 in_string = c;
04293 }
04294
04295
04296 if (c == '\"' || (in_string && c == '\\'))
04297 xbuf[totlen++] = '\\';
04298 if (ISPRINT (c))
04299 xbuf[totlen++] = c;
04300 else {
04301 sprintf ((char *) &xbuf[totlen], "\\%03o", (unsigned int) c);
04302 totlen += 4;
04303 }
04304 }
04305 } else {
04306 const U_CHAR *p1 = arg->raw;
04307 const U_CHAR *l1 = p1 + arg->raw_length;
04308
04309 if (ap->raw_before) {
04310 while (p1 != l1 && is_space (*p1)) p1++;
04311 while (p1 != l1 && is_idchar (*p1))
04312 xbuf[totlen++] = *p1++;
04313
04314
04315
04316 if (p1[0] == '\n' && p1[1] == '-')
04317 p1 += 2;
04318 }
04319 if (ap->raw_after) {
04320
04321
04322 while (p1 != l1) {
04323 if (is_space (l1[-1])) l1--;
04324 else if (l1[-1] == '-') {
04325 const U_CHAR *p2 = l1 - 1;
04326
04327
04328 while (p2 != p1 && p2[-1] == '\n') p2--;
04329 if ((l1 - 1 - p2) & 1) {
04330 l1 -= 2;
04331 }
04332 else break;
04333 }
04334 else break;
04335 }
04336 }
04337 memmove (xbuf + totlen, p1, l1 - p1);
04338 totlen += l1 - p1;
04339 }
04340
04341 if (totlen > xbuf_len)
04342 abort ();
04343 }
04344
04345
04346
04347
04348 for (i = offset; i < defn->length; i++)
04349 xbuf[totlen++] = exp[i];
04350
04351 xbuf[totlen] = 0;
04352 xbuf_len = totlen;
04353
04354 for (i = 0; i < nargs; i++) {
04355 if (args[i].free1 != 0)
04356 free (args[i].free1);
04357 if (args[i].free2 != 0)
04358 free (args[i].free2);
04359 }
04360 }
04361 } else {
04362 xbuf = defn->expansion;
04363 xbuf_len = defn->length;
04364 }
04365
04366
04367
04368 {
04369 FILE_BUF *ip2;
04370
04371 ip2 = &instack[++indepth];
04372
04373 ip2->fname = 0;
04374 ip2->lineno = 0;
04375 ip2->buf = xbuf;
04376 ip2->length = xbuf_len;
04377 ip2->bufp = xbuf;
04378 ip2->free_ptr = (nargs > 0) ? xbuf : 0;
04379 ip2->macro = hp;
04380 ip2->if_stack = if_stack;
04381 }
04382 }
04383
04384
04385
04386
04387
04388
04389 static const char *
04390 macarg (argptr)
04391 struct argdata *argptr;
04392 {
04393 FILE_BUF *ip = &instack[indepth];
04394 int paren = 0;
04395 int newlines = 0;
04396 int comments = 0;
04397
04398
04399
04400 U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length,
04401 &paren, &newlines, &comments);
04402
04403
04404
04405 if (!(ip->fname != 0 && (newlines != 0 || comments != 0))
04406 && bp != ip->buf + ip->length) {
04407 if (argptr != 0) {
04408 argptr->raw = ip->bufp;
04409 argptr->raw_length = bp - ip->bufp;
04410 }
04411 ip->bufp = bp;
04412 } else {
04413
04414
04415
04416
04417 int bufsize = bp - ip->bufp;
04418 int extra = newlines;
04419 U_CHAR *buffer = (U_CHAR *) xmalloc (bufsize + extra + 1);
04420 int final_start = 0;
04421
04422 memcpy (buffer, ip->bufp, bufsize);
04423 ip->bufp = bp;
04424 ip->lineno += newlines;
04425
04426 while (bp == ip->buf + ip->length) {
04427 if (instack[indepth].macro == 0) {
04428 free (buffer);
04429 return "unterminated macro call";
04430 }
04431 ip->macro->type = T_MACRO;
04432 if (ip->free_ptr)
04433 free (ip->free_ptr);
04434 ip = &instack[--indepth];
04435 newlines = 0;
04436 comments = 0;
04437 bp = macarg1 (ip->bufp, ip->buf + ip->length, &paren,
04438 &newlines, &comments);
04439 final_start = bufsize;
04440 bufsize += bp - ip->bufp;
04441 extra += newlines;
04442 buffer = (U_CHAR *) xrealloc (buffer, bufsize + extra + 1);
04443 memcpy (buffer + bufsize - (bp - ip->bufp), ip->bufp, bp - ip->bufp);
04444 ip->bufp = bp;
04445 ip->lineno += newlines;
04446 }
04447
04448
04449
04450
04451
04452
04453 if (argptr != 0) {
04454 argptr->raw = buffer;
04455 argptr->raw_length = bufsize;
04456 argptr->free1 = buffer;
04457 argptr->newlines = newlines;
04458 argptr->comments = comments;
04459 if ((newlines || comments) && ip->fname != 0)
04460 argptr->raw_length
04461 = final_start +
04462 discard_comments (argptr->raw + final_start,
04463 argptr->raw_length - final_start,
04464 newlines);
04465 argptr->raw[argptr->raw_length] = 0;
04466 if (argptr->raw_length > bufsize + extra)
04467 abort ();
04468 }
04469 }
04470
04471
04472
04473
04474
04475 if (argptr != 0) {
04476 FILE_BUF obuf;
04477 const U_CHAR *buf, *lim;
04478 int totlen;
04479
04480 obuf = expand_to_temp_buffer (argptr->raw,
04481 argptr->raw + argptr->raw_length,
04482 1);
04483
04484 argptr->expanded = obuf.buf;
04485 argptr->expand_length = obuf.length;
04486 argptr->free2 = obuf.buf;
04487
04488 buf = argptr->raw;
04489 lim = buf + argptr->raw_length;
04490
04491 totlen = 0;
04492 while (buf != lim) {
04493 U_CHAR c = *buf++;
04494 totlen++;
04495
04496
04497
04498 if (c == '\"' || c == '\\')
04499 totlen++;
04500 else if (!ISPRINT (c))
04501 totlen += 3;
04502 }
04503 argptr->stringified_length = totlen;
04504 }
04505 return 0;
04506 }
04507
04508
04509
04510
04511
04512
04513
04514
04515
04516
04517
04518
04519
04520 static U_CHAR *
04521 macarg1 (start, limit, depthptr, newlines, comments)
04522 U_CHAR *start;
04523 const U_CHAR *limit;
04524 int *depthptr, *newlines, *comments;
04525 {
04526 U_CHAR *bp = start;
04527
04528 while (bp < limit) {
04529 switch (*bp) {
04530 case '(':
04531 (*depthptr)++;
04532 break;
04533 case ')':
04534 if (--(*depthptr) < 0)
04535 return bp;
04536 break;
04537 case '\\':
04538
04539 if (bp + 1 < limit)
04540 {
04541 bp++;
04542
04543 if (*bp == '\n')
04544 ++*newlines;
04545 }
04546 break;
04547 case '\n':
04548 ++*newlines;
04549 break;
04550 case '/':
04551 if (bp[1] == '\\' && bp[2] == '\n')
04552 newline_fix (bp + 1);
04553 if (bp[1] != '*' || bp + 1 >= limit)
04554 break;
04555 *comments = 1;
04556 bp += 2;
04557 while (bp + 1 < limit) {
04558 if (bp[0] == '*'
04559 && bp[1] == '\\' && bp[2] == '\n')
04560 newline_fix (bp + 1);
04561 if (bp[0] == '*' && bp[1] == '/')
04562 break;
04563 if (*bp == '\n') ++*newlines;
04564 bp++;
04565 }
04566 bp += 1;
04567 break;
04568 case '\'':
04569 case '\"':
04570 {
04571 int quotec;
04572 for (quotec = *bp++; bp + 1 < limit && *bp != quotec; bp++) {
04573 if (*bp == '\\') {
04574 bp++;
04575 if (*bp == '\n')
04576 ++*newlines;
04577 while (*bp == '\\' && bp[1] == '\n') {
04578 bp += 2;
04579 }
04580 } else if (*bp == '\n') {
04581 ++*newlines;
04582 if (quotec == '\'')
04583 break;
04584 }
04585 }
04586 }
04587 break;
04588 case ',':
04589 if ((*depthptr) == 0)
04590 return bp;
04591 break;
04592 }
04593 bp++;
04594 }
04595
04596 return bp;
04597 }
04598
04599
04600
04601
04602
04603
04604
04605
04606
04607
04608 static int
04609 discard_comments (start, length, newlines)
04610 U_CHAR *start;
04611 int length;
04612 int newlines;
04613 {
04614 U_CHAR *ibp;
04615 U_CHAR *obp;
04616 const U_CHAR *limit;
04617 int c;
04618
04619
04620
04621
04622
04623
04624
04625
04626 if (newlines > 0) {
04627 ibp = start + length;
04628 obp = ibp + newlines;
04629 limit = start;
04630 while (limit != ibp)
04631 *--obp = *--ibp;
04632 }
04633
04634 ibp = start + newlines;
04635 limit = start + length + newlines;
04636 obp = start;
04637
04638 while (ibp < limit) {
04639 *obp++ = c = *ibp++;
04640 switch (c) {
04641 case '\n':
04642
04643 *obp++ = '\n';
04644 break;
04645
04646 case '\\':
04647 if (*ibp == '\n') {
04648 obp--;
04649 ibp++;
04650 }
04651 break;
04652
04653 case '/':
04654 if (*ibp == '\\' && ibp[1] == '\n')
04655 newline_fix (ibp);
04656
04657 if (ibp[0] != '*' || ibp + 1 >= limit)
04658 break;
04659 obp--;
04660 ibp++;
04661 while (ibp + 1 < limit) {
04662 if (ibp[0] == '*'
04663 && ibp[1] == '\\' && ibp[2] == '\n')
04664 newline_fix (ibp + 1);
04665 if (ibp[0] == '*' && ibp[1] == '/')
04666 break;
04667 ibp++;
04668 }
04669 ibp += 2;
04670 break;
04671
04672 case '\'':
04673 case '\"':
04674
04675
04676
04677 {
04678 int quotec = c;
04679 while (ibp < limit) {
04680 *obp++ = c = *ibp++;
04681 if (c == quotec)
04682 break;
04683 if (c == '\n' && quotec == '\'')
04684 break;
04685 if (c == '\\' && ibp < limit) {
04686 while (*ibp == '\\' && ibp[1] == '\n')
04687 ibp += 2;
04688 *obp++ = *ibp++;
04689 }
04690 }
04691 }
04692 break;
04693 }
04694 }
04695
04696 return obp - start;
04697 }
04698
04699
04700
04701 static void
04702 v_message (mtype, line, msgid, ap)
04703 enum msgtype mtype;
04704 int line;
04705 const char *msgid;
04706 va_list ap;
04707 {
04708 const char *fname = 0;
04709 int i;
04710
04711 if (mtype == MT_WARNING && inhibit_warnings)
04712 return;
04713
04714 for (i = indepth; i >= 0; i--)
04715 if (instack[i].fname != NULL) {
04716 if (line == 0)
04717 line = instack[i].lineno;
04718 fname = instack[i].fname;
04719 break;
04720 }
04721
04722 if (fname)
04723 fprintf (stderr, "%s:%d: ", fname, line);
04724 else
04725 fprintf (stderr, "%s: ", progname);
04726
04727 if (mtype == MT_WARNING)
04728 fputs (_("warning: "), stderr);
04729
04730 vfprintf (stderr, _(msgid), ap);
04731 putc ('\n', stderr);
04732
04733 if (mtype == MT_ERROR)
04734 errors++;
04735 }
04736
04737
04738
04739
04740 void
04741 error VPARAMS ((const char *msgid, ...))
04742 {
04743 VA_OPEN(ap, msgid);
04744 VA_FIXEDARG (ap, const char *, msgid);
04745
04746 v_message (MT_ERROR, 0, msgid, ap);
04747 VA_CLOSE (ap);
04748 }
04749
04750 void
04751 error_with_line VPARAMS ((int line, const char *msgid, ...))
04752 {
04753 VA_OPEN(ap, msgid);
04754 VA_FIXEDARG (ap, int, line);
04755 VA_FIXEDARG (ap, const char *, msgid);
04756
04757 v_message (MT_ERROR, line, msgid, ap);
04758 VA_CLOSE (ap);
04759 }
04760
04761
04762 void
04763 error_from_errno (name)
04764 const char *name;
04765 {
04766 error ("%s: %s", name, strerror (errno));
04767 }
04768
04769
04770 void
04771 warning VPARAMS ((const char *msgid, ...))
04772 {
04773 VA_OPEN(ap, msgid);
04774 VA_FIXEDARG (ap, const char *, msgid);
04775
04776 v_message (MT_WARNING, 0, msgid, ap);
04777 VA_CLOSE (ap);
04778 }
04779
04780 void
04781 fatal VPARAMS ((const char *msgid, ...))
04782 {
04783 VA_OPEN(ap, msgid);
04784 VA_FIXEDARG (ap, const char *, msgid);
04785
04786 v_message (MT_FATAL, 0, msgid, ap);
04787 VA_CLOSE (ap);
04788 exit (FATAL_EXIT_CODE);
04789 }
04790
04791
04792 void
04793 fancy_abort (line, func)
04794 int line;
04795 const char *func;
04796 {
04797 fatal ("internal error in %s, at tradcpp.c:%d\n\
04798 Please submit a full bug report.\n\
04799 See %s for instructions.", func, line, GCCBUGURL);
04800 }
04801
04802 void
04803 perror_with_name (name)
04804 const char *name;
04805 {
04806 fprintf (stderr, "%s: %s: %s\n", progname, name, strerror (errno));
04807 errors++;
04808 }
04809
04810 void
04811 pfatal_with_name (name)
04812 const char *name;
04813 {
04814 perror_with_name (name);
04815 exit (FATAL_EXIT_CODE);
04816 }
04817
04818
04819
04820
04821
04822
04823
04824
04825 static int
04826 line_for_error (line)
04827 int line;
04828 {
04829 int i;
04830 int line1 = line;
04831
04832 for (i = indepth; i >= 0; ) {
04833 if (instack[i].fname != 0)
04834 return line1;
04835 i--;
04836 if (i < 0)
04837 return 0;
04838 line1 = instack[i].lineno;
04839 }
04840 return 0;
04841 }
04842
04843
04844
04845
04846
04847
04848
04849
04850
04851
04852 static void
04853 grow_outbuf (obuf, needed)
04854 FILE_BUF *obuf;
04855 int needed;
04856 {
04857 U_CHAR *p;
04858 int minsize;
04859
04860 if (obuf->length - (obuf->bufp - obuf->buf) > needed)
04861 return;
04862
04863
04864 obuf->length *= 2;
04865
04866 minsize = (3 * needed) / 2 + (obuf->bufp - obuf->buf);
04867 if (minsize > obuf->length)
04868 obuf->length = minsize;
04869
04870 p = (U_CHAR *) xrealloc (obuf->buf, obuf->length);
04871 obuf->bufp = p + (obuf->bufp - obuf->buf);
04872 obuf->buf = p;
04873 }
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891
04892
04893 static HASHNODE *
04894 install (name, len, type, hash)
04895 const U_CHAR *name;
04896 int len;
04897 enum node_type type;
04898 int hash;
04899
04900 {
04901 HASHNODE *hp;
04902 int bucket;
04903 const U_CHAR *p;
04904 U_CHAR *q;
04905
04906 if (len < 0) {
04907 p = name;
04908 while (is_idchar (*p))
04909 p++;
04910 len = p - name;
04911 }
04912
04913 if (hash < 0)
04914 hash = hashf (name, len, HASHSIZE);
04915
04916 hp = (HASHNODE *) xmalloc (sizeof (HASHNODE) + len + 1);
04917 bucket = hash;
04918 hp->bucket_hdr = &hashtab[bucket];
04919 hp->next = hashtab[bucket];
04920 hashtab[bucket] = hp;
04921 hp->prev = NULL;
04922 if (hp->next != NULL)
04923 hp->next->prev = hp;
04924 hp->type = type;
04925 hp->length = len;
04926 hp->name = q = ((U_CHAR *) hp) + sizeof (HASHNODE);
04927 memcpy (q, name, len);
04928 q[len] = 0;
04929 return hp;
04930 }
04931
04932
04933
04934
04935
04936
04937
04938
04939
04940
04941
04942 HASHNODE *
04943 lookup (name, len, hash)
04944 const U_CHAR *name;
04945 int len;
04946 int hash;
04947 {
04948 const U_CHAR *bp;
04949 HASHNODE *bucket;
04950
04951 if (len < 0) {
04952 for (bp = name; is_idchar (*bp); bp++) ;
04953 len = bp - name;
04954 }
04955
04956 if (hash < 0)
04957 hash = hashf (name, len, HASHSIZE);
04958
04959 bucket = hashtab[hash];
04960 while (bucket) {
04961 if (bucket->length == len
04962 && strncmp ((const char *)bucket->name, (const char *)name, len) == 0)
04963 return bucket;
04964 bucket = bucket->next;
04965 }
04966 return NULL;
04967 }
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977
04978
04979
04980
04981
04982 static void
04983 delete_macro (hp)
04984 HASHNODE *hp;
04985 {
04986
04987 if (hp->prev != NULL)
04988 hp->prev->next = hp->next;
04989 if (hp->next != NULL)
04990 hp->next->prev = hp->prev;
04991
04992
04993
04994 if (hp == *hp->bucket_hdr)
04995 *hp->bucket_hdr = hp->next;
04996
04997 free (hp);
04998 }
04999
05000
05001
05002
05003
05004 static int
05005 hashf (name, len, hashsize)
05006 const U_CHAR *name;
05007 int len;
05008 int hashsize;
05009 {
05010 int r = 0;
05011
05012 while (len--)
05013 r = HASHSTEP (r, *name++);
05014
05015 return MAKE_POS (r) % hashsize;
05016 }
05017
05018
05019
05020 static void
05021 dump_all_macros ()
05022 {
05023 int bucket;
05024
05025 for (bucket = 0; bucket < HASHSIZE; bucket++) {
05026 HASHNODE *hp;
05027
05028 for (hp = hashtab[bucket]; hp; hp= hp->next) {
05029 if (hp->type == T_MACRO) {
05030 DEFINITION *defn = hp->value.defn;
05031 struct reflist *ap;
05032 int offset;
05033 int concat;
05034
05035
05036
05037
05038 printf ("#define %s", hp->name);
05039 if (defn->nargs >= 0) {
05040 int i;
05041
05042 printf ("(");
05043 for (i = 0; i < defn->nargs; i++) {
05044 dump_arg_n (defn, i);
05045 if (i + 1 < defn->nargs)
05046 printf (", ");
05047 }
05048 printf (")");
05049 }
05050
05051 printf (" ");
05052
05053 offset = 0;
05054 concat = 0;
05055 for (ap = defn->pattern; ap != NULL; ap = ap->next) {
05056 dump_defn_1 (defn->expansion, offset, ap->nchars);
05057 if (ap->nchars != 0)
05058 concat = 0;
05059 offset += ap->nchars;
05060 if (ap->stringify)
05061 printf (" #");
05062 if (ap->raw_before && !concat)
05063 printf (" ## ");
05064 concat = 0;
05065 dump_arg_n (defn, ap->argno);
05066 if (ap->raw_after) {
05067 printf (" ## ");
05068 concat = 1;
05069 }
05070 }
05071 dump_defn_1 (defn->expansion, offset, defn->length - offset);
05072 printf ("\n");
05073 }
05074 }
05075 }
05076 }
05077
05078
05079
05080
05081
05082
05083 static void
05084 dump_defn_1 (base, start, length)
05085 const U_CHAR *base;
05086 int start;
05087 int length;
05088 {
05089 const U_CHAR *p = base + start;
05090 const U_CHAR *limit = base + start + length;
05091
05092 while (p < limit) {
05093 if (*p != '\n')
05094 putchar (*p);
05095 else if (*p == '\"' || *p =='\'') {
05096 const U_CHAR *p1 = skip_quoted_string (p, limit, 0, 0, 0, 0);
05097 fwrite (p, p1 - p, 1, stdout);
05098 p = p1 - 1;
05099 }
05100 p++;
05101 }
05102 }
05103
05104
05105
05106
05107 static void
05108 dump_arg_n (defn, argnum)
05109 DEFINITION *defn;
05110 int argnum;
05111 {
05112 const U_CHAR *p = defn->argnames;
05113 while (argnum + 1 < defn->nargs) {
05114 p = (const U_CHAR *) strchr ((const char *)p, ' ') + 1;
05115 argnum++;
05116 }
05117
05118 while (*p && *p != ',') {
05119 putchar (*p);
05120 p++;
05121 }
05122 }
05123
05124
05125 #define DSC(x) U x, sizeof x - 1
05126 #define install_spec(name, type) \
05127 install(DSC(name), type, -1);
05128 #define install_value(name, val) \
05129 hp = install(DSC(name), T_CONST, -1); hp->value.cpval = val;
05130 static void
05131 initialize_builtins ()
05132 {
05133 HASHNODE *hp;
05134
05135 install_spec ("__BASE_FILE__", T_BASE_FILE);
05136 install_spec ("__DATE__", T_DATE);
05137 install_spec ("__FILE__", T_FILE);
05138 install_spec ("__TIME__", T_TIME);
05139 install_spec ("__VERSION__", T_VERSION);
05140 install_spec ("__INCLUDE_LEVEL__", T_INCLUDE_LEVEL);
05141 install_spec ("__LINE__", T_SPECLINE);
05142
05143 #ifndef NO_BUILTIN_SIZE_TYPE
05144 install_value ("__SIZE_TYPE__", SIZE_TYPE);
05145 #endif
05146 #ifndef NO_BUILTIN_PTRDIFF_TYPE
05147 install_value ("__PTRDIFF_TYPE__", PTRDIFF_TYPE);
05148 #endif
05149 #ifndef NO_BUILTIN_WCHAR_TYPE
05150 install_value ("__WCHAR_TYPE__", WCHAR_TYPE);
05151 #endif
05152 #ifndef NO_BUILTIN_WINT_TYPE
05153 install_value ("__WINT_TYPE__", WINT_TYPE);
05154 #endif
05155 install_value ("__REGISTER_PREFIX__", REGISTER_PREFIX);
05156 install_value ("__USER_LABEL_PREFIX__", user_label_prefix);
05157
05158 if (flag_signed_char == 0)
05159 install_value ("__CHAR_UNSIGNED__", "1");
05160 }
05161 #undef DSC
05162 #undef install_spec
05163 #undef install_value
05164
05165
05166 static void
05167 run_directive (str, len, type)
05168 const char *str;
05169 size_t len;
05170 enum node_type type;
05171 {
05172 const struct directive *kt;
05173 FILE_BUF *ip = &instack[++indepth];
05174 ip->fname = "*command line*";
05175
05176 ip->buf = ip->bufp = (U_CHAR *) str;
05177 ip->length = len;
05178 ip->lineno = 1;
05179 ip->macro = 0;
05180 ip->free_ptr = 0;
05181 ip->if_stack = if_stack;
05182
05183 for (kt = directive_table; kt->type != type; kt++)
05184 ;
05185
05186 (*kt->func) ((U_CHAR *) str, (U_CHAR *) str + len, NULL);
05187 --indepth;
05188 }
05189
05190
05191
05192
05193 static void
05194 make_definition (str)
05195 const char *str;
05196 {
05197 char *buf, *p;
05198 size_t count;
05199
05200
05201
05202
05203
05204
05205 count = strlen (str);
05206 buf = (char *) alloca (count + 2);
05207 memcpy (buf, str, count);
05208
05209 p = strchr (str, '=');
05210 if (p)
05211 buf[p - str] = ' ';
05212 else
05213 {
05214 buf[count++] = ' ';
05215 buf[count++] = '1';
05216 }
05217
05218 run_directive (buf, count, T_DEFINE);
05219 }
05220
05221
05222 static void
05223 make_undef (str)
05224 const char *str;
05225 {
05226 run_directive (str, strlen (str), T_UNDEF);
05227 }
05228
05229
05230 static void
05231 make_assertion (str)
05232 const char *str;
05233 {
05234 enum node_type type = T_ASSERT;
05235 size_t count;
05236 const char *p;
05237
05238 if (*str == '-')
05239 {
05240 str++;
05241 type = T_UNASSERT;
05242 }
05243
05244 count = strlen (str);
05245 p = strchr (str, '=');
05246 if (p)
05247 {
05248
05249
05250 char *buf = (char *) alloca (count + 1);
05251
05252 memcpy (buf, str, count);
05253 buf[p - str] = '(';
05254 buf[count++] = ')';
05255 str = buf;
05256 }
05257
05258 run_directive (str, count, type);
05259 }
05260
05261
05262
05263
05264 static int
05265 file_size_and_mode (fd, mode_pointer, size_pointer)
05266 int fd;
05267 int *mode_pointer;
05268 long *size_pointer;
05269 {
05270 struct stat sbuf;
05271
05272 if (fstat (fd, &sbuf) < 0) return -1;
05273 if (mode_pointer) *mode_pointer = sbuf.st_mode;
05274 if (size_pointer) *size_pointer = sbuf.st_size;
05275 return 0;
05276 }