|
|
1.1 ! root 1: /* C Compatible Compiler Preprocessor (CCCP) ! 2: Copyright (C) 1986, 1987, 1989, 1992, 1993 Free Software Foundation, Inc. ! 3: Written by Paul Rubin, June 1986 ! 4: Adapted to ANSI C, Richard Stallman, Jan 1987 ! 5: ! 6: This program is free software; you can redistribute it and/or modify it ! 7: under the terms of the GNU General Public License as published by the ! 8: Free Software Foundation; either version 2, or (at your option) any ! 9: later version. ! 10: ! 11: This program is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with this program; if not, write to the Free Software ! 18: Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ! 19: ! 20: In other words, you are welcome to use, share and improve this program. ! 21: You are forbidden to forbid anyone else to use, share and improve ! 22: what you give them. Help stamp out software-hoarding! */ ! 23: ! 24: typedef unsigned char U_CHAR; ! 25: ! 26: #ifdef EMACS ! 27: #define NO_SHORTNAMES ! 28: #include "../src/config.h" ! 29: #ifdef open ! 30: #undef open ! 31: #undef read ! 32: #undef write ! 33: #endif /* open */ ! 34: #endif /* EMACS */ ! 35: ! 36: /* The macro EMACS is defined when cpp is distributed as part of Emacs, ! 37: for the sake of machines with limited C compilers. */ ! 38: #ifndef EMACS ! 39: #include "config.h" ! 40: #endif /* not EMACS */ ! 41: ! 42: #ifndef STANDARD_INCLUDE_DIR ! 43: #define STANDARD_INCLUDE_DIR "/usr/include" ! 44: #endif ! 45: ! 46: #ifndef LOCAL_INCLUDE_DIR ! 47: #define LOCAL_INCLUDE_DIR "/usr/local/include" ! 48: #endif ! 49: ! 50: #if 0 /* We can't get ptrdiff_t, so I arranged not to need PTR_INT_TYPE. */ ! 51: #ifdef __STDC__ ! 52: #define PTR_INT_TYPE ptrdiff_t ! 53: #else ! 54: #define PTR_INT_TYPE long ! 55: #endif ! 56: #endif /* 0 */ ! 57: ! 58: #include "pcp.h" ! 59: ! 60: #ifndef STDC_VALUE ! 61: #define STDC_VALUE 1 ! 62: #endif ! 63: ! 64: /* By default, colon separates directories in a path. */ ! 65: #ifndef PATH_SEPARATOR ! 66: #define PATH_SEPARATOR ':' ! 67: #endif ! 68: ! 69: /* In case config.h defines these. */ ! 70: #undef bcopy ! 71: #undef bzero ! 72: #undef bcmp ! 73: ! 74: #include <sys/types.h> ! 75: #include <sys/stat.h> ! 76: #include <ctype.h> ! 77: #include <stdio.h> ! 78: #include <signal.h> ! 79: ! 80: #ifndef VMS ! 81: #ifndef USG ! 82: #include <sys/time.h> /* for __DATE__ and __TIME__ */ ! 83: #include <sys/resource.h> ! 84: #else ! 85: #include <time.h> ! 86: #include <fcntl.h> ! 87: #endif /* USG */ ! 88: #endif /* not VMS */ ! 89: ! 90: /* This defines "errno" properly for VMS, and gives us EACCES. */ ! 91: #include <errno.h> ! 92: ! 93: /* VMS-specific definitions */ ! 94: #ifdef VMS ! 95: #include <time.h> ! 96: #include <perror.h> /* This defines sys_errlist/sys_nerr properly */ ! 97: #include <descrip.h> ! 98: #define O_RDONLY 0 /* Open arg for Read/Only */ ! 99: #define O_WRONLY 1 /* Open arg for Write/Only */ ! 100: #define read(fd,buf,size) VMS_read (fd,buf,size) ! 101: #define write(fd,buf,size) VMS_write (fd,buf,size) ! 102: #define open(fname,mode,prot) VMS_open (fname,mode,prot) ! 103: #define fopen(fname,mode) VMS_fopen (fname,mode) ! 104: #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile) ! 105: #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt) ! 106: static char * VMS_strncat (); ! 107: static int VMS_read (); ! 108: static int VMS_write (); ! 109: static int VMS_open (); ! 110: static FILE * VMS_fopen (); ! 111: static FILE * VMS_freopen (); ! 112: static void hack_vms_include_specification (); ! 113: typedef struct { unsigned :16, :16, :16; } vms_ino_t; ! 114: #define ino_t vms_ino_t ! 115: #define INCLUDE_LEN_FUDGE 10 /* leave room for VMS syntax conversion */ ! 116: #ifdef __GNUC__ ! 117: #define BSTRING /* VMS/GCC supplies the bstring routines */ ! 118: #endif /* __GNUC__ */ ! 119: #endif /* VMS */ ! 120: ! 121: extern char *index (); ! 122: extern char *rindex (); ! 123: ! 124: #ifndef O_RDONLY ! 125: #define O_RDONLY 0 ! 126: #endif ! 127: ! 128: #undef MIN ! 129: #undef MAX ! 130: #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) ! 131: #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) ! 132: ! 133: /* Find the largest host integer type and set its size and type. */ ! 134: ! 135: #ifndef HOST_BITS_PER_WIDE_INT ! 136: ! 137: #if HOST_BITS_PER_LONG > HOST_BITS_PER_INT ! 138: #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG ! 139: #define HOST_WIDE_INT long ! 140: #else ! 141: #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT ! 142: #define HOST_WIDE_INT int ! 143: #endif ! 144: ! 145: #endif ! 146: ! 147: #ifndef S_ISREG ! 148: #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) ! 149: #endif ! 150: ! 151: #ifndef S_ISDIR ! 152: #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) ! 153: #endif ! 154: ! 155: /* Define a generic NULL if one hasn't already been defined. */ ! 156: ! 157: #ifndef NULL ! 158: #define NULL 0 ! 159: #endif ! 160: ! 161: #ifndef GENERIC_PTR ! 162: #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) ! 163: #define GENERIC_PTR void * ! 164: #else ! 165: #define GENERIC_PTR char * ! 166: #endif ! 167: #endif ! 168: ! 169: #ifndef NULL_PTR ! 170: #define NULL_PTR ((GENERIC_PTR)0) ! 171: #endif ! 172: ! 173: #ifndef INCLUDE_LEN_FUDGE ! 174: #define INCLUDE_LEN_FUDGE 0 ! 175: #endif ! 176: ! 177: /* Forward declarations. */ ! 178: ! 179: char *xmalloc (); ! 180: void error (); ! 181: void warning (); ! 182: ! 183: /* External declarations. */ ! 184: ! 185: extern char *getenv (); ! 186: extern FILE *fdopen (); ! 187: extern char *version_string; ! 188: extern struct tm *localtime (); ! 189: extern int sys_nerr; ! 190: #if defined(bsd4_4) ! 191: extern const char *const sys_errlist[]; ! 192: #else ! 193: extern char *sys_errlist[]; ! 194: #endif ! 195: extern int parse_escape (); ! 196: ! 197: #ifndef errno ! 198: extern int errno; ! 199: #endif ! 200: ! 201: /* Forward declarations. */ ! 202: ! 203: struct directive; ! 204: struct file_buf; ! 205: struct arglist; ! 206: struct argdata; ! 207: ! 208: #if defined(USG) || defined(VMS) ! 209: #ifndef BSTRING ! 210: void bcopy (); ! 211: void bzero (); ! 212: int bcmp (); ! 213: #endif ! 214: #endif ! 215: ! 216: /* These functions are declared to return int instead of void since they ! 217: are going to be placed in a table and some old compilers have trouble with ! 218: pointers to functions returning void. */ ! 219: ! 220: static int do_define (); ! 221: static int do_line (); ! 222: static int do_include (); ! 223: static int do_undef (); ! 224: static int do_error (); ! 225: static int do_pragma (); ! 226: static int do_ident (); ! 227: static int do_if (); ! 228: static int do_xifdef (); ! 229: static int do_else (); ! 230: static int do_elif (); ! 231: static int do_endif (); ! 232: static int do_sccs (); ! 233: static int do_once (); ! 234: static int do_assert (); ! 235: static int do_unassert (); ! 236: static int do_warning (); ! 237: ! 238: static void add_import (); ! 239: static void append_include_chain (); ! 240: static void deps_output (); ! 241: static void make_undef (); ! 242: static void make_definition (); ! 243: static void make_assertion (); ! 244: static void path_include (); ! 245: static void initialize_builtins (); ! 246: static void initialize_char_syntax (); ! 247: static void dump_arg_n (); ! 248: static void dump_defn_1 (); ! 249: static void delete_macro (); ! 250: static void trigraph_pcp (); ! 251: static void rescan (); ! 252: static void finclude (); ! 253: static void validate_else (); ! 254: static int comp_def_part (); ! 255: static void error_from_errno (); ! 256: static void error_with_line (); ! 257: void pedwarn (); ! 258: void pedwarn_with_line (); ! 259: static void pedwarn_with_file_and_line (); ! 260: static void fatal (); ! 261: void fancy_abort (); ! 262: static void pfatal_with_name (); ! 263: static void perror_with_name (); ! 264: static void pipe_closed (); ! 265: static void print_containing_files (); ! 266: static int lookup_import (); ! 267: static int redundant_include_p (); ! 268: static is_system_include (); ! 269: static int check_preconditions (); ! 270: static void pcfinclude (); ! 271: static void pcstring_used (); ! 272: static void write_output (); ! 273: static int check_macro_name (); ! 274: static int compare_defs (); ! 275: static int compare_token_lists (); ! 276: static int eval_if_expression (); ! 277: static int discard_comments (); ! 278: static int change_newlines (); ! 279: static int line_for_error (); ! 280: static int hashf (); ! 281: static int file_size_and_mode (); ! 282: ! 283: static struct arglist *read_token_list (); ! 284: static void free_token_list (); ! 285: ! 286: static struct hashnode *install (); ! 287: struct hashnode *lookup (); ! 288: ! 289: static struct assertion_hashnode *assertion_install (); ! 290: static struct assertion_hashnode *assertion_lookup (); ! 291: ! 292: static char *xrealloc (); ! 293: static char *xcalloc (); ! 294: static char *savestring (); ! 295: ! 296: static void delete_assertion (); ! 297: static void macroexpand (); ! 298: static void dump_all_macros (); ! 299: static void conditional_skip (); ! 300: static void skip_if_group (); ! 301: static void output_line_command (); ! 302: ! 303: #ifdef NEXT_SEMANTICS ! 304: /* convert rtf */ ! 305: static void buf_convert_rtf (); ! 306: static const char * rtf_to_ascii (); ! 307: #endif ! 308: ! 309: /* Last arg to output_line_command. */ ! 310: enum file_change_code {same_file, enter_file, leave_file}; ! 311: ! 312: static int grow_outbuf (); ! 313: static int handle_directive (); ! 314: static void memory_full (); ! 315: ! 316: static U_CHAR *macarg1 (); ! 317: static char *macarg (); ! 318: ! 319: static U_CHAR *skip_to_end_of_comment (); ! 320: static U_CHAR *skip_quoted_string (); ! 321: static U_CHAR *skip_paren_group (); ! 322: static char *quote_string (); ! 323: ! 324: static char *check_precompiled (); ! 325: /* static struct macrodef create_definition (); [moved below] */ ! 326: static void dump_single_macro (); ! 327: static void output_dots (); ! 328: ! 329: #ifndef FAILURE_EXIT_CODE ! 330: #define FAILURE_EXIT_CODE 33 /* gnu cc command understands this */ ! 331: #endif ! 332: ! 333: #ifndef SUCCESS_EXIT_CODE ! 334: #define SUCCESS_EXIT_CODE 0 /* 0 means success on Unix. */ ! 335: #endif ! 336: ! 337: /* Name under which this program was invoked. */ ! 338: ! 339: static char *progname; ! 340: ! 341: /* Nonzero means use extra default include directories for C++. */ ! 342: ! 343: static int cplusplus; ! 344: ! 345: /* Nonzero means handle cplusplus style comments */ ! 346: ! 347: static int cplusplus_comments; ! 348: ! 349: /* Nonzero means handle #import, for objective C. */ ! 350: ! 351: static int objc; ! 352: ! 353: /* Nonzero means this is an assembly file, and allow ! 354: unknown directives, which could be comments. */ ! 355: ! 356: static int lang_asm; ! 357: ! 358: /* Current maximum length of directory names in the search path ! 359: for include files. (Altered as we get more of them.) */ ! 360: ! 361: static int max_include_len; ! 362: ! 363: /* Nonzero means turn NOTREACHED into #pragma NOTREACHED etc */ ! 364: ! 365: static int lint = 0; ! 366: ! 367: /* Nonzero means copy comments into the output file. */ ! 368: ! 369: static int put_out_comments = 0; ! 370: ! 371: /* Nonzero means don't process the ANSI trigraph sequences. */ ! 372: ! 373: static int no_trigraphs = 0; ! 374: ! 375: /* Nonzero means print the names of included files rather than ! 376: the preprocessed output. 1 means just the #include "...", ! 377: 2 means #include <...> as well. */ ! 378: ! 379: static int print_deps = 0; ! 380: ! 381: /* Nonzero means print names of header files (-H). */ ! 382: ! 383: static int print_include_names = 0; ! 384: ! 385: /* Nonzero means don't output line number information. */ ! 386: ! 387: static int no_line_commands; ! 388: ! 389: /* dump_only means inhibit output of the preprocessed text ! 390: and instead output the definitions of all user-defined ! 391: macros in a form suitable for use as input to cccp. ! 392: dump_names means pass #define and the macro name through to output. ! 393: dump_definitions means pass the whole definition (plus #define) through ! 394: */ ! 395: ! 396: static enum {dump_none, dump_only, dump_names, dump_definitions} ! 397: dump_macros = dump_none; ! 398: ! 399: /* Nonzero means pass all #define and #undef directives which we actually ! 400: process through to the output stream. This feature is used primarily ! 401: to allow cc1 to record the #defines and #undefs for the sake of ! 402: debuggers which understand about preprocessor macros, but it may ! 403: also be useful with -E to figure out how symbols are defined, and ! 404: where they are defined. */ ! 405: static int debug_output = 0; ! 406: ! 407: /* Nonzero indicates special processing used by the pcp program. The ! 408: special effects of this mode are: ! 409: ! 410: Inhibit all macro expansion, except those inside #if directives. ! 411: ! 412: Process #define directives normally, and output their contents ! 413: to the output file. ! 414: ! 415: Output preconditions to pcp_outfile indicating all the relevant ! 416: preconditions for use of this file in a later cpp run. ! 417: */ ! 418: static FILE *pcp_outfile; ! 419: ! 420: /* Nonzero means we are inside an IF during a -pcp run. In this mode ! 421: macro expansion is done, and preconditions are output for all macro ! 422: uses requiring them. */ ! 423: static int pcp_inside_if; ! 424: ! 425: /* Nonzero means never to include precompiled files. ! 426: This is 1 since there's no way now to make precompiled files, ! 427: so it's not worth testing for them. */ ! 428: static int no_precomp = 1; ! 429: ! 430: /* Nonzero means give all the error messages the ANSI standard requires. */ ! 431: ! 432: int pedantic; ! 433: ! 434: /* Nonzero means try to make failure to fit ANSI C an error. */ ! 435: ! 436: static int pedantic_errors; ! 437: ! 438: /* Nonzero means don't print warning messages. -w. */ ! 439: ! 440: static int inhibit_warnings = 0; ! 441: ! 442: /* Nonzero means warn if slash-star appears in a comment. */ ! 443: ! 444: static int warn_comments; ! 445: ! 446: /* Nonzero means warn if a macro argument is (or would be) ! 447: stringified with -traditional. */ ! 448: ! 449: static int warn_stringify; ! 450: ! 451: /* Nonzero means warn if there are any trigraphs. */ ! 452: ! 453: static int warn_trigraphs; ! 454: ! 455: /* Nonzero means warn if #import is used. */ ! 456: ! 457: #ifdef NEXT_OBJC_RUNTIME ! 458: static int warn_import = 0; ! 459: #else ! 460: static int warn_import = 1; ! 461: #endif ! 462: ! 463: /* Nonzero means turn warnings into errors. */ ! 464: ! 465: static int warnings_are_errors; ! 466: ! 467: /* Nonzero means try to imitate old fashioned non-ANSI preprocessor. */ ! 468: ! 469: int traditional; ! 470: ! 471: /* Nonzero causes output not to be done, ! 472: but directives such as #define that have side effects ! 473: are still obeyed. */ ! 474: ! 475: static int no_output; ! 476: ! 477: #ifdef NEXT_SEMANTICS ! 478: /* Nonzero causes input not to have rtf codes stripped before ! 479: further processing. */ ! 480: ! 481: static int no_rtf = 0; ! 482: #endif ! 483: ! 484: /* Nonzero means that we have finished processing the command line options. ! 485: This flag is used to decide whether or not to issue certain errors ! 486: and/or warnings. */ ! 487: ! 488: static int done_initializing = 0; ! 489: ! 490: /* Line where a newline was first seen in a string constant. */ ! 491: ! 492: static int multiline_string_line = 0; ! 493: ! 494: /* I/O buffer structure. ! 495: The `fname' field is nonzero for source files and #include files ! 496: and for the dummy text used for -D and -U. ! 497: It is zero for rescanning results of macro expansion ! 498: and for expanding macro arguments. */ ! 499: #define INPUT_STACK_MAX 400 ! 500: static struct file_buf { ! 501: char *fname; ! 502: /* Filename specified with #line command. */ ! 503: char *nominal_fname; ! 504: /* Record where in the search path this file was found. ! 505: For #include_next. */ ! 506: struct file_name_list *dir; ! 507: int lineno; ! 508: int length; ! 509: U_CHAR *buf; ! 510: U_CHAR *bufp; ! 511: /* Macro that this level is the expansion of. ! 512: Included so that we can reenable the macro ! 513: at the end of this level. */ ! 514: struct hashnode *macro; ! 515: /* Value of if_stack at start of this file. ! 516: Used to prohibit unmatched #endif (etc) in an include file. */ ! 517: struct if_stack *if_stack; ! 518: /* Object to be freed at end of input at this level. */ ! 519: U_CHAR *free_ptr; ! 520: /* True if this is a header file included using <FILENAME>. */ ! 521: char system_header_p; ! 522: } instack[INPUT_STACK_MAX]; ! 523: ! 524: static int last_error_tick; /* Incremented each time we print it. */ ! 525: static int input_file_stack_tick; /* Incremented when the status changes. */ ! 526: ! 527: /* Current nesting level of input sources. ! 528: `instack[indepth]' is the level currently being read. */ ! 529: static int indepth = -1; ! 530: #define CHECK_DEPTH(code) \ ! 531: if (indepth >= (INPUT_STACK_MAX - 1)) \ ! 532: { \ ! 533: error_with_line (line_for_error (instack[indepth].lineno), \ ! 534: "macro or `#include' recursion too deep"); \ ! 535: code; \ ! 536: } ! 537: ! 538: /* Current depth in #include directives that use <...>. */ ! 539: static int system_include_depth = 0; ! 540: ! 541: typedef struct file_buf FILE_BUF; ! 542: ! 543: /* The output buffer. Its LENGTH field is the amount of room allocated ! 544: for the buffer, not the number of chars actually present. To get ! 545: that, subtract outbuf.buf from outbuf.bufp. */ ! 546: ! 547: #define OUTBUF_SIZE 10 /* initial size of output buffer */ ! 548: static FILE_BUF outbuf; ! 549: ! 550: /* Grow output buffer OBUF points at ! 551: so it can hold at least NEEDED more chars. */ ! 552: ! 553: #define check_expand(OBUF, NEEDED) \ ! 554: (((OBUF)->length - ((OBUF)->bufp - (OBUF)->buf) <= (NEEDED)) \ ! 555: ? grow_outbuf ((OBUF), (NEEDED)) : 0) ! 556: ! 557: struct file_name_list ! 558: { ! 559: struct file_name_list *next; ! 560: char *fname; ! 561: /* If the following is nonzero, it is a macro name. ! 562: Don't include the file again if that macro is defined. */ ! 563: U_CHAR *control_macro; ! 564: /* If the following is nonzero, it is a C-language system include ! 565: directory. */ ! 566: int c_system_include_path; ! 567: }; ! 568: ! 569: /* #include "file" looks in source file dir, then stack. */ ! 570: /* #include <file> just looks in the stack. */ ! 571: /* cplusplus = 0 -> C. cplusplus = 1 -> C++. cplusplus = 2 -> nothing */ ! 572: /* -I directories are added to the end, then the defaults are added. */ ! 573: static struct default_include { char *fname; int cplusplus; } include_defaults_array[] ! 574: #ifdef INCLUDE_DEFAULTS ! 575: = INCLUDE_DEFAULTS; ! 576: #else ! 577: = { ! 578: /* Pick up GNU C++ specific include files. */ ! 579: { GPLUSPLUS_INCLUDE_DIR, 1}, ! 580: #ifdef CROSS_COMPILE ! 581: /* This is the dir for fixincludes. Put it just before ! 582: the files that we fix. */ ! 583: { GCC_INCLUDE_DIR, 0}, ! 584: /* For cross-compilation, this dir name is generated ! 585: automatically in Makefile.in. */ ! 586: { CROSS_INCLUDE_DIR, 0 }, ! 587: /* This is another place that the target system's headers might be. */ ! 588: { TOOL_INCLUDE_DIR, 0}, ! 589: #else /* not CROSS_COMPILE */ ! 590: /* This should be /use/local/include and should come before ! 591: the fixincludes-fixed header files. */ ! 592: { LOCAL_INCLUDE_DIR, 0}, ! 593: /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here. ! 594: Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h. */ ! 595: { TOOL_INCLUDE_DIR, 0}, ! 596: /* This is the dir for fixincludes. Put it just before ! 597: the files that we fix. */ ! 598: { GCC_INCLUDE_DIR, 0}, ! 599: /* Some systems have an extra dir of include files. */ ! 600: #ifdef SYSTEM_INCLUDE_DIR ! 601: { SYSTEM_INCLUDE_DIR, 0}, ! 602: #endif ! 603: { STANDARD_INCLUDE_DIR, 0}, ! 604: #endif /* not CROSS_COMPILE */ ! 605: { 0, 0} ! 606: }; ! 607: #endif /* no INCLUDE_DEFAULTS */ ! 608: ! 609: /* The code looks at the defaults through this pointer, rather than through ! 610: the constant structure above. This pointer gets changed if an environment ! 611: variable specifies other defaults. */ ! 612: static struct default_include *include_defaults = include_defaults_array; ! 613: ! 614: static struct file_name_list *include = 0; /* First dir to search */ ! 615: /* First dir to search for <file> */ ! 616: /* This is the first element to use for #include <...>. ! 617: If it is 0, use the entire chain for such includes. */ ! 618: static struct file_name_list *first_bracket_include = 0; ! 619: /* This is the first element in the chain that corresponds to ! 620: a directory of system header files. */ ! 621: static struct file_name_list *first_system_include = 0; ! 622: static struct file_name_list *last_include = 0; /* Last in chain */ ! 623: ! 624: /* Chain of include directories to put at the end of the other chain. */ ! 625: static struct file_name_list *after_include = 0; ! 626: static struct file_name_list *last_after_include = 0; /* Last in chain */ ! 627: ! 628: /* List of included files that contained #pragma once. */ ! 629: static struct file_name_list *dont_repeat_files = 0; ! 630: ! 631: /* List of other included files. ! 632: If ->control_macro if nonzero, the file had a #ifndef ! 633: around the entire contents, and ->control_macro gives the macro name. */ ! 634: static struct file_name_list *all_include_files = 0; ! 635: ! 636: /* Directory prefix that should replace `/usr' in the standard ! 637: include file directories. */ ! 638: static char *include_prefix; ! 639: ! 640: /* Global list of strings read in from precompiled files. This list ! 641: is kept in the order the strings are read in, with new strings being ! 642: added at the end through stringlist_tailp. We use this list to output ! 643: the strings at the end of the run. ! 644: */ ! 645: static STRINGDEF *stringlist; ! 646: static STRINGDEF **stringlist_tailp = &stringlist; ! 647: ! 648: ! 649: /* Structure returned by create_definition */ ! 650: typedef struct macrodef MACRODEF; ! 651: struct macrodef ! 652: { ! 653: struct definition *defn; ! 654: U_CHAR *symnam; ! 655: int symlen; ! 656: }; ! 657: ! 658: static struct macrodef create_definition (); ! 659: ! 660: ! 661: /* Structure allocated for every #define. For a simple replacement ! 662: such as ! 663: #define foo bar , ! 664: nargs = -1, the `pattern' list is null, and the expansion is just ! 665: the replacement text. Nargs = 0 means a functionlike macro with no args, ! 666: e.g., ! 667: #define getchar() getc (stdin) . ! 668: When there are args, the expansion is the replacement text with the ! 669: args squashed out, and the reflist is a list describing how to ! 670: build the output from the input: e.g., "3 chars, then the 1st arg, ! 671: then 9 chars, then the 3rd arg, then 0 chars, then the 2nd arg". ! 672: The chars here come from the expansion. Whatever is left of the ! 673: expansion after the last arg-occurrence is copied after that arg. ! 674: Note that the reflist can be arbitrarily long--- ! 675: its length depends on the number of times the arguments appear in ! 676: the replacement text, not how many args there are. Example: ! 677: #define f(x) x+x+x+x+x+x+x would have replacement text "++++++" and ! 678: pattern list ! 679: { (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL } ! 680: where (x, y) means (nchars, argno). */ ! 681: ! 682: typedef struct definition DEFINITION; ! 683: struct definition { ! 684: int nargs; ! 685: int length; /* length of expansion string */ ! 686: int predefined; /* True if the macro was builtin or */ ! 687: /* came from the command line */ ! 688: U_CHAR *expansion; ! 689: int line; /* Line number of definition */ ! 690: char *file; /* File of definition */ ! 691: char rest_args; /* Nonzero if last arg. absorbs the rest */ ! 692: struct reflist { ! 693: struct reflist *next; ! 694: char stringify; /* nonzero if this arg was preceded by a ! 695: # operator. */ ! 696: char raw_before; /* Nonzero if a ## operator before arg. */ ! 697: char raw_after; /* Nonzero if a ## operator after arg. */ ! 698: char rest_args; /* Nonzero if this arg. absorbs the rest */ ! 699: int nchars; /* Number of literal chars to copy before ! 700: this arg occurrence. */ ! 701: int argno; /* Number of arg to substitute (origin-0) */ ! 702: } *pattern; ! 703: union { ! 704: /* Names of macro args, concatenated in reverse order ! 705: with comma-space between them. ! 706: The only use of this is that we warn on redefinition ! 707: if this differs between the old and new definitions. */ ! 708: U_CHAR *argnames; ! 709: } args; ! 710: }; ! 711: ! 712: /* different kinds of things that can appear in the value field ! 713: of a hash node. Actually, this may be useless now. */ ! 714: union hashval { ! 715: int ival; ! 716: char *cpval; ! 717: DEFINITION *defn; ! 718: KEYDEF *keydef; ! 719: }; ! 720: ! 721: /* ! 722: * special extension string that can be added to the last macro argument to ! 723: * allow it to absorb the "rest" of the arguments when expanded. Ex: ! 724: * #define wow(a, b...) process (b, a, b) ! 725: * { wow (1, 2, 3); } -> { process (2, 3, 1, 2, 3); } ! 726: * { wow (one, two); } -> { process (two, one, two); } ! 727: * if this "rest_arg" is used with the concat token '##' and if it is not ! 728: * supplied then the token attached to with ## will not be outputted. Ex: ! 729: * #define wow (a, b...) process (b ## , a, ## b) ! 730: * { wow (1, 2); } -> { process (2, 1, 2); } ! 731: * { wow (one); } -> { process (one); { ! 732: */ ! 733: static char rest_extension[] = "..."; ! 734: #define REST_EXTENSION_LENGTH (sizeof (rest_extension) - 1) ! 735: ! 736: /* The structure of a node in the hash table. The hash table ! 737: has entries for all tokens defined by #define commands (type T_MACRO), ! 738: plus some special tokens like __LINE__ (these each have their own ! 739: type, and the appropriate code is run when that type of node is seen. ! 740: It does not contain control words like "#define", which are recognized ! 741: by a separate piece of code. */ ! 742: ! 743: /* different flavors of hash nodes --- also used in keyword table */ ! 744: enum node_type { ! 745: T_DEFINE = 1, /* the `#define' keyword */ ! 746: T_INCLUDE, /* the `#include' keyword */ ! 747: T_INCLUDE_NEXT, /* the `#include_next' keyword */ ! 748: T_IMPORT, /* the `#import' keyword */ ! 749: T_IFDEF, /* the `#ifdef' keyword */ ! 750: T_IFNDEF, /* the `#ifndef' keyword */ ! 751: T_IF, /* the `#if' keyword */ ! 752: T_ELSE, /* `#else' */ ! 753: T_PRAGMA, /* `#pragma' */ ! 754: T_ELIF, /* `#elif' */ ! 755: T_UNDEF, /* `#undef' */ ! 756: T_LINE, /* `#line' */ ! 757: T_ERROR, /* `#error' */ ! 758: T_WARNING, /* `#warning' */ ! 759: T_ENDIF, /* `#endif' */ ! 760: T_SCCS, /* `#sccs', used on system V. */ ! 761: T_IDENT, /* `#ident', used on system V. */ ! 762: T_ASSERT, /* `#assert', taken from system V. */ ! 763: T_UNASSERT, /* `#unassert', taken from system V. */ ! 764: T_SPECLINE, /* special symbol `__LINE__' */ ! 765: T_DATE, /* `__DATE__' */ ! 766: T_FILE, /* `__FILE__' */ ! 767: T_BASE_FILE, /* `__BASE_FILE__' */ ! 768: T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */ ! 769: T_VERSION, /* `__VERSION__' */ ! 770: T_SIZE_TYPE, /* `__SIZE_TYPE__' */ ! 771: T_PTRDIFF_TYPE, /* `__PTRDIFF_TYPE__' */ ! 772: T_WCHAR_TYPE, /* `__WCHAR_TYPE__' */ ! 773: T_USER_LABEL_PREFIX_TYPE, /* `__USER_LABEL_PREFIX__' */ ! 774: T_REGISTER_PREFIX_TYPE, /* `__REGISTER_PREFIX__' */ ! 775: T_TIME, /* `__TIME__' */ ! 776: T_CONST, /* Constant value, used by `__STDC__' */ ! 777: T_MACRO, /* macro defined by `#define' */ ! 778: T_DISABLED, /* macro temporarily turned off for rescan */ ! 779: T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */ ! 780: T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */ ! 781: T_UNUSED /* Used for something not defined. */ ! 782: }; ! 783: ! 784: struct hashnode { ! 785: struct hashnode *next; /* double links for easy deletion */ ! 786: struct hashnode *prev; ! 787: struct hashnode **bucket_hdr; /* also, a back pointer to this node's hash ! 788: chain is kept, in case the node is the head ! 789: of the chain and gets deleted. */ ! 790: enum node_type type; /* type of special token */ ! 791: int length; /* length of token, for quick comparison */ ! 792: U_CHAR *name; /* the actual name */ ! 793: union hashval value; /* pointer to expansion, or whatever */ ! 794: }; ! 795: ! 796: typedef struct hashnode HASHNODE; ! 797: ! 798: /* Some definitions for the hash table. The hash function MUST be ! 799: computed as shown in hashf () below. That is because the rescan ! 800: loop computes the hash value `on the fly' for most tokens, ! 801: in order to avoid the overhead of a lot of procedure calls to ! 802: the hashf () function. Hashf () only exists for the sake of ! 803: politeness, for use when speed isn't so important. */ ! 804: ! 805: #define HASHSIZE 1403 ! 806: static HASHNODE *hashtab[HASHSIZE]; ! 807: #define HASHSTEP(old, c) ((old << 2) + c) ! 808: #define MAKE_POS(v) (v & 0x7fffffff) /* make number positive */ ! 809: ! 810: /* Symbols to predefine. */ ! 811: ! 812: #ifdef CPP_PREDEFINES ! 813: static char *predefs = CPP_PREDEFINES; ! 814: #else ! 815: static char *predefs = ""; ! 816: #endif ! 817: ! 818: /* We let tm.h override the types used here, to handle trivial differences ! 819: such as the choice of unsigned int or long unsigned int for size_t. ! 820: When machines start needing nontrivial differences in the size type, ! 821: it would be best to do something here to figure out automatically ! 822: from other information what type to use. */ ! 823: ! 824: /* The string value for __size_type__. */ ! 825: ! 826: #ifndef SIZE_TYPE ! 827: #define SIZE_TYPE "long unsigned int" ! 828: #endif ! 829: ! 830: /* The string value for __ptrdiff_type__. */ ! 831: ! 832: #ifndef PTRDIFF_TYPE ! 833: #define PTRDIFF_TYPE "long int" ! 834: #endif ! 835: ! 836: /* The string value for __wchar_type__. */ ! 837: ! 838: #ifndef WCHAR_TYPE ! 839: #define WCHAR_TYPE "int" ! 840: #endif ! 841: ! 842: /* The string value for __USER_LABEL_PREFIX__ */ ! 843: ! 844: #ifndef USER_LABEL_PREFIX ! 845: #define USER_LABEL_PREFIX "" ! 846: #endif ! 847: ! 848: /* The string value for __REGISTER_PREFIX__ */ ! 849: ! 850: #ifndef REGISTER_PREFIX ! 851: #define REGISTER_PREFIX "" ! 852: #endif ! 853: ! 854: /* In the definition of a #assert name, this structure forms ! 855: a list of the individual values asserted. ! 856: Each value is itself a list of "tokens". ! 857: These are strings that are compared by name. */ ! 858: ! 859: struct tokenlist_list { ! 860: struct tokenlist_list *next; ! 861: struct arglist *tokens; ! 862: }; ! 863: ! 864: struct assertion_hashnode { ! 865: struct assertion_hashnode *next; /* double links for easy deletion */ ! 866: struct assertion_hashnode *prev; ! 867: /* also, a back pointer to this node's hash ! 868: chain is kept, in case the node is the head ! 869: of the chain and gets deleted. */ ! 870: struct assertion_hashnode **bucket_hdr; ! 871: int length; /* length of token, for quick comparison */ ! 872: U_CHAR *name; /* the actual name */ ! 873: /* List of token-sequences. */ ! 874: struct tokenlist_list *value; ! 875: }; ! 876: ! 877: typedef struct assertion_hashnode ASSERTION_HASHNODE; ! 878: ! 879: /* Some definitions for the hash table. The hash function MUST be ! 880: computed as shown in hashf below. That is because the rescan ! 881: loop computes the hash value `on the fly' for most tokens, ! 882: in order to avoid the overhead of a lot of procedure calls to ! 883: the hashf function. hashf only exists for the sake of ! 884: politeness, for use when speed isn't so important. */ ! 885: ! 886: #define ASSERTION_HASHSIZE 37 ! 887: static ASSERTION_HASHNODE *assertion_hashtab[ASSERTION_HASHSIZE]; ! 888: ! 889: /* Nonzero means inhibit macroexpansion of what seem to be ! 890: assertion tests, in rescan. For #if. */ ! 891: static int assertions_flag; ! 892: ! 893: /* `struct directive' defines one #-directive, including how to handle it. */ ! 894: ! 895: struct directive { ! 896: int length; /* Length of name */ ! 897: int (*func)(); /* Function to handle directive */ ! 898: char *name; /* Name of directive */ ! 899: enum node_type type; /* Code which describes which directive. */ ! 900: char angle_brackets; /* Nonzero => <...> is special. */ ! 901: char traditional_comments; /* Nonzero: keep comments if -traditional. */ ! 902: char pass_thru; /* Copy preprocessed directive to output file. */ ! 903: }; ! 904: ! 905: /* Here is the actual list of #-directives, most-often-used first. */ ! 906: ! 907: static struct directive directive_table[] = { ! 908: { 6, do_define, "define", T_DEFINE, 0, 1}, ! 909: { 2, do_if, "if", T_IF}, ! 910: { 5, do_xifdef, "ifdef", T_IFDEF}, ! 911: { 6, do_xifdef, "ifndef", T_IFNDEF}, ! 912: { 5, do_endif, "endif", T_ENDIF}, ! 913: { 4, do_else, "else", T_ELSE}, ! 914: { 4, do_elif, "elif", T_ELIF}, ! 915: { 4, do_line, "line", T_LINE}, ! 916: { 7, do_include, "include", T_INCLUDE, 1}, ! 917: { 12, do_include, "include_next", T_INCLUDE_NEXT, 1}, ! 918: { 6, do_include, "import", T_IMPORT, 1}, ! 919: { 5, do_undef, "undef", T_UNDEF}, ! 920: { 5, do_error, "error", T_ERROR}, ! 921: { 7, do_warning, "warning", T_WARNING}, ! 922: #ifdef SCCS_DIRECTIVE ! 923: { 4, do_sccs, "sccs", T_SCCS}, ! 924: #endif ! 925: { 6, do_pragma, "pragma", T_PRAGMA, 0, 0, 1}, ! 926: { 5, do_ident, "ident", T_IDENT}, ! 927: { 6, do_assert, "assert", T_ASSERT}, ! 928: { 8, do_unassert, "unassert", T_UNASSERT}, ! 929: { -1, 0, "", T_UNUSED}, ! 930: }; ! 931: ! 932: /* When a directive handler is called, ! 933: this points to the # that started the directive. */ ! 934: U_CHAR *directive_start; ! 935: ! 936: /* table to tell if char can be part of a C identifier. */ ! 937: U_CHAR is_idchar[256]; ! 938: /* table to tell if char can be first char of a c identifier. */ ! 939: U_CHAR is_idstart[256]; ! 940: /* table to tell if c is horizontal space. */ ! 941: U_CHAR is_hor_space[256]; ! 942: /* table to tell if c is horizontal or vertical space. */ ! 943: static U_CHAR is_space[256]; ! 944: ! 945: #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0) ! 946: #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0) ! 947: ! 948: static int errors = 0; /* Error counter for exit code */ ! 949: ! 950: /* Name of output file, for error messages. */ ! 951: static char *out_fname; ! 952: ! 953: /* Zero means dollar signs are punctuation. ! 954: -$ stores 0; -traditional may store 1. Default is 1 for VMS, 0 otherwise. ! 955: This must be 0 for correct processing of this ANSI C program: ! 956: #define foo(a) #a ! 957: #define lose(b) foo (b) ! 958: #define test$ ! 959: lose (test) */ ! 960: static int dollars_in_ident; ! 961: #ifndef DOLLARS_IN_IDENTIFIERS ! 962: #define DOLLARS_IN_IDENTIFIERS 1 ! 963: #endif ! 964: ! 965: static FILE_BUF expand_to_temp_buffer (); ! 966: ! 967: static DEFINITION *collect_expansion (); ! 968: ! 969: /* Stack of conditionals currently in progress ! 970: (including both successful and failing conditionals). */ ! 971: ! 972: struct if_stack { ! 973: struct if_stack *next; /* for chaining to the next stack frame */ ! 974: char *fname; /* copied from input when frame is made */ ! 975: int lineno; /* similarly */ ! 976: int if_succeeded; /* true if a leg of this if-group ! 977: has been passed through rescan */ ! 978: U_CHAR *control_macro; /* For #ifndef at start of file, ! 979: this is the macro name tested. */ ! 980: enum node_type type; /* type of last directive seen in this group */ ! 981: }; ! 982: typedef struct if_stack IF_STACK_FRAME; ! 983: static IF_STACK_FRAME *if_stack = NULL; ! 984: ! 985: /* Buffer of -M output. */ ! 986: static char *deps_buffer; ! 987: ! 988: /* Number of bytes allocated in above. */ ! 989: static int deps_allocated_size; ! 990: ! 991: /* Number of bytes used. */ ! 992: static int deps_size; ! 993: ! 994: /* Number of bytes since the last newline. */ ! 995: static int deps_column; ! 996: ! 997: /* Nonzero means -I- has been seen, ! 998: so don't look for #include "foo" the source-file directory. */ ! 999: static int ignore_srcdir; ! 1000: ! 1001: /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME, ! 1002: retrying if necessary. Return the actual number of bytes read. */ ! 1003: ! 1004: static int ! 1005: safe_read (desc, ptr, len) ! 1006: int desc; ! 1007: char *ptr; ! 1008: int len; ! 1009: { ! 1010: int left = len; ! 1011: while (left > 0) { ! 1012: int nchars = read (desc, ptr, left); ! 1013: if (nchars < 0) ! 1014: { ! 1015: #ifdef EINTR ! 1016: if (errno == EINTR) ! 1017: continue; ! 1018: #endif ! 1019: return nchars; ! 1020: } ! 1021: if (nchars == 0) ! 1022: break; ! 1023: ptr += nchars; ! 1024: left -= nchars; ! 1025: } ! 1026: return len - left; ! 1027: } ! 1028: ! 1029: /* Write LEN bytes at PTR to descriptor DESC, ! 1030: retrying if necessary, and treating any real error as fatal. */ ! 1031: ! 1032: static void ! 1033: safe_write (desc, ptr, len) ! 1034: int desc; ! 1035: char *ptr; ! 1036: int len; ! 1037: { ! 1038: while (len > 0) { ! 1039: int written = write (desc, ptr, len); ! 1040: if (written < 0) ! 1041: { ! 1042: #ifdef EINTR ! 1043: if (errno == EINTR) ! 1044: continue; ! 1045: #endif ! 1046: pfatal_with_name (out_fname); ! 1047: } ! 1048: ptr += written; ! 1049: len -= written; ! 1050: } ! 1051: } ! 1052: ! 1053: int ! 1054: main (argc, argv) ! 1055: int argc; ! 1056: char **argv; ! 1057: { ! 1058: int st_mode; ! 1059: long st_size; ! 1060: char *in_fname; ! 1061: char *p; ! 1062: int f, i; ! 1063: FILE_BUF *fp; ! 1064: char **pend_files = (char **) xmalloc (argc * sizeof (char *)); ! 1065: char **pend_defs = (char **) xmalloc (argc * sizeof (char *)); ! 1066: char **pend_undefs = (char **) xmalloc (argc * sizeof (char *)); ! 1067: char **pend_assertions = (char **) xmalloc (argc * sizeof (char *)); ! 1068: char **pend_includes = (char **) xmalloc (argc * sizeof (char *)); ! 1069: ! 1070: /* Record the option used with each element of pend_assertions. ! 1071: This is preparation for supporting more than one option for making ! 1072: an assertion. */ ! 1073: char **pend_assertion_options = (char **) xmalloc (argc * sizeof (char *)); ! 1074: int inhibit_predefs = 0; ! 1075: int no_standard_includes = 0; ! 1076: int no_standard_cplusplus_includes = 0; ! 1077: int missing_newline = 0; ! 1078: ! 1079: /* Non-0 means don't output the preprocessed program. */ ! 1080: int inhibit_output = 0; ! 1081: /* Non-0 means -v, so print the full set of include dirs. */ ! 1082: int verbose = 0; ! 1083: ! 1084: /* File name which deps are being written to. ! 1085: This is 0 if deps are being written to stdout. */ ! 1086: char *deps_file = 0; ! 1087: /* Fopen file mode to open deps_file with. */ ! 1088: char *deps_mode = "a"; ! 1089: /* Stream on which to print the dependency information. */ ! 1090: FILE *deps_stream = 0; ! 1091: /* Target-name to write with the dependency information. */ ! 1092: char *deps_target = 0; ! 1093: ! 1094: #ifdef RLIMIT_STACK ! 1095: /* Get rid of any avoidable limit on stack size. */ ! 1096: { ! 1097: struct rlimit rlim; ! 1098: ! 1099: /* Set the stack limit huge so that alloca (particularly stringtab ! 1100: * in dbxread.c) does not fail. */ ! 1101: getrlimit (RLIMIT_STACK, &rlim); ! 1102: rlim.rlim_cur = rlim.rlim_max; ! 1103: setrlimit (RLIMIT_STACK, &rlim); ! 1104: } ! 1105: #endif /* RLIMIT_STACK defined */ ! 1106: ! 1107: #ifdef SIGPIPE ! 1108: signal (SIGPIPE, pipe_closed); ! 1109: #endif ! 1110: ! 1111: p = argv[0] + strlen (argv[0]); ! 1112: while (p != argv[0] && p[-1] != '/') --p; ! 1113: progname = p; ! 1114: ! 1115: #ifdef VMS ! 1116: { ! 1117: /* Remove directories from PROGNAME. */ ! 1118: char *s; ! 1119: ! 1120: progname = savestring (argv[0]); ! 1121: ! 1122: if (!(s = rindex (progname, ']'))) ! 1123: s = rindex (progname, ':'); ! 1124: if (s) ! 1125: strcpy (progname, s+1); ! 1126: if (s = rindex (progname, '.')) ! 1127: *s = '\0'; ! 1128: } ! 1129: #endif ! 1130: ! 1131: in_fname = NULL; ! 1132: out_fname = NULL; ! 1133: ! 1134: /* Initialize is_idchar to allow $. */ ! 1135: dollars_in_ident = 1; ! 1136: initialize_char_syntax (); ! 1137: dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 0; ! 1138: ! 1139: no_line_commands = 0; ! 1140: no_trigraphs = 1; ! 1141: dump_macros = dump_none; ! 1142: no_output = 0; ! 1143: cplusplus = 0; ! 1144: #ifdef NeXT ! 1145: cplusplus_comments = 1; ! 1146: #else ! 1147: cplusplus_comments = 0; ! 1148: #endif ! 1149: ! 1150: bzero (pend_files, argc * sizeof (char *)); ! 1151: bzero (pend_defs, argc * sizeof (char *)); ! 1152: bzero (pend_undefs, argc * sizeof (char *)); ! 1153: bzero (pend_assertions, argc * sizeof (char *)); ! 1154: bzero (pend_includes, argc * sizeof (char *)); ! 1155: ! 1156: /* Process switches and find input file name. */ ! 1157: ! 1158: for (i = 1; i < argc; i++) { ! 1159: if (argv[i][0] != '-') { ! 1160: if (out_fname != NULL) ! 1161: fatal ("Usage: %s [switches] input output", argv[0]); ! 1162: else if (in_fname != NULL) ! 1163: out_fname = argv[i]; ! 1164: else ! 1165: in_fname = argv[i]; ! 1166: } else { ! 1167: switch (argv[i][1]) { ! 1168: #ifdef NeXT ! 1169: case 'a': ! 1170: if (!strcmp (argv[i], "-arch")) /* ignore -arch <archname> */ ! 1171: i++; ! 1172: break; ! 1173: #endif ! 1174: ! 1175: case 'c': ! 1176: if (! strcmp (argv[i], "-c++-comments")) ! 1177: cplusplus_comments = 1; ! 1178: break; ! 1179: ! 1180: case 'i': ! 1181: if (!strcmp (argv[i], "-include")) { ! 1182: if (i + 1 == argc) ! 1183: fatal ("Filename missing after `-include' option"); ! 1184: else ! 1185: pend_includes[i] = argv[i+1], i++; ! 1186: } ! 1187: else if (!strcmp (argv[i], "-imacros")) { ! 1188: if (i + 1 == argc) ! 1189: fatal ("Filename missing after `-imacros' option"); ! 1190: else ! 1191: pend_files[i] = argv[i+1], i++; ! 1192: } ! 1193: else if (!strcmp (argv[i], "-iprefix")) { ! 1194: if (i + 1 == argc) ! 1195: fatal ("Filename missing after `-iprefix' option"); ! 1196: else ! 1197: include_prefix = argv[++i]; ! 1198: } ! 1199: /* Add directory to end of path for includes, ! 1200: with the default prefix at the front of its name. */ ! 1201: else if (!strcmp (argv[i], "-iwithprefix")) { ! 1202: struct file_name_list *dirtmp; ! 1203: char *prefix; ! 1204: ! 1205: if (include_prefix != 0) ! 1206: prefix = include_prefix; ! 1207: else { ! 1208: prefix = savestring (GCC_INCLUDE_DIR); ! 1209: /* Remove the `include' from /usr/local/lib/gcc.../include. */ ! 1210: if (!strcmp (prefix + strlen (prefix) - 8, "/include")) ! 1211: prefix[strlen (prefix) - 7] = 0; ! 1212: } ! 1213: ! 1214: dirtmp = (struct file_name_list *) ! 1215: xmalloc (sizeof (struct file_name_list)); ! 1216: dirtmp->next = 0; /* New one goes on the end */ ! 1217: dirtmp->control_macro = 0; ! 1218: dirtmp->c_system_include_path = 0; ! 1219: if (i + 1 == argc) ! 1220: fatal ("Directory name missing after `-iwithprefix' option"); ! 1221: ! 1222: dirtmp->fname = (char *) xmalloc (strlen (argv[i+1]) ! 1223: + strlen (prefix) + 1); ! 1224: strcpy (dirtmp->fname, prefix); ! 1225: strcat (dirtmp->fname, argv[++i]); ! 1226: ! 1227: if (after_include == 0) ! 1228: after_include = dirtmp; ! 1229: else ! 1230: last_after_include->next = dirtmp; ! 1231: last_after_include = dirtmp; /* Tail follows the last one */ ! 1232: } ! 1233: /* Add directory to main path for includes, ! 1234: with the default prefix at the front of its name. */ ! 1235: else if (!strcmp (argv[i], "-iwithprefixbefore")) { ! 1236: struct file_name_list *dirtmp; ! 1237: char *prefix; ! 1238: ! 1239: if (include_prefix != 0) ! 1240: prefix = include_prefix; ! 1241: else { ! 1242: prefix = savestring (GCC_INCLUDE_DIR); ! 1243: /* Remove the `include' from /usr/local/lib/gcc.../include. */ ! 1244: if (!strcmp (prefix + strlen (prefix) - 8, "/include")) ! 1245: prefix[strlen (prefix) - 7] = 0; ! 1246: } ! 1247: ! 1248: dirtmp = (struct file_name_list *) ! 1249: xmalloc (sizeof (struct file_name_list)); ! 1250: dirtmp->next = 0; /* New one goes on the end */ ! 1251: dirtmp->control_macro = 0; ! 1252: dirtmp->c_system_include_path = 0; ! 1253: if (i + 1 == argc) ! 1254: fatal ("Directory name missing after `-iwithprefixbefore' option"); ! 1255: ! 1256: dirtmp->fname = (char *) xmalloc (strlen (argv[i+1]) ! 1257: + strlen (prefix) + 1); ! 1258: strcpy (dirtmp->fname, prefix); ! 1259: strcat (dirtmp->fname, argv[++i]); ! 1260: ! 1261: append_include_chain (dirtmp, dirtmp); ! 1262: } ! 1263: /* Add directory to end of path for includes. */ ! 1264: else if (!strcmp (argv[i], "-idirafter")) { ! 1265: struct file_name_list *dirtmp; ! 1266: ! 1267: dirtmp = (struct file_name_list *) ! 1268: xmalloc (sizeof (struct file_name_list)); ! 1269: dirtmp->next = 0; /* New one goes on the end */ ! 1270: dirtmp->control_macro = 0; ! 1271: dirtmp->c_system_include_path = 0; ! 1272: if (i + 1 == argc) ! 1273: fatal ("Directory name missing after `-idirafter' option"); ! 1274: else ! 1275: dirtmp->fname = argv[++i]; ! 1276: ! 1277: if (after_include == 0) ! 1278: after_include = dirtmp; ! 1279: else ! 1280: last_after_include->next = dirtmp; ! 1281: last_after_include = dirtmp; /* Tail follows the last one */ ! 1282: } ! 1283: #ifdef NEXT_OBJC_RUNTIME ! 1284: else if (argv[i][2] != 0) ! 1285: pend_files[i] = argv[i] + 2; ! 1286: else if (i + 1 == argc) ! 1287: fatal ("Filename missing after -i option"); ! 1288: else ! 1289: pend_files[i] = argv[i+1], i++; ! 1290: #endif ! 1291: break; ! 1292: ! 1293: case 'o': ! 1294: if (out_fname != NULL) ! 1295: fatal ("Output filename specified twice"); ! 1296: if (i + 1 == argc) ! 1297: fatal ("Filename missing after -o option"); ! 1298: out_fname = argv[++i]; ! 1299: if (!strcmp (out_fname, "-")) ! 1300: out_fname = ""; ! 1301: break; ! 1302: ! 1303: case 'p': ! 1304: if (!strcmp (argv[i], "-pedantic")) ! 1305: pedantic = 1; ! 1306: else if (!strcmp (argv[i], "-pedantic-errors")) { ! 1307: pedantic = 1; ! 1308: pedantic_errors = 1; ! 1309: } else if (!strcmp (argv[i], "-pcp")) { ! 1310: char *pcp_fname = argv[++i]; ! 1311: pcp_outfile = ! 1312: ((pcp_fname[0] != '-' || pcp_fname[1] != '\0') ! 1313: ? fopen (pcp_fname, "w") ! 1314: : fdopen (dup (fileno (stdout)), "w")); ! 1315: if (pcp_outfile == 0) ! 1316: pfatal_with_name (pcp_fname); ! 1317: no_precomp = 1; ! 1318: } ! 1319: break; ! 1320: ! 1321: case 't': ! 1322: if (!strcmp (argv[i], "-traditional")) { ! 1323: traditional = 1; ! 1324: if (dollars_in_ident > 0) ! 1325: dollars_in_ident = 1; ! 1326: } else if (!strcmp (argv[i], "-trigraphs")) { ! 1327: no_trigraphs = 0; ! 1328: } ! 1329: break; ! 1330: ! 1331: #ifdef NeXT ! 1332: case 's': ! 1333: if (!strcmp (argv[i], "-smart")) ! 1334: /* ignore */; ! 1335: break; ! 1336: #endif ! 1337: ! 1338: case 'l': ! 1339: if (! strcmp (argv[i], "-lang-c")) ! 1340: cplusplus = 0, objc = 0; ! 1341: if (! strcmp (argv[i], "-lang-c++")) ! 1342: cplusplus = 1, cplusplus_comments = 1, objc = 0; ! 1343: if (! strcmp (argv[i], "-lang-objc")) ! 1344: objc = 1, cplusplus_comments = 1, cplusplus = 0; ! 1345: if (! strcmp (argv[i], "-lang-objc++")) ! 1346: objc = 1, cplusplus_comments = 1, cplusplus = 1; ! 1347: if (! strcmp (argv[i], "-lang-asm")) ! 1348: lang_asm = 1; ! 1349: if (! strcmp (argv[i], "-lint")) ! 1350: lint = 1; ! 1351: break; ! 1352: ! 1353: case '+': ! 1354: cplusplus = 1, cplusplus_comments = 1; ! 1355: break; ! 1356: ! 1357: case 'w': ! 1358: inhibit_warnings = 1; ! 1359: break; ! 1360: ! 1361: case 'W': ! 1362: if (!strcmp (argv[i], "-Wtrigraphs")) ! 1363: warn_trigraphs = 1; ! 1364: else if (!strcmp (argv[i], "-Wno-trigraphs")) ! 1365: warn_trigraphs = 0; ! 1366: else if (!strcmp (argv[i], "-Wcomment")) ! 1367: warn_comments = 1; ! 1368: else if (!strcmp (argv[i], "-Wno-comment")) ! 1369: warn_comments = 0; ! 1370: else if (!strcmp (argv[i], "-Wcomments")) ! 1371: warn_comments = 1; ! 1372: else if (!strcmp (argv[i], "-Wno-comments")) ! 1373: warn_comments = 0; ! 1374: else if (!strcmp (argv[i], "-Wtraditional")) ! 1375: warn_stringify = 1; ! 1376: else if (!strcmp (argv[i], "-Wno-traditional")) ! 1377: warn_stringify = 0; ! 1378: else if (!strcmp (argv[i], "-Wimport")) ! 1379: warn_import = 1; ! 1380: else if (!strcmp (argv[i], "-Wno-import")) ! 1381: warn_import = 0; ! 1382: else if (!strcmp (argv[i], "-Werror")) ! 1383: warnings_are_errors = 1; ! 1384: else if (!strcmp (argv[i], "-Wno-error")) ! 1385: warnings_are_errors = 0; ! 1386: else if (!strcmp (argv[i], "-Wall")) ! 1387: { ! 1388: warn_trigraphs = 1; ! 1389: warn_comments = 1; ! 1390: } ! 1391: break; ! 1392: ! 1393: case 'M': ! 1394: if (!strcmp (argv[i], "-M")) ! 1395: print_deps = 2; ! 1396: else if (!strcmp (argv[i], "-MM")) ! 1397: print_deps = 1; ! 1398: else if (!strcmp (argv[i], "-MD")) ! 1399: print_deps = 2; ! 1400: else if (!strcmp (argv[i], "-MMD")) ! 1401: print_deps = 1; ! 1402: /* For -MD and -MMD options, write deps on file named by next arg. */ ! 1403: if (!strcmp (argv[i], "-MD") ! 1404: || !strcmp (argv[i], "-MMD")) { ! 1405: i++; ! 1406: deps_file = argv[i]; ! 1407: deps_mode = "w"; ! 1408: } else { ! 1409: /* For -M and -MM, write deps on standard output ! 1410: and suppress the usual output. */ ! 1411: deps_stream = stdout; ! 1412: inhibit_output = 1; ! 1413: } ! 1414: break; ! 1415: ! 1416: case 'd': ! 1417: { ! 1418: char *p = argv[i] + 2; ! 1419: char c; ! 1420: while (c = *p++) { ! 1421: /* Arg to -d specifies what parts of macros to dump */ ! 1422: switch (c) { ! 1423: case 'M': ! 1424: dump_macros = dump_only; ! 1425: no_output = 1; ! 1426: break; ! 1427: case 'N': ! 1428: dump_macros = dump_names; ! 1429: break; ! 1430: case 'D': ! 1431: dump_macros = dump_definitions; ! 1432: break; ! 1433: } ! 1434: } ! 1435: } ! 1436: break; ! 1437: ! 1438: case 'g': ! 1439: if (argv[i][2] == '3') ! 1440: debug_output = 1; ! 1441: break; ! 1442: ! 1443: case 'v': ! 1444: fprintf (stderr, "GNU CPP version %s", version_string); ! 1445: #ifdef TARGET_VERSION ! 1446: TARGET_VERSION; ! 1447: #endif ! 1448: fprintf (stderr, "\n"); ! 1449: verbose = 1; ! 1450: break; ! 1451: ! 1452: case 'H': ! 1453: print_include_names = 1; ! 1454: break; ! 1455: ! 1456: case 'D': ! 1457: { ! 1458: char *p, *p1; ! 1459: ! 1460: if (argv[i][2] != 0) ! 1461: p = argv[i] + 2; ! 1462: else if (i + 1 == argc) ! 1463: fatal ("Macro name missing after -D option"); ! 1464: else ! 1465: p = argv[++i]; ! 1466: ! 1467: pend_defs[i] = p; ! 1468: } ! 1469: break; ! 1470: ! 1471: case 'A': ! 1472: { ! 1473: char *p, *p1; ! 1474: ! 1475: if (argv[i][2] != 0) ! 1476: p = argv[i] + 2; ! 1477: else if (i + 1 == argc) ! 1478: fatal ("Assertion missing after -A option"); ! 1479: else ! 1480: p = argv[++i]; ! 1481: ! 1482: if (!strcmp (p, "-")) { ! 1483: /* -A- eliminates all predefined macros and assertions. ! 1484: Let's include also any that were specified earlier ! 1485: on the command line. That way we can get rid of any ! 1486: that were passed automatically in from GCC. */ ! 1487: int j; ! 1488: inhibit_predefs = 1; ! 1489: for (j = 0; j < i; j++) ! 1490: pend_defs[j] = pend_assertions[j] = 0; ! 1491: } else { ! 1492: pend_assertions[i] = p; ! 1493: pend_assertion_options[i] = "-A"; ! 1494: } ! 1495: } ! 1496: break; ! 1497: ! 1498: case 'U': /* JF #undef something */ ! 1499: if (argv[i][2] != 0) ! 1500: pend_undefs[i] = argv[i] + 2; ! 1501: else if (i + 1 == argc) ! 1502: fatal ("Macro name missing after -U option"); ! 1503: else ! 1504: pend_undefs[i] = argv[i+1], i++; ! 1505: break; ! 1506: ! 1507: case 'C': ! 1508: put_out_comments = 1; ! 1509: break; ! 1510: ! 1511: case 'E': /* -E comes from cc -E; ignore it. */ ! 1512: break; ! 1513: ! 1514: case 'P': ! 1515: no_line_commands = 1; ! 1516: break; ! 1517: ! 1518: case '$': /* Don't include $ in identifiers. */ ! 1519: dollars_in_ident = 0; ! 1520: break; ! 1521: ! 1522: case 'I': /* Add directory to path for includes. */ ! 1523: { ! 1524: struct file_name_list *dirtmp; ! 1525: ! 1526: if (! ignore_srcdir && !strcmp (argv[i] + 2, "-")) { ! 1527: ignore_srcdir = 1; ! 1528: /* Don't use any preceding -I directories for #include <...>. */ ! 1529: first_bracket_include = 0; ! 1530: } ! 1531: else { ! 1532: dirtmp = (struct file_name_list *) ! 1533: xmalloc (sizeof (struct file_name_list)); ! 1534: dirtmp->next = 0; /* New one goes on the end */ ! 1535: dirtmp->control_macro = 0; ! 1536: dirtmp->c_system_include_path = 0; ! 1537: if (argv[i][2] != 0) ! 1538: dirtmp->fname = argv[i] + 2; ! 1539: else if (i + 1 == argc) ! 1540: fatal ("Directory name missing after -I option"); ! 1541: else ! 1542: dirtmp->fname = argv[++i]; ! 1543: append_include_chain (dirtmp, dirtmp); ! 1544: } ! 1545: } ! 1546: break; ! 1547: ! 1548: case 'n': ! 1549: if (!strcmp (argv[i], "-nostdinc")) ! 1550: /* -nostdinc causes no default include directories. ! 1551: You must specify all include-file directories with -I. */ ! 1552: no_standard_includes = 1; ! 1553: else if (!strcmp (argv[i], "-nostdinc++")) ! 1554: /* -nostdinc++ causes no default C++-specific include directories. */ ! 1555: no_standard_cplusplus_includes = 1; ! 1556: else if (!strcmp (argv[i], "-noprecomp")) ! 1557: no_precomp = 1; ! 1558: if (!strcmp (argv[i], "-no-c++-comments")) ! 1559: cplusplus_comments = 0; ! 1560: break; ! 1561: ! 1562: break; ! 1563: ! 1564: case 'u': ! 1565: /* Sun compiler passes undocumented switch "-undef". ! 1566: Let's assume it means to inhibit the predefined symbols. */ ! 1567: inhibit_predefs = 1; ! 1568: break; ! 1569: ! 1570: case '\0': /* JF handle '-' as file name meaning stdin or stdout */ ! 1571: if (in_fname == NULL) { ! 1572: in_fname = ""; ! 1573: break; ! 1574: } else if (out_fname == NULL) { ! 1575: out_fname = ""; ! 1576: break; ! 1577: } /* else fall through into error */ ! 1578: ! 1579: default: ! 1580: fatal ("Invalid option `%s'", argv[i]); ! 1581: } ! 1582: } ! 1583: } ! 1584: ! 1585: /* Add dirs from CPATH after dirs from -I. */ ! 1586: /* There seems to be confusion about what CPATH should do, ! 1587: so for the moment it is not documented. */ ! 1588: /* Some people say that CPATH should replace the standard include dirs, ! 1589: but that seems pointless: it comes before them, so it overrides them ! 1590: anyway. */ ! 1591: p = (char *) getenv ("CPATH"); ! 1592: if (p != 0 && ! no_standard_includes) ! 1593: path_include (p); ! 1594: ! 1595: /* Now that dollars_in_ident is known, initialize is_idchar. */ ! 1596: initialize_char_syntax (); ! 1597: ! 1598: /* Initialize output buffer */ ! 1599: ! 1600: outbuf.buf = (U_CHAR *) xmalloc (OUTBUF_SIZE); ! 1601: outbuf.bufp = outbuf.buf; ! 1602: outbuf.length = OUTBUF_SIZE; ! 1603: ! 1604: /* Do partial setup of input buffer for the sake of generating ! 1605: early #line directives (when -g is in effect). */ ! 1606: ! 1607: fp = &instack[++indepth]; ! 1608: if (in_fname == NULL) ! 1609: in_fname = ""; ! 1610: fp->nominal_fname = fp->fname = in_fname; ! 1611: fp->lineno = 0; ! 1612: ! 1613: /* Install __LINE__, etc. Must follow initialize_char_syntax ! 1614: and option processing. */ ! 1615: initialize_builtins (fp, &outbuf); ! 1616: ! 1617: /* Do standard #defines and assertions ! 1618: that identify system and machine type. */ ! 1619: ! 1620: if (!inhibit_predefs) { ! 1621: char *p = (char *) alloca (strlen (predefs) + 1); ! 1622: strcpy (p, predefs); ! 1623: while (*p) { ! 1624: char *q; ! 1625: while (*p == ' ' || *p == '\t') ! 1626: p++; ! 1627: /* Handle -D options. */ ! 1628: if (p[0] == '-' && p[1] == 'D') { ! 1629: q = &p[2]; ! 1630: while (*p && *p != ' ' && *p != '\t') ! 1631: p++; ! 1632: if (*p != 0) ! 1633: *p++= 0; ! 1634: if (debug_output) ! 1635: output_line_command (fp, &outbuf, 0, same_file); ! 1636: make_definition (q, &outbuf); ! 1637: while (*p == ' ' || *p == '\t') ! 1638: p++; ! 1639: } else if (p[0] == '-' && p[1] == 'A') { ! 1640: /* Handle -A options (assertions). */ ! 1641: char *assertion; ! 1642: char *past_name; ! 1643: char *value; ! 1644: char *past_value; ! 1645: char *termination; ! 1646: int save_char; ! 1647: ! 1648: assertion = &p[2]; ! 1649: past_name = assertion; ! 1650: /* Locate end of name. */ ! 1651: while (*past_name && *past_name != ' ' ! 1652: && *past_name != '\t' && *past_name != '(') ! 1653: past_name++; ! 1654: /* Locate `(' at start of value. */ ! 1655: value = past_name; ! 1656: while (*value && (*value == ' ' || *value == '\t')) ! 1657: value++; ! 1658: if (*value++ != '(') ! 1659: abort (); ! 1660: while (*value && (*value == ' ' || *value == '\t')) ! 1661: value++; ! 1662: past_value = value; ! 1663: /* Locate end of value. */ ! 1664: while (*past_value && *past_value != ' ' ! 1665: && *past_value != '\t' && *past_value != ')') ! 1666: past_value++; ! 1667: termination = past_value; ! 1668: while (*termination && (*termination == ' ' || *termination == '\t')) ! 1669: termination++; ! 1670: if (*termination++ != ')') ! 1671: abort (); ! 1672: if (*termination && *termination != ' ' && *termination != '\t') ! 1673: abort (); ! 1674: /* Temporarily null-terminate the value. */ ! 1675: save_char = *termination; ! 1676: *termination = '\0'; ! 1677: /* Install the assertion. */ ! 1678: make_assertion ("-A", assertion); ! 1679: *termination = (char) save_char; ! 1680: p = termination; ! 1681: while (*p == ' ' || *p == '\t') ! 1682: p++; ! 1683: } else { ! 1684: abort (); ! 1685: } ! 1686: } ! 1687: } ! 1688: ! 1689: /* Now handle the command line options. */ ! 1690: ! 1691: /* Do -U's, -D's and -A's in the order they were seen. */ ! 1692: for (i = 1; i < argc; i++) { ! 1693: if (pend_undefs[i]) { ! 1694: if (debug_output) ! 1695: output_line_command (fp, &outbuf, 0, same_file); ! 1696: make_undef (pend_undefs[i], &outbuf); ! 1697: } ! 1698: if (pend_defs[i]) { ! 1699: if (debug_output) ! 1700: output_line_command (fp, &outbuf, 0, same_file); ! 1701: make_definition (pend_defs[i], &outbuf); ! 1702: } ! 1703: if (pend_assertions[i]) ! 1704: make_assertion (pend_assertion_options[i], pend_assertions[i]); ! 1705: } ! 1706: ! 1707: done_initializing = 1; ! 1708: ! 1709: { /* read the appropriate environment variable and if it exists ! 1710: replace include_defaults with the listed path. */ ! 1711: char *epath = 0; ! 1712: switch ((objc << 1) + cplusplus) ! 1713: { ! 1714: case 0: ! 1715: epath = getenv ("C_INCLUDE_PATH"); ! 1716: break; ! 1717: case 1: ! 1718: epath = getenv ("CPLUS_INCLUDE_PATH"); ! 1719: break; ! 1720: case 2: ! 1721: epath = getenv ("OBJC_INCLUDE_PATH"); ! 1722: break; ! 1723: case 3: ! 1724: epath = getenv ("OBJCPLUS_INCLUDE_PATH"); ! 1725: break; ! 1726: } ! 1727: /* If the environment var for this language is set, ! 1728: add to the default list of include directories. */ ! 1729: if (epath) { ! 1730: char *nstore = (char *) alloca (strlen (epath) + 2); ! 1731: int num_dirs; ! 1732: char *startp, *endp; ! 1733: ! 1734: for (num_dirs = 1, startp = epath; *startp; startp++) ! 1735: if (*startp == PATH_SEPARATOR) ! 1736: num_dirs++; ! 1737: include_defaults ! 1738: = (struct default_include *) xmalloc ((num_dirs ! 1739: * sizeof (struct default_include)) ! 1740: + sizeof (include_defaults_array)); ! 1741: startp = endp = epath; ! 1742: num_dirs = 0; ! 1743: while (1) { ! 1744: /* Handle cases like c:/usr/lib:d:/gcc/lib */ ! 1745: if ((*endp == PATH_SEPARATOR ! 1746: #if 0 /* Obsolete, now that we use semicolons as the path separator. */ ! 1747: #ifdef __MSDOS__ ! 1748: && (endp-startp != 1 || !isalpha (*startp)) ! 1749: #endif ! 1750: #endif ! 1751: ) ! 1752: || *endp == 0) { ! 1753: strncpy (nstore, startp, endp-startp); ! 1754: if (endp == startp) ! 1755: strcpy (nstore, "."); ! 1756: else ! 1757: nstore[endp-startp] = '\0'; ! 1758: ! 1759: include_defaults[num_dirs].fname = savestring (nstore); ! 1760: include_defaults[num_dirs].cplusplus = cplusplus; ! 1761: num_dirs++; ! 1762: if (*endp == '\0') ! 1763: break; ! 1764: endp = startp = endp + 1; ! 1765: } else ! 1766: endp++; ! 1767: } ! 1768: /* Put the usual defaults back in at the end. */ ! 1769: bcopy (include_defaults_array, &include_defaults[num_dirs], ! 1770: sizeof (include_defaults_array)); ! 1771: } ! 1772: } ! 1773: ! 1774: first_system_include = 0; ! 1775: /* Unless -fnostdinc, ! 1776: tack on the standard include file dirs to the specified list */ ! 1777: if (!no_standard_includes) { ! 1778: struct default_include *p = include_defaults; ! 1779: char *specd_prefix = include_prefix; ! 1780: char *default_prefix = savestring (GCC_INCLUDE_DIR); ! 1781: int default_len = 0; ! 1782: /* Remove the `include' from /usr/local/lib/gcc.../include. */ ! 1783: if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) { ! 1784: default_len = strlen (default_prefix) - 7; ! 1785: default_prefix[default_len] = 0; ! 1786: } ! 1787: /* Search "translated" versions of GNU directories. ! 1788: These have /usr/local/lib/gcc... replaced by specd_prefix. */ ! 1789: if (specd_prefix != 0 && default_len != 0) ! 1790: for (p = include_defaults; p->fname; p++) { ! 1791: /* Some standard dirs are only for C++. */ ! 1792: if ((p->cplusplus != 1) ! 1793: || (cplusplus && !no_standard_cplusplus_includes)) ! 1794: { ! 1795: /* Does this dir start with the prefix? */ ! 1796: if (!strncmp (p->fname, default_prefix, default_len)) { ! 1797: /* Yes; change prefix and add to search list. */ ! 1798: struct file_name_list *new ! 1799: = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); ! 1800: int this_len = strlen (specd_prefix) + strlen (p->fname) - default_len; ! 1801: char *str = (char *) xmalloc (this_len + 1); ! 1802: strcpy (str, specd_prefix); ! 1803: strcat (str, p->fname + default_len); ! 1804: new->fname = str; ! 1805: new->control_macro = 0; ! 1806: new->c_system_include_path = (p->cplusplus == 0); ! 1807: append_include_chain (new, new); ! 1808: if (first_system_include == 0) ! 1809: first_system_include = new; ! 1810: } ! 1811: } ! 1812: } ! 1813: /* Search ordinary names for GNU include directories. */ ! 1814: for (p = include_defaults; p->fname; p++) { ! 1815: /* Some standard dirs are only for C++. */ ! 1816: if ((p->cplusplus != 1) ! 1817: || (cplusplus && !no_standard_cplusplus_includes)) ! 1818: { ! 1819: struct file_name_list *new ! 1820: = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); ! 1821: new->control_macro = 0; ! 1822: new->c_system_include_path = (p->cplusplus == 0); ! 1823: new->fname = p->fname; ! 1824: append_include_chain (new, new); ! 1825: if (first_system_include == 0) ! 1826: first_system_include = new; ! 1827: } ! 1828: } ! 1829: } ! 1830: ! 1831: /* Tack the after_include chain at the end of the include chain. */ ! 1832: append_include_chain (after_include, last_after_include); ! 1833: if (first_system_include == 0) ! 1834: first_system_include = after_include; ! 1835: ! 1836: /* With -v, print the list of dirs to search. */ ! 1837: if (verbose) { ! 1838: struct file_name_list *p; ! 1839: fprintf (stderr, "#include \"...\" search starts here:\n"); ! 1840: for (p = include; p; p = p->next) { ! 1841: if (p == first_bracket_include) ! 1842: fprintf (stderr, "#include <...> search starts here:\n"); ! 1843: fprintf (stderr, " %s\n", p->fname); ! 1844: } ! 1845: fprintf (stderr, "End of search list.\n"); ! 1846: } ! 1847: ! 1848: /* Scan the -imacros files before the main input. ! 1849: Much like #including them, but with no_output set ! 1850: so that only their macro definitions matter. */ ! 1851: ! 1852: no_output++; ! 1853: for (i = 1; i < argc; i++) ! 1854: if (pend_files[i]) { ! 1855: int fd = open (pend_files[i], O_RDONLY, 0666); ! 1856: if (fd < 0) { ! 1857: perror_with_name (pend_files[i]); ! 1858: return FAILURE_EXIT_CODE; ! 1859: } ! 1860: finclude (fd, pend_files[i], &outbuf, 0, NULL_PTR); ! 1861: } ! 1862: no_output--; ! 1863: ! 1864: /* Copy the entire contents of the main input file into ! 1865: the stacked input buffer previously allocated for it. */ ! 1866: ! 1867: /* JF check for stdin */ ! 1868: if (in_fname == NULL || *in_fname == 0) { ! 1869: in_fname = ""; ! 1870: f = 0; ! 1871: } else if ((f = open (in_fname, O_RDONLY, 0666)) < 0) ! 1872: goto perror; ! 1873: ! 1874: /* Either of two environment variables can specify output of deps. ! 1875: Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET", ! 1876: where OUTPUT_FILE is the file to write deps info to ! 1877: and DEPS_TARGET is the target to mention in the deps. */ ! 1878: ! 1879: if (print_deps == 0 ! 1880: && (getenv ("SUNPRO_DEPENDENCIES") != 0 ! 1881: || getenv ("DEPENDENCIES_OUTPUT") != 0)) { ! 1882: char *spec = getenv ("DEPENDENCIES_OUTPUT"); ! 1883: char *s; ! 1884: char *output_file; ! 1885: ! 1886: if (spec == 0) { ! 1887: spec = getenv ("SUNPRO_DEPENDENCIES"); ! 1888: print_deps = 2; ! 1889: } ! 1890: else ! 1891: print_deps = 1; ! 1892: ! 1893: s = spec; ! 1894: /* Find the space before the DEPS_TARGET, if there is one. */ ! 1895: /* This should use index. (mrs) */ ! 1896: while (*s != 0 && *s != ' ') s++; ! 1897: if (*s != 0) { ! 1898: deps_target = s + 1; ! 1899: output_file = (char *) xmalloc (s - spec + 1); ! 1900: bcopy (spec, output_file, s - spec); ! 1901: output_file[s - spec] = 0; ! 1902: } ! 1903: else { ! 1904: deps_target = 0; ! 1905: output_file = spec; ! 1906: } ! 1907: ! 1908: deps_file = output_file; ! 1909: deps_mode = "a"; ! 1910: } ! 1911: ! 1912: /* For -M, print the expected object file name ! 1913: as the target of this Make-rule. */ ! 1914: if (print_deps) { ! 1915: deps_allocated_size = 200; ! 1916: deps_buffer = (char *) xmalloc (deps_allocated_size); ! 1917: deps_buffer[0] = 0; ! 1918: deps_size = 0; ! 1919: deps_column = 0; ! 1920: ! 1921: if (deps_target) { ! 1922: deps_output (deps_target, 0); ! 1923: deps_output (":", 0); ! 1924: } else if (*in_fname == 0) ! 1925: deps_output ("-: ", 0); ! 1926: else { ! 1927: int len; ! 1928: char *p = in_fname; ! 1929: char *p1 = p; ! 1930: /* Discard all directory prefixes from P. */ ! 1931: while (*p1) { ! 1932: if (*p1 == '/') ! 1933: p = p1 + 1; ! 1934: p1++; ! 1935: } ! 1936: /* Output P, but remove known suffixes. */ ! 1937: len = strlen (p); ! 1938: if (p[len - 2] == '.' && p[len - 1] == 'c') ! 1939: deps_output (p, len - 2); ! 1940: else if (p[len - 2] == '.' && p[len - 1] == 'C') ! 1941: deps_output (p, len - 2); ! 1942: else if (p[len - 3] == '.' ! 1943: && p[len - 2] == 'c' ! 1944: && p[len - 1] == 'c') ! 1945: deps_output (p, len - 3); ! 1946: else if (p[len - 4] == '.' ! 1947: && p[len - 3] == 'c' ! 1948: && p[len - 2] == 'x' ! 1949: && p[len - 1] == 'x') ! 1950: deps_output (p, len - 4); ! 1951: else if (p[len - 2] == '.' && p[len - 1] == 's') ! 1952: deps_output (p, len - 2); ! 1953: else if (p[len - 2] == '.' && p[len - 1] == 'S') ! 1954: deps_output (p, len - 2); ! 1955: else if (p[len - 2] == '.' && p[len - 1] == 'm') ! 1956: deps_output (p, len - 2); ! 1957: else ! 1958: deps_output (p, 0); ! 1959: /* Supply our own suffix. */ ! 1960: #ifndef VMS ! 1961: deps_output (".o : ", 0); ! 1962: #else ! 1963: deps_output (".obj : ", 0); ! 1964: #endif ! 1965: deps_output (in_fname, 0); ! 1966: deps_output (" ", 0); ! 1967: } ! 1968: } ! 1969: ! 1970: file_size_and_mode (f, &st_mode, &st_size); ! 1971: fp->nominal_fname = fp->fname = in_fname; ! 1972: fp->lineno = 1; ! 1973: fp->system_header_p = 0; ! 1974: /* JF all this is mine about reading pipes and ttys */ ! 1975: if (! S_ISREG (st_mode)) { ! 1976: /* Read input from a file that is not a normal disk file. ! 1977: We cannot preallocate a buffer with the correct size, ! 1978: so we must read in the file a piece at the time and make it bigger. */ ! 1979: int size; ! 1980: int bsize; ! 1981: int cnt; ! 1982: U_CHAR *bufp; ! 1983: ! 1984: bsize = 2000; ! 1985: size = 0; ! 1986: fp->buf = (U_CHAR *) xmalloc (bsize + 2); ! 1987: bufp = fp->buf; ! 1988: for (;;) { ! 1989: cnt = safe_read (f, bufp, bsize - size); ! 1990: if (cnt < 0) goto perror; /* error! */ ! 1991: if (cnt == 0) break; /* End of file */ ! 1992: size += cnt; ! 1993: bufp += cnt; ! 1994: if (bsize == size) { /* Buffer is full! */ ! 1995: bsize *= 2; ! 1996: fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2); ! 1997: bufp = fp->buf + size; /* May have moved */ ! 1998: } ! 1999: } ! 2000: fp->length = size; ! 2001: } else { ! 2002: /* Read a file whose size we can determine in advance. ! 2003: For the sake of VMS, st_size is just an upper bound. */ ! 2004: long i; ! 2005: fp->length = 0; ! 2006: fp->buf = (U_CHAR *) xmalloc (st_size + 2); ! 2007: ! 2008: while (st_size > 0) { ! 2009: i = safe_read (f, fp->buf + fp->length, st_size); ! 2010: if (i <= 0) { ! 2011: if (i == 0) break; ! 2012: goto perror; ! 2013: } ! 2014: fp->length += i; ! 2015: st_size -= i; ! 2016: } ! 2017: } ! 2018: fp->bufp = fp->buf; ! 2019: fp->if_stack = if_stack; ! 2020: ! 2021: /* Make sure data ends with a newline. And put a null after it. */ ! 2022: ! 2023: if ((fp->length > 0 && fp->buf[fp->length - 1] != '\n') ! 2024: /* Backslash-newline at end is not good enough. */ ! 2025: || (fp->length > 1 && fp->buf[fp->length - 2] == '\\')) { ! 2026: fp->buf[fp->length++] = '\n'; ! 2027: missing_newline = 1; ! 2028: } ! 2029: fp->buf[fp->length] = '\0'; ! 2030: ! 2031: /* Unless inhibited, convert trigraphs in the input. */ ! 2032: ! 2033: if (!no_trigraphs) ! 2034: trigraph_pcp (fp); ! 2035: ! 2036: #ifdef NEXT_SEMANTICS ! 2037: if (!no_rtf) ! 2038: buf_convert_rtf (fp); ! 2039: #endif ! 2040: ! 2041: /* Now that we know the input file is valid, open the output. */ ! 2042: ! 2043: if (!out_fname || !strcmp (out_fname, "")) ! 2044: out_fname = "stdout"; ! 2045: else if (! freopen (out_fname, "w", stdout)) ! 2046: pfatal_with_name (out_fname); ! 2047: ! 2048: output_line_command (fp, &outbuf, 0, same_file); ! 2049: ! 2050: /* Scan the -include files before the main input. */ ! 2051: ! 2052: for (i = 1; i < argc; i++) ! 2053: if (pend_includes[i]) { ! 2054: int fd = open (pend_includes[i], O_RDONLY, 0666); ! 2055: if (fd < 0) { ! 2056: perror_with_name (pend_includes[i]); ! 2057: return FAILURE_EXIT_CODE; ! 2058: } ! 2059: finclude (fd, pend_includes[i], &outbuf, 0, NULL_PTR); ! 2060: } ! 2061: ! 2062: /* Scan the input, processing macros and directives. */ ! 2063: ! 2064: rescan (&outbuf, 0); ! 2065: ! 2066: if (missing_newline) ! 2067: fp->lineno--; ! 2068: ! 2069: if (pedantic && missing_newline) ! 2070: pedwarn ("file does not end in newline"); ! 2071: ! 2072: /* Now we have processed the entire input ! 2073: Write whichever kind of output has been requested. */ ! 2074: ! 2075: if (dump_macros == dump_only) ! 2076: dump_all_macros (); ! 2077: else if (! inhibit_output) { ! 2078: write_output (); ! 2079: } ! 2080: ! 2081: if (print_deps) { ! 2082: /* Don't actually write the deps file if compilation has failed. */ ! 2083: if (errors == 0) { ! 2084: if (deps_file && ! (deps_stream = fopen (deps_file, deps_mode))) ! 2085: pfatal_with_name (deps_file); ! 2086: fputs (deps_buffer, deps_stream); ! 2087: putc ('\n', deps_stream); ! 2088: if (deps_file) { ! 2089: if (ferror (deps_stream) || fclose (deps_stream) != 0) ! 2090: fatal ("I/O error on output"); ! 2091: } ! 2092: } ! 2093: } ! 2094: ! 2095: if (pcp_outfile && pcp_outfile != stdout ! 2096: && (ferror (pcp_outfile) || fclose (pcp_outfile) != 0)) ! 2097: fatal ("I/O error on `-pcp' output"); ! 2098: ! 2099: if (ferror (stdout) || fclose (stdout) != 0) ! 2100: fatal ("I/O error on output"); ! 2101: ! 2102: if (errors) ! 2103: exit (FAILURE_EXIT_CODE); ! 2104: exit (SUCCESS_EXIT_CODE); ! 2105: ! 2106: perror: ! 2107: pfatal_with_name (in_fname); ! 2108: return 0; ! 2109: } ! 2110: ! 2111: /* Given a colon-separated list of file names PATH, ! 2112: add all the names to the search path for include files. */ ! 2113: ! 2114: static void ! 2115: path_include (path) ! 2116: char *path; ! 2117: { ! 2118: char *p; ! 2119: ! 2120: p = path; ! 2121: ! 2122: if (*p) ! 2123: while (1) { ! 2124: char *q = p; ! 2125: char *name; ! 2126: struct file_name_list *dirtmp; ! 2127: ! 2128: /* Find the end of this name. */ ! 2129: while (*q != 0 && *q != PATH_SEPARATOR) q++; ! 2130: if (p == q) { ! 2131: /* An empty name in the path stands for the current directory. */ ! 2132: name = (char *) xmalloc (2); ! 2133: name[0] = '.'; ! 2134: name[1] = 0; ! 2135: } else { ! 2136: /* Otherwise use the directory that is named. */ ! 2137: name = (char *) xmalloc (q - p + 1); ! 2138: bcopy (p, name, q - p); ! 2139: name[q - p] = 0; ! 2140: } ! 2141: ! 2142: dirtmp = (struct file_name_list *) ! 2143: xmalloc (sizeof (struct file_name_list)); ! 2144: dirtmp->next = 0; /* New one goes on the end */ ! 2145: dirtmp->control_macro = 0; ! 2146: dirtmp->c_system_include_path = 0; ! 2147: dirtmp->fname = name; ! 2148: append_include_chain (dirtmp, dirtmp); ! 2149: ! 2150: /* Advance past this name. */ ! 2151: p = q; ! 2152: if (*p == 0) ! 2153: break; ! 2154: /* Skip the colon. */ ! 2155: p++; ! 2156: } ! 2157: } ! 2158: ! 2159: /* Pre-C-Preprocessor to translate ANSI trigraph idiocy in BUF ! 2160: before main CCCP processing. Name `pcp' is also in honor of the ! 2161: drugs the trigraph designers must have been on. ! 2162: ! 2163: Using an extra pass through the buffer takes a little extra time, ! 2164: but is infinitely less hairy than trying to handle trigraphs inside ! 2165: strings, etc. everywhere, and also makes sure that trigraphs are ! 2166: only translated in the top level of processing. */ ! 2167: ! 2168: static void ! 2169: trigraph_pcp (buf) ! 2170: FILE_BUF *buf; ! 2171: { ! 2172: register U_CHAR c, *fptr, *bptr, *sptr; ! 2173: int len; ! 2174: ! 2175: fptr = bptr = sptr = buf->buf; ! 2176: while ((sptr = (U_CHAR *) index (sptr, '?')) != NULL) { ! 2177: if (*++sptr != '?') ! 2178: continue; ! 2179: switch (*++sptr) { ! 2180: case '=': ! 2181: c = '#'; ! 2182: break; ! 2183: case '(': ! 2184: c = '['; ! 2185: break; ! 2186: case '/': ! 2187: c = '\\'; ! 2188: break; ! 2189: case ')': ! 2190: c = ']'; ! 2191: break; ! 2192: case '\'': ! 2193: c = '^'; ! 2194: break; ! 2195: case '<': ! 2196: c = '{'; ! 2197: break; ! 2198: case '!': ! 2199: c = '|'; ! 2200: break; ! 2201: case '>': ! 2202: c = '}'; ! 2203: break; ! 2204: case '-': ! 2205: c = '~'; ! 2206: break; ! 2207: case '?': ! 2208: sptr--; ! 2209: continue; ! 2210: default: ! 2211: continue; ! 2212: } ! 2213: len = sptr - fptr - 2; ! 2214: if (bptr != fptr && len > 0) ! 2215: bcopy (fptr, bptr, len); /* BSD doc says bcopy () works right ! 2216: for overlapping strings. In ANSI ! 2217: C, this will be memmove (). */ ! 2218: bptr += len; ! 2219: *bptr++ = c; ! 2220: fptr = ++sptr; ! 2221: } ! 2222: len = buf->length - (fptr - buf->buf); ! 2223: if (bptr != fptr && len > 0) ! 2224: bcopy (fptr, bptr, len); ! 2225: buf->length -= fptr - bptr; ! 2226: buf->buf[buf->length] = '\0'; ! 2227: if (warn_trigraphs && fptr != bptr) ! 2228: warning ("%d trigraph(s) encountered", (fptr - bptr) / 2); ! 2229: } ! 2230: ! 2231: /* Move all backslash-newline pairs out of embarrassing places. ! 2232: Exchange all such pairs following BP ! 2233: with any potentially-embarrassing characters that follow them. ! 2234: Potentially-embarrassing characters are / and * ! 2235: (because a backslash-newline inside a comment delimiter ! 2236: would cause it not to be recognized). */ ! 2237: ! 2238: static void ! 2239: newline_fix (bp) ! 2240: U_CHAR *bp; ! 2241: { ! 2242: register U_CHAR *p = bp; ! 2243: register int count = 0; ! 2244: ! 2245: /* First count the backslash-newline pairs here. */ ! 2246: ! 2247: while (1) { ! 2248: if (p[0] == '\\') { ! 2249: if (p[1] == '\n') ! 2250: p += 2, count++; ! 2251: else if (p[1] == '\r' && p[2] == '\n') ! 2252: p += 3, count++; ! 2253: else ! 2254: break; ! 2255: } else ! 2256: break; ! 2257: } ! 2258: ! 2259: /* What follows the backslash-newlines is not embarrassing. */ ! 2260: ! 2261: if (count == 0 || (*p != '/' && *p != '*')) ! 2262: return; ! 2263: ! 2264: /* Copy all potentially embarrassing characters ! 2265: that follow the backslash-newline pairs ! 2266: down to where the pairs originally started. */ ! 2267: ! 2268: while (*p == '*' || *p == '/') ! 2269: *bp++ = *p++; ! 2270: ! 2271: /* Now write the same number of pairs after the embarrassing chars. */ ! 2272: while (count-- > 0) { ! 2273: *bp++ = '\\'; ! 2274: *bp++ = '\n'; ! 2275: } ! 2276: } ! 2277: ! 2278: /* Like newline_fix but for use within a directive-name. ! 2279: Move any backslash-newlines up past any following symbol constituents. */ ! 2280: ! 2281: static void ! 2282: name_newline_fix (bp) ! 2283: U_CHAR *bp; ! 2284: { ! 2285: register U_CHAR *p = bp; ! 2286: register int count = 0; ! 2287: ! 2288: /* First count the backslash-newline pairs here. */ ! 2289: while (1) { ! 2290: if (p[0] == '\\') { ! 2291: if (p[1] == '\n') ! 2292: p += 2, count++; ! 2293: else if (p[1] == '\r' && p[2] == '\n') ! 2294: p += 3, count++; ! 2295: else ! 2296: break; ! 2297: } else ! 2298: break; ! 2299: } ! 2300: ! 2301: /* What follows the backslash-newlines is not embarrassing. */ ! 2302: ! 2303: if (count == 0 || !is_idchar[*p]) ! 2304: return; ! 2305: ! 2306: /* Copy all potentially embarrassing characters ! 2307: that follow the backslash-newline pairs ! 2308: down to where the pairs originally started. */ ! 2309: ! 2310: while (is_idchar[*p]) ! 2311: *bp++ = *p++; ! 2312: ! 2313: /* Now write the same number of pairs after the embarrassing chars. */ ! 2314: while (count-- > 0) { ! 2315: *bp++ = '\\'; ! 2316: *bp++ = '\n'; ! 2317: } ! 2318: } ! 2319: ! 2320: /* Look for lint commands in comments. ! 2321: ! 2322: When we come in here, ibp points into a comment. Limit is as one expects. ! 2323: scan within the comment -- it should start, after lwsp, with a lint command. ! 2324: If so that command is returned as a (constant) string. ! 2325: ! 2326: Upon return, any arg will be pointed to with argstart and will be ! 2327: arglen long. Note that we don't parse that arg since it will just ! 2328: be printed out again. ! 2329: */ ! 2330: ! 2331: static char * ! 2332: get_lintcmd (ibp, limit, argstart, arglen, cmdlen) ! 2333: register U_CHAR *ibp; ! 2334: register U_CHAR *limit; ! 2335: U_CHAR **argstart; /* point to command arg */ ! 2336: int *arglen, *cmdlen; /* how long they are */ ! 2337: { ! 2338: long linsize; ! 2339: register U_CHAR *numptr; /* temp for arg parsing */ ! 2340: ! 2341: *arglen = 0; ! 2342: ! 2343: SKIP_WHITE_SPACE (ibp); ! 2344: ! 2345: if (ibp >= limit) return NULL; ! 2346: ! 2347: linsize = limit - ibp; ! 2348: ! 2349: /* Oh, I wish C had lexical functions... hell, I'll just open-code the set */ ! 2350: if ((linsize >= 10) && !strncmp (ibp, "NOTREACHED", 10)) { ! 2351: *cmdlen = 10; ! 2352: return "NOTREACHED"; ! 2353: } ! 2354: if ((linsize >= 8) && !strncmp (ibp, "ARGSUSED", 8)) { ! 2355: *cmdlen = 8; ! 2356: return "ARGSUSED"; ! 2357: } ! 2358: if ((linsize >= 11) && !strncmp (ibp, "LINTLIBRARY", 11)) { ! 2359: *cmdlen = 11; ! 2360: return "LINTLIBRARY"; ! 2361: } ! 2362: if ((linsize >= 7) && !strncmp (ibp, "VARARGS", 7)) { ! 2363: *cmdlen = 7; ! 2364: ibp += 7; linsize -= 7; ! 2365: if ((linsize == 0) || ! isdigit (*ibp)) return "VARARGS"; ! 2366: ! 2367: /* OK, read a number */ ! 2368: for (numptr = *argstart = ibp; (numptr < limit) && isdigit (*numptr); ! 2369: numptr++); ! 2370: *arglen = numptr - *argstart; ! 2371: return "VARARGS"; ! 2372: } ! 2373: return NULL; ! 2374: } ! 2375: ! 2376: /* ! 2377: * The main loop of the program. ! 2378: * ! 2379: * Read characters from the input stack, transferring them to the ! 2380: * output buffer OP. ! 2381: * ! 2382: * Macros are expanded and push levels on the input stack. ! 2383: * At the end of such a level it is popped off and we keep reading. ! 2384: * At the end of any other kind of level, we return. ! 2385: * #-directives are handled, except within macros. ! 2386: * ! 2387: * If OUTPUT_MARKS is nonzero, keep Newline markers found in the input ! 2388: * and insert them when appropriate. This is set while scanning macro ! 2389: * arguments before substitution. It is zero when scanning for final output. ! 2390: * There are three types of Newline markers: ! 2391: * * Newline - follows a macro name that was not expanded ! 2392: * because it appeared inside an expansion of the same macro. ! 2393: * This marker prevents future expansion of that identifier. ! 2394: * When the input is rescanned into the final output, these are deleted. ! 2395: * These are also deleted by ## concatenation. ! 2396: * * Newline Space (or Newline and any other whitespace character) ! 2397: * stands for a place that tokens must be separated or whitespace ! 2398: * is otherwise desirable, but where the ANSI standard specifies there ! 2399: * is no whitespace. This marker turns into a Space (or whichever other ! 2400: * whitespace char appears in the marker) in the final output, ! 2401: * but it turns into nothing in an argument that is stringified with #. ! 2402: * Such stringified arguments are the only place where the ANSI standard ! 2403: * specifies with precision that whitespace may not appear. ! 2404: * ! 2405: * During this function, IP->bufp is kept cached in IBP for speed of access. ! 2406: * Likewise, OP->bufp is kept in OBP. Before calling a subroutine ! 2407: * IBP, IP and OBP must be copied back to memory. IP and IBP are ! 2408: * copied back with the RECACHE macro. OBP must be copied back from OP->bufp ! 2409: * explicitly, and before RECACHE, since RECACHE uses OBP. ! 2410: */ ! 2411: ! 2412: static void ! 2413: rescan (op, output_marks) ! 2414: FILE_BUF *op; ! 2415: int output_marks; ! 2416: { ! 2417: /* Character being scanned in main loop. */ ! 2418: register U_CHAR c; ! 2419: ! 2420: /* Length of pending accumulated identifier. */ ! 2421: register int ident_length = 0; ! 2422: ! 2423: /* Hash code of pending accumulated identifier. */ ! 2424: register int hash = 0; ! 2425: ! 2426: /* Current input level (&instack[indepth]). */ ! 2427: FILE_BUF *ip; ! 2428: ! 2429: /* Pointer for scanning input. */ ! 2430: register U_CHAR *ibp; ! 2431: ! 2432: /* Pointer to end of input. End of scan is controlled by LIMIT. */ ! 2433: register U_CHAR *limit; ! 2434: ! 2435: /* Pointer for storing output. */ ! 2436: register U_CHAR *obp; ! 2437: ! 2438: /* REDO_CHAR is nonzero if we are processing an identifier ! 2439: after backing up over the terminating character. ! 2440: Sometimes we process an identifier without backing up over ! 2441: the terminating character, if the terminating character ! 2442: is not special. Backing up is done so that the terminating character ! 2443: will be dispatched on again once the identifier is dealt with. */ ! 2444: int redo_char = 0; ! 2445: ! 2446: /* 1 if within an identifier inside of which a concatenation ! 2447: marker (Newline -) has been seen. */ ! 2448: int concatenated = 0; ! 2449: ! 2450: /* While scanning a comment or a string constant, ! 2451: this records the line it started on, for error messages. */ ! 2452: int start_line; ! 2453: ! 2454: /* Record position of last `real' newline. */ ! 2455: U_CHAR *beg_of_line; ! 2456: ! 2457: /* Pop the innermost input stack level, assuming it is a macro expansion. */ ! 2458: ! 2459: #define POPMACRO \ ! 2460: do { ip->macro->type = T_MACRO; \ ! 2461: if (ip->free_ptr) free (ip->free_ptr); \ ! 2462: --indepth; } while (0) ! 2463: ! 2464: /* Reload `rescan's local variables that describe the current ! 2465: level of the input stack. */ ! 2466: ! 2467: #define RECACHE \ ! 2468: do { ip = &instack[indepth]; \ ! 2469: ibp = ip->bufp; \ ! 2470: limit = ip->buf + ip->length; \ ! 2471: op->bufp = obp; \ ! 2472: check_expand (op, limit - ibp); \ ! 2473: beg_of_line = 0; \ ! 2474: obp = op->bufp; } while (0) ! 2475: ! 2476: if (no_output && instack[indepth].fname != 0) ! 2477: skip_if_group (&instack[indepth], 1); ! 2478: ! 2479: obp = op->bufp; ! 2480: RECACHE; ! 2481: ! 2482: beg_of_line = ibp; ! 2483: ! 2484: /* Our caller must always put a null after the end of ! 2485: the input at each input stack level. */ ! 2486: if (*limit != 0) ! 2487: abort (); ! 2488: ! 2489: while (1) { ! 2490: c = *ibp++; ! 2491: *obp++ = c; ! 2492: ! 2493: switch (c) { ! 2494: case '\\': ! 2495: if (ibp >= limit) ! 2496: break; ! 2497: if (*ibp == '\n') { ! 2498: /* Always merge lines ending with backslash-newline, ! 2499: even in middle of identifier. */ ! 2500: ++ibp; ! 2501: ++ip->lineno; ! 2502: --obp; /* remove backslash from obuf */ ! 2503: break; ! 2504: } ! 2505: /* Otherwise, backslash suppresses specialness of following char, ! 2506: so copy it here to prevent the switch from seeing it. ! 2507: But first get any pending identifier processed. */ ! 2508: if (ident_length > 0) ! 2509: goto specialchar; ! 2510: *obp++ = *ibp++; ! 2511: break; ! 2512: ! 2513: case '#': ! 2514: if (assertions_flag) { ! 2515: /* Copy #foo (bar lose) without macro expansion. */ ! 2516: SKIP_WHITE_SPACE (ibp); ! 2517: while (is_idchar[*ibp]) ! 2518: *obp++ = *ibp++; ! 2519: SKIP_WHITE_SPACE (ibp); ! 2520: if (*ibp == '(') { ! 2521: ip->bufp = ibp; ! 2522: skip_paren_group (ip); ! 2523: bcopy (ibp, obp, ip->bufp - ibp); ! 2524: obp += ip->bufp - ibp; ! 2525: ibp = ip->bufp; ! 2526: } ! 2527: } ! 2528: ! 2529: /* If this is expanding a macro definition, don't recognize ! 2530: preprocessor directives. */ ! 2531: if (ip->macro != 0) ! 2532: goto randomchar; ! 2533: /* If this is expand_into_temp_buffer, recognize them ! 2534: only after an actual newline at this level, ! 2535: not at the beginning of the input level. */ ! 2536: if (ip->fname == 0 && beg_of_line == ip->buf) ! 2537: goto randomchar; ! 2538: if (ident_length) ! 2539: goto specialchar; ! 2540: ! 2541: ! 2542: /* # keyword: a # must be first nonblank char on the line */ ! 2543: if (beg_of_line == 0) ! 2544: goto randomchar; ! 2545: { ! 2546: U_CHAR *bp; ! 2547: ! 2548: /* Scan from start of line, skipping whitespace, comments ! 2549: and backslash-newlines, and see if we reach this #. ! 2550: If not, this # is not special. */ ! 2551: bp = beg_of_line; ! 2552: /* If -traditional, require # to be at beginning of line. */ ! 2553: if (!traditional) ! 2554: while (1) { ! 2555: if (is_hor_space[*bp]) ! 2556: bp++; ! 2557: else if (*bp == '\\' && bp[1] == '\n') ! 2558: bp += 2; ! 2559: else if (*bp == '/' && bp[1] == '*') { ! 2560: bp += 2; ! 2561: while (!(*bp == '*' && bp[1] == '/')) ! 2562: bp++; ! 2563: bp += 2; ! 2564: } ! 2565: else if (cplusplus_comments && *bp == '/' && bp[1] == '/') { ! 2566: bp += 2; ! 2567: while (*bp++ != '\n') ; ! 2568: } ! 2569: else break; ! 2570: } ! 2571: if (bp + 1 != ibp) ! 2572: goto randomchar; ! 2573: } ! 2574: ! 2575: /* This # can start a directive. */ ! 2576: ! 2577: --obp; /* Don't copy the '#' */ ! 2578: ! 2579: ip->bufp = ibp; ! 2580: op->bufp = obp; ! 2581: if (! handle_directive (ip, op)) { ! 2582: #ifdef USE_C_ALLOCA ! 2583: alloca (0); ! 2584: #endif ! 2585: /* Not a known directive: treat it as ordinary text. ! 2586: IP, OP, IBP, etc. have not been changed. */ ! 2587: if (no_output && instack[indepth].fname) { ! 2588: /* If not generating expanded output, ! 2589: what we do with ordinary text is skip it. ! 2590: Discard everything until next # directive. */ ! 2591: skip_if_group (&instack[indepth], 1); ! 2592: RECACHE; ! 2593: beg_of_line = ibp; ! 2594: break; ! 2595: } ! 2596: ++obp; /* Copy the '#' after all */ ! 2597: /* Don't expand an identifier that could be a macro directive. ! 2598: (Section 3.8.3 of the ANSI C standard) */ ! 2599: SKIP_WHITE_SPACE (ibp); ! 2600: if (is_idstart[*ibp]) ! 2601: { ! 2602: *obp++ = *ibp++; ! 2603: while (is_idchar[*ibp]) ! 2604: *obp++ = *ibp++; ! 2605: } ! 2606: goto randomchar; ! 2607: } ! 2608: #ifdef USE_C_ALLOCA ! 2609: alloca (0); ! 2610: #endif ! 2611: /* A # directive has been successfully processed. */ ! 2612: /* If not generating expanded output, ignore everything until ! 2613: next # directive. */ ! 2614: if (no_output && instack[indepth].fname) ! 2615: skip_if_group (&instack[indepth], 1); ! 2616: obp = op->bufp; ! 2617: RECACHE; ! 2618: beg_of_line = ibp; ! 2619: break; ! 2620: ! 2621: case '\"': /* skip quoted string */ ! 2622: case '\'': ! 2623: /* A single quoted string is treated like a double -- some ! 2624: programs (e.g., troff) are perverse this way */ ! 2625: ! 2626: if (ident_length) ! 2627: goto specialchar; ! 2628: ! 2629: start_line = ip->lineno; ! 2630: ! 2631: /* Skip ahead to a matching quote. */ ! 2632: ! 2633: while (1) { ! 2634: if (ibp >= limit) { ! 2635: if (ip->macro != 0) { ! 2636: /* try harder: this string crosses a macro expansion boundary. ! 2637: This can happen naturally if -traditional. ! 2638: Otherwise, only -D can make a macro with an unmatched quote. */ ! 2639: POPMACRO; ! 2640: RECACHE; ! 2641: continue; ! 2642: } ! 2643: if (!traditional) { ! 2644: error_with_line (line_for_error (start_line), ! 2645: "unterminated string or character constant"); ! 2646: error_with_line (multiline_string_line, ! 2647: "possible real start of unterminated constant"); ! 2648: multiline_string_line = 0; ! 2649: } ! 2650: break; ! 2651: } ! 2652: *obp++ = *ibp; ! 2653: switch (*ibp++) { ! 2654: case '\n': ! 2655: ++ip->lineno; ! 2656: ++op->lineno; ! 2657: /* Traditionally, end of line ends a string constant with no error. ! 2658: So exit the loop and record the new line. */ ! 2659: if (traditional) { ! 2660: beg_of_line = ibp; ! 2661: goto while2end; ! 2662: } ! 2663: if (c == '\'') { ! 2664: error_with_line (line_for_error (start_line), ! 2665: "unterminated character constant"); ! 2666: goto while2end; ! 2667: } ! 2668: if (pedantic && multiline_string_line == 0) { ! 2669: pedwarn_with_line (line_for_error (start_line), ! 2670: "string constant runs past end of line"); ! 2671: } ! 2672: if (multiline_string_line == 0) ! 2673: multiline_string_line = ip->lineno - 1; ! 2674: break; ! 2675: ! 2676: case '\\': ! 2677: if (ibp >= limit) ! 2678: break; ! 2679: if (*ibp == '\n') { ! 2680: /* Backslash newline is replaced by nothing at all, ! 2681: but keep the line counts correct. */ ! 2682: --obp; ! 2683: ++ibp; ! 2684: ++ip->lineno; ! 2685: } else { ! 2686: /* ANSI stupidly requires that in \\ the second \ ! 2687: is *not* prevented from combining with a newline. */ ! 2688: while (*ibp == '\\' && ibp[1] == '\n') { ! 2689: ibp += 2; ! 2690: ++ip->lineno; ! 2691: } ! 2692: *obp++ = *ibp++; ! 2693: } ! 2694: break; ! 2695: ! 2696: case '\"': ! 2697: case '\'': ! 2698: if (ibp[-1] == c) ! 2699: goto while2end; ! 2700: break; ! 2701: } ! 2702: } ! 2703: while2end: ! 2704: break; ! 2705: ! 2706: case '/': ! 2707: if (*ibp == '\\' && ibp[1] == '\n') ! 2708: newline_fix (ibp); ! 2709: ! 2710: if (*ibp != '*' ! 2711: && !(cplusplus_comments && *ibp == '/')) ! 2712: goto randomchar; ! 2713: if (ip->macro != 0) ! 2714: goto randomchar; ! 2715: if (ident_length) ! 2716: goto specialchar; ! 2717: ! 2718: if (*ibp == '/') { ! 2719: /* C++ style comment... */ ! 2720: start_line = ip->lineno; ! 2721: ! 2722: --ibp; /* Back over the slash */ ! 2723: --obp; ! 2724: ! 2725: /* Comments are equivalent to spaces. */ ! 2726: if (! put_out_comments) ! 2727: *obp++ = ' '; ! 2728: else { ! 2729: /* must fake up a comment here */ ! 2730: *obp++ = '/'; ! 2731: *obp++ = '/'; ! 2732: } ! 2733: { ! 2734: U_CHAR *before_bp = ibp+2; ! 2735: ! 2736: while (ibp < limit) { ! 2737: if (*ibp++ == '\n') { ! 2738: ibp--; ! 2739: if (put_out_comments) { ! 2740: bcopy (before_bp, obp, ibp - before_bp); ! 2741: obp += ibp - before_bp; ! 2742: } ! 2743: break; ! 2744: } ! 2745: } ! 2746: break; ! 2747: } ! 2748: } ! 2749: ! 2750: /* Ordinary C comment. Skip it, optionally copying it to output. */ ! 2751: ! 2752: start_line = ip->lineno; ! 2753: ! 2754: ++ibp; /* Skip the star. */ ! 2755: ! 2756: /* If this cpp is for lint, we peek inside the comments: */ ! 2757: if (lint) { ! 2758: U_CHAR *argbp; ! 2759: int cmdlen, arglen; ! 2760: char *lintcmd = get_lintcmd (ibp, limit, &argbp, &arglen, &cmdlen); ! 2761: ! 2762: if (lintcmd != NULL) { ! 2763: /* I believe it is always safe to emit this newline: */ ! 2764: obp[-1] = '\n'; ! 2765: bcopy ("#pragma lint ", obp, 13); ! 2766: obp += 13; ! 2767: bcopy (lintcmd, obp, cmdlen); ! 2768: obp += cmdlen; ! 2769: ! 2770: if (arglen != 0) { ! 2771: *(obp++) = ' '; ! 2772: bcopy (argbp, obp, arglen); ! 2773: obp += arglen; ! 2774: } ! 2775: ! 2776: /* OK, now bring us back to the state we were in before we entered ! 2777: this branch. We need #line b/c the newline for the pragma ! 2778: could fuck things up. */ ! 2779: output_line_command (ip, op, 0, same_file); ! 2780: *(obp++) = ' '; /* just in case, if comments are copied thru */ ! 2781: *(obp++) = '/'; ! 2782: } ! 2783: } ! 2784: ! 2785: /* Comments are equivalent to spaces. ! 2786: Note that we already output the slash; we might not want it. ! 2787: For -traditional, a comment is equivalent to nothing. */ ! 2788: if (! put_out_comments) { ! 2789: if (traditional) ! 2790: obp--; ! 2791: else ! 2792: obp[-1] = ' '; ! 2793: } ! 2794: else ! 2795: *obp++ = '*'; ! 2796: ! 2797: { ! 2798: U_CHAR *before_bp = ibp; ! 2799: ! 2800: while (ibp < limit) { ! 2801: switch (*ibp++) { ! 2802: case '/': ! 2803: if (warn_comments && ibp < limit && *ibp == '*') ! 2804: warning ("`/*' within comment"); ! 2805: break; ! 2806: case '*': ! 2807: if (*ibp == '\\' && ibp[1] == '\n') ! 2808: newline_fix (ibp); ! 2809: if (ibp >= limit || *ibp == '/') ! 2810: goto comment_end; ! 2811: break; ! 2812: case '\n': ! 2813: ++ip->lineno; ! 2814: /* Copy the newline into the output buffer, in order to ! 2815: avoid the pain of a #line every time a multiline comment ! 2816: is seen. */ ! 2817: if (!put_out_comments) ! 2818: *obp++ = '\n'; ! 2819: ++op->lineno; ! 2820: } ! 2821: } ! 2822: comment_end: ! 2823: ! 2824: if (ibp >= limit) ! 2825: error_with_line (line_for_error (start_line), ! 2826: "unterminated comment"); ! 2827: else { ! 2828: ibp++; ! 2829: if (put_out_comments) { ! 2830: bcopy (before_bp, obp, ibp - before_bp); ! 2831: obp += ibp - before_bp; ! 2832: } ! 2833: } ! 2834: } ! 2835: break; ! 2836: ! 2837: case '$': ! 2838: if (!dollars_in_ident) ! 2839: goto randomchar; ! 2840: goto letter; ! 2841: ! 2842: case '0': case '1': case '2': case '3': case '4': ! 2843: case '5': case '6': case '7': case '8': case '9': ! 2844: /* If digit is not part of identifier, it starts a number, ! 2845: which means that following letters are not an identifier. ! 2846: "0x5" does not refer to an identifier "x5". ! 2847: So copy all alphanumerics that follow without accumulating ! 2848: as an identifier. Periods also, for sake of "3.e7". */ ! 2849: ! 2850: if (ident_length == 0) { ! 2851: while (ibp < limit) { ! 2852: while (ibp < limit && ibp[0] == '\\' && ibp[1] == '\n') { ! 2853: ++ip->lineno; ! 2854: ibp += 2; ! 2855: } ! 2856: c = *ibp++; ! 2857: /* ".." terminates a preprocessing number. This is useless for C ! 2858: code but useful for preprocessing other things. */ ! 2859: if (!isalnum (c) && (c != '.' || *ibp == '.') && c != '_') { ! 2860: --ibp; ! 2861: break; ! 2862: } ! 2863: *obp++ = c; ! 2864: /* A sign can be part of a preprocessing number ! 2865: if it follows an e. */ ! 2866: if (c == 'e' || c == 'E') { ! 2867: while (ibp < limit && ibp[0] == '\\' && ibp[1] == '\n') { ! 2868: ++ip->lineno; ! 2869: ibp += 2; ! 2870: } ! 2871: if (ibp < limit && (*ibp == '+' || *ibp == '-')) { ! 2872: *obp++ = *ibp++; ! 2873: /* But traditional C does not let the token go past the sign. */ ! 2874: if (traditional) ! 2875: break; ! 2876: } ! 2877: } ! 2878: } ! 2879: break; ! 2880: } ! 2881: /* fall through */ ! 2882: ! 2883: case '_': ! 2884: case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': ! 2885: case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': ! 2886: case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': ! 2887: case 's': case 't': case 'u': case 'v': case 'w': case 'x': ! 2888: case 'y': case 'z': ! 2889: case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': ! 2890: case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': ! 2891: case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': ! 2892: case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': ! 2893: case 'Y': case 'Z': ! 2894: letter: ! 2895: ident_length++; ! 2896: /* Compute step of hash function, to avoid a proc call on every token */ ! 2897: hash = HASHSTEP (hash, c); ! 2898: break; ! 2899: ! 2900: case '\n': ! 2901: if (ip->fname == 0 && *ibp == '-') { ! 2902: /* Newline - inhibits expansion of preceding token. ! 2903: If expanding a macro arg, we keep the newline -. ! 2904: In final output, it is deleted. ! 2905: We recognize Newline - in macro bodies and macro args. */ ! 2906: if (! concatenated) { ! 2907: ident_length = 0; ! 2908: hash = 0; ! 2909: } ! 2910: ibp++; ! 2911: if (!output_marks) { ! 2912: obp--; ! 2913: } else { ! 2914: /* If expanding a macro arg, keep the newline -. */ ! 2915: *obp++ = '-'; ! 2916: } ! 2917: break; ! 2918: } ! 2919: ! 2920: /* If reprocessing a macro expansion, newline is a special marker. */ ! 2921: else if (ip->macro != 0) { ! 2922: /* Newline White is a "funny space" to separate tokens that are ! 2923: supposed to be separate but without space between. ! 2924: Here White means any whitespace character. ! 2925: Newline - marks a recursive macro use that is not ! 2926: supposed to be expandable. */ ! 2927: ! 2928: if (is_space[*ibp]) { ! 2929: /* Newline Space does not prevent expansion of preceding token ! 2930: so expand the preceding token and then come back. */ ! 2931: if (ident_length > 0) ! 2932: goto specialchar; ! 2933: ! 2934: /* If generating final output, newline space makes a space. */ ! 2935: if (!output_marks) { ! 2936: obp[-1] = *ibp++; ! 2937: /* And Newline Newline makes a newline, so count it. */ ! 2938: if (obp[-1] == '\n') ! 2939: op->lineno++; ! 2940: } else { ! 2941: /* If expanding a macro arg, keep the newline space. ! 2942: If the arg gets stringified, newline space makes nothing. */ ! 2943: *obp++ = *ibp++; ! 2944: } ! 2945: } else abort (); /* Newline followed by something random? */ ! 2946: break; ! 2947: } ! 2948: ! 2949: /* If there is a pending identifier, handle it and come back here. */ ! 2950: if (ident_length > 0) ! 2951: goto specialchar; ! 2952: ! 2953: beg_of_line = ibp; ! 2954: ! 2955: /* Update the line counts and output a #line if necessary. */ ! 2956: ++ip->lineno; ! 2957: ++op->lineno; ! 2958: if (ip->lineno != op->lineno) { ! 2959: op->bufp = obp; ! 2960: output_line_command (ip, op, 1, same_file); ! 2961: check_expand (op, ip->length - (ip->bufp - ip->buf)); ! 2962: obp = op->bufp; ! 2963: } ! 2964: break; ! 2965: ! 2966: /* Come here either after (1) a null character that is part of the input ! 2967: or (2) at the end of the input, because there is a null there. */ ! 2968: case 0: ! 2969: if (ibp <= limit) ! 2970: /* Our input really contains a null character. */ ! 2971: goto randomchar; ! 2972: ! 2973: /* At end of a macro-expansion level, pop it and read next level. */ ! 2974: if (ip->macro != 0) { ! 2975: obp--; ! 2976: ibp--; ! 2977: /* If traditional, and we have an identifier that ends here, ! 2978: process it now, so we get the right error for recursion. */ ! 2979: if (traditional && ident_length ! 2980: && ! is_idchar[*instack[indepth - 1].bufp]) { ! 2981: redo_char = 1; ! 2982: goto randomchar; ! 2983: } ! 2984: POPMACRO; ! 2985: RECACHE; ! 2986: break; ! 2987: } ! 2988: ! 2989: /* If we don't have a pending identifier, ! 2990: return at end of input. */ ! 2991: if (ident_length == 0) { ! 2992: obp--; ! 2993: ibp--; ! 2994: op->bufp = obp; ! 2995: ip->bufp = ibp; ! 2996: goto ending; ! 2997: } ! 2998: ! 2999: /* If we do have a pending identifier, just consider this null ! 3000: a special character and arrange to dispatch on it again. ! 3001: The second time, IDENT_LENGTH will be zero so we will return. */ ! 3002: ! 3003: /* Fall through */ ! 3004: ! 3005: specialchar: ! 3006: ! 3007: /* Handle the case of a character such as /, ', " or null ! 3008: seen following an identifier. Back over it so that ! 3009: after the identifier is processed the special char ! 3010: will be dispatched on again. */ ! 3011: ! 3012: ibp--; ! 3013: obp--; ! 3014: redo_char = 1; ! 3015: ! 3016: default: ! 3017: ! 3018: randomchar: ! 3019: ! 3020: if (ident_length > 0) { ! 3021: register HASHNODE *hp; ! 3022: ! 3023: /* We have just seen an identifier end. If it's a macro, expand it. ! 3024: ! 3025: IDENT_LENGTH is the length of the identifier ! 3026: and HASH is its hash code. ! 3027: ! 3028: The identifier has already been copied to the output, ! 3029: so if it is a macro we must remove it. ! 3030: ! 3031: If REDO_CHAR is 0, the char that terminated the identifier ! 3032: has been skipped in the output and the input. ! 3033: OBP-IDENT_LENGTH-1 points to the identifier. ! 3034: If the identifier is a macro, we must back over the terminator. ! 3035: ! 3036: If REDO_CHAR is 1, the terminating char has already been ! 3037: backed over. OBP-IDENT_LENGTH points to the identifier. */ ! 3038: ! 3039: if (!pcp_outfile || pcp_inside_if) { ! 3040: startagain: ! 3041: for (hp = hashtab[MAKE_POS (hash) % HASHSIZE]; hp != NULL; ! 3042: hp = hp->next) { ! 3043: ! 3044: if (hp->length == ident_length) { ! 3045: int obufp_before_macroname; ! 3046: int op_lineno_before_macroname; ! 3047: register int i = ident_length; ! 3048: register U_CHAR *p = hp->name; ! 3049: register U_CHAR *q = obp - i; ! 3050: int disabled; ! 3051: ! 3052: if (! redo_char) ! 3053: q--; ! 3054: ! 3055: do { /* All this to avoid a strncmp () */ ! 3056: if (*p++ != *q++) ! 3057: goto hashcollision; ! 3058: } while (--i); ! 3059: ! 3060: /* We found a use of a macro name. ! 3061: see if the context shows it is a macro call. */ ! 3062: ! 3063: /* Back up over terminating character if not already done. */ ! 3064: if (! redo_char) { ! 3065: ibp--; ! 3066: obp--; ! 3067: } ! 3068: ! 3069: /* Save this as a displacement from the beginning of the output ! 3070: buffer. We can not save this as a position in the output ! 3071: buffer, because it may get realloc'ed by RECACHE. */ ! 3072: obufp_before_macroname = (obp - op->buf) - ident_length; ! 3073: op_lineno_before_macroname = op->lineno; ! 3074: ! 3075: if (hp->type == T_PCSTRING) { ! 3076: pcstring_used (hp); /* Mark the definition of this key ! 3077: as needed, ensuring that it ! 3078: will be output. */ ! 3079: break; /* Exit loop, since the key cannot have a ! 3080: definition any longer. */ ! 3081: } ! 3082: ! 3083: /* Record whether the macro is disabled. */ ! 3084: disabled = hp->type == T_DISABLED; ! 3085: ! 3086: /* This looks like a macro ref, but if the macro was disabled, ! 3087: just copy its name and put in a marker if requested. */ ! 3088: ! 3089: if (disabled) { ! 3090: #if 0 ! 3091: /* This error check caught useful cases such as ! 3092: #define foo(x,y) bar (x (y,0), y) ! 3093: foo (foo, baz) */ ! 3094: if (traditional) ! 3095: error ("recursive use of macro `%s'", hp->name); ! 3096: #endif ! 3097: ! 3098: if (output_marks) { ! 3099: check_expand (op, limit - ibp + 2); ! 3100: *obp++ = '\n'; ! 3101: *obp++ = '-'; ! 3102: } ! 3103: break; ! 3104: } ! 3105: ! 3106: /* If macro wants an arglist, verify that a '(' follows. ! 3107: first skip all whitespace, copying it to the output ! 3108: after the macro name. Then, if there is no '(', ! 3109: decide this is not a macro call and leave things that way. */ ! 3110: if ((hp->type == T_MACRO || hp->type == T_DISABLED) ! 3111: && hp->value.defn->nargs >= 0) ! 3112: { ! 3113: U_CHAR *old_ibp = ibp; ! 3114: U_CHAR *old_obp = obp; ! 3115: int old_iln = ip->lineno; ! 3116: int old_oln = op->lineno; ! 3117: ! 3118: while (1) { ! 3119: /* Scan forward over whitespace, copying it to the output. */ ! 3120: if (ibp == limit && ip->macro != 0) { ! 3121: POPMACRO; ! 3122: RECACHE; ! 3123: old_ibp = ibp; ! 3124: old_obp = obp; ! 3125: old_iln = ip->lineno; ! 3126: old_oln = op->lineno; ! 3127: } ! 3128: /* A comment: copy it unchanged or discard it. */ ! 3129: else if (*ibp == '/' && ibp+1 != limit && ibp[1] == '*') { ! 3130: if (put_out_comments) { ! 3131: *obp++ = '/'; ! 3132: *obp++ = '*'; ! 3133: } else if (! traditional) { ! 3134: *obp++ = ' '; ! 3135: } ! 3136: ibp += 2; ! 3137: while (ibp + 1 != limit ! 3138: && !(ibp[0] == '*' && ibp[1] == '/')) { ! 3139: /* We need not worry about newline-marks, ! 3140: since they are never found in comments. */ ! 3141: if (*ibp == '\n') { ! 3142: /* Newline in a file. Count it. */ ! 3143: ++ip->lineno; ! 3144: ++op->lineno; ! 3145: } ! 3146: if (put_out_comments) ! 3147: *obp++ = *ibp++; ! 3148: else ! 3149: ibp++; ! 3150: } ! 3151: ibp += 2; ! 3152: if (put_out_comments) { ! 3153: *obp++ = '*'; ! 3154: *obp++ = '/'; ! 3155: } ! 3156: } ! 3157: else if (is_space[*ibp]) { ! 3158: *obp++ = *ibp++; ! 3159: if (ibp[-1] == '\n') { ! 3160: if (ip->macro == 0) { ! 3161: /* Newline in a file. Count it. */ ! 3162: ++ip->lineno; ! 3163: ++op->lineno; ! 3164: } else if (!output_marks) { ! 3165: /* A newline mark, and we don't want marks ! 3166: in the output. If it is newline-hyphen, ! 3167: discard it entirely. Otherwise, it is ! 3168: newline-whitechar, so keep the whitechar. */ ! 3169: obp--; ! 3170: if (*ibp == '-') ! 3171: ibp++; ! 3172: else { ! 3173: if (*ibp == '\n') ! 3174: ++op->lineno; ! 3175: *obp++ = *ibp++; ! 3176: } ! 3177: } else { ! 3178: /* A newline mark; copy both chars to the output. */ ! 3179: *obp++ = *ibp++; ! 3180: } ! 3181: } ! 3182: } ! 3183: else break; ! 3184: } ! 3185: if (*ibp != '(') { ! 3186: /* It isn't a macro call. ! 3187: Put back the space that we just skipped. */ ! 3188: ibp = old_ibp; ! 3189: obp = old_obp; ! 3190: ip->lineno = old_iln; ! 3191: op->lineno = old_oln; ! 3192: /* Exit the for loop. */ ! 3193: break; ! 3194: } ! 3195: } ! 3196: ! 3197: /* This is now known to be a macro call. ! 3198: Discard the macro name from the output, ! 3199: along with any following whitespace just copied. */ ! 3200: obp = op->buf + obufp_before_macroname; ! 3201: op->lineno = op_lineno_before_macroname; ! 3202: ! 3203: /* Prevent accidental token-pasting with a character ! 3204: before the macro call. */ ! 3205: if (!traditional && obp != op->buf ! 3206: && (obp[-1] == '-' || obp[1] == '+' || obp[1] == '&' ! 3207: || obp[-1] == '|' || obp[1] == '<' || obp[1] == '>')) { ! 3208: /* If we are expanding a macro arg, make a newline marker ! 3209: to separate the tokens. If we are making real output, ! 3210: a plain space will do. */ ! 3211: if (output_marks) ! 3212: *obp++ = '\n'; ! 3213: *obp++ = ' '; ! 3214: } ! 3215: ! 3216: /* Expand the macro, reading arguments as needed, ! 3217: and push the expansion on the input stack. */ ! 3218: ip->bufp = ibp; ! 3219: op->bufp = obp; ! 3220: macroexpand (hp, op); ! 3221: ! 3222: /* Reexamine input stack, since macroexpand has pushed ! 3223: a new level on it. */ ! 3224: obp = op->bufp; ! 3225: RECACHE; ! 3226: break; ! 3227: } ! 3228: hashcollision: ! 3229: ; ! 3230: } /* End hash-table-search loop */ ! 3231: } ! 3232: ident_length = hash = 0; /* Stop collecting identifier */ ! 3233: redo_char = 0; ! 3234: concatenated = 0; ! 3235: } /* End if (ident_length > 0) */ ! 3236: } /* End switch */ ! 3237: } /* End per-char loop */ ! 3238: ! 3239: /* Come here to return -- but first give an error message ! 3240: if there was an unterminated successful conditional. */ ! 3241: ending: ! 3242: if (if_stack != ip->if_stack) { ! 3243: char *str; ! 3244: switch (if_stack->type) { ! 3245: case T_IF: ! 3246: str = "if"; ! 3247: break; ! 3248: case T_IFDEF: ! 3249: str = "ifdef"; ! 3250: break; ! 3251: case T_IFNDEF: ! 3252: str = "ifndef"; ! 3253: break; ! 3254: case T_ELSE: ! 3255: str = "else"; ! 3256: break; ! 3257: case T_ELIF: ! 3258: str = "elif"; ! 3259: break; ! 3260: } ! 3261: error_with_line (line_for_error (if_stack->lineno), ! 3262: "unterminated `#%s' conditional", str); ! 3263: } ! 3264: if_stack = ip->if_stack; ! 3265: } ! 3266: ! 3267: /* ! 3268: * Rescan a string into a temporary buffer and return the result ! 3269: * as a FILE_BUF. Note this function returns a struct, not a pointer. ! 3270: * ! 3271: * OUTPUT_MARKS nonzero means keep Newline markers found in the input ! 3272: * and insert such markers when appropriate. See `rescan' for details. ! 3273: * OUTPUT_MARKS is 1 for macroexpanding a macro argument separately ! 3274: * before substitution; it is 0 for other uses. ! 3275: */ ! 3276: static FILE_BUF ! 3277: expand_to_temp_buffer (buf, limit, output_marks, assertions) ! 3278: U_CHAR *buf, *limit; ! 3279: int output_marks, assertions; ! 3280: { ! 3281: register FILE_BUF *ip; ! 3282: FILE_BUF obuf; ! 3283: int length = limit - buf; ! 3284: U_CHAR *buf1; ! 3285: int odepth = indepth; ! 3286: int save_assertions_flag = assertions_flag; ! 3287: ! 3288: assertions_flag = assertions; ! 3289: ! 3290: if (length < 0) ! 3291: abort (); ! 3292: ! 3293: /* Set up the input on the input stack. */ ! 3294: ! 3295: buf1 = (U_CHAR *) alloca (length + 1); ! 3296: { ! 3297: register U_CHAR *p1 = buf; ! 3298: register U_CHAR *p2 = buf1; ! 3299: ! 3300: while (p1 != limit) ! 3301: *p2++ = *p1++; ! 3302: } ! 3303: buf1[length] = 0; ! 3304: ! 3305: /* Set up to receive the output. */ ! 3306: ! 3307: obuf.length = length * 2 + 100; /* Usually enough. Why be stingy? */ ! 3308: obuf.bufp = obuf.buf = (U_CHAR *) xmalloc (obuf.length); ! 3309: obuf.fname = 0; ! 3310: obuf.macro = 0; ! 3311: obuf.free_ptr = 0; ! 3312: ! 3313: CHECK_DEPTH ({return obuf;}); ! 3314: ! 3315: ++indepth; ! 3316: ! 3317: ip = &instack[indepth]; ! 3318: ip->fname = 0; ! 3319: ip->nominal_fname = 0; ! 3320: ip->system_header_p = 0; ! 3321: ip->macro = 0; ! 3322: ip->free_ptr = 0; ! 3323: ip->length = length; ! 3324: ip->buf = ip->bufp = buf1; ! 3325: ip->if_stack = if_stack; ! 3326: ! 3327: ip->lineno = obuf.lineno = 1; ! 3328: ! 3329: /* Scan the input, create the output. */ ! 3330: rescan (&obuf, output_marks); ! 3331: ! 3332: /* Pop input stack to original state. */ ! 3333: --indepth; ! 3334: ! 3335: if (indepth != odepth) ! 3336: abort (); ! 3337: ! 3338: /* Record the output. */ ! 3339: obuf.length = obuf.bufp - obuf.buf; ! 3340: ! 3341: assertions_flag = save_assertions_flag; ! 3342: return obuf; ! 3343: } ! 3344: ! 3345: /* ! 3346: * Process a # directive. Expects IP->bufp to point after the '#', as in ! 3347: * `#define foo bar'. Passes to the command handler ! 3348: * (do_define, do_include, etc.): the addresses of the 1st and ! 3349: * last chars of the command (starting immediately after the # ! 3350: * keyword), plus op and the keyword table pointer. If the command ! 3351: * contains comments it is copied into a temporary buffer sans comments ! 3352: * and the temporary buffer is passed to the command handler instead. ! 3353: * Likewise for backslash-newlines. ! 3354: * ! 3355: * Returns nonzero if this was a known # directive. ! 3356: * Otherwise, returns zero, without advancing the input pointer. ! 3357: */ ! 3358: ! 3359: static int ! 3360: handle_directive (ip, op) ! 3361: FILE_BUF *ip, *op; ! 3362: { ! 3363: register U_CHAR *bp, *cp; ! 3364: register struct directive *kt; ! 3365: register int ident_length; ! 3366: U_CHAR *resume_p; ! 3367: ! 3368: /* Nonzero means we must copy the entire command ! 3369: to get rid of comments or backslash-newlines. */ ! 3370: int copy_command = 0; ! 3371: ! 3372: U_CHAR *ident, *after_ident; ! 3373: ! 3374: bp = ip->bufp; ! 3375: ! 3376: /* Record where the directive started. do_xifdef needs this. */ ! 3377: directive_start = bp - 1; ! 3378: ! 3379: /* Skip whitespace and \-newline. */ ! 3380: while (1) { ! 3381: if (is_hor_space[*bp]) { ! 3382: if ((*bp == '\f' || *bp == '\v') && pedantic) ! 3383: pedwarn ("%s in preprocessing directive", ! 3384: *bp == '\f' ? "formfeed" : "vertical tab"); ! 3385: bp++; ! 3386: } else if (*bp == '/' && bp[1] == '*') { ! 3387: ip->bufp = bp; ! 3388: skip_to_end_of_comment (ip, &ip->lineno, 0); ! 3389: bp = ip->bufp; ! 3390: } else if (*bp == '\\' && bp[1] == '\n') { ! 3391: bp += 2; ip->lineno++; ! 3392: } else break; ! 3393: } ! 3394: ! 3395: /* Now find end of directive name. ! 3396: If we encounter a backslash-newline, exchange it with any following ! 3397: symbol-constituents so that we end up with a contiguous name. */ ! 3398: ! 3399: cp = bp; ! 3400: while (1) { ! 3401: if (is_idchar[*cp]) ! 3402: cp++; ! 3403: else { ! 3404: if (*cp == '\\' && cp[1] == '\n') ! 3405: name_newline_fix (cp); ! 3406: if (is_idchar[*cp]) ! 3407: cp++; ! 3408: else break; ! 3409: } ! 3410: } ! 3411: ident_length = cp - bp; ! 3412: ident = bp; ! 3413: after_ident = cp; ! 3414: ! 3415: /* A line of just `#' becomes blank. */ ! 3416: ! 3417: if (ident_length == 0 && *after_ident == '\n') { ! 3418: ip->bufp = after_ident; ! 3419: return 1; ! 3420: } ! 3421: ! 3422: if (ident_length == 0 || !is_idstart[*ident]) { ! 3423: U_CHAR *p = ident; ! 3424: while (is_idchar[*p]) { ! 3425: if (*p < '0' || *p > '9') ! 3426: break; ! 3427: p++; ! 3428: } ! 3429: /* Handle # followed by a line number. */ ! 3430: if (p != ident && !is_idchar[*p]) { ! 3431: static struct directive line_directive_table[] = { ! 3432: { 4, do_line, "line", T_LINE}, ! 3433: }; ! 3434: if (pedantic) ! 3435: pedwarn ("`#' followed by integer"); ! 3436: after_ident = ident; ! 3437: kt = line_directive_table; ! 3438: goto old_linenum; ! 3439: } ! 3440: ! 3441: /* Avoid error for `###' and similar cases unless -pedantic. */ ! 3442: if (p == ident) { ! 3443: while (*p == '#' || is_hor_space[*p]) p++; ! 3444: if (*p == '\n') { ! 3445: if (pedantic && !lang_asm) ! 3446: warning ("invalid preprocessor directive"); ! 3447: return 0; ! 3448: } ! 3449: } ! 3450: ! 3451: if (!lang_asm) ! 3452: error ("invalid preprocessor directive name"); ! 3453: ! 3454: return 0; ! 3455: } ! 3456: ! 3457: /* ! 3458: * Decode the keyword and call the appropriate expansion ! 3459: * routine, after moving the input pointer up to the next line. ! 3460: */ ! 3461: for (kt = directive_table; kt->length > 0; kt++) { ! 3462: if (kt->length == ident_length && !strncmp (kt->name, ident, ident_length)) { ! 3463: register U_CHAR *buf; ! 3464: register U_CHAR *limit; ! 3465: int unterminated; ! 3466: int junk; ! 3467: int *already_output; ! 3468: ! 3469: /* Nonzero means do not delete comments within the directive. ! 3470: #define needs this when -traditional. */ ! 3471: int keep_comments; ! 3472: ! 3473: old_linenum: ! 3474: ! 3475: limit = ip->buf + ip->length; ! 3476: unterminated = 0; ! 3477: already_output = 0; ! 3478: keep_comments = traditional && kt->traditional_comments; ! 3479: #ifndef NEXT_OBJC_RUNTIME ! 3480: /* #import is defined only in Objective C, or when on the NeXT. */ ! 3481: if (kt->type == T_IMPORT && !(objc || lookup ("__NeXT__", -1, -1))) ! 3482: break; ! 3483: #endif ! 3484: ! 3485: /* Find the end of this command (first newline not backslashed ! 3486: and not in a string or comment). ! 3487: Set COPY_COMMAND if the command must be copied ! 3488: (it contains a backslash-newline or a comment). */ ! 3489: ! 3490: buf = bp = after_ident; ! 3491: while (bp < limit) { ! 3492: register U_CHAR c = *bp++; ! 3493: switch (c) { ! 3494: case '\\': ! 3495: if (bp < limit) { ! 3496: if (*bp == '\n') { ! 3497: ip->lineno++; ! 3498: copy_command = 1; ! 3499: } ! 3500: bp++; ! 3501: } ! 3502: break; ! 3503: ! 3504: case '\'': ! 3505: case '\"': ! 3506: bp = skip_quoted_string (bp - 1, limit, ip->lineno, &ip->lineno, ©_command, &unterminated); ! 3507: /* Don't bother calling the directive if we already got an error ! 3508: message due to unterminated string. Skip everything and pretend ! 3509: we called the directive. */ ! 3510: if (unterminated) { ! 3511: if (traditional) { ! 3512: /* Traditional preprocessing permits unterminated strings. */ ! 3513: ip->bufp = bp; ! 3514: goto endloop1; ! 3515: } ! 3516: ip->bufp = bp; ! 3517: return 1; ! 3518: } ! 3519: break; ! 3520: ! 3521: /* <...> is special for #include. */ ! 3522: case '<': ! 3523: if (!kt->angle_brackets) ! 3524: break; ! 3525: while (*bp && *bp != '>') bp++; ! 3526: break; ! 3527: ! 3528: case '/': ! 3529: if (*bp == '\\' && bp[1] == '\n') ! 3530: newline_fix (bp); ! 3531: if (*bp == '*' ! 3532: || (cplusplus_comments && *bp == '/')) { ! 3533: U_CHAR *obp = bp - 1; ! 3534: ip->bufp = bp + 1; ! 3535: skip_to_end_of_comment (ip, &ip->lineno, 0); ! 3536: bp = ip->bufp; ! 3537: /* No need to copy the command because of a comment at the end; ! 3538: just don't include the comment in the directive. */ ! 3539: if (bp == limit || *bp == '\n') { ! 3540: bp = obp; ! 3541: goto endloop1; ! 3542: } ! 3543: /* Don't remove the comments if -traditional. */ ! 3544: if (! keep_comments) ! 3545: copy_command++; ! 3546: } ! 3547: break; ! 3548: ! 3549: case '\f': ! 3550: case '\v': ! 3551: if (pedantic) ! 3552: pedwarn ("%s in preprocessing directive", ! 3553: c == '\f' ? "formfeed" : "vertical tab"); ! 3554: break; ! 3555: ! 3556: case '\n': ! 3557: --bp; /* Point to the newline */ ! 3558: ip->bufp = bp; ! 3559: goto endloop1; ! 3560: } ! 3561: } ! 3562: ip->bufp = bp; ! 3563: ! 3564: endloop1: ! 3565: resume_p = ip->bufp; ! 3566: /* BP is the end of the directive. ! 3567: RESUME_P is the next interesting data after the directive. ! 3568: A comment may come between. */ ! 3569: ! 3570: /* If a directive should be copied through, and -E was given, ! 3571: pass it through before removing comments. */ ! 3572: if (!no_output && kt->pass_thru && put_out_comments) { ! 3573: int len; ! 3574: ! 3575: /* Output directive name. */ ! 3576: check_expand (op, kt->length + 2); ! 3577: /* Make sure # is at the start of a line */ ! 3578: if (op->bufp > op->buf && op->bufp[-1] != '\n') { ! 3579: op->lineno++; ! 3580: *op->bufp++ = '\n'; ! 3581: } ! 3582: *op->bufp++ = '#'; ! 3583: bcopy (kt->name, op->bufp, kt->length); ! 3584: op->bufp += kt->length; ! 3585: ! 3586: /* Output arguments. */ ! 3587: len = (bp - buf); ! 3588: check_expand (op, len); ! 3589: bcopy (buf, op->bufp, len); ! 3590: op->bufp += len; ! 3591: /* Take account of any (escaped) newlines just output. */ ! 3592: while (--len >= 0) ! 3593: if (buf[len] == '\n') ! 3594: op->lineno++; ! 3595: ! 3596: already_output = &junk; ! 3597: } /* Don't we need a newline or #line? */ ! 3598: ! 3599: if (copy_command) { ! 3600: register U_CHAR *xp = buf; ! 3601: /* Need to copy entire command into temp buffer before dispatching */ ! 3602: ! 3603: cp = (U_CHAR *) alloca (bp - buf + 5); /* room for cmd plus ! 3604: some slop */ ! 3605: buf = cp; ! 3606: ! 3607: /* Copy to the new buffer, deleting comments ! 3608: and backslash-newlines (and whitespace surrounding the latter). */ ! 3609: ! 3610: while (xp < bp) { ! 3611: register U_CHAR c = *xp++; ! 3612: *cp++ = c; ! 3613: ! 3614: switch (c) { ! 3615: case '\n': ! 3616: abort (); /* A bare newline should never part of the line. */ ! 3617: break; ! 3618: ! 3619: /* <...> is special for #include. */ ! 3620: case '<': ! 3621: if (!kt->angle_brackets) ! 3622: break; ! 3623: while (xp < bp && c != '>') { ! 3624: c = *xp++; ! 3625: if (c == '\\' && xp < bp && *xp == '\n') ! 3626: xp++; ! 3627: else ! 3628: *cp++ = c; ! 3629: } ! 3630: break; ! 3631: ! 3632: case '\\': ! 3633: if (*xp == '\n') { ! 3634: xp++; ! 3635: cp--; ! 3636: if (cp != buf && is_space[cp[-1]]) { ! 3637: while (cp != buf && is_space[cp[-1]]) cp--; ! 3638: cp++; ! 3639: SKIP_WHITE_SPACE (xp); ! 3640: } else if (is_space[*xp]) { ! 3641: *cp++ = *xp++; ! 3642: SKIP_WHITE_SPACE (xp); ! 3643: } ! 3644: } else { ! 3645: *cp++ = *xp++; ! 3646: } ! 3647: break; ! 3648: ! 3649: case '\'': ! 3650: case '\"': ! 3651: { ! 3652: register U_CHAR *bp1 ! 3653: = skip_quoted_string (xp - 1, bp, ip->lineno, ! 3654: NULL_PTR, NULL_PTR, NULL_PTR); ! 3655: while (xp != bp1) ! 3656: if (*xp == '\\') { ! 3657: if (*++xp != '\n') ! 3658: *cp++ = '\\'; ! 3659: else ! 3660: xp++; ! 3661: } else ! 3662: *cp++ = *xp++; ! 3663: } ! 3664: break; ! 3665: ! 3666: case '/': ! 3667: if (*xp == '*' ! 3668: || (cplusplus_comments && *xp == '/')) { ! 3669: ip->bufp = xp + 1; ! 3670: /* If we already copied the command through, ! 3671: already_output != 0 prevents outputting comment now. */ ! 3672: skip_to_end_of_comment (ip, already_output, 0); ! 3673: if (keep_comments) ! 3674: while (xp != ip->bufp) ! 3675: *cp++ = *xp++; ! 3676: /* Delete or replace the slash. */ ! 3677: else if (traditional) ! 3678: cp--; ! 3679: else ! 3680: cp[-1] = ' '; ! 3681: xp = ip->bufp; ! 3682: } ! 3683: } ! 3684: } ! 3685: ! 3686: /* Null-terminate the copy. */ ! 3687: ! 3688: *cp = 0; ! 3689: } else ! 3690: cp = bp; ! 3691: ! 3692: ip->bufp = resume_p; ! 3693: ! 3694: /* Some directives should be written out for cc1 to process, ! 3695: just as if they were not defined. And sometimes we're copying ! 3696: definitions through. */ ! 3697: ! 3698: if (!no_output && already_output == 0 ! 3699: && (kt->pass_thru ! 3700: || (kt->type == T_DEFINE ! 3701: && (dump_macros == dump_names ! 3702: || dump_macros == dump_definitions)))) { ! 3703: int len; ! 3704: ! 3705: /* Output directive name. */ ! 3706: check_expand (op, kt->length + 1); ! 3707: *op->bufp++ = '#'; ! 3708: bcopy (kt->name, op->bufp, kt->length); ! 3709: op->bufp += kt->length; ! 3710: ! 3711: if (kt->pass_thru || dump_macros == dump_definitions) { ! 3712: /* Output arguments. */ ! 3713: len = (cp - buf); ! 3714: check_expand (op, len); ! 3715: bcopy (buf, op->bufp, len); ! 3716: op->bufp += len; ! 3717: } else if (kt->type == T_DEFINE && dump_macros == dump_names) { ! 3718: U_CHAR *xp = buf; ! 3719: U_CHAR *yp; ! 3720: SKIP_WHITE_SPACE (xp); ! 3721: yp = xp; ! 3722: while (is_idchar[*xp]) xp++; ! 3723: len = (xp - yp); ! 3724: check_expand (op, len + 1); ! 3725: *op->bufp++ = ' '; ! 3726: bcopy (yp, op->bufp, len); ! 3727: op->bufp += len; ! 3728: } ! 3729: } /* Don't we need a newline or #line? */ ! 3730: ! 3731: /* Call the appropriate command handler. buf now points to ! 3732: either the appropriate place in the input buffer, or to ! 3733: the temp buffer if it was necessary to make one. cp ! 3734: points to the first char after the contents of the (possibly ! 3735: copied) command, in either case. */ ! 3736: (*kt->func) (buf, cp, op, kt); ! 3737: check_expand (op, ip->length - (ip->bufp - ip->buf)); ! 3738: ! 3739: return 1; ! 3740: } ! 3741: } ! 3742: ! 3743: /* It is deliberate that we don't warn about undefined directives. ! 3744: That is the responsibility of cc1. */ ! 3745: return 0; ! 3746: } ! 3747: ! 3748: static struct tm * ! 3749: timestamp () ! 3750: { ! 3751: static struct tm *timebuf; ! 3752: if (!timebuf) { ! 3753: time_t t = time (0); ! 3754: timebuf = localtime (&t); ! 3755: } ! 3756: return timebuf; ! 3757: } ! 3758: ! 3759: static char *monthnames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", ! 3760: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ! 3761: }; ! 3762: ! 3763: /* ! 3764: * expand things like __FILE__. Place the expansion into the output ! 3765: * buffer *without* rescanning. ! 3766: */ ! 3767: ! 3768: static void ! 3769: special_symbol (hp, op) ! 3770: HASHNODE *hp; ! 3771: FILE_BUF *op; ! 3772: { ! 3773: char *buf; ! 3774: int i, len; ! 3775: int true_indepth; ! 3776: FILE_BUF *ip = NULL; ! 3777: struct tm *timebuf; ! 3778: ! 3779: int paren = 0; /* For special `defined' keyword */ ! 3780: ! 3781: if (pcp_outfile && pcp_inside_if ! 3782: && hp->type != T_SPEC_DEFINED && hp->type != T_CONST) ! 3783: error ("Predefined macro `%s' used inside `#if' during precompilation", ! 3784: hp->name); ! 3785: ! 3786: for (i = indepth; i >= 0; i--) ! 3787: if (instack[i].fname != NULL) { ! 3788: ip = &instack[i]; ! 3789: break; ! 3790: } ! 3791: if (ip == NULL) { ! 3792: error ("cccp error: not in any file?!"); ! 3793: return; /* the show must go on */ ! 3794: } ! 3795: ! 3796: switch (hp->type) { ! 3797: case T_FILE: ! 3798: case T_BASE_FILE: ! 3799: { ! 3800: char *string; ! 3801: if (hp->type == T_FILE) ! 3802: string = ip->nominal_fname; ! 3803: else ! 3804: string = instack[0].nominal_fname; ! 3805: ! 3806: if (string) ! 3807: { ! 3808: buf = (char *) alloca (3 + 4 * strlen (string)); ! 3809: quote_string (buf, string); ! 3810: } ! 3811: else ! 3812: buf = "\"\""; ! 3813: ! 3814: break; ! 3815: } ! 3816: ! 3817: case T_INCLUDE_LEVEL: ! 3818: true_indepth = 0; ! 3819: for (i = indepth; i >= 0; i--) ! 3820: if (instack[i].fname != NULL) ! 3821: true_indepth++; ! 3822: ! 3823: buf = (char *) alloca (8); /* Eight bytes ought to be more than enough */ ! 3824: sprintf (buf, "%d", true_indepth - 1); ! 3825: break; ! 3826: ! 3827: case T_VERSION: ! 3828: buf = (char *) alloca (3 + strlen (version_string)); ! 3829: sprintf (buf, "\"%s\"", version_string); ! 3830: break; ! 3831: ! 3832: #ifndef NO_BUILTIN_SIZE_TYPE ! 3833: case T_SIZE_TYPE: ! 3834: buf = (char *) alloca (3 + strlen (SIZE_TYPE)); ! 3835: sprintf (buf, "%s", SIZE_TYPE); ! 3836: break; ! 3837: #endif ! 3838: ! 3839: #ifndef NO_BUILTIN_PTRDIFF_TYPE ! 3840: case T_PTRDIFF_TYPE: ! 3841: buf = (char *) alloca (3 + strlen (PTRDIFF_TYPE)); ! 3842: sprintf (buf, "%s", PTRDIFF_TYPE); ! 3843: break; ! 3844: #endif ! 3845: ! 3846: case T_WCHAR_TYPE: ! 3847: buf = (char *) alloca (3 + strlen (WCHAR_TYPE)); ! 3848: sprintf (buf, "%s", WCHAR_TYPE); ! 3849: break; ! 3850: ! 3851: case T_USER_LABEL_PREFIX_TYPE: ! 3852: buf = (char *) alloca (3 + strlen (USER_LABEL_PREFIX)); ! 3853: sprintf (buf, "%s", USER_LABEL_PREFIX); ! 3854: break; ! 3855: ! 3856: case T_REGISTER_PREFIX_TYPE: ! 3857: buf = (char *) alloca (3 + strlen (REGISTER_PREFIX)); ! 3858: sprintf (buf, "%s", REGISTER_PREFIX); ! 3859: break; ! 3860: ! 3861: case T_CONST: ! 3862: buf = (char *) alloca (4 * sizeof (int)); ! 3863: sprintf (buf, "%d", hp->value.ival); ! 3864: if (pcp_inside_if && pcp_outfile) ! 3865: /* Output a precondition for this macro use */ ! 3866: fprintf (pcp_outfile, "#define %s %d\n", hp->name, hp->value.ival); ! 3867: break; ! 3868: ! 3869: case T_SPECLINE: ! 3870: buf = (char *) alloca (10); ! 3871: sprintf (buf, "%d", ip->lineno); ! 3872: break; ! 3873: ! 3874: case T_DATE: ! 3875: case T_TIME: ! 3876: buf = (char *) alloca (20); ! 3877: timebuf = timestamp (); ! 3878: if (hp->type == T_DATE) ! 3879: sprintf (buf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon], ! 3880: timebuf->tm_mday, timebuf->tm_year + 1900); ! 3881: else ! 3882: sprintf (buf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min, ! 3883: timebuf->tm_sec); ! 3884: break; ! 3885: ! 3886: case T_SPEC_DEFINED: ! 3887: buf = " 0 "; /* Assume symbol is not defined */ ! 3888: ip = &instack[indepth]; ! 3889: SKIP_WHITE_SPACE (ip->bufp); ! 3890: if (*ip->bufp == '(') { ! 3891: paren++; ! 3892: ip->bufp++; /* Skip over the paren */ ! 3893: SKIP_WHITE_SPACE (ip->bufp); ! 3894: } ! 3895: ! 3896: if (!is_idstart[*ip->bufp]) ! 3897: goto oops; ! 3898: if (hp = lookup (ip->bufp, -1, -1)) { ! 3899: if (pcp_outfile && pcp_inside_if ! 3900: && hp->value.defn->predefined) ! 3901: /* Output a precondition for this macro use. */ ! 3902: fprintf (pcp_outfile, "#define %s\n", hp->name); ! 3903: buf = " 1 "; ! 3904: } ! 3905: else ! 3906: if (pcp_outfile && pcp_inside_if) { ! 3907: /* Output a precondition for this macro use */ ! 3908: U_CHAR *cp = ip->bufp; ! 3909: fprintf (pcp_outfile, "#undef "); ! 3910: while (is_idchar[*cp]) /* Ick! */ ! 3911: fputc (*cp++, pcp_outfile); ! 3912: putc ('\n', pcp_outfile); ! 3913: } ! 3914: while (is_idchar[*ip->bufp]) ! 3915: ++ip->bufp; ! 3916: SKIP_WHITE_SPACE (ip->bufp); ! 3917: if (paren) { ! 3918: if (*ip->bufp != ')') ! 3919: goto oops; ! 3920: ++ip->bufp; ! 3921: } ! 3922: break; ! 3923: ! 3924: oops: ! 3925: ! 3926: error ("`defined' without an identifier"); ! 3927: break; ! 3928: ! 3929: default: ! 3930: error ("cccp error: invalid special hash type"); /* time for gdb */ ! 3931: abort (); ! 3932: } ! 3933: len = strlen (buf); ! 3934: check_expand (op, len); ! 3935: bcopy (buf, op->bufp, len); ! 3936: op->bufp += len; ! 3937: ! 3938: return; ! 3939: } ! 3940: ! 3941: ! 3942: /* Routines to handle #directives */ ! 3943: ! 3944: /* Handle #include and #import. ! 3945: This function expects to see "fname" or <fname> on the input. */ ! 3946: ! 3947: static int ! 3948: do_include (buf, limit, op, keyword) ! 3949: U_CHAR *buf, *limit; ! 3950: FILE_BUF *op; ! 3951: struct directive *keyword; ! 3952: { ! 3953: int importing = (keyword->type == T_IMPORT); ! 3954: int skip_dirs = (keyword->type == T_INCLUDE_NEXT); ! 3955: #ifdef NEXT_OBJC_RUNTIME ! 3956: static int import_warning = 1; ! 3957: #else ! 3958: static int import_warning = 0; ! 3959: #endif ! 3960: char *fname; /* Dynamically allocated fname buffer */ ! 3961: char *pcftry; ! 3962: char *pcfname; ! 3963: U_CHAR *fbeg, *fend; /* Beginning and end of fname */ ! 3964: ! 3965: struct file_name_list *search_start = include; /* Chain of dirs to search */ ! 3966: struct file_name_list dsp[1]; /* First in chain, if #include "..." */ ! 3967: struct file_name_list *searchptr = 0; ! 3968: int flen; ! 3969: ! 3970: int f; /* file number */ ! 3971: ! 3972: int retried = 0; /* Have already tried macro ! 3973: expanding the include line*/ ! 3974: FILE_BUF trybuf; /* It got expanded into here */ ! 3975: int angle_brackets = 0; /* 0 for "...", 1 for <...> */ ! 3976: int pcf = -1; ! 3977: char *pcfbuf; ! 3978: int pcfbuflimit; ! 3979: int pcfnum; ! 3980: #ifdef NEXT_OBJC_RUNTIME ! 3981: U_CHAR *partial = NULL; ! 3982: int plen = 0; ! 3983: #endif ! 3984: f= -1; /* JF we iz paranoid! */ ! 3985: ! 3986: if (importing && warn_import && !inhibit_warnings ! 3987: && !instack[indepth].system_header_p && !import_warning) { ! 3988: import_warning = 1; ! 3989: warning ("using `#import' is not recommended"); ! 3990: fprintf (stderr, "The fact that a certain header file need not be processed more than once\n"); ! 3991: fprintf (stderr, "should be indicated in the header file, not where it is used.\n"); ! 3992: fprintf (stderr, "The best way to do this is with a conditional of this form:\n\n"); ! 3993: fprintf (stderr, " #ifndef _FOO_H_INCLUDED\n"); ! 3994: fprintf (stderr, " #define _FOO_H_INCLUDED\n"); ! 3995: fprintf (stderr, " ... <real contents of file> ...\n"); ! 3996: fprintf (stderr, " #endif /* Not _FOO_H_INCLUDED */\n\n"); ! 3997: fprintf (stderr, "Then users can use `#include' any number of times.\n"); ! 3998: fprintf (stderr, "GNU C automatically avoids processing the file more than once\n"); ! 3999: fprintf (stderr, "when it is equipped with such a conditional.\n"); ! 4000: } ! 4001: ! 4002: get_filename: ! 4003: ! 4004: fbeg = buf; ! 4005: SKIP_WHITE_SPACE (fbeg); ! 4006: /* Discard trailing whitespace so we can easily see ! 4007: if we have parsed all the significant chars we were given. */ ! 4008: while (limit != fbeg && is_hor_space[limit[-1]]) limit--; ! 4009: ! 4010: switch (*fbeg++) { ! 4011: case '\"': ! 4012: { ! 4013: FILE_BUF *fp; ! 4014: /* Copy the operand text, concatenating the strings. */ ! 4015: { ! 4016: U_CHAR *fin = fbeg; ! 4017: fbeg = (U_CHAR *) alloca (limit - fbeg + 1); ! 4018: fend = fbeg; ! 4019: while (fin != limit) { ! 4020: while (fin != limit && *fin != '\"') ! 4021: *fend++ = *fin++; ! 4022: fin++; ! 4023: if (fin == limit) ! 4024: break; ! 4025: /* If not at the end, there had better be another string. */ ! 4026: /* Skip just horiz space, and don't go past limit. */ ! 4027: while (fin != limit && is_hor_space[*fin]) fin++; ! 4028: if (fin != limit && *fin == '\"') ! 4029: fin++; ! 4030: else ! 4031: goto fail; ! 4032: } ! 4033: } ! 4034: *fend = 0; ! 4035: ! 4036: /* We have "filename". Figure out directory this source ! 4037: file is coming from and put it on the front of the list. */ ! 4038: ! 4039: /* If -I- was specified, don't search current dir, only spec'd ones. */ ! 4040: if (ignore_srcdir) break; ! 4041: ! 4042: for (fp = &instack[indepth]; fp >= instack; fp--) ! 4043: { ! 4044: int n; ! 4045: char *ep,*nam; ! 4046: ! 4047: if ((nam = fp->nominal_fname) != NULL) { ! 4048: /* Found a named file. Figure out dir of the file, ! 4049: and put it in front of the search list. */ ! 4050: dsp[0].next = search_start; ! 4051: search_start = dsp; ! 4052: #ifndef VMS ! 4053: ep = rindex (nam, '/'); ! 4054: #else /* VMS */ ! 4055: ep = rindex (nam, ']'); ! 4056: if (ep == NULL) ep = rindex (nam, '>'); ! 4057: if (ep == NULL) ep = rindex (nam, ':'); ! 4058: if (ep != NULL) ep++; ! 4059: #endif /* VMS */ ! 4060: if (ep != NULL) { ! 4061: n = ep - nam; ! 4062: dsp[0].fname = (char *) alloca (n + 1); ! 4063: strncpy (dsp[0].fname, nam, n); ! 4064: dsp[0].fname[n] = '\0'; ! 4065: if (n + INCLUDE_LEN_FUDGE > max_include_len) ! 4066: max_include_len = n + INCLUDE_LEN_FUDGE; ! 4067: } else { ! 4068: dsp[0].fname = 0; /* Current directory */ ! 4069: } ! 4070: break; ! 4071: } ! 4072: } ! 4073: break; ! 4074: } ! 4075: ! 4076: case '<': ! 4077: fend = fbeg; ! 4078: while (fend != limit && *fend != '>') fend++; ! 4079: if (*fend == '>' && fend + 1 == limit) { ! 4080: angle_brackets = 1; ! 4081: /* If -I-, start with the first -I dir after the -I-. */ ! 4082: if (first_bracket_include) ! 4083: search_start = first_bracket_include; ! 4084: break; ! 4085: } ! 4086: goto fail; ! 4087: ! 4088: default: ! 4089: fail: ! 4090: if (retried) { ! 4091: error ("`#%s' expects \"FILENAME\" or <FILENAME>", keyword->name); ! 4092: return 0; ! 4093: } else { ! 4094: trybuf = expand_to_temp_buffer (buf, limit, 0, 0); ! 4095: buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1); ! 4096: bcopy (trybuf.buf, buf, trybuf.bufp - trybuf.buf); ! 4097: limit = buf + (trybuf.bufp - trybuf.buf); ! 4098: free (trybuf.buf); ! 4099: retried++; ! 4100: goto get_filename; ! 4101: } ! 4102: } ! 4103: ! 4104: /* For #include_next, skip in the search path ! 4105: past the dir in which the containing file was found. */ ! 4106: if (skip_dirs) { ! 4107: FILE_BUF *fp; ! 4108: for (fp = &instack[indepth]; fp >= instack; fp--) ! 4109: if (fp->fname != NULL) { ! 4110: /* fp->dir is null if the containing file was specified ! 4111: with an absolute file name. In that case, don't skip anything. */ ! 4112: if (fp->dir) ! 4113: search_start = fp->dir->next; ! 4114: break; ! 4115: } ! 4116: } ! 4117: ! 4118: flen = fend - fbeg; ! 4119: ! 4120: if (flen == 0) ! 4121: { ! 4122: error ("empty file name in `#%s'", keyword->name); ! 4123: return 0; ! 4124: } ! 4125: ! 4126: /* Allocate this permanently, because it gets stored in the definitions ! 4127: of macros. */ ! 4128: fname = (char *) xmalloc (max_include_len + flen + 2); ! 4129: /* + 2 above for slash and terminating null. */ ! 4130: ! 4131: /* If specified file name is absolute, just open it. */ ! 4132: ! 4133: if (*fbeg == '/') { ! 4134: strncpy (fname, fbeg, flen); ! 4135: fname[flen] = 0; ! 4136: if (redundant_include_p (fname)) ! 4137: return 0; ! 4138: if (importing) ! 4139: f = lookup_import (fname); ! 4140: else ! 4141: f = open (fname, O_RDONLY, 0666); ! 4142: if (f == -2) ! 4143: return 0; /* Already included this file */ ! 4144: } else { ! 4145: /* Search directory path, trying to open the file. ! 4146: Copy each filename tried into FNAME. */ ! 4147: ! 4148: for (searchptr = search_start; searchptr; searchptr = searchptr->next) { ! 4149: if (searchptr->fname) { ! 4150: /* The empty string in a search path is ignored. ! 4151: This makes it possible to turn off entirely ! 4152: a standard piece of the list. */ ! 4153: if (searchptr->fname[0] == 0) ! 4154: continue; ! 4155: strcpy (fname, searchptr->fname); ! 4156: strcat (fname, "/"); ! 4157: fname[strlen (fname) + flen] = 0; ! 4158: } else { ! 4159: fname[0] = 0; ! 4160: } ! 4161: strncat (fname, fbeg, flen); ! 4162: #ifdef VMS ! 4163: /* Change this 1/2 Unix 1/2 VMS file specification into a ! 4164: full VMS file specification */ ! 4165: if (searchptr->fname && (searchptr->fname[0] != 0)) { ! 4166: /* Fix up the filename */ ! 4167: hack_vms_include_specification (fname); ! 4168: } else { ! 4169: /* This is a normal VMS filespec, so use it unchanged. */ ! 4170: strncpy (fname, fbeg, flen); ! 4171: fname[flen] = 0; ! 4172: } ! 4173: #endif /* VMS */ ! 4174: if (importing) ! 4175: f = lookup_import (fname); ! 4176: else ! 4177: f = open (fname, O_RDONLY, 0666); ! 4178: if (f == -2) ! 4179: return 0; /* Already included this file */ ! 4180: #ifdef EACCES ! 4181: else if (f == -1 && errno == EACCES) ! 4182: warning ("Header file %s exists, but is not readable", fname); ! 4183: #endif ! 4184: if (redundant_include_p (fname)) { ! 4185: close (f); ! 4186: return 0; ! 4187: } ! 4188: if (f >= 0) ! 4189: break; ! 4190: } ! 4191: } ! 4192: ! 4193: if (f < 0) { ! 4194: /* A file that was not found. */ ! 4195: ! 4196: strncpy (fname, fbeg, flen); ! 4197: fname[flen] = 0; ! 4198: /* If -M was specified, and this header file won't be added to the ! 4199: dependency list, then don't count this as an error, because we can ! 4200: still produce correct output. Otherwise, we can't produce correct ! 4201: output, because there may be dependencies we need inside the missing ! 4202: file, and we don't know what directory this missing file exists in. */ ! 4203: if (print_deps ! 4204: && (print_deps <= (angle_brackets || (system_include_depth > 0)))) ! 4205: warning ("No include path in which to find %s", fname); ! 4206: else if (search_start) ! 4207: error_from_errno (fname); ! 4208: else ! 4209: error ("No include path in which to find %s", fname); ! 4210: } else { ! 4211: struct stat stat_f; ! 4212: ! 4213: /* Check to see if this include file is a once-only include file. ! 4214: If so, give up. */ ! 4215: ! 4216: struct file_name_list* ptr; ! 4217: ! 4218: for (ptr = dont_repeat_files; ptr; ptr = ptr->next) { ! 4219: if (!strcmp (ptr->fname, fname)) { ! 4220: close (f); ! 4221: return 0; /* This file was once'd. */ ! 4222: } ! 4223: } ! 4224: ! 4225: for (ptr = all_include_files; ptr; ptr = ptr->next) { ! 4226: if (!strcmp (ptr->fname, fname)) ! 4227: break; /* This file was included before. */ ! 4228: } ! 4229: ! 4230: if (ptr == 0) { ! 4231: /* This is the first time for this file. */ ! 4232: /* Add it to list of files included. */ ! 4233: ! 4234: ptr = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); ! 4235: ptr->control_macro = 0; ! 4236: ptr->c_system_include_path = 0; ! 4237: ptr->next = all_include_files; ! 4238: all_include_files = ptr; ! 4239: ptr->fname = savestring (fname); ! 4240: ! 4241: /* For -M, add this file to the dependencies. */ ! 4242: if (print_deps > (angle_brackets || (system_include_depth > 0))) { ! 4243: deps_output ("", 0); ! 4244: deps_output (fname, 0); ! 4245: deps_output (" ", 0); ! 4246: } ! 4247: } ! 4248: ! 4249: /* Handle -H option. */ ! 4250: if (print_include_names) { ! 4251: output_dots (stderr, indepth); ! 4252: fprintf (stderr, "%s\n", fname); ! 4253: } ! 4254: ! 4255: if (angle_brackets) ! 4256: system_include_depth++; ! 4257: ! 4258: /* Actually process the file. */ ! 4259: add_import (f, fname); /* Record file on "seen" list for #import. */ ! 4260: ! 4261: pcftry = (char *) alloca (strlen (fname) + 30); ! 4262: pcfbuf = 0; ! 4263: pcfnum = 0; ! 4264: ! 4265: fstat (f, &stat_f); ! 4266: ! 4267: if (!no_precomp) ! 4268: do { ! 4269: sprintf (pcftry, "%s%d", fname, pcfnum++); ! 4270: ! 4271: pcf = open (pcftry, O_RDONLY, 0666); ! 4272: if (pcf != -1) ! 4273: { ! 4274: struct stat s; ! 4275: ! 4276: fstat (pcf, &s); ! 4277: if (bcmp (&stat_f.st_ino, &s.st_ino, sizeof (s.st_ino)) ! 4278: || stat_f.st_dev != s.st_dev) ! 4279: { ! 4280: pcfbuf = check_precompiled (pcf, fname, &pcfbuflimit); ! 4281: /* Don't need it any more. */ ! 4282: close (pcf); ! 4283: } ! 4284: else ! 4285: { ! 4286: /* Don't need it at all. */ ! 4287: close (pcf); ! 4288: break; ! 4289: } ! 4290: } ! 4291: } while (pcf != -1 && !pcfbuf); ! 4292: ! 4293: /* Actually process the file */ ! 4294: if (pcfbuf) { ! 4295: pcfname = xmalloc (strlen (pcftry) + 1); ! 4296: strcpy (pcfname, pcftry); ! 4297: pcfinclude (pcfbuf, pcfbuflimit, fname, op); ! 4298: } ! 4299: else ! 4300: finclude (f, fname, op, is_system_include (fname), searchptr); ! 4301: ! 4302: if (angle_brackets) ! 4303: system_include_depth--; ! 4304: } ! 4305: return 0; ! 4306: } ! 4307: ! 4308: /* Return nonzero if there is no need to include file NAME ! 4309: because it has already been included and it contains a conditional ! 4310: to make a repeated include do nothing. */ ! 4311: ! 4312: static int ! 4313: redundant_include_p (name) ! 4314: char *name; ! 4315: { ! 4316: struct file_name_list *l = all_include_files; ! 4317: for (; l; l = l->next) ! 4318: if (! strcmp (name, l->fname) ! 4319: && l->control_macro ! 4320: && lookup (l->control_macro, -1, -1)) ! 4321: return 1; ! 4322: return 0; ! 4323: } ! 4324: ! 4325: /* Return nonzero if the given FILENAME is an absolute pathname which ! 4326: designates a file within one of the known "system" include file ! 4327: directories. We assume here that if the given FILENAME looks like ! 4328: it is the name of a file which resides either directly in a "system" ! 4329: include file directory, or within any subdirectory thereof, then the ! 4330: given file must be a "system" include file. This function tells us ! 4331: if we should suppress pedantic errors/warnings for the given FILENAME. ! 4332: ! 4333: The value is 2 if the file is a C-language system header file ! 4334: for which C++ should (on most systems) assume `extern "C"'. */ ! 4335: ! 4336: static int ! 4337: is_system_include (filename) ! 4338: register char *filename; ! 4339: { ! 4340: struct file_name_list *searchptr; ! 4341: ! 4342: for (searchptr = first_system_include; searchptr; ! 4343: searchptr = searchptr->next) ! 4344: if (searchptr->fname) { ! 4345: register char *sys_dir = searchptr->fname; ! 4346: register unsigned length = strlen (sys_dir); ! 4347: ! 4348: if (! strncmp (sys_dir, filename, length) && filename[length] == '/') ! 4349: { ! 4350: #ifdef GO_IF_CPLUSPLUS_INCLUDE_NAME ! 4351: char *name = filename+length; ! 4352: GO_IF_CPLUSPLUS_INCLUDE_NAME (name, cplusfile); ! 4353: #endif ! 4354: if (searchptr->c_system_include_path) ! 4355: { ! 4356: return 2; ! 4357: } ! 4358: ! 4359: cplusfile: ! 4360: return 1; ! 4361: } ! 4362: } ! 4363: return 0; ! 4364: } ! 4365: ! 4366: /* Process the contents of include file FNAME, already open on descriptor F, ! 4367: with output to OP. ! 4368: SYSTEM_HEADER_P is 1 if this file resides in any one of the known ! 4369: "system" include directories (as decided by the `is_system_include' ! 4370: function above). ! 4371: DIRPTR is the link in the dir path through which this file was found, ! 4372: or 0 if the file name was absolute. */ ! 4373: ! 4374: static void ! 4375: finclude (f, fname, op, system_header_p, dirptr) ! 4376: int f; ! 4377: char *fname; ! 4378: FILE_BUF *op; ! 4379: int system_header_p; ! 4380: struct file_name_list *dirptr; ! 4381: { ! 4382: int st_mode; ! 4383: long st_size; ! 4384: long i; ! 4385: FILE_BUF *fp; /* For input stack frame */ ! 4386: int missing_newline = 0; ! 4387: ! 4388: CHECK_DEPTH (return;); ! 4389: ! 4390: if (file_size_and_mode (f, &st_mode, &st_size) < 0) ! 4391: { ! 4392: perror_with_name (fname); ! 4393: close (f); ! 4394: return; ! 4395: } ! 4396: ! 4397: fp = &instack[indepth + 1]; ! 4398: bzero (fp, sizeof (FILE_BUF)); ! 4399: fp->nominal_fname = fp->fname = fname; ! 4400: fp->length = 0; ! 4401: fp->lineno = 1; ! 4402: fp->if_stack = if_stack; ! 4403: fp->system_header_p = system_header_p; ! 4404: fp->dir = dirptr; ! 4405: ! 4406: if (S_ISREG (st_mode)) { ! 4407: fp->buf = (U_CHAR *) xmalloc (st_size + 2); ! 4408: fp->bufp = fp->buf; ! 4409: ! 4410: /* Read the file contents, knowing that st_size is an upper bound ! 4411: on the number of bytes we can read. */ ! 4412: while (st_size > 0) { ! 4413: i = safe_read (f, fp->buf + fp->length, st_size); ! 4414: if (i <= 0) { ! 4415: if (i == 0) break; ! 4416: goto nope; ! 4417: } ! 4418: fp->length += i; ! 4419: st_size -= i; ! 4420: } ! 4421: } ! 4422: else if (S_ISDIR (st_mode)) { ! 4423: error ("directory `%s' specified in #include", fname); ! 4424: close (f); ! 4425: return; ! 4426: } else { ! 4427: /* Cannot count its file size before reading. ! 4428: First read the entire file into heap and ! 4429: copy them into buffer on stack. */ ! 4430: ! 4431: U_CHAR *bufp; ! 4432: U_CHAR *basep; ! 4433: int bsize = 2000; ! 4434: ! 4435: st_size = 0; ! 4436: basep = (U_CHAR *) xmalloc (bsize + 2); ! 4437: fp->buf = basep; /* So it will get freed, on error. */ ! 4438: bufp = basep; ! 4439: ! 4440: for (;;) { ! 4441: i = safe_read (f, bufp, bsize - st_size); ! 4442: if (i < 0) ! 4443: goto nope; /* error! */ ! 4444: if (i == 0) ! 4445: break; /* End of file */ ! 4446: st_size += i; ! 4447: bufp += i; ! 4448: if (bsize == st_size) { /* Buffer is full! */ ! 4449: bsize *= 2; ! 4450: basep = (U_CHAR *) xrealloc (basep, bsize + 2); ! 4451: fp->buf = basep; ! 4452: bufp = basep + st_size; /* May have moved */ ! 4453: } ! 4454: } ! 4455: fp->bufp = fp->buf; ! 4456: fp->length = st_size; ! 4457: } ! 4458: ! 4459: if ((fp->length > 0 && fp->buf[fp->length - 1] != '\n') ! 4460: /* Backslash-newline at end is not good enough. */ ! 4461: || (fp->length > 1 && fp->buf[fp->length - 2] == '\\')) { ! 4462: fp->buf[fp->length++] = '\n'; ! 4463: missing_newline = 1; ! 4464: } ! 4465: fp->buf[fp->length] = '\0'; ! 4466: ! 4467: /* Close descriptor now, so nesting does not use lots of descriptors. */ ! 4468: close (f); ! 4469: ! 4470: /* Must do this before calling trigraph_pcp, so that the correct file name ! 4471: will be printed in warning messages. */ ! 4472: ! 4473: indepth++; ! 4474: input_file_stack_tick++; ! 4475: ! 4476: if (!no_trigraphs) ! 4477: trigraph_pcp (fp); ! 4478: ! 4479: #ifdef NEXT_SEMANTICS ! 4480: if (!no_rtf) ! 4481: buf_convert_rtf (fp); ! 4482: #endif ! 4483: ! 4484: output_line_command (fp, op, 0, enter_file); ! 4485: rescan (op, 0); ! 4486: ! 4487: if (missing_newline) ! 4488: fp->lineno--; ! 4489: ! 4490: if (pedantic && missing_newline) ! 4491: pedwarn ("file does not end in newline"); ! 4492: ! 4493: indepth--; ! 4494: input_file_stack_tick++; ! 4495: output_line_command (&instack[indepth], op, 0, leave_file); ! 4496: free (fp->buf); ! 4497: return; ! 4498: ! 4499: nope: ! 4500: ! 4501: perror_with_name (fname); ! 4502: close (f); ! 4503: free (fp->buf); ! 4504: } ! 4505: ! 4506: /* Record that inclusion of the file named FILE ! 4507: should be controlled by the macro named MACRO_NAME. ! 4508: This means that trying to include the file again ! 4509: will do something if that macro is defined. */ ! 4510: ! 4511: static void ! 4512: record_control_macro (file, macro_name) ! 4513: char *file; ! 4514: U_CHAR *macro_name; ! 4515: { ! 4516: struct file_name_list *new; ! 4517: ! 4518: for (new = all_include_files; new; new = new->next) { ! 4519: if (!strcmp (new->fname, file)) { ! 4520: new->control_macro = macro_name; ! 4521: return; ! 4522: } ! 4523: } ! 4524: ! 4525: /* If the file is not in all_include_files, something's wrong. */ ! 4526: abort (); ! 4527: } ! 4528: ! 4529: /* Maintain and search list of included files, for #import. */ ! 4530: ! 4531: #define IMPORT_HASH_SIZE 31 ! 4532: ! 4533: struct import_file { ! 4534: char *name; ! 4535: ino_t inode; ! 4536: dev_t dev; ! 4537: struct import_file *next; ! 4538: }; ! 4539: ! 4540: /* Hash table of files already included with #include or #import. */ ! 4541: ! 4542: static struct import_file *import_hash_table[IMPORT_HASH_SIZE]; ! 4543: ! 4544: /* Hash a file name for import_hash_table. */ ! 4545: ! 4546: static int ! 4547: import_hash (f) ! 4548: char *f; ! 4549: { ! 4550: int val = 0; ! 4551: ! 4552: while (*f) val += *f++; ! 4553: return (val%IMPORT_HASH_SIZE); ! 4554: } ! 4555: ! 4556: /* Search for file FILENAME in import_hash_table. ! 4557: Return -2 if found, either a matching name or a matching inode. ! 4558: Otherwise, open the file and return a file descriptor if successful ! 4559: or -1 if unsuccessful. */ ! 4560: ! 4561: static int ! 4562: lookup_import (filename) ! 4563: char *filename; ! 4564: { ! 4565: struct import_file *i; ! 4566: int h; ! 4567: int hashval; ! 4568: struct stat sb; ! 4569: int fd; ! 4570: ! 4571: hashval = import_hash (filename); ! 4572: ! 4573: /* Attempt to find file in list of already included files */ ! 4574: i = import_hash_table[hashval]; ! 4575: ! 4576: while (i) { ! 4577: if (!strcmp (filename, i->name)) ! 4578: return -2; /* return found */ ! 4579: i = i->next; ! 4580: } ! 4581: /* Open it and try a match on inode/dev */ ! 4582: fd = open (filename, O_RDONLY, 0666); ! 4583: if (fd < 0) ! 4584: return fd; ! 4585: fstat (fd, &sb); ! 4586: for (h = 0; h < IMPORT_HASH_SIZE; h++) { ! 4587: i = import_hash_table[h]; ! 4588: while (i) { ! 4589: /* Compare the inode and the device. ! 4590: Supposedly on some systems the inode is not a scalar. */ ! 4591: if (!bcmp (&i->inode, &sb.st_ino, sizeof (sb.st_ino)) ! 4592: && i->dev == sb.st_dev) { ! 4593: close (fd); ! 4594: return -2; /* return found */ ! 4595: } ! 4596: i = i->next; ! 4597: } ! 4598: } ! 4599: return fd; /* Not found, return open file */ ! 4600: } ! 4601: ! 4602: /* Add the file FNAME, open on descriptor FD, to import_hash_table. */ ! 4603: ! 4604: static void ! 4605: add_import (fd, fname) ! 4606: int fd; ! 4607: char *fname; ! 4608: { ! 4609: struct import_file *i; ! 4610: int hashval; ! 4611: struct stat sb; ! 4612: ! 4613: hashval = import_hash (fname); ! 4614: fstat (fd, &sb); ! 4615: i = (struct import_file *)xmalloc (sizeof (struct import_file)); ! 4616: i->name = (char *)xmalloc (strlen (fname)+1); ! 4617: strcpy (i->name, fname); ! 4618: bcopy (&sb.st_ino, &i->inode, sizeof (sb.st_ino)); ! 4619: i->dev = sb.st_dev; ! 4620: i->next = import_hash_table[hashval]; ! 4621: import_hash_table[hashval] = i; ! 4622: } ! 4623: ! 4624: /* Load the specified precompiled header into core, and verify its ! 4625: preconditions. PCF indicates the file descriptor to read, which must ! 4626: be a regular file. FNAME indicates the file name of the original ! 4627: header. *LIMIT will be set to an address one past the end of the file. ! 4628: If the preconditions of the file are not satisfied, the buffer is ! 4629: freed and we return 0. If the preconditions are satisfied, return ! 4630: the address of the buffer following the preconditions. The buffer, in ! 4631: this case, should never be freed because various pieces of it will ! 4632: be referred to until all precompiled strings are output at the end of ! 4633: the run. ! 4634: */ ! 4635: static char * ! 4636: check_precompiled (pcf, fname, limit) ! 4637: int pcf; ! 4638: char *fname; ! 4639: char **limit; ! 4640: { ! 4641: int st_mode; ! 4642: long st_size; ! 4643: int length = 0; ! 4644: char *buf; ! 4645: char *dollar_loc; ! 4646: int i; ! 4647: char *cp; ! 4648: ! 4649: if (pcp_outfile) ! 4650: return 0; ! 4651: ! 4652: if (file_size_and_mode (pcf, &st_mode, &st_size) < 0) ! 4653: return 0; ! 4654: ! 4655: if (S_ISREG (st_mode)) ! 4656: { ! 4657: buf = xmalloc (st_size + 2); ! 4658: while (st_size > 0) ! 4659: { ! 4660: i = safe_read (pcf, buf + length, st_size); ! 4661: if (i < 0) ! 4662: goto nope; ! 4663: if (i == 0) ! 4664: break; ! 4665: length += i; ! 4666: st_size -= i; ! 4667: } ! 4668: } ! 4669: else ! 4670: abort (); ! 4671: ! 4672: if (length > 0 && buf[length-1] != '\n') ! 4673: buf[length++] = '\n'; ! 4674: buf[length] = '\0'; ! 4675: ! 4676: *limit = buf + length; ! 4677: ! 4678: /* File is in core. Check the preconditions. */ ! 4679: if (!check_preconditions (buf)) ! 4680: goto nope; ! 4681: for (cp = buf; *cp; cp++) ! 4682: ; ! 4683: #ifdef DEBUG_PCP ! 4684: fprintf (stderr, "Using preinclude %s\n", fname); ! 4685: #endif ! 4686: return cp + 1; ! 4687: ! 4688: nope: ! 4689: #ifdef DEBUG_PCP ! 4690: fprintf (stderr, "Cannot use preinclude %s\n", fname); ! 4691: #endif ! 4692: free (buf); ! 4693: return 0; ! 4694: } ! 4695: ! 4696: /* PREC (null terminated) points to the preconditions of a ! 4697: precompiled header. These are a series of #define and #undef ! 4698: lines which must match the current contents of the hash ! 4699: table. */ ! 4700: static int ! 4701: check_preconditions (prec) ! 4702: char *prec; ! 4703: { ! 4704: MACRODEF mdef; ! 4705: char *lineend; ! 4706: ! 4707: while (*prec) { ! 4708: lineend = (char *) index (prec, '\n'); ! 4709: ! 4710: if (*prec++ != '#') { ! 4711: error ("Bad format encountered while reading precompiled file"); ! 4712: return 0; ! 4713: } ! 4714: if (!strncmp (prec, "define", 6)) { ! 4715: HASHNODE *hp; ! 4716: ! 4717: prec += 6; ! 4718: mdef = create_definition (prec, lineend, NULL_PTR); ! 4719: ! 4720: if (mdef.defn == 0) ! 4721: abort (); ! 4722: ! 4723: if ((hp = lookup (mdef.symnam, mdef.symlen, -1)) == NULL ! 4724: || (hp->type != T_MACRO && hp->type != T_CONST) ! 4725: || (hp->type == T_MACRO ! 4726: && !compare_defs (mdef.defn, hp->value.defn) ! 4727: && (mdef.defn->length != 2 ! 4728: || mdef.defn->expansion[0] != '\n' ! 4729: || mdef.defn->expansion[1] != ' '))) ! 4730: return 0; ! 4731: } else if (!strncmp (prec, "undef", 5)) { ! 4732: char *name; ! 4733: int len; ! 4734: ! 4735: prec += 5; ! 4736: while (is_hor_space[(U_CHAR) *prec]) ! 4737: prec++; ! 4738: name = prec; ! 4739: while (is_idchar[(U_CHAR) *prec]) ! 4740: prec++; ! 4741: len = prec - name; ! 4742: ! 4743: if (lookup (name, len, -1)) ! 4744: return 0; ! 4745: } else { ! 4746: error ("Bad format encountered while reading precompiled file"); ! 4747: return 0; ! 4748: } ! 4749: prec = lineend + 1; ! 4750: } ! 4751: /* They all passed successfully */ ! 4752: return 1; ! 4753: } ! 4754: ! 4755: /* Process the main body of a precompiled file. BUF points to the ! 4756: string section of the file, following the preconditions. LIMIT is one ! 4757: character past the end. NAME is the name of the file being read ! 4758: in. OP is the main output buffer */ ! 4759: static void ! 4760: pcfinclude (buf, limit, name, op) ! 4761: U_CHAR *buf, *limit, *name; ! 4762: FILE_BUF *op; ! 4763: { ! 4764: FILE_BUF tmpbuf; ! 4765: int nstrings; ! 4766: U_CHAR *cp = buf; ! 4767: ! 4768: /* First in the file comes 4 bytes indicating the number of strings, */ ! 4769: /* in network byte order. (MSB first). */ ! 4770: nstrings = *cp++; ! 4771: nstrings = (nstrings << 8) | *cp++; ! 4772: nstrings = (nstrings << 8) | *cp++; ! 4773: nstrings = (nstrings << 8) | *cp++; ! 4774: ! 4775: /* Looping over each string... */ ! 4776: while (nstrings--) { ! 4777: U_CHAR *string_start; ! 4778: U_CHAR *endofthiskey; ! 4779: STRINGDEF *str; ! 4780: int nkeys; ! 4781: ! 4782: /* Each string starts with a STRINGDEF structure (str), followed */ ! 4783: /* by the text of the string (string_start) */ ! 4784: ! 4785: /* First skip to a longword boundary */ ! 4786: /* ??? Why a 4-byte boundary? On all machines? */ ! 4787: /* NOTE: This works correctly even if HOST_WIDE_INT ! 4788: is narrower than a pointer. ! 4789: Do not try risky measures here to get another type to use! ! 4790: Do not include gstddef.h or stddef.h--either one will fail! */ ! 4791: if ((HOST_WIDE_INT) cp & 3) ! 4792: cp += 4 - ((HOST_WIDE_INT) cp & 3); ! 4793: ! 4794: /* Now get the string. */ ! 4795: str = (STRINGDEF *) cp; ! 4796: string_start = cp += sizeof (STRINGDEF); ! 4797: ! 4798: for (; *cp; cp++) /* skip the string */ ! 4799: ; ! 4800: ! 4801: /* We need to macro expand the string here to ensure that the ! 4802: proper definition environment is in place. If it were only ! 4803: expanded when we find out it is needed, macros necessary for ! 4804: its proper expansion might have had their definitions changed. */ ! 4805: tmpbuf = expand_to_temp_buffer (string_start, cp++, 0, 0); ! 4806: /* Lineno is already set in the precompiled file */ ! 4807: str->contents = tmpbuf.buf; ! 4808: str->len = tmpbuf.length; ! 4809: str->writeflag = 0; ! 4810: str->filename = name; ! 4811: str->output_mark = outbuf.bufp - outbuf.buf; ! 4812: ! 4813: str->chain = 0; ! 4814: *stringlist_tailp = str; ! 4815: stringlist_tailp = &str->chain; ! 4816: ! 4817: /* Next comes a fourbyte number indicating the number of keys */ ! 4818: /* for this string. */ ! 4819: nkeys = *cp++; ! 4820: nkeys = (nkeys << 8) | *cp++; ! 4821: nkeys = (nkeys << 8) | *cp++; ! 4822: nkeys = (nkeys << 8) | *cp++; ! 4823: ! 4824: /* If this number is -1, then the string is mandatory. */ ! 4825: if (nkeys == -1) ! 4826: str->writeflag = 1; ! 4827: else ! 4828: /* Otherwise, for each key, */ ! 4829: for (; nkeys--; free (tmpbuf.buf), cp = endofthiskey + 1) { ! 4830: KEYDEF *kp = (KEYDEF *) cp; ! 4831: HASHNODE *hp; ! 4832: ! 4833: /* It starts with a KEYDEF structure */ ! 4834: cp += sizeof (KEYDEF); ! 4835: ! 4836: /* Find the end of the key. At the end of this for loop we ! 4837: advance CP to the start of the next key using this variable. */ ! 4838: endofthiskey = cp + strlen (cp); ! 4839: kp->str = str; ! 4840: ! 4841: /* Expand the key, and enter it into the hash table. */ ! 4842: tmpbuf = expand_to_temp_buffer (cp, endofthiskey, 0, 0); ! 4843: tmpbuf.bufp = tmpbuf.buf; ! 4844: ! 4845: while (is_hor_space[*tmpbuf.bufp]) ! 4846: tmpbuf.bufp++; ! 4847: if (!is_idstart[*tmpbuf.bufp] ! 4848: || tmpbuf.bufp == tmpbuf.buf + tmpbuf.length) { ! 4849: str->writeflag = 1; ! 4850: continue; ! 4851: } ! 4852: ! 4853: hp = lookup (tmpbuf.bufp, -1, -1); ! 4854: if (hp == NULL) { ! 4855: kp->chain = 0; ! 4856: install (tmpbuf.bufp, -1, T_PCSTRING, 0, (char *) kp, -1); ! 4857: } ! 4858: else if (hp->type == T_PCSTRING) { ! 4859: kp->chain = hp->value.keydef; ! 4860: hp->value.keydef = kp; ! 4861: } ! 4862: else ! 4863: str->writeflag = 1; ! 4864: } ! 4865: } ! 4866: /* This output_line_command serves to switch us back to the current ! 4867: input file in case some of these strings get output (which will ! 4868: result in line commands for the header file being output). */ ! 4869: output_line_command (&instack[indepth], op, 0, enter_file); ! 4870: } ! 4871: ! 4872: /* Called from rescan when it hits a key for strings. Mark them all */ ! 4873: /* used and clean up. */ ! 4874: static void ! 4875: pcstring_used (hp) ! 4876: HASHNODE *hp; ! 4877: { ! 4878: KEYDEF *kp, *tmp; ! 4879: ! 4880: for (kp = hp->value.keydef; kp; kp = kp->chain) ! 4881: kp->str->writeflag = 1; ! 4882: delete_macro (hp); ! 4883: } ! 4884: ! 4885: /* Write the output, interspersing precompiled strings in their */ ! 4886: /* appropriate places. */ ! 4887: static void ! 4888: write_output () ! 4889: { ! 4890: STRINGDEF *next_string; ! 4891: U_CHAR *cur_buf_loc; ! 4892: int line_command_len = 80; ! 4893: char *line_command = xmalloc (line_command_len); ! 4894: int len; ! 4895: int written; ! 4896: ! 4897: /* In each run through the loop, either cur_buf_loc == */ ! 4898: /* next_string_loc, in which case we print a series of strings, or */ ! 4899: /* it is less than next_string_loc, in which case we write some of */ ! 4900: /* the buffer. */ ! 4901: cur_buf_loc = outbuf.buf; ! 4902: next_string = stringlist; ! 4903: ! 4904: while (cur_buf_loc < outbuf.bufp || next_string) { ! 4905: if (next_string ! 4906: && cur_buf_loc - outbuf.buf == next_string->output_mark) { ! 4907: if (next_string->writeflag) { ! 4908: len = 4 * strlen (next_string->filename) + 32; ! 4909: while (len > line_command_len) ! 4910: line_command = xrealloc (line_command, ! 4911: line_command_len *= 2); ! 4912: sprintf (line_command, "\n# %d ", next_string->lineno); ! 4913: strcpy (quote_string (line_command + strlen (line_command), ! 4914: next_string->filename), ! 4915: "\n"); ! 4916: safe_write (fileno (stdout), line_command, strlen (line_command)); ! 4917: safe_write (fileno (stdout), next_string->contents, next_string->len); ! 4918: } ! 4919: next_string = next_string->chain; ! 4920: } ! 4921: else { ! 4922: len = (next_string ! 4923: ? (next_string->output_mark ! 4924: - (cur_buf_loc - outbuf.buf)) ! 4925: : outbuf.bufp - cur_buf_loc); ! 4926: ! 4927: safe_write (fileno (stdout), cur_buf_loc, len); ! 4928: cur_buf_loc += len; ! 4929: } ! 4930: } ! 4931: free (line_command); ! 4932: } ! 4933: ! 4934: /* Pass a directive through to the output file. ! 4935: BUF points to the contents of the directive, as a contiguous string. ! 4936: LIMIT points to the first character past the end of the directive. ! 4937: KEYWORD is the keyword-table entry for the directive. */ ! 4938: ! 4939: static void ! 4940: pass_thru_directive (buf, limit, op, keyword) ! 4941: U_CHAR *buf, *limit; ! 4942: FILE_BUF *op; ! 4943: struct directive *keyword; ! 4944: { ! 4945: register unsigned keyword_length = keyword->length; ! 4946: ! 4947: check_expand (op, 1 + keyword_length + (limit - buf)); ! 4948: *op->bufp++ = '#'; ! 4949: bcopy (keyword->name, op->bufp, keyword_length); ! 4950: op->bufp += keyword_length; ! 4951: if (limit != buf && buf[0] != ' ') ! 4952: *op->bufp++ = ' '; ! 4953: bcopy (buf, op->bufp, limit - buf); ! 4954: op->bufp += (limit - buf); ! 4955: #if 0 ! 4956: *op->bufp++ = '\n'; ! 4957: /* Count the line we have just made in the output, ! 4958: to get in sync properly. */ ! 4959: op->lineno++; ! 4960: #endif ! 4961: } ! 4962: ! 4963: /* The arglist structure is built by do_define to tell ! 4964: collect_definition where the argument names begin. That ! 4965: is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist ! 4966: would contain pointers to the strings x, y, and z. ! 4967: Collect_definition would then build a DEFINITION node, ! 4968: with reflist nodes pointing to the places x, y, and z had ! 4969: appeared. So the arglist is just convenience data passed ! 4970: between these two routines. It is not kept around after ! 4971: the current #define has been processed and entered into the ! 4972: hash table. */ ! 4973: ! 4974: struct arglist { ! 4975: struct arglist *next; ! 4976: U_CHAR *name; ! 4977: int length; ! 4978: int argno; ! 4979: char rest_args; ! 4980: }; ! 4981: ! 4982: /* Create a DEFINITION node from a #define directive. Arguments are ! 4983: as for do_define. */ ! 4984: static MACRODEF ! 4985: create_definition (buf, limit, op) ! 4986: U_CHAR *buf, *limit; ! 4987: FILE_BUF *op; ! 4988: { ! 4989: U_CHAR *bp; /* temp ptr into input buffer */ ! 4990: U_CHAR *symname; /* remember where symbol name starts */ ! 4991: int sym_length; /* and how long it is */ ! 4992: int line = instack[indepth].lineno; ! 4993: char *file = instack[indepth].nominal_fname; ! 4994: int rest_args = 0; ! 4995: ! 4996: DEFINITION *defn; ! 4997: int arglengths = 0; /* Accumulate lengths of arg names ! 4998: plus number of args. */ ! 4999: MACRODEF mdef; ! 5000: ! 5001: bp = buf; ! 5002: ! 5003: while (is_hor_space[*bp]) ! 5004: bp++; ! 5005: ! 5006: symname = bp; /* remember where it starts */ ! 5007: sym_length = check_macro_name (bp, "macro"); ! 5008: bp += sym_length; ! 5009: ! 5010: /* Lossage will occur if identifiers or control keywords are broken ! 5011: across lines using backslash. This is not the right place to take ! 5012: care of that. */ ! 5013: ! 5014: if (*bp == '(') { ! 5015: struct arglist *arg_ptrs = NULL; ! 5016: int argno = 0; ! 5017: ! 5018: bp++; /* skip '(' */ ! 5019: SKIP_WHITE_SPACE (bp); ! 5020: ! 5021: /* Loop over macro argument names. */ ! 5022: while (*bp != ')') { ! 5023: struct arglist *temp; ! 5024: ! 5025: temp = (struct arglist *) alloca (sizeof (struct arglist)); ! 5026: temp->name = bp; ! 5027: temp->next = arg_ptrs; ! 5028: temp->argno = argno++; ! 5029: temp->rest_args = 0; ! 5030: arg_ptrs = temp; ! 5031: ! 5032: if (rest_args) ! 5033: pedwarn ("another parameter follows `%s'", ! 5034: rest_extension); ! 5035: ! 5036: if (!is_idstart[*bp]) ! 5037: pedwarn ("invalid character in macro parameter name"); ! 5038: ! 5039: /* Find the end of the arg name. */ ! 5040: while (is_idchar[*bp]) { ! 5041: bp++; ! 5042: /* do we have a "special" rest-args extension here? */ ! 5043: if (limit - bp > REST_EXTENSION_LENGTH && ! 5044: strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) { ! 5045: rest_args = 1; ! 5046: temp->rest_args = 1; ! 5047: break; ! 5048: } ! 5049: } ! 5050: temp->length = bp - temp->name; ! 5051: if (rest_args == 1) ! 5052: bp += REST_EXTENSION_LENGTH; ! 5053: arglengths += temp->length + 2; ! 5054: SKIP_WHITE_SPACE (bp); ! 5055: if (temp->length == 0 || (*bp != ',' && *bp != ')')) { ! 5056: error ("badly punctuated parameter list in `#define'"); ! 5057: goto nope; ! 5058: } ! 5059: if (*bp == ',') { ! 5060: bp++; ! 5061: SKIP_WHITE_SPACE (bp); ! 5062: } ! 5063: if (bp >= limit) { ! 5064: error ("unterminated parameter list in `#define'"); ! 5065: goto nope; ! 5066: } ! 5067: { ! 5068: struct arglist *otemp; ! 5069: ! 5070: for (otemp = temp->next; otemp != NULL; otemp = otemp->next) ! 5071: if (temp->length == otemp->length && ! 5072: strncmp (temp->name, otemp->name, temp->length) == 0) { ! 5073: U_CHAR *name; ! 5074: ! 5075: name = (U_CHAR *) alloca (temp->length + 1); ! 5076: (void) strncpy (name, temp->name, temp->length); ! 5077: name[temp->length] = '\0'; ! 5078: error ("duplicate argument name `%s' in `#define'", name); ! 5079: goto nope; ! 5080: } ! 5081: } ! 5082: } ! 5083: ! 5084: ++bp; /* skip paren */ ! 5085: /* Skip exactly one space or tab if any. */ ! 5086: if (bp < limit && (*bp == ' ' || *bp == '\t')) ++bp; ! 5087: /* now everything from bp before limit is the definition. */ ! 5088: defn = collect_expansion (bp, limit, argno, arg_ptrs); ! 5089: defn->rest_args = rest_args; ! 5090: ! 5091: /* Now set defn->args.argnames to the result of concatenating ! 5092: the argument names in reverse order ! 5093: with comma-space between them. */ ! 5094: defn->args.argnames = (U_CHAR *) xmalloc (arglengths + 1); ! 5095: { ! 5096: struct arglist *temp; ! 5097: int i = 0; ! 5098: for (temp = arg_ptrs; temp; temp = temp->next) { ! 5099: bcopy (temp->name, &defn->args.argnames[i], temp->length); ! 5100: i += temp->length; ! 5101: if (temp->next != 0) { ! 5102: defn->args.argnames[i++] = ','; ! 5103: defn->args.argnames[i++] = ' '; ! 5104: } ! 5105: } ! 5106: defn->args.argnames[i] = 0; ! 5107: } ! 5108: } else { ! 5109: /* simple expansion or empty definition; gobble it */ ! 5110: if (is_hor_space[*bp]) ! 5111: ++bp; /* skip exactly one blank/tab char */ ! 5112: /* now everything from bp before limit is the definition. */ ! 5113: defn = collect_expansion (bp, limit, -1, NULL_PTR); ! 5114: defn->args.argnames = (U_CHAR *) ""; ! 5115: } ! 5116: ! 5117: defn->line = line; ! 5118: defn->file = file; ! 5119: ! 5120: /* OP is null if this is a predefinition */ ! 5121: defn->predefined = !op; ! 5122: mdef.defn = defn; ! 5123: mdef.symnam = symname; ! 5124: mdef.symlen = sym_length; ! 5125: ! 5126: return mdef; ! 5127: ! 5128: nope: ! 5129: mdef.defn = 0; ! 5130: return mdef; ! 5131: } ! 5132: ! 5133: /* Process a #define command. ! 5134: BUF points to the contents of the #define command, as a contiguous string. ! 5135: LIMIT points to the first character past the end of the definition. ! 5136: KEYWORD is the keyword-table entry for #define. */ ! 5137: ! 5138: static int ! 5139: do_define (buf, limit, op, keyword) ! 5140: U_CHAR *buf, *limit; ! 5141: FILE_BUF *op; ! 5142: struct directive *keyword; ! 5143: { ! 5144: int hashcode; ! 5145: MACRODEF mdef; ! 5146: ! 5147: /* If this is a precompiler run (with -pcp) pass thru #define commands. */ ! 5148: if (pcp_outfile && op) ! 5149: pass_thru_directive (buf, limit, op, keyword); ! 5150: ! 5151: mdef = create_definition (buf, limit, op); ! 5152: if (mdef.defn == 0) ! 5153: goto nope; ! 5154: ! 5155: hashcode = hashf (mdef.symnam, mdef.symlen, HASHSIZE); ! 5156: ! 5157: { ! 5158: HASHNODE *hp; ! 5159: if ((hp = lookup (mdef.symnam, mdef.symlen, hashcode)) != NULL) { ! 5160: int ok = 0; ! 5161: /* Redefining a precompiled key is ok. */ ! 5162: if (hp->type == T_PCSTRING) ! 5163: ok = 1; ! 5164: /* Redefining a macro is ok if the definitions are the same. */ ! 5165: else if (hp->type == T_MACRO) ! 5166: ok = ! compare_defs (mdef.defn, hp->value.defn); ! 5167: /* Redefining a constant is ok with -D. */ ! 5168: else if (hp->type == T_CONST) ! 5169: ok = ! done_initializing; ! 5170: /* Print the warning if it's not ok. */ ! 5171: if (!ok) { ! 5172: U_CHAR *msg; /* what pain... */ ! 5173: ! 5174: /* If we are passing through #define and #undef directives, do ! 5175: that for this re-definition now. */ ! 5176: if (debug_output && op) ! 5177: pass_thru_directive (buf, limit, op, keyword); ! 5178: ! 5179: msg = (U_CHAR *) alloca (mdef.symlen + 22); ! 5180: *msg = '`'; ! 5181: bcopy (mdef.symnam, msg + 1, mdef.symlen); ! 5182: strcpy ((char *) (msg + mdef.symlen + 1), "' redefined"); ! 5183: pedwarn (msg); ! 5184: if (hp->type == T_MACRO) ! 5185: pedwarn_with_file_and_line (hp->value.defn->file, hp->value.defn->line, ! 5186: "this is the location of the previous definition"); ! 5187: } ! 5188: /* Replace the old definition. */ ! 5189: hp->type = T_MACRO; ! 5190: hp->value.defn = mdef.defn; ! 5191: } else { ! 5192: /* If we are passing through #define and #undef directives, do ! 5193: that for this new definition now. */ ! 5194: if (debug_output && op) ! 5195: pass_thru_directive (buf, limit, op, keyword); ! 5196: install (mdef.symnam, mdef.symlen, T_MACRO, 0, ! 5197: (char *) mdef.defn, hashcode); ! 5198: } ! 5199: } ! 5200: ! 5201: return 0; ! 5202: ! 5203: nope: ! 5204: ! 5205: return 1; ! 5206: } ! 5207: ! 5208: /* Check a purported macro name SYMNAME, and yield its length. ! 5209: USAGE is the kind of name this is intended for. */ ! 5210: ! 5211: static int ! 5212: check_macro_name (symname, usage) ! 5213: U_CHAR *symname; ! 5214: char *usage; ! 5215: { ! 5216: U_CHAR *p; ! 5217: int sym_length; ! 5218: ! 5219: for (p = symname; is_idchar[*p]; p++) ! 5220: ; ! 5221: sym_length = p - symname; ! 5222: if (sym_length == 0) ! 5223: error ("invalid %s name", usage); ! 5224: else if (!is_idstart[*symname]) { ! 5225: U_CHAR *msg; /* what pain... */ ! 5226: msg = (U_CHAR *) alloca (sym_length + 1); ! 5227: bcopy (symname, msg, sym_length); ! 5228: msg[sym_length] = 0; ! 5229: error ("invalid %s name `%s'", usage, msg); ! 5230: } else { ! 5231: if (! strncmp (symname, "defined", 7) && sym_length == 7) ! 5232: error ("invalid %s name `defined'", usage); ! 5233: } ! 5234: return sym_length; ! 5235: } ! 5236: ! 5237: /* ! 5238: * return zero if two DEFINITIONs are isomorphic ! 5239: */ ! 5240: static int ! 5241: compare_defs (d1, d2) ! 5242: DEFINITION *d1, *d2; ! 5243: { ! 5244: register struct reflist *a1, *a2; ! 5245: register U_CHAR *p1 = d1->expansion; ! 5246: register U_CHAR *p2 = d2->expansion; ! 5247: int first = 1; ! 5248: ! 5249: if (d1->nargs != d2->nargs) ! 5250: return 1; ! 5251: if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames)) ! 5252: return 1; ! 5253: for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2; ! 5254: a1 = a1->next, a2 = a2->next) { ! 5255: if (!((a1->nchars == a2->nchars && ! strncmp (p1, p2, a1->nchars)) ! 5256: || ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0)) ! 5257: || a1->argno != a2->argno ! 5258: || a1->stringify != a2->stringify ! 5259: || a1->raw_before != a2->raw_before ! 5260: || a1->raw_after != a2->raw_after) ! 5261: return 1; ! 5262: first = 0; ! 5263: p1 += a1->nchars; ! 5264: p2 += a2->nchars; ! 5265: } ! 5266: if (a1 != a2) ! 5267: return 1; ! 5268: if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion), ! 5269: p2, d2->length - (p2 - d2->expansion), 1)) ! 5270: return 1; ! 5271: return 0; ! 5272: } ! 5273: ! 5274: /* Return 1 if two parts of two macro definitions are effectively different. ! 5275: One of the parts starts at BEG1 and has LEN1 chars; ! 5276: the other has LEN2 chars at BEG2. ! 5277: Any sequence of whitespace matches any other sequence of whitespace. ! 5278: FIRST means these parts are the first of a macro definition; ! 5279: so ignore leading whitespace entirely. ! 5280: LAST means these parts are the last of a macro definition; ! 5281: so ignore trailing whitespace entirely. */ ! 5282: ! 5283: static int ! 5284: comp_def_part (first, beg1, len1, beg2, len2, last) ! 5285: int first; ! 5286: U_CHAR *beg1, *beg2; ! 5287: int len1, len2; ! 5288: int last; ! 5289: { ! 5290: register U_CHAR *end1 = beg1 + len1; ! 5291: register U_CHAR *end2 = beg2 + len2; ! 5292: if (first) { ! 5293: while (beg1 != end1 && is_space[*beg1]) beg1++; ! 5294: while (beg2 != end2 && is_space[*beg2]) beg2++; ! 5295: } ! 5296: if (last) { ! 5297: while (beg1 != end1 && is_space[end1[-1]]) end1--; ! 5298: while (beg2 != end2 && is_space[end2[-1]]) end2--; ! 5299: } ! 5300: while (beg1 != end1 && beg2 != end2) { ! 5301: if (is_space[*beg1] && is_space[*beg2]) { ! 5302: while (beg1 != end1 && is_space[*beg1]) beg1++; ! 5303: while (beg2 != end2 && is_space[*beg2]) beg2++; ! 5304: } else if (*beg1 == *beg2) { ! 5305: beg1++; beg2++; ! 5306: } else break; ! 5307: } ! 5308: return (beg1 != end1) || (beg2 != end2); ! 5309: } ! 5310: ! 5311: /* Read a replacement list for a macro with parameters. ! 5312: Build the DEFINITION structure. ! 5313: Reads characters of text starting at BUF until END. ! 5314: ARGLIST specifies the formal parameters to look for ! 5315: in the text of the definition; NARGS is the number of args ! 5316: in that list, or -1 for a macro name that wants no argument list. ! 5317: MACRONAME is the macro name itself (so we can avoid recursive expansion) ! 5318: and NAMELEN is its length in characters. ! 5319: ! 5320: Note that comments and backslash-newlines have already been deleted ! 5321: from the argument. */ ! 5322: ! 5323: /* Leading and trailing Space, Tab, etc. are converted to markers ! 5324: Newline Space, Newline Tab, etc. ! 5325: Newline Space makes a space in the final output ! 5326: but is discarded if stringified. (Newline Tab is similar but ! 5327: makes a Tab instead.) ! 5328: ! 5329: If there is no trailing whitespace, a Newline Space is added at the end ! 5330: to prevent concatenation that would be contrary to the standard. */ ! 5331: ! 5332: static DEFINITION * ! 5333: collect_expansion (buf, end, nargs, arglist) ! 5334: U_CHAR *buf, *end; ! 5335: int nargs; ! 5336: struct arglist *arglist; ! 5337: { ! 5338: DEFINITION *defn; ! 5339: register U_CHAR *p, *limit, *lastp, *exp_p; ! 5340: struct reflist *endpat = NULL; ! 5341: /* Pointer to first nonspace after last ## seen. */ ! 5342: U_CHAR *concat = 0; ! 5343: /* Pointer to first nonspace after last single-# seen. */ ! 5344: U_CHAR *stringify = 0; ! 5345: int maxsize; ! 5346: int expected_delimiter = '\0'; ! 5347: ! 5348: /* Scan thru the replacement list, ignoring comments and quoted ! 5349: strings, picking up on the macro calls. It does a linear search ! 5350: thru the arg list on every potential symbol. Profiling might say ! 5351: that something smarter should happen. */ ! 5352: ! 5353: if (end < buf) ! 5354: abort (); ! 5355: ! 5356: /* Find the beginning of the trailing whitespace. */ ! 5357: /* Find end of leading whitespace. */ ! 5358: limit = end; ! 5359: p = buf; ! 5360: while (p < limit && is_space[limit[-1]]) limit--; ! 5361: while (p < limit && is_space[*p]) p++; ! 5362: ! 5363: /* Allocate space for the text in the macro definition. ! 5364: Leading and trailing whitespace chars need 2 bytes each. ! 5365: Each other input char may or may not need 1 byte, ! 5366: so this is an upper bound. ! 5367: The extra 2 are for invented trailing newline-marker and final null. */ ! 5368: maxsize = (sizeof (DEFINITION) ! 5369: + 2 * (end - limit) + 2 * (p - buf) ! 5370: + (limit - p) + 3); ! 5371: defn = (DEFINITION *) xcalloc (1, maxsize); ! 5372: ! 5373: defn->nargs = nargs; ! 5374: exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION); ! 5375: lastp = exp_p; ! 5376: ! 5377: p = buf; ! 5378: ! 5379: /* Convert leading whitespace to Newline-markers. */ ! 5380: while (p < limit && is_space[*p]) { ! 5381: *exp_p++ = '\n'; ! 5382: *exp_p++ = *p++; ! 5383: } ! 5384: ! 5385: if (limit - p >= 2 && p[0] == '#' && p[1] == '#') { ! 5386: error ("`##' at start of macro definition"); ! 5387: p += 2; ! 5388: } ! 5389: ! 5390: /* Process the main body of the definition. */ ! 5391: while (p < limit) { ! 5392: int skipped_arg = 0; ! 5393: register U_CHAR c = *p++; ! 5394: ! 5395: *exp_p++ = c; ! 5396: ! 5397: if (!traditional) { ! 5398: switch (c) { ! 5399: case '\'': ! 5400: case '\"': ! 5401: if (expected_delimiter != '\0') { ! 5402: if (c == expected_delimiter) ! 5403: expected_delimiter = '\0'; ! 5404: } else ! 5405: expected_delimiter = c; ! 5406: break; ! 5407: ! 5408: /* Special hack: if a \# is written in the #define ! 5409: include a # in the definition. This is useless for C code ! 5410: but useful for preprocessing other things. */ ! 5411: ! 5412: case '\\': ! 5413: /* \# quotes a # even outside of strings. */ ! 5414: if (p < limit && *p == '#' && !expected_delimiter) { ! 5415: exp_p--; ! 5416: *exp_p++ = *p++; ! 5417: } else if (p < limit && expected_delimiter) { ! 5418: /* In a string, backslash goes through ! 5419: and makes next char ordinary. */ ! 5420: *exp_p++ = *p++; ! 5421: } ! 5422: break; ! 5423: ! 5424: case '#': ! 5425: /* # is ordinary inside a string. */ ! 5426: if (expected_delimiter) ! 5427: break; ! 5428: if (p < limit && *p == '#') { ! 5429: /* ##: concatenate preceding and following tokens. */ ! 5430: /* Take out the first #, discard preceding whitespace. */ ! 5431: exp_p--; ! 5432: while (exp_p > lastp && is_hor_space[exp_p[-1]]) ! 5433: --exp_p; ! 5434: /* Skip the second #. */ ! 5435: p++; ! 5436: /* Discard following whitespace. */ ! 5437: SKIP_WHITE_SPACE (p); ! 5438: concat = p; ! 5439: if (p == limit) ! 5440: error ("`##' at end of macro definition"); ! 5441: } else if (nargs >= 0) { ! 5442: /* Single #: stringify following argument ref. ! 5443: Don't leave the # in the expansion. */ ! 5444: exp_p--; ! 5445: SKIP_WHITE_SPACE (p); ! 5446: if (p == limit || ! is_idstart[*p]) ! 5447: error ("`#' operator is not followed by a macro argument name"); ! 5448: else ! 5449: stringify = p; ! 5450: } ! 5451: break; ! 5452: } ! 5453: } else { ! 5454: /* In -traditional mode, recognize arguments inside strings and ! 5455: and character constants, and ignore special properties of #. ! 5456: Arguments inside strings are considered "stringified", but no ! 5457: extra quote marks are supplied. */ ! 5458: switch (c) { ! 5459: case '\'': ! 5460: case '\"': ! 5461: if (expected_delimiter != '\0') { ! 5462: if (c == expected_delimiter) ! 5463: expected_delimiter = '\0'; ! 5464: } else ! 5465: expected_delimiter = c; ! 5466: break; ! 5467: ! 5468: case '\\': ! 5469: /* Backslash quotes delimiters and itself, but not macro args. */ ! 5470: if (expected_delimiter != 0 && p < limit ! 5471: && (*p == expected_delimiter || *p == '\\')) { ! 5472: *exp_p++ = *p++; ! 5473: continue; ! 5474: } ! 5475: break; ! 5476: ! 5477: case '/': ! 5478: if (expected_delimiter != '\0') /* No comments inside strings. */ ! 5479: break; ! 5480: if (*p == '*') { ! 5481: /* If we find a comment that wasn't removed by handle_directive, ! 5482: this must be -traditional. So replace the comment with ! 5483: nothing at all. */ ! 5484: exp_p--; ! 5485: p += 1; ! 5486: while (p < limit && !(p[-2] == '*' && p[-1] == '/')) ! 5487: p++; ! 5488: #if 0 ! 5489: /* Mark this as a concatenation-point, as if it had been ##. */ ! 5490: concat = p; ! 5491: #endif ! 5492: } ! 5493: break; ! 5494: } ! 5495: } ! 5496: ! 5497: /* Handle the start of a symbol. */ ! 5498: if (is_idchar[c] && nargs > 0) { ! 5499: U_CHAR *id_beg = p - 1; ! 5500: int id_len; ! 5501: ! 5502: --exp_p; ! 5503: while (p != limit && is_idchar[*p]) p++; ! 5504: id_len = p - id_beg; ! 5505: ! 5506: if (is_idstart[c]) { ! 5507: register struct arglist *arg; ! 5508: ! 5509: for (arg = arglist; arg != NULL; arg = arg->next) { ! 5510: struct reflist *tpat; ! 5511: ! 5512: if (arg->name[0] == c ! 5513: && arg->length == id_len ! 5514: && strncmp (arg->name, id_beg, id_len) == 0) { ! 5515: if (expected_delimiter && warn_stringify) { ! 5516: if (traditional) { ! 5517: warning ("macro argument `%.*s' is stringified.", ! 5518: id_len, arg->name); ! 5519: } else { ! 5520: warning ("macro arg `%.*s' would be stringified with -traditional.", ! 5521: id_len, arg->name); ! 5522: } ! 5523: } ! 5524: /* If ANSI, don't actually substitute inside a string. */ ! 5525: if (!traditional && expected_delimiter) ! 5526: break; ! 5527: /* make a pat node for this arg and append it to the end of ! 5528: the pat list */ ! 5529: tpat = (struct reflist *) xmalloc (sizeof (struct reflist)); ! 5530: tpat->next = NULL; ! 5531: tpat->raw_before = concat == id_beg; ! 5532: tpat->raw_after = 0; ! 5533: tpat->rest_args = arg->rest_args; ! 5534: tpat->stringify = (traditional ? expected_delimiter != '\0' ! 5535: : stringify == id_beg); ! 5536: ! 5537: if (endpat == NULL) ! 5538: defn->pattern = tpat; ! 5539: else ! 5540: endpat->next = tpat; ! 5541: endpat = tpat; ! 5542: ! 5543: tpat->argno = arg->argno; ! 5544: tpat->nchars = exp_p - lastp; ! 5545: { ! 5546: register U_CHAR *p1 = p; ! 5547: SKIP_WHITE_SPACE (p1); ! 5548: if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#') ! 5549: tpat->raw_after = 1; ! 5550: } ! 5551: lastp = exp_p; /* place to start copying from next time */ ! 5552: skipped_arg = 1; ! 5553: break; ! 5554: } ! 5555: } ! 5556: } ! 5557: ! 5558: /* If this was not a macro arg, copy it into the expansion. */ ! 5559: if (! skipped_arg) { ! 5560: register U_CHAR *lim1 = p; ! 5561: p = id_beg; ! 5562: while (p != lim1) ! 5563: *exp_p++ = *p++; ! 5564: if (stringify == id_beg) ! 5565: error ("`#' operator should be followed by a macro argument name"); ! 5566: } ! 5567: } ! 5568: } ! 5569: ! 5570: if (limit < end) { ! 5571: /* Convert trailing whitespace to Newline-markers. */ ! 5572: while (limit < end && is_space[*limit]) { ! 5573: *exp_p++ = '\n'; ! 5574: *exp_p++ = *limit++; ! 5575: } ! 5576: } else if (!traditional && expected_delimiter == 0) { ! 5577: /* There is no trailing whitespace, so invent some in ANSI mode. ! 5578: But not if "inside a string" (which in ANSI mode ! 5579: happens only for -D option). */ ! 5580: *exp_p++ = '\n'; ! 5581: *exp_p++ = ' '; ! 5582: } ! 5583: ! 5584: *exp_p = '\0'; ! 5585: ! 5586: defn->length = exp_p - defn->expansion; ! 5587: ! 5588: /* Crash now if we overrun the allocated size. */ ! 5589: if (defn->length + 1 > maxsize) ! 5590: abort (); ! 5591: ! 5592: #if 0 ! 5593: /* This isn't worth the time it takes. */ ! 5594: /* give back excess storage */ ! 5595: defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1); ! 5596: #endif ! 5597: ! 5598: return defn; ! 5599: } ! 5600: ! 5601: static int ! 5602: do_assert (buf, limit, op, keyword) ! 5603: U_CHAR *buf, *limit; ! 5604: FILE_BUF *op; ! 5605: struct directive *keyword; ! 5606: { ! 5607: U_CHAR *bp; /* temp ptr into input buffer */ ! 5608: U_CHAR *symname; /* remember where symbol name starts */ ! 5609: int sym_length; /* and how long it is */ ! 5610: struct arglist *tokens = NULL; ! 5611: ! 5612: if (pedantic && done_initializing && !instack[indepth].system_header_p) ! 5613: pedwarn ("ANSI C does not allow `#assert'"); ! 5614: ! 5615: bp = buf; ! 5616: ! 5617: while (is_hor_space[*bp]) ! 5618: bp++; ! 5619: ! 5620: symname = bp; /* remember where it starts */ ! 5621: sym_length = check_macro_name (bp, "assertion"); ! 5622: bp += sym_length; ! 5623: /* #define doesn't do this, but we should. */ ! 5624: SKIP_WHITE_SPACE (bp); ! 5625: ! 5626: /* Lossage will occur if identifiers or control tokens are broken ! 5627: across lines using backslash. This is not the right place to take ! 5628: care of that. */ ! 5629: ! 5630: if (*bp != '(') { ! 5631: error ("missing token-sequence in `#assert'"); ! 5632: return 1; ! 5633: } ! 5634: ! 5635: { ! 5636: int error_flag = 0; ! 5637: ! 5638: bp++; /* skip '(' */ ! 5639: SKIP_WHITE_SPACE (bp); ! 5640: ! 5641: tokens = read_token_list (&bp, limit, &error_flag); ! 5642: if (error_flag) ! 5643: return 1; ! 5644: if (tokens == 0) { ! 5645: error ("empty token-sequence in `#assert'"); ! 5646: return 1; ! 5647: } ! 5648: ! 5649: ++bp; /* skip paren */ ! 5650: SKIP_WHITE_SPACE (bp); ! 5651: } ! 5652: ! 5653: /* If this name isn't already an assertion name, make it one. ! 5654: Error if it was already in use in some other way. */ ! 5655: ! 5656: { ! 5657: ASSERTION_HASHNODE *hp; ! 5658: int hashcode = hashf (symname, sym_length, ASSERTION_HASHSIZE); ! 5659: struct tokenlist_list *value ! 5660: = (struct tokenlist_list *) xmalloc (sizeof (struct tokenlist_list)); ! 5661: ! 5662: hp = assertion_lookup (symname, sym_length, hashcode); ! 5663: if (hp == NULL) { ! 5664: if (sym_length == 7 && ! strncmp (symname, "defined", sym_length)) ! 5665: error ("`defined' redefined as assertion"); ! 5666: hp = assertion_install (symname, sym_length, hashcode); ! 5667: } ! 5668: ! 5669: /* Add the spec'd token-sequence to the list of such. */ ! 5670: value->tokens = tokens; ! 5671: value->next = hp->value; ! 5672: hp->value = value; ! 5673: } ! 5674: ! 5675: return 0; ! 5676: } ! 5677: ! 5678: static int ! 5679: do_unassert (buf, limit, op, keyword) ! 5680: U_CHAR *buf, *limit; ! 5681: FILE_BUF *op; ! 5682: struct directive *keyword; ! 5683: { ! 5684: U_CHAR *bp; /* temp ptr into input buffer */ ! 5685: U_CHAR *symname; /* remember where symbol name starts */ ! 5686: int sym_length; /* and how long it is */ ! 5687: ! 5688: struct arglist *tokens = NULL; ! 5689: int tokens_specified = 0; ! 5690: ! 5691: if (pedantic && done_initializing && !instack[indepth].system_header_p) ! 5692: pedwarn ("ANSI C does not allow `#unassert'"); ! 5693: ! 5694: bp = buf; ! 5695: ! 5696: while (is_hor_space[*bp]) ! 5697: bp++; ! 5698: ! 5699: symname = bp; /* remember where it starts */ ! 5700: sym_length = check_macro_name (bp, "assertion"); ! 5701: bp += sym_length; ! 5702: /* #define doesn't do this, but we should. */ ! 5703: SKIP_WHITE_SPACE (bp); ! 5704: ! 5705: /* Lossage will occur if identifiers or control tokens are broken ! 5706: across lines using backslash. This is not the right place to take ! 5707: care of that. */ ! 5708: ! 5709: if (*bp == '(') { ! 5710: int error_flag = 0; ! 5711: ! 5712: bp++; /* skip '(' */ ! 5713: SKIP_WHITE_SPACE (bp); ! 5714: ! 5715: tokens = read_token_list (&bp, limit, &error_flag); ! 5716: if (error_flag) ! 5717: return 1; ! 5718: if (tokens == 0) { ! 5719: error ("empty token list in `#unassert'"); ! 5720: return 1; ! 5721: } ! 5722: ! 5723: tokens_specified = 1; ! 5724: ! 5725: ++bp; /* skip paren */ ! 5726: SKIP_WHITE_SPACE (bp); ! 5727: } ! 5728: ! 5729: { ! 5730: ASSERTION_HASHNODE *hp; ! 5731: int hashcode = hashf (symname, sym_length, ASSERTION_HASHSIZE); ! 5732: struct tokenlist_list *tail, *prev; ! 5733: ! 5734: hp = assertion_lookup (symname, sym_length, hashcode); ! 5735: if (hp == NULL) ! 5736: return 1; ! 5737: ! 5738: /* If no token list was specified, then eliminate this assertion ! 5739: entirely. */ ! 5740: if (! tokens_specified) { ! 5741: struct tokenlist_list *next; ! 5742: for (tail = hp->value; tail; tail = next) { ! 5743: next = tail->next; ! 5744: free_token_list (tail->tokens); ! 5745: free (tail); ! 5746: } ! 5747: delete_assertion (hp); ! 5748: } else { ! 5749: /* If a list of tokens was given, then delete any matching list. */ ! 5750: ! 5751: tail = hp->value; ! 5752: prev = 0; ! 5753: while (tail) { ! 5754: struct tokenlist_list *next = tail->next; ! 5755: if (compare_token_lists (tail->tokens, tokens)) { ! 5756: if (prev) ! 5757: prev->next = next; ! 5758: else ! 5759: hp->value = tail->next; ! 5760: free_token_list (tail->tokens); ! 5761: free (tail); ! 5762: } else { ! 5763: prev = tail; ! 5764: } ! 5765: tail = next; ! 5766: } ! 5767: } ! 5768: } ! 5769: ! 5770: return 0; ! 5771: } ! 5772: ! 5773: /* Test whether there is an assertion named NAME ! 5774: and optionally whether it has an asserted token list TOKENS. ! 5775: NAME is not null terminated; its length is SYM_LENGTH. ! 5776: If TOKENS_SPECIFIED is 0, then don't check for any token list. */ ! 5777: ! 5778: int ! 5779: check_assertion (name, sym_length, tokens_specified, tokens) ! 5780: U_CHAR *name; ! 5781: int sym_length; ! 5782: int tokens_specified; ! 5783: struct arglist *tokens; ! 5784: { ! 5785: ASSERTION_HASHNODE *hp; ! 5786: int hashcode = hashf (name, sym_length, ASSERTION_HASHSIZE); ! 5787: ! 5788: if (pedantic && !instack[indepth].system_header_p) ! 5789: pedwarn ("ANSI C does not allow testing assertions"); ! 5790: ! 5791: hp = assertion_lookup (name, sym_length, hashcode); ! 5792: if (hp == NULL) ! 5793: /* It is not an assertion; just return false. */ ! 5794: return 0; ! 5795: ! 5796: /* If no token list was specified, then value is 1. */ ! 5797: if (! tokens_specified) ! 5798: return 1; ! 5799: ! 5800: { ! 5801: struct tokenlist_list *tail; ! 5802: ! 5803: tail = hp->value; ! 5804: ! 5805: /* If a list of tokens was given, ! 5806: then succeed if the assertion records a matching list. */ ! 5807: ! 5808: while (tail) { ! 5809: if (compare_token_lists (tail->tokens, tokens)) ! 5810: return 1; ! 5811: tail = tail->next; ! 5812: } ! 5813: ! 5814: /* Fail if the assertion has no matching list. */ ! 5815: return 0; ! 5816: } ! 5817: } ! 5818: ! 5819: /* Compare two lists of tokens for equality including order of tokens. */ ! 5820: ! 5821: static int ! 5822: compare_token_lists (l1, l2) ! 5823: struct arglist *l1, *l2; ! 5824: { ! 5825: while (l1 && l2) { ! 5826: if (l1->length != l2->length) ! 5827: return 0; ! 5828: if (strncmp (l1->name, l2->name, l1->length)) ! 5829: return 0; ! 5830: l1 = l1->next; ! 5831: l2 = l2->next; ! 5832: } ! 5833: ! 5834: /* Succeed if both lists end at the same time. */ ! 5835: return l1 == l2; ! 5836: } ! 5837: ! 5838: /* Read a space-separated list of tokens ending in a close parenthesis. ! 5839: Return a list of strings, in the order they were written. ! 5840: (In case of error, return 0 and store -1 in *ERROR_FLAG.) ! 5841: Parse the text starting at *BPP, and update *BPP. ! 5842: Don't parse beyond LIMIT. */ ! 5843: ! 5844: static struct arglist * ! 5845: read_token_list (bpp, limit, error_flag) ! 5846: U_CHAR **bpp; ! 5847: U_CHAR *limit; ! 5848: int *error_flag; ! 5849: { ! 5850: struct arglist *token_ptrs = 0; ! 5851: U_CHAR *bp = *bpp; ! 5852: int depth = 1; ! 5853: ! 5854: *error_flag = 0; ! 5855: ! 5856: /* Loop over the assertion value tokens. */ ! 5857: while (depth > 0) { ! 5858: struct arglist *temp; ! 5859: int eofp = 0; ! 5860: U_CHAR *beg = bp; ! 5861: ! 5862: /* Find the end of the token. */ ! 5863: if (*bp == '(') { ! 5864: bp++; ! 5865: depth++; ! 5866: } else if (*bp == ')') { ! 5867: depth--; ! 5868: if (depth == 0) ! 5869: break; ! 5870: bp++; ! 5871: } else if (*bp == '"' || *bp == '\'') ! 5872: bp = skip_quoted_string (bp, limit, 0, NULL_PTR, NULL_PTR, &eofp); ! 5873: else ! 5874: while (! is_hor_space[*bp] && *bp != '(' && *bp != ')' ! 5875: && *bp != '"' && *bp != '\'' && bp != limit) ! 5876: bp++; ! 5877: ! 5878: temp = (struct arglist *) xmalloc (sizeof (struct arglist)); ! 5879: temp->name = (U_CHAR *) xmalloc (bp - beg + 1); ! 5880: bcopy (beg, temp->name, bp - beg); ! 5881: temp->name[bp - beg] = 0; ! 5882: temp->next = token_ptrs; ! 5883: token_ptrs = temp; ! 5884: temp->length = bp - beg; ! 5885: ! 5886: SKIP_WHITE_SPACE (bp); ! 5887: ! 5888: if (bp >= limit) { ! 5889: error ("unterminated token sequence in `#assert' or `#unassert'"); ! 5890: *error_flag = -1; ! 5891: return 0; ! 5892: } ! 5893: } ! 5894: *bpp = bp; ! 5895: ! 5896: /* We accumulated the names in reverse order. ! 5897: Now reverse them to get the proper order. */ ! 5898: { ! 5899: register struct arglist *prev = 0, *this, *next; ! 5900: for (this = token_ptrs; this; this = next) { ! 5901: next = this->next; ! 5902: this->next = prev; ! 5903: prev = this; ! 5904: } ! 5905: return prev; ! 5906: } ! 5907: } ! 5908: ! 5909: static void ! 5910: free_token_list (tokens) ! 5911: struct arglist *tokens; ! 5912: { ! 5913: while (tokens) { ! 5914: struct arglist *next = tokens->next; ! 5915: free (tokens->name); ! 5916: free (tokens); ! 5917: tokens = next; ! 5918: } ! 5919: } ! 5920: ! 5921: /* ! 5922: * Install a name in the assertion hash table. ! 5923: * ! 5924: * If LEN is >= 0, it is the length of the name. ! 5925: * Otherwise, compute the length by scanning the entire name. ! 5926: * ! 5927: * If HASH is >= 0, it is the precomputed hash code. ! 5928: * Otherwise, compute the hash code. ! 5929: */ ! 5930: static ASSERTION_HASHNODE * ! 5931: assertion_install (name, len, hash) ! 5932: U_CHAR *name; ! 5933: int len; ! 5934: int hash; ! 5935: { ! 5936: register ASSERTION_HASHNODE *hp; ! 5937: register int i, bucket; ! 5938: register U_CHAR *p, *q; ! 5939: ! 5940: i = sizeof (ASSERTION_HASHNODE) + len + 1; ! 5941: hp = (ASSERTION_HASHNODE *) xmalloc (i); ! 5942: bucket = hash; ! 5943: hp->bucket_hdr = &assertion_hashtab[bucket]; ! 5944: hp->next = assertion_hashtab[bucket]; ! 5945: assertion_hashtab[bucket] = hp; ! 5946: hp->prev = NULL; ! 5947: if (hp->next != NULL) ! 5948: hp->next->prev = hp; ! 5949: hp->length = len; ! 5950: hp->value = 0; ! 5951: hp->name = ((U_CHAR *) hp) + sizeof (ASSERTION_HASHNODE); ! 5952: p = hp->name; ! 5953: q = name; ! 5954: for (i = 0; i < len; i++) ! 5955: *p++ = *q++; ! 5956: hp->name[len] = 0; ! 5957: return hp; ! 5958: } ! 5959: ! 5960: /* ! 5961: * find the most recent hash node for name name (ending with first ! 5962: * non-identifier char) installed by install ! 5963: * ! 5964: * If LEN is >= 0, it is the length of the name. ! 5965: * Otherwise, compute the length by scanning the entire name. ! 5966: * ! 5967: * If HASH is >= 0, it is the precomputed hash code. ! 5968: * Otherwise, compute the hash code. ! 5969: */ ! 5970: static ASSERTION_HASHNODE * ! 5971: assertion_lookup (name, len, hash) ! 5972: U_CHAR *name; ! 5973: int len; ! 5974: int hash; ! 5975: { ! 5976: register U_CHAR *bp; ! 5977: register ASSERTION_HASHNODE *bucket; ! 5978: ! 5979: bucket = assertion_hashtab[hash]; ! 5980: while (bucket) { ! 5981: if (bucket->length == len && strncmp (bucket->name, name, len) == 0) ! 5982: return bucket; ! 5983: bucket = bucket->next; ! 5984: } ! 5985: return NULL; ! 5986: } ! 5987: ! 5988: static void ! 5989: delete_assertion (hp) ! 5990: ASSERTION_HASHNODE *hp; ! 5991: { ! 5992: ! 5993: if (hp->prev != NULL) ! 5994: hp->prev->next = hp->next; ! 5995: if (hp->next != NULL) ! 5996: hp->next->prev = hp->prev; ! 5997: ! 5998: /* make sure that the bucket chain header that ! 5999: the deleted guy was on points to the right thing afterwards. */ ! 6000: if (hp == *hp->bucket_hdr) ! 6001: *hp->bucket_hdr = hp->next; ! 6002: ! 6003: free (hp); ! 6004: } ! 6005: ! 6006: /* ! 6007: * interpret #line command. Remembers previously seen fnames ! 6008: * in its very own hash table. ! 6009: */ ! 6010: #define FNAME_HASHSIZE 37 ! 6011: ! 6012: static int ! 6013: do_line (buf, limit, op, keyword) ! 6014: U_CHAR *buf, *limit; ! 6015: FILE_BUF *op; ! 6016: struct directive *keyword; ! 6017: { ! 6018: register U_CHAR *bp; ! 6019: FILE_BUF *ip = &instack[indepth]; ! 6020: FILE_BUF tem; ! 6021: int new_lineno; ! 6022: enum file_change_code file_change = same_file; ! 6023: ! 6024: /* Expand any macros. */ ! 6025: tem = expand_to_temp_buffer (buf, limit, 0, 0); ! 6026: ! 6027: /* Point to macroexpanded line, which is null-terminated now. */ ! 6028: bp = tem.buf; ! 6029: SKIP_WHITE_SPACE (bp); ! 6030: ! 6031: if (!isdigit (*bp)) { ! 6032: error ("invalid format `#line' command"); ! 6033: return 0; ! 6034: } ! 6035: ! 6036: /* The Newline at the end of this line remains to be processed. ! 6037: To put the next line at the specified line number, ! 6038: we must store a line number now that is one less. */ ! 6039: new_lineno = atoi (bp) - 1; ! 6040: ! 6041: /* NEW_LINENO is one less than the actual line number here. */ ! 6042: if (pedantic && new_lineno < 0) ! 6043: pedwarn ("line number out of range in `#line' command"); ! 6044: ! 6045: /* skip over the line number. */ ! 6046: while (isdigit (*bp)) ! 6047: bp++; ! 6048: ! 6049: #if 0 /* #line 10"foo.c" is supposed to be allowed. */ ! 6050: if (*bp && !is_space[*bp]) { ! 6051: error ("invalid format `#line' command"); ! 6052: return; ! 6053: } ! 6054: #endif ! 6055: ! 6056: SKIP_WHITE_SPACE (bp); ! 6057: ! 6058: if (*bp == '\"') { ! 6059: static HASHNODE *fname_table[FNAME_HASHSIZE]; ! 6060: HASHNODE *hp, **hash_bucket; ! 6061: U_CHAR *fname, *p; ! 6062: int fname_length; ! 6063: ! 6064: fname = ++bp; ! 6065: ! 6066: /* Turn the file name, which is a character string literal, ! 6067: into a null-terminated string. Do this in place. */ ! 6068: p = bp; ! 6069: for (;;) ! 6070: switch ((*p++ = *bp++)) { ! 6071: case '\0': ! 6072: error ("invalid format `#line' command"); ! 6073: return 0; ! 6074: ! 6075: case '\\': ! 6076: { ! 6077: char *bpc = (char *) bp; ! 6078: int c = parse_escape (&bpc); ! 6079: bp = (U_CHAR *) bpc; ! 6080: if (c < 0) ! 6081: p--; ! 6082: else ! 6083: p[-1] = c; ! 6084: } ! 6085: break; ! 6086: ! 6087: case '\"': ! 6088: p[-1] = 0; ! 6089: goto fname_done; ! 6090: } ! 6091: fname_done: ! 6092: fname_length = p - fname; ! 6093: ! 6094: SKIP_WHITE_SPACE (bp); ! 6095: if (*bp) { ! 6096: if (pedantic) ! 6097: pedwarn ("garbage at end of `#line' command"); ! 6098: if (*bp == '1') ! 6099: file_change = enter_file; ! 6100: else if (*bp == '2') ! 6101: file_change = leave_file; ! 6102: else if (*bp == '3') ! 6103: ip->system_header_p = 1; ! 6104: else if (*bp == '4') ! 6105: ip->system_header_p = 2; ! 6106: else { ! 6107: error ("invalid format `#line' command"); ! 6108: return 0; ! 6109: } ! 6110: ! 6111: bp++; ! 6112: SKIP_WHITE_SPACE (bp); ! 6113: if (*bp == '3') { ! 6114: ip->system_header_p = 1; ! 6115: bp++; ! 6116: SKIP_WHITE_SPACE (bp); ! 6117: } ! 6118: if (*bp == '4') { ! 6119: ip->system_header_p = 2; ! 6120: bp++; ! 6121: SKIP_WHITE_SPACE (bp); ! 6122: } ! 6123: if (*bp) { ! 6124: error ("invalid format `#line' command"); ! 6125: return 0; ! 6126: } ! 6127: } ! 6128: ! 6129: hash_bucket = ! 6130: &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)]; ! 6131: for (hp = *hash_bucket; hp != NULL; hp = hp->next) ! 6132: if (hp->length == fname_length && ! 6133: strncmp (hp->value.cpval, fname, fname_length) == 0) { ! 6134: ip->nominal_fname = hp->value.cpval; ! 6135: break; ! 6136: } ! 6137: if (hp == 0) { ! 6138: /* Didn't find it; cons up a new one. */ ! 6139: hp = (HASHNODE *) xcalloc (1, sizeof (HASHNODE) + fname_length + 1); ! 6140: hp->next = *hash_bucket; ! 6141: *hash_bucket = hp; ! 6142: ! 6143: hp->length = fname_length; ! 6144: ip->nominal_fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE); ! 6145: bcopy (fname, hp->value.cpval, fname_length); ! 6146: } ! 6147: } else if (*bp) { ! 6148: error ("invalid format `#line' command"); ! 6149: return 0; ! 6150: } ! 6151: ! 6152: ip->lineno = new_lineno; ! 6153: output_line_command (ip, op, 0, file_change); ! 6154: check_expand (op, ip->length - (ip->bufp - ip->buf)); ! 6155: return 0; ! 6156: } ! 6157: ! 6158: /* ! 6159: * remove the definition of a symbol from the symbol table. ! 6160: * according to un*x /lib/cpp, it is not an error to undef ! 6161: * something that has no definitions, so it isn't one here either. ! 6162: */ ! 6163: ! 6164: static int ! 6165: do_undef (buf, limit, op, keyword) ! 6166: U_CHAR *buf, *limit; ! 6167: FILE_BUF *op; ! 6168: struct directive *keyword; ! 6169: { ! 6170: int sym_length; ! 6171: HASHNODE *hp; ! 6172: U_CHAR *orig_buf = buf; ! 6173: ! 6174: /* If this is a precompiler run (with -pcp) pass thru #undef commands. */ ! 6175: if (pcp_outfile && op) ! 6176: pass_thru_directive (buf, limit, op, keyword); ! 6177: ! 6178: SKIP_WHITE_SPACE (buf); ! 6179: sym_length = check_macro_name (buf, "macro"); ! 6180: ! 6181: while ((hp = lookup (buf, sym_length, -1)) != NULL) { ! 6182: /* If we are generating additional info for debugging (with -g) we ! 6183: need to pass through all effective #undef commands. */ ! 6184: if (debug_output && op) ! 6185: pass_thru_directive (orig_buf, limit, op, keyword); ! 6186: if (hp->type != T_MACRO) ! 6187: warning ("undefining `%s'", hp->name); ! 6188: delete_macro (hp); ! 6189: } ! 6190: ! 6191: if (pedantic) { ! 6192: buf += sym_length; ! 6193: SKIP_WHITE_SPACE (buf); ! 6194: if (buf != limit) ! 6195: pedwarn ("garbage after `#undef' directive"); ! 6196: } ! 6197: return 0; ! 6198: } ! 6199: ! 6200: /* ! 6201: * Report a fatal error detected by the program we are processing. ! 6202: * Use the text of the line in the error message, then terminate. ! 6203: * (We use error because it prints the filename & line#.) ! 6204: */ ! 6205: ! 6206: static int ! 6207: do_error (buf, limit, op, keyword) ! 6208: U_CHAR *buf, *limit; ! 6209: FILE_BUF *op; ! 6210: struct directive *keyword; ! 6211: { ! 6212: int length = limit - buf; ! 6213: U_CHAR *copy = (U_CHAR *) xmalloc (length + 1); ! 6214: bcopy (buf, copy, length); ! 6215: copy[length] = 0; ! 6216: SKIP_WHITE_SPACE (copy); ! 6217: error ("#error %s", copy); ! 6218: exit (FAILURE_EXIT_CODE); ! 6219: /* NOTREACHED */ ! 6220: return 0; ! 6221: } ! 6222: ! 6223: /* ! 6224: * Report a warning detected by the program we are processing. ! 6225: * Use the text of the line in the warning message, then continue. ! 6226: * (We use error because it prints the filename & line#.) ! 6227: */ ! 6228: ! 6229: static int ! 6230: do_warning (buf, limit, op, keyword) ! 6231: U_CHAR *buf, *limit; ! 6232: FILE_BUF *op; ! 6233: struct directive *keyword; ! 6234: { ! 6235: int length = limit - buf; ! 6236: U_CHAR *copy = (U_CHAR *) xmalloc (length + 1); ! 6237: bcopy (buf, copy, length); ! 6238: copy[length] = 0; ! 6239: SKIP_WHITE_SPACE (copy); ! 6240: warning ("#warning %s", copy); ! 6241: return 0; ! 6242: } ! 6243: ! 6244: /* Remember the name of the current file being read from so that we can ! 6245: avoid ever including it again. */ ! 6246: ! 6247: static int ! 6248: do_once () ! 6249: { ! 6250: int i; ! 6251: FILE_BUF *ip = NULL; ! 6252: ! 6253: for (i = indepth; i >= 0; i--) ! 6254: if (instack[i].fname != NULL) { ! 6255: ip = &instack[i]; ! 6256: break; ! 6257: } ! 6258: ! 6259: if (ip != NULL) { ! 6260: struct file_name_list *new; ! 6261: ! 6262: new = (struct file_name_list *) xmalloc (sizeof (struct file_name_list)); ! 6263: new->next = dont_repeat_files; ! 6264: dont_repeat_files = new; ! 6265: new->fname = savestring (ip->fname); ! 6266: new->control_macro = 0; ! 6267: new->c_system_include_path = 0; ! 6268: } ! 6269: return 0; ! 6270: } ! 6271: ! 6272: /* #ident has already been copied to the output file, so just ignore it. */ ! 6273: ! 6274: static int ! 6275: do_ident (buf, limit) ! 6276: U_CHAR *buf, *limit; ! 6277: { ! 6278: FILE_BUF trybuf; ! 6279: int len; ! 6280: FILE_BUF *op = &outbuf; ! 6281: ! 6282: /* Allow #ident in system headers, since that's not user's fault. */ ! 6283: if (pedantic && !instack[indepth].system_header_p) ! 6284: pedwarn ("ANSI C does not allow `#ident'"); ! 6285: ! 6286: trybuf = expand_to_temp_buffer (buf, limit, 0, 0); ! 6287: buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1); ! 6288: bcopy (trybuf.buf, buf, trybuf.bufp - trybuf.buf); ! 6289: limit = buf + (trybuf.bufp - trybuf.buf); ! 6290: len = (limit - buf); ! 6291: free (trybuf.buf); ! 6292: ! 6293: /* Output directive name. */ ! 6294: check_expand (op, 8); ! 6295: bcopy ("#ident ", op->bufp, 7); ! 6296: op->bufp += 7; ! 6297: ! 6298: /* Output the expanded argument line. */ ! 6299: check_expand (op, len); ! 6300: bcopy (buf, op->bufp, len); ! 6301: op->bufp += len; ! 6302: ! 6303: return 0; ! 6304: } ! 6305: ! 6306: /* #pragma and its argument line have already been copied to the output file. ! 6307: Just check for some recognized pragmas that need validation here. */ ! 6308: ! 6309: static int ! 6310: do_pragma (buf, limit) ! 6311: U_CHAR *buf, *limit; ! 6312: { ! 6313: while (*buf == ' ' || *buf == '\t') ! 6314: buf++; ! 6315: if (!strncmp (buf, "once", 4)) { ! 6316: /* Allow #pragma once in system headers, since that's not the user's ! 6317: fault. */ ! 6318: if (!instack[indepth].system_header_p) ! 6319: warning ("`#pragma once' is obsolete"); ! 6320: do_once (); ! 6321: } ! 6322: ! 6323: if (!strncmp (buf, "cplusplus", 9)) ! 6324: { ! 6325: if (instack[indepth].system_header_p == 2 && cplusplus) ! 6326: { ! 6327: instack[indepth].system_header_p = 1; ! 6328: output_line_command (&instack[indepth], &outbuf, 0, same_file); ! 6329: } ! 6330: } ! 6331: ! 6332: if (!strncmp (buf, "implementation", 14)) { ! 6333: /* Be quiet about `#pragma implementation' for a file only if it hasn't ! 6334: been included yet. */ ! 6335: struct file_name_list *ptr; ! 6336: U_CHAR *p = buf + 14, *fname, *inc_fname; ! 6337: SKIP_WHITE_SPACE (p); ! 6338: if (*p == '\n' || *p != '\"') ! 6339: return 0; ! 6340: ! 6341: fname = p + 1; ! 6342: if (p = (U_CHAR *) index (fname, '\"')) ! 6343: *p = '\0'; ! 6344: ! 6345: for (ptr = all_include_files; ptr; ptr = ptr->next) { ! 6346: inc_fname = (U_CHAR *) rindex (ptr->fname, '/'); ! 6347: inc_fname = inc_fname ? inc_fname + 1 : (U_CHAR *) ptr->fname; ! 6348: if (inc_fname && !strcmp (inc_fname, fname)) ! 6349: warning ("`#pragma implementation' for `%s' appears after file is included", ! 6350: fname); ! 6351: } ! 6352: } ! 6353: ! 6354: return 0; ! 6355: } ! 6356: ! 6357: #if 0 ! 6358: /* This was a fun hack, but #pragma seems to start to be useful. ! 6359: By failing to recognize it, we pass it through unchanged to cc1. */ ! 6360: ! 6361: /* ! 6362: * the behavior of the #pragma directive is implementation defined. ! 6363: * this implementation defines it as follows. ! 6364: */ ! 6365: ! 6366: static int ! 6367: do_pragma () ! 6368: { ! 6369: close (0); ! 6370: if (open ("/dev/tty", O_RDONLY, 0666) != 0) ! 6371: goto nope; ! 6372: close (1); ! 6373: if (open ("/dev/tty", O_WRONLY, 0666) != 1) ! 6374: goto nope; ! 6375: execl ("/usr/games/hack", "#pragma", 0); ! 6376: execl ("/usr/games/rogue", "#pragma", 0); ! 6377: execl ("/usr/new/emacs", "-f", "hanoi", "9", "-kill", 0); ! 6378: execl ("/usr/local/emacs", "-f", "hanoi", "9", "-kill", 0); ! 6379: nope: ! 6380: fatal ("You are in a maze of twisty compiler features, all different"); ! 6381: } ! 6382: #endif ! 6383: ! 6384: /* Just ignore #sccs, on systems where we define it at all. */ ! 6385: ! 6386: static int ! 6387: do_sccs () ! 6388: { ! 6389: if (pedantic) ! 6390: pedwarn ("ANSI C does not allow `#sccs'"); ! 6391: return 0; ! 6392: } ! 6393: ! 6394: /* ! 6395: * handle #if command by ! 6396: * 1) inserting special `defined' keyword into the hash table ! 6397: * that gets turned into 0 or 1 by special_symbol (thus, ! 6398: * if the luser has a symbol called `defined' already, it won't ! 6399: * work inside the #if command) ! 6400: * 2) rescan the input into a temporary output buffer ! 6401: * 3) pass the output buffer to the yacc parser and collect a value ! 6402: * 4) clean up the mess left from steps 1 and 2. ! 6403: * 5) call conditional_skip to skip til the next #endif (etc.), ! 6404: * or not, depending on the value from step 3. ! 6405: */ ! 6406: ! 6407: static int ! 6408: do_if (buf, limit, op, keyword) ! 6409: U_CHAR *buf, *limit; ! 6410: FILE_BUF *op; ! 6411: struct directive *keyword; ! 6412: { ! 6413: int value; ! 6414: FILE_BUF *ip = &instack[indepth]; ! 6415: ! 6416: value = eval_if_expression (buf, limit - buf); ! 6417: conditional_skip (ip, value == 0, T_IF, NULL_PTR); ! 6418: return 0; ! 6419: } ! 6420: ! 6421: /* ! 6422: * handle a #elif directive by not changing if_stack either. ! 6423: * see the comment above do_else. ! 6424: */ ! 6425: ! 6426: static int ! 6427: do_elif (buf, limit, op, keyword) ! 6428: U_CHAR *buf, *limit; ! 6429: FILE_BUF *op; ! 6430: struct directive *keyword; ! 6431: { ! 6432: int value; ! 6433: FILE_BUF *ip = &instack[indepth]; ! 6434: ! 6435: if (if_stack == instack[indepth].if_stack) { ! 6436: error ("`#elif' not within a conditional"); ! 6437: return 0; ! 6438: } else { ! 6439: if (if_stack->type != T_IF && if_stack->type != T_ELIF) { ! 6440: error ("`#elif' after `#else'"); ! 6441: #ifdef REPORT_EVENT ! 6442: REPORT_EVENT (0, NULL, if_stack->fname, if_stack->lineno, ! 6443: "matching conditional", 0, 0, 0); ! 6444: #endif ! 6445: fprintf (stderr, " (matches line %d", if_stack->lineno); ! 6446: if (if_stack->fname != NULL && ip->fname != NULL && ! 6447: strcmp (if_stack->fname, ip->nominal_fname) != 0) ! 6448: fprintf (stderr, ", file %s", if_stack->fname); ! 6449: fprintf (stderr, ")\n"); ! 6450: } ! 6451: if_stack->type = T_ELIF; ! 6452: } ! 6453: ! 6454: if (if_stack->if_succeeded) ! 6455: skip_if_group (ip, 0); ! 6456: else { ! 6457: value = eval_if_expression (buf, limit - buf); ! 6458: if (value == 0) ! 6459: skip_if_group (ip, 0); ! 6460: else { ! 6461: ++if_stack->if_succeeded; /* continue processing input */ ! 6462: output_line_command (ip, op, 1, same_file); ! 6463: } ! 6464: } ! 6465: return 0; ! 6466: } ! 6467: ! 6468: /* ! 6469: * evaluate a #if expression in BUF, of length LENGTH, ! 6470: * then parse the result as a C expression and return the value as an int. ! 6471: */ ! 6472: static int ! 6473: eval_if_expression (buf, length) ! 6474: U_CHAR *buf; ! 6475: int length; ! 6476: { ! 6477: FILE_BUF temp_obuf; ! 6478: HASHNODE *save_defined; ! 6479: int value; ! 6480: ! 6481: save_defined = install ("defined", -1, T_SPEC_DEFINED, 0, 0, -1); ! 6482: pcp_inside_if = 1; ! 6483: temp_obuf = expand_to_temp_buffer (buf, buf + length, 0, 1); ! 6484: pcp_inside_if = 0; ! 6485: delete_macro (save_defined); /* clean up special symbol */ ! 6486: ! 6487: value = parse_c_expression (temp_obuf.buf); ! 6488: ! 6489: free (temp_obuf.buf); ! 6490: ! 6491: return value; ! 6492: } ! 6493: ! 6494: /* ! 6495: * routine to handle ifdef/ifndef. Try to look up the symbol, ! 6496: * then do or don't skip to the #endif/#else/#elif depending ! 6497: * on what directive is actually being processed. ! 6498: */ ! 6499: ! 6500: static int ! 6501: do_xifdef (buf, limit, op, keyword) ! 6502: U_CHAR *buf, *limit; ! 6503: FILE_BUF *op; ! 6504: struct directive *keyword; ! 6505: { ! 6506: int skip; ! 6507: FILE_BUF *ip = &instack[indepth]; ! 6508: U_CHAR *end; ! 6509: int start_of_file = 0; ! 6510: U_CHAR *control_macro = 0; ! 6511: ! 6512: /* Detect a #ifndef at start of file (not counting comments). */ ! 6513: if (ip->fname != 0 && keyword->type == T_IFNDEF) { ! 6514: U_CHAR *p = ip->buf; ! 6515: while (p != directive_start) { ! 6516: U_CHAR c = *p++; ! 6517: if (is_space[c]) ! 6518: ; ! 6519: else if (c == '/' && p != ip->bufp && *p == '*') { ! 6520: /* Skip this comment. */ ! 6521: int junk; ! 6522: U_CHAR *save_bufp = ip->bufp; ! 6523: ip->bufp = p + 1; ! 6524: p = skip_to_end_of_comment (ip, &junk, 1); ! 6525: ip->bufp = save_bufp; ! 6526: } else { ! 6527: goto fail; ! 6528: } ! 6529: } ! 6530: /* If we get here, this conditional is the beginning of the file. */ ! 6531: start_of_file = 1; ! 6532: fail: ; ! 6533: } ! 6534: ! 6535: /* Discard leading and trailing whitespace. */ ! 6536: SKIP_WHITE_SPACE (buf); ! 6537: while (limit != buf && is_hor_space[limit[-1]]) limit--; ! 6538: ! 6539: /* Find the end of the identifier at the beginning. */ ! 6540: for (end = buf; is_idchar[*end]; end++); ! 6541: ! 6542: if (end == buf) { ! 6543: skip = (keyword->type == T_IFDEF); ! 6544: if (! traditional) ! 6545: pedwarn (end == limit ? "`#%s' with no argument" ! 6546: : "`#%s' argument starts with punctuation", ! 6547: keyword->name); ! 6548: } else { ! 6549: HASHNODE *hp; ! 6550: ! 6551: if (pedantic && buf[0] >= '0' && buf[0] <= '9') ! 6552: pedwarn ("`#%s' argument starts with a digit", keyword->name); ! 6553: else if (end != limit && !traditional) ! 6554: pedwarn ("garbage at end of `#%s' argument", keyword->name); ! 6555: ! 6556: hp = lookup (buf, end-buf, -1); ! 6557: ! 6558: if (pcp_outfile) { ! 6559: /* Output a precondition for this macro. */ ! 6560: if (hp && hp->value.defn->predefined) ! 6561: fprintf (pcp_outfile, "#define %s\n", hp->name); ! 6562: else { ! 6563: U_CHAR *cp = buf; ! 6564: fprintf (pcp_outfile, "#undef "); ! 6565: while (is_idchar[*cp]) /* Ick! */ ! 6566: fputc (*cp++, pcp_outfile); ! 6567: putc ('\n', pcp_outfile); ! 6568: } ! 6569: } ! 6570: ! 6571: skip = (hp == NULL) ^ (keyword->type == T_IFNDEF); ! 6572: if (start_of_file && !skip) { ! 6573: control_macro = (U_CHAR *) xmalloc (end - buf + 1); ! 6574: bcopy (buf, control_macro, end - buf); ! 6575: control_macro[end - buf] = 0; ! 6576: } ! 6577: } ! 6578: ! 6579: conditional_skip (ip, skip, T_IF, control_macro); ! 6580: return 0; ! 6581: } ! 6582: ! 6583: /* Push TYPE on stack; then, if SKIP is nonzero, skip ahead. ! 6584: If this is a #ifndef starting at the beginning of a file, ! 6585: CONTROL_MACRO is the macro name tested by the #ifndef. ! 6586: Otherwise, CONTROL_MACRO is 0. */ ! 6587: ! 6588: static void ! 6589: conditional_skip (ip, skip, type, control_macro) ! 6590: FILE_BUF *ip; ! 6591: int skip; ! 6592: enum node_type type; ! 6593: U_CHAR *control_macro; ! 6594: { ! 6595: IF_STACK_FRAME *temp; ! 6596: ! 6597: temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME)); ! 6598: temp->fname = ip->nominal_fname; ! 6599: temp->lineno = ip->lineno; ! 6600: temp->next = if_stack; ! 6601: temp->control_macro = control_macro; ! 6602: if_stack = temp; ! 6603: ! 6604: if_stack->type = type; ! 6605: ! 6606: if (skip != 0) { ! 6607: skip_if_group (ip, 0); ! 6608: return; ! 6609: } else { ! 6610: ++if_stack->if_succeeded; ! 6611: output_line_command (ip, &outbuf, 1, same_file); ! 6612: } ! 6613: } ! 6614: ! 6615: /* ! 6616: * skip to #endif, #else, or #elif. adjust line numbers, etc. ! 6617: * leaves input ptr at the sharp sign found. ! 6618: * If ANY is nonzero, return at next directive of any sort. ! 6619: */ ! 6620: static void ! 6621: skip_if_group (ip, any) ! 6622: FILE_BUF *ip; ! 6623: int any; ! 6624: { ! 6625: register U_CHAR *bp = ip->bufp, *cp; ! 6626: register U_CHAR *endb = ip->buf + ip->length; ! 6627: struct directive *kt; ! 6628: IF_STACK_FRAME *save_if_stack = if_stack; /* don't pop past here */ ! 6629: U_CHAR *beg_of_line = bp; ! 6630: register int ident_length; ! 6631: U_CHAR *ident, *after_ident; ! 6632: ! 6633: while (bp < endb) { ! 6634: switch (*bp++) { ! 6635: case '/': /* possible comment */ ! 6636: if (*bp == '\\' && bp[1] == '\n') ! 6637: newline_fix (bp); ! 6638: if (*bp == '*' ! 6639: || (cplusplus_comments && *bp == '/')) { ! 6640: ip->bufp = ++bp; ! 6641: bp = skip_to_end_of_comment (ip, &ip->lineno, 0); ! 6642: } ! 6643: break; ! 6644: case '\"': ! 6645: case '\'': ! 6646: bp = skip_quoted_string (bp - 1, endb, ip->lineno, &ip->lineno, ! 6647: NULL_PTR, NULL_PTR); ! 6648: break; ! 6649: case '\\': ! 6650: /* Char after backslash loses its special meaning. */ ! 6651: if (bp < endb) { ! 6652: if (*bp == '\n') ! 6653: ++ip->lineno; /* But do update the line-count. */ ! 6654: bp++; ! 6655: } ! 6656: break; ! 6657: case '\n': ! 6658: ++ip->lineno; ! 6659: beg_of_line = bp; ! 6660: break; ! 6661: case '#': ! 6662: ip->bufp = bp - 1; ! 6663: ! 6664: /* # keyword: a # must be first nonblank char on the line */ ! 6665: if (beg_of_line == 0) ! 6666: break; ! 6667: /* Scan from start of line, skipping whitespace, comments ! 6668: and backslash-newlines, and see if we reach this #. ! 6669: If not, this # is not special. */ ! 6670: bp = beg_of_line; ! 6671: /* If -traditional, require # to be at beginning of line. */ ! 6672: if (!traditional) ! 6673: while (1) { ! 6674: if (is_hor_space[*bp]) ! 6675: bp++; ! 6676: else if (*bp == '\\' && bp[1] == '\n') ! 6677: bp += 2; ! 6678: else if (*bp == '/' && bp[1] == '*') { ! 6679: bp += 2; ! 6680: while (!(*bp == '*' && bp[1] == '/')) ! 6681: bp++; ! 6682: bp += 2; ! 6683: } else if (cplusplus_comments && *bp == '/' && bp[1] == '/') { ! 6684: bp += 2; ! 6685: while (*bp++ != '\n') ; ! 6686: } ! 6687: else break; ! 6688: } ! 6689: if (bp != ip->bufp) { ! 6690: bp = ip->bufp + 1; /* Reset bp to after the #. */ ! 6691: break; ! 6692: } ! 6693: ! 6694: bp = ip->bufp + 1; /* Point after the '#' */ ! 6695: ! 6696: /* Skip whitespace and \-newline. */ ! 6697: while (1) { ! 6698: if (is_hor_space[*bp]) ! 6699: bp++; ! 6700: else if (*bp == '\\' && bp[1] == '\n') ! 6701: bp += 2; ! 6702: else if (*bp == '/' && bp[1] == '*') { ! 6703: bp += 2; ! 6704: while (!(*bp == '*' && bp[1] == '/')) { ! 6705: if (*bp == '\n') ! 6706: ip->lineno++; ! 6707: bp++; ! 6708: } ! 6709: bp += 2; ! 6710: } else if (cplusplus_comments && *bp == '/' && bp[1] == '/') { ! 6711: bp += 2; ! 6712: while (*bp++ != '\n') ; ! 6713: } ! 6714: else break; ! 6715: } ! 6716: ! 6717: cp = bp; ! 6718: ! 6719: /* Now find end of directive name. ! 6720: If we encounter a backslash-newline, exchange it with any following ! 6721: symbol-constituents so that we end up with a contiguous name. */ ! 6722: ! 6723: while (1) { ! 6724: if (is_idchar[*bp]) ! 6725: bp++; ! 6726: else { ! 6727: if (*bp == '\\' && bp[1] == '\n') ! 6728: name_newline_fix (bp); ! 6729: if (is_idchar[*bp]) ! 6730: bp++; ! 6731: else break; ! 6732: } ! 6733: } ! 6734: ident_length = bp - cp; ! 6735: ident = cp; ! 6736: after_ident = bp; ! 6737: ! 6738: /* A line of just `#' becomes blank. */ ! 6739: ! 6740: if (ident_length == 0 && *after_ident == '\n') { ! 6741: continue; ! 6742: } ! 6743: ! 6744: if (ident_length == 0 || !is_idstart[*ident]) { ! 6745: U_CHAR *p = ident; ! 6746: while (is_idchar[*p]) { ! 6747: if (*p < '0' || *p > '9') ! 6748: break; ! 6749: p++; ! 6750: } ! 6751: /* Handle # followed by a line number. */ ! 6752: if (p != ident && !is_idchar[*p]) { ! 6753: if (pedantic) ! 6754: pedwarn ("`#' followed by integer"); ! 6755: continue; ! 6756: } ! 6757: ! 6758: /* Avoid error for `###' and similar cases unless -pedantic. */ ! 6759: if (p == ident) { ! 6760: while (*p == '#' || is_hor_space[*p]) p++; ! 6761: if (*p == '\n') { ! 6762: if (pedantic && !lang_asm) ! 6763: pedwarn ("invalid preprocessor directive"); ! 6764: continue; ! 6765: } ! 6766: } ! 6767: ! 6768: if (!lang_asm && pedantic) ! 6769: pedwarn ("invalid preprocessor directive name"); ! 6770: continue; ! 6771: } ! 6772: ! 6773: for (kt = directive_table; kt->length >= 0; kt++) { ! 6774: IF_STACK_FRAME *temp; ! 6775: if (ident_length == kt->length ! 6776: && strncmp (cp, kt->name, kt->length) == 0) { ! 6777: /* If we are asked to return on next directive, do so now. */ ! 6778: if (any) ! 6779: return; ! 6780: ! 6781: switch (kt->type) { ! 6782: case T_IF: ! 6783: case T_IFDEF: ! 6784: case T_IFNDEF: ! 6785: temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME)); ! 6786: temp->next = if_stack; ! 6787: if_stack = temp; ! 6788: temp->lineno = ip->lineno; ! 6789: temp->fname = ip->nominal_fname; ! 6790: temp->type = kt->type; ! 6791: break; ! 6792: case T_ELSE: ! 6793: case T_ENDIF: ! 6794: if (pedantic && if_stack != save_if_stack) ! 6795: validate_else (bp); ! 6796: case T_ELIF: ! 6797: if (if_stack == instack[indepth].if_stack) { ! 6798: error ("`#%s' not within a conditional", kt->name); ! 6799: break; ! 6800: } ! 6801: else if (if_stack == save_if_stack) ! 6802: return; /* found what we came for */ ! 6803: ! 6804: if (kt->type != T_ENDIF) { ! 6805: if (if_stack->type == T_ELSE) ! 6806: error ("`#else' or `#elif' after `#else'"); ! 6807: if_stack->type = kt->type; ! 6808: break; ! 6809: } ! 6810: ! 6811: temp = if_stack; ! 6812: if_stack = if_stack->next; ! 6813: free (temp); ! 6814: break; ! 6815: } ! 6816: break; ! 6817: } ! 6818: } ! 6819: /* Don't let erroneous code go by. */ ! 6820: if (kt->length < 0 && !lang_asm && pedantic) ! 6821: pedwarn ("invalid preprocessor directive name"); ! 6822: } ! 6823: } ! 6824: ip->bufp = bp; ! 6825: /* after this returns, rescan will exit because ip->bufp ! 6826: now points to the end of the buffer. ! 6827: rescan is responsible for the error message also. */ ! 6828: } ! 6829: ! 6830: /* ! 6831: * handle a #else directive. Do this by just continuing processing ! 6832: * without changing if_stack ; this is so that the error message ! 6833: * for missing #endif's etc. will point to the original #if. It ! 6834: * is possible that something different would be better. ! 6835: */ ! 6836: ! 6837: static int ! 6838: do_else (buf, limit, op, keyword) ! 6839: U_CHAR *buf, *limit; ! 6840: FILE_BUF *op; ! 6841: struct directive *keyword; ! 6842: { ! 6843: FILE_BUF *ip = &instack[indepth]; ! 6844: ! 6845: if (pedantic) { ! 6846: SKIP_WHITE_SPACE (buf); ! 6847: if (buf != limit) ! 6848: pedwarn ("text following `#else' violates ANSI standard"); ! 6849: } ! 6850: ! 6851: if (if_stack == instack[indepth].if_stack) { ! 6852: error ("`#else' not within a conditional"); ! 6853: return 0; ! 6854: } else { ! 6855: /* #ifndef can't have its special treatment for containing the whole file ! 6856: if it has a #else clause. */ ! 6857: if_stack->control_macro = 0; ! 6858: ! 6859: if (if_stack->type != T_IF && if_stack->type != T_ELIF) { ! 6860: error ("`#else' after `#else'"); ! 6861: #ifdef REPORT_EVENT ! 6862: REPORT_EVENT (0, NULL, if_stack->fname, if_stack->lineno, ! 6863: "matching conditional", 0, 0, 0); ! 6864: #endif ! 6865: fprintf (stderr, " (matches line %d", if_stack->lineno); ! 6866: if (strcmp (if_stack->fname, ip->nominal_fname) != 0) ! 6867: fprintf (stderr, ", file %s", if_stack->fname); ! 6868: fprintf (stderr, ")\n"); ! 6869: } ! 6870: if_stack->type = T_ELSE; ! 6871: } ! 6872: ! 6873: if (if_stack->if_succeeded) ! 6874: skip_if_group (ip, 0); ! 6875: else { ! 6876: ++if_stack->if_succeeded; /* continue processing input */ ! 6877: output_line_command (ip, op, 1, same_file); ! 6878: } ! 6879: return 0; ! 6880: } ! 6881: ! 6882: /* ! 6883: * unstack after #endif command ! 6884: */ ! 6885: ! 6886: static int ! 6887: do_endif (buf, limit, op, keyword) ! 6888: U_CHAR *buf, *limit; ! 6889: FILE_BUF *op; ! 6890: struct directive *keyword; ! 6891: { ! 6892: if (pedantic) { ! 6893: SKIP_WHITE_SPACE (buf); ! 6894: if (buf != limit) ! 6895: pedwarn ("text following `#endif' violates ANSI standard"); ! 6896: } ! 6897: ! 6898: if (if_stack == instack[indepth].if_stack) ! 6899: error ("unbalanced `#endif'"); ! 6900: else { ! 6901: IF_STACK_FRAME *temp = if_stack; ! 6902: if_stack = if_stack->next; ! 6903: if (temp->control_macro != 0) { ! 6904: /* This #endif matched a #ifndef at the start of the file. ! 6905: See if it is at the end of the file. */ ! 6906: FILE_BUF *ip = &instack[indepth]; ! 6907: U_CHAR *p = ip->bufp; ! 6908: U_CHAR *ep = ip->buf + ip->length; ! 6909: ! 6910: while (p != ep) { ! 6911: U_CHAR c = *p++; ! 6912: switch (c) { ! 6913: case ' ': ! 6914: case '\t': ! 6915: case '\n': ! 6916: break; ! 6917: case '/': ! 6918: if (p != ep && *p == '*') { ! 6919: /* Skip this comment. */ ! 6920: int junk; ! 6921: U_CHAR *save_bufp = ip->bufp; ! 6922: ip->bufp = p + 1; ! 6923: p = skip_to_end_of_comment (ip, &junk, 1); ! 6924: ip->bufp = save_bufp; ! 6925: } ! 6926: break; ! 6927: default: ! 6928: goto fail; ! 6929: } ! 6930: } ! 6931: /* If we get here, this #endif ends a #ifndef ! 6932: that contains all of the file (aside from whitespace). ! 6933: Arrange not to include the file again ! 6934: if the macro that was tested is defined. */ ! 6935: if (indepth != 0) ! 6936: record_control_macro (ip->fname, temp->control_macro); ! 6937: fail: ; ! 6938: } ! 6939: free (temp); ! 6940: output_line_command (&instack[indepth], op, 1, same_file); ! 6941: } ! 6942: return 0; ! 6943: } ! 6944: ! 6945: /* When an #else or #endif is found while skipping failed conditional, ! 6946: if -pedantic was specified, this is called to warn about text after ! 6947: the command name. P points to the first char after the command name. */ ! 6948: ! 6949: static void ! 6950: validate_else (p) ! 6951: register U_CHAR *p; ! 6952: { ! 6953: /* Advance P over whitespace and comments. */ ! 6954: while (1) { ! 6955: if (*p == '\\' && p[1] == '\n') ! 6956: p += 2; ! 6957: if (is_hor_space[*p]) ! 6958: p++; ! 6959: else if (*p == '/') { ! 6960: if (p[1] == '\\' && p[2] == '\n') ! 6961: newline_fix (p + 1); ! 6962: if (p[1] == '*') { ! 6963: p += 2; ! 6964: /* Don't bother warning about unterminated comments ! 6965: since that will happen later. Just be sure to exit. */ ! 6966: while (*p) { ! 6967: if (p[1] == '\\' && p[2] == '\n') ! 6968: newline_fix (p + 1); ! 6969: if (*p == '*' && p[1] == '/') { ! 6970: p += 2; ! 6971: break; ! 6972: } ! 6973: p++; ! 6974: } ! 6975: } ! 6976: else if (cplusplus_comments && p[1] == '/') { ! 6977: p += 2; ! 6978: while (*p && *p++ != '\n') ; ! 6979: } ! 6980: } else break; ! 6981: } ! 6982: if (*p && *p != '\n') ! 6983: pedwarn ("text following `#else' or `#endif' violates ANSI standard"); ! 6984: } ! 6985: ! 6986: /* Skip a comment, assuming the input ptr immediately follows the ! 6987: initial slash-star. Bump *LINE_COUNTER for each newline. ! 6988: (The canonical line counter is &ip->lineno.) ! 6989: Don't use this routine (or the next one) if bumping the line ! 6990: counter is not sufficient to deal with newlines in the string. ! 6991: ! 6992: If NOWARN is nonzero, don't warn about slash-star inside a comment. ! 6993: This feature is useful when processing a comment that is going to be ! 6994: processed or was processed at another point in the preprocessor, ! 6995: to avoid a duplicate warning. */ ! 6996: static U_CHAR * ! 6997: skip_to_end_of_comment (ip, line_counter, nowarn) ! 6998: register FILE_BUF *ip; ! 6999: int *line_counter; /* place to remember newlines, or NULL */ ! 7000: int nowarn; ! 7001: { ! 7002: register U_CHAR *limit = ip->buf + ip->length; ! 7003: register U_CHAR *bp = ip->bufp; ! 7004: FILE_BUF *op = &outbuf; /* JF */ ! 7005: int output = put_out_comments && !line_counter; ! 7006: ! 7007: /* JF this line_counter stuff is a crock to make sure the ! 7008: comment is only put out once, no matter how many times ! 7009: the comment is skipped. It almost works */ ! 7010: if (output) { ! 7011: *op->bufp++ = '/'; ! 7012: *op->bufp++ = '*'; ! 7013: } ! 7014: if (cplusplus_comments && bp[-1] == '/') { ! 7015: if (output) { ! 7016: while (bp < limit) ! 7017: if ((*op->bufp++ = *bp++) == '\n') { ! 7018: bp--; ! 7019: break; ! 7020: } ! 7021: op->bufp[-1] = '*'; ! 7022: *op->bufp++ = '/'; ! 7023: *op->bufp++ = '\n'; ! 7024: } else { ! 7025: while (bp < limit) { ! 7026: if (*bp++ == '\n') { ! 7027: bp--; ! 7028: break; ! 7029: } ! 7030: } ! 7031: } ! 7032: ip->bufp = bp; ! 7033: return bp; ! 7034: } ! 7035: while (bp < limit) { ! 7036: if (output) ! 7037: *op->bufp++ = *bp; ! 7038: switch (*bp++) { ! 7039: case '/': ! 7040: if (warn_comments && !nowarn && bp < limit && *bp == '*') ! 7041: warning ("`/*' within comment"); ! 7042: break; ! 7043: case '\n': ! 7044: if (line_counter != NULL) ! 7045: ++*line_counter; ! 7046: if (output) ! 7047: ++op->lineno; ! 7048: break; ! 7049: case '*': ! 7050: if (*bp == '\\' && bp[1] == '\n') ! 7051: newline_fix (bp); ! 7052: if (*bp == '/') { ! 7053: if (output) ! 7054: *op->bufp++ = '/'; ! 7055: ip->bufp = ++bp; ! 7056: return bp; ! 7057: } ! 7058: break; ! 7059: } ! 7060: } ! 7061: ip->bufp = bp; ! 7062: return bp; ! 7063: } ! 7064: ! 7065: /* ! 7066: * Skip over a quoted string. BP points to the opening quote. ! 7067: * Returns a pointer after the closing quote. Don't go past LIMIT. ! 7068: * START_LINE is the line number of the starting point (but it need ! 7069: * not be valid if the starting point is inside a macro expansion). ! 7070: * ! 7071: * The input stack state is not changed. ! 7072: * ! 7073: * If COUNT_NEWLINES is nonzero, it points to an int to increment ! 7074: * for each newline passed. ! 7075: * ! 7076: * If BACKSLASH_NEWLINES_P is nonzero, store 1 thru it ! 7077: * if we pass a backslash-newline. ! 7078: * ! 7079: * If EOFP is nonzero, set *EOFP to 1 if the string is unterminated. ! 7080: */ ! 7081: static U_CHAR * ! 7082: skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, eofp) ! 7083: register U_CHAR *bp; ! 7084: register U_CHAR *limit; ! 7085: int start_line; ! 7086: int *count_newlines; ! 7087: int *backslash_newlines_p; ! 7088: int *eofp; ! 7089: { ! 7090: register U_CHAR c, match; ! 7091: ! 7092: match = *bp++; ! 7093: while (1) { ! 7094: if (bp >= limit) { ! 7095: error_with_line (line_for_error (start_line), ! 7096: "unterminated string or character constant"); ! 7097: error_with_line (multiline_string_line, ! 7098: "possible real start of unterminated constant"); ! 7099: multiline_string_line = 0; ! 7100: if (eofp) ! 7101: *eofp = 1; ! 7102: break; ! 7103: } ! 7104: c = *bp++; ! 7105: if (c == '\\') { ! 7106: while (*bp == '\\' && bp[1] == '\n') { ! 7107: if (backslash_newlines_p) ! 7108: *backslash_newlines_p = 1; ! 7109: if (count_newlines) ! 7110: ++*count_newlines; ! 7111: bp += 2; ! 7112: } ! 7113: if (*bp == '\n' && count_newlines) { ! 7114: if (backslash_newlines_p) ! 7115: *backslash_newlines_p = 1; ! 7116: ++*count_newlines; ! 7117: } ! 7118: bp++; ! 7119: } else if (c == '\n') { ! 7120: if (traditional) { ! 7121: /* Unterminated strings and character constants are 'legal'. */ ! 7122: bp--; /* Don't consume the newline. */ ! 7123: if (eofp) ! 7124: *eofp = 1; ! 7125: break; ! 7126: } ! 7127: if (pedantic || match == '\'') { ! 7128: error_with_line (line_for_error (start_line), ! 7129: "unterminated string or character constant"); ! 7130: bp--; ! 7131: if (eofp) ! 7132: *eofp = 1; ! 7133: break; ! 7134: } ! 7135: /* If not traditional, then allow newlines inside strings. */ ! 7136: if (count_newlines) ! 7137: ++*count_newlines; ! 7138: if (multiline_string_line == 0) ! 7139: multiline_string_line = start_line; ! 7140: } else if (c == match) ! 7141: break; ! 7142: } ! 7143: return bp; ! 7144: } ! 7145: ! 7146: /* Place into DST a quoted string representing the string SRC. ! 7147: Return the address of DST's terminating null. */ ! 7148: static char * ! 7149: quote_string (dst, src) ! 7150: char *dst, *src; ! 7151: { ! 7152: U_CHAR c; ! 7153: ! 7154: *dst++ = '\"'; ! 7155: for (;;) ! 7156: switch ((c = *src++)) ! 7157: { ! 7158: default: ! 7159: if (isprint (c)) ! 7160: *dst++ = c; ! 7161: else ! 7162: { ! 7163: sprintf (dst, "\\%03o", c); ! 7164: dst += 4; ! 7165: } ! 7166: break; ! 7167: ! 7168: case '\"': ! 7169: case '\\': ! 7170: *dst++ = '\\'; ! 7171: *dst++ = c; ! 7172: break; ! 7173: ! 7174: case '\0': ! 7175: *dst++ = '\"'; ! 7176: *dst = '\0'; ! 7177: return dst; ! 7178: } ! 7179: } ! 7180: ! 7181: /* Skip across a group of balanced parens, starting from IP->bufp. ! 7182: IP->bufp is updated. Use this with IP->bufp pointing at an open-paren. ! 7183: ! 7184: This does not handle newlines, because it's used for the arg of #if, ! 7185: where there aren't any newlines. Also, backslash-newline can't appear. */ ! 7186: ! 7187: static U_CHAR * ! 7188: skip_paren_group (ip) ! 7189: register FILE_BUF *ip; ! 7190: { ! 7191: U_CHAR *limit = ip->buf + ip->length; ! 7192: U_CHAR *p = ip->bufp; ! 7193: int depth = 0; ! 7194: int lines_dummy = 0; ! 7195: ! 7196: while (p != limit) { ! 7197: int c = *p++; ! 7198: switch (c) { ! 7199: case '(': ! 7200: depth++; ! 7201: break; ! 7202: ! 7203: case ')': ! 7204: depth--; ! 7205: if (depth == 0) ! 7206: return ip->bufp = p; ! 7207: break; ! 7208: ! 7209: case '/': ! 7210: if (*p == '*') { ! 7211: ip->bufp = p; ! 7212: p = skip_to_end_of_comment (ip, &lines_dummy, 0); ! 7213: p = ip->bufp; ! 7214: } ! 7215: ! 7216: case '"': ! 7217: case '\'': ! 7218: { ! 7219: int eofp = 0; ! 7220: p = skip_quoted_string (p - 1, limit, 0, NULL_PTR, NULL_PTR, &eofp); ! 7221: if (eofp) ! 7222: return ip->bufp = p; ! 7223: } ! 7224: break; ! 7225: } ! 7226: } ! 7227: ! 7228: ip->bufp = p; ! 7229: return p; ! 7230: } ! 7231: ! 7232: /* ! 7233: * write out a #line command, for instance, after an #include file. ! 7234: * If CONDITIONAL is nonzero, we can omit the #line if it would ! 7235: * appear to be a no-op, and we can output a few newlines instead ! 7236: * if we want to increase the line number by a small amount. ! 7237: * FILE_CHANGE says whether we are entering a file, leaving, or neither. ! 7238: */ ! 7239: ! 7240: static void ! 7241: output_line_command (ip, op, conditional, file_change) ! 7242: FILE_BUF *ip, *op; ! 7243: int conditional; ! 7244: enum file_change_code file_change; ! 7245: { ! 7246: int len; ! 7247: char *line_cmd_buf, *line_end; ! 7248: ! 7249: if (no_line_commands ! 7250: || ip->fname == NULL ! 7251: || no_output) { ! 7252: op->lineno = ip->lineno; ! 7253: return; ! 7254: } ! 7255: ! 7256: if (conditional) { ! 7257: if (ip->lineno == op->lineno) ! 7258: return; ! 7259: ! 7260: /* If the inherited line number is a little too small, ! 7261: output some newlines instead of a #line command. */ ! 7262: if (ip->lineno > op->lineno && ip->lineno < op->lineno + 8) { ! 7263: check_expand (op, 10); ! 7264: while (ip->lineno > op->lineno) { ! 7265: *op->bufp++ = '\n'; ! 7266: op->lineno++; ! 7267: } ! 7268: return; ! 7269: } ! 7270: } ! 7271: ! 7272: /* Don't output a line number of 0 if we can help it. */ ! 7273: if (ip->lineno == 0 && ip->bufp - ip->buf < ip->length ! 7274: && *ip->bufp == '\n') { ! 7275: ip->lineno++; ! 7276: ip->bufp++; ! 7277: } ! 7278: ! 7279: line_cmd_buf = (char *) alloca (4 * strlen (ip->nominal_fname) + 100); ! 7280: #ifdef OUTPUT_LINE_COMMANDS ! 7281: sprintf (line_cmd_buf, "#line %d ", ip->lineno); ! 7282: #else ! 7283: sprintf (line_cmd_buf, "# %d ", ip->lineno); ! 7284: #endif ! 7285: line_end = quote_string (line_cmd_buf + strlen (line_cmd_buf), ! 7286: ip->nominal_fname); ! 7287: if (file_change != same_file) { ! 7288: *line_end++ = ' '; ! 7289: *line_end++ = file_change == enter_file ? '1' : '2'; ! 7290: } ! 7291: /* Tell cc1 if following text comes from a system header file. */ ! 7292: if (ip->system_header_p) { ! 7293: *line_end++ = ' '; ! 7294: *line_end++ = '3'; ! 7295: } ! 7296: #ifndef NO_IMPLICIT_EXTERN_C ! 7297: /* Tell cc1plus if following text should be treated as C. */ ! 7298: if (ip->system_header_p == 2 && cplusplus) { ! 7299: *line_end++ = ' '; ! 7300: *line_end++ = '4'; ! 7301: } ! 7302: #endif ! 7303: *line_end++ = '\n'; ! 7304: len = line_end - line_cmd_buf; ! 7305: check_expand (op, len + 1); ! 7306: if (op->bufp > op->buf && op->bufp[-1] != '\n') ! 7307: *op->bufp++ = '\n'; ! 7308: bcopy (line_cmd_buf, op->bufp, len); ! 7309: op->bufp += len; ! 7310: op->lineno = ip->lineno; ! 7311: } ! 7312: ! 7313: /* This structure represents one parsed argument in a macro call. ! 7314: `raw' points to the argument text as written (`raw_length' is its length). ! 7315: `expanded' points to the argument's macro-expansion ! 7316: (its length is `expand_length'). ! 7317: `stringified_length' is the length the argument would have ! 7318: if stringified. ! 7319: `use_count' is the number of times this macro arg is substituted ! 7320: into the macro. If the actual use count exceeds 10, ! 7321: the value stored is 10. ! 7322: `free1' and `free2', if nonzero, point to blocks to be freed ! 7323: when the macro argument data is no longer needed. */ ! 7324: ! 7325: struct argdata { ! 7326: U_CHAR *raw, *expanded; ! 7327: int raw_length, expand_length; ! 7328: int stringified_length; ! 7329: U_CHAR *free1, *free2; ! 7330: char newlines; ! 7331: char comments; ! 7332: char use_count; ! 7333: }; ! 7334: ! 7335: /* Expand a macro call. ! 7336: HP points to the symbol that is the macro being called. ! 7337: Put the result of expansion onto the input stack ! 7338: so that subsequent input by our caller will use it. ! 7339: ! 7340: If macro wants arguments, caller has already verified that ! 7341: an argument list follows; arguments come from the input stack. */ ! 7342: ! 7343: static void ! 7344: macroexpand (hp, op) ! 7345: HASHNODE *hp; ! 7346: FILE_BUF *op; ! 7347: { ! 7348: int nargs; ! 7349: DEFINITION *defn = hp->value.defn; ! 7350: register U_CHAR *xbuf; ! 7351: int xbuf_len; ! 7352: int start_line = instack[indepth].lineno; ! 7353: int rest_args, rest_zero; ! 7354: ! 7355: CHECK_DEPTH (return;); ! 7356: ! 7357: /* it might not actually be a macro. */ ! 7358: if (hp->type != T_MACRO) { ! 7359: special_symbol (hp, op); ! 7360: return; ! 7361: } ! 7362: ! 7363: /* This macro is being used inside a #if, which means it must be */ ! 7364: /* recorded as a precondition. */ ! 7365: if (pcp_inside_if && pcp_outfile && defn->predefined) ! 7366: dump_single_macro (hp, pcp_outfile); ! 7367: ! 7368: nargs = defn->nargs; ! 7369: ! 7370: if (nargs >= 0) { ! 7371: register int i; ! 7372: struct argdata *args; ! 7373: char *parse_error = 0; ! 7374: ! 7375: args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata)); ! 7376: ! 7377: for (i = 0; i < nargs; i++) { ! 7378: args[i].raw = (U_CHAR *) ""; ! 7379: args[i].expanded = 0; ! 7380: args[i].raw_length = args[i].expand_length ! 7381: = args[i].stringified_length = 0; ! 7382: args[i].free1 = args[i].free2 = 0; ! 7383: args[i].use_count = 0; ! 7384: } ! 7385: ! 7386: /* Parse all the macro args that are supplied. I counts them. ! 7387: The first NARGS args are stored in ARGS. ! 7388: The rest are discarded. ! 7389: If rest_args is set then we assume macarg absorbed the rest of the args. ! 7390: */ ! 7391: i = 0; ! 7392: rest_args = 0; ! 7393: do { ! 7394: /* Discard the open-parenthesis or comma before the next arg. */ ! 7395: ++instack[indepth].bufp; ! 7396: if (rest_args) ! 7397: continue; ! 7398: if (i < nargs || (nargs == 0 && i == 0)) { ! 7399: /* if we are working on last arg which absorbs rest of args... */ ! 7400: if (i == nargs - 1 && defn->rest_args) ! 7401: rest_args = 1; ! 7402: parse_error = macarg (&args[i], rest_args); ! 7403: } ! 7404: else ! 7405: parse_error = macarg (NULL_PTR, 0); ! 7406: if (parse_error) { ! 7407: error_with_line (line_for_error (start_line), parse_error); ! 7408: break; ! 7409: } ! 7410: i++; ! 7411: } while (*instack[indepth].bufp != ')'); ! 7412: ! 7413: /* If we got one arg but it was just whitespace, call that 0 args. */ ! 7414: if (i == 1) { ! 7415: register U_CHAR *bp = args[0].raw; ! 7416: register U_CHAR *lim = bp + args[0].raw_length; ! 7417: /* cpp.texi says for foo ( ) we provide one argument. ! 7418: However, if foo wants just 0 arguments, treat this as 0. */ ! 7419: if (nargs == 0) ! 7420: while (bp != lim && is_space[*bp]) bp++; ! 7421: if (bp == lim) ! 7422: i = 0; ! 7423: } ! 7424: ! 7425: /* Don't output an error message if we have already output one for ! 7426: a parse error above. */ ! 7427: rest_zero = 0; ! 7428: if (nargs == 0 && i > 0) { ! 7429: if (! parse_error) ! 7430: error ("arguments given to macro `%s'", hp->name); ! 7431: } else if (i < nargs) { ! 7432: /* traditional C allows foo() if foo wants one argument. */ ! 7433: if (nargs == 1 && i == 0 && traditional) ! 7434: ; ! 7435: /* the rest args token is allowed to absorb 0 tokens */ ! 7436: else if (i == nargs - 1 && defn->rest_args) ! 7437: rest_zero = 1; ! 7438: else if (parse_error) ! 7439: ; ! 7440: else if (i == 0) ! 7441: error ("macro `%s' used without args", hp->name); ! 7442: else if (i == 1) ! 7443: error ("macro `%s' used with just one arg", hp->name); ! 7444: else ! 7445: error ("macro `%s' used with only %d args", hp->name, i); ! 7446: } else if (i > nargs) { ! 7447: if (! parse_error) ! 7448: error ("macro `%s' used with too many (%d) args", hp->name, i); ! 7449: } ! 7450: ! 7451: /* Swallow the closeparen. */ ! 7452: ++instack[indepth].bufp; ! 7453: ! 7454: /* If macro wants zero args, we parsed the arglist for checking only. ! 7455: Read directly from the macro definition. */ ! 7456: if (nargs == 0) { ! 7457: xbuf = defn->expansion; ! 7458: xbuf_len = defn->length; ! 7459: } else { ! 7460: register U_CHAR *exp = defn->expansion; ! 7461: register int offset; /* offset in expansion, ! 7462: copied a piece at a time */ ! 7463: register int totlen; /* total amount of exp buffer filled so far */ ! 7464: ! 7465: register struct reflist *ap, *last_ap; ! 7466: ! 7467: /* Macro really takes args. Compute the expansion of this call. */ ! 7468: ! 7469: /* Compute length in characters of the macro's expansion. ! 7470: Also count number of times each arg is used. */ ! 7471: xbuf_len = defn->length; ! 7472: for (ap = defn->pattern; ap != NULL; ap = ap->next) { ! 7473: if (ap->stringify) ! 7474: xbuf_len += args[ap->argno].stringified_length; ! 7475: else if (ap->raw_before || ap->raw_after || traditional) ! 7476: /* Add 4 for two newline-space markers to prevent ! 7477: token concatenation. */ ! 7478: xbuf_len += args[ap->argno].raw_length + 4; ! 7479: else { ! 7480: /* We have an ordinary (expanded) occurrence of the arg. ! 7481: So compute its expansion, if we have not already. */ ! 7482: if (args[ap->argno].expanded == 0) { ! 7483: FILE_BUF obuf; ! 7484: obuf = expand_to_temp_buffer (args[ap->argno].raw, ! 7485: args[ap->argno].raw + args[ap->argno].raw_length, ! 7486: 1, 0); ! 7487: ! 7488: args[ap->argno].expanded = obuf.buf; ! 7489: args[ap->argno].expand_length = obuf.length; ! 7490: args[ap->argno].free2 = obuf.buf; ! 7491: } ! 7492: ! 7493: /* Add 4 for two newline-space markers to prevent ! 7494: token concatenation. */ ! 7495: xbuf_len += args[ap->argno].expand_length + 4; ! 7496: } ! 7497: if (args[ap->argno].use_count < 10) ! 7498: args[ap->argno].use_count++; ! 7499: } ! 7500: ! 7501: xbuf = (U_CHAR *) xmalloc (xbuf_len + 1); ! 7502: ! 7503: /* Generate in XBUF the complete expansion ! 7504: with arguments substituted in. ! 7505: TOTLEN is the total size generated so far. ! 7506: OFFSET is the index in the definition ! 7507: of where we are copying from. */ ! 7508: offset = totlen = 0; ! 7509: for (last_ap = NULL, ap = defn->pattern; ap != NULL; ! 7510: last_ap = ap, ap = ap->next) { ! 7511: register struct argdata *arg = &args[ap->argno]; ! 7512: int count_before = totlen; ! 7513: ! 7514: /* Add chars to XBUF. */ ! 7515: for (i = 0; i < ap->nchars; i++, offset++) ! 7516: xbuf[totlen++] = exp[offset]; ! 7517: ! 7518: /* If followed by an empty rest arg with concatenation, ! 7519: delete the last run of nonwhite chars. */ ! 7520: if (rest_zero && totlen > count_before ! 7521: && ((ap->rest_args && ap->raw_before) ! 7522: || (last_ap != NULL && last_ap->rest_args ! 7523: && last_ap->raw_after))) { ! 7524: /* Delete final whitespace. */ ! 7525: while (totlen > count_before && is_space[xbuf[totlen - 1]]) { ! 7526: totlen--; ! 7527: } ! 7528: ! 7529: /* Delete the nonwhites before them. */ ! 7530: while (totlen > count_before && ! is_space[xbuf[totlen - 1]]) { ! 7531: totlen--; ! 7532: } ! 7533: } ! 7534: ! 7535: if (ap->stringify != 0) { ! 7536: int arglen = arg->raw_length; ! 7537: int escaped = 0; ! 7538: int in_string = 0; ! 7539: int c; ! 7540: i = 0; ! 7541: while (i < arglen ! 7542: && (c = arg->raw[i], is_space[c])) ! 7543: i++; ! 7544: while (i < arglen ! 7545: && (c = arg->raw[arglen - 1], is_space[c])) ! 7546: arglen--; ! 7547: if (!traditional) ! 7548: xbuf[totlen++] = '\"'; /* insert beginning quote */ ! 7549: for (; i < arglen; i++) { ! 7550: c = arg->raw[i]; ! 7551: ! 7552: /* Special markers Newline Space ! 7553: generate nothing for a stringified argument. */ ! 7554: if (c == '\n' && arg->raw[i+1] != '\n') { ! 7555: i++; ! 7556: continue; ! 7557: } ! 7558: ! 7559: /* Internal sequences of whitespace are replaced by one space ! 7560: except within an string or char token. */ ! 7561: if (! in_string ! 7562: && (c == '\n' ? arg->raw[i+1] == '\n' : is_space[c])) { ! 7563: while (1) { ! 7564: /* Note that Newline Space does occur within whitespace ! 7565: sequences; consider it part of the sequence. */ ! 7566: if (c == '\n' && is_space[arg->raw[i+1]]) ! 7567: i += 2; ! 7568: else if (c != '\n' && is_space[c]) ! 7569: i++; ! 7570: else break; ! 7571: c = arg->raw[i]; ! 7572: } ! 7573: i--; ! 7574: c = ' '; ! 7575: } ! 7576: ! 7577: if (escaped) ! 7578: escaped = 0; ! 7579: else { ! 7580: if (c == '\\') ! 7581: escaped = 1; ! 7582: if (in_string) { ! 7583: if (c == in_string) ! 7584: in_string = 0; ! 7585: } else if (c == '\"' || c == '\'') ! 7586: in_string = c; ! 7587: } ! 7588: ! 7589: /* Escape these chars */ ! 7590: if (c == '\"' || (in_string && c == '\\')) ! 7591: xbuf[totlen++] = '\\'; ! 7592: if (isprint (c)) ! 7593: xbuf[totlen++] = c; ! 7594: else { ! 7595: sprintf ((char *) &xbuf[totlen], "\\%03o", (unsigned int) c); ! 7596: totlen += 4; ! 7597: } ! 7598: } ! 7599: if (!traditional) ! 7600: xbuf[totlen++] = '\"'; /* insert ending quote */ ! 7601: } else if (ap->raw_before || ap->raw_after || traditional) { ! 7602: U_CHAR *p1 = arg->raw; ! 7603: U_CHAR *l1 = p1 + arg->raw_length; ! 7604: if (ap->raw_before) { ! 7605: while (p1 != l1 && is_space[*p1]) p1++; ! 7606: while (p1 != l1 && is_idchar[*p1]) ! 7607: xbuf[totlen++] = *p1++; ! 7608: /* Delete any no-reexpansion marker that follows ! 7609: an identifier at the beginning of the argument ! 7610: if the argument is concatenated with what precedes it. */ ! 7611: if (p1[0] == '\n' && p1[1] == '-') ! 7612: p1 += 2; ! 7613: } else if (!traditional) { ! 7614: /* Ordinary expanded use of the argument. ! 7615: Put in newline-space markers to prevent token pasting. */ ! 7616: xbuf[totlen++] = '\n'; ! 7617: xbuf[totlen++] = ' '; ! 7618: } ! 7619: if (ap->raw_after) { ! 7620: /* Arg is concatenated after: delete trailing whitespace, ! 7621: whitespace markers, and no-reexpansion markers. */ ! 7622: while (p1 != l1) { ! 7623: if (is_space[l1[-1]]) l1--; ! 7624: else if (l1[-1] == '-') { ! 7625: U_CHAR *p2 = l1 - 1; ! 7626: /* If a `-' is preceded by an odd number of newlines then it ! 7627: and the last newline are a no-reexpansion marker. */ ! 7628: while (p2 != p1 && p2[-1] == '\n') p2--; ! 7629: if ((l1 - 1 - p2) & 1) { ! 7630: l1 -= 2; ! 7631: } ! 7632: else break; ! 7633: } ! 7634: else break; ! 7635: } ! 7636: } ! 7637: ! 7638: bcopy (p1, xbuf + totlen, l1 - p1); ! 7639: totlen += l1 - p1; ! 7640: if (!traditional && !ap->raw_after) { ! 7641: /* Ordinary expanded use of the argument. ! 7642: Put in newline-space markers to prevent token pasting. */ ! 7643: xbuf[totlen++] = '\n'; ! 7644: xbuf[totlen++] = ' '; ! 7645: } ! 7646: } else { ! 7647: /* Ordinary expanded use of the argument. ! 7648: Put in newline-space markers to prevent token pasting. */ ! 7649: if (!traditional) { ! 7650: xbuf[totlen++] = '\n'; ! 7651: xbuf[totlen++] = ' '; ! 7652: } ! 7653: bcopy (arg->expanded, xbuf + totlen, arg->expand_length); ! 7654: totlen += arg->expand_length; ! 7655: if (!traditional) { ! 7656: xbuf[totlen++] = '\n'; ! 7657: xbuf[totlen++] = ' '; ! 7658: } ! 7659: /* If a macro argument with newlines is used multiple times, ! 7660: then only expand the newlines once. This avoids creating output ! 7661: lines which don't correspond to any input line, which confuses ! 7662: gdb and gcov. */ ! 7663: if (arg->use_count > 1 && arg->newlines > 0) { ! 7664: /* Don't bother doing change_newlines for subsequent ! 7665: uses of arg. */ ! 7666: arg->use_count = 1; ! 7667: arg->expand_length ! 7668: = change_newlines (arg->expanded, arg->expand_length); ! 7669: } ! 7670: } ! 7671: ! 7672: if (totlen > xbuf_len) ! 7673: abort (); ! 7674: } ! 7675: ! 7676: /* if there is anything left of the definition ! 7677: after handling the arg list, copy that in too. */ ! 7678: ! 7679: for (i = offset; i < defn->length; i++) { ! 7680: /* if we've reached the end of the macro */ ! 7681: if (exp[i] == ')') ! 7682: rest_zero = 0; ! 7683: if (! (rest_zero && last_ap != NULL && last_ap->rest_args ! 7684: && last_ap->raw_after)) ! 7685: xbuf[totlen++] = exp[i]; ! 7686: } ! 7687: ! 7688: xbuf[totlen] = 0; ! 7689: xbuf_len = totlen; ! 7690: ! 7691: for (i = 0; i < nargs; i++) { ! 7692: if (args[i].free1 != 0) ! 7693: free (args[i].free1); ! 7694: if (args[i].free2 != 0) ! 7695: free (args[i].free2); ! 7696: } ! 7697: } ! 7698: } else { ! 7699: xbuf = defn->expansion; ! 7700: xbuf_len = defn->length; ! 7701: } ! 7702: ! 7703: /* Now put the expansion on the input stack ! 7704: so our caller will commence reading from it. */ ! 7705: { ! 7706: register FILE_BUF *ip2; ! 7707: ! 7708: ip2 = &instack[++indepth]; ! 7709: ! 7710: ip2->fname = 0; ! 7711: ip2->nominal_fname = 0; ! 7712: ip2->lineno = 0; ! 7713: ip2->buf = xbuf; ! 7714: ip2->length = xbuf_len; ! 7715: ip2->bufp = xbuf; ! 7716: ip2->free_ptr = (nargs > 0) ? xbuf : 0; ! 7717: ip2->macro = hp; ! 7718: ip2->if_stack = if_stack; ! 7719: ip2->system_header_p = 0; ! 7720: ! 7721: /* Recursive macro use sometimes works traditionally. ! 7722: #define foo(x,y) bar (x (y,0), y) ! 7723: foo (foo, baz) */ ! 7724: ! 7725: if (!traditional) ! 7726: hp->type = T_DISABLED; ! 7727: } ! 7728: } ! 7729: ! 7730: /* ! 7731: * Parse a macro argument and store the info on it into *ARGPTR. ! 7732: * REST_ARGS is passed to macarg1 to make it absorb the rest of the args. ! 7733: * Return nonzero to indicate a syntax error. ! 7734: */ ! 7735: ! 7736: static char * ! 7737: macarg (argptr, rest_args) ! 7738: register struct argdata *argptr; ! 7739: int rest_args; ! 7740: { ! 7741: FILE_BUF *ip = &instack[indepth]; ! 7742: int paren = 0; ! 7743: int newlines = 0; ! 7744: int comments = 0; ! 7745: ! 7746: /* Try to parse as much of the argument as exists at this ! 7747: input stack level. */ ! 7748: U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length, ! 7749: &paren, &newlines, &comments, rest_args); ! 7750: ! 7751: /* If we find the end of the argument at this level, ! 7752: set up *ARGPTR to point at it in the input stack. */ ! 7753: if (!(ip->fname != 0 && (newlines != 0 || comments != 0)) ! 7754: && bp != ip->buf + ip->length) { ! 7755: if (argptr != 0) { ! 7756: argptr->raw = ip->bufp; ! 7757: argptr->raw_length = bp - ip->bufp; ! 7758: argptr->newlines = newlines; ! 7759: } ! 7760: ip->bufp = bp; ! 7761: } else { ! 7762: /* This input stack level ends before the macro argument does. ! 7763: We must pop levels and keep parsing. ! 7764: Therefore, we must allocate a temporary buffer and copy ! 7765: the macro argument into it. */ ! 7766: int bufsize = bp - ip->bufp; ! 7767: int extra = newlines; ! 7768: U_CHAR *buffer = (U_CHAR *) xmalloc (bufsize + extra + 1); ! 7769: int final_start = 0; ! 7770: ! 7771: bcopy (ip->bufp, buffer, bufsize); ! 7772: ip->bufp = bp; ! 7773: ip->lineno += newlines; ! 7774: ! 7775: while (bp == ip->buf + ip->length) { ! 7776: if (instack[indepth].macro == 0) { ! 7777: free (buffer); ! 7778: return "unterminated macro call"; ! 7779: } ! 7780: ip->macro->type = T_MACRO; ! 7781: if (ip->free_ptr) ! 7782: free (ip->free_ptr); ! 7783: ip = &instack[--indepth]; ! 7784: newlines = 0; ! 7785: comments = 0; ! 7786: bp = macarg1 (ip->bufp, ip->buf + ip->length, &paren, ! 7787: &newlines, &comments, rest_args); ! 7788: final_start = bufsize; ! 7789: bufsize += bp - ip->bufp; ! 7790: extra += newlines; ! 7791: buffer = (U_CHAR *) xrealloc (buffer, bufsize + extra + 1); ! 7792: bcopy (ip->bufp, buffer + bufsize - (bp - ip->bufp), bp - ip->bufp); ! 7793: ip->bufp = bp; ! 7794: ip->lineno += newlines; ! 7795: } ! 7796: ! 7797: /* Now, if arg is actually wanted, record its raw form, ! 7798: discarding comments and duplicating newlines in whatever ! 7799: part of it did not come from a macro expansion. ! 7800: EXTRA space has been preallocated for duplicating the newlines. ! 7801: FINAL_START is the index of the start of that part. */ ! 7802: if (argptr != 0) { ! 7803: argptr->raw = buffer; ! 7804: argptr->raw_length = bufsize; ! 7805: argptr->free1 = buffer; ! 7806: argptr->newlines = newlines; ! 7807: argptr->comments = comments; ! 7808: if ((newlines || comments) && ip->fname != 0) ! 7809: argptr->raw_length ! 7810: = final_start + ! 7811: discard_comments (argptr->raw + final_start, ! 7812: argptr->raw_length - final_start, ! 7813: newlines); ! 7814: argptr->raw[argptr->raw_length] = 0; ! 7815: if (argptr->raw_length > bufsize + extra) ! 7816: abort (); ! 7817: } ! 7818: } ! 7819: ! 7820: /* If we are not discarding this argument, ! 7821: macroexpand it and compute its length as stringified. ! 7822: All this info goes into *ARGPTR. */ ! 7823: ! 7824: if (argptr != 0) { ! 7825: register U_CHAR *buf, *lim; ! 7826: register int totlen; ! 7827: ! 7828: buf = argptr->raw; ! 7829: lim = buf + argptr->raw_length; ! 7830: ! 7831: while (buf != lim && is_space[*buf]) ! 7832: buf++; ! 7833: while (buf != lim && is_space[lim[-1]]) ! 7834: lim--; ! 7835: totlen = traditional ? 0 : 2; /* Count opening and closing quote. */ ! 7836: while (buf != lim) { ! 7837: register U_CHAR c = *buf++; ! 7838: totlen++; ! 7839: /* Internal sequences of whitespace are replaced by one space ! 7840: in most cases, but not always. So count all the whitespace ! 7841: in case we need to keep it all. */ ! 7842: #if 0 ! 7843: if (is_space[c]) ! 7844: SKIP_ALL_WHITE_SPACE (buf); ! 7845: else ! 7846: #endif ! 7847: if (c == '\"' || c == '\\') /* escape these chars */ ! 7848: totlen++; ! 7849: else if (!isprint (c)) ! 7850: totlen += 3; ! 7851: } ! 7852: argptr->stringified_length = totlen; ! 7853: } ! 7854: return 0; ! 7855: } ! 7856: ! 7857: /* Scan text from START (inclusive) up to LIMIT (exclusive), ! 7858: counting parens in *DEPTHPTR, ! 7859: and return if reach LIMIT ! 7860: or before a `)' that would make *DEPTHPTR negative ! 7861: or before a comma when *DEPTHPTR is zero. ! 7862: Single and double quotes are matched and termination ! 7863: is inhibited within them. Comments also inhibit it. ! 7864: Value returned is pointer to stopping place. ! 7865: ! 7866: Increment *NEWLINES each time a newline is passed. ! 7867: REST_ARGS notifies macarg1 that it should absorb the rest of the args. ! 7868: Set *COMMENTS to 1 if a comment is seen. */ ! 7869: ! 7870: static U_CHAR * ! 7871: macarg1 (start, limit, depthptr, newlines, comments, rest_args) ! 7872: U_CHAR *start; ! 7873: register U_CHAR *limit; ! 7874: int *depthptr, *newlines, *comments; ! 7875: int rest_args; ! 7876: { ! 7877: register U_CHAR *bp = start; ! 7878: ! 7879: while (bp < limit) { ! 7880: switch (*bp) { ! 7881: case '(': ! 7882: (*depthptr)++; ! 7883: break; ! 7884: case ')': ! 7885: if (--(*depthptr) < 0) ! 7886: return bp; ! 7887: break; ! 7888: case '\\': ! 7889: /* Traditionally, backslash makes following char not special. */ ! 7890: if (bp + 1 < limit && traditional) ! 7891: { ! 7892: bp++; ! 7893: /* But count source lines anyway. */ ! 7894: if (*bp == '\n') ! 7895: ++*newlines; ! 7896: } ! 7897: break; ! 7898: case '\n': ! 7899: ++*newlines; ! 7900: break; ! 7901: case '/': ! 7902: if (bp[1] == '\\' && bp[2] == '\n') ! 7903: newline_fix (bp + 1); ! 7904: if (cplusplus_comments && bp[1] == '/') { ! 7905: *comments = 1; ! 7906: bp += 2; ! 7907: while (bp < limit && *bp++ != '\n') ; ! 7908: ++*newlines; ! 7909: break; ! 7910: } ! 7911: if (bp[1] != '*' || bp + 1 >= limit) ! 7912: break; ! 7913: *comments = 1; ! 7914: bp += 2; ! 7915: while (bp + 1 < limit) { ! 7916: if (bp[0] == '*' ! 7917: && bp[1] == '\\' && bp[2] == '\n') ! 7918: newline_fix (bp + 1); ! 7919: if (bp[0] == '*' && bp[1] == '/') ! 7920: break; ! 7921: if (*bp == '\n') ++*newlines; ! 7922: bp++; ! 7923: } ! 7924: break; ! 7925: case '\'': ! 7926: case '\"': ! 7927: { ! 7928: int quotec; ! 7929: for (quotec = *bp++; bp + 1 < limit && *bp != quotec; bp++) { ! 7930: if (*bp == '\\') { ! 7931: bp++; ! 7932: if (*bp == '\n') ! 7933: ++*newlines; ! 7934: while (*bp == '\\' && bp[1] == '\n') { ! 7935: bp += 2; ! 7936: } ! 7937: } else if (*bp == '\n') { ! 7938: ++*newlines; ! 7939: if (quotec == '\'') ! 7940: break; ! 7941: } ! 7942: } ! 7943: } ! 7944: break; ! 7945: case ',': ! 7946: /* if we've returned to lowest level and we aren't absorbing all args */ ! 7947: if ((*depthptr) == 0 && rest_args == 0) ! 7948: return bp; ! 7949: break; ! 7950: } ! 7951: bp++; ! 7952: } ! 7953: ! 7954: return bp; ! 7955: } ! 7956: ! 7957: /* Discard comments and duplicate newlines ! 7958: in the string of length LENGTH at START, ! 7959: except inside of string constants. ! 7960: The string is copied into itself with its beginning staying fixed. ! 7961: ! 7962: NEWLINES is the number of newlines that must be duplicated. ! 7963: We assume that that much extra space is available past the end ! 7964: of the string. */ ! 7965: ! 7966: static int ! 7967: discard_comments (start, length, newlines) ! 7968: U_CHAR *start; ! 7969: int length; ! 7970: int newlines; ! 7971: { ! 7972: register U_CHAR *ibp; ! 7973: register U_CHAR *obp; ! 7974: register U_CHAR *limit; ! 7975: register int c; ! 7976: ! 7977: /* If we have newlines to duplicate, copy everything ! 7978: that many characters up. Then, in the second part, ! 7979: we will have room to insert the newlines ! 7980: while copying down. ! 7981: NEWLINES may actually be too large, because it counts ! 7982: newlines in string constants, and we don't duplicate those. ! 7983: But that does no harm. */ ! 7984: if (newlines > 0) { ! 7985: ibp = start + length; ! 7986: obp = ibp + newlines; ! 7987: limit = start; ! 7988: while (limit != ibp) ! 7989: *--obp = *--ibp; ! 7990: } ! 7991: ! 7992: ibp = start + newlines; ! 7993: limit = start + length + newlines; ! 7994: obp = start; ! 7995: ! 7996: while (ibp < limit) { ! 7997: *obp++ = c = *ibp++; ! 7998: switch (c) { ! 7999: case '\n': ! 8000: /* Duplicate the newline. */ ! 8001: *obp++ = '\n'; ! 8002: break; ! 8003: ! 8004: case '\\': ! 8005: if (*ibp == '\n') { ! 8006: obp--; ! 8007: ibp++; ! 8008: } ! 8009: break; ! 8010: ! 8011: case '/': ! 8012: if (*ibp == '\\' && ibp[1] == '\n') ! 8013: newline_fix (ibp); ! 8014: /* Delete any comment. */ ! 8015: if (cplusplus_comments && ibp[0] == '/') { ! 8016: obp--; ! 8017: ibp++; ! 8018: while (ibp < limit && *ibp++ != '\n') ; ! 8019: break; ! 8020: } ! 8021: if (ibp[0] != '*' || ibp + 1 >= limit) ! 8022: break; ! 8023: obp--; ! 8024: ibp++; ! 8025: while (ibp + 1 < limit) { ! 8026: if (ibp[0] == '*' ! 8027: && ibp[1] == '\\' && ibp[2] == '\n') ! 8028: newline_fix (ibp + 1); ! 8029: if (ibp[0] == '*' && ibp[1] == '/') ! 8030: break; ! 8031: ibp++; ! 8032: } ! 8033: ibp += 2; ! 8034: break; ! 8035: ! 8036: case '\'': ! 8037: case '\"': ! 8038: /* Notice and skip strings, so that we don't ! 8039: think that comments start inside them, ! 8040: and so we don't duplicate newlines in them. */ ! 8041: { ! 8042: int quotec = c; ! 8043: while (ibp < limit) { ! 8044: *obp++ = c = *ibp++; ! 8045: if (c == quotec) ! 8046: break; ! 8047: if (c == '\n' && quotec == '\'') ! 8048: break; ! 8049: if (c == '\\' && ibp < limit) { ! 8050: while (*ibp == '\\' && ibp[1] == '\n') ! 8051: ibp += 2; ! 8052: *obp++ = *ibp++; ! 8053: } ! 8054: } ! 8055: } ! 8056: break; ! 8057: } ! 8058: } ! 8059: ! 8060: return obp - start; ! 8061: } ! 8062: ! 8063: /* Turn newlines to spaces in the string of length LENGTH at START, ! 8064: except inside of string constants. ! 8065: The string is copied into itself with its beginning staying fixed. */ ! 8066: ! 8067: static int ! 8068: change_newlines (start, length) ! 8069: U_CHAR *start; ! 8070: int length; ! 8071: { ! 8072: register U_CHAR *ibp; ! 8073: register U_CHAR *obp; ! 8074: register U_CHAR *limit; ! 8075: register int c; ! 8076: ! 8077: ibp = start; ! 8078: limit = start + length; ! 8079: obp = start; ! 8080: ! 8081: while (ibp < limit) { ! 8082: *obp++ = c = *ibp++; ! 8083: switch (c) { ! 8084: case '\n': ! 8085: /* If this is a NEWLINE NEWLINE, then this is a real newline in the ! 8086: string. Skip past the newline and its duplicate. ! 8087: Put a space in the output. */ ! 8088: if (*ibp == '\n') ! 8089: { ! 8090: ibp++; ! 8091: obp--; ! 8092: *obp++ = ' '; ! 8093: } ! 8094: break; ! 8095: ! 8096: case '\'': ! 8097: case '\"': ! 8098: /* Notice and skip strings, so that we don't delete newlines in them. */ ! 8099: { ! 8100: int quotec = c; ! 8101: while (ibp < limit) { ! 8102: *obp++ = c = *ibp++; ! 8103: if (c == quotec) ! 8104: break; ! 8105: if (c == '\n' && quotec == '\'') ! 8106: break; ! 8107: } ! 8108: } ! 8109: break; ! 8110: } ! 8111: } ! 8112: ! 8113: return obp - start; ! 8114: } ! 8115: ! 8116: /* ! 8117: * error - print error message and increment count of errors. ! 8118: */ ! 8119: ! 8120: void ! 8121: error (msg, arg1, arg2, arg3) ! 8122: char *msg; ! 8123: char *arg1, *arg2, *arg3; ! 8124: { ! 8125: int i; ! 8126: FILE_BUF *ip = NULL; ! 8127: ! 8128: print_containing_files (); ! 8129: ! 8130: for (i = indepth; i >= 0; i--) ! 8131: if (instack[i].fname != NULL) { ! 8132: ip = &instack[i]; ! 8133: break; ! 8134: } ! 8135: ! 8136: #ifdef REPORT_EVENT ! 8137: REPORT_EVENT (0, NULL, ! 8138: ip ? ip->nominal_fname : NULL, ! 8139: ip ? ip->lineno : 0, ! 8140: msg, arg1, arg2, arg3); ! 8141: #endif ! 8142: ! 8143: if (ip != NULL) ! 8144: fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno); ! 8145: fprintf (stderr, msg, arg1, arg2, arg3); ! 8146: fprintf (stderr, "\n"); ! 8147: errors++; ! 8148: } ! 8149: ! 8150: /* Error including a message from `errno'. */ ! 8151: ! 8152: static void ! 8153: error_from_errno (name) ! 8154: char *name; ! 8155: { ! 8156: int i; ! 8157: FILE_BUF *ip = NULL; ! 8158: ! 8159: print_containing_files (); ! 8160: ! 8161: for (i = indepth; i >= 0; i--) ! 8162: if (instack[i].fname != NULL) { ! 8163: ip = &instack[i]; ! 8164: break; ! 8165: } ! 8166: ! 8167: #ifdef REPORT_EVENT ! 8168: REPORT_EVENT (0, NULL, ! 8169: ip ? ip->nominal_fname : NULL, ! 8170: ip ? ip->lineno : 0, ! 8171: "%s: %s", name, ! 8172: (errno < sys_nerr) ! 8173: ? sys_errlist[errno] ! 8174: : "undocumented I/O error", ! 8175: 0); ! 8176: #endif ! 8177: ! 8178: if (ip != NULL) ! 8179: fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno); ! 8180: ! 8181: if (errno < sys_nerr) ! 8182: fprintf (stderr, "%s: %s\n", name, sys_errlist[errno]); ! 8183: else ! 8184: fprintf (stderr, "%s: undocumented I/O error\n", name); ! 8185: ! 8186: errors++; ! 8187: } ! 8188: ! 8189: /* Print error message but don't count it. */ ! 8190: ! 8191: void ! 8192: warning (msg, arg1, arg2, arg3) ! 8193: char *msg; ! 8194: char *arg1, *arg2, *arg3; ! 8195: { ! 8196: int i; ! 8197: FILE_BUF *ip = NULL; ! 8198: ! 8199: if (inhibit_warnings) ! 8200: return; ! 8201: ! 8202: if (warnings_are_errors) ! 8203: errors++; ! 8204: ! 8205: print_containing_files (); ! 8206: ! 8207: for (i = indepth; i >= 0; i--) ! 8208: if (instack[i].fname != NULL) { ! 8209: ip = &instack[i]; ! 8210: break; ! 8211: } ! 8212: ! 8213: #ifdef REPORT_EVENT ! 8214: REPORT_EVENT (1, NULL, ! 8215: ip ? ip->nominal_fname : NULL, ! 8216: ip ? ip->lineno : 0, ! 8217: msg, arg1, arg2, arg3); ! 8218: #endif ! 8219: ! 8220: if (ip != NULL) ! 8221: fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno); ! 8222: fprintf (stderr, "warning: "); ! 8223: fprintf (stderr, msg, arg1, arg2, arg3); ! 8224: fprintf (stderr, "\n"); ! 8225: } ! 8226: ! 8227: static void ! 8228: error_with_line (line, msg, arg1, arg2, arg3) ! 8229: int line; ! 8230: char *msg; ! 8231: char *arg1, *arg2, *arg3; ! 8232: { ! 8233: int i; ! 8234: FILE_BUF *ip = NULL; ! 8235: ! 8236: print_containing_files (); ! 8237: ! 8238: for (i = indepth; i >= 0; i--) ! 8239: if (instack[i].fname != NULL) { ! 8240: ip = &instack[i]; ! 8241: break; ! 8242: } ! 8243: ! 8244: #ifdef REPORT_EVENT ! 8245: REPORT_EVENT (0, NULL, ! 8246: ip ? ip->nominal_fname : NULL, ! 8247: line, msg, arg1, arg2, arg3); ! 8248: #endif ! 8249: ! 8250: if (ip != NULL) ! 8251: fprintf (stderr, "%s:%d: ", ip->nominal_fname, line); ! 8252: fprintf (stderr, msg, arg1, arg2, arg3); ! 8253: fprintf (stderr, "\n"); ! 8254: errors++; ! 8255: } ! 8256: ! 8257: static void ! 8258: warning_with_line (line, msg, arg1, arg2, arg3) ! 8259: int line; ! 8260: char *msg; ! 8261: char *arg1, *arg2, *arg3; ! 8262: { ! 8263: int i; ! 8264: FILE_BUF *ip = NULL; ! 8265: ! 8266: if (inhibit_warnings) ! 8267: return; ! 8268: ! 8269: if (warnings_are_errors) ! 8270: errors++; ! 8271: ! 8272: print_containing_files (); ! 8273: ! 8274: for (i = indepth; i >= 0; i--) ! 8275: if (instack[i].fname != NULL) { ! 8276: ip = &instack[i]; ! 8277: break; ! 8278: } ! 8279: ! 8280: #ifdef REPORT_EVENT ! 8281: REPORT_EVENT (0, NULL, ! 8282: ip ? ip->nominal_fname : NULL, ! 8283: line, msg, arg1, arg2, arg3); ! 8284: #endif ! 8285: ! 8286: if (ip != NULL) ! 8287: fprintf (stderr, "%s:%d: ", ip->nominal_fname, line); ! 8288: fprintf (stderr, "warning: "); ! 8289: fprintf (stderr, msg, arg1, arg2, arg3); ! 8290: fprintf (stderr, "\n"); ! 8291: } ! 8292: ! 8293: /* print an error message and maybe count it. */ ! 8294: ! 8295: void ! 8296: pedwarn (msg, arg1, arg2, arg3) ! 8297: char *msg; ! 8298: char *arg1, *arg2, *arg3; ! 8299: { ! 8300: if (pedantic_errors) ! 8301: error (msg, arg1, arg2, arg3); ! 8302: else ! 8303: warning (msg, arg1, arg2, arg3); ! 8304: } ! 8305: ! 8306: void ! 8307: pedwarn_with_line (line, msg, arg1, arg2, arg3) ! 8308: int line; ! 8309: char *msg; ! 8310: char *arg1, *arg2, *arg3; ! 8311: { ! 8312: if (pedantic_errors) ! 8313: error_with_line (line, msg, arg1, arg2, arg3); ! 8314: else ! 8315: warning_with_line (line, msg, arg1, arg2, arg3); ! 8316: } ! 8317: ! 8318: /* Report a warning (or an error if pedantic_errors) ! 8319: giving specified file name and line number, not current. */ ! 8320: ! 8321: static void ! 8322: pedwarn_with_file_and_line (file, line, msg, arg1, arg2, arg3) ! 8323: char *file; ! 8324: int line; ! 8325: char *msg; ! 8326: char *arg1, *arg2, *arg3; ! 8327: { ! 8328: int i; ! 8329: #ifdef REPORT_EVENT ! 8330: REPORT_EVENT (pedantic_errors ? 0 : 1, ! 8331: NULL, file, line, msg, arg1, arg2, arg3); ! 8332: #endif ! 8333: if (!pedantic_errors && inhibit_warnings) ! 8334: return; ! 8335: if (file != NULL) ! 8336: fprintf (stderr, "%s:%d: ", file, line); ! 8337: if (pedantic_errors) ! 8338: errors++; ! 8339: if (!pedantic_errors) ! 8340: fprintf (stderr, "warning: "); ! 8341: fprintf (stderr, msg, arg1, arg2, arg3); ! 8342: fprintf (stderr, "\n"); ! 8343: } ! 8344: ! 8345: /* Print the file names and line numbers of the #include ! 8346: commands which led to the current file. */ ! 8347: ! 8348: static void ! 8349: print_containing_files () ! 8350: { ! 8351: FILE_BUF *ip = NULL; ! 8352: int i; ! 8353: int first = 1; ! 8354: ! 8355: /* If stack of files hasn't changed since we last printed ! 8356: this info, don't repeat it. */ ! 8357: if (last_error_tick == input_file_stack_tick) ! 8358: return; ! 8359: ! 8360: for (i = indepth; i >= 0; i--) ! 8361: if (instack[i].fname != NULL) { ! 8362: ip = &instack[i]; ! 8363: break; ! 8364: } ! 8365: ! 8366: /* Give up if we don't find a source file. */ ! 8367: if (ip == NULL) ! 8368: return; ! 8369: ! 8370: /* Find the other, outer source files. */ ! 8371: for (i--; i >= 0; i--) ! 8372: if (instack[i].fname != NULL) { ! 8373: ip = &instack[i]; ! 8374: if (first) { ! 8375: first = 0; ! 8376: fprintf (stderr, "In file included"); ! 8377: } else { ! 8378: fprintf (stderr, ",\n "); ! 8379: } ! 8380: ! 8381: fprintf (stderr, " from %s:%d", ip->nominal_fname, ip->lineno); ! 8382: } ! 8383: if (! first) ! 8384: fprintf (stderr, ":\n"); ! 8385: ! 8386: /* Record we have printed the status as of this time. */ ! 8387: last_error_tick = input_file_stack_tick; ! 8388: } ! 8389: ! 8390: /* Return the line at which an error occurred. ! 8391: The error is not necessarily associated with the current spot ! 8392: in the input stack, so LINE says where. LINE will have been ! 8393: copied from ip->lineno for the current input level. ! 8394: If the current level is for a file, we return LINE. ! 8395: But if the current level is not for a file, LINE is meaningless. ! 8396: In that case, we return the lineno of the innermost file. */ ! 8397: ! 8398: static int ! 8399: line_for_error (line) ! 8400: int line; ! 8401: { ! 8402: int i; ! 8403: int line1 = line; ! 8404: ! 8405: for (i = indepth; i >= 0; ) { ! 8406: if (instack[i].fname != 0) ! 8407: return line1; ! 8408: i--; ! 8409: if (i < 0) ! 8410: return 0; ! 8411: line1 = instack[i].lineno; ! 8412: } ! 8413: abort (); ! 8414: /*NOTREACHED*/ ! 8415: return 0; ! 8416: } ! 8417: ! 8418: /* ! 8419: * If OBUF doesn't have NEEDED bytes after OPTR, make it bigger. ! 8420: * ! 8421: * As things stand, nothing is ever placed in the output buffer to be ! 8422: * removed again except when it's KNOWN to be part of an identifier, ! 8423: * so flushing and moving down everything left, instead of expanding, ! 8424: * should work ok. ! 8425: */ ! 8426: ! 8427: /* You might think void was cleaner for the return type, ! 8428: but that would get type mismatch in check_expand in strict ANSI. */ ! 8429: static int ! 8430: grow_outbuf (obuf, needed) ! 8431: register FILE_BUF *obuf; ! 8432: register int needed; ! 8433: { ! 8434: register U_CHAR *p; ! 8435: int minsize; ! 8436: ! 8437: if (obuf->length - (obuf->bufp - obuf->buf) > needed) ! 8438: return 0; ! 8439: ! 8440: /* Make it at least twice as big as it is now. */ ! 8441: obuf->length *= 2; ! 8442: /* Make it have at least 150% of the free space we will need. */ ! 8443: minsize = (3 * needed) / 2 + (obuf->bufp - obuf->buf); ! 8444: if (minsize > obuf->length) ! 8445: obuf->length = minsize; ! 8446: ! 8447: if ((p = (U_CHAR *) xrealloc (obuf->buf, obuf->length)) == NULL) ! 8448: memory_full (); ! 8449: ! 8450: obuf->bufp = p + (obuf->bufp - obuf->buf); ! 8451: obuf->buf = p; ! 8452: ! 8453: return 0; ! 8454: } ! 8455: ! 8456: /* Symbol table for macro names and special symbols */ ! 8457: ! 8458: /* ! 8459: * install a name in the main hash table, even if it is already there. ! 8460: * name stops with first non alphanumeric, except leading '#'. ! 8461: * caller must check against redefinition if that is desired. ! 8462: * delete_macro () removes things installed by install () in fifo order. ! 8463: * this is important because of the `defined' special symbol used ! 8464: * in #if, and also if pushdef/popdef directives are ever implemented. ! 8465: * ! 8466: * If LEN is >= 0, it is the length of the name. ! 8467: * Otherwise, compute the length by scanning the entire name. ! 8468: * ! 8469: * If HASH is >= 0, it is the precomputed hash code. ! 8470: * Otherwise, compute the hash code. ! 8471: */ ! 8472: static HASHNODE * ! 8473: install (name, len, type, ivalue, value, hash) ! 8474: U_CHAR *name; ! 8475: int len; ! 8476: enum node_type type; ! 8477: int ivalue; ! 8478: char *value; ! 8479: int hash; ! 8480: { ! 8481: register HASHNODE *hp; ! 8482: register int i, bucket; ! 8483: register U_CHAR *p, *q; ! 8484: ! 8485: if (len < 0) { ! 8486: p = name; ! 8487: while (is_idchar[*p]) ! 8488: p++; ! 8489: len = p - name; ! 8490: } ! 8491: ! 8492: if (hash < 0) ! 8493: hash = hashf (name, len, HASHSIZE); ! 8494: ! 8495: i = sizeof (HASHNODE) + len + 1; ! 8496: hp = (HASHNODE *) xmalloc (i); ! 8497: bucket = hash; ! 8498: hp->bucket_hdr = &hashtab[bucket]; ! 8499: hp->next = hashtab[bucket]; ! 8500: hashtab[bucket] = hp; ! 8501: hp->prev = NULL; ! 8502: if (hp->next != NULL) ! 8503: hp->next->prev = hp; ! 8504: hp->type = type; ! 8505: hp->length = len; ! 8506: if (hp->type == T_CONST) ! 8507: hp->value.ival = ivalue; ! 8508: else ! 8509: hp->value.cpval = value; ! 8510: hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE); ! 8511: p = hp->name; ! 8512: q = name; ! 8513: for (i = 0; i < len; i++) ! 8514: *p++ = *q++; ! 8515: hp->name[len] = 0; ! 8516: return hp; ! 8517: } ! 8518: ! 8519: /* ! 8520: * find the most recent hash node for name name (ending with first ! 8521: * non-identifier char) installed by install ! 8522: * ! 8523: * If LEN is >= 0, it is the length of the name. ! 8524: * Otherwise, compute the length by scanning the entire name. ! 8525: * ! 8526: * If HASH is >= 0, it is the precomputed hash code. ! 8527: * Otherwise, compute the hash code. ! 8528: */ ! 8529: HASHNODE * ! 8530: lookup (name, len, hash) ! 8531: U_CHAR *name; ! 8532: int len; ! 8533: int hash; ! 8534: { ! 8535: register U_CHAR *bp; ! 8536: register HASHNODE *bucket; ! 8537: ! 8538: if (len < 0) { ! 8539: for (bp = name; is_idchar[*bp]; bp++) ; ! 8540: len = bp - name; ! 8541: } ! 8542: ! 8543: if (hash < 0) ! 8544: hash = hashf (name, len, HASHSIZE); ! 8545: ! 8546: bucket = hashtab[hash]; ! 8547: while (bucket) { ! 8548: if (bucket->length == len && strncmp (bucket->name, name, len) == 0) ! 8549: return bucket; ! 8550: bucket = bucket->next; ! 8551: } ! 8552: return NULL; ! 8553: } ! 8554: ! 8555: /* ! 8556: * Delete a hash node. Some weirdness to free junk from macros. ! 8557: * More such weirdness will have to be added if you define more hash ! 8558: * types that need it. ! 8559: */ ! 8560: ! 8561: /* Note that the DEFINITION of a macro is removed from the hash table ! 8562: but its storage is not freed. This would be a storage leak ! 8563: except that it is not reasonable to keep undefining and redefining ! 8564: large numbers of macros many times. ! 8565: In any case, this is necessary, because a macro can be #undef'd ! 8566: in the middle of reading the arguments to a call to it. ! 8567: If #undef freed the DEFINITION, that would crash. */ ! 8568: ! 8569: static void ! 8570: delete_macro (hp) ! 8571: HASHNODE *hp; ! 8572: { ! 8573: ! 8574: if (hp->prev != NULL) ! 8575: hp->prev->next = hp->next; ! 8576: if (hp->next != NULL) ! 8577: hp->next->prev = hp->prev; ! 8578: ! 8579: /* make sure that the bucket chain header that ! 8580: the deleted guy was on points to the right thing afterwards. */ ! 8581: if (hp == *hp->bucket_hdr) ! 8582: *hp->bucket_hdr = hp->next; ! 8583: ! 8584: #if 0 ! 8585: if (hp->type == T_MACRO) { ! 8586: DEFINITION *d = hp->value.defn; ! 8587: struct reflist *ap, *nextap; ! 8588: ! 8589: for (ap = d->pattern; ap != NULL; ap = nextap) { ! 8590: nextap = ap->next; ! 8591: free (ap); ! 8592: } ! 8593: free (d); ! 8594: } ! 8595: #endif ! 8596: free (hp); ! 8597: } ! 8598: ! 8599: /* ! 8600: * return hash function on name. must be compatible with the one ! 8601: * computed a step at a time, elsewhere ! 8602: */ ! 8603: static int ! 8604: hashf (name, len, hashsize) ! 8605: register U_CHAR *name; ! 8606: register int len; ! 8607: int hashsize; ! 8608: { ! 8609: register int r = 0; ! 8610: ! 8611: while (len--) ! 8612: r = HASHSTEP (r, *name++); ! 8613: ! 8614: return MAKE_POS (r) % hashsize; ! 8615: } ! 8616: ! 8617: ! 8618: /* Dump the definition of a single macro HP to OF. */ ! 8619: static void ! 8620: dump_single_macro (hp, of) ! 8621: register HASHNODE *hp; ! 8622: FILE *of; ! 8623: { ! 8624: register DEFINITION *defn = hp->value.defn; ! 8625: struct reflist *ap; ! 8626: int offset; ! 8627: int concat; ! 8628: ! 8629: ! 8630: /* Print the definition of the macro HP. */ ! 8631: ! 8632: fprintf (of, "#define %s", hp->name); ! 8633: ! 8634: if (defn->nargs >= 0) { ! 8635: int i; ! 8636: ! 8637: fprintf (of, "("); ! 8638: for (i = 0; i < defn->nargs; i++) { ! 8639: dump_arg_n (defn, i, of); ! 8640: if (i + 1 < defn->nargs) ! 8641: fprintf (of, ", "); ! 8642: } ! 8643: fprintf (of, ")"); ! 8644: } ! 8645: ! 8646: fprintf (of, " "); ! 8647: ! 8648: offset = 0; ! 8649: concat = 0; ! 8650: for (ap = defn->pattern; ap != NULL; ap = ap->next) { ! 8651: dump_defn_1 (defn->expansion, offset, ap->nchars, of); ! 8652: if (ap->nchars != 0) ! 8653: concat = 0; ! 8654: offset += ap->nchars; ! 8655: if (ap->stringify) ! 8656: fprintf (of, " #"); ! 8657: if (ap->raw_before && !concat) ! 8658: fprintf (of, " ## "); ! 8659: concat = 0; ! 8660: dump_arg_n (defn, ap->argno, of); ! 8661: if (ap->raw_after) { ! 8662: fprintf (of, " ## "); ! 8663: concat = 1; ! 8664: } ! 8665: } ! 8666: dump_defn_1 (defn->expansion, offset, defn->length - offset, of); ! 8667: fprintf (of, "\n"); ! 8668: } ! 8669: ! 8670: /* Dump all macro definitions as #defines to stdout. */ ! 8671: ! 8672: static void ! 8673: dump_all_macros () ! 8674: { ! 8675: int bucket; ! 8676: ! 8677: for (bucket = 0; bucket < HASHSIZE; bucket++) { ! 8678: register HASHNODE *hp; ! 8679: ! 8680: for (hp = hashtab[bucket]; hp; hp= hp->next) { ! 8681: if (hp->type == T_MACRO) ! 8682: dump_single_macro (hp, stdout); ! 8683: } ! 8684: } ! 8685: } ! 8686: ! 8687: /* Output to OF a substring of a macro definition. ! 8688: BASE is the beginning of the definition. ! 8689: Output characters START thru LENGTH. ! 8690: Discard newlines outside of strings, thus ! 8691: converting funny-space markers to ordinary spaces. */ ! 8692: ! 8693: static void ! 8694: dump_defn_1 (base, start, length, of) ! 8695: U_CHAR *base; ! 8696: int start; ! 8697: int length; ! 8698: FILE *of; ! 8699: { ! 8700: U_CHAR *p = base + start; ! 8701: U_CHAR *limit = base + start + length; ! 8702: ! 8703: while (p < limit) { ! 8704: if (*p != '\n') ! 8705: putc (*p, of); ! 8706: else if (*p == '\"' || *p =='\'') { ! 8707: U_CHAR *p1 = skip_quoted_string (p, limit, 0, NULL_PTR, ! 8708: NULL_PTR, NULL_PTR); ! 8709: fwrite (p, p1 - p, 1, of); ! 8710: p = p1 - 1; ! 8711: } ! 8712: p++; ! 8713: } ! 8714: } ! 8715: ! 8716: /* Print the name of argument number ARGNUM of macro definition DEFN ! 8717: to OF. ! 8718: Recall that DEFN->args.argnames contains all the arg names ! 8719: concatenated in reverse order with comma-space in between. */ ! 8720: ! 8721: static void ! 8722: dump_arg_n (defn, argnum, of) ! 8723: DEFINITION *defn; ! 8724: int argnum; ! 8725: FILE *of; ! 8726: { ! 8727: register U_CHAR *p = defn->args.argnames; ! 8728: while (argnum + 1 < defn->nargs) { ! 8729: p = (U_CHAR *) index (p, ' ') + 1; ! 8730: argnum++; ! 8731: } ! 8732: ! 8733: while (*p && *p != ',') { ! 8734: putc (*p, of); ! 8735: p++; ! 8736: } ! 8737: } ! 8738: ! 8739: /* Initialize syntactic classifications of characters. */ ! 8740: ! 8741: static void ! 8742: initialize_char_syntax () ! 8743: { ! 8744: register int i; ! 8745: ! 8746: /* ! 8747: * Set up is_idchar and is_idstart tables. These should be ! 8748: * faster than saying (is_alpha (c) || c == '_'), etc. ! 8749: * Set up these things before calling any routines tthat ! 8750: * refer to them. ! 8751: */ ! 8752: for (i = 'a'; i <= 'z'; i++) { ! 8753: is_idchar[i - 'a' + 'A'] = 1; ! 8754: is_idchar[i] = 1; ! 8755: is_idstart[i - 'a' + 'A'] = 1; ! 8756: is_idstart[i] = 1; ! 8757: } ! 8758: for (i = '0'; i <= '9'; i++) ! 8759: is_idchar[i] = 1; ! 8760: is_idchar['_'] = 1; ! 8761: is_idstart['_'] = 1; ! 8762: is_idchar['$'] = dollars_in_ident; ! 8763: is_idstart['$'] = dollars_in_ident; ! 8764: ! 8765: /* horizontal space table */ ! 8766: is_hor_space[' '] = 1; ! 8767: is_hor_space['\t'] = 1; ! 8768: is_hor_space['\v'] = 1; ! 8769: is_hor_space['\f'] = 1; ! 8770: is_hor_space['\r'] = 1; ! 8771: ! 8772: is_space[' '] = 1; ! 8773: is_space['\t'] = 1; ! 8774: is_space['\v'] = 1; ! 8775: is_space['\f'] = 1; ! 8776: is_space['\n'] = 1; ! 8777: is_space['\r'] = 1; ! 8778: } ! 8779: ! 8780: /* Initialize the built-in macros. */ ! 8781: ! 8782: static void ! 8783: initialize_builtins (inp, outp) ! 8784: FILE_BUF *inp; ! 8785: FILE_BUF *outp; ! 8786: { ! 8787: install ("__LINE__", -1, T_SPECLINE, 0, 0, -1); ! 8788: install ("__DATE__", -1, T_DATE, 0, 0, -1); ! 8789: install ("__FILE__", -1, T_FILE, 0, 0, -1); ! 8790: install ("__BASE_FILE__", -1, T_BASE_FILE, 0, 0, -1); ! 8791: install ("__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, 0, -1); ! 8792: install ("__VERSION__", -1, T_VERSION, 0, 0, -1); ! 8793: #ifndef NO_BUILTIN_SIZE_TYPE ! 8794: install ("__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, 0, -1); ! 8795: #endif ! 8796: #ifndef NO_BUILTIN_PTRDIFF_TYPE ! 8797: install ("__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, 0, -1); ! 8798: #endif ! 8799: install ("__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, 0, -1); ! 8800: install ("__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE, 0, 0, -1); ! 8801: install ("__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, 0, 0, -1); ! 8802: install ("__TIME__", -1, T_TIME, 0, 0, -1); ! 8803: if (!traditional) ! 8804: install ("__STDC__", -1, T_CONST, STDC_VALUE, 0, -1); ! 8805: if (objc) ! 8806: install ("__OBJC__", -1, T_CONST, 1, 0, -1); ! 8807: /* This is supplied using a -D by the compiler driver ! 8808: so that it is present only when truly compiling with GNU C. */ ! 8809: /* install ("__GNUC__", -1, T_CONST, 2, 0, -1); */ ! 8810: ! 8811: if (debug_output) ! 8812: { ! 8813: char directive[2048]; ! 8814: register struct directive *dp = &directive_table[0]; ! 8815: struct tm *timebuf = timestamp (); ! 8816: ! 8817: sprintf (directive, " __BASE_FILE__ \"%s\"\n", ! 8818: instack[0].nominal_fname); ! 8819: output_line_command (inp, outp, 0, same_file); ! 8820: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp); ! 8821: ! 8822: sprintf (directive, " __VERSION__ \"%s\"\n", version_string); ! 8823: output_line_command (inp, outp, 0, same_file); ! 8824: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp); ! 8825: ! 8826: #ifndef NO_BUILTIN_SIZE_TYPE ! 8827: sprintf (directive, " __SIZE_TYPE__ %s\n", SIZE_TYPE); ! 8828: output_line_command (inp, outp, 0, same_file); ! 8829: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp); ! 8830: #endif ! 8831: ! 8832: #ifndef NO_BUILTIN_PTRDIFF_TYPE ! 8833: sprintf (directive, " __PTRDIFF_TYPE__ %s\n", PTRDIFF_TYPE); ! 8834: output_line_command (inp, outp, 0, same_file); ! 8835: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp); ! 8836: #endif ! 8837: ! 8838: sprintf (directive, " __WCHAR_TYPE__ %s\n", WCHAR_TYPE); ! 8839: output_line_command (inp, outp, 0, same_file); ! 8840: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp); ! 8841: ! 8842: sprintf (directive, " __DATE__ \"%s %2d %4d\"\n", ! 8843: monthnames[timebuf->tm_mon], ! 8844: timebuf->tm_mday, timebuf->tm_year + 1900); ! 8845: output_line_command (inp, outp, 0, same_file); ! 8846: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp); ! 8847: ! 8848: sprintf (directive, " __TIME__ \"%02d:%02d:%02d\"\n", ! 8849: timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec); ! 8850: output_line_command (inp, outp, 0, same_file); ! 8851: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp); ! 8852: ! 8853: if (!traditional) ! 8854: { ! 8855: sprintf (directive, " __STDC__ 1"); ! 8856: output_line_command (inp, outp, 0, same_file); ! 8857: pass_thru_directive (directive, &directive[strlen (directive)], ! 8858: outp, dp); ! 8859: } ! 8860: if (objc) ! 8861: { ! 8862: sprintf (directive, " __OBJC__ 1"); ! 8863: output_line_command (inp, outp, 0, same_file); ! 8864: pass_thru_directive (directive, &directive[strlen (directive)], ! 8865: outp, dp); ! 8866: } ! 8867: } ! 8868: } ! 8869: ! 8870: /* ! 8871: * process a given definition string, for initialization ! 8872: * If STR is just an identifier, define it with value 1. ! 8873: * If STR has anything after the identifier, then it should ! 8874: * be identifier=definition. ! 8875: */ ! 8876: ! 8877: static void ! 8878: make_definition (str, op) ! 8879: U_CHAR *str; ! 8880: FILE_BUF *op; ! 8881: { ! 8882: FILE_BUF *ip; ! 8883: struct directive *kt; ! 8884: U_CHAR *buf, *p; ! 8885: ! 8886: buf = str; ! 8887: p = str; ! 8888: if (!is_idstart[*p]) { ! 8889: error ("malformed option `-D %s'", str); ! 8890: return; ! 8891: } ! 8892: while (is_idchar[*++p]) ! 8893: ; ! 8894: if (*p == 0) { ! 8895: buf = (U_CHAR *) alloca (p - buf + 4); ! 8896: strcpy ((char *)buf, str); ! 8897: strcat ((char *)buf, " 1"); ! 8898: } else if (*p != '=') { ! 8899: error ("malformed option `-D %s'", str); ! 8900: return; ! 8901: } else { ! 8902: U_CHAR *q; ! 8903: /* Copy the entire option so we can modify it. */ ! 8904: buf = (U_CHAR *) alloca (2 * strlen (str) + 1); ! 8905: strncpy (buf, str, p - str); ! 8906: /* Change the = to a space. */ ! 8907: buf[p - str] = ' '; ! 8908: /* Scan for any backslash-newline and remove it. */ ! 8909: p++; ! 8910: q = &buf[p - str]; ! 8911: while (*p) { ! 8912: if (*p == '\\' && p[1] == '\n') ! 8913: p += 2; ! 8914: /* Change newline chars into newline-markers. */ ! 8915: else if (*p == '\n') ! 8916: { ! 8917: *q++ = '\n'; ! 8918: *q++ = '\n'; ! 8919: p++; ! 8920: } ! 8921: else ! 8922: *q++ = *p++; ! 8923: } ! 8924: *q = 0; ! 8925: } ! 8926: ! 8927: ip = &instack[++indepth]; ! 8928: ip->nominal_fname = ip->fname = "*Initialization*"; ! 8929: ! 8930: ip->buf = ip->bufp = buf; ! 8931: ip->length = strlen (buf); ! 8932: ip->lineno = 1; ! 8933: ip->macro = 0; ! 8934: ip->free_ptr = 0; ! 8935: ip->if_stack = if_stack; ! 8936: ip->system_header_p = 0; ! 8937: ! 8938: for (kt = directive_table; kt->type != T_DEFINE; kt++) ! 8939: ; ! 8940: ! 8941: /* Pass NULL instead of OP, since this is a "predefined" macro. */ ! 8942: do_define (buf, buf + strlen (buf), NULL, kt); ! 8943: --indepth; ! 8944: } ! 8945: ! 8946: /* JF, this does the work for the -U option */ ! 8947: ! 8948: static void ! 8949: make_undef (str, op) ! 8950: U_CHAR *str; ! 8951: FILE_BUF *op; ! 8952: { ! 8953: FILE_BUF *ip; ! 8954: struct directive *kt; ! 8955: ! 8956: ip = &instack[++indepth]; ! 8957: ip->nominal_fname = ip->fname = "*undef*"; ! 8958: ! 8959: ip->buf = ip->bufp = str; ! 8960: ip->length = strlen (str); ! 8961: ip->lineno = 1; ! 8962: ip->macro = 0; ! 8963: ip->free_ptr = 0; ! 8964: ip->if_stack = if_stack; ! 8965: ip->system_header_p = 0; ! 8966: ! 8967: for (kt = directive_table; kt->type != T_UNDEF; kt++) ! 8968: ; ! 8969: ! 8970: do_undef (str, str + strlen (str), op, kt); ! 8971: --indepth; ! 8972: } ! 8973: ! 8974: /* Process the string STR as if it appeared as the body of a #assert. ! 8975: OPTION is the option name for which STR was the argument. */ ! 8976: ! 8977: static void ! 8978: make_assertion (option, str) ! 8979: char *option; ! 8980: U_CHAR *str; ! 8981: { ! 8982: FILE_BUF *ip; ! 8983: struct directive *kt; ! 8984: U_CHAR *buf, *p, *q; ! 8985: ! 8986: /* Copy the entire option so we can modify it. */ ! 8987: buf = (U_CHAR *) alloca (strlen (str) + 1); ! 8988: strcpy ((char *) buf, str); ! 8989: /* Scan for any backslash-newline and remove it. */ ! 8990: p = q = buf; ! 8991: while (*p) { ! 8992: if (*p == '\\' && p[1] == '\n') ! 8993: p += 2; ! 8994: else ! 8995: *q++ = *p++; ! 8996: } ! 8997: *q = 0; ! 8998: ! 8999: p = buf; ! 9000: if (!is_idstart[*p]) { ! 9001: error ("malformed option `%s %s'", option, str); ! 9002: return; ! 9003: } ! 9004: while (is_idchar[*++p]) ! 9005: ; ! 9006: while (*p == ' ' || *p == '\t') p++; ! 9007: if (! (*p == 0 || *p == '(')) { ! 9008: error ("malformed option `%s %s'", option, str); ! 9009: return; ! 9010: } ! 9011: ! 9012: ip = &instack[++indepth]; ! 9013: ip->nominal_fname = ip->fname = "*Initialization*"; ! 9014: ! 9015: ip->buf = ip->bufp = buf; ! 9016: ip->length = strlen (buf); ! 9017: ip->lineno = 1; ! 9018: ip->macro = 0; ! 9019: ip->free_ptr = 0; ! 9020: ip->if_stack = if_stack; ! 9021: ip->system_header_p = 0; ! 9022: ! 9023: for (kt = directive_table; kt->type != T_ASSERT; kt++) ! 9024: ; ! 9025: ! 9026: /* pass NULL as output ptr to do_define since we KNOW it never ! 9027: does any output.... */ ! 9028: do_assert (buf, buf + strlen (buf) , NULL_PTR, kt); ! 9029: --indepth; ! 9030: } ! 9031: ! 9032: /* Append a chain of `struct file_name_list's ! 9033: to the end of the main include chain. ! 9034: FIRST is the beginning of the chain to append, and LAST is the end. */ ! 9035: ! 9036: static void ! 9037: append_include_chain (first, last) ! 9038: struct file_name_list *first, *last; ! 9039: { ! 9040: struct file_name_list *dir; ! 9041: ! 9042: if (!first || !last) ! 9043: return; ! 9044: ! 9045: if (include == 0) ! 9046: include = first; ! 9047: else ! 9048: last_include->next = first; ! 9049: ! 9050: if (first_bracket_include == 0) ! 9051: first_bracket_include = first; ! 9052: ! 9053: for (dir = first; ; dir = dir->next) { ! 9054: int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE; ! 9055: if (len > max_include_len) ! 9056: max_include_len = len; ! 9057: if (dir == last) ! 9058: break; ! 9059: } ! 9060: ! 9061: last->next = NULL; ! 9062: last_include = last; ! 9063: } ! 9064: ! 9065: /* Add output to `deps_buffer' for the -M switch. ! 9066: STRING points to the text to be output. ! 9067: SIZE is the number of bytes, or 0 meaning output until a null. ! 9068: Outputting the empty string breaks the line if it is long enough. */ ! 9069: ! 9070: static void ! 9071: deps_output (string, size) ! 9072: char *string; ! 9073: unsigned size; ! 9074: { ! 9075: if (size == 0) ! 9076: size = strlen (string); ! 9077: ! 9078: #ifndef MAX_OUTPUT_COLUMNS ! 9079: #define MAX_OUTPUT_COLUMNS 75 ! 9080: #endif ! 9081: if (size == 0 && deps_column != 0 ! 9082: && size + deps_column > MAX_OUTPUT_COLUMNS) { ! 9083: deps_output ("\\\n ", 0); ! 9084: deps_column = 0; ! 9085: } ! 9086: ! 9087: if (deps_size + size + 1 > deps_allocated_size) { ! 9088: deps_allocated_size = deps_size + size + 50; ! 9089: deps_allocated_size *= 2; ! 9090: deps_buffer = (char *) xrealloc (deps_buffer, deps_allocated_size); ! 9091: } ! 9092: bcopy (string, &deps_buffer[deps_size], size); ! 9093: deps_size += size; ! 9094: deps_column += size; ! 9095: deps_buffer[deps_size] = 0; ! 9096: } ! 9097: ! 9098: #if defined(USG) || defined(VMS) ! 9099: #ifndef BSTRING ! 9100: ! 9101: void ! 9102: bzero (b, length) ! 9103: register char *b; ! 9104: register unsigned length; ! 9105: { ! 9106: while (length-- > 0) ! 9107: *b++ = 0; ! 9108: } ! 9109: ! 9110: void ! 9111: bcopy (b1, b2, length) ! 9112: register char *b1; ! 9113: register char *b2; ! 9114: register unsigned length; ! 9115: { ! 9116: while (length-- > 0) ! 9117: *b2++ = *b1++; ! 9118: } ! 9119: ! 9120: int ! 9121: bcmp (b1, b2, length) /* This could be a macro! */ ! 9122: register char *b1; ! 9123: register char *b2; ! 9124: register unsigned length; ! 9125: { ! 9126: while (length-- > 0) ! 9127: if (*b1++ != *b2++) ! 9128: return 1; ! 9129: ! 9130: return 0; ! 9131: } ! 9132: #endif /* not BSTRING */ ! 9133: #endif /* USG or VMS */ ! 9134: ! 9135: ! 9136: static void ! 9137: fatal (str, arg) ! 9138: char *str, *arg; ! 9139: { ! 9140: #ifdef REPORT_EVENT ! 9141: REPORT_EVENT (0, progname, NULL, 0, str, arg, 0, 0); ! 9142: #endif ! 9143: fprintf (stderr, "%s: ", progname); ! 9144: fprintf (stderr, str, arg); ! 9145: fprintf (stderr, "\n"); ! 9146: exit (FAILURE_EXIT_CODE); ! 9147: } ! 9148: ! 9149: /* More 'friendly' abort that prints the line and file. ! 9150: config.h can #define abort fancy_abort if you like that sort of thing. */ ! 9151: ! 9152: void ! 9153: fancy_abort () ! 9154: { ! 9155: fatal ("Internal gcc abort."); ! 9156: } ! 9157: ! 9158: static void ! 9159: perror_with_name (name) ! 9160: char *name; ! 9161: { ! 9162: #ifdef REPORT_EVENT ! 9163: REPORT_EVENT (0, progname, NULL, 0, ! 9164: "%s: %s", name, ! 9165: (errno < sys_nerr) ! 9166: ? sys_errlist[errno] ! 9167: : "undocumented I/O error", ! 9168: 0); ! 9169: #endif ! 9170: fprintf (stderr, "%s: ", progname); ! 9171: if (errno < sys_nerr) ! 9172: fprintf (stderr, "%s: %s\n", name, sys_errlist[errno]); ! 9173: else ! 9174: fprintf (stderr, "%s: undocumented I/O error\n", name); ! 9175: errors++; ! 9176: } ! 9177: ! 9178: static void ! 9179: pfatal_with_name (name) ! 9180: char *name; ! 9181: { ! 9182: perror_with_name (name); ! 9183: #ifdef VMS ! 9184: exit (vaxc$errno); ! 9185: #else ! 9186: exit (FAILURE_EXIT_CODE); ! 9187: #endif ! 9188: } ! 9189: ! 9190: /* Handler for SIGPIPE. */ ! 9191: ! 9192: static void ! 9193: pipe_closed (signo) ! 9194: /* If this is missing, some compilers complain. */ ! 9195: int signo; ! 9196: { ! 9197: fatal ("output pipe has been closed"); ! 9198: } ! 9199: ! 9200: static void ! 9201: memory_full () ! 9202: { ! 9203: fatal ("Memory exhausted."); ! 9204: } ! 9205: ! 9206: ! 9207: char * ! 9208: xmalloc (size) ! 9209: unsigned size; ! 9210: { ! 9211: register char *ptr = (char *) malloc (size); ! 9212: if (ptr != 0) return (ptr); ! 9213: memory_full (); ! 9214: /*NOTREACHED*/ ! 9215: return 0; ! 9216: } ! 9217: ! 9218: static char * ! 9219: xrealloc (old, size) ! 9220: char *old; ! 9221: unsigned size; ! 9222: { ! 9223: register char *ptr = (char *) realloc (old, size); ! 9224: if (ptr != 0) return (ptr); ! 9225: memory_full (); ! 9226: /*NOTREACHED*/ ! 9227: return 0; ! 9228: } ! 9229: ! 9230: static char * ! 9231: xcalloc (number, size) ! 9232: unsigned number, size; ! 9233: { ! 9234: register unsigned total = number * size; ! 9235: register char *ptr = (char *) malloc (total); ! 9236: if (ptr != 0) { ! 9237: if (total > 100) ! 9238: bzero (ptr, total); ! 9239: else { ! 9240: /* It's not too long, so loop, zeroing by longs. ! 9241: It must be safe because malloc values are always well aligned. */ ! 9242: register long *zp = (long *) ptr; ! 9243: register long *zl = (long *) (ptr + total - 4); ! 9244: register int i = total - 4; ! 9245: while (zp < zl) ! 9246: *zp++ = 0; ! 9247: if (i < 0) ! 9248: i = 0; ! 9249: while (i < total) ! 9250: ptr[i++] = 0; ! 9251: } ! 9252: return ptr; ! 9253: } ! 9254: memory_full (); ! 9255: /*NOTREACHED*/ ! 9256: return 0; ! 9257: } ! 9258: ! 9259: static char * ! 9260: savestring (input) ! 9261: char *input; ! 9262: { ! 9263: unsigned size = strlen (input); ! 9264: char *output = xmalloc (size + 1); ! 9265: strcpy (output, input); ! 9266: return output; ! 9267: } ! 9268: ! 9269: /* Get the file-mode and data size of the file open on FD ! 9270: and store them in *MODE_POINTER and *SIZE_POINTER. */ ! 9271: ! 9272: static int ! 9273: file_size_and_mode (fd, mode_pointer, size_pointer) ! 9274: int fd; ! 9275: int *mode_pointer; ! 9276: long int *size_pointer; ! 9277: { ! 9278: struct stat sbuf; ! 9279: ! 9280: if (fstat (fd, &sbuf) < 0) return (-1); ! 9281: if (mode_pointer) *mode_pointer = sbuf.st_mode; ! 9282: if (size_pointer) *size_pointer = sbuf.st_size; ! 9283: return 0; ! 9284: } ! 9285: ! 9286: static void ! 9287: output_dots (fd, depth) ! 9288: FILE* fd; ! 9289: int depth; ! 9290: { ! 9291: while (depth > 0) { ! 9292: putc ('.', fd); ! 9293: depth--; ! 9294: } ! 9295: } ! 9296: ! 9297: ! 9298: #ifdef VMS ! 9299: ! 9300: /* Under VMS we need to fix up the "include" specification ! 9301: filename so that everything following the 1st slash is ! 9302: changed into its correct VMS file specification. */ ! 9303: ! 9304: static void ! 9305: hack_vms_include_specification (fname) ! 9306: char *fname; ! 9307: { ! 9308: register char *cp, *cp1, *cp2; ! 9309: int f, check_filename_before_returning, no_prefix_seen; ! 9310: char Local[512]; ! 9311: ! 9312: check_filename_before_returning = 0; ! 9313: no_prefix_seen = 0; ! 9314: ! 9315: /* Ignore leading "./"s */ ! 9316: while (fname[0] == '.' && fname[1] == '/') { ! 9317: strcpy (fname, fname+2); ! 9318: no_prefix_seen = 1; /* mark this for later */ ! 9319: } ! 9320: /* Look for the boundary between the VMS and UNIX filespecs */ ! 9321: cp = rindex (fname, ']'); /* Look for end of dirspec. */ ! 9322: if (cp == 0) cp = rindex (fname, '>'); /* ... Ditto */ ! 9323: if (cp == 0) cp = rindex (fname, ':'); /* Look for end of devspec. */ ! 9324: if (cp) { ! 9325: cp++; ! 9326: } else { ! 9327: cp = index (fname, '/'); /* Look for the "/" */ ! 9328: } ! 9329: ! 9330: cp2 = Local; /* initialize */ ! 9331: ! 9332: /* We are trying to do a number of things here. First of all, we are ! 9333: trying to hammer the filenames into a standard format, such that later ! 9334: processing can handle them. ! 9335: ! 9336: If the file name contains something like [dir.], then it recognizes this ! 9337: as a root, and strips the ".]". Later processing will add whatever is ! 9338: needed to get things working properly. ! 9339: ! 9340: If no device is specified, then the first directory name is taken to be ! 9341: a device name (or a rooted logical). */ ! 9342: ! 9343: /* See if we found that 1st slash */ ! 9344: if (cp == 0) return; /* Nothing to do!!! */ ! 9345: if (*cp != '/') return; /* Nothing to do!!! */ ! 9346: /* Point to the UNIX filename part (which needs to be fixed!) */ ! 9347: cp1 = cp+1; ! 9348: /* If the directory spec is not rooted, we can just copy ! 9349: the UNIX filename part and we are done */ ! 9350: if (((cp - fname) > 1) && ((cp[-1] == ']') || (cp[-1] == '>'))) { ! 9351: if (cp[-2] != '.') { ! 9352: /* ! 9353: * The VMS part ends in a `]', and the preceding character is not a `.'. ! 9354: * We strip the `]', and then splice the two parts of the name in the ! 9355: * usual way. Given the default locations for include files in cccp.c, ! 9356: * we will only use this code if the user specifies alternate locations ! 9357: * with the /include (-I) switch on the command line. */ ! 9358: cp -= 1; /* Strip "]" */ ! 9359: cp1--; /* backspace */ ! 9360: } else { ! 9361: /* ! 9362: * The VMS part has a ".]" at the end, and this will not do. Later ! 9363: * processing will add a second directory spec, and this would be a syntax ! 9364: * error. Thus we strip the ".]", and thus merge the directory specs. ! 9365: * We also backspace cp1, so that it points to a '/'. This inhibits the ! 9366: * generation of the 000000 root directory spec (which does not belong here ! 9367: * in this case). ! 9368: */ ! 9369: cp -= 2; /* Strip ".]" */ ! 9370: cp1--; }; /* backspace */ ! 9371: } else { ! 9372: ! 9373: /* We drop in here if there is no VMS style directory specification yet. ! 9374: * If there is no device specification either, we make the first dir a ! 9375: * device and try that. If we do not do this, then we will be essentially ! 9376: * searching the users default directory (as if they did a #include "asdf.h"). ! 9377: * ! 9378: * Then all we need to do is to push a '[' into the output string. Later ! 9379: * processing will fill this in, and close the bracket. ! 9380: */ ! 9381: if (cp[-1] != ':') *cp2++ = ':'; /* dev not in spec. take first dir */ ! 9382: *cp2++ = '['; /* Open the directory specification */ ! 9383: } ! 9384: ! 9385: /* at this point we assume that we have the device spec, and (at least ! 9386: the opening "[" for a directory specification. We may have directories ! 9387: specified already */ ! 9388: ! 9389: /* If there are no other slashes then the filename will be ! 9390: in the "root" directory. Otherwise, we need to add ! 9391: directory specifications. */ ! 9392: if (index (cp1, '/') == 0) { ! 9393: /* Just add "000000]" as the directory string */ ! 9394: strcpy (cp2, "000000]"); ! 9395: cp2 += strlen (cp2); ! 9396: check_filename_before_returning = 1; /* we might need to fool with this later */ ! 9397: } else { ! 9398: /* As long as there are still subdirectories to add, do them. */ ! 9399: while (index (cp1, '/') != 0) { ! 9400: /* If this token is "." we can ignore it */ ! 9401: if ((cp1[0] == '.') && (cp1[1] == '/')) { ! 9402: cp1 += 2; ! 9403: continue; ! 9404: } ! 9405: /* Add a subdirectory spec. Do not duplicate "." */ ! 9406: if (cp2[-1] != '.' && cp2[-1] != '[' && cp2[-1] != '<') ! 9407: *cp2++ = '.'; ! 9408: /* If this is ".." then the spec becomes "-" */ ! 9409: if ((cp1[0] == '.') && (cp1[1] == '.') && (cp[2] == '/')) { ! 9410: /* Add "-" and skip the ".." */ ! 9411: *cp2++ = '-'; ! 9412: cp1 += 3; ! 9413: continue; ! 9414: } ! 9415: /* Copy the subdirectory */ ! 9416: while (*cp1 != '/') *cp2++= *cp1++; ! 9417: cp1++; /* Skip the "/" */ ! 9418: } ! 9419: /* Close the directory specification */ ! 9420: if (cp2[-1] == '.') /* no trailing periods */ ! 9421: cp2--; ! 9422: *cp2++ = ']'; ! 9423: } ! 9424: /* Now add the filename */ ! 9425: while (*cp1) *cp2++ = *cp1++; ! 9426: *cp2 = 0; ! 9427: /* Now append it to the original VMS spec. */ ! 9428: strcpy (cp, Local); ! 9429: ! 9430: /* If we put a [000000] in the filename, try to open it first. If this fails, ! 9431: remove the [000000], and return that name. This provides flexibility ! 9432: to the user in that they can use both rooted and non-rooted logical names ! 9433: to point to the location of the file. */ ! 9434: ! 9435: if (check_filename_before_returning && no_prefix_seen) { ! 9436: f = open (fname, O_RDONLY, 0666); ! 9437: if (f >= 0) { ! 9438: /* The file name is OK as it is, so return it as is. */ ! 9439: close (f); ! 9440: return; ! 9441: } ! 9442: /* The filename did not work. Try to remove the [000000] from the name, ! 9443: and return it. */ ! 9444: cp = index (fname, '['); ! 9445: cp2 = index (fname, ']') + 1; ! 9446: strcpy (cp, cp2); /* this gets rid of it */ ! 9447: } ! 9448: return; ! 9449: } ! 9450: #endif /* VMS */ ! 9451: ! 9452: #ifdef VMS ! 9453: ! 9454: /* These are the read/write replacement routines for ! 9455: VAX-11 "C". They make read/write behave enough ! 9456: like their UNIX counterparts that CCCP will work */ ! 9457: ! 9458: static int ! 9459: read (fd, buf, size) ! 9460: int fd; ! 9461: char *buf; ! 9462: int size; ! 9463: { ! 9464: #undef read /* Get back the REAL read routine */ ! 9465: register int i; ! 9466: register int total = 0; ! 9467: ! 9468: /* Read until the buffer is exhausted */ ! 9469: while (size > 0) { ! 9470: /* Limit each read to 32KB */ ! 9471: i = (size > (32*1024)) ? (32*1024) : size; ! 9472: i = read (fd, buf, i); ! 9473: if (i <= 0) { ! 9474: if (i == 0) return (total); ! 9475: return (i); ! 9476: } ! 9477: /* Account for this read */ ! 9478: total += i; ! 9479: buf += i; ! 9480: size -= i; ! 9481: } ! 9482: return (total); ! 9483: } ! 9484: ! 9485: static int ! 9486: write (fd, buf, size) ! 9487: int fd; ! 9488: char *buf; ! 9489: int size; ! 9490: { ! 9491: #undef write /* Get back the REAL write routine */ ! 9492: int i; ! 9493: int j; ! 9494: ! 9495: /* Limit individual writes to 32Kb */ ! 9496: i = size; ! 9497: while (i > 0) { ! 9498: j = (i > (32*1024)) ? (32*1024) : i; ! 9499: if (write (fd, buf, j) < 0) return (-1); ! 9500: /* Account for the data written */ ! 9501: buf += j; ! 9502: i -= j; ! 9503: } ! 9504: return (size); ! 9505: } ! 9506: ! 9507: /* The following wrapper functions supply additional arguments to the VMS ! 9508: I/O routines to optimize performance with file handling. The arguments ! 9509: are: ! 9510: "mbc=16" - Set multi-block count to 16 (use a 8192 byte buffer). ! 9511: "deq=64" - When extending the file, extend it in chunks of 32Kbytes. ! 9512: "fop=tef"- Truncate unused portions of file when closing file. ! 9513: "shr=nil"- Disallow file sharing while file is open. ! 9514: */ ! 9515: ! 9516: static FILE * ! 9517: freopen (fname, type, oldfile) ! 9518: char *fname; ! 9519: char *type; ! 9520: FILE *oldfile; ! 9521: { ! 9522: #undef freopen /* Get back the REAL fopen routine */ ! 9523: if (strcmp (type, "w") == 0) ! 9524: return freopen (fname, type, oldfile, "mbc=16", "deq=64", "fop=tef", "shr=nil"); ! 9525: return freopen (fname, type, oldfile, "mbc=16"); ! 9526: } ! 9527: ! 9528: static FILE * ! 9529: fopen (fname, type) ! 9530: char *fname; ! 9531: char *type; ! 9532: { ! 9533: #undef fopen /* Get back the REAL fopen routine */ ! 9534: if (strcmp (type, "w") == 0) ! 9535: return fopen (fname, type, "mbc=16", "deq=64", "fop=tef", "shr=nil"); ! 9536: return fopen (fname, type, "mbc=16"); ! 9537: } ! 9538: ! 9539: static int ! 9540: open (fname, flags, prot) ! 9541: char *fname; ! 9542: int flags; ! 9543: int prot; ! 9544: { ! 9545: #undef open /* Get back the REAL open routine */ ! 9546: return open (fname, flags, prot, "mbc=16", "deq=64", "fop=tef"); ! 9547: } ! 9548: ! 9549: /* Avoid run-time library bug, where copying M out of N+M characters with ! 9550: N >= 65535 results in VAXCRTL's strncat falling into an infinite loop. ! 9551: gcc-cpp exercises this particular bug. */ ! 9552: ! 9553: static char * ! 9554: strncat (dst, src, cnt) ! 9555: char *dst; ! 9556: const char *src; ! 9557: unsigned cnt; ! 9558: { ! 9559: register char *d = dst, *s = (char *) src; ! 9560: register int n = cnt; /* convert to _signed_ type */ ! 9561: ! 9562: while (*d) d++; /* advance to end */ ! 9563: while (--n >= 0) ! 9564: if (!(*d++ = *s++)) break; ! 9565: if (n < 0) *d = '\0'; ! 9566: return dst; ! 9567: } ! 9568: #endif /* VMS */ ! 9569: ! 9570: #ifdef NEXT_SEMANTICS ! 9571: ! 9572: /* Pre-C-Preprocessor to translate RTF (Rich Text Format) Level 0 ! 9573: to plain ASCII before normal preprocessing. This removes all font, color, ! 9574: and help links from the text, but leaves the actual contents unchanged. ! 9575: ! 9576: Using an extra pass through the buffer takes a little extra time, ! 9577: but Rich Source Code is rare and a separate, shared routine ! 9578: can be used. */ ! 9579: ! 9580: #define RTF_HEADER "{\\rtf0\\ansi" ! 9581: #define RTF_HEADER_LEN 11 ! 9582: ! 9583: static void ! 9584: buf_convert_rtf (buf) ! 9585: FILE_BUF *buf; ! 9586: { ! 9587: int asciiTextLen; ! 9588: ! 9589: if (buf->buf ! 9590: && buf->length > RTF_HEADER_LEN ! 9591: && !strncmp (buf->buf, RTF_HEADER, RTF_HEADER_LEN)) ! 9592: { ! 9593: const char * asciiText = rtf_to_ascii(buf->buf, buf->length, &asciiTextLen); ! 9594: if (asciiText) ! 9595: { ! 9596: /* FIXME: deallocate buf->buf */ ! 9597: buf->buf = buf->bufp = (char *) asciiText; ! 9598: buf->length = asciiTextLen; ! 9599: } ! 9600: } ! 9601: } ! 9602: ! 9603: ! 9604: /* Process rtf text. RTFTEXTLEN bytes are processed from ! 9605: RTFTEXTPTR. The output is ASCIITEXTLEN bytes in the same buffer. */ ! 9606: ! 9607: #define ASCII_TERMINATOR '\0' ! 9608: ! 9609: static const char * ! 9610: rtf_to_ascii (const char *rtfTextPtr, int rtfTextLen, int * asciiTextLen) ! 9611: { ! 9612: char * asciiTextBuf = (char *) xmalloc(rtfTextLen); ! 9613: char * asciiTextPtr = asciiTextBuf; ! 9614: const char *endRtfPtr = rtfTextPtr + rtfTextLen; ! 9615: ! 9616: if (!asciiTextBuf) ! 9617: return NULL; ! 9618: ! 9619: while ( rtfTextPtr != endRtfPtr ) { ! 9620: switch( *rtfTextPtr ) { ! 9621: case '\n': ! 9622: rtfTextPtr++; ! 9623: break; ! 9624: case '}': ! 9625: if ( *++rtfTextPtr == '\n' ) { ! 9626: rtfTextPtr++; ! 9627: if (*rtfTextPtr == '�') rtfTextPtr++; ! 9628: } ! 9629: break; ! 9630: case '{': ! 9631: if ( !strncmp( rtfTextPtr, "{\\stylesheet", 12 ) ! 9632: || !strncmp( rtfTextPtr, "{\\fonttbl", 9 ) ! 9633: || !strncmp( rtfTextPtr, "{\\colortbl", 10 ) ! 9634: || !strncmp( rtfTextPtr, "{\\NeXTHelp", 10 ) ! 9635: || !strncmp( rtfTextPtr, "{{\\NeXTHelp", 11 ) ) { ! 9636: int depth = 1; ! 9637: while ( depth > 0 ) { ! 9638: switch ( *++rtfTextPtr ) { ! 9639: case '{': depth++; break; ! 9640: case '}': depth--; break; ! 9641: } ! 9642: } ! 9643: } ! 9644: else ! 9645: rtfTextPtr++; ! 9646: break; ! 9647: case '\\': ! 9648: rtfTextPtr++; ! 9649: if (*rtfTextPtr == '{' ! 9650: || *rtfTextPtr == '}' ! 9651: || *rtfTextPtr == '\\' ! 9652: || *rtfTextPtr == '\n' ) { ! 9653: *asciiTextPtr++ = *rtfTextPtr++; ! 9654: } else if ( *rtfTextPtr == '\'' ) { ! 9655: int v1, v2, value; ! 9656: rtfTextPtr++; ! 9657: v1 = isdigit( *rtfTextPtr ) ? (*rtfTextPtr - '0') ! 9658: : ((*rtfTextPtr - 'a') + 10); ! 9659: rtfTextPtr++; ! 9660: v2 = isdigit( *rtfTextPtr ) ? (*rtfTextPtr - '0') ! 9661: : ((*rtfTextPtr - 'a') + 10); ! 9662: value = (v1 << 4) | (v2); ! 9663: *asciiTextPtr++ = value; ! 9664: rtfTextPtr++; ! 9665: } else { ! 9666: while ( isalpha( *rtfTextPtr ) ) rtfTextPtr++; ! 9667: if (*rtfTextPtr == '-') rtfTextPtr++; ! 9668: while ( isdigit( *rtfTextPtr ) ) rtfTextPtr++; ! 9669: if ( *rtfTextPtr == ' ' ) rtfTextPtr++; ! 9670: else while (*rtfTextPtr == ' ') rtfTextPtr++; ! 9671: } ! 9672: break; ! 9673: default: ! 9674: *asciiTextPtr++ = *rtfTextPtr++; ! 9675: } ! 9676: } ! 9677: *asciiTextPtr = ASCII_TERMINATOR; ! 9678: *asciiTextLen = (int)asciiTextPtr - (int)asciiTextBuf; ! 9679: return asciiTextBuf; ! 9680: } ! 9681: ! 9682: ! 9683: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.