Annotation of GNUtools/cc/cccp.c, revision 1.1

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

unix.superglobalmegacorp.com

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