Annotation of researchv10dc/cmd/gcc/cccp.c, revision 1.1.1.1

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, &copy_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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.