|
|
1.1 ! root 1: /* C Compatible Compiler Preprocessor (CCCP) ! 2: Copyright (C) 1986, 1987, Free Software Foundation, Inc. ! 3: Written by Paul Rubin, June 1986 ! 4: Adapted to ANSI C, Richard Stallman, Jan 1987 ! 5: ! 6: NO WARRANTY ! 7: ! 8: BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY ! 9: NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT ! 10: WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, ! 11: RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS" ! 12: WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, ! 13: BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ! 14: FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY ! 15: AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE ! 16: DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR ! 17: CORRECTION. ! 18: ! 19: IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. ! 20: STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY ! 21: WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE ! 22: LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR ! 23: OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE ! 24: USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR ! 25: DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR ! 26: A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS ! 27: PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH ! 28: DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. ! 29: ! 30: GENERAL PUBLIC LICENSE TO COPY ! 31: ! 32: 1. You may copy and distribute verbatim copies of this source file ! 33: as you receive it, in any medium, provided that you conspicuously ! 34: and appropriately publish on each copy a valid copyright notice ! 35: "Copyright (C) 1987, Free Software Foundation"; and include ! 36: following the copyright notice a verbatim copy of the above disclaimer ! 37: of warranty and of this License. You may charge a distribution fee for the ! 38: physical act of transferring a copy. ! 39: ! 40: 2. You may modify your copy or copies of this source file or ! 41: any portion of it, and copy and distribute such modifications under ! 42: the terms of Paragraph 1 above, provided that you also do the following: ! 43: ! 44: a) cause the modified files to carry prominent notices stating ! 45: that you changed the files and the date of any change; and ! 46: ! 47: b) cause the whole of any work that you distribute or publish, ! 48: that in whole or in part contains or is a derivative of this ! 49: program or any part thereof, to be licensed at no charge to all ! 50: third parties on terms identical to those contained in this ! 51: License Agreement (except that you may choose to grant more extensive ! 52: warranty protection to some or all third parties, at your option). ! 53: ! 54: c) You may charge a distribution fee for the physical act of ! 55: transferring a copy, and you may at your option offer warranty ! 56: protection in exchange for a fee. ! 57: ! 58: Mere aggregation of another unrelated program with this program (or its ! 59: derivative) on a volume of a storage or distribution medium does not bring ! 60: the other program under the scope of these terms. ! 61: ! 62: 3. You may copy and distribute this program (or a portion or derivative ! 63: of it, under Paragraph 2) in object code or executable form under the terms ! 64: of Paragraphs 1 and 2 above provided that you also do one of the following: ! 65: ! 66: a) accompany it with the complete corresponding machine-readable ! 67: source code, which must be distributed under the terms of ! 68: Paragraphs 1 and 2 above; or, ! 69: ! 70: b) accompany it with a written offer, valid for at least three ! 71: years, to give any third party free (except for a nominal ! 72: shipping charge) a complete machine-readable copy of the ! 73: corresponding source code, to be distributed under the terms of ! 74: Paragraphs 1 and 2 above; or, ! 75: ! 76: c) accompany it with the information you received as to where the ! 77: corresponding source code may be obtained. (This alternative is ! 78: allowed only for noncommercial distribution and only if you ! 79: received the program in object code or executable form alone.) ! 80: ! 81: For an executable file, complete source code means all the source code for ! 82: all modules it contains; but, as a special exception, it need not include ! 83: source code for modules which are standard libraries that accompany the ! 84: operating system on which the executable file runs. ! 85: ! 86: 4. You may not copy, sublicense, distribute or transfer this program ! 87: except as expressly provided under this License Agreement. Any attempt ! 88: otherwise to copy, sublicense, distribute or transfer this program is void and ! 89: your rights to use the program under this License agreement shall be ! 90: automatically terminated. However, parties who have received computer ! 91: software programs from you with this License Agreement will not have ! 92: their licenses terminated so long as such parties remain in full compliance. ! 93: ! 94: 5. If you wish to incorporate parts of this program into other free ! 95: programs whose distribution conditions are different, write to the Free ! 96: Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet ! 97: worked out a simple rule that can be stated here, but we will often permit ! 98: this. We will be guided by the two goals of preserving the free status of ! 99: all derivatives of our free software and of promoting the sharing and reuse of ! 100: software. ! 101: ! 102: ! 103: In other words, you are welcome to use, share and improve this program. ! 104: You are forbidden to forbid anyone else to use, share and improve ! 105: what you give them. Help stamp out software-hoarding! */ ! 106: ! 107: typedef unsigned char U_CHAR; ! 108: ! 109: #ifdef EMACS ! 110: #define NO_SHORTNAMES ! 111: #include "../src/config.h" ! 112: #ifdef open ! 113: #undef open ! 114: #undef read ! 115: #undef write ! 116: #endif /* open */ ! 117: #endif /* EMACS */ ! 118: ! 119: #ifndef EMACS ! 120: #include "config.h" ! 121: #endif /* not EMACS */ ! 122: ! 123: /* In case config.h defines these. */ ! 124: #undef bcopy ! 125: #undef bzero ! 126: #undef bcmp ! 127: ! 128: #include <sys/types.h> ! 129: #include <sys/stat.h> ! 130: #include <ctype.h> ! 131: #include <stdio.h> ! 132: ! 133: #ifndef VMS ! 134: #include <sys/file.h> ! 135: #ifndef USG ! 136: #include <sys/time.h> /* for __DATE__ and __TIME__ */ ! 137: #include <sys/resource.h> ! 138: #else ! 139: #define index strchr ! 140: #define rindex strrchr ! 141: #include <time.h> ! 142: #include <fcntl.h> ! 143: #endif /* USG */ ! 144: #endif /* not VMS */ ! 145: ! 146: /* VMS-specific definitions */ ! 147: #ifdef VMS ! 148: #include <time.h> ! 149: #include <errno.h> /* This defines "errno" properly */ ! 150: #include <perror.h> /* This defines sys_errlist/sys_nerr properly */ ! 151: #define O_RDONLY 0 /* Open arg for Read/Only */ ! 152: #define O_WRONLY 1 /* Open arg for Write/Only */ ! 153: #define read(fd,buf,size) VAX11_C_read(fd,buf,size) ! 154: #define write(fd,buf,size) VAX11_C_write(fd,buf,size) ! 155: #ifdef __GNUC__ ! 156: #define BSTRING /* VMS/GCC supplies the bstring routines */ ! 157: #endif __GNUC__ ! 158: #endif /* VMS */ ! 159: ! 160: /* External declarations. */ ! 161: ! 162: void bcopy (), bzero (); ! 163: int bcmp (); ! 164: extern char version_string[]; ! 165: ! 166: /* Forward declarations. */ ! 167: ! 168: int do_define (), do_line (), do_include (), do_undef (), do_error (), ! 169: do_pragma (), do_if (), do_xifdef (), do_else (), ! 170: do_elif (), do_endif (), do_sccs (); ! 171: ! 172: struct hashnode *install (); ! 173: struct hashnode *lookup (); ! 174: ! 175: char *xmalloc (), *xrealloc (), *xcalloc (); ! 176: void fatal (), pfatal_with_name (), perror_with_name (); ! 177: ! 178: int grow_outbuf (); ! 179: int handle_directive (); ! 180: void memory_full (); ! 181: ! 182: U_CHAR *macarg1 (); ! 183: char *macarg (); ! 184: ! 185: U_CHAR *skip_to_end_of_comment (); ! 186: U_CHAR *skip_quoted_string (); ! 187: ! 188: #ifndef FATAL_EXIT_CODE ! 189: #define FATAL_EXIT_CODE 33 /* gnu cc command understands this */ ! 190: #endif ! 191: ! 192: #ifndef SUCCESS_EXIT_CODE ! 193: #define SUCCESS_EXIT_CODE 0 /* 0 means success on Unix. */ ! 194: #endif ! 195: ! 196: /* Name under which this program was invoked. */ ! 197: ! 198: char *progname; ! 199: ! 200: /* Current maximum length of directory names in the search path ! 201: for include files. (Altered as we get more of them.) */ ! 202: ! 203: int max_include_len = sizeof("/usr/local/lib/gcc-include"); ! 204: ! 205: /* Nonzero means copy comments into the output file. */ ! 206: ! 207: int put_out_comments = 0; ! 208: ! 209: /* Nonzero means don't process the ANSI trigraph sequences. */ ! 210: ! 211: int no_trigraphs = 0; ! 212: ! 213: /* Nonzero means print the names of included files rather than ! 214: the preprocessed output. 1 means just the #include "...", ! 215: 2 means #include <...> as well. */ ! 216: ! 217: int print_deps = 0; ! 218: ! 219: /* Nonzero means don't output line number information. */ ! 220: ! 221: int no_line_commands; ! 222: ! 223: /* Nonzero means inhibit output of the preprocessed text ! 224: and instead output the definitions of all user-defined macros ! 225: in a form suitable for use as input to cccp. */ ! 226: ! 227: int dump_macros; ! 228: ! 229: /* Nonzero means give all the error messages the ANSI standard requires. */ ! 230: ! 231: int pedantic; ! 232: ! 233: /* Nonzero means warn if slash-star appears in a comment. */ ! 234: ! 235: int warn_comments; ! 236: ! 237: /* Nonzero means try to imitate old fashioned non-ANSI preprocessor. */ ! 238: ! 239: int traditional; ! 240: ! 241: /* Nonzero causes output not to be done, ! 242: but directives such as #define that have side effects ! 243: are still obeyed. */ ! 244: ! 245: int no_output; ! 246: ! 247: /* I/O buffer structure. ! 248: The `fname' field is nonzero for source files and #include files ! 249: and for the dummy text used for -D and -U. ! 250: It is zero for rescanning results of macro expansion ! 251: and for expanding macro arguments. */ ! 252: #define INPUT_STACK_MAX 200 ! 253: struct file_buf { ! 254: char *fname; ! 255: int lineno; ! 256: int length; ! 257: U_CHAR *buf; ! 258: U_CHAR *bufp; ! 259: /* Macro that this level is the expansion of. ! 260: Included so that we can reenable the macro ! 261: at the end of this level. */ ! 262: struct hashnode *macro; ! 263: /* Value of if_stack at start of this file. ! 264: Used to prohibit unmatched #endif (etc) in an include file. */ ! 265: struct if_stack *if_stack; ! 266: /* Object to be freed at end of input at this level. */ ! 267: U_CHAR *free; ! 268: } instack[INPUT_STACK_MAX]; ! 269: ! 270: /* Current nesting level of input sources. ! 271: `instack[indepth]' is the level currently being read. */ ! 272: int indepth = -1; ! 273: ! 274: typedef struct file_buf FILE_BUF; ! 275: ! 276: /* The output buffer. Its LENGTH field is the amount of room allocated ! 277: for the buffer, not the number of chars actually present. To get ! 278: that, subtract outbuf.buf from outbuf.bufp. */ ! 279: ! 280: #define OUTBUF_SIZE 10 /* initial size of output buffer */ ! 281: FILE_BUF outbuf; ! 282: ! 283: /* Grow output buffer OBUF points at ! 284: so it can hold at least NEEDED more chars. */ ! 285: ! 286: #define check_expand(OBUF, NEEDED) \ ! 287: (((OBUF)->length - ((OBUF)->bufp - (OBUF)->buf) <= (NEEDED)) \ ! 288: ? grow_outbuf ((OBUF), (NEEDED)) : 0) ! 289: ! 290: struct directory_stack ! 291: { ! 292: struct directory_stack *next; ! 293: char *fname; ! 294: }; ! 295: ! 296: /* #include "file" looks in source file dir, then stack. */ ! 297: /* #include <file> just looks in the stack. */ ! 298: /* -I directories are added to the end, then the defaults are added. */ ! 299: struct directory_stack include_defaults[] = ! 300: { ! 301: #ifndef VMS ! 302: #ifdef CPLUSPLUS ! 303: /* Pick up GNU C++ specific include files. */ ! 304: { &include_defaults[1], "/usr/local/lib/g++-include" }, ! 305: /* Borrow AT&T C++ head files, if available. */ ! 306: { &include_defaults[2], "/usr/include/CC" }, ! 307: /* Use GNU CC specific header files. */ ! 308: { &include_defaults[3], "/usr/local/lib/gcc-include" }, ! 309: #else ! 310: { &include_defaults[1], "/usr/local/lib/gcc-include" }, ! 311: #endif ! 312: { 0, "/usr/include" } ! 313: #else ! 314: { &include_defaults[1], "GNU_CC_INCLUDE:" }, /* GNU includes */ ! 315: { &include_defaults[2], "SYS$SYSROOT:[SYSLIB.]" }, /* VAX-11 "C" includes */ ! 316: { 0, "" }, /* This makes normal VMS filespecs work OK */ ! 317: #endif /* VMS */ ! 318: }; ! 319: ! 320: struct directory_stack *include = 0; /* First dir to search */ ! 321: /* First dir to search for <file> */ ! 322: struct directory_stack *first_bracket_include = 0; ! 323: struct directory_stack *last_include = 0; /* Last in chain */ ! 324: ! 325: /* Structure allocated for every #define. For a simple replacement ! 326: such as ! 327: #define foo bar , ! 328: nargs = -1, the `pattern' list is null, and the expansion is just ! 329: the replacement text. Nargs = 0 means a functionlike macro with no args, ! 330: e.g., ! 331: #define getchar() getc (stdin) . ! 332: When there are args, the expansion is the replacement text with the ! 333: args squashed out, and the reflist is a list describing how to ! 334: build the output from the input: e.g., "3 chars, then the 1st arg, ! 335: then 9 chars, then the 3rd arg, then 0 chars, then the 2nd arg". ! 336: The chars here come from the expansion. Whatever is left of the ! 337: expansion after the last arg-occurrence is copied after that arg. ! 338: Note that the reflist can be arbitrarily long--- ! 339: its length depends on the number of times the arguments appear in ! 340: the replacement text, not how many args there are. Example: ! 341: #define f(x) x+x+x+x+x+x+x would have replacement text "++++++" and ! 342: pattern list ! 343: { (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL } ! 344: where (x, y) means (nchars, argno). */ ! 345: ! 346: typedef struct definition DEFINITION; ! 347: struct definition { ! 348: int nargs; ! 349: int length; /* length of expansion string */ ! 350: U_CHAR *expansion; ! 351: struct reflist { ! 352: struct reflist *next; ! 353: char stringify; /* nonzero if this arg was preceded by a ! 354: # operator. */ ! 355: char raw_before; /* Nonzero if a ## operator before arg. */ ! 356: char raw_after; /* Nonzero if a ## operator after arg. */ ! 357: int nchars; /* Number of literal chars to copy before ! 358: this arg occurrence. */ ! 359: int argno; /* Number of arg to substitute (origin-0) */ ! 360: } *pattern; ! 361: /* Names of macro args, concatenated in reverse order ! 362: with comma-space between them. ! 363: The only use of this is that we warn on redefinition ! 364: if this differs between the old and new definitions. */ ! 365: U_CHAR *argnames; ! 366: }; ! 367: ! 368: /* different kinds of things that can appear in the value field ! 369: of a hash node. Actually, this may be useless now. */ ! 370: union hashval { ! 371: int ival; ! 372: char *cpval; ! 373: DEFINITION *defn; ! 374: }; ! 375: ! 376: ! 377: /* The structure of a node in the hash table. The hash table ! 378: has entries for all tokens defined by #define commands (type T_MACRO), ! 379: plus some special tokens like __LINE__ (these each have their own ! 380: type, and the appropriate code is run when that type of node is seen. ! 381: It does not contain control words like "#define", which are recognized ! 382: by a separate piece of code. */ ! 383: ! 384: /* different flavors of hash nodes --- also used in keyword table */ ! 385: enum node_type { ! 386: T_DEFINE = 1, /* the `#define' keyword */ ! 387: T_INCLUDE, /* the `#include' keyword */ ! 388: T_IFDEF, /* the `#ifdef' keyword */ ! 389: T_IFNDEF, /* the `#ifndef' keyword */ ! 390: T_IF, /* the `#if' keyword */ ! 391: T_ELSE, /* `#else' */ ! 392: #if 0 ! 393: /* cpp can pass #pragma through unchanged. */ ! 394: T_PRAGMA, /* `#pragma' */ ! 395: #endif ! 396: T_ELIF, /* `#else' */ ! 397: T_UNDEF, /* `#undef' */ ! 398: T_LINE, /* `#line' */ ! 399: T_ERROR, /* `#error' */ ! 400: T_ENDIF, /* `#endif' */ ! 401: T_SCCS, /* `#sccs', used on system V. */ ! 402: T_SPECLINE, /* special symbol `__LINE__' */ ! 403: T_DATE, /* `__DATE__' */ ! 404: T_FILE, /* `__FILE__' */ ! 405: T_VERSION, /* `__VERSION__' */ ! 406: T_TIME, /* `__TIME__' */ ! 407: T_CONST, /* Constant value, used by `__STDC__' */ ! 408: T_MACRO, /* macro defined by `#define' */ ! 409: T_DISABLED, /* macro temporarily turned off for rescan */ ! 410: T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */ ! 411: T_UNUSED /* Used for something not defined. */ ! 412: }; ! 413: ! 414: struct hashnode { ! 415: struct hashnode *next; /* double links for easy deletion */ ! 416: struct hashnode *prev; ! 417: struct hashnode **bucket_hdr; /* also, a back pointer to this node's hash ! 418: chain is kept, in case the node is the head ! 419: of the chain and gets deleted. */ ! 420: enum node_type type; /* type of special token */ ! 421: int length; /* length of token, for quick comparison */ ! 422: U_CHAR *name; /* the actual name */ ! 423: union hashval value; /* pointer to expansion, or whatever */ ! 424: }; ! 425: ! 426: typedef struct hashnode HASHNODE; ! 427: ! 428: /* Some definitions for the hash table. The hash function MUST be ! 429: computed as shown in hashf () below. That is because the rescan ! 430: loop computes the hash value `on the fly' for most tokens, ! 431: in order to avoid the overhead of a lot of procedure calls to ! 432: the hashf () function. Hashf () only exists for the sake of ! 433: politeness, for use when speed isn't so important. */ ! 434: ! 435: #define HASHSIZE 1403 ! 436: HASHNODE *hashtab[HASHSIZE]; ! 437: #define HASHSTEP(old, c) ((old << 2) + c) ! 438: #define MAKE_POS(v) (v & ~0x80000000) /* make number positive */ ! 439: ! 440: /* Symbols to predefine. */ ! 441: ! 442: #ifdef CPP_PREDEFINES ! 443: char *predefs = CPP_PREDEFINES; ! 444: #else ! 445: char *predefs = ""; ! 446: #endif ! 447: ! 448: /* `struct directive' defines one #-directive, including how to handle it. */ ! 449: ! 450: struct directive { ! 451: int length; /* Length of name */ ! 452: int (*func)(); /* Function to handle directive */ ! 453: char *name; /* Name of directive */ ! 454: enum node_type type; /* Code which describes which directive. */ ! 455: char angle_brackets; /* Nonzero => don't delete comments. */ ! 456: }; ! 457: ! 458: /* Here is the actual list of #-directives, most-often-used first. */ ! 459: ! 460: struct directive directive_table[] = { ! 461: { 6, do_define, "define", T_DEFINE}, ! 462: { 2, do_if, "if", T_IF}, ! 463: { 5, do_xifdef, "ifdef", T_IFDEF}, ! 464: { 6, do_xifdef, "ifndef", T_IFNDEF}, ! 465: { 5, do_endif, "endif", T_ENDIF}, ! 466: { 4, do_else, "else", T_ELSE}, ! 467: { 4, do_elif, "elif", T_ELIF}, ! 468: { 4, do_line, "line", T_LINE}, ! 469: { 7, do_include, "include", T_INCLUDE, 1}, ! 470: { 5, do_undef, "undef", T_UNDEF}, ! 471: { 5, do_error, "error", T_ERROR}, ! 472: #ifdef SCCS_DIRECTIVE ! 473: { 4, do_sccs, "sccs", T_SCCS}, ! 474: #endif ! 475: #if 0 ! 476: { 6, do_pragma, "pragma", T_PRAGMA}, ! 477: #endif ! 478: { -1, 0, "", T_UNUSED}, ! 479: }; ! 480: ! 481: /* table to tell if char can be part of a C identifier. */ ! 482: U_CHAR is_idchar[256]; ! 483: /* table to tell if char can be first char of a c identifier. */ ! 484: U_CHAR is_idstart[256]; ! 485: /* table to tell if c is horizontal space. */ ! 486: U_CHAR is_hor_space[256]; ! 487: /* table to tell if c is horizontal or vertical space. */ ! 488: U_CHAR is_space[256]; ! 489: ! 490: #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0) ! 491: #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0) ! 492: ! 493: int errors = 0; /* Error counter for exit code */ ! 494: ! 495: /* Nonzero if have already warned about use of `$'. */ ! 496: int dollar_seen = 0; ! 497: ! 498: FILE_BUF expand_to_temp_buffer (); ! 499: ! 500: DEFINITION *collect_expansion (); ! 501: ! 502: /* Stack of conditionals currently in progress ! 503: (including both successful and failing conditionals). */ ! 504: ! 505: struct if_stack { ! 506: struct if_stack *next; /* for chaining to the next stack frame */ ! 507: char *fname; /* copied from input when frame is made */ ! 508: int lineno; /* similarly */ ! 509: int if_succeeded; /* true if a leg of this if-group ! 510: has been passed through rescan */ ! 511: enum node_type type; /* type of last directive seen in this group */ ! 512: }; ! 513: typedef struct if_stack IF_STACK_FRAME; ! 514: IF_STACK_FRAME *if_stack = NULL; ! 515: ! 516: /* Buffer of -M output. */ ! 517: ! 518: char *deps_buffer; ! 519: ! 520: /* Number of bytes allocated in above. */ ! 521: int deps_allocated_size; ! 522: ! 523: /* Number of bytes used. */ ! 524: int deps_size; ! 525: ! 526: /* Number of bytes since the last newline. */ ! 527: int deps_column; ! 528: ! 529: /* Nonzero means -I- has been seen, ! 530: so don't look for #include "foo" the source-file directory. */ ! 531: int ignore_srcdir; ! 532: ! 533: int ! 534: main (argc, argv) ! 535: int argc; ! 536: char **argv; ! 537: { ! 538: int st_mode; ! 539: long st_size; ! 540: char *in_fname, *out_fname; ! 541: int f, i; ! 542: FILE_BUF *fp; ! 543: char **pend_files = (char **) xmalloc (argc * sizeof (char *)); ! 544: char **pend_defs = (char **) xmalloc (argc * sizeof (char *)); ! 545: char **pend_undefs = (char **) xmalloc (argc * sizeof (char *)); ! 546: int inhibit_predefs = 0; ! 547: int no_standard_includes = 0; ! 548: ! 549: #ifdef RLIMIT_STACK ! 550: /* Get rid of any avoidable limit on stack size. */ ! 551: { ! 552: struct rlimit rlim; ! 553: ! 554: /* Set the stack limit huge so that alloca (particularly stringtab ! 555: * in dbxread.c) does not fail. */ ! 556: getrlimit (RLIMIT_STACK, &rlim); ! 557: rlim.rlim_cur = rlim.rlim_max; ! 558: setrlimit (RLIMIT_STACK, &rlim); ! 559: } ! 560: #endif /* RLIMIT_STACK defined */ ! 561: ! 562: progname = argv[0]; ! 563: in_fname = NULL; ! 564: out_fname = NULL; ! 565: initialize_random_junk (); ! 566: ! 567: no_line_commands = 0; ! 568: no_trigraphs = 1; ! 569: dump_macros = 0; ! 570: no_output = 0; ! 571: ! 572: bzero (pend_files, argc * sizeof (char *)); ! 573: bzero (pend_defs, argc * sizeof (char *)); ! 574: bzero (pend_undefs, argc * sizeof (char *)); ! 575: ! 576: /* Process switches and find input file name. */ ! 577: ! 578: for (i = 1; i < argc; i++) { ! 579: if (argv[i][0] != '-') { ! 580: if (out_fname != NULL) ! 581: fatal ("Usage: %s [switches] input output\n", argv[0]); ! 582: else if (in_fname != NULL) { ! 583: out_fname = argv[i]; ! 584: if (! freopen (out_fname, "w", stdout)) ! 585: pfatal_with_name (out_fname); ! 586: } else ! 587: in_fname = argv[i]; ! 588: } else { ! 589: switch (argv[i][1]) { ! 590: ! 591: case 'i': ! 592: if (argv[i][2] != 0) ! 593: pend_files[i] = argv[i] + 2; ! 594: else ! 595: pend_files[i] = argv[i+1], i++; ! 596: break; ! 597: ! 598: case 'o': ! 599: if (out_fname != NULL) ! 600: fatal ("Output filename specified twice\n"); ! 601: out_fname = argv[++i]; ! 602: if (! freopen (out_fname, "w", stdout)) ! 603: pfatal_with_name (out_fname); ! 604: break; ! 605: ! 606: case 'p': ! 607: pedantic = 1; ! 608: break; ! 609: ! 610: case 't': ! 611: traditional = 1; ! 612: break; ! 613: ! 614: case 'W': ! 615: warn_comments = 1; ! 616: break; ! 617: ! 618: case 'M': ! 619: if (!strcmp (argv[i], "-M")) ! 620: print_deps = 2; ! 621: else if (!strcmp (argv[i], "-MM")) ! 622: print_deps = 1; ! 623: deps_allocated_size = 200; ! 624: deps_buffer = (char *) xmalloc (deps_allocated_size); ! 625: deps_buffer[0] = 0; ! 626: deps_size = 0; ! 627: deps_column = 0; ! 628: ! 629: break; ! 630: ! 631: case 'd': ! 632: dump_macros = 1; ! 633: no_output = 1; ! 634: break; ! 635: ! 636: case 'v': ! 637: { ! 638: fprintf (stderr, "GNU CPP version %s\n", version_string); ! 639: } ! 640: break; ! 641: ! 642: case 'D': ! 643: { ! 644: char *p, *p1; ! 645: ! 646: if (argv[i][2] != 0) ! 647: p = argv[i] + 2; ! 648: else ! 649: p = argv[++i]; ! 650: ! 651: if ((p1 = (char *) index (p, '=')) != NULL) ! 652: *p1 = ' '; ! 653: pend_defs[i] = p; ! 654: } ! 655: break; ! 656: ! 657: case 'U': /* JF #undef something */ ! 658: if (argv[i][2] != 0) ! 659: pend_undefs[i] = argv[i] + 2; ! 660: else ! 661: pend_undefs[i] = argv[i+1], i++; ! 662: break; ! 663: ! 664: case 'C': ! 665: put_out_comments = 1; ! 666: break; ! 667: ! 668: case 'E': /* -E comes from cc -E; ignore it. */ ! 669: break; ! 670: ! 671: case 'P': ! 672: no_line_commands = 1; ! 673: break; ! 674: ! 675: case 'T': /* Enable ANSI trigraphs */ ! 676: no_trigraphs = 0; ! 677: break; ! 678: ! 679: case 'I': /* Add directory to path for includes. */ ! 680: { ! 681: struct directory_stack *dirtmp; ! 682: ! 683: if (! ignore_srcdir && !strcmp (argv[i] + 2, "-")) ! 684: ignore_srcdir; ! 685: else { ! 686: dirtmp = (struct directory_stack *) ! 687: xmalloc (sizeof (struct directory_stack)); ! 688: dirtmp->next = 0; /* New one goes on the end */ ! 689: if (include == 0) ! 690: include = dirtmp; ! 691: else ! 692: last_include->next = dirtmp; ! 693: last_include = dirtmp; /* Tail follows the last one */ ! 694: if (argv[i][2] != 0) ! 695: dirtmp->fname = argv[i] + 2; ! 696: else ! 697: dirtmp->fname = argv[++i]; ! 698: if (strlen (dirtmp->fname) > max_include_len) ! 699: max_include_len = strlen (dirtmp->fname); ! 700: if (ignore_srcdir && first_bracket_include == 0) ! 701: first_bracket_include = dirtmp; ! 702: } ! 703: } ! 704: break; ! 705: ! 706: case 'n': ! 707: /* -nostdinc causes no default include directories. ! 708: You must specify all include-file directories with -I. */ ! 709: no_standard_includes = 1; ! 710: break; ! 711: ! 712: case 'u': ! 713: /* Sun compiler passes undocumented switch "-undef". ! 714: Let's assume it means to inhibit the predefined symbols. */ ! 715: inhibit_predefs = 1; ! 716: break; ! 717: ! 718: case '\0': /* JF handle '-' as file name meaning stdin or stdout */ ! 719: if (in_fname == NULL) { ! 720: in_fname = ""; ! 721: break; ! 722: } else if (out_fname == NULL) { ! 723: out_fname = "stdout"; ! 724: break; ! 725: } /* else fall through into error */ ! 726: ! 727: default: ! 728: fatal ("Invalid option `%s'\n", argv[i]); ! 729: } ! 730: } ! 731: } ! 732: ! 733: /* Do standard #defines that identify processor type. */ ! 734: ! 735: if (!inhibit_predefs) { ! 736: char *p = (char *) alloca (strlen (predefs) + 1); ! 737: strcpy (p, predefs); ! 738: while (*p) { ! 739: char *q; ! 740: if (p[0] != '-' || p[1] != 'D') ! 741: abort (); ! 742: q = &p[2]; ! 743: while (*p && *p != ' ') p++; ! 744: if (*p != 0) ! 745: *p++= 0; ! 746: make_definition (q); ! 747: } ! 748: } ! 749: ! 750: /* Do defines specified with -D. */ ! 751: for (i = 1; i < argc; i++) ! 752: if (pend_defs[i]) ! 753: make_definition (pend_defs[i]); ! 754: ! 755: /* Do undefines specified with -U. */ ! 756: for (i = 1; i < argc; i++) ! 757: if (pend_undefs[i]) ! 758: make_undef (pend_undefs[i]); ! 759: ! 760: /* Unless -fnostdinc, ! 761: tack on the standard include file dirs to the specified list */ ! 762: if (!no_standard_includes) { ! 763: if (include == 0) ! 764: include = include_defaults; ! 765: else ! 766: last_include->next = include_defaults; ! 767: } ! 768: ! 769: /* Initialize output buffer */ ! 770: ! 771: outbuf.buf = (U_CHAR *) xmalloc (OUTBUF_SIZE); ! 772: outbuf.bufp = outbuf.buf; ! 773: outbuf.length = OUTBUF_SIZE; ! 774: ! 775: /* Scan the -i files before the main input. ! 776: Much like #including them, but with no_output set ! 777: so that only their macro definitions matter. */ ! 778: ! 779: no_output++; ! 780: for (i = 1; i < argc; i++) ! 781: if (pend_files[i]) { ! 782: int fd = open (pend_files[i], O_RDONLY, 0666); ! 783: if (fd < 0) { ! 784: perror_with_name (pend_files[i]); ! 785: return FATAL_EXIT_CODE; ! 786: } ! 787: finclude (fd, pend_files[i], &outbuf); ! 788: } ! 789: no_output--; ! 790: ! 791: /* Create an input stack level for the main input file ! 792: and copy the entire contents of the file into it. */ ! 793: ! 794: fp = &instack[++indepth]; ! 795: ! 796: /* JF check for stdin */ ! 797: if (in_fname == NULL || *in_fname == 0) { ! 798: in_fname = ""; ! 799: f = 0; ! 800: } else if ((f = open (in_fname, O_RDONLY)) < 0) ! 801: goto perror; ! 802: ! 803: /* For -M, print the expected object file name ! 804: as the target of this Make-rule. */ ! 805: if (print_deps) { ! 806: if (*in_fname == 0) ! 807: deps_output ("-: ", 0); ! 808: else { ! 809: int len; ! 810: char *p = in_fname; ! 811: char *p1 = p; ! 812: /* Discard all directory prefixes from P. */ ! 813: while (*p1) ! 814: { ! 815: if (*p1 == '/') ! 816: p = p1; ! 817: p1++; ! 818: } ! 819: /* Output P, but remove known suffixes. */ ! 820: len = strlen (p); ! 821: if (p[len - 2] == '.' && p[len - 1] == 'c') ! 822: deps_output (p, len - 2); ! 823: else if (p[len - 3] == '.' ! 824: && p[len - 2] == 'c' ! 825: && p[len - 1] == 'c') ! 826: deps_output (p, len - 3); ! 827: else ! 828: deps_output (p, 0); ! 829: /* Supply our own suffix. */ ! 830: deps_output (".o : ", 0); ! 831: deps_output (in_fname, 0); ! 832: deps_output (" ", 0); ! 833: } ! 834: } ! 835: ! 836: file_size_and_mode (f, &st_mode, &st_size); ! 837: fp->fname = in_fname; ! 838: fp->lineno = 1; ! 839: /* JF all this is mine about reading pipes and ttys */ ! 840: if ((st_mode & S_IFMT) != S_IFREG) { ! 841: /* Read input from a file that is not a normal disk file. ! 842: We cannot preallocate a buffer with the correct size, ! 843: so we must read in the file a piece at the time and make it bigger. */ ! 844: int size; ! 845: int bsize; ! 846: int cnt; ! 847: U_CHAR *bufp; ! 848: ! 849: bsize = 2000; ! 850: size = 0; ! 851: fp->buf = (U_CHAR *) xmalloc (bsize + 2); ! 852: bufp = fp->buf; ! 853: for (;;) { ! 854: cnt = read (f, bufp, bsize - size); ! 855: if (cnt < 0) goto perror; /* error! */ ! 856: if (cnt == 0) break; /* End of file */ ! 857: size += cnt; ! 858: bufp += cnt; ! 859: if (bsize == size) { /* Buffer is full! */ ! 860: bsize *= 2; ! 861: fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2); ! 862: bufp = fp->buf + size; /* May have moved */ ! 863: } ! 864: } ! 865: fp->length = size; ! 866: } else { ! 867: /* Read a file whose size we can determine in advance. ! 868: For the sake of VMS, st_size is just an upper bound. */ ! 869: long i; ! 870: fp->length = 0; ! 871: fp->buf = (U_CHAR *) xmalloc (st_size + 2); ! 872: ! 873: while (st_size > 0) { ! 874: i = read (f, fp->buf + fp->length, st_size); ! 875: if (i <= 0) { ! 876: if (i == 0) break; ! 877: goto perror; ! 878: } ! 879: fp->length += i; ! 880: st_size -= i; ! 881: } ! 882: } ! 883: fp->bufp = fp->buf; ! 884: fp->if_stack = if_stack; ! 885: ! 886: /* Unless inhibited, convert trigraphs in the input. */ ! 887: ! 888: if (!no_trigraphs) ! 889: trigraph_pcp (fp); ! 890: ! 891: /* Make sure data ends with a newline. And put a null after it. */ ! 892: ! 893: if (fp->length > 0 && fp->buf[fp->length-1] != '\n') ! 894: fp->buf[fp->length++] = '\n'; ! 895: fp->buf[fp->length] = '\0'; ! 896: ! 897: output_line_command (fp, &outbuf, 0); ! 898: ! 899: /* Scan the input, processing macros and directives. */ ! 900: ! 901: rescan (&outbuf, 0); ! 902: ! 903: /* Now we have processed the entire input ! 904: Write whichever kind of output has been requested. */ ! 905: ! 906: ! 907: if (dump_macros) ! 908: dump_all_macros (); ! 909: else if (print_deps) ! 910: puts (deps_buffer); ! 911: else if (write (fileno (stdout), outbuf.buf, outbuf.bufp - outbuf.buf) < 0) ! 912: fatal ("I/O error on output"); ! 913: ! 914: if (ferror (stdout)) ! 915: fatal ("I/O error on output"); ! 916: ! 917: if (errors) ! 918: exit (FATAL_EXIT_CODE); ! 919: exit (SUCCESS_EXIT_CODE); ! 920: ! 921: perror: ! 922: pfatal_with_name (in_fname); ! 923: } ! 924: ! 925: /* Pre-C-Preprocessor to translate ANSI trigraph idiocy in BUF ! 926: before main CCCP processing. Name `pcp' is also in honor of the ! 927: drugs the trigraph designers must have been on. ! 928: ! 929: Using an extra pass through the buffer takes a little extra time, ! 930: but is infinitely less hairy than trying to handle ??/" inside ! 931: strings, etc. everywhere, and also makes sure that trigraphs are ! 932: only translated in the top level of processing. */ ! 933: ! 934: trigraph_pcp (buf) ! 935: FILE_BUF *buf; ! 936: { ! 937: register U_CHAR c, *fptr, *bptr, *sptr; ! 938: int len; ! 939: ! 940: fptr = bptr = sptr = buf->buf; ! 941: while ((sptr = (U_CHAR *) index (sptr, '?')) != NULL) { ! 942: if (*++sptr != '?') ! 943: continue; ! 944: switch (*++sptr) { ! 945: case '=': ! 946: c = '#'; ! 947: break; ! 948: case '(': ! 949: c = '['; ! 950: break; ! 951: case '/': ! 952: c = '\\'; ! 953: break; ! 954: case ')': ! 955: c = ']'; ! 956: break; ! 957: case '\'': ! 958: c = '^'; ! 959: break; ! 960: case '<': ! 961: c = '{'; ! 962: break; ! 963: case '!': ! 964: c = '|'; ! 965: break; ! 966: case '>': ! 967: c = '}'; ! 968: break; ! 969: case '-': ! 970: c = '~'; ! 971: break; ! 972: case '?': ! 973: sptr--; ! 974: continue; ! 975: default: ! 976: continue; ! 977: } ! 978: len = sptr - fptr - 2; ! 979: if (bptr != fptr && len > 0) ! 980: bcopy (fptr, bptr, len); /* BSD doc says bcopy () works right ! 981: for overlapping strings. In ANSI ! 982: C, this will be memmove (). */ ! 983: bptr += len; ! 984: *bptr++ = c; ! 985: fptr = ++sptr; ! 986: } ! 987: len = buf->length - (fptr - buf->buf); ! 988: if (bptr != fptr && len > 0) ! 989: bcopy (fptr, bptr, len); ! 990: buf->length -= fptr - bptr; ! 991: buf->buf[buf->length] = '\0'; ! 992: } ! 993: ! 994: /* Move all backslash-newline pairs out of embarrassing places. ! 995: Exchange all such pairs following BP ! 996: with any potentially-embarrasing characters that follow them. ! 997: Potentially-embarrassing characters are / and * ! 998: (because a backslash-newline inside a comment delimiter ! 999: would cause it not to be recognized). */ ! 1000: ! 1001: newline_fix (bp) ! 1002: U_CHAR *bp; ! 1003: { ! 1004: register U_CHAR *p = bp; ! 1005: register int count = 0; ! 1006: ! 1007: /* First count the backslash-newline pairs here. */ ! 1008: ! 1009: while (*p++ == '\\' && *p++ == '\n') ! 1010: count++; ! 1011: ! 1012: p = bp + count * 2; ! 1013: ! 1014: /* What follows the backslash-newlines is not embarrassing. */ ! 1015: ! 1016: if (count == 0 || (*p != '/' && *p != '*')) ! 1017: return; ! 1018: ! 1019: /* Copy all potentially embarrassing characters ! 1020: that follow the backslash-newline pairs ! 1021: down to where the pairs originally started. */ ! 1022: ! 1023: while (*p == '*' || *p == '/') ! 1024: *bp++ = *p++; ! 1025: ! 1026: /* Now write the same number of pairs after the embarrassing chars. */ ! 1027: while (count-- > 0) { ! 1028: *bp++ = '\\'; ! 1029: *bp++ = '\n'; ! 1030: } ! 1031: } ! 1032: ! 1033: /* Like newline_fix but for use within a directive-name. ! 1034: Move any backslash-newlines up past any following symbol constituents. */ ! 1035: ! 1036: name_newline_fix (bp) ! 1037: U_CHAR *bp; ! 1038: { ! 1039: register U_CHAR *p = bp; ! 1040: register int count = 0; ! 1041: ! 1042: /* First count the backslash-newline pairs here. */ ! 1043: ! 1044: while (*p++ == '\\' && *p++ == '\n') ! 1045: count++; ! 1046: ! 1047: p = bp + count * 2; ! 1048: ! 1049: /* What follows the backslash-newlines is not embarrassing. */ ! 1050: ! 1051: if (count == 0 || !is_idchar[*p]) ! 1052: return; ! 1053: ! 1054: /* Copy all potentially embarrassing characters ! 1055: that follow the backslash-newline pairs ! 1056: down to where the pairs originally started. */ ! 1057: ! 1058: while (is_idchar[*p]) ! 1059: *bp++ = *p++; ! 1060: ! 1061: /* Now write the same number of pairs after the embarrassing chars. */ ! 1062: while (count-- > 0) { ! 1063: *bp++ = '\\'; ! 1064: *bp++ = '\n'; ! 1065: } ! 1066: } ! 1067: ! 1068: /* ! 1069: * The main loop of the program. ! 1070: * ! 1071: * Read characters from the input stack, transferring them to the ! 1072: * output buffer OP. ! 1073: * ! 1074: * Macros are expanded and push levels on the input stack. ! 1075: * At the end of such a level it is popped off and we keep reading. ! 1076: * At the end of any other kind of level, we return. ! 1077: * #-directives are handled, except within macros. ! 1078: * ! 1079: * If OUTPUT_MARKS is nonzero, keep Newline markers found in the input ! 1080: * and insert them when appropriate. This is set while scanning macro ! 1081: * arguments before substitution. It is zero when scanning for final output. ! 1082: * There are three types of Newline markers: ! 1083: * * Newline - follows a macro name that was not expanded ! 1084: * because it appeared inside an expansion of the same macro. ! 1085: * This marker prevents future expansion of that identifier. ! 1086: * When the input is rescanned into the final output, these are deleted. ! 1087: * These are also deleted by ## concatenation. ! 1088: * * Newline Space (or Newline and any other whitespace character) ! 1089: * stands for a place that tokens must be separated or whitespace ! 1090: * is otherwise desirable, but where the ANSI standard specifies there ! 1091: * is no whitespace. This marker turns into a Space (or whichever other ! 1092: * whitespace char appears in the marker) in the final output, ! 1093: * but it turns into nothing in an argument that is stringified with #. ! 1094: * Such stringified arguments are the only place where the ANSI standard ! 1095: * specifies with precision that whitespace may not appear. ! 1096: * ! 1097: * During this function, IP->bufp is kept cached in IBP for speed of access. ! 1098: * Likewise, OP->bufp is kept in OBP. Before calling a subroutine ! 1099: * IBP, IP and OBP must be copied back to memory. IP and IBP are ! 1100: * copied back with the RECACHE macro. OBP must be copied back from OP->bufp ! 1101: * explicitly, and before RECACHE, since RECACHE uses OBP. ! 1102: */ ! 1103: ! 1104: rescan (op, output_marks) ! 1105: FILE_BUF *op; ! 1106: int output_marks; ! 1107: { ! 1108: /* Character being scanned in main loop. */ ! 1109: register U_CHAR c; ! 1110: ! 1111: /* Length of pending accumulated identifier. */ ! 1112: register int ident_length = 0; ! 1113: ! 1114: /* Hash code of pending accumulated identifier. */ ! 1115: register int hash = 0; ! 1116: ! 1117: /* Current input level (&instack[indepth]). */ ! 1118: FILE_BUF *ip; ! 1119: ! 1120: /* Pointer for scanning input. */ ! 1121: register U_CHAR *ibp; ! 1122: ! 1123: /* Pointer to end of input. End of scan is controlled by LIMIT. */ ! 1124: register U_CHAR *limit; ! 1125: ! 1126: /* Pointer for storing output. */ ! 1127: register U_CHAR *obp; ! 1128: ! 1129: /* REDO_CHAR is nonzero if we are processing an identifier ! 1130: after backing up over the terminating character. ! 1131: Sometimes we process an identifier without backing up over ! 1132: the terminating character, if the terminating character ! 1133: is not special. Backing up is done so that the terminating character ! 1134: will be dispatched on again once the identifier is dealt with. */ ! 1135: int redo_char = 0; ! 1136: ! 1137: /* 1 if within an identifier inside of which a concatenation ! 1138: marker (Newline -) has been seen. */ ! 1139: int concatenated = 0; ! 1140: ! 1141: /* While scanning a comment or a string constant, ! 1142: this records the line it started on, for error messages. */ ! 1143: int start_line; ! 1144: ! 1145: /* Record position of last `real' newline. */ ! 1146: U_CHAR *beg_of_line; ! 1147: ! 1148: /* Pop the innermost input stack level, assuming it is a macro expansion. */ ! 1149: ! 1150: #define POPMACRO \ ! 1151: do { ip->macro->type = T_MACRO; \ ! 1152: if (ip->free) free (ip->free); \ ! 1153: --indepth; } while (0) ! 1154: ! 1155: /* Reload `rescan's local variables that describe the current ! 1156: level of the input stack. */ ! 1157: ! 1158: #define RECACHE \ ! 1159: do { ip = &instack[indepth]; \ ! 1160: ibp = ip->bufp; \ ! 1161: limit = ip->buf + ip->length; \ ! 1162: op->bufp = obp; \ ! 1163: check_expand (op, limit - ibp); \ ! 1164: beg_of_line = 0; \ ! 1165: obp = op->bufp; } while (0) ! 1166: ! 1167: if (no_output && instack[indepth].fname != 0) ! 1168: skip_if_group (&instack[indepth], 1); ! 1169: ! 1170: obp = op->bufp; ! 1171: RECACHE; ! 1172: beg_of_line = ibp; ! 1173: ! 1174: /* Our caller must always put a null after the end of ! 1175: the input at each input stack level. */ ! 1176: if (*limit != 0) ! 1177: abort (); ! 1178: ! 1179: while (1) { ! 1180: c = *ibp++; ! 1181: *obp++ = c; ! 1182: ! 1183: switch (c) { ! 1184: case '\\': ! 1185: if (ibp >= limit) ! 1186: break; ! 1187: if (*ibp == '\n') { ! 1188: /* Always merge lines ending with backslash-newline, ! 1189: even in middle of identifier. */ ! 1190: ++ibp; ! 1191: ++ip->lineno; ! 1192: --obp; /* remove backslash from obuf */ ! 1193: break; ! 1194: } ! 1195: /* Otherwise, backslash suppresses specialness of following char, ! 1196: so copy it here to prevent the switch from seeing it. ! 1197: But first get any pending identifier processed. */ ! 1198: if (ident_length > 0) ! 1199: goto specialchar; ! 1200: *obp++ = *ibp++; ! 1201: break; ! 1202: ! 1203: case '#': ! 1204: /* If this is expanding a macro definition, don't recognize ! 1205: preprocessor directives. */ ! 1206: if (ip->macro != 0) ! 1207: goto randomchar; ! 1208: if (ident_length) ! 1209: goto specialchar; ! 1210: ! 1211: /* # keyword: a # must be first nonblank char on the line */ ! 1212: if (beg_of_line == 0) ! 1213: goto randomchar; ! 1214: { ! 1215: U_CHAR *bp; ! 1216: ! 1217: /* Scan from start of line, skipping whitespace, comments ! 1218: and backslash-newlines, and see if we reach this #. ! 1219: If not, this # is not special. */ ! 1220: bp = beg_of_line; ! 1221: while (1) { ! 1222: if (is_hor_space[*bp]) ! 1223: bp++; ! 1224: else if (*bp == '\\' && bp[1] == '\n') ! 1225: bp += 2; ! 1226: else if (*bp == '/' && bp[1] == '*') { ! 1227: bp += 2; ! 1228: while (!(*bp == '*' && bp[1] == '/')) ! 1229: bp++; ! 1230: bp += 2; ! 1231: } ! 1232: #ifdef CPLUSPLUS ! 1233: else if (*bp == '/' && bp[1] == '/') { ! 1234: bp += 2; ! 1235: while (*bp++ != '\n') ; ! 1236: } ! 1237: #endif ! 1238: else break; ! 1239: } ! 1240: if (bp + 1 != ibp) ! 1241: goto randomchar; ! 1242: } ! 1243: ! 1244: /* This # can start a directive. */ ! 1245: ! 1246: --obp; /* Don't copy the '#' */ ! 1247: ! 1248: ip->bufp = ibp; ! 1249: op->bufp = obp; ! 1250: if (! handle_directive (ip, op)) { ! 1251: /* Not a known directive: treat it as ordinary text. ! 1252: IP, OP, IBP, etc. have not been changed. */ ! 1253: if (no_output && instack[indepth].fname) { ! 1254: /* If not generating expanded output, ! 1255: what we do with ordinary text is skip it. ! 1256: Discard everything until next # directive. */ ! 1257: skip_if_group (&instack[indepth], 1); ! 1258: RECACHE; ! 1259: beg_of_line = ibp; ! 1260: break; ! 1261: } ! 1262: ++obp; /* Copy the '#' after all */ ! 1263: goto randomchar; ! 1264: } ! 1265: /* A # directive has been successfully processed. */ ! 1266: /* If not generating expanded output, ignore everything until ! 1267: next # directive. */ ! 1268: if (no_output && instack[indepth].fname) ! 1269: skip_if_group (&instack[indepth], 1); ! 1270: obp = op->bufp; ! 1271: RECACHE; ! 1272: beg_of_line = ibp; ! 1273: break; ! 1274: ! 1275: case '\"': /* skip quoted string */ ! 1276: case '\'': ! 1277: /* A single quoted string is treated like a double -- some ! 1278: programs (e.g., troff) are perverse this way */ ! 1279: ! 1280: if (ident_length) ! 1281: goto specialchar; ! 1282: ! 1283: start_line = ip->lineno; ! 1284: ! 1285: /* Skip ahead to a matching quote. */ ! 1286: ! 1287: while (1) { ! 1288: if (ibp >= limit) ! 1289: { ! 1290: error_with_line (line_for_error (start_line), ! 1291: "unterminated string constant"); ! 1292: break; ! 1293: } ! 1294: *obp++ = *ibp; ! 1295: switch (*ibp++) { ! 1296: case '\n': ! 1297: ++ip->lineno; ! 1298: ++op->lineno; ! 1299: break; ! 1300: ! 1301: case '\\': ! 1302: if (ibp >= limit) ! 1303: break; ! 1304: if (*ibp == '\n') ! 1305: { ! 1306: /* Backslash newline is replaced by nothing at all, ! 1307: but keep the line counts correct. */ ! 1308: --obp; ! 1309: ++ibp; ! 1310: ++ip->lineno; ! 1311: } ! 1312: else { ! 1313: /* ANSI stupidly requires that in \\ the second \ ! 1314: is *not* prevented from combining with a newline. */ ! 1315: while (*ibp == '\\' && ibp[1] == '\n') { ! 1316: ibp += 2; ! 1317: ++ip->lineno; ! 1318: } ! 1319: *obp++ = *ibp++; ! 1320: } ! 1321: break; ! 1322: ! 1323: case '\"': ! 1324: case '\'': ! 1325: if (ibp[-1] == c) ! 1326: goto while2end; ! 1327: break; ! 1328: } ! 1329: } ! 1330: while2end: ! 1331: break; ! 1332: ! 1333: case '/': ! 1334: if (*ibp == '\\' && ibp[1] == '\n') ! 1335: newline_fix (ibp); ! 1336: #ifdef CPLUSPLUS ! 1337: if (*ibp == '/') ! 1338: { ! 1339: /* C++ style comment... */ ! 1340: start_line = ip->lineno; ! 1341: ! 1342: --ibp; /* Back over the slash */ ! 1343: --obp; ! 1344: ! 1345: /* Comments are equivalent to spaces. */ ! 1346: if (! put_out_comments) ! 1347: *obp++ = ' '; ! 1348: else { ! 1349: /* must fake up a comment here */ ! 1350: *obp++ = '/'; ! 1351: *obp++ = '/'; ! 1352: } ! 1353: { ! 1354: U_CHAR *before_bp = ibp+2; ! 1355: ! 1356: while (ibp < limit) { ! 1357: if (*ibp++ == '\n') { ! 1358: ibp--; ! 1359: if (put_out_comments) { ! 1360: bcopy (before_bp, obp, ibp - before_bp); ! 1361: obp += ibp - before_bp; ! 1362: } ! 1363: break; ! 1364: } ! 1365: } ! 1366: break; ! 1367: } ! 1368: } ! 1369: #endif ! 1370: if (*ibp != '*') ! 1371: goto randomchar; ! 1372: if (ip->macro != 0) ! 1373: goto randomchar; ! 1374: if (ident_length) ! 1375: goto specialchar; ! 1376: ! 1377: /* We have a comment. Skip it, optionally copying it to output. */ ! 1378: ! 1379: start_line = ip->lineno; ! 1380: ! 1381: ++ibp; /* Skip the star. */ ! 1382: ! 1383: /* Comments are equivalent to spaces. ! 1384: Note that we already output the slash; we might not want it. ! 1385: For -traditional, a comment is equivalent to nothing. */ ! 1386: if (! put_out_comments) ! 1387: { ! 1388: if (traditional) ! 1389: obp--; ! 1390: else ! 1391: obp[-1] = ' '; ! 1392: } ! 1393: else ! 1394: *obp++ = '*'; ! 1395: ! 1396: { ! 1397: U_CHAR *before_bp = ibp; ! 1398: ! 1399: while (ibp < limit) { ! 1400: switch (*ibp++) { ! 1401: case '/': ! 1402: if (warn_comments && ibp < limit && *ibp == '*') ! 1403: warning("`/*' within comment"); ! 1404: break; ! 1405: case '*': ! 1406: if (*ibp == '\\' && ibp[1] == '\n') ! 1407: newline_fix (ibp); ! 1408: if (ibp >= limit || *ibp == '/') ! 1409: goto comment_end; ! 1410: break; ! 1411: case '\n': ! 1412: ++ip->lineno; ! 1413: /* Copy the newline into the output buffer, in order to ! 1414: avoid the pain of a #line every time a multiline comment ! 1415: is seen. */ ! 1416: if (!put_out_comments) ! 1417: *obp++ = '\n'; ! 1418: ++op->lineno; ! 1419: } ! 1420: } ! 1421: comment_end: ! 1422: ! 1423: if (ibp >= limit) ! 1424: error_with_line (line_for_error (start_line), ! 1425: "unterminated comment"); ! 1426: else { ! 1427: ibp++; ! 1428: if (put_out_comments) { ! 1429: bcopy (before_bp, obp, ibp - before_bp); ! 1430: obp += ibp - before_bp; ! 1431: } ! 1432: } ! 1433: } ! 1434: break; ! 1435: ! 1436: case '$': ! 1437: if (pedantic) ! 1438: { ! 1439: if (! dollar_seen) ! 1440: warning ("ANSI C forbids `$' in identifier (first use here)"); ! 1441: dollar_seen = 1; ! 1442: } ! 1443: goto letter; ! 1444: ! 1445: case '0': case '1': case '2': case '3': case '4': ! 1446: case '5': case '6': case '7': case '8': case '9': ! 1447: /* If digit is not part of identifier, it starts a number, ! 1448: which means that following letters are not an identifier. ! 1449: "0x5" does not refer to an identifier "x5". ! 1450: So copy all alphanumerics that follow without accumulating ! 1451: as an identifier. Periods also, for sake of "3.e7". */ ! 1452: ! 1453: if (ident_length == 0) { ! 1454: while (ibp < limit) { ! 1455: c = *ibp++; ! 1456: if (!isalnum (c) && c != '.') { ! 1457: --ibp; ! 1458: break; ! 1459: } ! 1460: *obp++ = c; ! 1461: } ! 1462: break; ! 1463: } ! 1464: /* fall through */ ! 1465: ! 1466: case '_': ! 1467: case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': ! 1468: case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': ! 1469: case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': ! 1470: case 's': case 't': case 'u': case 'v': case 'w': case 'x': ! 1471: case 'y': case 'z': ! 1472: case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': ! 1473: case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': ! 1474: case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': ! 1475: case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': ! 1476: case 'Y': case 'Z': ! 1477: letter: ! 1478: ident_length++; ! 1479: /* Compute step of hash function, to avoid a proc call on every token */ ! 1480: hash = HASHSTEP (hash, c); ! 1481: break; ! 1482: ! 1483: case '\n': ! 1484: /* If reprocessing a macro expansion, newline is a special marker. */ ! 1485: if (ip->macro != 0) { ! 1486: /* Newline White is a "funny space" to separate tokens that are ! 1487: supposed to be separate but without space between. ! 1488: Here While means any horizontal whitespace character. ! 1489: Newline - marks a recursive macro use that is not ! 1490: supposed to be expandable. */ ! 1491: ! 1492: if (*ibp == '-') { ! 1493: /* Newline - inhibits expansion of preceding token. ! 1494: If expanding a macro arg, we keep the newline -. ! 1495: In final output, it is deleted. */ ! 1496: if (! concatenated) { ! 1497: ident_length = 0; ! 1498: hash = 0; ! 1499: } ! 1500: ibp++; ! 1501: if (!output_marks) { ! 1502: obp--; ! 1503: } else { ! 1504: /* If expanding a macro arg, keep the newline -. */ ! 1505: *obp++ = '-'; ! 1506: } ! 1507: } else if (is_space[*ibp]) { ! 1508: /* Newline Space does not prevent expansion of preceding token ! 1509: so expand the preceding token and then come back. */ ! 1510: if (ident_length > 0) ! 1511: goto specialchar; ! 1512: ! 1513: /* If generating final output, newline space makes a space. */ ! 1514: if (!output_marks) { ! 1515: obp[-1] = *ibp++; ! 1516: /* And Newline Newline makes a newline, so count it. */ ! 1517: if (obp[-1] == '\n') ! 1518: op->lineno++; ! 1519: } else { ! 1520: /* If expanding a macro arg, keep the newline space. ! 1521: If the arg gets stringified, newline space makes nothing. */ ! 1522: *obp++ = *ibp++; ! 1523: } ! 1524: } else abort (); /* Newline followed by something random? */ ! 1525: break; ! 1526: } ! 1527: ! 1528: /* If there is a pending identifier, handle it and come back here. */ ! 1529: if (ident_length > 0) ! 1530: goto specialchar; ! 1531: ! 1532: beg_of_line = ibp; ! 1533: ! 1534: /* Update the line counts and output a #line if necessary. */ ! 1535: ++ip->lineno; ! 1536: ++op->lineno; ! 1537: if (ip->lineno != op->lineno) { ! 1538: op->bufp = obp; ! 1539: output_line_command (ip, op, 1); ! 1540: check_expand (op, ip->length - (ip->bufp - ip->buf)); ! 1541: obp = op->bufp; ! 1542: } ! 1543: break; ! 1544: ! 1545: /* Come here either after (1) a null character that is part of the input ! 1546: or (2) at the end of the input, because there is a null there. */ ! 1547: case 0: ! 1548: if (ibp <= limit) ! 1549: /* Our input really contains a null character. */ ! 1550: goto randomchar; ! 1551: ! 1552: /* At end of a macro-expansion level, pop it and read next level. */ ! 1553: if (ip->macro != 0) { ! 1554: obp--; ! 1555: ibp--; ! 1556: POPMACRO; ! 1557: RECACHE; ! 1558: break; ! 1559: } ! 1560: ! 1561: /* If we don't have a pending identifier, ! 1562: return at end of input. */ ! 1563: if (ident_length == 0) ! 1564: { ! 1565: obp--; ! 1566: ibp--; ! 1567: op->bufp = obp; ! 1568: ip->bufp = ibp; ! 1569: goto ending; ! 1570: } ! 1571: ! 1572: /* If we do have a pending identifier, just consider this null ! 1573: a special character and arrange to dispatch on it again. ! 1574: The second time, IDENT_LENGTH will be zero so we will return. */ ! 1575: ! 1576: /* Fall through */ ! 1577: ! 1578: specialchar: ! 1579: ! 1580: /* Handle the case of a character such as /, ', " or null ! 1581: seen following an identifier. Back over it so that ! 1582: after the identifier is processed the special char ! 1583: will be dispatched on again. */ ! 1584: ! 1585: ibp--; ! 1586: obp--; ! 1587: redo_char = 1; ! 1588: ! 1589: default: ! 1590: ! 1591: randomchar: ! 1592: ! 1593: if (ident_length > 0) { ! 1594: register HASHNODE *hp; ! 1595: ! 1596: /* We have just seen an identifier end. If it's a macro, expand it. ! 1597: ! 1598: IDENT_LENGTH is the length of the identifier ! 1599: and HASH is its hash code. ! 1600: ! 1601: The identifier has already been copied to the output, ! 1602: so if it is a macro we must remove it. ! 1603: ! 1604: If REDO_CHAR is 0, the char that terminated the identifier ! 1605: has been skipped in the output and the input. ! 1606: OBP-IDENT_LENGTH-1 points to the identifier. ! 1607: If the identifier is a macro, we must back over the terminator. ! 1608: ! 1609: If REDO_CHAR is 1, the terminating char has already been ! 1610: backed over. OBP-IDENT_LENGTH points to the identifier. */ ! 1611: ! 1612: for (hp = hashtab[MAKE_POS (hash) % HASHSIZE]; hp != NULL; ! 1613: hp = hp->next) { ! 1614: ! 1615: if (hp->length == ident_length) { ! 1616: U_CHAR *obufp_before_macroname; ! 1617: int op_lineno_before_macroname; ! 1618: register int i = ident_length; ! 1619: register U_CHAR *p = hp->name; ! 1620: register U_CHAR *q = obp - i; ! 1621: int disabled; ! 1622: ! 1623: if (! redo_char) ! 1624: q--; ! 1625: ! 1626: do { /* All this to avoid a strncmp () */ ! 1627: if (*p++ != *q++) ! 1628: goto hashcollision; ! 1629: } while (--i); ! 1630: ! 1631: /* We found a use of a macro name. ! 1632: see if the context shows it is a macro call. */ ! 1633: ! 1634: /* Back up over terminating character if not already done. */ ! 1635: if (! redo_char) ! 1636: { ! 1637: ibp--; ! 1638: obp--; ! 1639: } ! 1640: ! 1641: obufp_before_macroname = obp - ident_length; ! 1642: op_lineno_before_macroname = op->lineno; ! 1643: ! 1644: /* Record whether the macro is disabled. */ ! 1645: disabled = hp->type == T_DISABLED; ! 1646: ! 1647: /* This looks like a macro ref, but if the macro was disabled, ! 1648: just copy its name and put in a marker if requested. */ ! 1649: ! 1650: if (disabled) ! 1651: { ! 1652: if (output_marks) { ! 1653: check_expand (op, limit - ibp + 2); ! 1654: *obp++ = '\n'; ! 1655: *obp++ = '-'; ! 1656: } ! 1657: break; ! 1658: } ! 1659: ! 1660: /* If macro wants an arglist, verify that a '(' follows. ! 1661: first skip all whitespace, copying it to the output ! 1662: after the macro name. Then, if there is no '(', ! 1663: decide this is not a macro call and leave things that way. */ ! 1664: if ((hp->type == T_MACRO || hp->type == T_DISABLED) ! 1665: && hp->value.defn->nargs >= 0) ! 1666: { ! 1667: while (1) { ! 1668: /* Scan forward over whitespace, copying it to the output. */ ! 1669: if (ibp == limit && ip->macro != 0) { ! 1670: POPMACRO; ! 1671: RECACHE; ! 1672: } ! 1673: else if (is_space[*ibp]) { ! 1674: *obp++ = *ibp++; ! 1675: if (ibp[-1] == '\n') ! 1676: { ! 1677: if (ip->macro == 0) { ! 1678: /* Newline in a file. Count it. */ ! 1679: ++ip->lineno; ! 1680: ++op->lineno; ! 1681: } else if (!output_marks) { ! 1682: /* A newline mark, and we don't want marks ! 1683: in the output. If it is newline-hyphen, ! 1684: discard it entirely. Otherwise, it is ! 1685: newline-whitechar, so keep the whitechar. */ ! 1686: obp--; ! 1687: if (*ibp == '-') ! 1688: ibp++; ! 1689: else { ! 1690: if (*ibp == '\n') ! 1691: ++op->lineno; ! 1692: *obp++ = *ibp++; ! 1693: } ! 1694: } else { ! 1695: /* A newline mark; copy both chars to the output. */ ! 1696: *obp++ = *ibp++; ! 1697: } ! 1698: } ! 1699: } ! 1700: else break; ! 1701: } ! 1702: if (*ibp != '(') ! 1703: break; ! 1704: } ! 1705: ! 1706: /* This is now known to be a macro call. ! 1707: Discard the macro name from the output, ! 1708: along with any following whitespace just copied. */ ! 1709: obp = obufp_before_macroname; ! 1710: op->lineno = op_lineno_before_macroname; ! 1711: ! 1712: /* Expand the macro, reading arguments as needed, ! 1713: and push the expansion on the input stack. */ ! 1714: ip->bufp = ibp; ! 1715: op->bufp = obp; ! 1716: macroexpand (hp, op); ! 1717: ! 1718: /* Reexamine input stack, since macroexpand has pushed ! 1719: a new level on it. */ ! 1720: obp = op->bufp; ! 1721: RECACHE; ! 1722: break; ! 1723: } ! 1724: hashcollision: ! 1725: ; ! 1726: } /* End hash-table-search loop */ ! 1727: ident_length = hash = 0; /* Stop collecting identifier */ ! 1728: redo_char = 0; ! 1729: concatenated = 0; ! 1730: } /* End if (ident_length > 0) */ ! 1731: } /* End switch */ ! 1732: } /* End per-char loop */ ! 1733: ! 1734: /* Come here to return -- but first give an error message ! 1735: if there was an unterminated successful conditional. */ ! 1736: ending: ! 1737: if (if_stack != ip->if_stack) { ! 1738: char *str; ! 1739: switch (if_stack->type) { ! 1740: case T_IF: ! 1741: str = "if"; ! 1742: break; ! 1743: case T_IFDEF: ! 1744: str = "ifdef"; ! 1745: break; ! 1746: case T_IFNDEF: ! 1747: str = "ifndef"; ! 1748: break; ! 1749: case T_ELSE: ! 1750: str = "else"; ! 1751: break; ! 1752: case T_ELIF: ! 1753: str = "elif"; ! 1754: break; ! 1755: } ! 1756: error_with_line (line_for_error (if_stack->lineno), ! 1757: "unterminated #%s conditional", str); ! 1758: } ! 1759: if_stack = ip->if_stack; ! 1760: } ! 1761: ! 1762: /* ! 1763: * Rescan a string into a temporary buffer and return the result ! 1764: * as a FILE_BUF. Note this function returns a struct, not a pointer. ! 1765: * ! 1766: * OUTPUT_MARKS nonzero means keep Newline markers found in the input ! 1767: * and insert such markers when appropriate. See `rescan' for details. ! 1768: * OUTPUT_MARKS is 1 for macroexpanding a macro argument separately ! 1769: * before substitution; it is 0 for other uses. ! 1770: */ ! 1771: static FILE_BUF ! 1772: expand_to_temp_buffer (buf, limit, output_marks) ! 1773: U_CHAR *buf, *limit; ! 1774: int output_marks; ! 1775: { ! 1776: register FILE_BUF *ip; ! 1777: FILE_BUF obuf; ! 1778: int length = limit - buf; ! 1779: U_CHAR *buf1; ! 1780: int odepth = indepth; ! 1781: ! 1782: if (length < 0) ! 1783: abort (); ! 1784: ! 1785: /* Set up the input on the input stack. */ ! 1786: ! 1787: buf1 = (U_CHAR *) alloca (length + 1); ! 1788: { ! 1789: register U_CHAR *p1 = buf; ! 1790: register U_CHAR *p2 = buf1; ! 1791: ! 1792: while (p1 != limit) ! 1793: *p2++ = *p1++; ! 1794: } ! 1795: buf1[length] = 0; ! 1796: ! 1797: ++indepth; ! 1798: ! 1799: ip = &instack[indepth]; ! 1800: ip->fname = 0; ! 1801: ip->macro = 0; ! 1802: ip->free = 0; ! 1803: ip->length = length; ! 1804: ip->buf = ip->bufp = buf1; ! 1805: ip->if_stack = if_stack; ! 1806: ! 1807: /* Set up to receive the output. */ ! 1808: ! 1809: obuf.length = length * 2 + 100; /* Usually enough. Why be stingy? */ ! 1810: obuf.bufp = obuf.buf = (U_CHAR *) xmalloc (obuf.length); ! 1811: obuf.fname = 0; ! 1812: obuf.macro = 0; ! 1813: obuf.free = 0; ! 1814: ! 1815: ip->lineno = obuf.lineno = 1; ! 1816: ! 1817: /* Scan the input, create the output. */ ! 1818: ! 1819: rescan (&obuf, output_marks); ! 1820: ! 1821: /* Pop input stack to original state. */ ! 1822: --indepth; ! 1823: ! 1824: if (indepth != odepth) ! 1825: abort (); ! 1826: ! 1827: /* Record the output. */ ! 1828: obuf.length = obuf.bufp - obuf.buf; ! 1829: ! 1830: return obuf; ! 1831: } ! 1832: ! 1833: /* ! 1834: * Process a # directive. Expects IP->bufp to point to the '#', as in ! 1835: * `#define foo bar'. Passes to the command handler ! 1836: * (do_define, do_include, etc.): the addresses of the 1st and ! 1837: * last chars of the command (starting immediately after the # ! 1838: * keyword), plus op and the keyword table pointer. If the command ! 1839: * contains comments it is copied into a temporary buffer sans comments ! 1840: * and the temporary buffer is passed to the command handler instead. ! 1841: * Likewise for backslash-newlines. ! 1842: * ! 1843: * Returns nonzero if this was a known # directive. ! 1844: * Otherwise, returns zero, without advancing the input pointer. ! 1845: */ ! 1846: ! 1847: int ! 1848: handle_directive (ip, op) ! 1849: FILE_BUF *ip, *op; ! 1850: { ! 1851: register U_CHAR *bp, *cp; ! 1852: register struct directive *kt; ! 1853: register int ident_length; ! 1854: U_CHAR *resume_p; ! 1855: ! 1856: /* Nonzero means we must copy the entire command ! 1857: to get rid of comments or backslash-newlines. */ ! 1858: int copy_command = 0; ! 1859: ! 1860: U_CHAR *ident, *after_ident; ! 1861: ! 1862: bp = ip->bufp; ! 1863: /* Skip whitespace and \-newline. */ ! 1864: while (1) { ! 1865: if (is_hor_space[*bp]) ! 1866: bp++; ! 1867: else if (*bp == '\\' && bp[1] == '\n') { ! 1868: bp += 2; ip->lineno++; ! 1869: } else break; ! 1870: } ! 1871: ! 1872: /* Now find end of directive name. ! 1873: If we encounter a backslash-newline, exchange it with any following ! 1874: symbol-constituents so that we end up with a contiguous name. */ ! 1875: ! 1876: cp = bp; ! 1877: while (1) { ! 1878: if (is_idchar[*cp]) ! 1879: cp++; ! 1880: else { ! 1881: if (*cp == '\\' && cp[1] == '\n') ! 1882: name_newline_fix (cp); ! 1883: if (is_idchar[*cp]) ! 1884: cp++; ! 1885: else break; ! 1886: } ! 1887: } ! 1888: ident_length = cp - bp; ! 1889: ident = bp; ! 1890: after_ident = cp; ! 1891: ! 1892: /* ! 1893: * Decode the keyword and call the appropriate expansion ! 1894: * routine, after moving the input pointer up to the next line. ! 1895: */ ! 1896: for (kt = directive_table; kt->length > 0; kt++) { ! 1897: if (kt->length == ident_length && !strncmp (kt->name, ident, ident_length)) { ! 1898: register U_CHAR *buf; ! 1899: register U_CHAR *limit = ip->buf + ip->length; ! 1900: int unterminated = 0; ! 1901: ! 1902: /* Find the end of this command (first newline not backslashed ! 1903: and not in a string or comment). ! 1904: Set COPY_COMMAND if the command must be copied ! 1905: (it contains a backslash-newline or a comment). */ ! 1906: ! 1907: buf = bp = after_ident; ! 1908: while (bp < limit) { ! 1909: register U_CHAR c = *bp++; ! 1910: switch (c) { ! 1911: case '\\': ! 1912: if (bp < limit) { ! 1913: if (*bp == '\n') ! 1914: { ! 1915: ip->lineno++; ! 1916: copy_command = 1; ! 1917: } ! 1918: bp++; ! 1919: } ! 1920: break; ! 1921: ! 1922: case '\'': ! 1923: case '\"': ! 1924: bp = skip_quoted_string (bp - 1, limit, ip->lineno, &ip->lineno, ©_command, &unterminated); ! 1925: /* Don't bother calling the directive if we already got an error ! 1926: message due to unterminated string. Skip everything and pretend ! 1927: we called the directive. */ ! 1928: if (unterminated) { ! 1929: ip->bufp = bp; ! 1930: return 1; ! 1931: } ! 1932: break; ! 1933: ! 1934: /* <...> is special for #include. */ ! 1935: case '<': ! 1936: if (!kt->angle_brackets) ! 1937: break; ! 1938: while (*bp && *bp != '>') bp++; ! 1939: break; ! 1940: ! 1941: case '/': ! 1942: if (*bp == '\\' && bp[1] == '\n') ! 1943: newline_fix (bp); ! 1944: if (*bp == '*' ! 1945: #ifdef CPLUSPLUS ! 1946: || *bp == '/' ! 1947: #endif ! 1948: ) { ! 1949: U_CHAR *obp = bp - 1; ! 1950: ip->bufp = bp + 1; ! 1951: skip_to_end_of_comment (ip, &ip->lineno); ! 1952: bp = ip->bufp; ! 1953: /* No need to copy the command because of a comment at the end; ! 1954: just don't include the comment in the directive. */ ! 1955: if (bp == limit || *bp == '\n') { ! 1956: bp = obp; ! 1957: goto endloop1; ! 1958: } ! 1959: copy_command++; ! 1960: } ! 1961: break; ! 1962: ! 1963: case '\n': ! 1964: --bp; /* Point to the newline */ ! 1965: ip->bufp = bp; ! 1966: goto endloop1; ! 1967: } ! 1968: } ! 1969: ip->bufp = bp; ! 1970: ! 1971: endloop1: ! 1972: resume_p = ip->bufp; ! 1973: /* BP is the end of the directive. ! 1974: RESUME_P is the next interesting data after the directive. ! 1975: A comment may come between. */ ! 1976: ! 1977: if (copy_command) { ! 1978: register U_CHAR *xp = buf; ! 1979: /* Need to copy entire command into temp buffer before dispatching */ ! 1980: ! 1981: cp = (U_CHAR *) alloca (bp - buf + 5); /* room for cmd plus ! 1982: some slop */ ! 1983: buf = cp; ! 1984: ! 1985: /* Copy to the new buffer, deleting comments ! 1986: and backslash-newlines (and whitespace surrounding the latter). */ ! 1987: ! 1988: while (xp < bp) { ! 1989: register U_CHAR c = *xp++; ! 1990: *cp++ = c; ! 1991: ! 1992: switch (c) { ! 1993: case '\n': ! 1994: break; ! 1995: ! 1996: /* <...> is special for #include. */ ! 1997: case '<': ! 1998: if (!kt->angle_brackets) ! 1999: break; ! 2000: while (*bp && *bp != '>') bp++; ! 2001: break; ! 2002: ! 2003: case '\\': ! 2004: if (*xp == '\n') { ! 2005: xp++; ! 2006: cp--; ! 2007: if (cp != buf && is_space[cp[-1]]) { ! 2008: while (cp != buf && is_space[cp[-1]]) cp--; ! 2009: cp++; ! 2010: SKIP_WHITE_SPACE (xp); ! 2011: } else if (is_space[*xp]) { ! 2012: *cp++ = *xp++; ! 2013: SKIP_WHITE_SPACE (xp); ! 2014: } ! 2015: } ! 2016: break; ! 2017: ! 2018: case '\'': ! 2019: case '\"': ! 2020: { ! 2021: register U_CHAR *bp1 ! 2022: = skip_quoted_string (xp - 1, limit, ip->lineno, 0, 0, 0); ! 2023: while (xp != bp1) ! 2024: *cp++ = *xp++; ! 2025: } ! 2026: break; ! 2027: ! 2028: case '/': ! 2029: if (*xp == '*' ! 2030: #ifdef CPLUSPLUS ! 2031: || *xp == '/' ! 2032: #endif ! 2033: ) { ! 2034: if (traditional) ! 2035: cp--; ! 2036: else ! 2037: cp[-1] = ' '; ! 2038: ip->bufp = xp + 1; ! 2039: skip_to_end_of_comment (ip, 0); ! 2040: xp = ip->bufp; ! 2041: } ! 2042: } ! 2043: } ! 2044: ! 2045: /* Null-terminate the copy. */ ! 2046: ! 2047: *cp = 0; ! 2048: } ! 2049: else ! 2050: cp = bp; ! 2051: ! 2052: ip->bufp = resume_p; ! 2053: ! 2054: /* Call the appropriate command handler. buf now points to ! 2055: either the appropriate place in the input buffer, or to ! 2056: the temp buffer if it was necessary to make one. cp ! 2057: points to the first char after the contents of the (possibly ! 2058: copied) command, in either case. */ ! 2059: (*kt->func) (buf, cp, op, kt); ! 2060: check_expand (op, ip->length - (ip->bufp - ip->buf)); ! 2061: ! 2062: return 1; ! 2063: } ! 2064: } ! 2065: ! 2066: return 0; ! 2067: } ! 2068: ! 2069: static char *monthnames[] = {"jan", "feb", "mar", "apr", "may", "jun", ! 2070: "jul", "aug", "sep", "oct", "nov", "dec", ! 2071: }; ! 2072: ! 2073: /* ! 2074: * expand things like __FILE__. Place the expansion into the output ! 2075: * buffer *without* rescanning. ! 2076: */ ! 2077: special_symbol (hp, op) ! 2078: HASHNODE *hp; ! 2079: FILE_BUF *op; ! 2080: { ! 2081: char *buf; ! 2082: int i, len; ! 2083: FILE_BUF *ip = NULL; ! 2084: static struct tm *timebuf = NULL; ! 2085: struct tm *localtime (); ! 2086: ! 2087: int paren = 0; /* For special `defined' keyword */ ! 2088: ! 2089: for (i = indepth; i >= 0; i--) ! 2090: if (instack[i].fname != NULL) { ! 2091: ip = &instack[i]; ! 2092: break; ! 2093: } ! 2094: if (ip == NULL) { ! 2095: error ("cccp error: not in any file?!"); ! 2096: return; /* the show must go on */ ! 2097: } ! 2098: ! 2099: switch (hp->type) { ! 2100: case T_FILE: ! 2101: buf = (char *) alloca (3 + strlen (ip->fname)); ! 2102: sprintf (buf, "\"%s\"", ip->fname); ! 2103: break; ! 2104: ! 2105: case T_VERSION: ! 2106: buf = (char *) alloca (3 + strlen (version_string)); ! 2107: sprintf (buf, "\"%s\"", version_string); ! 2108: break; ! 2109: ! 2110: case T_CONST: ! 2111: buf = (char *) alloca (4 * sizeof (int)); ! 2112: sprintf (buf, "%d", hp->value.ival); ! 2113: break; ! 2114: ! 2115: case T_SPECLINE: ! 2116: buf = (char *) alloca (10); ! 2117: sprintf (buf, "%d", ip->lineno); ! 2118: break; ! 2119: ! 2120: case T_DATE: ! 2121: case T_TIME: ! 2122: if (timebuf == NULL) { ! 2123: i = time (0); ! 2124: timebuf = localtime (&i); ! 2125: } ! 2126: buf = (char *) alloca (20); ! 2127: if (hp->type == T_DATE) ! 2128: sprintf (buf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon], ! 2129: timebuf->tm_mday, timebuf->tm_year + 1900); ! 2130: else ! 2131: sprintf (buf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min, ! 2132: timebuf->tm_sec); ! 2133: break; ! 2134: ! 2135: case T_SPEC_DEFINED: ! 2136: buf = " 0 "; /* Assume symbol is not defined */ ! 2137: ip = &instack[indepth]; ! 2138: SKIP_WHITE_SPACE (ip->bufp); ! 2139: if (*ip->bufp == '(') { ! 2140: paren++; ! 2141: ip->bufp++; /* Skip over the paren */ ! 2142: SKIP_WHITE_SPACE (ip->bufp); ! 2143: } ! 2144: ! 2145: if (!is_idstart[*ip->bufp]) ! 2146: goto oops; ! 2147: if (lookup (ip->bufp, -1, -1)) ! 2148: buf = " 1 "; ! 2149: while (is_idchar[*ip->bufp]) ! 2150: ++ip->bufp; ! 2151: SKIP_WHITE_SPACE (ip->bufp); ! 2152: if (paren) { ! 2153: if (*ip->bufp != ')') ! 2154: goto oops; ! 2155: ++ip->bufp; ! 2156: } ! 2157: break; ! 2158: ! 2159: oops: ! 2160: ! 2161: error ("`defined' must be followed by ident or (ident)"); ! 2162: break; ! 2163: ! 2164: default: ! 2165: error ("cccp error: invalid special hash type"); /* time for gdb */ ! 2166: abort (); ! 2167: } ! 2168: len = strlen (buf); ! 2169: check_expand (op, len); ! 2170: bcopy (buf, op->bufp, len); ! 2171: op->bufp += len; ! 2172: ! 2173: return; ! 2174: } ! 2175: ! 2176: ! 2177: /* Routines to handle #directives */ ! 2178: ! 2179: /* ! 2180: * Process include file by reading it in and calling rescan. ! 2181: * Expects to see "fname" or <fname> on the input. ! 2182: */ ! 2183: ! 2184: do_include (buf, limit, op, keyword) ! 2185: U_CHAR *buf, *limit; ! 2186: FILE_BUF *op; ! 2187: struct directive *keyword; ! 2188: { ! 2189: char *fname; /* Dynamically allocated fname buffer */ ! 2190: U_CHAR *fbeg, *fend; /* Beginning and end of fname */ ! 2191: ! 2192: struct directory_stack *stackp = include; /* Chain of dirs to search */ ! 2193: struct directory_stack dsp[1]; /* First in chain, if #include "..." */ ! 2194: int flen; ! 2195: ! 2196: int f; /* file number */ ! 2197: ! 2198: int retried = 0; /* Have already tried macro ! 2199: expanding the include line*/ ! 2200: FILE_BUF trybuf; /* It got expanded into here */ ! 2201: int system_header_p = 0; /* 0 for "...", 1 for <...> */ ! 2202: ! 2203: f= -1; /* JF we iz paranoid! */ ! 2204: ! 2205: get_filename: ! 2206: ! 2207: fbeg = buf; ! 2208: SKIP_WHITE_SPACE (fbeg); ! 2209: /* Discard trailing whitespace so we can easily see ! 2210: if we have parsed all the significant chars we were given. */ ! 2211: while (limit != fbeg && is_hor_space[limit[-1]]) limit--; ! 2212: ! 2213: switch (*fbeg++) { ! 2214: case '\"': ! 2215: fend = fbeg; ! 2216: while (fend != limit && *fend != '\"') ! 2217: fend++; ! 2218: if (*fend == '\"' && fend + 1 == limit) { ! 2219: FILE_BUF *fp; ! 2220: ! 2221: /* We have "filename". Figure out directory this source ! 2222: file is coming from and put it on the front of the list. */ ! 2223: ! 2224: /* If -I- was specified, don't search current dir, only spec'd ones. */ ! 2225: if (ignore_srcdir) break; ! 2226: ! 2227: for (fp = &instack[indepth]; fp >= instack; fp--) ! 2228: { ! 2229: int n; ! 2230: char *ep,*nam; ! 2231: extern char *rindex (); ! 2232: ! 2233: if ((nam = fp->fname) != NULL) ! 2234: { ! 2235: /* Found a named file. Figure out dir of the file, ! 2236: and put it in front of the search list. */ ! 2237: dsp[0].next = stackp; ! 2238: stackp = dsp; ! 2239: #ifndef VMS ! 2240: ep = rindex (nam, '/'); ! 2241: #else /* VMS */ ! 2242: ep = rindex (nam, ']'); ! 2243: if (ep == NULL) ep = rindex (nam, '>'); ! 2244: if (ep == NULL) ep = rindex (nam, ':'); ! 2245: if (ep != NULL) ep++; ! 2246: #endif /* VMS */ ! 2247: if (ep != NULL) { ! 2248: n = ep - nam; ! 2249: dsp[0].fname = (char *) alloca (n + 1); ! 2250: strncpy (dsp[0].fname, nam, n); ! 2251: dsp[0].fname[n] = '\0'; ! 2252: if (n > max_include_len) max_include_len = n; ! 2253: } else { ! 2254: dsp[0].fname = 0; /* Current directory */ ! 2255: } ! 2256: break; ! 2257: } ! 2258: } ! 2259: break; ! 2260: } ! 2261: goto fail; ! 2262: ! 2263: case '<': ! 2264: fend = fbeg; ! 2265: while (fend != limit && *fend != '>') fend++; ! 2266: if (*fend == '>' && fend + 1 == limit) { ! 2267: system_header_p = 1; ! 2268: /* If -I-, start with the first -I dir after the -I-. */ ! 2269: if (first_bracket_include) ! 2270: stackp = first_bracket_include; ! 2271: break; ! 2272: } ! 2273: goto fail; ! 2274: ! 2275: default: ! 2276: fail: ! 2277: if (retried) { ! 2278: error ("#include expects \"fname\" or <fname>"); ! 2279: return; ! 2280: } else { ! 2281: trybuf = expand_to_temp_buffer (buf, limit, 0); ! 2282: buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1); ! 2283: bcopy (trybuf.buf, buf, trybuf.bufp - trybuf.buf); ! 2284: limit = buf + (trybuf.bufp - trybuf.buf); ! 2285: free (trybuf.buf); ! 2286: retried++; ! 2287: goto get_filename; ! 2288: } ! 2289: } ! 2290: ! 2291: flen = fend - fbeg; ! 2292: fname = (char *) alloca (max_include_len + flen + 2); ! 2293: /* + 2 above for slash and terminating null. */ ! 2294: ! 2295: /* If specified file name is absolute, just open it. */ ! 2296: ! 2297: if (*fbeg == '/') { ! 2298: strncpy (fname, fbeg, flen); ! 2299: fname[flen] = 0; ! 2300: f = open (fname, O_RDONLY); ! 2301: } else { ! 2302: /* Search directory path, trying to open the file. ! 2303: Copy each filename tried into FNAME. */ ! 2304: ! 2305: for (; stackp; stackp = stackp->next) { ! 2306: if (stackp->fname) { ! 2307: strcpy (fname, stackp->fname); ! 2308: strcat (fname, "/"); ! 2309: fname[strlen (fname) + flen] = 0; ! 2310: } else { ! 2311: fname[0] = 0; ! 2312: } ! 2313: strncat (fname, fbeg, flen); ! 2314: #ifdef VMS ! 2315: /* Change this 1/2 Unix 1/2 VMS file specification into a ! 2316: full VMS file specification */ ! 2317: if (stackp->fname && (stackp->fname[0] != 0)) { ! 2318: /* Fix up the filename */ ! 2319: hack_vms_include_specification (fname); ! 2320: } else { ! 2321: /* This is a normal VMS filespec, so use it unchanged. */ ! 2322: strncpy (fname, fbeg, flen); ! 2323: fname[flen] = 0; ! 2324: } ! 2325: #endif /* VMS */ ! 2326: if ((f = open (fname, O_RDONLY)) >= 0) ! 2327: break; ! 2328: } ! 2329: } ! 2330: ! 2331: /* For -M, print the name of the included file. */ ! 2332: if (print_deps > system_header_p) ! 2333: { ! 2334: deps_output (fname, strlen (fname)); ! 2335: deps_output (" ", 0); ! 2336: } ! 2337: ! 2338: if (f < 0) { ! 2339: strncpy (fname, fbeg, flen); ! 2340: fname[flen] = 0; ! 2341: error ("can't find include file `%s'", fname); ! 2342: } else { ! 2343: finclude (f, fname, op); ! 2344: close (f); ! 2345: } ! 2346: } ! 2347: ! 2348: /* Process the contents of include file FNAME, already open on descriptor F, ! 2349: with output to OP. */ ! 2350: ! 2351: finclude (f, fname, op) ! 2352: int f; ! 2353: char *fname; ! 2354: FILE_BUF *op; ! 2355: { ! 2356: long st_size; ! 2357: long i; ! 2358: FILE_BUF *fp; /* For input stack frame */ ! 2359: int success = 0; ! 2360: ! 2361: if (file_size_and_mode (f, (int *)0, &st_size) < 0) ! 2362: goto nope; /* Impossible? */ ! 2363: ! 2364: fp = &instack[indepth + 1]; ! 2365: bzero (fp, sizeof (FILE_BUF)); ! 2366: fp->buf = (U_CHAR *) alloca (st_size + 2); ! 2367: fp->fname = fname; ! 2368: fp->length = 0; ! 2369: fp->lineno = 1; ! 2370: fp->bufp = fp->buf; ! 2371: fp->if_stack = if_stack; ! 2372: ! 2373: /* Read the file contents, knowing that st_size is an upper bound ! 2374: on the number of bytes we can read. */ ! 2375: while (st_size > 0) { ! 2376: i = read (f, fp->buf + fp->length, st_size); ! 2377: if (i <= 0) { ! 2378: if (i == 0) break; ! 2379: goto nope; ! 2380: } ! 2381: fp->length += i; ! 2382: st_size -= i; ! 2383: } ! 2384: ! 2385: if (!no_trigraphs) ! 2386: trigraph_pcp (fp); ! 2387: ! 2388: if (fp->length > 0 && fp->buf[fp->length-1] != '\n') ! 2389: fp->buf[fp->length++] = '\n'; ! 2390: fp->buf[fp->length] = '\0'; ! 2391: ! 2392: success = 1; ! 2393: indepth++; ! 2394: ! 2395: output_line_command (fp, op, 0); ! 2396: rescan (op, 0); ! 2397: indepth--; ! 2398: output_line_command (&instack[indepth], op, 0); ! 2399: ! 2400: nope: ! 2401: ! 2402: close (f); ! 2403: if (!success) { ! 2404: perror_with_name (fname); ! 2405: } ! 2406: } ! 2407: ! 2408: /* The arglist structure is built by do_define to tell ! 2409: collect_definition where the argument names begin. That ! 2410: is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist ! 2411: would contain pointers to the strings x, y, and z. ! 2412: Collect_definition would then build a DEFINITION node, ! 2413: with reflist nodes pointing to the places x, y, and z had ! 2414: appeared. So the arglist is just convenience data passed ! 2415: between these two routines. It is not kept around after ! 2416: the current #define has been processed and entered into the ! 2417: hash table. */ ! 2418: ! 2419: struct arglist { ! 2420: struct arglist *next; ! 2421: U_CHAR *name; ! 2422: int length; ! 2423: int argno; ! 2424: }; ! 2425: ! 2426: /* Process a #define command. ! 2427: BUF points to the contents of the #define command, as a continguous string. ! 2428: LIMIT points to the first character past the end of the definition. ! 2429: KEYWORD is the keyword-table entry for #define. */ ! 2430: ! 2431: do_define (buf, limit, op, keyword) ! 2432: U_CHAR *buf, *limit; ! 2433: FILE_BUF *op; ! 2434: struct directive *keyword; ! 2435: { ! 2436: U_CHAR *bp; /* temp ptr into input buffer */ ! 2437: U_CHAR *symname; /* remember where symbol name starts */ ! 2438: int sym_length; /* and how long it is */ ! 2439: ! 2440: DEFINITION *defn; ! 2441: int arglengths = 0; /* Accumulate lengths of arg names ! 2442: plus number of args. */ ! 2443: int hashcode; ! 2444: ! 2445: bp = buf; ! 2446: ! 2447: while (is_hor_space[*bp]) ! 2448: bp++; ! 2449: if (!is_idstart[*bp]) ! 2450: warning ("macro name starts with a digit"); ! 2451: ! 2452: symname = bp; /* remember where it starts */ ! 2453: while (is_idchar[*bp] && bp < limit) { ! 2454: if (*bp == '$' && pedantic) { ! 2455: if (! dollar_seen) ! 2456: warning ("ANSI C forbids `$' in identifier (first use here)"); ! 2457: dollar_seen = 1; ! 2458: } ! 2459: bp++; ! 2460: } ! 2461: sym_length = bp - symname; ! 2462: ! 2463: /* lossage will occur if identifiers or control keywords are broken ! 2464: across lines using backslash. This is not the right place to take ! 2465: care of that. */ ! 2466: ! 2467: if (*bp == '(') { ! 2468: struct arglist *arg_ptrs = NULL; ! 2469: int argno = 0; ! 2470: ! 2471: bp++; /* skip '(' */ ! 2472: SKIP_WHITE_SPACE (bp); ! 2473: ! 2474: /* Loop over macro argument names. */ ! 2475: while (*bp != ')') { ! 2476: struct arglist *temp; ! 2477: ! 2478: temp = (struct arglist *) alloca (sizeof (struct arglist)); ! 2479: temp->name = bp; ! 2480: temp->next = arg_ptrs; ! 2481: temp->argno = argno++; ! 2482: arg_ptrs = temp; ! 2483: ! 2484: if (!is_idstart[*bp]) ! 2485: warning ("parameter name starts with a digit in #define"); ! 2486: ! 2487: /* Find the end of the arg name. */ ! 2488: while (is_idchar[*bp]) { ! 2489: if (*bp == '$' && pedantic) { ! 2490: if (! dollar_seen) ! 2491: warning ("ANSI C forbids `$' in identifier (first use here)"); ! 2492: dollar_seen = 1; ! 2493: } ! 2494: bp++; ! 2495: } ! 2496: temp->length = bp - temp->name; ! 2497: arglengths += temp->length + 2; ! 2498: SKIP_WHITE_SPACE (bp); ! 2499: if (temp->length == 0 || (*bp != ',' && *bp != ')')) { ! 2500: error ("badly punctuated parameter list in #define"); ! 2501: goto nope; ! 2502: } ! 2503: if (*bp == ',') { ! 2504: bp++; ! 2505: SKIP_WHITE_SPACE (bp); ! 2506: } ! 2507: if (bp >= limit) { ! 2508: error ("unterminated parameter list in #define"); ! 2509: goto nope; ! 2510: } ! 2511: } ! 2512: ! 2513: ++bp; /* skip paren */ ! 2514: /* Skip exactly one space or tab if any. */ ! 2515: if (bp < limit && (*bp == ' ' || *bp == '\t')) ++bp; ! 2516: /* now everything from bp before limit is the definition. */ ! 2517: defn = collect_expansion (bp, limit, argno, arg_ptrs); ! 2518: ! 2519: /* Now set defn->argnames to the result of concatenating ! 2520: the argument names in reverse order ! 2521: with comma-space between them. */ ! 2522: defn->argnames = (U_CHAR *) xmalloc (arglengths + 1); ! 2523: { ! 2524: struct arglist *temp; ! 2525: int i = 0; ! 2526: for (temp = arg_ptrs; temp; temp = temp->next) ! 2527: { ! 2528: bcopy (temp->name, &defn->argnames[i], temp->length); ! 2529: i += temp->length; ! 2530: if (temp->next != 0) { ! 2531: defn->argnames[i++] = ','; ! 2532: defn->argnames[i++] = ' '; ! 2533: } ! 2534: } ! 2535: defn->argnames[i] = 0; ! 2536: } ! 2537: } else { ! 2538: /* simple expansion or empty definition; gobble it */ ! 2539: if (is_hor_space[*bp]) ! 2540: ++bp; /* skip exactly one blank/tab char */ ! 2541: /* now everything from bp before limit is the definition. */ ! 2542: defn = collect_expansion (bp, limit, -1, 0); ! 2543: defn->argnames = (U_CHAR *) ""; ! 2544: } ! 2545: ! 2546: hashcode = hashf (symname, sym_length, HASHSIZE); ! 2547: ! 2548: { ! 2549: HASHNODE *hp; ! 2550: if ((hp = lookup (symname, sym_length, hashcode)) != NULL) { ! 2551: if (hp->type != T_MACRO ! 2552: || compare_defs (defn, hp->value.defn)) { ! 2553: U_CHAR *msg; /* what pain... */ ! 2554: msg = (U_CHAR *) alloca (sym_length + 20); ! 2555: bcopy (symname, msg, sym_length); ! 2556: strcpy (msg + sym_length, " redefined"); ! 2557: warning (msg); ! 2558: } ! 2559: /* Replace the old definition. */ ! 2560: hp->type = T_MACRO; ! 2561: hp->value.defn = defn; ! 2562: } else ! 2563: install (symname, sym_length, T_MACRO, defn, hashcode); ! 2564: } ! 2565: ! 2566: return 0; ! 2567: ! 2568: nope: ! 2569: ! 2570: return 1; ! 2571: } ! 2572: ! 2573: /* ! 2574: * return zero if two DEFINITIONs are isomorphic ! 2575: */ ! 2576: static ! 2577: compare_defs (d1, d2) ! 2578: DEFINITION *d1, *d2; ! 2579: { ! 2580: register struct reflist *a1, *a2; ! 2581: register U_CHAR *p1 = d1->expansion; ! 2582: register U_CHAR *p2 = d2->expansion; ! 2583: int first = 1; ! 2584: ! 2585: if (d1->nargs != d2->nargs) ! 2586: return 1; ! 2587: if (strcmp (d1->argnames, d2->argnames)) ! 2588: return 1; ! 2589: for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2; ! 2590: a1 = a1->next, a2 = a2->next) { ! 2591: if (!((a1->nchars == a2->nchars && ! strncmp (p1, p2, a1->nchars)) ! 2592: || ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0)) ! 2593: || a1->argno != a2->argno ! 2594: || a1->stringify != a2->stringify ! 2595: || a1->raw_before != a2->raw_before ! 2596: || a1->raw_after != a2->raw_after) ! 2597: return 1; ! 2598: first = 0; ! 2599: p1 += a1->nchars; ! 2600: p2 += a2->nchars; ! 2601: } ! 2602: if (a1 != a2) ! 2603: return 1; ! 2604: if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion), ! 2605: p2, d2->length - (p2 - d2->expansion), 1)) ! 2606: return 1; ! 2607: return 0; ! 2608: } ! 2609: ! 2610: /* Return 1 if two parts of two macro definitions are effectively different. ! 2611: One of the parts starts at BEG1 and has LEN1 chars; ! 2612: the other has LEN2 chars at BEG2. ! 2613: Any sequence of whitespace matches any other sequence of whitespace. ! 2614: FIRST means these parts are the first of a macro definition; ! 2615: so ignore leading whitespace entirely. ! 2616: LAST means these parts are the last of a macro definition; ! 2617: so ignore trailing whitespace entirely. */ ! 2618: ! 2619: comp_def_part (first, beg1, len1, beg2, len2, last) ! 2620: int first; ! 2621: U_CHAR *beg1, *beg2; ! 2622: int len1, len2; ! 2623: int last; ! 2624: { ! 2625: register U_CHAR *end1 = beg1 + len1; ! 2626: register U_CHAR *end2 = beg2 + len2; ! 2627: if (first) { ! 2628: while (beg1 != end1 && is_space[*beg1]) beg1++; ! 2629: while (beg2 != end2 && is_space[*beg2]) beg2++; ! 2630: } ! 2631: if (last) { ! 2632: while (beg1 != end1 && is_space[end1[-1]]) end1--; ! 2633: while (beg2 != end2 && is_space[end2[-1]]) end2--; ! 2634: } ! 2635: while (beg1 != end1 && beg2 != end2) { ! 2636: if (is_space[*beg1] && is_space[*beg2]) { ! 2637: while (beg1 != end1 && is_space[*beg1]) beg1++; ! 2638: while (beg2 != end2 && is_space[*beg2]) beg2++; ! 2639: } else if (*beg1 == *beg2) { ! 2640: beg1++; beg2++; ! 2641: } else break; ! 2642: } ! 2643: return (beg1 != end1) || (beg2 != end2); ! 2644: } ! 2645: ! 2646: /* Read a replacement list for a macro with parameters. ! 2647: Build the DEFINITION structure. ! 2648: Reads characters of text starting at BUF until LIMIT. ! 2649: ARGLIST specifies the formal parameters to look for ! 2650: in the text of the definition; NARGS is the number of args ! 2651: in that list, or -1 for a macro name that wants no argument list. ! 2652: MACRONAME is the macro name itself (so we can avoid recursive expansion) ! 2653: and NAMELEN is its length in characters. ! 2654: ! 2655: Note that comments and backslash-newlines have already been deleted ! 2656: from the argument. */ ! 2657: ! 2658: /* Leading and trailing Space, Tab, etc. are converted to markers ! 2659: Newline Space, Newline Tab, etc. ! 2660: Newline Space makes a space in the final output ! 2661: but is discarded if stringified. (Newline Tab is similar but ! 2662: makes a Tab instead.) ! 2663: ! 2664: If there is no trailing whitespace, a Newline Space is added at the end ! 2665: to prevent concatenation that would be contrary to the standard. */ ! 2666: ! 2667: static DEFINITION * ! 2668: collect_expansion (buf, end, nargs, arglist) ! 2669: U_CHAR *buf, *end; ! 2670: int nargs; ! 2671: struct arglist *arglist; ! 2672: { ! 2673: DEFINITION *defn; ! 2674: register U_CHAR *p, *limit, *lastp, *exp_p; ! 2675: struct reflist *endpat = NULL; ! 2676: /* Pointer to first nonspace after last ## seen. */ ! 2677: U_CHAR *concat = 0; ! 2678: /* Pointer to first nonspace after last single-# seen. */ ! 2679: U_CHAR *stringify = 0; ! 2680: ! 2681: /* Scan thru the replacement list, ignoring comments and quoted ! 2682: strings, picking up on the macro calls. It does a linear search ! 2683: thru the arg list on every potential symbol. Profiling might say ! 2684: that something smarter should happen. */ ! 2685: ! 2686: if (end < buf) ! 2687: abort (); ! 2688: ! 2689: defn = (DEFINITION *) xcalloc (1, sizeof (DEFINITION) + 2 * (end - buf + 2)); ! 2690: ! 2691: defn->nargs = nargs; ! 2692: exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION); ! 2693: lastp = exp_p; ! 2694: ! 2695: /* Speed this loop up later? */ ! 2696: ! 2697: p = buf; ! 2698: limit = end; ! 2699: ! 2700: /* Find the beginning of the trailing whitespace. */ ! 2701: while (p < limit && is_space[limit[-1]]) limit--; ! 2702: ! 2703: /* Convert leading whitespace to Newline-markers. */ ! 2704: while (p < limit && is_space[*p]) { ! 2705: *exp_p++ = '\n'; ! 2706: *exp_p++ = *p++; ! 2707: } ! 2708: ! 2709: /* Process the main body of the definition. */ ! 2710: while (p < limit) { ! 2711: int skipped_arg = 0; ! 2712: register U_CHAR c = *p++; ! 2713: ! 2714: *exp_p++ = c; ! 2715: ! 2716: switch (c) { ! 2717: case '\'': ! 2718: case '\"': ! 2719: if (!traditional) { ! 2720: for (; p < limit && *p != c; p++) { ! 2721: *exp_p++ = *p; ! 2722: if (*p == '\\') { ! 2723: *exp_p++ = *++p; ! 2724: } ! 2725: } ! 2726: *exp_p++ = *p++; ! 2727: } ! 2728: break; ! 2729: ! 2730: /* Special hack: if a \# is written in the #define ! 2731: include a # in the definition. This is useless for C code ! 2732: but useful for preprocessing other things. */ ! 2733: ! 2734: case '\\': ! 2735: if (p < limit && *p == '#') { ! 2736: /* Pass through this # */ ! 2737: exp_p--; ! 2738: *exp_p++ = *p++; ! 2739: } ! 2740: break; ! 2741: ! 2742: case '#': ! 2743: if (p < limit && *p == '#') { ! 2744: /* ##: concatenate preceding and following tokens. */ ! 2745: /* Take out the first #, discard preceding whitespace. */ ! 2746: exp_p--; ! 2747: while (exp_p > lastp && is_hor_space[exp_p[-1]]) ! 2748: --exp_p; ! 2749: /* Skip the second #. */ ! 2750: p++; ! 2751: /* Discard following whitespace. */ ! 2752: SKIP_WHITE_SPACE (p); ! 2753: concat = p; ! 2754: } else { ! 2755: /* Single #: stringify following argument ref. ! 2756: Don't leave the # in the expansion. */ ! 2757: exp_p--; ! 2758: SKIP_WHITE_SPACE (p); ! 2759: if (p == limit || ! is_idstart[*p] || nargs <= 0) ! 2760: error ("# operator should be followed by a macro argument name\n"); ! 2761: else ! 2762: stringify = p; ! 2763: } ! 2764: break; ! 2765: } ! 2766: ! 2767: if (is_idchar[c] && nargs > 0) { ! 2768: U_CHAR *id_beg = p - 1; ! 2769: int id_len; ! 2770: ! 2771: --exp_p; ! 2772: while (p != limit && is_idchar[*p]) p++; ! 2773: id_len = p - id_beg; ! 2774: ! 2775: if (is_idstart[c]) { ! 2776: register struct arglist *arg; ! 2777: ! 2778: for (arg = arglist; arg != NULL; arg = arg->next) { ! 2779: struct reflist *tpat; ! 2780: ! 2781: if (arg->name[0] == c ! 2782: && arg->length == id_len ! 2783: && strncmp (arg->name, id_beg, id_len) == 0) { ! 2784: /* make a pat node for this arg and append it to the end of ! 2785: the pat list */ ! 2786: tpat = (struct reflist *) xmalloc (sizeof (struct reflist)); ! 2787: tpat->next = NULL; ! 2788: tpat->stringify = stringify == id_beg; ! 2789: tpat->raw_before = concat == id_beg; ! 2790: tpat->raw_after = 0; ! 2791: ! 2792: if (endpat == NULL) ! 2793: defn->pattern = tpat; ! 2794: else ! 2795: endpat->next = tpat; ! 2796: endpat = tpat; ! 2797: ! 2798: tpat->argno = arg->argno; ! 2799: tpat->nchars = exp_p - lastp; ! 2800: { ! 2801: register U_CHAR *p1 = p; ! 2802: SKIP_WHITE_SPACE (p1); ! 2803: if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#') ! 2804: tpat->raw_after = 1; ! 2805: } ! 2806: lastp = exp_p; /* place to start copying from next time */ ! 2807: skipped_arg = 1; ! 2808: break; ! 2809: } ! 2810: } ! 2811: } ! 2812: ! 2813: /* If this was not a macro arg, copy it into the expansion. */ ! 2814: if (! skipped_arg) { ! 2815: register U_CHAR *lim1 = p; ! 2816: p = id_beg; ! 2817: while (p != lim1) ! 2818: *exp_p++ = *p++; ! 2819: if (stringify == id_beg) ! 2820: error ("# operator should be followed by a macro argument name\n"); ! 2821: } ! 2822: } ! 2823: } ! 2824: ! 2825: if (limit < end) { ! 2826: /* Convert trailing whitespace to Newline-markers. */ ! 2827: while (limit < end && is_space[*limit]) { ! 2828: *exp_p++ = '\n'; ! 2829: *exp_p++ = *limit++; ! 2830: } ! 2831: } else if (!traditional) { ! 2832: /* There is no trailing whitespace, so invent some. */ ! 2833: *exp_p++ = '\n'; ! 2834: *exp_p++ = ' '; ! 2835: } ! 2836: ! 2837: *exp_p = '\0'; ! 2838: ! 2839: defn->length = exp_p - defn->expansion; ! 2840: ! 2841: #if 0 ! 2842: /* This isn't worth the time it takes. */ ! 2843: /* give back excess storage */ ! 2844: defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1); ! 2845: #endif ! 2846: ! 2847: return defn; ! 2848: } ! 2849: ! 2850: #ifdef DEBUG ! 2851: /* ! 2852: * debugging routine ---- return a ptr to a string containing ! 2853: * first n chars of s. Returns a ptr to a static object ! 2854: * since I happen to know it will fit. ! 2855: */ ! 2856: static U_CHAR * ! 2857: prefix (s, n) ! 2858: U_CHAR *s; ! 2859: int n; ! 2860: { ! 2861: static U_CHAR buf[1000]; ! 2862: bcopy (s, buf, n); ! 2863: buf[n] = '\0'; /* this should not be necessary! */ ! 2864: return buf; ! 2865: } ! 2866: #endif ! 2867: ! 2868: /* ! 2869: * interpret #line command. Remembers previously seen fnames ! 2870: * in its very own hash table. ! 2871: */ ! 2872: #define FNAME_HASHSIZE 37 ! 2873: ! 2874: do_line (buf, limit, op, keyword) ! 2875: U_CHAR *buf, *limit; ! 2876: FILE_BUF *op; ! 2877: struct directive *keyword; ! 2878: { ! 2879: register U_CHAR *bp; ! 2880: FILE_BUF *ip = &instack[indepth]; ! 2881: FILE_BUF tem; ! 2882: int new_lineno; ! 2883: ! 2884: /* Expand any macros. */ ! 2885: tem = expand_to_temp_buffer (buf, limit, 0); ! 2886: ! 2887: /* Point to macroexpanded line, which is null-terminated now. */ ! 2888: bp = tem.buf; ! 2889: SKIP_WHITE_SPACE (bp); ! 2890: ! 2891: if (!isdigit (*bp)) { ! 2892: error ("invalid format #line command"); ! 2893: return; ! 2894: } ! 2895: ! 2896: /* The Newline at the end of this line remains to be processed. ! 2897: To put the next line at the specified line number, ! 2898: we must store a line number now that is one less. */ ! 2899: new_lineno = atoi (bp) - 1; ! 2900: ! 2901: /* skip over the line number. */ ! 2902: while (isdigit (*bp)) ! 2903: bp++; ! 2904: if (*bp && !is_space[*bp]) { ! 2905: error ("invalid format #line command"); ! 2906: return; ! 2907: } ! 2908: ! 2909: SKIP_WHITE_SPACE (bp); ! 2910: ! 2911: if (*bp == '\"') { ! 2912: static HASHNODE *fname_table[FNAME_HASHSIZE]; ! 2913: HASHNODE *hp, **hash_bucket; ! 2914: U_CHAR *fname; ! 2915: int fname_length; ! 2916: ! 2917: fname = ++bp; ! 2918: ! 2919: while (*bp && *bp != '\"') ! 2920: bp++; ! 2921: if (*bp != '\"') { ! 2922: error ("invalid format #line command"); ! 2923: return; ! 2924: } ! 2925: ! 2926: fname_length = bp - fname; ! 2927: ! 2928: bp++; ! 2929: SKIP_WHITE_SPACE (bp); ! 2930: if (*bp) { ! 2931: error ("invalid format #line command"); ! 2932: return; ! 2933: } ! 2934: ! 2935: hash_bucket = ! 2936: &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)]; ! 2937: for (hp = *hash_bucket; hp != NULL; hp = hp->next) ! 2938: if (hp->length == fname_length && ! 2939: strncmp (hp->value.cpval, fname, fname_length) == 0) { ! 2940: ip->fname = hp->value.cpval; ! 2941: break; ! 2942: } ! 2943: if (hp == 0) { ! 2944: /* Didn't find it; cons up a new one. */ ! 2945: hp = (HASHNODE *) xcalloc (1, sizeof (HASHNODE) + fname_length + 1); ! 2946: hp->next = *hash_bucket; ! 2947: *hash_bucket = hp; ! 2948: ! 2949: hp->length = fname_length; ! 2950: ip->fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE); ! 2951: bcopy (fname, hp->value.cpval, fname_length); ! 2952: } ! 2953: } else if (*bp) { ! 2954: error ("invalid format #line command"); ! 2955: return; ! 2956: } ! 2957: ! 2958: ip->lineno = new_lineno; ! 2959: output_line_command (ip, op, 0); ! 2960: check_expand (op, ip->length - (ip->bufp - ip->buf)); ! 2961: } ! 2962: ! 2963: /* ! 2964: * remove all definitions of symbol from symbol table. ! 2965: * according to un*x /lib/cpp, it is not an error to undef ! 2966: * something that has no definitions, so it isn't one here either. ! 2967: */ ! 2968: do_undef (buf, limit, op, keyword) ! 2969: U_CHAR *buf, *limit; ! 2970: FILE_BUF *op; ! 2971: struct directive *keyword; ! 2972: { ! 2973: HASHNODE *hp; ! 2974: ! 2975: SKIP_WHITE_SPACE (buf); ! 2976: ! 2977: while ((hp = lookup (buf, -1, -1)) != NULL) { ! 2978: if (hp->type != T_MACRO) ! 2979: error ("undefining `%s'", hp->name); ! 2980: delete_macro (hp); ! 2981: } ! 2982: } ! 2983: ! 2984: /* ! 2985: * Report a fatal error detected by the program we are processing. ! 2986: * Use the text of the line in the error message, then terminate. ! 2987: * (We use error() because it prints the filename & line#.) ! 2988: */ ! 2989: do_error (buf, limit, op, keyword) ! 2990: U_CHAR *buf, *limit; ! 2991: FILE_BUF *op; ! 2992: struct directive *keyword; ! 2993: { ! 2994: int length = limit - buf; ! 2995: char *copy = (char *) xmalloc (length + 1); ! 2996: bcopy (buf, copy, length); ! 2997: copy[length] = 0; ! 2998: SKIP_WHITE_SPACE (copy); ! 2999: error ("#error %s", copy); ! 3000: exit (FATAL_EXIT_CODE); ! 3001: } ! 3002: ! 3003: #if 0 ! 3004: /* This was a fun hack, but #pragma seems to start to be useful. ! 3005: By failing to recognize it, we pass it through unchanged to cc1. */ ! 3006: ! 3007: /* ! 3008: * the behavior of the #pragma directive is implementation defined. ! 3009: * this implementation defines it as follows. ! 3010: */ ! 3011: do_pragma () ! 3012: { ! 3013: close (0); ! 3014: if (open ("/dev/tty", O_RDONLY) != 0) ! 3015: goto nope; ! 3016: close (1); ! 3017: if (open ("/dev/tty", O_WRONLY) != 1) ! 3018: goto nope; ! 3019: execl ("/usr/games/hack", "#pragma", 0); ! 3020: execl ("/usr/games/rogue", "#pragma", 0); ! 3021: execl ("/usr/new/emacs", "-f", "hanoi", "9", "-kill", 0); ! 3022: execl ("/usr/local/emacs", "-f", "hanoi", "9", "-kill", 0); ! 3023: nope: ! 3024: fatal ("You are in a maze of twisty compiler features, all different"); ! 3025: } ! 3026: #endif ! 3027: ! 3028: /* Just ignore #sccs, on systems where we define it at all. */ ! 3029: do_sccs () ! 3030: {} ! 3031: ! 3032: /* ! 3033: * handle #if command by ! 3034: * 1) inserting special `defined' keyword into the hash table ! 3035: * that gets turned into 0 or 1 by special_symbol (thus, ! 3036: * if the luser has a symbol called `defined' already, it won't ! 3037: * work inside the #if command) ! 3038: * 2) rescan the input into a temporary output buffer ! 3039: * 3) pass the output buffer to the yacc parser and collect a value ! 3040: * 4) clean up the mess left from steps 1 and 2. ! 3041: * 5) call conditional_skip to skip til the next #endif (etc.), ! 3042: * or not, depending on the value from step 3. ! 3043: */ ! 3044: ! 3045: do_if (buf, limit, op, keyword) ! 3046: U_CHAR *buf, *limit; ! 3047: FILE_BUF *op; ! 3048: struct directive *keyword; ! 3049: { ! 3050: int value; ! 3051: FILE_BUF *ip = &instack[indepth]; ! 3052: ! 3053: value = eval_if_expression (buf, limit - buf); ! 3054: conditional_skip (ip, value == 0, T_IF); ! 3055: } ! 3056: ! 3057: /* ! 3058: * handle a #elif directive by not changing if_stack either. ! 3059: * see the comment above do_else. ! 3060: */ ! 3061: ! 3062: do_elif (buf, limit, op, keyword) ! 3063: U_CHAR *buf, *limit; ! 3064: FILE_BUF *op; ! 3065: struct directive *keyword; ! 3066: { ! 3067: int value; ! 3068: FILE_BUF *ip = &instack[indepth]; ! 3069: ! 3070: if (if_stack == instack[indepth].if_stack) { ! 3071: error ("#elif not within a conditional"); ! 3072: return; ! 3073: } else { ! 3074: if (if_stack->type != T_IF && if_stack->type != T_ELIF) { ! 3075: error ("#elif after #else"); ! 3076: fprintf (stderr, " (matches line %d", if_stack->lineno); ! 3077: if (if_stack->fname != NULL && ip->fname != NULL && ! 3078: strcmp (if_stack->fname, ip->fname) != 0) ! 3079: fprintf (stderr, ", file %s", if_stack->fname); ! 3080: fprintf (stderr, ")\n"); ! 3081: } ! 3082: if_stack->type = T_ELIF; ! 3083: } ! 3084: ! 3085: if (if_stack->if_succeeded) ! 3086: skip_if_group (ip, 0); ! 3087: else { ! 3088: value = eval_if_expression (buf, limit - buf); ! 3089: if (value == 0) ! 3090: skip_if_group (ip, 0); ! 3091: else { ! 3092: ++if_stack->if_succeeded; /* continue processing input */ ! 3093: output_line_command (ip, op, 1); ! 3094: } ! 3095: } ! 3096: } ! 3097: ! 3098: /* ! 3099: * evaluate a #if expression in BUF, of length LENGTH, ! 3100: * then parse the result as a C expression and return the value as an int. ! 3101: */ ! 3102: static int ! 3103: eval_if_expression (buf, length) ! 3104: U_CHAR *buf; ! 3105: int length; ! 3106: { ! 3107: FILE_BUF temp_obuf; ! 3108: HASHNODE *save_defined; ! 3109: int value; ! 3110: ! 3111: save_defined = install ("defined", -1, T_SPEC_DEFINED, 0, -1); ! 3112: temp_obuf = expand_to_temp_buffer (buf, buf + length, 0); ! 3113: delete_macro (save_defined); /* clean up special symbol */ ! 3114: ! 3115: value = parse_c_expression (temp_obuf.buf); ! 3116: ! 3117: free (temp_obuf.buf); ! 3118: ! 3119: return value; ! 3120: } ! 3121: ! 3122: /* ! 3123: * routine to handle ifdef/ifndef. Try to look up the symbol, ! 3124: * then do or don't skip to the #endif/#else/#elif depending ! 3125: * on what directive is actually being processed. ! 3126: */ ! 3127: do_xifdef (buf, limit, op, keyword) ! 3128: U_CHAR *buf, *limit; ! 3129: FILE_BUF *op; ! 3130: struct directive *keyword; ! 3131: { ! 3132: int skip; ! 3133: FILE_BUF *ip = &instack[indepth]; ! 3134: U_CHAR *end; ! 3135: ! 3136: /* Discard leading and trailing whitespace. */ ! 3137: SKIP_WHITE_SPACE (buf); ! 3138: while (limit != buf && is_hor_space[limit[-1]]) limit--; ! 3139: ! 3140: /* Find the end of the identifier at the beginning. */ ! 3141: for (end = buf; is_idchar[*end]; end++); ! 3142: ! 3143: if (end == buf) ! 3144: { ! 3145: skip = (keyword->type == T_IFDEF); ! 3146: if (! traditional) ! 3147: warning (end == limit ? "#%s with no argument" ! 3148: : "#%s argument starts with punctuation", ! 3149: keyword->name); ! 3150: } ! 3151: else ! 3152: { ! 3153: if (pedantic && buf[0] >= '0' && buf[0] <= '9') ! 3154: warning ("#%s argument starts with a digit", keyword->name); ! 3155: else if (end != limit && !traditional) ! 3156: warning ("garbage at end of #%s argument", keyword->name); ! 3157: ! 3158: skip = (lookup (buf, end-buf, -1) == NULL) ^ (keyword->type == T_IFNDEF); ! 3159: } ! 3160: ! 3161: conditional_skip (ip, skip, T_IF); ! 3162: } ! 3163: ! 3164: /* ! 3165: * push TYPE on stack; then, if SKIP is nonzero, skip ahead. ! 3166: */ ! 3167: static ! 3168: conditional_skip (ip, skip, type) ! 3169: FILE_BUF *ip; ! 3170: int skip; ! 3171: enum node_type type; ! 3172: { ! 3173: IF_STACK_FRAME *temp; ! 3174: ! 3175: temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME)); ! 3176: temp->fname = ip->fname; ! 3177: temp->lineno = ip->lineno; ! 3178: temp->next = if_stack; ! 3179: if_stack = temp; ! 3180: ! 3181: if_stack->type = type; ! 3182: ! 3183: if (skip != 0) { ! 3184: skip_if_group (ip, 0); ! 3185: return; ! 3186: } else { ! 3187: ++if_stack->if_succeeded; ! 3188: output_line_command (ip, &outbuf, 1); ! 3189: } ! 3190: } ! 3191: ! 3192: /* ! 3193: * skip to #endif, #else, or #elif. adjust line numbers, etc. ! 3194: * leaves input ptr at the sharp sign found. ! 3195: * If ANY is nonzero, return at next directive of any sort. ! 3196: */ ! 3197: static ! 3198: skip_if_group (ip, any) ! 3199: FILE_BUF *ip; ! 3200: int any; ! 3201: { ! 3202: register U_CHAR *bp = ip->bufp, *cp; ! 3203: register U_CHAR *endb = ip->buf + ip->length; ! 3204: struct directive *kt; ! 3205: IF_STACK_FRAME *save_if_stack = if_stack; /* don't pop past here */ ! 3206: U_CHAR *beg_of_line = bp; ! 3207: ! 3208: while (bp < endb) { ! 3209: switch (*bp++) { ! 3210: case '/': /* possible comment */ ! 3211: if (*bp == '\\' && bp[1] == '\n') ! 3212: newline_fix (bp); ! 3213: if (*bp == '*' ! 3214: #ifdef CPLUSPLUS ! 3215: || *bp == '/' ! 3216: #endif ! 3217: ) { ! 3218: ip->bufp = ++bp; ! 3219: bp = skip_to_end_of_comment (ip, &ip->lineno); ! 3220: } ! 3221: break; ! 3222: case '\"': ! 3223: case '\'': ! 3224: if (!traditional) ! 3225: bp = skip_quoted_string (bp - 1, endb, ip->lineno, &ip->lineno, 0, 0); ! 3226: break; ! 3227: case '\n': ! 3228: ++ip->lineno; ! 3229: beg_of_line = bp; ! 3230: break; ! 3231: case '#': ! 3232: ip->bufp = bp - 1; ! 3233: ! 3234: /* # keyword: a # must be first nonblank char on the line */ ! 3235: if (beg_of_line == 0) ! 3236: break; ! 3237: /* Scan from start of line, skipping whitespace, comments ! 3238: and backslash-newlines, and see if we reach this #. ! 3239: If not, this # is not special. */ ! 3240: bp = beg_of_line; ! 3241: while (1) { ! 3242: if (is_hor_space[*bp]) ! 3243: bp++; ! 3244: else if (*bp == '\\' && bp[1] == '\n') ! 3245: bp += 2; ! 3246: else if (*bp == '/' && bp[1] == '*') { ! 3247: bp += 2; ! 3248: while (!(*bp == '*' && bp[1] == '/')) ! 3249: bp++; ! 3250: bp += 2; ! 3251: } ! 3252: #ifdef CPLUSPLUS ! 3253: else if (*bp == '/' && bp[1] == '/') { ! 3254: bp += 2; ! 3255: while (*bp++ != '\n') ; ! 3256: } ! 3257: #endif ! 3258: else break; ! 3259: } ! 3260: if (bp != ip->bufp) { ! 3261: bp = ip->bufp + 1; /* Reset bp to after the #. */ ! 3262: break; ! 3263: } ! 3264: ! 3265: bp = ip->bufp + 1; /* point at '#' */ ! 3266: ! 3267: /* Skip whitespace and \-newline. */ ! 3268: while (1) { ! 3269: if (is_hor_space[*bp]) ! 3270: bp++; ! 3271: else if (*bp == '\\' && bp[1] == '\n') ! 3272: bp += 2; ! 3273: else break; ! 3274: } ! 3275: ! 3276: cp = bp; ! 3277: ! 3278: /* Now find end of directive name. ! 3279: If we encounter a backslash-newline, exchange it with any following ! 3280: symbol-constituents so that we end up with a contiguous name. */ ! 3281: ! 3282: while (1) { ! 3283: if (is_idchar[*bp]) ! 3284: bp++; ! 3285: else { ! 3286: if (*bp == '\\' && bp[1] == '\n') ! 3287: name_newline_fix (bp); ! 3288: if (is_idchar[*bp]) ! 3289: bp++; ! 3290: else break; ! 3291: } ! 3292: } ! 3293: ! 3294: for (kt = directive_table; kt->length >= 0; kt++) { ! 3295: IF_STACK_FRAME *temp; ! 3296: if (strncmp (cp, kt->name, kt->length) == 0 ! 3297: && !is_idchar[cp[kt->length]]) { ! 3298: ! 3299: /* If we are asked to return on next directive, ! 3300: do so now. */ ! 3301: if (any) ! 3302: return; ! 3303: ! 3304: switch (kt->type) { ! 3305: case T_IF: ! 3306: case T_IFDEF: ! 3307: case T_IFNDEF: ! 3308: temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME)); ! 3309: temp->next = if_stack; ! 3310: if_stack = temp; ! 3311: temp->lineno = ip->lineno; ! 3312: temp->fname = ip->fname; ! 3313: temp->type = kt->type; ! 3314: break; ! 3315: case T_ELSE: ! 3316: case T_ENDIF: ! 3317: if (pedantic && if_stack != save_if_stack) ! 3318: validate_else (bp); ! 3319: case T_ELIF: ! 3320: if (if_stack == instack[indepth].if_stack) { ! 3321: error ("#%s not within a conditional", kt->name); ! 3322: break; ! 3323: } ! 3324: else if (if_stack == save_if_stack) ! 3325: return; /* found what we came for */ ! 3326: ! 3327: if (kt->type != T_ENDIF) { ! 3328: if (if_stack->type == T_ELSE) ! 3329: error ("#else or #elif after #else"); ! 3330: if_stack->type = kt->type; ! 3331: break; ! 3332: } ! 3333: ! 3334: temp = if_stack; ! 3335: if_stack = if_stack->next; ! 3336: free (temp); ! 3337: break; ! 3338: } ! 3339: break; ! 3340: } ! 3341: } ! 3342: } ! 3343: } ! 3344: ip->bufp = bp; ! 3345: /* after this returns, rescan will exit because ip->bufp ! 3346: now points to the end of the buffer. ! 3347: rescan is responsible for the error message also. */ ! 3348: } ! 3349: ! 3350: /* ! 3351: * handle a #else directive. Do this by just continuing processing ! 3352: * without changing if_stack ; this is so that the error message ! 3353: * for missing #endif's etc. will point to the original #if. It ! 3354: * is possible that something different would be better. ! 3355: */ ! 3356: do_else (buf, limit, op, keyword) ! 3357: U_CHAR *buf, *limit; ! 3358: FILE_BUF *op; ! 3359: struct directive *keyword; ! 3360: { ! 3361: FILE_BUF *ip = &instack[indepth]; ! 3362: ! 3363: if (pedantic) { ! 3364: SKIP_WHITE_SPACE (buf); ! 3365: if (buf != limit) ! 3366: warning ("text following #else violates ANSI standard"); ! 3367: } ! 3368: ! 3369: if (if_stack == instack[indepth].if_stack) { ! 3370: error ("#else not within a conditional"); ! 3371: return; ! 3372: } else { ! 3373: if (if_stack->type != T_IF && if_stack->type != T_ELIF) { ! 3374: error ("#else after #else"); ! 3375: fprintf (stderr, " (matches line %d", if_stack->lineno); ! 3376: if (strcmp (if_stack->fname, ip->fname) != 0) ! 3377: fprintf (stderr, ", file %s", if_stack->fname); ! 3378: fprintf (stderr, ")\n"); ! 3379: } ! 3380: if_stack->type = T_ELSE; ! 3381: } ! 3382: ! 3383: if (if_stack->if_succeeded) ! 3384: skip_if_group (ip, 0); ! 3385: else { ! 3386: ++if_stack->if_succeeded; /* continue processing input */ ! 3387: output_line_command (ip, op, 1); ! 3388: } ! 3389: } ! 3390: ! 3391: /* ! 3392: * unstack after #endif command ! 3393: */ ! 3394: do_endif (buf, limit, op, keyword) ! 3395: U_CHAR *buf, *limit; ! 3396: FILE_BUF *op; ! 3397: struct directive *keyword; ! 3398: { ! 3399: if (pedantic) { ! 3400: SKIP_WHITE_SPACE (buf); ! 3401: if (buf != limit) ! 3402: warning ("text following #endif violates ANSI standard"); ! 3403: } ! 3404: ! 3405: if (if_stack == instack[indepth].if_stack) ! 3406: error ("unbalanced #endif"); ! 3407: else { ! 3408: IF_STACK_FRAME *temp = if_stack; ! 3409: if_stack = if_stack->next; ! 3410: free (temp); ! 3411: output_line_command (&instack[indepth], op, 1); ! 3412: } ! 3413: } ! 3414: ! 3415: /* When an #else or #endif is found while skipping failed conditional, ! 3416: if -pedantic was specified, this is called to warn about text after ! 3417: the command name. P points to the first char after the command name. */ ! 3418: ! 3419: validate_else (p) ! 3420: register U_CHAR *p; ! 3421: { ! 3422: /* Advance P over whitespace and comments. */ ! 3423: while (1) { ! 3424: if (*p == '\\' && p[1] == '\n') ! 3425: p += 2; ! 3426: if (is_hor_space[*p]) ! 3427: p++; ! 3428: else if (*p == '/') { ! 3429: if (p[1] == '\\' && p[2] == '\n') ! 3430: newline_fix (p + 1); ! 3431: if (p[1] == '*') { ! 3432: p += 2; ! 3433: /* Don't bother warning about unterminated comments ! 3434: since that will happen later. Just be sure to exit. */ ! 3435: while (*p) { ! 3436: if (p[1] == '\\' && p[2] == '\n') ! 3437: newline_fix (p + 1); ! 3438: if (*p == '*' && p[1] == '/') { ! 3439: p += 2; ! 3440: break; ! 3441: } ! 3442: p++; ! 3443: } ! 3444: } ! 3445: #ifdef CPLUSPLUS ! 3446: else if (p[1] == '/') { ! 3447: p += 2; ! 3448: while (*p && *p++ != '\n') ; ! 3449: } ! 3450: #endif ! 3451: } else break; ! 3452: } ! 3453: if (*p && *p != '\n') ! 3454: warning ("text following #else or #endif violates ANSI standard"); ! 3455: } ! 3456: ! 3457: /* ! 3458: * Skip a comment, assuming the input ptr immediately follows the ! 3459: * initial slash-star. Bump line counter as necessary. ! 3460: * (The canonical line counter is &ip->lineno). ! 3461: * Don't use this routine (or the next one) if bumping the line ! 3462: * counter is not sufficient to deal with newlines in the string. ! 3463: */ ! 3464: U_CHAR * ! 3465: skip_to_end_of_comment (ip, line_counter) ! 3466: register FILE_BUF *ip; ! 3467: int *line_counter; /* place to remember newlines, or NULL */ ! 3468: { ! 3469: register U_CHAR *limit = ip->buf + ip->length; ! 3470: register U_CHAR *bp = ip->bufp; ! 3471: FILE_BUF *op = &outbuf; /* JF */ ! 3472: int output = put_out_comments && !line_counter; ! 3473: ! 3474: /* JF this line_counter stuff is a crock to make sure the ! 3475: comment is only put out once, no matter how many times ! 3476: the comment is skipped. It almost works */ ! 3477: if (output) { ! 3478: *op->bufp++ = '/'; ! 3479: *op->bufp++ = '*'; ! 3480: } ! 3481: #ifdef CPLUSPLUS ! 3482: if (bp[-1] == '/') { ! 3483: if (output) ! 3484: { ! 3485: while (bp < limit) ! 3486: if ((*op->bufp++ = *bp++) == '\n') ! 3487: { ! 3488: bp--; ! 3489: break; ! 3490: } ! 3491: op->bufp[-1] = '*'; ! 3492: *op->bufp++ = '/'; ! 3493: *op->bufp++ = '\n'; ! 3494: } ! 3495: else ! 3496: { ! 3497: while (bp < limit) { ! 3498: if (*bp++ == '\n') ! 3499: { ! 3500: bp--; ! 3501: break; ! 3502: } ! 3503: } ! 3504: } ! 3505: ip->bufp = bp; ! 3506: return bp; ! 3507: } ! 3508: #endif ! 3509: while (bp < limit) { ! 3510: if (output) ! 3511: *op->bufp++ = *bp; ! 3512: switch (*bp++) { ! 3513: case '\n': ! 3514: if (line_counter != NULL) ! 3515: ++*line_counter; ! 3516: if (output) ! 3517: ++op->lineno; ! 3518: break; ! 3519: case '*': ! 3520: if (*bp == '\\' && bp[1] == '\n') ! 3521: newline_fix (bp); ! 3522: if (*bp == '/') { ! 3523: if (output) ! 3524: *op->bufp++ = '/'; ! 3525: ip->bufp = ++bp; ! 3526: return bp; ! 3527: } ! 3528: break; ! 3529: } ! 3530: } ! 3531: ip->bufp = bp; ! 3532: return bp; ! 3533: } ! 3534: ! 3535: /* ! 3536: * Skip over a quoted string. BP points to the opening quote. ! 3537: * Returns a pointer after the closing quote. Don't go past LIMIT. ! 3538: * START_LINE is the line number of the starting point (but it need ! 3539: * not be valid if the starting point is inside a macro expansion). ! 3540: * ! 3541: * The input stack state is not changed. ! 3542: * ! 3543: * If COUNT_NEWLINES is nonzero, it points to an int to increment ! 3544: * for each newline passed. ! 3545: * ! 3546: * If BACKSLASH_NEWLINES_P is nonzero, store 1 thru it ! 3547: * if we pass a backslash-newline. ! 3548: * ! 3549: * If EOFP is nonzero, set *EOFP to 1 if the string is unterminated. ! 3550: */ ! 3551: U_CHAR * ! 3552: skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, eofp) ! 3553: register U_CHAR *bp; ! 3554: register U_CHAR *limit; ! 3555: int start_line; ! 3556: int *count_newlines; ! 3557: int *backslash_newlines_p; ! 3558: int *eofp; ! 3559: { ! 3560: register U_CHAR c, match; ! 3561: ! 3562: match = *bp++; ! 3563: while (1) { ! 3564: if (bp >= limit) { ! 3565: error_with_line (line_for_error (start_line), ! 3566: "unterminated string constant"); ! 3567: if (eofp) ! 3568: *eofp = 1; ! 3569: break; ! 3570: } ! 3571: c = *bp++; ! 3572: if (c == '\\') { ! 3573: while (*bp == '\\' && bp[1] == '\n') { ! 3574: if (backslash_newlines_p) ! 3575: *backslash_newlines_p = 1; ! 3576: if (count_newlines) ! 3577: ++*count_newlines; ! 3578: bp += 2; ! 3579: } ! 3580: if (*bp == '\n' && count_newlines) { ! 3581: if (backslash_newlines_p) ! 3582: *backslash_newlines_p = 1; ! 3583: ++*count_newlines; ! 3584: } ! 3585: bp++; ! 3586: } else if (c == '\n') { ! 3587: if (count_newlines) ! 3588: ++*count_newlines; ! 3589: } else if (c == match) ! 3590: break; ! 3591: } ! 3592: return bp; ! 3593: } ! 3594: ! 3595: /* ! 3596: * write out a #line command, for instance, after an #include file. ! 3597: * If CONDITIONAL is nonzero, we can omit the #line if it would ! 3598: * appear to be a no-op, and we can output a few newlines instead ! 3599: * if we want to increase the line number by a small amount. ! 3600: */ ! 3601: static ! 3602: output_line_command (ip, op, conditional) ! 3603: FILE_BUF *ip, *op; ! 3604: int conditional; ! 3605: { ! 3606: int len; ! 3607: char line_cmd_buf[500]; ! 3608: ! 3609: if (no_line_commands ! 3610: || ip->fname == NULL ! 3611: || no_output) { ! 3612: op->lineno = ip->lineno; ! 3613: return; ! 3614: } ! 3615: ! 3616: if (conditional) { ! 3617: if (ip->lineno == op->lineno) ! 3618: return; ! 3619: ! 3620: /* If the inherited line number is a little too small, ! 3621: output some newlines instead of a #line command. */ ! 3622: if (ip->lineno > op->lineno && ip->lineno < op->lineno + 8) { ! 3623: check_expand (op, 10); ! 3624: while (ip->lineno > op->lineno) { ! 3625: *op->bufp++ = '\n'; ! 3626: op->lineno++; ! 3627: } ! 3628: return; ! 3629: } ! 3630: } ! 3631: ! 3632: #ifdef OUTPUT_LINE_COMMANDS ! 3633: sprintf (line_cmd_buf, "#line %d \"%s\"\n", ip->lineno, ip->fname); ! 3634: #else ! 3635: sprintf (line_cmd_buf, "# %d \"%s\"\n", ip->lineno, ip->fname); ! 3636: #endif ! 3637: len = strlen (line_cmd_buf); ! 3638: check_expand (op, len + 1); ! 3639: if (op->bufp > op->buf && op->bufp[-1] != '\n') ! 3640: *op->bufp++ = '\n'; ! 3641: bcopy (line_cmd_buf, op->bufp, len); ! 3642: op->bufp += len; ! 3643: op->lineno = ip->lineno; ! 3644: } ! 3645: ! 3646: /* This structure represents one parsed argument in a macro call. ! 3647: `raw' points to the argument text as written (`raw_length' is its length). ! 3648: `expanded' points to the argument's macro-expansion ! 3649: (its length is `expand_length'). ! 3650: `stringified_length' is the length the argument would have ! 3651: if stringified. ! 3652: `free1' and `free2', if nonzero, point to blocks to be freed ! 3653: when the macro argument data is no longer needed. */ ! 3654: ! 3655: struct argdata { ! 3656: U_CHAR *raw, *expanded; ! 3657: int raw_length, expand_length; ! 3658: int stringified_length; ! 3659: U_CHAR *free1, *free2; ! 3660: char newlines; ! 3661: char comments; ! 3662: }; ! 3663: ! 3664: /* Expand a macro call. ! 3665: HP points to the symbol that is the macro being called. ! 3666: Put the result of expansion onto the input stack ! 3667: so that subsequent input by our caller will use it. ! 3668: ! 3669: If macro wants arguments, caller has already verified that ! 3670: an argument list follows; arguments come from the input stack. */ ! 3671: ! 3672: macroexpand (hp, op) ! 3673: HASHNODE *hp; ! 3674: FILE_BUF *op; ! 3675: { ! 3676: int nargs; ! 3677: DEFINITION *defn = hp->value.defn; ! 3678: register U_CHAR *xbuf; ! 3679: int xbuf_len; ! 3680: int start_line = instack[indepth].lineno; ! 3681: ! 3682: /* it might not actually be a macro. */ ! 3683: if (hp->type != T_MACRO) ! 3684: { ! 3685: special_symbol (hp, op); ! 3686: return; ! 3687: } ! 3688: ! 3689: nargs = defn->nargs; ! 3690: ! 3691: if (nargs >= 0) ! 3692: { ! 3693: register int i; ! 3694: struct argdata *args; ! 3695: char *parse_error = 0; ! 3696: ! 3697: args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata)); ! 3698: ! 3699: for (i = 0; i < nargs; i++) { ! 3700: args[i].raw = args[i].expanded = (U_CHAR *) ""; ! 3701: args[i].raw_length = args[i].expand_length ! 3702: = args[i].stringified_length = 0; ! 3703: args[i].free1 = args[i].free2 = 0; ! 3704: } ! 3705: ! 3706: /* Parse all the macro args that are supplied. I counts them. ! 3707: The first NARGS args are stored in ARGS. ! 3708: The rest are discarded. */ ! 3709: i = 0; ! 3710: do { ! 3711: /* Discard the open-parenthesis or comma before the next arg. */ ! 3712: ++instack[indepth].bufp; ! 3713: if (parse_error = macarg ((i < nargs || (nargs == 0 && i == 0)) ? &args[i] : 0)) ! 3714: { ! 3715: error_with_line (line_for_error (start_line), parse_error); ! 3716: break; ! 3717: } ! 3718: i++; ! 3719: } while (*instack[indepth].bufp != ')'); ! 3720: ! 3721: if (nargs == 0 && i == 1) { ! 3722: register U_CHAR *bp = args[0].raw; ! 3723: register U_CHAR *lim = bp + args[0].raw_length; ! 3724: while (bp != lim && is_space[*bp]) bp++; ! 3725: if (bp != lim) ! 3726: error ("arguments given to macro `%s'", hp->name); ! 3727: } else if (i < nargs) ! 3728: error ("only %d args to macro `%s'", i, hp->name); ! 3729: else if (i > nargs) ! 3730: error ("too many (%d) args to macro `%s'", i, hp->name); ! 3731: ! 3732: /* Swallow the closeparen. */ ! 3733: ++instack[indepth].bufp; ! 3734: ! 3735: /* If macro wants zero args, we parsed the arglist for checking only. ! 3736: Read directly from the macro definition. */ ! 3737: if (nargs == 0) { ! 3738: xbuf = defn->expansion; ! 3739: xbuf_len = defn->length; ! 3740: } else { ! 3741: register U_CHAR *exp = defn->expansion; ! 3742: register int offset; /* offset in expansion, ! 3743: copied a piece at a time */ ! 3744: register int totlen; /* total amount of exp buffer filled so far */ ! 3745: ! 3746: register struct reflist *ap; ! 3747: ! 3748: /* Macro really takes args. Compute the expansion of this call. */ ! 3749: ! 3750: /* Compute length in characters of the macro's expansion. */ ! 3751: xbuf_len = defn->length; ! 3752: for (ap = defn->pattern; ap != NULL; ap = ap->next) { ! 3753: if (ap->stringify) ! 3754: xbuf_len += args[ap->argno].stringified_length; ! 3755: else if (ap->raw_before || ap->raw_after) ! 3756: xbuf_len += args[ap->argno].raw_length; ! 3757: else ! 3758: xbuf_len += args[ap->argno].expand_length; ! 3759: } ! 3760: ! 3761: xbuf = (U_CHAR *) xmalloc (xbuf_len + 1); ! 3762: ! 3763: /* Generate in XBUF the complete expansion ! 3764: with arguments substituted in. ! 3765: TOTLEN is the total size generated so far. ! 3766: OFFSET is the index in the definition ! 3767: of where we are copying from. */ ! 3768: offset = totlen = 0; ! 3769: for (ap = defn->pattern; ap != NULL; ap = ap->next) { ! 3770: register struct argdata *arg = &args[ap->argno]; ! 3771: ! 3772: for (i = 0; i < ap->nchars; i++) ! 3773: xbuf[totlen++] = exp[offset++]; ! 3774: ! 3775: if (ap->stringify != 0) { ! 3776: int arglen = arg->raw_length; ! 3777: int escaped = 0; ! 3778: int in_string = 0; ! 3779: int c; ! 3780: i = 0; ! 3781: while (i < arglen ! 3782: && (c = arg->raw[i], is_space[c])) ! 3783: i++; ! 3784: while (i < arglen ! 3785: && (c = arg->raw[arglen - 1], is_space[c])) ! 3786: arglen--; ! 3787: xbuf[totlen++] = '\"'; /* insert beginning quote */ ! 3788: for (; i < arglen; i++) { ! 3789: c = arg->raw[i]; ! 3790: ! 3791: /* Special markers Newline Space and Newline Newline ! 3792: generate nothing for a stringified argument. */ ! 3793: if (c == '\n') { ! 3794: i++; ! 3795: continue; ! 3796: } ! 3797: ! 3798: /* Internal sequences of whitespace are replaced by one space. */ ! 3799: if (is_space[c]) { ! 3800: while (c = arg->raw[i+1], is_space[c]) i++; ! 3801: c = ' '; ! 3802: } ! 3803: ! 3804: if (escaped) ! 3805: escaped = 0; ! 3806: else { ! 3807: if (c == '\\') ! 3808: escaped = 1; ! 3809: if (in_string && c == in_string) ! 3810: in_string = 0; ! 3811: else if (c == '\"' || c == '\'') ! 3812: in_string = c; ! 3813: } ! 3814: ! 3815: /* Escape these chars */ ! 3816: if (c == '\"' || (in_string && c == '\\')) ! 3817: xbuf[totlen++] = '\\'; ! 3818: if (isprint (c)) ! 3819: xbuf[totlen++] = c; ! 3820: else { ! 3821: sprintf (&xbuf[totlen], "\\%03o", (unsigned int) c); ! 3822: totlen += 4; ! 3823: } ! 3824: } ! 3825: xbuf[totlen++] = '\"'; /* insert ending quote */ ! 3826: } else if (ap->raw_before || ap->raw_after) { ! 3827: U_CHAR *p1 = arg->raw; ! 3828: U_CHAR *l1 = p1 + arg->raw_length; ! 3829: if (ap->raw_before) { ! 3830: while (p1 != l1 && is_space[*p1]) p1++; ! 3831: while (p1 != l1 && is_idchar[*p1]) ! 3832: xbuf[totlen++] = *p1++; ! 3833: /* Delete any no-reexpansion marker that follows ! 3834: an identifier at the beginning of the argument ! 3835: if the argument is concatenated with what precedes it. */ ! 3836: if (p1[0] == '\n' && p1[1] == '-') ! 3837: p1 += 2; ! 3838: } ! 3839: if (ap->raw_after) { ! 3840: /* Arg is concatenated after: delete trailing whitespace, ! 3841: whitespace markers, and no-reexpansion markers. */ ! 3842: while (p1 != l1) { ! 3843: if (is_space[l1[-1]]) l1--; ! 3844: else if (l1[-1] == '-') { ! 3845: U_CHAR *p2 = l1 - 1; ! 3846: /* If a `-' is preceded by an odd number of newlines then it ! 3847: and the last newline are a no-reexpansion marker. */ ! 3848: while (p2 != p1 && p2[-1] == '\n') p2--; ! 3849: if ((l1 - 1 - p2) & 1) { ! 3850: l1 -= 2; ! 3851: } ! 3852: else break; ! 3853: } ! 3854: else break; ! 3855: } ! 3856: } ! 3857: bcopy (p1, xbuf + totlen, l1 - p1); ! 3858: totlen += l1 - p1; ! 3859: } else { ! 3860: bcopy (arg->expanded, xbuf + totlen, arg->expand_length); ! 3861: totlen += arg->expand_length; ! 3862: } ! 3863: ! 3864: if (totlen > xbuf_len) ! 3865: abort (); ! 3866: } ! 3867: ! 3868: /* if there is anything left of the definition ! 3869: after handling the arg list, copy that in too. */ ! 3870: ! 3871: for (i = offset; i < defn->length; i++) ! 3872: xbuf[totlen++] = exp[i]; ! 3873: ! 3874: xbuf[totlen] = 0; ! 3875: xbuf_len = totlen; ! 3876: ! 3877: for (i = 0; i < nargs; i++) { ! 3878: if (args[i].free1 != 0) ! 3879: free (args[i].free1); ! 3880: if (args[i].free2 != 0) ! 3881: free (args[i].free2); ! 3882: } ! 3883: } ! 3884: } ! 3885: else ! 3886: { ! 3887: xbuf = defn->expansion; ! 3888: xbuf_len = defn->length; ! 3889: } ! 3890: ! 3891: /* Now put the expansion on the input stack ! 3892: so our caller will commence reading from it. */ ! 3893: { ! 3894: register FILE_BUF *ip2; ! 3895: ! 3896: ip2 = &instack[++indepth]; ! 3897: ! 3898: ip2->fname = 0; ! 3899: ip2->lineno = 0; ! 3900: ip2->buf = xbuf; ! 3901: ip2->length = xbuf_len; ! 3902: ip2->bufp = xbuf; ! 3903: ip2->free = (nargs > 0) ? xbuf : 0; ! 3904: ip2->macro = hp; ! 3905: ip2->if_stack = if_stack; ! 3906: ! 3907: if (!traditional) ! 3908: hp->type = T_DISABLED; ! 3909: } ! 3910: } ! 3911: ! 3912: /* ! 3913: * Parse a macro argument and store the info on it into *ARGPTR. ! 3914: * Return nonzero to indicate a syntax error. ! 3915: */ ! 3916: ! 3917: char * ! 3918: macarg (argptr) ! 3919: register struct argdata *argptr; ! 3920: { ! 3921: FILE_BUF *ip = &instack[indepth]; ! 3922: int paren = 0; ! 3923: int newlines = 0; ! 3924: int comments = 0; ! 3925: ! 3926: /* Try to parse as much of the argument as exists at this ! 3927: input stack level. */ ! 3928: U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length, ! 3929: &paren, &newlines, &comments); ! 3930: ! 3931: /* If we find the end of the argument at this level, ! 3932: set up *ARGPTR to point at it in the input stack. */ ! 3933: if (!(ip->fname != 0 && (newlines != 0 || comments != 0)) ! 3934: && bp != ip->buf + ip->length) { ! 3935: if (argptr != 0) { ! 3936: argptr->raw = ip->bufp; ! 3937: argptr->raw_length = bp - ip->bufp; ! 3938: } ! 3939: ip->bufp = bp; ! 3940: } else { ! 3941: /* This input stack level ends before the macro argument does. ! 3942: We must pop levels and keep parsing. ! 3943: Therefore, we must allocate a temporary buffer and copy ! 3944: the macro argument into it. */ ! 3945: int bufsize = bp - ip->bufp; ! 3946: int extra = newlines; ! 3947: U_CHAR *buffer = (U_CHAR *) xmalloc (bufsize + extra + 1); ! 3948: int final_start = 0; ! 3949: ! 3950: bcopy (ip->bufp, buffer, bufsize); ! 3951: ip->bufp = bp; ! 3952: ip->lineno += newlines; ! 3953: ! 3954: while (bp == ip->buf + ip->length) { ! 3955: if (instack[indepth].macro == 0) { ! 3956: free (buffer); ! 3957: return "Unterminated macro call"; ! 3958: } ! 3959: ip->macro->type = T_MACRO; ! 3960: free (ip->buf); ! 3961: ip = &instack[--indepth]; ! 3962: newlines = 0; ! 3963: comments = 0; ! 3964: bp = macarg1 (ip->bufp, ip->buf + ip->length, &paren, ! 3965: &newlines, &comments); ! 3966: final_start = bufsize; ! 3967: bufsize += bp - ip->bufp; ! 3968: extra += newlines; ! 3969: buffer = (U_CHAR *) xrealloc (buffer, bufsize + extra + 1); ! 3970: bcopy (ip->bufp, buffer + bufsize - (bp - ip->bufp), bp - ip->bufp); ! 3971: ip->bufp = bp; ! 3972: ip->lineno += newlines; ! 3973: } ! 3974: ! 3975: /* Now, if arg is actually wanted, record its raw form, ! 3976: discarding comments and duplicating newlines in whatever ! 3977: part of it did not come from a macro expansion. ! 3978: EXTRA space has been preallocated for duplicating the newlines. ! 3979: FINAL_START is the index of the start of that part. */ ! 3980: if (argptr != 0) { ! 3981: argptr->raw = buffer; ! 3982: argptr->raw_length = bufsize; ! 3983: argptr->free1 = buffer; ! 3984: argptr->newlines = newlines; ! 3985: argptr->comments = comments; ! 3986: if ((newlines || comments) && ip->fname != 0) ! 3987: argptr->raw_length ! 3988: = final_start + ! 3989: discard_comments (argptr->raw + final_start, ! 3990: argptr->raw_length - final_start, ! 3991: newlines); ! 3992: argptr->raw[argptr->raw_length] = 0; ! 3993: if (argptr->raw_length > bufsize + extra) ! 3994: abort (); ! 3995: } ! 3996: } ! 3997: ! 3998: /* If we are not discarding this argument, ! 3999: macroexpand it and compute its length as stringified. ! 4000: All this info goes into *ARGPTR. */ ! 4001: ! 4002: if (argptr != 0) { ! 4003: FILE_BUF obuf; ! 4004: register U_CHAR *buf, *lim; ! 4005: register int totlen; ! 4006: ! 4007: obuf = expand_to_temp_buffer (argptr->raw, ! 4008: argptr->raw + argptr->raw_length, ! 4009: 1); ! 4010: ! 4011: argptr->expanded = obuf.buf; ! 4012: argptr->expand_length = obuf.length; ! 4013: argptr->free2 = obuf.buf; ! 4014: ! 4015: buf = argptr->raw; ! 4016: lim = buf + argptr->raw_length; ! 4017: ! 4018: while (buf != lim && is_space[*buf]) ! 4019: buf++; ! 4020: while (buf != lim && is_space[lim[-1]]) ! 4021: lim--; ! 4022: totlen = 2; /* Count opening and closing quote. */ ! 4023: while (buf != lim) { ! 4024: register U_CHAR c = *buf++; ! 4025: totlen++; ! 4026: /* Internal sequences of whitespace are replaced by one space. */ ! 4027: if (is_space[c]) ! 4028: SKIP_ALL_WHITE_SPACE (buf); ! 4029: else if (c == '\"' || c == '\\') /* escape these chars */ ! 4030: totlen++; ! 4031: else if (!isprint (c)) ! 4032: totlen += 3; ! 4033: } ! 4034: argptr->stringified_length = totlen; ! 4035: } ! 4036: return 0; ! 4037: } ! 4038: ! 4039: /* Scan text from START (inclusive) up to LIMIT (exclusive), ! 4040: counting parens in *DEPTHPTR, ! 4041: and return if reach LIMIT ! 4042: or before a `)' that would make *DEPTHPTR negative ! 4043: or before a comma when *DEPTHPTR is zero. ! 4044: Single and double quotes are matched and termination ! 4045: is inhibited within them. Comments also inhibit it. ! 4046: Value returned is pointer to stopping place. ! 4047: ! 4048: Increment *NEWLINES each time a newline is passed. ! 4049: Set *COMMENTS to 1 if a comment is seen. */ ! 4050: ! 4051: U_CHAR * ! 4052: macarg1 (start, limit, depthptr, newlines, comments) ! 4053: U_CHAR *start; ! 4054: register U_CHAR *limit; ! 4055: int *depthptr, *newlines, *comments; ! 4056: { ! 4057: register U_CHAR *bp = start; ! 4058: ! 4059: while (bp < limit) { ! 4060: switch (*bp) { ! 4061: case '(': ! 4062: (*depthptr)++; ! 4063: break; ! 4064: case ')': ! 4065: if (--(*depthptr) < 0) ! 4066: return bp; ! 4067: break; ! 4068: case '\n': ! 4069: ++*newlines; ! 4070: break; ! 4071: case '/': ! 4072: if (bp[1] == '\\' && bp[2] == '\n') ! 4073: newline_fix (bp + 1); ! 4074: #ifdef CPLUSPLUS ! 4075: if (bp[1] == '/') { ! 4076: *comments = 1; ! 4077: bp += 2; ! 4078: while (bp < limit && *bp++ != '\n') ; ! 4079: ++*newlines; ! 4080: break; ! 4081: } ! 4082: #endif ! 4083: if (bp[1] != '*' || bp + 1 >= limit) ! 4084: break; ! 4085: *comments = 1; ! 4086: bp += 2; ! 4087: while (bp + 1 < limit) { ! 4088: if (bp[0] == '*' ! 4089: && bp[1] == '\\' && bp[2] == '\n') ! 4090: newline_fix (bp + 1); ! 4091: if (bp[0] == '*' && bp[1] == '/') ! 4092: break; ! 4093: if (*bp == '\n') ++*newlines; ! 4094: bp++; ! 4095: } ! 4096: break; ! 4097: case '\'': ! 4098: case '\"': ! 4099: { ! 4100: int quotec; ! 4101: for (quotec = *bp++; bp + 1 < limit && *bp != quotec; bp++) { ! 4102: if (*bp == '\\') { ! 4103: bp++; ! 4104: if (*bp == '\n') ! 4105: ++*newlines; ! 4106: while (*bp == '\\' && bp[1] == '\n') { ! 4107: bp += 2; ! 4108: } ! 4109: } else if (*bp == '\n') ! 4110: ++*newlines; ! 4111: } ! 4112: } ! 4113: break; ! 4114: case ',': ! 4115: if ((*depthptr) == 0) ! 4116: return bp; ! 4117: break; ! 4118: } ! 4119: bp++; ! 4120: } ! 4121: ! 4122: return bp; ! 4123: } ! 4124: ! 4125: /* Discard comments and duplicate newlines ! 4126: in the string of length LENGTH at START, ! 4127: except inside of string constants. ! 4128: The string is copied into itself with its beginning staying fixed. ! 4129: ! 4130: NEWLINES is the number of newlines that must be duplicated. ! 4131: We assume that that much extra space is available past the end ! 4132: of the string. */ ! 4133: ! 4134: int ! 4135: discard_comments (start, length, newlines) ! 4136: U_CHAR *start; ! 4137: int length; ! 4138: int newlines; ! 4139: { ! 4140: register U_CHAR *ibp; ! 4141: register U_CHAR *obp; ! 4142: register U_CHAR *limit; ! 4143: register int c; ! 4144: ! 4145: /* If we have newlines to duplicate, copy everything ! 4146: that many characters up. Then, in the second part, ! 4147: we will have room to insert the newlines ! 4148: while copying down. ! 4149: NEWLINES may actually be too large, because it counts ! 4150: newlines in string constants, and we don't duplicate those. ! 4151: But that does no harm. */ ! 4152: if (newlines > 0) { ! 4153: ibp = start + length; ! 4154: obp = ibp + newlines; ! 4155: limit = start; ! 4156: while (limit != ibp) ! 4157: *--obp = *--ibp; ! 4158: } ! 4159: ! 4160: ibp = start + newlines; ! 4161: limit = start + length + newlines; ! 4162: obp = start; ! 4163: ! 4164: while (ibp < limit) { ! 4165: *obp++ = c = *ibp++; ! 4166: switch (c) { ! 4167: case '\n': ! 4168: /* Duplicate the newline. */ ! 4169: *obp++ = '\n'; ! 4170: break; ! 4171: ! 4172: case '/': ! 4173: if (*ibp == '\\' && ibp[1] == '\n') ! 4174: newline_fix (ibp); ! 4175: /* Delete any comment. */ ! 4176: #ifdef CPLUSPLUS ! 4177: if (ibp[0] == '/') { ! 4178: obp--; ! 4179: ibp++; ! 4180: while (ibp < limit && *ibp++ != '\n') ; ! 4181: break; ! 4182: } ! 4183: #endif ! 4184: if (ibp[0] != '*' || ibp + 1 >= limit) ! 4185: break; ! 4186: obp--; ! 4187: ibp++; ! 4188: while (ibp + 1 < limit) { ! 4189: if (ibp[0] == '*' ! 4190: && ibp[1] == '\\' && ibp[2] == '\n') ! 4191: newline_fix (ibp + 1); ! 4192: if (ibp[0] == '*' && ibp[1] == '/') ! 4193: break; ! 4194: ibp++; ! 4195: } ! 4196: ibp += 2; ! 4197: break; ! 4198: ! 4199: case '\'': ! 4200: case '\"': ! 4201: /* Notice and skip strings, so that we don't ! 4202: think that comments start inside them, ! 4203: and so we don't duplicate newlines in them. */ ! 4204: { ! 4205: int quotec = c; ! 4206: while (ibp < limit) ! 4207: { ! 4208: *obp++ = c = *ibp++; ! 4209: if (c == quotec) ! 4210: break; ! 4211: if (c == '\\' && ibp < limit) { ! 4212: while (*ibp == '\\' && ibp[1] == '\n') ! 4213: ibp += 2; ! 4214: *obp++ = *ibp++; ! 4215: } ! 4216: } ! 4217: } ! 4218: break; ! 4219: } ! 4220: } ! 4221: ! 4222: return obp - start; ! 4223: } ! 4224: ! 4225: /* ! 4226: * error - print error message and increment count of errors. ! 4227: */ ! 4228: error (msg, arg1, arg2, arg3) ! 4229: U_CHAR *msg; ! 4230: { ! 4231: int i; ! 4232: FILE_BUF *ip = NULL; ! 4233: ! 4234: for (i = indepth; i >= 0; i--) ! 4235: if (instack[i].fname != NULL) { ! 4236: ip = &instack[i]; ! 4237: break; ! 4238: } ! 4239: ! 4240: if (ip != NULL) ! 4241: fprintf (stderr, "%s:%d: ", ip->fname, ip->lineno); ! 4242: fprintf (stderr, msg, arg1, arg2, arg3); ! 4243: fprintf (stderr, "\n", msg); ! 4244: errors++; ! 4245: return 0; ! 4246: } ! 4247: ! 4248: /* Print error message but don't count it. */ ! 4249: ! 4250: warning (msg, arg1, arg2, arg3) ! 4251: U_CHAR *msg; ! 4252: { ! 4253: int i; ! 4254: FILE_BUF *ip = NULL; ! 4255: ! 4256: for (i = indepth; i >= 0; i--) ! 4257: if (instack[i].fname != NULL) { ! 4258: ip = &instack[i]; ! 4259: break; ! 4260: } ! 4261: ! 4262: if (ip != NULL) ! 4263: fprintf (stderr, "%s:%d: ", ip->fname, ip->lineno); ! 4264: fprintf (stderr, "warning: "); ! 4265: fprintf (stderr, msg, arg1, arg2, arg3); ! 4266: fprintf (stderr, "\n", msg); ! 4267: return 0; ! 4268: } ! 4269: ! 4270: error_with_line (line, msg, arg1, arg2, arg3) ! 4271: int line; ! 4272: U_CHAR *msg; ! 4273: { ! 4274: int i; ! 4275: FILE_BUF *ip = NULL; ! 4276: ! 4277: for (i = indepth; i >= 0; i--) ! 4278: if (instack[i].fname != NULL) { ! 4279: ip = &instack[i]; ! 4280: break; ! 4281: } ! 4282: ! 4283: if (ip != NULL) ! 4284: fprintf (stderr, "%s:%d: ", ip->fname, line); ! 4285: fprintf (stderr, msg, arg1, arg2, arg3); ! 4286: fprintf (stderr, "\n", msg); ! 4287: errors++; ! 4288: return 0; ! 4289: } ! 4290: ! 4291: /* Return the line at which an error occurred. ! 4292: The error is not necessarily associated with the current spot ! 4293: in the input stack, so LINE says where. LINE will have been ! 4294: copied from ip->lineno for the current input level. ! 4295: If the current level is for a file, we return LINE. ! 4296: But if the current level is not for a file, LINE is meaningless. ! 4297: In that case, we return the lineno of the innermost file. */ ! 4298: int ! 4299: line_for_error (line) ! 4300: int line; ! 4301: { ! 4302: int i; ! 4303: int line1 = line; ! 4304: ! 4305: for (i = indepth; i >= 0; ) { ! 4306: if (instack[i].fname != 0) ! 4307: return line1; ! 4308: i--; ! 4309: if (i < 0) ! 4310: return 0; ! 4311: line1 = instack[i].lineno; ! 4312: } ! 4313: } ! 4314: ! 4315: /* ! 4316: * If OBUF doesn't have NEEDED bytes after OPTR, make it bigger. ! 4317: * ! 4318: * As things stand, nothing is ever placed in the output buffer to be ! 4319: * removed again except when it's KNOWN to be part of an identifier, ! 4320: * so flushing and moving down everything left, instead of expanding, ! 4321: * should work ok. ! 4322: */ ! 4323: ! 4324: int ! 4325: grow_outbuf (obuf, needed) ! 4326: register FILE_BUF *obuf; ! 4327: register int needed; ! 4328: { ! 4329: register U_CHAR *p; ! 4330: int minsize; ! 4331: ! 4332: if (obuf->length - (obuf->bufp - obuf->buf) > needed) ! 4333: return; ! 4334: ! 4335: /* Make it at least twice as big as it is now. */ ! 4336: obuf->length *= 2; ! 4337: /* Make it have at least 150% of the free space we will need. */ ! 4338: minsize = (3 * needed) / 2 + (obuf->bufp - obuf->buf); ! 4339: if (minsize > obuf->length) ! 4340: obuf->length = minsize; ! 4341: ! 4342: if ((p = (U_CHAR *) xrealloc (obuf->buf, obuf->length)) == NULL) ! 4343: memory_full (); ! 4344: ! 4345: obuf->bufp = p + (obuf->bufp - obuf->buf); ! 4346: obuf->buf = p; ! 4347: } ! 4348: ! 4349: /* Symbol table for macro names and special symbols */ ! 4350: ! 4351: /* ! 4352: * install a name in the main hash table, even if it is already there. ! 4353: * name stops with first non alphanumeric, except leading '#'. ! 4354: * caller must check against redefinition if that is desired. ! 4355: * delete_macro () removes things installed by install () in fifo order. ! 4356: * this is important because of the `defined' special symbol used ! 4357: * in #if, and also if pushdef/popdef directives are ever implemented. ! 4358: * ! 4359: * If LEN is >= 0, it is the length of the name. ! 4360: * Otherwise, compute the length by scanning the entire name. ! 4361: * ! 4362: * If HASH is >= 0, it is the precomputed hash code. ! 4363: * Otherwise, compute the hash code. ! 4364: */ ! 4365: HASHNODE * ! 4366: install (name, len, type, value, hash) ! 4367: U_CHAR *name; ! 4368: int len; ! 4369: enum node_type type; ! 4370: int value; ! 4371: int hash; ! 4372: /* watch out here if sizeof (U_CHAR *) != sizeof (int) */ ! 4373: { ! 4374: register HASHNODE *hp; ! 4375: register int i, bucket; ! 4376: register U_CHAR *p, *q; ! 4377: ! 4378: if (len < 0) { ! 4379: p = name; ! 4380: while (is_idchar[*p]) ! 4381: p++; ! 4382: len = p - name; ! 4383: } ! 4384: ! 4385: if (hash < 0) ! 4386: hash = hashf (name, len, HASHSIZE); ! 4387: ! 4388: i = sizeof (HASHNODE) + len + 1; ! 4389: hp = (HASHNODE *) xmalloc (i); ! 4390: bucket = hash; ! 4391: hp->bucket_hdr = &hashtab[bucket]; ! 4392: hp->next = hashtab[bucket]; ! 4393: hashtab[bucket] = hp; ! 4394: hp->prev = NULL; ! 4395: if (hp->next != NULL) ! 4396: hp->next->prev = hp; ! 4397: hp->type = type; ! 4398: hp->length = len; ! 4399: hp->value.ival = value; ! 4400: hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE); ! 4401: p = hp->name; ! 4402: q = name; ! 4403: for (i = 0; i < len; i++) ! 4404: *p++ = *q++; ! 4405: hp->name[len] = 0; ! 4406: return hp; ! 4407: } ! 4408: ! 4409: /* ! 4410: * find the most recent hash node for name name (ending with first ! 4411: * non-identifier char) installed by install ! 4412: * ! 4413: * If LEN is >= 0, it is the length of the name. ! 4414: * Otherwise, compute the length by scanning the entire name. ! 4415: * ! 4416: * If HASH is >= 0, it is the precomputed hash code. ! 4417: * Otherwise, compute the hash code. ! 4418: */ ! 4419: HASHNODE * ! 4420: lookup (name, len, hash) ! 4421: U_CHAR *name; ! 4422: int len; ! 4423: int hash; ! 4424: { ! 4425: register U_CHAR *bp; ! 4426: register HASHNODE *bucket; ! 4427: ! 4428: if (len < 0) { ! 4429: for (bp = name; is_idchar[*bp]; bp++) ; ! 4430: len = bp - name; ! 4431: } ! 4432: ! 4433: if (hash < 0) ! 4434: hash = hashf (name, len, HASHSIZE); ! 4435: ! 4436: bucket = hashtab[hash]; ! 4437: while (bucket) { ! 4438: if (bucket->length == len && strncmp (bucket->name, name, len) == 0) ! 4439: return bucket; ! 4440: bucket = bucket->next; ! 4441: } ! 4442: return NULL; ! 4443: } ! 4444: ! 4445: /* ! 4446: * Delete a hash node. Some weirdness to free junk from macros. ! 4447: * More such weirdness will have to be added if you define more hash ! 4448: * types that need it. ! 4449: */ ! 4450: ! 4451: /* Note that the DEFINITION of a macro is removed from the hash table ! 4452: but its storage is not freed. This would be a storage leak ! 4453: except that it is not reasonable to keep undefining and redefining ! 4454: large numbers of macros many times. ! 4455: In any case, this is necessary, because a macro can be #undef'd ! 4456: in the middle of reading the arguments to a call to it. ! 4457: If #undef freed the DEFINITION, that would crash. */ ! 4458: ! 4459: delete_macro (hp) ! 4460: HASHNODE *hp; ! 4461: { ! 4462: ! 4463: if (hp->prev != NULL) ! 4464: hp->prev->next = hp->next; ! 4465: if (hp->next != NULL) ! 4466: hp->next->prev = hp->prev; ! 4467: ! 4468: /* make sure that the bucket chain header that ! 4469: the deleted guy was on points to the right thing afterwards. */ ! 4470: if (hp == *hp->bucket_hdr) ! 4471: *hp->bucket_hdr = hp->next; ! 4472: ! 4473: #if 0 ! 4474: if (hp->type == T_MACRO) { ! 4475: DEFINITION *d = hp->value.defn; ! 4476: struct reflist *ap, *nextap; ! 4477: ! 4478: for (ap = d->pattern; ap != NULL; ap = nextap) { ! 4479: nextap = ap->next; ! 4480: free (ap); ! 4481: } ! 4482: free (d); ! 4483: } ! 4484: #endif ! 4485: free (hp); ! 4486: } ! 4487: ! 4488: /* ! 4489: * return hash function on name. must be compatible with the one ! 4490: * computed a step at a time, elsewhere ! 4491: */ ! 4492: int ! 4493: hashf (name, len, hashsize) ! 4494: register U_CHAR *name; ! 4495: register int len; ! 4496: int hashsize; ! 4497: { ! 4498: register int r = 0; ! 4499: ! 4500: while (len--) ! 4501: r = HASHSTEP (r, *name++); ! 4502: ! 4503: return MAKE_POS (r) % hashsize; ! 4504: } ! 4505: ! 4506: /* Dump all macro definitions as #defines to stdout. */ ! 4507: ! 4508: dump_all_macros () ! 4509: { ! 4510: int bucket; ! 4511: ! 4512: for (bucket = 0; bucket < HASHSIZE; bucket++) { ! 4513: register HASHNODE *hp; ! 4514: ! 4515: for (hp = hashtab[bucket]; hp; hp= hp->next) { ! 4516: if (hp->type == T_MACRO) { ! 4517: register DEFINITION *defn = hp->value.defn; ! 4518: struct reflist *ap; ! 4519: int offset; ! 4520: int concat; ! 4521: ! 4522: ! 4523: /* Print the definition of the macro HP. */ ! 4524: ! 4525: printf ("#define %s", hp->name); ! 4526: if (defn->nargs >= 0) { ! 4527: int i; ! 4528: ! 4529: printf ("("); ! 4530: for (i = 0; i < defn->nargs; i++) { ! 4531: dump_arg_n (defn, i); ! 4532: if (i + 1 < defn->nargs) ! 4533: printf (", "); ! 4534: } ! 4535: printf (")"); ! 4536: } ! 4537: ! 4538: printf (" "); ! 4539: ! 4540: offset = 0; ! 4541: concat = 0; ! 4542: for (ap = defn->pattern; ap != NULL; ap = ap->next) { ! 4543: dump_defn_1 (defn->expansion, offset, ap->nchars); ! 4544: if (ap->nchars != 0) ! 4545: concat = 0; ! 4546: offset += ap->nchars; ! 4547: if (ap->stringify) ! 4548: printf (" #"); ! 4549: if (ap->raw_before && !concat) ! 4550: printf (" ## "); ! 4551: concat = 0; ! 4552: dump_arg_n (defn, ap->argno); ! 4553: if (ap->raw_after) { ! 4554: printf (" ## "); ! 4555: concat = 1; ! 4556: } ! 4557: } ! 4558: dump_defn_1 (defn->expansion, offset, defn->length - offset); ! 4559: printf ("\n"); ! 4560: } ! 4561: } ! 4562: } ! 4563: return NULL; ! 4564: } ! 4565: ! 4566: /* Output to stdout a substring of a macro definition. ! 4567: BASE is the beginning of the definition. ! 4568: Output characters START thru LENGTH. ! 4569: Discard newlines outside of strings, thus ! 4570: converting funny-space markers to ordinary spaces. */ ! 4571: ! 4572: dump_defn_1 (base, start, length) ! 4573: U_CHAR *base; ! 4574: int start; ! 4575: int length; ! 4576: { ! 4577: U_CHAR *p = base + start; ! 4578: U_CHAR *limit = base + start + length; ! 4579: ! 4580: while (p < limit) { ! 4581: if (*p != '\n') ! 4582: putchar (*p); ! 4583: else if (*p == '\"' || *p =='\'') { ! 4584: U_CHAR *p1 = skip_quoted_string (p, limit, 0, 0, 0); ! 4585: fwrite (p, p1 - p, 1, stdout); ! 4586: p = p1 - 1; ! 4587: } ! 4588: p++; ! 4589: } ! 4590: } ! 4591: ! 4592: /* Print the name of argument number ARGNUM of macro definition DEFN. ! 4593: Recall that DEFN->argnames contains all the arg names ! 4594: concatenated in reverse order with comma-space in between. */ ! 4595: ! 4596: dump_arg_n (defn, argnum) ! 4597: DEFINITION *defn; ! 4598: int argnum; ! 4599: { ! 4600: register U_CHAR *p = defn->argnames; ! 4601: while (argnum + 1 < defn->nargs) { ! 4602: p = (U_CHAR *) index (p, ' ') + 1; ! 4603: argnum++; ! 4604: } ! 4605: ! 4606: while (*p && *p != ',') { ! 4607: putchar (*p); ! 4608: p++; ! 4609: } ! 4610: } ! 4611: ! 4612: /* ! 4613: * initialize random junk in the hash table and maybe other places ! 4614: */ ! 4615: initialize_random_junk () ! 4616: { ! 4617: register int i; ! 4618: ! 4619: /* ! 4620: * Set up is_idchar and is_idstart tables. These should be ! 4621: * faster than saying (is_alpha (c) || c == '_'), etc. ! 4622: * Must do set up these things before calling any routines tthat ! 4623: * refer to them. ! 4624: */ ! 4625: for (i = 'a'; i <= 'z'; i++) { ! 4626: ++is_idchar[i - 'a' + 'A']; ! 4627: ++is_idchar[i]; ! 4628: ++is_idstart[i - 'a' + 'A']; ! 4629: ++is_idstart[i]; ! 4630: } ! 4631: for (i = '0'; i <= '9'; i++) ! 4632: ++is_idchar[i]; ! 4633: ++is_idchar['_']; ! 4634: ++is_idstart['_']; ! 4635: ++is_idchar['$']; ! 4636: ++is_idstart['$']; ! 4637: ! 4638: /* horizontal space table */ ! 4639: ++is_hor_space[' ']; ! 4640: ++is_hor_space['\t']; ! 4641: ++is_hor_space['\v']; ! 4642: ++is_hor_space['\f']; ! 4643: ! 4644: ++is_space[' ']; ! 4645: ++is_space['\t']; ! 4646: ++is_space['\v']; ! 4647: ++is_space['\f']; ! 4648: ++is_space['\n']; ! 4649: ! 4650: install ("__LINE__", -1, T_SPECLINE, 0, -1); ! 4651: install ("__DATE__", -1, T_DATE, 0, -1); ! 4652: install ("__FILE__", -1, T_FILE, 0, -1); ! 4653: install ("__VERSION__", -1, T_VERSION, 0, -1); ! 4654: install ("__TIME__", -1, T_TIME, 0, -1); ! 4655: install ("__STDC__", -1, T_CONST, 1, -1); ! 4656: /* install ("__GNU__", -1, T_CONST, 1, -1); */ ! 4657: /* This is supplied using a -D by the compiler driver ! 4658: so that it is present only when truly compiling with GNU C. */ ! 4659: } ! 4660: ! 4661: /* ! 4662: * process a given definition string, for initialization ! 4663: * If STR is just an identifier, define it with value 1. ! 4664: * If STR has anything after the identifier, then it should ! 4665: * be identifier-space-definition. ! 4666: */ ! 4667: make_definition (str) ! 4668: U_CHAR *str; ! 4669: { ! 4670: FILE_BUF *ip; ! 4671: struct directive *kt; ! 4672: U_CHAR *buf, *p; ! 4673: ! 4674: buf = str; ! 4675: p = str; ! 4676: while (is_idchar[*p]) p++; ! 4677: if (*p == 0) { ! 4678: buf = (U_CHAR *) alloca (p - buf + 4); ! 4679: strcpy (buf, str); ! 4680: strcat (buf, " 1"); ! 4681: } ! 4682: ! 4683: ip = &instack[++indepth]; ! 4684: ip->fname = "*Initialization*"; ! 4685: ! 4686: ip->buf = ip->bufp = buf; ! 4687: ip->length = strlen (buf); ! 4688: ip->lineno = 1; ! 4689: ip->macro = 0; ! 4690: ip->free = 0; ! 4691: ip->if_stack = if_stack; ! 4692: ! 4693: for (kt = directive_table; kt->type != T_DEFINE; kt++) ! 4694: ; ! 4695: ! 4696: /* pass NULL as output ptr to do_define since we KNOW it never ! 4697: does any output.... */ ! 4698: do_define (buf, buf + strlen (buf) , NULL, kt); ! 4699: --indepth; ! 4700: } ! 4701: ! 4702: /* JF, this does the work for the -U option */ ! 4703: make_undef (str) ! 4704: U_CHAR *str; ! 4705: { ! 4706: FILE_BUF *ip; ! 4707: struct directive *kt; ! 4708: ! 4709: ip = &instack[++indepth]; ! 4710: ip->fname = "*undef*"; ! 4711: ! 4712: ip->buf = ip->bufp = str; ! 4713: ip->length = strlen (str); ! 4714: ip->lineno = 1; ! 4715: ip->macro = 0; ! 4716: ip->free = 0; ! 4717: ip->if_stack = if_stack; ! 4718: ! 4719: for (kt = directive_table; kt->type != T_UNDEF; kt++) ! 4720: ; ! 4721: ! 4722: do_undef (str,str + strlen (str) - 1, NULL, kt); ! 4723: --indepth; ! 4724: } ! 4725: ! 4726: /* Add output to `deps_buffer' for the -M switch. ! 4727: STRING points to the text to be output. ! 4728: SIZE is the number of bytes, or 0 meaning output until a null. ! 4729: If SIZE is nonzero, we break the line first, if it is long enough. */ ! 4730: ! 4731: deps_output (string, size) ! 4732: char *string; ! 4733: int size; ! 4734: { ! 4735: if (size != 0 && deps_column > 50) ! 4736: { ! 4737: deps_output ("\\\n ", 0); ! 4738: deps_column = 0; ! 4739: } ! 4740: ! 4741: if (size == 0) ! 4742: size = strlen (string); ! 4743: ! 4744: if (deps_size + size + 1 > deps_allocated_size) ! 4745: { ! 4746: deps_allocated_size = deps_size + size + 50; ! 4747: deps_allocated_size *= 2; ! 4748: deps_buffer = (char *) xrealloc (deps_buffer, deps_allocated_size); ! 4749: } ! 4750: bcopy (string, &deps_buffer[deps_size], size); ! 4751: deps_size += size; ! 4752: deps_column += size; ! 4753: deps_buffer[deps_size] = 0; ! 4754: } ! 4755: ! 4756: #ifndef BSD ! 4757: #ifndef BSTRING ! 4758: ! 4759: void ! 4760: bzero (b, length) ! 4761: register char *b; ! 4762: register int length; ! 4763: { ! 4764: #ifdef VMS ! 4765: short zero = 0; ! 4766: long max_str = 65535; ! 4767: ! 4768: while (length > max_str) ! 4769: { ! 4770: (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b); ! 4771: length -= max_str; ! 4772: b += max_str; ! 4773: } ! 4774: (void) LIB$MOVC5 (&zero, &zero, &zero, &length, b); ! 4775: #else ! 4776: while (length-- > 0) ! 4777: *b++ = 0; ! 4778: #endif /* not VMS */ ! 4779: } ! 4780: ! 4781: void ! 4782: bcopy (b1, b2, length) ! 4783: register char *b1; ! 4784: register char *b2; ! 4785: register int length; ! 4786: { ! 4787: #ifdef VMS ! 4788: long max_str = 65535; ! 4789: ! 4790: while (length > max_str) ! 4791: { ! 4792: (void) LIB$MOVC3 (&max_str, b1, b2); ! 4793: length -= max_str; ! 4794: b1 += max_str; ! 4795: b2 += max_str; ! 4796: } ! 4797: (void) LIB$MOVC3 (&length, b1, b2); ! 4798: #else ! 4799: while (length-- > 0) ! 4800: *b2++ = *b1++; ! 4801: #endif /* not VMS */ ! 4802: } ! 4803: ! 4804: int ! 4805: bcmp (b1, b2, length) /* This could be a macro! */ ! 4806: register char *b1; ! 4807: register char *b2; ! 4808: register int length; ! 4809: { ! 4810: #ifdef VMS ! 4811: struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1}; ! 4812: struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2}; ! 4813: ! 4814: return STR$COMPARE (&src1, &src2); ! 4815: #else ! 4816: while (length-- > 0) ! 4817: if (*b1++ != *b2++) ! 4818: return 1; ! 4819: ! 4820: return 0; ! 4821: #endif /* not VMS */ ! 4822: } ! 4823: #endif /* not BSTRING */ ! 4824: #endif /* not BSD */ ! 4825: ! 4826: ! 4827: void ! 4828: fatal (str, arg) ! 4829: char *str, *arg; ! 4830: { ! 4831: fprintf (stderr, "%s: ", progname); ! 4832: fprintf (stderr, str, arg); ! 4833: fprintf (stderr, "\n"); ! 4834: exit (FATAL_EXIT_CODE); ! 4835: } ! 4836: ! 4837: void ! 4838: perror_with_name (name) ! 4839: char *name; ! 4840: { ! 4841: extern int errno, sys_nerr; ! 4842: extern char *sys_errlist[]; ! 4843: ! 4844: fprintf (stderr, "%s: ", progname); ! 4845: if (errno < sys_nerr) ! 4846: fprintf (stderr, "%s for `%s'\n", sys_errlist[errno], name); ! 4847: else ! 4848: fprintf (stderr, "cannot open `%s'\n", sys_errlist[errno], name); ! 4849: } ! 4850: ! 4851: void ! 4852: pfatal_with_name (name) ! 4853: char *name; ! 4854: { ! 4855: perror_with_name (name); ! 4856: exit (FATAL_EXIT_CODE); ! 4857: } ! 4858: ! 4859: ! 4860: void ! 4861: memory_full () ! 4862: { ! 4863: fatal ("Memory exhausted."); ! 4864: } ! 4865: ! 4866: ! 4867: char * ! 4868: xmalloc (size) ! 4869: int size; ! 4870: { ! 4871: extern char *malloc (); ! 4872: register char *ptr = malloc (size); ! 4873: if (ptr != 0) return (ptr); ! 4874: memory_full (); ! 4875: /*NOTREACHED*/ ! 4876: } ! 4877: ! 4878: char * ! 4879: xrealloc (old, size) ! 4880: char *old; ! 4881: int size; ! 4882: { ! 4883: extern char *realloc (); ! 4884: register char *ptr = realloc (old, size); ! 4885: if (ptr != 0) return (ptr); ! 4886: memory_full (); ! 4887: /*NOTREACHED*/ ! 4888: } ! 4889: ! 4890: char * ! 4891: xcalloc (number, size) ! 4892: int number, size; ! 4893: { ! 4894: extern char *malloc (); ! 4895: register int total = number * size; ! 4896: register char *ptr = malloc (total); ! 4897: if (ptr != 0) ! 4898: { ! 4899: if (total > 100) ! 4900: bzero (ptr, total); ! 4901: else { ! 4902: /* It's not too long, so loop, zeroing by longs. ! 4903: It must be safe because malloc values are always well aligned. */ ! 4904: register long *zp = (long *) ptr; ! 4905: register long *zl = (long *) (ptr + total - 4); ! 4906: register int i = total - 4; ! 4907: while (zp < zl) ! 4908: *zp++ = 0; ! 4909: if (i < 0) ! 4910: i = 0; ! 4911: while (i < total) ! 4912: ptr[i++] = 0; ! 4913: } ! 4914: return ptr; ! 4915: } ! 4916: memory_full (); ! 4917: /*NOTREACHED*/ ! 4918: } ! 4919: ! 4920: ! 4921: /* Get the file-mode and data size of the file open on FD ! 4922: and store them in *MODE_POINTER and *SIZE_POINTER. */ ! 4923: ! 4924: int ! 4925: file_size_and_mode (fd, mode_pointer, size_pointer) ! 4926: int fd; ! 4927: int *mode_pointer; ! 4928: long int *size_pointer; ! 4929: { ! 4930: struct stat sbuf; ! 4931: ! 4932: if (fstat (fd, &sbuf) < 0) return (-1); ! 4933: #ifdef VMS ! 4934: #ifdef __GNUC__ ! 4935: #ifdef stat_alignment_fix ! 4936: /* Fix the size data in the stat buffer (this is temporary!) */ ! 4937: sbuf.st_size = (stat_alignment_fix(&(sbuf))->st_size); ! 4938: #endif stat_alignment_fix ! 4939: #endif __GNUC__ ! 4940: #endif VMS ! 4941: if (mode_pointer) *mode_pointer = sbuf.st_mode; ! 4942: if (size_pointer) *size_pointer = sbuf.st_size; ! 4943: return 0; ! 4944: } ! 4945: ! 4946: #ifdef VMS ! 4947: ! 4948: /* Under VMS we need to fix up the "include" specification ! 4949: filename so that everything following the 1st slash is ! 4950: changed into its correct VMS file specification. */ ! 4951: ! 4952: hack_vms_include_specification (fname) ! 4953: char *fname; ! 4954: { ! 4955: register char *cp, *cp1, *cp2; ! 4956: char Local[512]; ! 4957: extern char *index (), *rindex (); ! 4958: ! 4959: /* Ignore leading "./"s */ ! 4960: while (fname[0] == '.' && fname[1] == '/') ! 4961: strcpy (fname, fname+2); ! 4962: /* Look for the boundary between the VMS and UNIX filespecs */ ! 4963: cp = rindex (fname, ']'); /* Look for end of dirspec. */ ! 4964: if (cp == 0) cp == rindex (fname, '>'); /* ... Ditto */ ! 4965: if (cp == 0) cp == rindex (fname, ':'); /* Look for end of devspec. */ ! 4966: if (cp) { ! 4967: cp++; ! 4968: } else { ! 4969: cp = index (fname, '/'); /* Look for the "/" */ ! 4970: } ! 4971: /* See if we found that 1st slash */ ! 4972: if (cp == 0) return; /* Nothing to do!!! */ ! 4973: if (*cp != '/') return; /* Nothing to do!!! */ ! 4974: /* Point to the UNIX filename part (which needs to be fixed!) */ ! 4975: cp1 = cp+1; ! 4976: /* If the directory spec is not rooted, we can just copy ! 4977: the UNIX filename part and we are done */ ! 4978: if (((cp - fname) > 2) ! 4979: && ((cp[-1] == ']') || (cp[-1] == '>')) ! 4980: && (cp[-2] != '.')) { ! 4981: strcpy (cp, cp1); ! 4982: return; ! 4983: } ! 4984: /* If there are no other slashes then the filename will be ! 4985: in the "root" directory. Otherwise, we need to add ! 4986: directory specifications. */ ! 4987: if (index (cp1, '/') == 0) { ! 4988: /* Just add "[000000]" as the directory string */ ! 4989: strcpy (Local, "[000000]"); ! 4990: cp2 = Local + strlen (Local); ! 4991: } else { ! 4992: /* Open the directory specification */ ! 4993: cp2 = Local; ! 4994: *cp2++ = '['; ! 4995: /* As long as there are still subdirectories to add, do them. */ ! 4996: while (index (cp1, '/') != 0) { ! 4997: /* If this token is "." we can ignore it */ ! 4998: if ((cp1[0] == '.') && (cp1[1] == '/')) { ! 4999: cp1 += 2; ! 5000: continue; ! 5001: } ! 5002: /* Add a subdirectory spec. */ ! 5003: if (cp2 != Local+1) *cp2++ = '.'; ! 5004: /* If this is ".." then the spec becomes "-" */ ! 5005: if ((cp1[0] == '.') && (cp1[1] == '.') && (cp[2] == '/')) { ! 5006: /* Add "-" and skip the ".." */ ! 5007: *cp2++ = '-'; ! 5008: cp1 += 3; ! 5009: continue; ! 5010: } ! 5011: /* Copy the subdirectory */ ! 5012: while (*cp1 != '/') *cp2++= *cp1++; ! 5013: cp1++; /* Skip the "/" */ ! 5014: } ! 5015: /* Close the directory specification */ ! 5016: *cp2++ = ']'; ! 5017: } ! 5018: /* Now add the filename */ ! 5019: while (*cp1) *cp2++ = *cp1++; ! 5020: *cp2 = 0; ! 5021: /* Now append it to the original VMS spec. */ ! 5022: strcpy (cp, Local); ! 5023: return; ! 5024: } ! 5025: #endif /* VMS */ ! 5026: ! 5027: #ifdef VMS ! 5028: ! 5029: /* These are the read/write replacement routines for ! 5030: VAX-11 "C". They make read/write behave enough ! 5031: like their UNIX counterparts that CCCP will work */ ! 5032: ! 5033: int ! 5034: read (fd, buf, size) ! 5035: int fd; ! 5036: char *buf; ! 5037: int size; ! 5038: { ! 5039: #undef read /* Get back the REAL read routine */ ! 5040: register int i; ! 5041: register int total = 0; ! 5042: ! 5043: /* Read until the buffer is exhausted */ ! 5044: while (size > 0) { ! 5045: /* Limit each read to 32KB */ ! 5046: i = (size > (32*1024)) ? (32*1024) : size; ! 5047: i = read (fd, buf, i); ! 5048: if (i <= 0) { ! 5049: if (i == 0) return (total); ! 5050: return(i); ! 5051: } ! 5052: /* Account for this read */ ! 5053: total += i; ! 5054: buf += i; ! 5055: size -= i; ! 5056: } ! 5057: return (total); ! 5058: } ! 5059: ! 5060: int ! 5061: write (fd, buf, size) ! 5062: int fd; ! 5063: char *buf; ! 5064: int size; ! 5065: { ! 5066: #undef write /* Get back the REAL write routine */ ! 5067: int i; ! 5068: int j; ! 5069: ! 5070: /* Limit individual writes to 32Kb */ ! 5071: i = size; ! 5072: while (i > 0) { ! 5073: j = (i > (32*1024)) ? (32*1024) : i; ! 5074: if (write (fd, buf, j) < 0) return (-1); ! 5075: /* Account for the data written */ ! 5076: buf += j; ! 5077: i -= j; ! 5078: } ! 5079: return (size); ! 5080: } ! 5081: ! 5082: #endif /* VMS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.