Annotation of gcc/cccp.c, revision 1.1.1.8

1.1       root        1: /* C Compatible Compiler Preprocessor (CCCP)
1.1.1.8 ! root        2:    Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
1.1.1.7   root        3:    Written by Paul Rubin, June 1986
                      4:    Adapted to ANSI C, Richard Stallman, Jan 1987
1.1       root        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
1.1.1.8 ! root       18: Foundation, 59 Temple Place - Suite 330,
        !            19: Boston, MA 02111-1307, USA.
1.1       root       20: 
                     21:  In other words, you are welcome to use, share and improve this program.
                     22:  You are forbidden to forbid anyone else to use, share and improve
                     23:  what you give them.   Help stamp out software-hoarding!  */
                     24: 
                     25: typedef unsigned char U_CHAR;
                     26: 
                     27: #ifdef EMACS
                     28: #define NO_SHORTNAMES
                     29: #include "../src/config.h"
                     30: #ifdef open
                     31: #undef open
                     32: #undef read
                     33: #undef write
                     34: #endif /* open */
                     35: #endif /* EMACS */
                     36: 
                     37: /* The macro EMACS is defined when cpp is distributed as part of Emacs,
                     38:    for the sake of machines with limited C compilers.  */
                     39: #ifndef EMACS
                     40: #include "config.h"
                     41: #endif /* not EMACS */
                     42: 
                     43: #ifndef STANDARD_INCLUDE_DIR
                     44: #define STANDARD_INCLUDE_DIR "/usr/include"
                     45: #endif
                     46: 
                     47: #ifndef LOCAL_INCLUDE_DIR
                     48: #define LOCAL_INCLUDE_DIR "/usr/local/include"
                     49: #endif
                     50: 
1.1.1.4   root       51: #if 0 /* We can't get ptrdiff_t, so I arranged not to need PTR_INT_TYPE.  */
                     52: #ifdef __STDC__
                     53: #define PTR_INT_TYPE ptrdiff_t
                     54: #else
                     55: #define PTR_INT_TYPE long
                     56: #endif
                     57: #endif /* 0 */
                     58: 
1.1       root       59: #include "pcp.h"
                     60: 
1.1.1.3   root       61: /* By default, colon separates directories in a path.  */
                     62: #ifndef PATH_SEPARATOR
                     63: #define PATH_SEPARATOR ':'
                     64: #endif
                     65: 
1.1       root       66: #include <sys/types.h>
                     67: #include <sys/stat.h>
                     68: #include <ctype.h>
                     69: #include <stdio.h>
1.1.1.5   root       70: #include <signal.h>
1.1       root       71: 
1.1.1.8 ! root       72: /* The following symbols should be autoconfigured:
        !            73:        HAVE_FCNTL_H
        !            74:        HAVE_STDLIB_H
        !            75:        HAVE_SYS_TIME_H
        !            76:        HAVE_UNISTD_H
        !            77:        STDC_HEADERS
        !            78:        TIME_WITH_SYS_TIME
        !            79:    In the mean time, we'll get by with approximations based
        !            80:    on existing GCC configuration symbols.  */
        !            81: 
        !            82: #ifdef POSIX
        !            83: # ifndef HAVE_STDLIB_H
        !            84: # define HAVE_STDLIB_H 1
        !            85: # endif
        !            86: # ifndef HAVE_UNISTD_H
        !            87: # define HAVE_UNISTD_H 1
        !            88: # endif
        !            89: # ifndef STDC_HEADERS
        !            90: # define STDC_HEADERS 1
        !            91: # endif
        !            92: #endif /* defined (POSIX) */
        !            93: 
        !            94: #if defined (POSIX) || (defined (USG) && !defined (VMS))
        !            95: # ifndef HAVE_FCNTL_H
        !            96: # define HAVE_FCNTL_H 1
        !            97: # endif
        !            98: #endif
        !            99: 
        !           100: #ifndef RLIMIT_STACK
        !           101: # include <time.h>
1.1       root      102: #else
1.1.1.8 ! root      103: # if TIME_WITH_SYS_TIME
        !           104: #  include <sys/time.h>
        !           105: #  include <time.h>
        !           106: # else
        !           107: #  if HAVE_SYS_TIME_H
        !           108: #   include <sys/time.h>
        !           109: #  else
        !           110: #   include <time.h>
        !           111: #  endif
        !           112: # endif
        !           113: # include <sys/resource.h>
        !           114: #endif
        !           115: 
        !           116: #if HAVE_FCNTL_H
        !           117: # include <fcntl.h>
        !           118: #endif
1.1       root      119: 
1.1.1.5   root      120: /* This defines "errno" properly for VMS, and gives us EACCES. */
                    121: #include <errno.h>
                    122: 
1.1.1.8 ! root      123: #if HAVE_STDLIB_H
        !           124: # include <stdlib.h>
        !           125: #else
        !           126: char *getenv ();
        !           127: #endif
        !           128: 
        !           129: #if STDC_HEADERS
        !           130: # include <string.h>
        !           131: # ifndef bcmp
        !           132: # define bcmp(a, b, n) memcmp (a, b, n)
        !           133: # endif
        !           134: # ifndef bcopy
        !           135: # define bcopy(s, d, n) memcpy (d, s, n)
        !           136: # endif
        !           137: # ifndef bzero
        !           138: # define bzero(d, n) memset (d, 0, n)
        !           139: # endif
        !           140: #else /* !STDC_HEADERS */
        !           141: char *index ();
        !           142: char *rindex ();
        !           143: 
        !           144: # if !defined (BSTRING) && (defined (USG) || defined (VMS))
        !           145: 
        !           146: #  ifndef bcmp
        !           147: #  define bcmp my_bcmp
        !           148: static int
        !           149: my_bcmp (a, b, n)
        !           150:      register char *a;
        !           151:      register char *b;
        !           152:      register unsigned n;
        !           153: {
        !           154:    while (n-- > 0)
        !           155:      if (*a++ != *b++)
        !           156:        return 1;
        !           157: 
        !           158:    return 0;
        !           159: }
        !           160: #  endif /* !defined (bcmp) */
        !           161: 
        !           162: #  ifndef bcopy
        !           163: #  define bcopy my_bcopy
        !           164: static void
        !           165: my_bcopy (s, d, n)
        !           166:      register char *s;
        !           167:      register char *d;
        !           168:      register unsigned n;
        !           169: {
        !           170:   while (n-- > 0)
        !           171:     *d++ = *s++;
        !           172: }
        !           173: #  endif /* !defined (bcopy) */
        !           174: 
        !           175: #  ifndef bzero
        !           176: #  define bzero my_bzero
        !           177: static void
        !           178: my_bzero (b, length)
        !           179:      register char *b;
        !           180:      register unsigned length;
        !           181: {
        !           182:   while (length-- > 0)
        !           183:     *b++ = 0;
        !           184: }
        !           185: #  endif /* !defined (bzero) */
        !           186: 
        !           187: # endif /* !defined (BSTRING) && (defined (USG) || defined (VMS)) */
        !           188: #endif /* ! STDC_HEADERS */
        !           189: 
        !           190: #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6)
        !           191: # define __attribute__(x)
        !           192: #endif
        !           193: 
        !           194: #ifndef PROTO
        !           195: # if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
        !           196: #  define PROTO(ARGS) ARGS
        !           197: # else
        !           198: #  define PROTO(ARGS) ()
        !           199: # endif
        !           200: #endif
        !           201: 
        !           202: #if defined (__STDC__) && defined (HAVE_VPRINTF)
        !           203: # include <stdarg.h>
        !           204: # define VA_START(va_list, var) va_start (va_list, var)
        !           205: # define PRINTF_ALIST(msg) char *msg, ...
        !           206: # define PRINTF_DCL(msg)
        !           207: # define PRINTF_PROTO(ARGS, m, n) PROTO (ARGS) __attribute__ ((format (printf, m, n)))
        !           208: #else
        !           209: # include <varargs.h>
        !           210: # define VA_START(va_list, var) va_start (va_list)
        !           211: # define PRINTF_ALIST(msg) msg, va_alist
        !           212: # define PRINTF_DCL(msg) char *msg; va_dcl
        !           213: # define PRINTF_PROTO(ARGS, m, n) () __attribute__ ((format (printf, m, n)))
        !           214: # define vfprintf(file, msg, args) \
        !           215:     { \
        !           216:       char *a0 = va_arg(args, char *); \
        !           217:       char *a1 = va_arg(args, char *); \
        !           218:       char *a2 = va_arg(args, char *); \
        !           219:       char *a3 = va_arg(args, char *); \
        !           220:       fprintf (file, msg, a0, a1, a2, a3); \
        !           221:     }
        !           222: #endif
        !           223: 
        !           224: #define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2)
        !           225: #define PRINTF_PROTO_2(ARGS) PRINTF_PROTO(ARGS, 2, 3)
        !           226: #define PRINTF_PROTO_3(ARGS) PRINTF_PROTO(ARGS, 3, 4)
        !           227: 
        !           228: #if HAVE_UNISTD_H
        !           229: # include <unistd.h>
        !           230: #endif
        !           231: 
1.1       root      232: /* VMS-specific definitions */
                    233: #ifdef VMS
                    234: #include <descrip.h>
                    235: #define O_RDONLY       0       /* Open arg for Read/Only  */
                    236: #define O_WRONLY       1       /* Open arg for Write/Only */
1.1.1.5   root      237: #define read(fd,buf,size)      VMS_read (fd,buf,size)
                    238: #define write(fd,buf,size)     VMS_write (fd,buf,size)
                    239: #define open(fname,mode,prot)  VMS_open (fname,mode,prot)
                    240: #define fopen(fname,mode)      VMS_fopen (fname,mode)
                    241: #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
                    242: #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
1.1.1.8 ! root      243: #define fstat(fd,stbuf)                VMS_fstat (fd,stbuf)
        !           244: static int VMS_fstat (), VMS_stat ();
1.1.1.4   root      245: static char * VMS_strncat ();
1.1       root      246: static int VMS_read ();
                    247: static int VMS_write ();
                    248: static int VMS_open ();
                    249: static FILE * VMS_fopen ();
                    250: static FILE * VMS_freopen ();
                    251: static void hack_vms_include_specification ();
                    252: typedef struct { unsigned :16, :16, :16; } vms_ino_t;
                    253: #define ino_t vms_ino_t
1.1.1.4   root      254: #define INCLUDE_LEN_FUDGE 10   /* leave room for VMS syntax conversion */
1.1       root      255: #ifdef __GNUC__
                    256: #define BSTRING                        /* VMS/GCC supplies the bstring routines */
                    257: #endif /* __GNUC__ */
                    258: #endif /* VMS */
                    259: 
                    260: #ifndef O_RDONLY
                    261: #define O_RDONLY 0
                    262: #endif
                    263: 
                    264: #undef MIN
                    265: #undef MAX
                    266: #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
                    267: #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
                    268: 
1.1.1.4   root      269: /* Find the largest host integer type and set its size and type.  */
                    270: 
                    271: #ifndef HOST_BITS_PER_WIDE_INT
                    272: 
                    273: #if HOST_BITS_PER_LONG > HOST_BITS_PER_INT
                    274: #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
                    275: #define HOST_WIDE_INT long
                    276: #else
                    277: #define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
                    278: #define HOST_WIDE_INT int
                    279: #endif
                    280: 
                    281: #endif
                    282: 
1.1       root      283: #ifndef S_ISREG
                    284: #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
                    285: #endif
                    286: 
1.1.1.5   root      287: #ifndef S_ISDIR
                    288: #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
                    289: #endif
                    290: 
1.1.1.4   root      291: /* Define a generic NULL if one hasn't already been defined.  */
                    292: 
                    293: #ifndef NULL
                    294: #define NULL 0
                    295: #endif
                    296: 
                    297: #ifndef GENERIC_PTR
                    298: #if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
                    299: #define GENERIC_PTR void *
                    300: #else
                    301: #define GENERIC_PTR char *
                    302: #endif
                    303: #endif
                    304: 
                    305: #ifndef NULL_PTR
                    306: #define NULL_PTR ((GENERIC_PTR)0)
                    307: #endif
                    308: 
                    309: #ifndef INCLUDE_LEN_FUDGE
                    310: #define INCLUDE_LEN_FUDGE 0
                    311: #endif
                    312: 
1.1       root      313: /* External declarations.  */
                    314: 
                    315: extern char *version_string;
1.1.1.7   root      316: #ifndef VMS
                    317: #ifndef HAVE_STRERROR
1.1       root      318: extern int sys_nerr;
1.1.1.8 ! root      319: #if defined(bsd4_4)
1.1.1.6   root      320: extern const char *const sys_errlist[];
                    321: #else
1.1       root      322: extern char *sys_errlist[];
1.1.1.6   root      323: #endif
1.1.1.8 ! root      324: #else  /* HAVE_STRERROR */
1.1.1.7   root      325: char *strerror ();
                    326: #endif
                    327: #else  /* VMS */
                    328: char *strerror (int,...);
                    329: #endif
1.1.1.8 ! root      330: int parse_escape PROTO((char **));
        !           331: HOST_WIDE_INT parse_c_expression PROTO((char *));
1.1       root      332: 
                    333: #ifndef errno
                    334: extern int errno;
                    335: #endif
                    336: 
                    337: /* Name under which this program was invoked.  */
                    338: 
                    339: static char *progname;
                    340: 
1.1.1.4   root      341: /* Nonzero means use extra default include directories for C++.  */
1.1       root      342: 
                    343: static int cplusplus;
                    344: 
1.1.1.4   root      345: /* Nonzero means handle cplusplus style comments */
                    346: 
                    347: static int cplusplus_comments;
                    348: 
1.1       root      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: 
1.1.1.7   root      365: static int for_lint = 0;
1.1       root      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: 
1.1.1.7   root      381: /* Nonzero if missing .h files in -M output are assumed to be generated
                    382:    files and not errors.  */
                    383: 
                    384: static int print_deps_missing_files = 0;
                    385: 
1.1       root      386: /* Nonzero means print names of header files (-H).  */
                    387: 
                    388: static int print_include_names = 0;
                    389: 
                    390: /* Nonzero means don't output line number information.  */
                    391: 
1.1.1.8 ! root      392: static int no_line_directives;
1.1       root      393: 
1.1.1.7   root      394: /* Nonzero means output the text in failing conditionals,
                    395:    inside #failed ... #endfailed.  */
                    396: 
                    397: static int output_conditionals;
                    398: 
1.1       root      399: /* dump_only means inhibit output of the preprocessed text
                    400:              and instead output the definitions of all user-defined
                    401:              macros in a form suitable for use as input to cccp.
                    402:    dump_names means pass #define and the macro name through to output.
                    403:    dump_definitions means pass the whole definition (plus #define) through
                    404: */
                    405: 
                    406: static enum {dump_none, dump_only, dump_names, dump_definitions}
                    407:      dump_macros = dump_none;
                    408: 
                    409: /* Nonzero means pass all #define and #undef directives which we actually
                    410:    process through to the output stream.  This feature is used primarily
                    411:    to allow cc1 to record the #defines and #undefs for the sake of
                    412:    debuggers which understand about preprocessor macros, but it may
                    413:    also be useful with -E to figure out how symbols are defined, and
                    414:    where they are defined.  */
                    415: static int debug_output = 0;
                    416: 
                    417: /* Nonzero indicates special processing used by the pcp program.  The
                    418:    special effects of this mode are: 
                    419:      
                    420:      Inhibit all macro expansion, except those inside #if directives.
                    421: 
                    422:      Process #define directives normally, and output their contents 
                    423:      to the output file.
                    424: 
                    425:      Output preconditions to pcp_outfile indicating all the relevant
                    426:      preconditions for use of this file in a later cpp run.
                    427: */
                    428: static FILE *pcp_outfile;
                    429: 
                    430: /* Nonzero means we are inside an IF during a -pcp run.  In this mode
                    431:    macro expansion is done, and preconditions are output for all macro
                    432:    uses requiring them. */
                    433: static int pcp_inside_if;
                    434: 
1.1.1.5   root      435: /* Nonzero means never to include precompiled files.
                    436:    This is 1 since there's no way now to make precompiled files,
                    437:    so it's not worth testing for them.  */
                    438: static int no_precomp = 1;
1.1       root      439: 
                    440: /* Nonzero means give all the error messages the ANSI standard requires.  */
                    441: 
                    442: int pedantic;
                    443: 
                    444: /* Nonzero means try to make failure to fit ANSI C an error.  */
                    445: 
                    446: static int pedantic_errors;
                    447: 
                    448: /* Nonzero means don't print warning messages.  -w.  */
                    449: 
                    450: static int inhibit_warnings = 0;
                    451: 
                    452: /* Nonzero means warn if slash-star appears in a comment.  */
                    453: 
                    454: static int warn_comments;
                    455: 
                    456: /* Nonzero means warn if a macro argument is (or would be)
                    457:    stringified with -traditional.  */
                    458: 
                    459: static int warn_stringify;
                    460: 
                    461: /* Nonzero means warn if there are any trigraphs.  */
                    462: 
                    463: static int warn_trigraphs;
                    464: 
1.1.1.2   root      465: /* Nonzero means warn if #import is used.  */
                    466: 
                    467: static int warn_import = 1;
                    468: 
1.1       root      469: /* Nonzero means turn warnings into errors.  */
                    470: 
                    471: static int warnings_are_errors;
                    472: 
                    473: /* Nonzero means try to imitate old fashioned non-ANSI preprocessor.  */
                    474: 
                    475: int traditional;
                    476: 
                    477: /* Nonzero causes output not to be done,
                    478:    but directives such as #define that have side effects
                    479:    are still obeyed.  */
                    480: 
                    481: static int no_output;
                    482: 
1.1.1.7   root      483: /* Nonzero means this file was included with a -imacros or -include
                    484:    command line and should not be recorded as an include file.  */
                    485: 
                    486: static int no_record_file;
                    487: 
1.1       root      488: /* Nonzero means that we have finished processing the command line options.
                    489:    This flag is used to decide whether or not to issue certain errors
                    490:    and/or warnings.  */
                    491: 
                    492: static int done_initializing = 0;
1.1.1.5   root      493: 
                    494: /* Line where a newline was first seen in a string constant.  */
                    495: 
                    496: static int multiline_string_line = 0;
1.1       root      497: 
                    498: /* I/O buffer structure.
                    499:    The `fname' field is nonzero for source files and #include files
                    500:    and for the dummy text used for -D and -U.
                    501:    It is zero for rescanning results of macro expansion
                    502:    and for expanding macro arguments.  */
1.1.1.6   root      503: #define INPUT_STACK_MAX 400
1.1       root      504: static struct file_buf {
                    505:   char *fname;
1.1.1.8 ! root      506:   /* Filename specified with #line directive.  */
1.1       root      507:   char *nominal_fname;
                    508:   /* Record where in the search path this file was found.
                    509:      For #include_next.  */
                    510:   struct file_name_list *dir;
                    511:   int lineno;
                    512:   int length;
                    513:   U_CHAR *buf;
                    514:   U_CHAR *bufp;
                    515:   /* Macro that this level is the expansion of.
                    516:      Included so that we can reenable the macro
                    517:      at the end of this level.  */
                    518:   struct hashnode *macro;
                    519:   /* Value of if_stack at start of this file.
                    520:      Used to prohibit unmatched #endif (etc) in an include file.  */
                    521:   struct if_stack *if_stack;
                    522:   /* Object to be freed at end of input at this level.  */
                    523:   U_CHAR *free_ptr;
                    524:   /* True if this is a header file included using <FILENAME>.  */
                    525:   char system_header_p;
                    526: } instack[INPUT_STACK_MAX];
                    527: 
                    528: static int last_error_tick;       /* Incremented each time we print it.  */
                    529: static int input_file_stack_tick;  /* Incremented when the status changes.  */
                    530: 
                    531: /* Current nesting level of input sources.
                    532:    `instack[indepth]' is the level currently being read.  */
                    533: static int indepth = -1;
                    534: #define CHECK_DEPTH(code) \
                    535:   if (indepth >= (INPUT_STACK_MAX - 1))                                        \
                    536:     {                                                                  \
                    537:       error_with_line (line_for_error (instack[indepth].lineno),       \
                    538:                       "macro or `#include' recursion too deep");       \
                    539:       code;                                                            \
                    540:     }
                    541: 
                    542: /* Current depth in #include directives that use <...>.  */
                    543: static int system_include_depth = 0;
                    544: 
                    545: typedef struct file_buf FILE_BUF;
                    546: 
                    547: /* The output buffer.  Its LENGTH field is the amount of room allocated
                    548:    for the buffer, not the number of chars actually present.  To get
                    549:    that, subtract outbuf.buf from outbuf.bufp. */
                    550: 
                    551: #define OUTBUF_SIZE 10 /* initial size of output buffer */
                    552: static FILE_BUF outbuf;
                    553: 
                    554: /* Grow output buffer OBUF points at
                    555:    so it can hold at least NEEDED more chars.  */
                    556: 
                    557: #define check_expand(OBUF, NEEDED)  \
                    558:   (((OBUF)->length - ((OBUF)->bufp - (OBUF)->buf) <= (NEEDED))   \
                    559:    ? grow_outbuf ((OBUF), (NEEDED)) : 0)
                    560: 
                    561: struct file_name_list
                    562:   {
                    563:     struct file_name_list *next;
                    564:     char *fname;
                    565:     /* If the following is nonzero, it is a macro name.
                    566:        Don't include the file again if that macro is defined.  */
                    567:     U_CHAR *control_macro;
1.1.1.6   root      568:     /* If the following is nonzero, it is a C-language system include
                    569:        directory.  */
                    570:     int c_system_include_path;
1.1.1.7   root      571:     /* Mapping of file names for this directory.  */
                    572:     struct file_name_map *name_map;
                    573:     /* Non-zero if name_map is valid.  */
                    574:     int got_name_map;
1.1       root      575:   };
                    576: 
                    577: /* #include "file" looks in source file dir, then stack. */
                    578: /* #include <file> just looks in the stack. */
                    579: /* -I directories are added to the end, then the defaults are added. */
1.1.1.7   root      580: /* The */
                    581: static struct default_include {
                    582:   char *fname;                 /* The name of the directory.  */
                    583:   int cplusplus;               /* Only look here if we're compiling C++.  */
                    584:   int cxx_aware;               /* Includes in this directory don't need to
                    585:                                   be wrapped in extern "C" when compiling
                    586:                                   C++.  */
                    587: } include_defaults_array[]
1.1       root      588: #ifdef INCLUDE_DEFAULTS
                    589:   = INCLUDE_DEFAULTS;
                    590: #else
                    591:   = {
                    592:     /* Pick up GNU C++ specific include files.  */
1.1.1.7   root      593:     { GPLUSPLUS_INCLUDE_DIR, 1, 1 },
1.1       root      594: #ifdef CROSS_COMPILE
1.1.1.5   root      595:     /* This is the dir for fixincludes.  Put it just before
                    596:        the files that we fix.  */
1.1.1.7   root      597:     { GCC_INCLUDE_DIR, 0, 0 },
1.1       root      598:     /* For cross-compilation, this dir name is generated
                    599:        automatically in Makefile.in.  */
1.1.1.7   root      600:     { CROSS_INCLUDE_DIR, 0, 0 },
1.1.1.5   root      601:     /* This is another place that the target system's headers might be.  */
1.1.1.7   root      602:     { TOOL_INCLUDE_DIR, 0, 0 },
1.1       root      603: #else /* not CROSS_COMPILE */
1.1.1.7   root      604:     /* This should be /usr/local/include and should come before
1.1.1.5   root      605:        the fixincludes-fixed header files.  */
1.1.1.7   root      606:     { LOCAL_INCLUDE_DIR, 0, 1 },
1.1.1.5   root      607:     /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here.
                    608:        Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h.  */
1.1.1.7   root      609:     { TOOL_INCLUDE_DIR, 0, 0 },
1.1.1.5   root      610:     /* This is the dir for fixincludes.  Put it just before
                    611:        the files that we fix.  */
1.1.1.7   root      612:     { GCC_INCLUDE_DIR, 0, 0 },
1.1       root      613:     /* Some systems have an extra dir of include files.  */
                    614: #ifdef SYSTEM_INCLUDE_DIR
1.1.1.7   root      615:     { SYSTEM_INCLUDE_DIR, 0, 0 },
1.1       root      616: #endif
1.1.1.7   root      617:     { STANDARD_INCLUDE_DIR, 0, 0 },
1.1       root      618: #endif /* not CROSS_COMPILE */
1.1.1.7   root      619:     { 0, 0, 0 }
1.1       root      620:     };
                    621: #endif /* no INCLUDE_DEFAULTS */
                    622: 
                    623: /* The code looks at the defaults through this pointer, rather than through
                    624:    the constant structure above.  This pointer gets changed if an environment
                    625:    variable specifies other defaults.  */
                    626: static struct default_include *include_defaults = include_defaults_array;
                    627: 
                    628: static struct file_name_list *include = 0;     /* First dir to search */
                    629:        /* First dir to search for <file> */
1.1.1.4   root      630: /* This is the first element to use for #include <...>.
                    631:    If it is 0, use the entire chain for such includes.  */
1.1       root      632: static struct file_name_list *first_bracket_include = 0;
1.1.1.4   root      633: /* This is the first element in the chain that corresponds to
                    634:    a directory of system header files.  */
                    635: static struct file_name_list *first_system_include = 0;
1.1       root      636: static struct file_name_list *last_include = 0;        /* Last in chain */
                    637: 
                    638: /* Chain of include directories to put at the end of the other chain.  */
                    639: static struct file_name_list *after_include = 0;
                    640: static struct file_name_list *last_after_include = 0;  /* Last in chain */
                    641: 
1.1.1.7   root      642: /* Chain to put at the start of the system include files.  */
                    643: static struct file_name_list *before_system = 0;
                    644: static struct file_name_list *last_before_system = 0;  /* Last in chain */
                    645: 
1.1       root      646: /* List of included files that contained #pragma once.  */
                    647: static struct file_name_list *dont_repeat_files = 0;
                    648: 
                    649: /* List of other included files.
                    650:    If ->control_macro if nonzero, the file had a #ifndef
                    651:    around the entire contents, and ->control_macro gives the macro name.  */
                    652: static struct file_name_list *all_include_files = 0;
                    653: 
1.1.1.3   root      654: /* Directory prefix that should replace `/usr' in the standard
                    655:    include file directories.  */
                    656: static char *include_prefix;
                    657: 
1.1       root      658: /* Global list of strings read in from precompiled files.  This list
                    659:    is kept in the order the strings are read in, with new strings being
                    660:    added at the end through stringlist_tailp.  We use this list to output
                    661:    the strings at the end of the run. 
                    662: */
                    663: static STRINGDEF *stringlist;
                    664: static STRINGDEF **stringlist_tailp = &stringlist;
                    665: 
                    666: 
                    667: /* Structure returned by create_definition */
                    668: typedef struct macrodef MACRODEF;
                    669: struct macrodef
                    670: {
                    671:   struct definition *defn;
                    672:   U_CHAR *symnam;
                    673:   int symlen;
                    674: };
1.1.1.8 ! root      675: 
        !           676: enum sharp_token_type {
        !           677:   NO_SHARP_TOKEN = 0,          /* token not present */
1.1       root      678: 
1.1.1.8 ! root      679:   SHARP_TOKEN = '#',           /* token spelled with # only */
        !           680:   WHITE_SHARP_TOKEN,           /* token spelled with # and white space */
        !           681: 
        !           682:   PERCENT_COLON_TOKEN = '%',   /* token spelled with %: only */
        !           683:   WHITE_PERCENT_COLON_TOKEN    /* token spelled with %: and white space */
        !           684: };
1.1.1.4   root      685: 
1.1       root      686: /* Structure allocated for every #define.  For a simple replacement
                    687:    such as
                    688:        #define foo bar ,
                    689:    nargs = -1, the `pattern' list is null, and the expansion is just
                    690:    the replacement text.  Nargs = 0 means a functionlike macro with no args,
                    691:    e.g.,
                    692:        #define getchar() getc (stdin) .
                    693:    When there are args, the expansion is the replacement text with the
                    694:    args squashed out, and the reflist is a list describing how to
                    695:    build the output from the input: e.g., "3 chars, then the 1st arg,
                    696:    then 9 chars, then the 3rd arg, then 0 chars, then the 2nd arg".
                    697:    The chars here come from the expansion.  Whatever is left of the
                    698:    expansion after the last arg-occurrence is copied after that arg.
                    699:    Note that the reflist can be arbitrarily long---
                    700:    its length depends on the number of times the arguments appear in
                    701:    the replacement text, not how many args there are.  Example:
                    702:    #define f(x) x+x+x+x+x+x+x would have replacement text "++++++" and
                    703:    pattern list
                    704:      { (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL }
                    705:    where (x, y) means (nchars, argno). */
                    706: 
                    707: typedef struct definition DEFINITION;
                    708: struct definition {
                    709:   int nargs;
                    710:   int length;                  /* length of expansion string */
                    711:   int predefined;              /* True if the macro was builtin or */
                    712:                                /* came from the command line */
                    713:   U_CHAR *expansion;
                    714:   int line;                    /* Line number of definition */
                    715:   char *file;                  /* File of definition */
1.1.1.3   root      716:   char rest_args;              /* Nonzero if last arg. absorbs the rest */
1.1       root      717:   struct reflist {
                    718:     struct reflist *next;
1.1.1.8 ! root      719: 
        !           720:     enum sharp_token_type stringify;   /* set if a # operator before arg */
        !           721:     enum sharp_token_type raw_before;  /* set if a ## operator before arg */
        !           722:     enum sharp_token_type raw_after;   /* set if a ## operator after arg */
        !           723: 
1.1.1.3   root      724:     char rest_args;            /* Nonzero if this arg. absorbs the rest */
1.1       root      725:     int nchars;                        /* Number of literal chars to copy before
                    726:                                   this arg occurrence.  */
                    727:     int argno;                 /* Number of arg to substitute (origin-0) */
                    728:   } *pattern;
                    729:   union {
                    730:     /* Names of macro args, concatenated in reverse order
                    731:        with comma-space between them.
                    732:        The only use of this is that we warn on redefinition
                    733:        if this differs between the old and new definitions.  */
                    734:     U_CHAR *argnames;
                    735:   } args;
                    736: };
                    737: 
                    738: /* different kinds of things that can appear in the value field
                    739:    of a hash node.  Actually, this may be useless now. */
                    740: union hashval {
                    741:   char *cpval;
                    742:   DEFINITION *defn;
                    743:   KEYDEF *keydef;
                    744: };
                    745: 
1.1.1.3   root      746: /*
                    747:  * special extension string that can be added to the last macro argument to 
                    748:  * allow it to absorb the "rest" of the arguments when expanded.  Ex:
1.1.1.5   root      749:  *             #define wow(a, b...)            process (b, a, b)
                    750:  *             { wow (1, 2, 3); }      ->      { process (2, 3, 1, 2, 3); }
                    751:  *             { wow (one, two); }     ->      { process (two, one, two); }
1.1.1.3   root      752:  * if this "rest_arg" is used with the concat token '##' and if it is not
1.1.1.4   root      753:  * supplied then the token attached to with ## will not be outputted.  Ex:
1.1.1.5   root      754:  *             #define wow (a, b...)           process (b ## , a, ## b)
                    755:  *             { wow (1, 2); }         ->      { process (2, 1, 2); }
                    756:  *             { wow (one); }          ->      { process (one); {
1.1.1.3   root      757:  */
                    758: static char rest_extension[] = "...";
                    759: #define REST_EXTENSION_LENGTH  (sizeof (rest_extension) - 1)
1.1       root      760: 
                    761: /* The structure of a node in the hash table.  The hash table
1.1.1.8 ! root      762:    has entries for all tokens defined by #define directives (type T_MACRO),
1.1       root      763:    plus some special tokens like __LINE__ (these each have their own
                    764:    type, and the appropriate code is run when that type of node is seen.
                    765:    It does not contain control words like "#define", which are recognized
                    766:    by a separate piece of code. */
                    767: 
                    768: /* different flavors of hash nodes --- also used in keyword table */
                    769: enum node_type {
                    770:  T_DEFINE = 1, /* the `#define' keyword */
                    771:  T_INCLUDE,    /* the `#include' keyword */
                    772:  T_INCLUDE_NEXT, /* the `#include_next' keyword */
                    773:  T_IMPORT,      /* the `#import' keyword */
                    774:  T_IFDEF,      /* the `#ifdef' keyword */
                    775:  T_IFNDEF,     /* the `#ifndef' keyword */
                    776:  T_IF,         /* the `#if' keyword */
                    777:  T_ELSE,       /* `#else' */
                    778:  T_PRAGMA,     /* `#pragma' */
                    779:  T_ELIF,       /* `#elif' */
                    780:  T_UNDEF,      /* `#undef' */
                    781:  T_LINE,       /* `#line' */
                    782:  T_ERROR,      /* `#error' */
                    783:  T_WARNING,    /* `#warning' */
                    784:  T_ENDIF,      /* `#endif' */
                    785:  T_SCCS,       /* `#sccs', used on system V.  */
                    786:  T_IDENT,      /* `#ident', used on system V.  */
                    787:  T_ASSERT,     /* `#assert', taken from system V.  */
                    788:  T_UNASSERT,   /* `#unassert', taken from system V.  */
                    789:  T_SPECLINE,   /* special symbol `__LINE__' */
                    790:  T_DATE,       /* `__DATE__' */
                    791:  T_FILE,       /* `__FILE__' */
                    792:  T_BASE_FILE,  /* `__BASE_FILE__' */
                    793:  T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */
                    794:  T_VERSION,    /* `__VERSION__' */
                    795:  T_SIZE_TYPE,   /* `__SIZE_TYPE__' */
                    796:  T_PTRDIFF_TYPE,   /* `__PTRDIFF_TYPE__' */
                    797:  T_WCHAR_TYPE,   /* `__WCHAR_TYPE__' */
1.1.1.5   root      798:  T_USER_LABEL_PREFIX_TYPE, /* `__USER_LABEL_PREFIX__' */
                    799:  T_REGISTER_PREFIX_TYPE,   /* `__REGISTER_PREFIX__' */
1.1.1.8 ! root      800:  T_IMMEDIATE_PREFIX_TYPE,  /* `__IMMEDIATE_PREFIX__' */
1.1       root      801:  T_TIME,       /* `__TIME__' */
                    802:  T_CONST,      /* Constant value, used by `__STDC__' */
                    803:  T_MACRO,      /* macro defined by `#define' */
                    804:  T_DISABLED,   /* macro temporarily turned off for rescan */
                    805:  T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */
                    806:  T_PCSTRING,   /* precompiled string (hashval is KEYDEF *) */
                    807:  T_UNUSED      /* Used for something not defined.  */
                    808:  };
                    809: 
                    810: struct hashnode {
                    811:   struct hashnode *next;       /* double links for easy deletion */
                    812:   struct hashnode *prev;
                    813:   struct hashnode **bucket_hdr;        /* also, a back pointer to this node's hash
                    814:                                   chain is kept, in case the node is the head
                    815:                                   of the chain and gets deleted. */
                    816:   enum node_type type;         /* type of special token */
                    817:   int length;                  /* length of token, for quick comparison */
                    818:   U_CHAR *name;                        /* the actual name */
                    819:   union hashval value;         /* pointer to expansion, or whatever */
                    820: };
                    821: 
                    822: typedef struct hashnode HASHNODE;
                    823: 
                    824: /* Some definitions for the hash table.  The hash function MUST be
                    825:    computed as shown in hashf () below.  That is because the rescan
                    826:    loop computes the hash value `on the fly' for most tokens,
                    827:    in order to avoid the overhead of a lot of procedure calls to
                    828:    the hashf () function.  Hashf () only exists for the sake of
                    829:    politeness, for use when speed isn't so important. */
                    830: 
                    831: #define HASHSIZE 1403
                    832: static HASHNODE *hashtab[HASHSIZE];
                    833: #define HASHSTEP(old, c) ((old << 2) + c)
                    834: #define MAKE_POS(v) (v & 0x7fffffff) /* make number positive */
                    835: 
                    836: /* Symbols to predefine.  */
                    837: 
                    838: #ifdef CPP_PREDEFINES
                    839: static char *predefs = CPP_PREDEFINES;
                    840: #else
                    841: static char *predefs = "";
                    842: #endif
                    843: 
                    844: /* We let tm.h override the types used here, to handle trivial differences
                    845:    such as the choice of unsigned int or long unsigned int for size_t.
                    846:    When machines start needing nontrivial differences in the size type,
                    847:    it would be best to do something here to figure out automatically
                    848:    from other information what type to use.  */
                    849: 
1.1.1.7   root      850: /* The string value for __SIZE_TYPE__.  */
1.1       root      851: 
                    852: #ifndef SIZE_TYPE
                    853: #define SIZE_TYPE "long unsigned int"
                    854: #endif
                    855: 
1.1.1.7   root      856: /* The string value for __PTRDIFF_TYPE__.  */
1.1       root      857: 
                    858: #ifndef PTRDIFF_TYPE
                    859: #define PTRDIFF_TYPE "long int"
                    860: #endif
                    861: 
1.1.1.7   root      862: /* The string value for __WCHAR_TYPE__.  */
1.1       root      863: 
                    864: #ifndef WCHAR_TYPE
                    865: #define WCHAR_TYPE "int"
                    866: #endif
1.1.1.7   root      867: char * wchar_type = WCHAR_TYPE;
                    868: #undef WCHAR_TYPE
1.1.1.5   root      869: 
                    870: /* The string value for __USER_LABEL_PREFIX__ */
                    871: 
                    872: #ifndef USER_LABEL_PREFIX
                    873: #define USER_LABEL_PREFIX ""
                    874: #endif
                    875: 
                    876: /* The string value for __REGISTER_PREFIX__ */
                    877: 
                    878: #ifndef REGISTER_PREFIX
                    879: #define REGISTER_PREFIX ""
                    880: #endif
1.1.1.8 ! root      881: 
        !           882: /* The string value for __IMMEDIATE_PREFIX__ */
        !           883: 
        !           884: #ifndef IMMEDIATE_PREFIX
        !           885: #define IMMEDIATE_PREFIX ""
        !           886: #endif
1.1       root      887: 
                    888: /* In the definition of a #assert name, this structure forms
                    889:    a list of the individual values asserted.
                    890:    Each value is itself a list of "tokens".
                    891:    These are strings that are compared by name.  */
                    892: 
                    893: struct tokenlist_list {
                    894:   struct tokenlist_list *next;
                    895:   struct arglist *tokens;
                    896: };
                    897: 
                    898: struct assertion_hashnode {
                    899:   struct assertion_hashnode *next;     /* double links for easy deletion */
                    900:   struct assertion_hashnode *prev;
                    901:   /* also, a back pointer to this node's hash
                    902:      chain is kept, in case the node is the head
                    903:      of the chain and gets deleted. */
                    904:   struct assertion_hashnode **bucket_hdr;
                    905:   int length;                  /* length of token, for quick comparison */
                    906:   U_CHAR *name;                        /* the actual name */
                    907:   /* List of token-sequences.  */
                    908:   struct tokenlist_list *value;
                    909: };
                    910: 
                    911: typedef struct assertion_hashnode ASSERTION_HASHNODE;
                    912: 
                    913: /* Some definitions for the hash table.  The hash function MUST be
1.1.1.4   root      914:    computed as shown in hashf below.  That is because the rescan
1.1       root      915:    loop computes the hash value `on the fly' for most tokens,
                    916:    in order to avoid the overhead of a lot of procedure calls to
1.1.1.4   root      917:    the hashf function.  hashf only exists for the sake of
1.1       root      918:    politeness, for use when speed isn't so important. */
                    919: 
                    920: #define ASSERTION_HASHSIZE 37
                    921: static ASSERTION_HASHNODE *assertion_hashtab[ASSERTION_HASHSIZE];
                    922: 
                    923: /* Nonzero means inhibit macroexpansion of what seem to be
                    924:    assertion tests, in rescan.  For #if.  */
                    925: static int assertions_flag;
                    926: 
                    927: /* `struct directive' defines one #-directive, including how to handle it.  */
                    928: 
1.1.1.8 ! root      929: #define DO_PROTO PROTO((U_CHAR *, U_CHAR *, FILE_BUF *, struct directive *))
        !           930: 
1.1       root      931: struct directive {
                    932:   int length;                  /* Length of name */
1.1.1.8 ! root      933:   int (*func) DO_PROTO;        /* Function to handle directive */
1.1       root      934:   char *name;                  /* Name of directive */
                    935:   enum node_type type;         /* Code which describes which directive. */
                    936:   char angle_brackets;         /* Nonzero => <...> is special.  */
                    937:   char traditional_comments;   /* Nonzero: keep comments if -traditional.  */
                    938:   char pass_thru;              /* Copy preprocessed directive to output file.  */
                    939: };
                    940: 
1.1.1.8 ! root      941: /* These functions are declared to return int instead of void since they
        !           942:    are going to be placed in the table and some old compilers have trouble with
        !           943:    pointers to functions returning void.  */
        !           944: 
        !           945: static int do_assert DO_PROTO;
        !           946: static int do_define DO_PROTO;
        !           947: static int do_elif DO_PROTO;
        !           948: static int do_else DO_PROTO;
        !           949: static int do_endif DO_PROTO;
        !           950: static int do_error DO_PROTO;
        !           951: static int do_ident DO_PROTO;
        !           952: static int do_if DO_PROTO;
        !           953: static int do_include DO_PROTO;
        !           954: static int do_line DO_PROTO;
        !           955: static int do_pragma DO_PROTO;
        !           956: #ifdef SCCS_DIRECTIVE
        !           957: static int do_sccs DO_PROTO;
        !           958: #endif
        !           959: static int do_unassert DO_PROTO;
        !           960: static int do_undef DO_PROTO;
        !           961: static int do_warning DO_PROTO;
        !           962: static int do_xifdef DO_PROTO;
        !           963: 
1.1       root      964: /* Here is the actual list of #-directives, most-often-used first.  */
                    965: 
                    966: static struct directive directive_table[] = {
                    967:   {  6, do_define, "define", T_DEFINE, 0, 1},
                    968:   {  2, do_if, "if", T_IF},
                    969:   {  5, do_xifdef, "ifdef", T_IFDEF},
                    970:   {  6, do_xifdef, "ifndef", T_IFNDEF},
                    971:   {  5, do_endif, "endif", T_ENDIF},
                    972:   {  4, do_else, "else", T_ELSE},
                    973:   {  4, do_elif, "elif", T_ELIF},
                    974:   {  4, do_line, "line", T_LINE},
                    975:   {  7, do_include, "include", T_INCLUDE, 1},
                    976:   { 12, do_include, "include_next", T_INCLUDE_NEXT, 1},
                    977:   {  6, do_include, "import", T_IMPORT, 1},
                    978:   {  5, do_undef, "undef", T_UNDEF},
                    979:   {  5, do_error, "error", T_ERROR},
                    980:   {  7, do_warning, "warning", T_WARNING},
                    981: #ifdef SCCS_DIRECTIVE
                    982:   {  4, do_sccs, "sccs", T_SCCS},
                    983: #endif
                    984:   {  6, do_pragma, "pragma", T_PRAGMA, 0, 0, 1},
1.1.1.6   root      985:   {  5, do_ident, "ident", T_IDENT},
1.1       root      986:   {  6, do_assert, "assert", T_ASSERT},
                    987:   {  8, do_unassert, "unassert", T_UNASSERT},
                    988:   {  -1, 0, "", T_UNUSED},
                    989: };
                    990: 
                    991: /* When a directive handler is called,
1.1.1.8 ! root      992:    this points to the # (or the : of the %:) that started the directive.  */
1.1       root      993: U_CHAR *directive_start;
                    994: 
                    995: /* table to tell if char can be part of a C identifier. */
                    996: U_CHAR is_idchar[256];
                    997: /* table to tell if char can be first char of a c identifier. */
                    998: U_CHAR is_idstart[256];
                    999: /* table to tell if c is horizontal space.  */
                   1000: U_CHAR is_hor_space[256];
                   1001: /* table to tell if c is horizontal or vertical space.  */
                   1002: static U_CHAR is_space[256];
1.1.1.8 ! root     1003: /* names of some characters */
        !          1004: static char *char_name[256];
1.1       root     1005: 
                   1006: #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
                   1007: #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
                   1008:   
                   1009: static int errors = 0;                 /* Error counter for exit code */
                   1010: 
1.1.1.5   root     1011: /* Name of output file, for error messages.  */
                   1012: static char *out_fname;
                   1013: 
1.1       root     1014: /* Zero means dollar signs are punctuation.
                   1015:    -$ stores 0; -traditional may store 1.  Default is 1 for VMS, 0 otherwise.
                   1016:    This must be 0 for correct processing of this ANSI C program:
                   1017:        #define foo(a) #a
1.1.1.5   root     1018:        #define lose(b) foo (b)
1.1       root     1019:        #define test$
1.1.1.5   root     1020:        lose (test)     */
1.1       root     1021: static int dollars_in_ident;
                   1022: #ifndef DOLLARS_IN_IDENTIFIERS
                   1023: #define DOLLARS_IN_IDENTIFIERS 1
                   1024: #endif
                   1025: 
                   1026: 
                   1027: /* Stack of conditionals currently in progress
                   1028:    (including both successful and failing conditionals).  */
                   1029: 
                   1030: struct if_stack {
                   1031:   struct if_stack *next;       /* for chaining to the next stack frame */
                   1032:   char *fname;         /* copied from input when frame is made */
                   1033:   int lineno;                  /* similarly */
                   1034:   int if_succeeded;            /* true if a leg of this if-group
                   1035:                                    has been passed through rescan */
                   1036:   U_CHAR *control_macro;       /* For #ifndef at start of file,
                   1037:                                   this is the macro name tested.  */
                   1038:   enum node_type type;         /* type of last directive seen in this group */
                   1039: };
                   1040: typedef struct if_stack IF_STACK_FRAME;
                   1041: static IF_STACK_FRAME *if_stack = NULL;
                   1042: 
                   1043: /* Buffer of -M output.  */
                   1044: static char *deps_buffer;
                   1045: 
                   1046: /* Number of bytes allocated in above.  */
                   1047: static int deps_allocated_size;
                   1048: 
                   1049: /* Number of bytes used.  */
                   1050: static int deps_size;
                   1051: 
                   1052: /* Number of bytes since the last newline.  */
                   1053: static int deps_column;
                   1054: 
                   1055: /* Nonzero means -I- has been seen,
                   1056:    so don't look for #include "foo" the source-file directory.  */
                   1057: static int ignore_srcdir;
                   1058: 
1.1.1.8 ! root     1059: static int safe_read PROTO((int, char *, int));
        !          1060: static void safe_write PROTO((int, char *, int));
        !          1061: 
        !          1062: int main PROTO((int, char **));
        !          1063: 
        !          1064: static void path_include PROTO((char *));
        !          1065: 
        !          1066: static U_CHAR *index0 PROTO((U_CHAR *, int, size_t));
        !          1067: 
        !          1068: static void trigraph_pcp PROTO((FILE_BUF *));
        !          1069: 
        !          1070: static void newline_fix PROTO((U_CHAR *));
        !          1071: static void name_newline_fix PROTO((U_CHAR *));
        !          1072: 
        !          1073: static char *get_lintcmd PROTO((U_CHAR *, U_CHAR *, U_CHAR **, int *, int *));
        !          1074: 
        !          1075: static void rescan PROTO((FILE_BUF *, int));
        !          1076: 
        !          1077: static FILE_BUF expand_to_temp_buffer PROTO((U_CHAR *, U_CHAR *, int, int));
        !          1078: 
        !          1079: static int handle_directive PROTO((FILE_BUF *, FILE_BUF *));
        !          1080: 
        !          1081: static struct tm *timestamp PROTO((void));
        !          1082: static void special_symbol PROTO((HASHNODE *, FILE_BUF *));
        !          1083: 
        !          1084: static int redundant_include_p PROTO((char *));
        !          1085: static int is_system_include PROTO((char *));
        !          1086: static char *skip_redundant_dir_prefix PROTO((char *));
        !          1087: 
        !          1088: static char *read_filename_string PROTO((int, FILE *));
        !          1089: static struct file_name_map *read_name_map PROTO((char *));
        !          1090: static int open_include_file PROTO((char *, struct file_name_list *));
        !          1091: 
        !          1092: static void finclude PROTO((int, char *, FILE_BUF *, int, struct file_name_list *));
        !          1093: static void record_control_macro PROTO((char *, U_CHAR *));
        !          1094: 
        !          1095: static int import_hash PROTO((char *));
        !          1096: static int lookup_import PROTO((char *, struct file_name_list *));
        !          1097: static void add_import PROTO((int, char *));
        !          1098: 
        !          1099: static char *check_precompiled PROTO((int, char *, char **));
        !          1100: static int check_preconditions PROTO((char *));
        !          1101: static void pcfinclude PROTO((U_CHAR *, U_CHAR *, U_CHAR *, FILE_BUF *));
        !          1102: static void pcstring_used PROTO((HASHNODE *));
        !          1103: static void write_output PROTO((void));
        !          1104: static void pass_thru_directive PROTO((U_CHAR *, U_CHAR *, FILE_BUF *, struct directive *));
        !          1105: 
        !          1106: static MACRODEF create_definition PROTO((U_CHAR *, U_CHAR *, FILE_BUF *));
        !          1107: 
        !          1108: static int check_macro_name PROTO((U_CHAR *, char *));
        !          1109: static int compare_defs PROTO((DEFINITION *, DEFINITION *));
        !          1110: static int comp_def_part PROTO((int, U_CHAR *, int, U_CHAR *, int, int));
        !          1111: 
        !          1112: static DEFINITION *collect_expansion  PROTO((U_CHAR *, U_CHAR *, int, struct arglist *));
        !          1113: 
        !          1114: int check_assertion PROTO((U_CHAR *, int, int, struct arglist *));
        !          1115: static int compare_token_lists PROTO((struct arglist *, struct arglist *));
        !          1116: 
        !          1117: static struct arglist *read_token_list PROTO((U_CHAR **, U_CHAR *, int *));
        !          1118: static void free_token_list PROTO((struct arglist *));
        !          1119: 
        !          1120: static ASSERTION_HASHNODE *assertion_install PROTO((U_CHAR *, int, int));
        !          1121: static ASSERTION_HASHNODE *assertion_lookup PROTO((U_CHAR *, int, int));
        !          1122: static void delete_assertion PROTO((ASSERTION_HASHNODE *));
        !          1123: 
        !          1124: static void do_once PROTO((void));
        !          1125: 
        !          1126: static HOST_WIDE_INT eval_if_expression PROTO((U_CHAR *, int));
        !          1127: static void conditional_skip PROTO((FILE_BUF *, int, enum node_type, U_CHAR *, FILE_BUF *));
        !          1128: static void skip_if_group PROTO((FILE_BUF *, int, FILE_BUF *));
        !          1129: static void validate_else PROTO((U_CHAR *));
        !          1130: 
        !          1131: static U_CHAR *skip_to_end_of_comment PROTO((FILE_BUF *, int *, int));
        !          1132: static U_CHAR *skip_quoted_string PROTO((U_CHAR *, U_CHAR *, int, int *, int *, int *));
        !          1133: static char *quote_string PROTO((char *, char *));
        !          1134: static U_CHAR *skip_paren_group PROTO((FILE_BUF *));
        !          1135: 
        !          1136: /* Last arg to output_line_directive.  */
        !          1137: enum file_change_code {same_file, enter_file, leave_file};
        !          1138: static void output_line_directive PROTO((FILE_BUF *, FILE_BUF *, int, enum file_change_code));
        !          1139: 
        !          1140: static void macroexpand PROTO((HASHNODE *, FILE_BUF *));
        !          1141: 
        !          1142: struct argdata;
        !          1143: static char *macarg PROTO((struct argdata *, int));
        !          1144: 
        !          1145: static U_CHAR *macarg1 PROTO((U_CHAR *, U_CHAR *, int *, int *, int *, int));
        !          1146: 
        !          1147: static int discard_comments PROTO((U_CHAR *, int, int));
        !          1148: 
        !          1149: static int change_newlines PROTO((U_CHAR *, int));
        !          1150: 
        !          1151: char *my_strerror PROTO((int));
        !          1152: void error PRINTF_PROTO_1((char *, ...));
        !          1153: static void verror PROTO((char *, va_list));
        !          1154: static void error_from_errno PROTO((char *));
        !          1155: void warning PRINTF_PROTO_1((char *, ...));
        !          1156: static void vwarning PROTO((char *, va_list));
        !          1157: static void error_with_line PRINTF_PROTO_2((int, char *, ...));
        !          1158: static void verror_with_line PROTO((int, char *, va_list));
        !          1159: static void vwarning_with_line PROTO((int, char *, va_list));
        !          1160: static void warning_with_line PRINTF_PROTO_2((int, char *, ...));
        !          1161: void pedwarn PRINTF_PROTO_1((char *, ...));
        !          1162: void pedwarn_with_line PRINTF_PROTO_2((int, char *, ...));
        !          1163: static void pedwarn_with_file_and_line PRINTF_PROTO_3((char *, int, char *, ...));
        !          1164: 
        !          1165: static void print_containing_files PROTO((void));
        !          1166: 
        !          1167: static int line_for_error PROTO((int));
        !          1168: static int grow_outbuf PROTO((FILE_BUF *, int));
        !          1169: 
        !          1170: static HASHNODE *install PROTO((U_CHAR *, int, enum node_type, char *, int));
        !          1171: HASHNODE *lookup PROTO((U_CHAR *, int, int));
        !          1172: static void delete_macro PROTO((HASHNODE *));
        !          1173: static int hashf PROTO((U_CHAR *, int, int));
        !          1174: 
        !          1175: static void dump_single_macro PROTO((HASHNODE *, FILE *));
        !          1176: static void dump_all_macros PROTO((void));
        !          1177: static void dump_defn_1 PROTO((U_CHAR *, int, int, FILE *));
        !          1178: static void dump_arg_n PROTO((DEFINITION *, int, FILE *));
        !          1179: 
        !          1180: static void initialize_char_syntax PROTO((void));
        !          1181: static void initialize_builtins PROTO((FILE_BUF *, FILE_BUF *));
        !          1182: 
        !          1183: static void make_definition PROTO((char *, FILE_BUF *));
        !          1184: static void make_undef PROTO((char *, FILE_BUF *));
        !          1185: 
        !          1186: static void make_assertion PROTO((char *, char *));
        !          1187: 
        !          1188: static void append_include_chain PROTO((struct file_name_list *, struct file_name_list *));
        !          1189: 
        !          1190: static void deps_output PROTO((char *, int));
        !          1191: 
        !          1192: static void fatal PRINTF_PROTO_1((char *, ...)) __attribute__ ((noreturn));
        !          1193: void fancy_abort PROTO((void)) __attribute__ ((noreturn));
        !          1194: static void perror_with_name PROTO((char *));
        !          1195: static void pfatal_with_name PROTO((char *)) __attribute__ ((noreturn));
        !          1196: static void pipe_closed PROTO((int)) __attribute__ ((noreturn));
        !          1197: 
        !          1198: static void memory_full PROTO((void)) __attribute__ ((noreturn));
        !          1199: GENERIC_PTR xmalloc PROTO((size_t));
        !          1200: static GENERIC_PTR xrealloc PROTO((GENERIC_PTR, size_t));
        !          1201: static GENERIC_PTR xcalloc PROTO((size_t, size_t));
        !          1202: static char *savestring PROTO((char *));
        !          1203: 
        !          1204: static int file_size_and_mode PROTO((int, int *, long int *));
        !          1205: 
1.1.1.6   root     1206: /* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
1.1.1.7   root     1207:    retrying if necessary.  Return a negative value if an error occurs,
                   1208:    otherwise return the actual number of bytes read,
                   1209:    which must be LEN unless end-of-file was reached.  */
1.1.1.6   root     1210: 
                   1211: static int
                   1212: safe_read (desc, ptr, len)
                   1213:      int desc;
                   1214:      char *ptr;
                   1215:      int len;
                   1216: {
                   1217:   int left = len;
                   1218:   while (left > 0) {
                   1219:     int nchars = read (desc, ptr, left);
                   1220:     if (nchars < 0)
                   1221:       {
                   1222: #ifdef EINTR
                   1223:        if (errno == EINTR)
                   1224:          continue;
                   1225: #endif
                   1226:        return nchars;
                   1227:       }
                   1228:     if (nchars == 0)
                   1229:       break;
                   1230:     ptr += nchars;
                   1231:     left -= nchars;
                   1232:   }
                   1233:   return len - left;
                   1234: }
                   1235: 
                   1236: /* Write LEN bytes at PTR to descriptor DESC,
                   1237:    retrying if necessary, and treating any real error as fatal.  */
                   1238: 
                   1239: static void
                   1240: safe_write (desc, ptr, len)
                   1241:      int desc;
                   1242:      char *ptr;
                   1243:      int len;
                   1244: {
                   1245:   while (len > 0) {
                   1246:     int written = write (desc, ptr, len);
                   1247:     if (written < 0)
                   1248:       {
                   1249: #ifdef EINTR
                   1250:        if (errno == EINTR)
                   1251:          continue;
                   1252: #endif
                   1253:        pfatal_with_name (out_fname);
                   1254:       }
                   1255:     ptr += written;
                   1256:     len -= written;
                   1257:   }
                   1258: }
                   1259: 
1.1       root     1260: int
                   1261: main (argc, argv)
                   1262:      int argc;
                   1263:      char **argv;
                   1264: {
                   1265:   int st_mode;
                   1266:   long st_size;
1.1.1.5   root     1267:   char *in_fname;
1.1.1.8 ! root     1268:   char *cp;
1.1       root     1269:   int f, i;
                   1270:   FILE_BUF *fp;
                   1271:   char **pend_files = (char **) xmalloc (argc * sizeof (char *));
                   1272:   char **pend_defs = (char **) xmalloc (argc * sizeof (char *));
                   1273:   char **pend_undefs = (char **) xmalloc (argc * sizeof (char *));
                   1274:   char **pend_assertions = (char **) xmalloc (argc * sizeof (char *));
                   1275:   char **pend_includes = (char **) xmalloc (argc * sizeof (char *));
                   1276: 
                   1277:   /* Record the option used with each element of pend_assertions.
                   1278:      This is preparation for supporting more than one option for making
                   1279:      an assertion.  */
                   1280:   char **pend_assertion_options = (char **) xmalloc (argc * sizeof (char *));
                   1281:   int inhibit_predefs = 0;
                   1282:   int no_standard_includes = 0;
1.1.1.3   root     1283:   int no_standard_cplusplus_includes = 0;
1.1       root     1284:   int missing_newline = 0;
                   1285: 
                   1286:   /* Non-0 means don't output the preprocessed program.  */
                   1287:   int inhibit_output = 0;
1.1.1.6   root     1288:   /* Non-0 means -v, so print the full set of include dirs.  */
                   1289:   int verbose = 0;
1.1       root     1290: 
1.1.1.4   root     1291:   /* File name which deps are being written to.
                   1292:      This is 0 if deps are being written to stdout.  */
                   1293:   char *deps_file = 0;
1.1.1.5   root     1294:   /* Fopen file mode to open deps_file with.  */
                   1295:   char *deps_mode = "a";
1.1       root     1296:   /* Stream on which to print the dependency information.  */
                   1297:   FILE *deps_stream = 0;
                   1298:   /* Target-name to write with the dependency information.  */
                   1299:   char *deps_target = 0;
                   1300: 
                   1301: #ifdef RLIMIT_STACK
                   1302:   /* Get rid of any avoidable limit on stack size.  */
                   1303:   {
                   1304:     struct rlimit rlim;
                   1305: 
                   1306:     /* Set the stack limit huge so that alloca (particularly stringtab
                   1307:      * in dbxread.c) does not fail. */
                   1308:     getrlimit (RLIMIT_STACK, &rlim);
                   1309:     rlim.rlim_cur = rlim.rlim_max;
                   1310:     setrlimit (RLIMIT_STACK, &rlim);
                   1311:   }
                   1312: #endif /* RLIMIT_STACK defined */
                   1313: 
1.1.1.6   root     1314: #ifdef SIGPIPE
1.1.1.5   root     1315:   signal (SIGPIPE, pipe_closed);
1.1.1.6   root     1316: #endif
1.1.1.5   root     1317: 
1.1.1.8 ! root     1318:   cp = argv[0] + strlen (argv[0]);
        !          1319:   while (cp != argv[0] && cp[-1] != '/'
1.1.1.7   root     1320: #ifdef DIR_SEPARATOR
1.1.1.8 ! root     1321:         && cp[-1] != DIR_SEPARATOR
1.1.1.7   root     1322: #endif
                   1323:         )
1.1.1.8 ! root     1324:     --cp;
        !          1325:   progname = cp;
1.1.1.5   root     1326: 
1.1       root     1327: #ifdef VMS
                   1328:   {
                   1329:     /* Remove directories from PROGNAME.  */
1.1.1.8 ! root     1330:     char *p;
        !          1331:     char *s = progname;
1.1       root     1332: 
1.1.1.8 ! root     1333:     if ((p = rindex (s, ':')) != 0) s = p + 1; /* skip device */
        !          1334:     if ((p = rindex (s, ']')) != 0) s = p + 1; /* skip directory */
        !          1335:     if ((p = rindex (s, '>')) != 0) s = p + 1; /* alternate (int'n'l) dir */
        !          1336:     s = progname = savestring (s);
        !          1337:     if ((p = rindex (s, ';')) != 0) *p = '\0'; /* strip version number */
        !          1338:     if ((p = rindex (s, '.')) != 0             /* strip type iff ".exe" */
        !          1339:        && (p[1] == 'e' || p[1] == 'E')
        !          1340:        && (p[2] == 'x' || p[2] == 'X')
        !          1341:        && (p[3] == 'e' || p[3] == 'E')
        !          1342:        && !p[4])
        !          1343:       *p = '\0';
1.1       root     1344:   }
                   1345: #endif
                   1346: 
                   1347:   in_fname = NULL;
                   1348:   out_fname = NULL;
                   1349: 
                   1350:   /* Initialize is_idchar to allow $.  */
                   1351:   dollars_in_ident = 1;
                   1352:   initialize_char_syntax ();
                   1353:   dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 0;
                   1354: 
1.1.1.8 ! root     1355:   no_line_directives = 0;
1.1       root     1356:   no_trigraphs = 1;
                   1357:   dump_macros = dump_none;
                   1358:   no_output = 0;
                   1359:   cplusplus = 0;
1.1.1.8 ! root     1360:   cplusplus_comments = 1;
1.1       root     1361: 
1.1.1.7   root     1362:   bzero ((char *) pend_files, argc * sizeof (char *));
                   1363:   bzero ((char *) pend_defs, argc * sizeof (char *));
                   1364:   bzero ((char *) pend_undefs, argc * sizeof (char *));
                   1365:   bzero ((char *) pend_assertions, argc * sizeof (char *));
                   1366:   bzero ((char *) pend_includes, argc * sizeof (char *));
1.1       root     1367: 
                   1368:   /* Process switches and find input file name.  */
                   1369: 
                   1370:   for (i = 1; i < argc; i++) {
                   1371:     if (argv[i][0] != '-') {
                   1372:       if (out_fname != NULL)
                   1373:        fatal ("Usage: %s [switches] input output", argv[0]);
                   1374:       else if (in_fname != NULL)
                   1375:        out_fname = argv[i];
                   1376:       else
                   1377:        in_fname = argv[i];
                   1378:     } else {
                   1379:       switch (argv[i][1]) {
                   1380: 
                   1381:       case 'i':
                   1382:        if (!strcmp (argv[i], "-include")) {
                   1383:          if (i + 1 == argc)
1.1.1.5   root     1384:            fatal ("Filename missing after `-include' option");
1.1       root     1385:          else
                   1386:            pend_includes[i] = argv[i+1], i++;
                   1387:        }
                   1388:        if (!strcmp (argv[i], "-imacros")) {
                   1389:          if (i + 1 == argc)
1.1.1.5   root     1390:            fatal ("Filename missing after `-imacros' option");
1.1       root     1391:          else
                   1392:            pend_files[i] = argv[i+1], i++;
                   1393:        }
1.1.1.3   root     1394:        if (!strcmp (argv[i], "-iprefix")) {
                   1395:          if (i + 1 == argc)
1.1.1.5   root     1396:            fatal ("Filename missing after `-iprefix' option");
1.1.1.3   root     1397:          else
                   1398:            include_prefix = argv[++i];
                   1399:        }
1.1.1.7   root     1400:        if (!strcmp (argv[i], "-ifoutput")) {
                   1401:          output_conditionals = 1;
                   1402:        }
                   1403:        if (!strcmp (argv[i], "-isystem")) {
                   1404:          struct file_name_list *dirtmp;
                   1405: 
                   1406:          if (i + 1 == argc)
                   1407:            fatal ("Filename missing after `-isystem' option");
                   1408: 
                   1409:          dirtmp = (struct file_name_list *)
                   1410:            xmalloc (sizeof (struct file_name_list));
                   1411:          dirtmp->next = 0;
                   1412:          dirtmp->control_macro = 0;
                   1413:          dirtmp->c_system_include_path = 1;
1.1.1.8 ! root     1414:          dirtmp->fname = xmalloc (strlen (argv[i+1]) + 1);
1.1.1.7   root     1415:          strcpy (dirtmp->fname, argv[++i]);
                   1416:          dirtmp->got_name_map = 0;
                   1417: 
                   1418:          if (before_system == 0)
                   1419:            before_system = dirtmp;
                   1420:          else
                   1421:            last_before_system->next = dirtmp;
                   1422:          last_before_system = dirtmp; /* Tail follows the last one */
                   1423:        }
1.1.1.5   root     1424:        /* Add directory to end of path for includes,
                   1425:           with the default prefix at the front of its name.  */
                   1426:        if (!strcmp (argv[i], "-iwithprefix")) {
                   1427:          struct file_name_list *dirtmp;
1.1.1.6   root     1428:          char *prefix;
                   1429: 
                   1430:          if (include_prefix != 0)
                   1431:            prefix = include_prefix;
                   1432:          else {
                   1433:            prefix = savestring (GCC_INCLUDE_DIR);
                   1434:            /* Remove the `include' from /usr/local/lib/gcc.../include.  */
                   1435:            if (!strcmp (prefix + strlen (prefix) - 8, "/include"))
                   1436:              prefix[strlen (prefix) - 7] = 0;
                   1437:          }
1.1.1.5   root     1438: 
                   1439:          dirtmp = (struct file_name_list *)
                   1440:            xmalloc (sizeof (struct file_name_list));
                   1441:          dirtmp->next = 0;     /* New one goes on the end */
                   1442:          dirtmp->control_macro = 0;
1.1.1.6   root     1443:          dirtmp->c_system_include_path = 0;
1.1.1.5   root     1444:          if (i + 1 == argc)
                   1445:            fatal ("Directory name missing after `-iwithprefix' option");
                   1446: 
1.1.1.8 ! root     1447:          dirtmp->fname = xmalloc (strlen (argv[i+1]) + strlen (prefix) + 1);
1.1.1.6   root     1448:          strcpy (dirtmp->fname, prefix);
1.1.1.5   root     1449:          strcat (dirtmp->fname, argv[++i]);
1.1.1.7   root     1450:          dirtmp->got_name_map = 0;
1.1.1.5   root     1451: 
                   1452:          if (after_include == 0)
                   1453:            after_include = dirtmp;
                   1454:          else
                   1455:            last_after_include->next = dirtmp;
                   1456:          last_after_include = dirtmp; /* Tail follows the last one */
                   1457:        }
1.1.1.6   root     1458:        /* Add directory to main path for includes,
                   1459:           with the default prefix at the front of its name.  */
                   1460:        if (!strcmp (argv[i], "-iwithprefixbefore")) {
                   1461:          struct file_name_list *dirtmp;
                   1462:          char *prefix;
                   1463: 
                   1464:          if (include_prefix != 0)
                   1465:            prefix = include_prefix;
                   1466:          else {
                   1467:            prefix = savestring (GCC_INCLUDE_DIR);
                   1468:            /* Remove the `include' from /usr/local/lib/gcc.../include.  */
                   1469:            if (!strcmp (prefix + strlen (prefix) - 8, "/include"))
                   1470:              prefix[strlen (prefix) - 7] = 0;
                   1471:          }
                   1472: 
                   1473:          dirtmp = (struct file_name_list *)
                   1474:            xmalloc (sizeof (struct file_name_list));
                   1475:          dirtmp->next = 0;     /* New one goes on the end */
                   1476:          dirtmp->control_macro = 0;
                   1477:          dirtmp->c_system_include_path = 0;
                   1478:          if (i + 1 == argc)
                   1479:            fatal ("Directory name missing after `-iwithprefixbefore' option");
                   1480: 
1.1.1.8 ! root     1481:          dirtmp->fname = xmalloc (strlen (argv[i+1]) + strlen (prefix) + 1);
1.1.1.6   root     1482:          strcpy (dirtmp->fname, prefix);
                   1483:          strcat (dirtmp->fname, argv[++i]);
1.1.1.7   root     1484:          dirtmp->got_name_map = 0;
1.1.1.6   root     1485: 
                   1486:          append_include_chain (dirtmp, dirtmp);
                   1487:        }
1.1       root     1488:        /* Add directory to end of path for includes.  */
                   1489:        if (!strcmp (argv[i], "-idirafter")) {
                   1490:          struct file_name_list *dirtmp;
                   1491: 
                   1492:          dirtmp = (struct file_name_list *)
                   1493:            xmalloc (sizeof (struct file_name_list));
                   1494:          dirtmp->next = 0;     /* New one goes on the end */
                   1495:          dirtmp->control_macro = 0;
1.1.1.6   root     1496:          dirtmp->c_system_include_path = 0;
1.1       root     1497:          if (i + 1 == argc)
1.1.1.5   root     1498:            fatal ("Directory name missing after `-idirafter' option");
1.1       root     1499:          else
                   1500:            dirtmp->fname = argv[++i];
1.1.1.7   root     1501:          dirtmp->got_name_map = 0;
1.1       root     1502: 
1.1.1.4   root     1503:          if (after_include == 0)
                   1504:            after_include = dirtmp;
                   1505:          else
                   1506:            last_after_include->next = dirtmp;
                   1507:          last_after_include = dirtmp; /* Tail follows the last one */
1.1       root     1508:        }
                   1509:        break;
                   1510: 
                   1511:       case 'o':
                   1512:        if (out_fname != NULL)
                   1513:          fatal ("Output filename specified twice");
                   1514:        if (i + 1 == argc)
                   1515:          fatal ("Filename missing after -o option");
                   1516:        out_fname = argv[++i];
                   1517:        if (!strcmp (out_fname, "-"))
                   1518:          out_fname = "";
                   1519:        break;
                   1520: 
                   1521:       case 'p':
                   1522:        if (!strcmp (argv[i], "-pedantic"))
                   1523:          pedantic = 1;
                   1524:        else if (!strcmp (argv[i], "-pedantic-errors")) {
                   1525:          pedantic = 1;
                   1526:          pedantic_errors = 1;
                   1527:        } else if (!strcmp (argv[i], "-pcp")) {
1.1.1.7   root     1528:          char *pcp_fname;
                   1529:          if (i + 1 == argc)
                   1530:            fatal ("Filename missing after -pcp option");
                   1531:          pcp_fname = argv[++i];
1.1       root     1532:          pcp_outfile = 
                   1533:            ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
                   1534:             ? fopen (pcp_fname, "w")
1.1.1.8 ! root     1535:             : stdout);
1.1       root     1536:          if (pcp_outfile == 0)
                   1537:            pfatal_with_name (pcp_fname);
                   1538:          no_precomp = 1;
                   1539:        }
                   1540:        break;
                   1541: 
                   1542:       case 't':
                   1543:        if (!strcmp (argv[i], "-traditional")) {
                   1544:          traditional = 1;
1.1.1.8 ! root     1545:          cplusplus_comments = 0;
1.1       root     1546:          if (dollars_in_ident > 0)
                   1547:            dollars_in_ident = 1;
                   1548:        } else if (!strcmp (argv[i], "-trigraphs")) {
                   1549:          no_trigraphs = 0;
                   1550:        }
                   1551:        break;
                   1552: 
                   1553:       case 'l':
                   1554:        if (! strcmp (argv[i], "-lang-c"))
1.1.1.8 ! root     1555:          cplusplus = 0, cplusplus_comments = 1, objc = 0;
        !          1556:        if (! strcmp (argv[i], "-lang-c89"))
1.1.1.4   root     1557:          cplusplus = 0, cplusplus_comments = 0, objc = 0;
1.1       root     1558:        if (! strcmp (argv[i], "-lang-c++"))
1.1.1.4   root     1559:          cplusplus = 1, cplusplus_comments = 1, objc = 0;
1.1       root     1560:        if (! strcmp (argv[i], "-lang-objc"))
1.1.1.4   root     1561:          objc = 1, cplusplus = 0, cplusplus_comments = 1;
1.1       root     1562:        if (! strcmp (argv[i], "-lang-objc++"))
1.1.1.4   root     1563:          objc = 1, cplusplus = 1, cplusplus_comments = 1;
1.1       root     1564:        if (! strcmp (argv[i], "-lang-asm"))
                   1565:          lang_asm = 1;
                   1566:        if (! strcmp (argv[i], "-lint"))
1.1.1.7   root     1567:          for_lint = 1;
1.1       root     1568:        break;
                   1569: 
                   1570:       case '+':
1.1.1.4   root     1571:        cplusplus = 1, cplusplus_comments = 1;
1.1       root     1572:        break;
                   1573: 
                   1574:       case 'w':
                   1575:        inhibit_warnings = 1;
                   1576:        break;
                   1577: 
                   1578:       case 'W':
                   1579:        if (!strcmp (argv[i], "-Wtrigraphs"))
                   1580:          warn_trigraphs = 1;
                   1581:        else if (!strcmp (argv[i], "-Wno-trigraphs"))
                   1582:          warn_trigraphs = 0;
                   1583:        else if (!strcmp (argv[i], "-Wcomment"))
                   1584:          warn_comments = 1;
                   1585:        else if (!strcmp (argv[i], "-Wno-comment"))
                   1586:          warn_comments = 0;
                   1587:        else if (!strcmp (argv[i], "-Wcomments"))
                   1588:          warn_comments = 1;
                   1589:        else if (!strcmp (argv[i], "-Wno-comments"))
                   1590:          warn_comments = 0;
                   1591:        else if (!strcmp (argv[i], "-Wtraditional"))
                   1592:          warn_stringify = 1;
                   1593:        else if (!strcmp (argv[i], "-Wno-traditional"))
                   1594:          warn_stringify = 0;
1.1.1.2   root     1595:        else if (!strcmp (argv[i], "-Wimport"))
                   1596:          warn_import = 1;
                   1597:        else if (!strcmp (argv[i], "-Wno-import"))
                   1598:          warn_import = 0;
1.1       root     1599:        else if (!strcmp (argv[i], "-Werror"))
                   1600:          warnings_are_errors = 1;
                   1601:        else if (!strcmp (argv[i], "-Wno-error"))
                   1602:          warnings_are_errors = 0;
                   1603:        else if (!strcmp (argv[i], "-Wall"))
                   1604:          {
                   1605:            warn_trigraphs = 1;
                   1606:            warn_comments = 1;
                   1607:          }
                   1608:        break;
                   1609: 
                   1610:       case 'M':
1.1.1.7   root     1611:        /* The style of the choices here is a bit mixed.
                   1612:           The chosen scheme is a hybrid of keeping all options in one string
                   1613:           and specifying each option in a separate argument:
                   1614:           -M|-MM|-MD file|-MMD file [-MG].  An alternative is:
                   1615:           -M|-MM|-MD file|-MMD file|-MG|-MMG; or more concisely:
                   1616:           -M[M][G][D file].  This is awkward to handle in specs, and is not
                   1617:           as extensible.  */
                   1618:        /* ??? -MG must be specified in addition to one of -M or -MM.
                   1619:           This can be relaxed in the future without breaking anything.
                   1620:           The converse isn't true.  */
                   1621: 
                   1622:        /* -MG isn't valid with -MD or -MMD.  This is checked for later.  */
                   1623:        if (!strcmp (argv[i], "-MG"))
                   1624:          {
                   1625:            print_deps_missing_files = 1;
                   1626:            break;
                   1627:          }
1.1       root     1628:        if (!strcmp (argv[i], "-M"))
                   1629:          print_deps = 2;
                   1630:        else if (!strcmp (argv[i], "-MM"))
                   1631:          print_deps = 1;
                   1632:        else if (!strcmp (argv[i], "-MD"))
                   1633:          print_deps = 2;
                   1634:        else if (!strcmp (argv[i], "-MMD"))
                   1635:          print_deps = 1;
                   1636:        /* For -MD and -MMD options, write deps on file named by next arg.  */
                   1637:        if (!strcmp (argv[i], "-MD")
                   1638:            || !strcmp (argv[i], "-MMD")) {
1.1.1.7   root     1639:          if (i + 1 == argc)
                   1640:            fatal ("Filename missing after %s option", argv[i]);
1.1       root     1641:          i++;
                   1642:          deps_file = argv[i];
1.1.1.5   root     1643:          deps_mode = "w";
1.1       root     1644:        } else {
                   1645:          /* For -M and -MM, write deps on standard output
                   1646:             and suppress the usual output.  */
                   1647:          deps_stream = stdout;
                   1648:          inhibit_output = 1;
                   1649:        }         
                   1650:        break;
                   1651: 
                   1652:       case 'd':
                   1653:        {
                   1654:          char *p = argv[i] + 2;
                   1655:          char c;
1.1.1.8 ! root     1656:          while ((c = *p++)) {
1.1       root     1657:            /* Arg to -d specifies what parts of macros to dump */
                   1658:            switch (c) {
                   1659:            case 'M':
                   1660:              dump_macros = dump_only;
                   1661:              no_output = 1;
                   1662:              break;
                   1663:            case 'N':
                   1664:              dump_macros = dump_names;
                   1665:              break;
                   1666:            case 'D':
                   1667:              dump_macros = dump_definitions;
                   1668:              break;
                   1669:            }
                   1670:          }
                   1671:        }
                   1672:        break;
                   1673: 
                   1674:       case 'g':
                   1675:        if (argv[i][2] == '3')
                   1676:          debug_output = 1;
                   1677:        break;
                   1678: 
                   1679:       case 'v':
                   1680:        fprintf (stderr, "GNU CPP version %s", version_string);
                   1681: #ifdef TARGET_VERSION
                   1682:        TARGET_VERSION;
                   1683: #endif
                   1684:        fprintf (stderr, "\n");
1.1.1.6   root     1685:        verbose = 1;
1.1       root     1686:        break;
                   1687: 
                   1688:       case 'H':
                   1689:        print_include_names = 1;
                   1690:        break;
                   1691: 
                   1692:       case 'D':
1.1.1.7   root     1693:        if (argv[i][2] != 0)
                   1694:          pend_defs[i] = argv[i] + 2;
                   1695:        else if (i + 1 == argc)
                   1696:          fatal ("Macro name missing after -D option");
                   1697:        else
                   1698:          i++, pend_defs[i] = argv[i];
1.1       root     1699:        break;
                   1700: 
                   1701:       case 'A':
                   1702:        {
1.1.1.7   root     1703:          char *p;
1.1       root     1704: 
                   1705:          if (argv[i][2] != 0)
                   1706:            p = argv[i] + 2;
                   1707:          else if (i + 1 == argc)
                   1708:            fatal ("Assertion missing after -A option");
                   1709:          else
                   1710:            p = argv[++i];
                   1711: 
                   1712:          if (!strcmp (p, "-")) {
                   1713:            /* -A- eliminates all predefined macros and assertions.
                   1714:               Let's include also any that were specified earlier
                   1715:               on the command line.  That way we can get rid of any
                   1716:               that were passed automatically in from GCC.  */
                   1717:            int j;
                   1718:            inhibit_predefs = 1;
                   1719:            for (j = 0; j < i; j++)
                   1720:              pend_defs[j] = pend_assertions[j] = 0;
                   1721:          } else {
                   1722:            pend_assertions[i] = p;
                   1723:            pend_assertion_options[i] = "-A";
                   1724:          }
                   1725:        }
                   1726:        break;
                   1727: 
                   1728:       case 'U':                /* JF #undef something */
                   1729:        if (argv[i][2] != 0)
                   1730:          pend_undefs[i] = argv[i] + 2;
                   1731:        else if (i + 1 == argc)
                   1732:          fatal ("Macro name missing after -U option");
                   1733:        else
                   1734:          pend_undefs[i] = argv[i+1], i++;
                   1735:        break;
                   1736: 
                   1737:       case 'C':
                   1738:        put_out_comments = 1;
                   1739:        break;
                   1740: 
                   1741:       case 'E':                        /* -E comes from cc -E; ignore it.  */
                   1742:        break;
                   1743: 
                   1744:       case 'P':
1.1.1.8 ! root     1745:        no_line_directives = 1;
1.1       root     1746:        break;
                   1747: 
                   1748:       case '$':                        /* Don't include $ in identifiers.  */
                   1749:        dollars_in_ident = 0;
                   1750:        break;
                   1751: 
                   1752:       case 'I':                        /* Add directory to path for includes.  */
                   1753:        {
                   1754:          struct file_name_list *dirtmp;
                   1755: 
1.1.1.4   root     1756:          if (! ignore_srcdir && !strcmp (argv[i] + 2, "-")) {
1.1       root     1757:            ignore_srcdir = 1;
1.1.1.4   root     1758:            /* Don't use any preceding -I directories for #include <...>.  */
                   1759:            first_bracket_include = 0;
                   1760:          }
1.1       root     1761:          else {
                   1762:            dirtmp = (struct file_name_list *)
                   1763:              xmalloc (sizeof (struct file_name_list));
                   1764:            dirtmp->next = 0;           /* New one goes on the end */
                   1765:            dirtmp->control_macro = 0;
1.1.1.6   root     1766:            dirtmp->c_system_include_path = 0;
1.1       root     1767:            if (argv[i][2] != 0)
                   1768:              dirtmp->fname = argv[i] + 2;
                   1769:            else if (i + 1 == argc)
                   1770:              fatal ("Directory name missing after -I option");
                   1771:            else
                   1772:              dirtmp->fname = argv[++i];
1.1.1.7   root     1773:            dirtmp->got_name_map = 0;
1.1.1.4   root     1774:            append_include_chain (dirtmp, dirtmp);
                   1775:          }
1.1       root     1776:        }
                   1777:        break;
                   1778: 
                   1779:       case 'n':
                   1780:        if (!strcmp (argv[i], "-nostdinc"))
                   1781:          /* -nostdinc causes no default include directories.
                   1782:             You must specify all include-file directories with -I.  */
                   1783:          no_standard_includes = 1;
1.1.1.3   root     1784:        else if (!strcmp (argv[i], "-nostdinc++"))
                   1785:          /* -nostdinc++ causes no default C++-specific include directories. */
                   1786:          no_standard_cplusplus_includes = 1;
1.1       root     1787:        else if (!strcmp (argv[i], "-noprecomp"))
                   1788:          no_precomp = 1;
                   1789:        break;
                   1790: 
                   1791:       case 'u':
                   1792:        /* Sun compiler passes undocumented switch "-undef".
                   1793:           Let's assume it means to inhibit the predefined symbols.  */
                   1794:        inhibit_predefs = 1;
                   1795:        break;
                   1796: 
                   1797:       case '\0': /* JF handle '-' as file name meaning stdin or stdout */
                   1798:        if (in_fname == NULL) {
                   1799:          in_fname = "";
                   1800:          break;
                   1801:        } else if (out_fname == NULL) {
                   1802:          out_fname = "";
                   1803:          break;
                   1804:        }       /* else fall through into error */
                   1805: 
                   1806:       default:
                   1807:        fatal ("Invalid option `%s'", argv[i]);
                   1808:       }
                   1809:     }
                   1810:   }
                   1811: 
                   1812:   /* Add dirs from CPATH after dirs from -I.  */
                   1813:   /* There seems to be confusion about what CPATH should do,
                   1814:      so for the moment it is not documented.  */
                   1815:   /* Some people say that CPATH should replace the standard include dirs,
                   1816:      but that seems pointless: it comes before them, so it overrides them
                   1817:      anyway.  */
1.1.1.8 ! root     1818:   cp = getenv ("CPATH");
        !          1819:   if (cp && ! no_standard_includes)
        !          1820:     path_include (cp);
1.1       root     1821: 
                   1822:   /* Now that dollars_in_ident is known, initialize is_idchar.  */
                   1823:   initialize_char_syntax ();
                   1824: 
                   1825:   /* Initialize output buffer */
                   1826: 
                   1827:   outbuf.buf = (U_CHAR *) xmalloc (OUTBUF_SIZE);
                   1828:   outbuf.bufp = outbuf.buf;
                   1829:   outbuf.length = OUTBUF_SIZE;
                   1830: 
                   1831:   /* Do partial setup of input buffer for the sake of generating
                   1832:      early #line directives (when -g is in effect).  */
                   1833: 
                   1834:   fp = &instack[++indepth];
                   1835:   if (in_fname == NULL)
                   1836:     in_fname = "";
                   1837:   fp->nominal_fname = fp->fname = in_fname;
                   1838:   fp->lineno = 0;
                   1839: 
1.1.1.7   root     1840:   /* In C++, wchar_t is a distinct basic type, and we can expect
                   1841:      __wchar_t to be defined by cc1plus.  */
                   1842:   if (cplusplus)
                   1843:     wchar_type = "__wchar_t";
                   1844: 
1.1       root     1845:   /* Install __LINE__, etc.  Must follow initialize_char_syntax
                   1846:      and option processing.  */
                   1847:   initialize_builtins (fp, &outbuf);
                   1848: 
                   1849:   /* Do standard #defines and assertions
                   1850:      that identify system and machine type.  */
                   1851: 
                   1852:   if (!inhibit_predefs) {
                   1853:     char *p = (char *) alloca (strlen (predefs) + 1);
                   1854:     strcpy (p, predefs);
                   1855:     while (*p) {
                   1856:       char *q;
                   1857:       while (*p == ' ' || *p == '\t')
                   1858:        p++;
                   1859:       /* Handle -D options.  */ 
                   1860:       if (p[0] == '-' && p[1] == 'D') {
                   1861:        q = &p[2];
                   1862:        while (*p && *p != ' ' && *p != '\t')
                   1863:          p++;
                   1864:        if (*p != 0)
                   1865:          *p++= 0;
                   1866:        if (debug_output)
1.1.1.8 ! root     1867:          output_line_directive (fp, &outbuf, 0, same_file);
1.1       root     1868:        make_definition (q, &outbuf);
                   1869:        while (*p == ' ' || *p == '\t')
                   1870:          p++;
                   1871:       } else if (p[0] == '-' && p[1] == 'A') {
                   1872:        /* Handle -A options (assertions).  */ 
                   1873:        char *assertion;
                   1874:        char *past_name;
                   1875:        char *value;
                   1876:        char *past_value;
                   1877:        char *termination;
                   1878:        int save_char;
                   1879: 
                   1880:        assertion = &p[2];
                   1881:        past_name = assertion;
                   1882:        /* Locate end of name.  */
                   1883:        while (*past_name && *past_name != ' '
                   1884:               && *past_name != '\t' && *past_name != '(')
                   1885:          past_name++;
                   1886:        /* Locate `(' at start of value.  */
                   1887:        value = past_name;
                   1888:        while (*value && (*value == ' ' || *value == '\t'))
                   1889:          value++;
                   1890:        if (*value++ != '(')
                   1891:          abort ();
                   1892:        while (*value && (*value == ' ' || *value == '\t'))
                   1893:          value++;
                   1894:        past_value = value;
                   1895:        /* Locate end of value.  */
                   1896:        while (*past_value && *past_value != ' '
                   1897:               && *past_value != '\t' && *past_value != ')')
                   1898:          past_value++;
                   1899:        termination = past_value;
                   1900:        while (*termination && (*termination == ' ' || *termination == '\t'))
                   1901:          termination++;
                   1902:        if (*termination++ != ')')
                   1903:          abort ();
                   1904:        if (*termination && *termination != ' ' && *termination != '\t')
                   1905:          abort ();
                   1906:        /* Temporarily null-terminate the value.  */
                   1907:        save_char = *termination;
                   1908:        *termination = '\0';
                   1909:        /* Install the assertion.  */
                   1910:        make_assertion ("-A", assertion);
                   1911:        *termination = (char) save_char;
                   1912:        p = termination;
                   1913:        while (*p == ' ' || *p == '\t')
                   1914:          p++;
                   1915:       } else {
                   1916:        abort ();
                   1917:       }
                   1918:     }
                   1919:   }
                   1920: 
                   1921:   /* Now handle the command line options.  */
                   1922: 
1.1.1.4   root     1923:   /* Do -U's, -D's and -A's in the order they were seen.  */
                   1924:   for (i = 1; i < argc; i++) {
                   1925:     if (pend_undefs[i]) {
1.1       root     1926:       if (debug_output)
1.1.1.8 ! root     1927:         output_line_directive (fp, &outbuf, 0, same_file);
1.1.1.4   root     1928:       make_undef (pend_undefs[i], &outbuf);
1.1       root     1929:     }
1.1.1.4   root     1930:     if (pend_defs[i]) {
1.1       root     1931:       if (debug_output)
1.1.1.8 ! root     1932:         output_line_directive (fp, &outbuf, 0, same_file);
1.1.1.4   root     1933:       make_definition (pend_defs[i], &outbuf);
1.1       root     1934:     }
1.1.1.4   root     1935:     if (pend_assertions[i])
                   1936:       make_assertion (pend_assertion_options[i], pend_assertions[i]);
                   1937:   }
1.1       root     1938: 
                   1939:   done_initializing = 1;
                   1940: 
                   1941:   { /* read the appropriate environment variable and if it exists
                   1942:        replace include_defaults with the listed path. */
                   1943:     char *epath = 0;
                   1944:     switch ((objc << 1) + cplusplus)
                   1945:       {
                   1946:       case 0:
                   1947:        epath = getenv ("C_INCLUDE_PATH");
                   1948:        break;
                   1949:       case 1:
1.1.1.2   root     1950:        epath = getenv ("CPLUS_INCLUDE_PATH");
1.1       root     1951:        break;
                   1952:       case 2:
                   1953:        epath = getenv ("OBJC_INCLUDE_PATH");
                   1954:        break;
                   1955:       case 3:
1.1.1.2   root     1956:        epath = getenv ("OBJCPLUS_INCLUDE_PATH");
1.1       root     1957:        break;
                   1958:       }
                   1959:     /* If the environment var for this language is set,
                   1960:        add to the default list of include directories.  */
                   1961:     if (epath) {
                   1962:       char *nstore = (char *) alloca (strlen (epath) + 2);
                   1963:       int num_dirs;
                   1964:       char *startp, *endp;
                   1965: 
                   1966:       for (num_dirs = 1, startp = epath; *startp; startp++)
1.1.1.3   root     1967:        if (*startp == PATH_SEPARATOR)
1.1       root     1968:          num_dirs++;
                   1969:       include_defaults
                   1970:        = (struct default_include *) xmalloc ((num_dirs
                   1971:                                               * sizeof (struct default_include))
                   1972:                                              + sizeof (include_defaults_array));
                   1973:       startp = endp = epath;
                   1974:       num_dirs = 0;
                   1975:       while (1) {
1.1.1.2   root     1976:         /* Handle cases like c:/usr/lib:d:/gcc/lib */
1.1.1.3   root     1977:         if ((*endp == PATH_SEPARATOR
                   1978: #if 0 /* Obsolete, now that we use semicolons as the path separator.  */
1.1.1.2   root     1979: #ifdef __MSDOS__
1.1.1.4   root     1980:             && (endp-startp != 1 || !isalpha (*startp))
1.1.1.2   root     1981: #endif
1.1.1.3   root     1982: #endif
1.1.1.2   root     1983:             )
1.1.1.3   root     1984:             || *endp == 0) {
1.1       root     1985:          strncpy (nstore, startp, endp-startp);
                   1986:          if (endp == startp)
                   1987:            strcpy (nstore, ".");
                   1988:          else
                   1989:            nstore[endp-startp] = '\0';
                   1990: 
                   1991:          include_defaults[num_dirs].fname = savestring (nstore);
                   1992:          include_defaults[num_dirs].cplusplus = cplusplus;
1.1.1.7   root     1993:          include_defaults[num_dirs].cxx_aware = 1;
1.1       root     1994:          num_dirs++;
                   1995:          if (*endp == '\0')
                   1996:            break;
                   1997:          endp = startp = endp + 1;
                   1998:        } else
                   1999:          endp++;
                   2000:       }
                   2001:       /* Put the usual defaults back in at the end.  */
1.1.1.7   root     2002:       bcopy ((char *) include_defaults_array,
                   2003:             (char *) &include_defaults[num_dirs],
1.1       root     2004:             sizeof (include_defaults_array));
                   2005:     }
                   2006:   }
                   2007: 
1.1.1.7   root     2008:   append_include_chain (before_system, last_before_system);
                   2009:   first_system_include = before_system;
                   2010: 
1.1       root     2011:   /* Unless -fnostdinc,
                   2012:      tack on the standard include file dirs to the specified list */
                   2013:   if (!no_standard_includes) {
                   2014:     struct default_include *p = include_defaults;
1.1.1.3   root     2015:     char *specd_prefix = include_prefix;
1.1       root     2016:     char *default_prefix = savestring (GCC_INCLUDE_DIR);
                   2017:     int default_len = 0;
                   2018:     /* Remove the `include' from /usr/local/lib/gcc.../include.  */
                   2019:     if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {
                   2020:       default_len = strlen (default_prefix) - 7;
                   2021:       default_prefix[default_len] = 0;
                   2022:     }
                   2023:     /* Search "translated" versions of GNU directories.
                   2024:        These have /usr/local/lib/gcc... replaced by specd_prefix.  */
                   2025:     if (specd_prefix != 0 && default_len != 0)
                   2026:       for (p = include_defaults; p->fname; p++) {
                   2027:        /* Some standard dirs are only for C++.  */
1.1.1.3   root     2028:        if (!p->cplusplus || (cplusplus && !no_standard_cplusplus_includes)) {
1.1       root     2029:          /* Does this dir start with the prefix?  */
                   2030:          if (!strncmp (p->fname, default_prefix, default_len)) {
                   2031:            /* Yes; change prefix and add to search list.  */
                   2032:            struct file_name_list *new
                   2033:              = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
                   2034:            int this_len = strlen (specd_prefix) + strlen (p->fname) - default_len;
1.1.1.8 ! root     2035:            char *str = xmalloc (this_len + 1);
1.1       root     2036:            strcpy (str, specd_prefix);
                   2037:            strcat (str, p->fname + default_len);
                   2038:            new->fname = str;
                   2039:            new->control_macro = 0;
1.1.1.7   root     2040:            new->c_system_include_path = !p->cxx_aware;
                   2041:            new->got_name_map = 0;
1.1.1.4   root     2042:            append_include_chain (new, new);
                   2043:            if (first_system_include == 0)
                   2044:              first_system_include = new;
1.1       root     2045:          }
                   2046:        }
                   2047:       }
                   2048:     /* Search ordinary names for GNU include directories.  */
                   2049:     for (p = include_defaults; p->fname; p++) {
                   2050:       /* Some standard dirs are only for C++.  */
1.1.1.3   root     2051:       if (!p->cplusplus || (cplusplus && !no_standard_cplusplus_includes)) {
1.1       root     2052:        struct file_name_list *new
                   2053:          = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
                   2054:        new->control_macro = 0;
1.1.1.7   root     2055:        new->c_system_include_path = !p->cxx_aware;
1.1       root     2056:        new->fname = p->fname;
1.1.1.7   root     2057:        new->got_name_map = 0;
1.1.1.4   root     2058:        append_include_chain (new, new);
                   2059:        if (first_system_include == 0)
                   2060:          first_system_include = new;
1.1       root     2061:       }
                   2062:     }
                   2063:   }
                   2064: 
                   2065:   /* Tack the after_include chain at the end of the include chain.  */
1.1.1.4   root     2066:   append_include_chain (after_include, last_after_include);
                   2067:   if (first_system_include == 0)
                   2068:     first_system_include = after_include;
1.1       root     2069: 
1.1.1.6   root     2070:   /* With -v, print the list of dirs to search.  */
                   2071:   if (verbose) {
                   2072:     struct file_name_list *p;
                   2073:     fprintf (stderr, "#include \"...\" search starts here:\n");
                   2074:     for (p = include; p; p = p->next) {
                   2075:       if (p == first_bracket_include)
                   2076:        fprintf (stderr, "#include <...> search starts here:\n");
                   2077:       fprintf (stderr, " %s\n", p->fname);
                   2078:     }
                   2079:     fprintf (stderr, "End of search list.\n");
                   2080:   }
                   2081: 
1.1       root     2082:   /* Scan the -imacros files before the main input.
                   2083:      Much like #including them, but with no_output set
                   2084:      so that only their macro definitions matter.  */
                   2085: 
1.1.1.7   root     2086:   no_output++; no_record_file++;
1.1       root     2087:   for (i = 1; i < argc; i++)
                   2088:     if (pend_files[i]) {
                   2089:       int fd = open (pend_files[i], O_RDONLY, 0666);
                   2090:       if (fd < 0) {
                   2091:        perror_with_name (pend_files[i]);
1.1.1.8 ! root     2092:        return FATAL_EXIT_CODE;
1.1       root     2093:       }
1.1.1.4   root     2094:       finclude (fd, pend_files[i], &outbuf, 0, NULL_PTR);
1.1       root     2095:     }
1.1.1.7   root     2096:   no_output--; no_record_file--;
1.1       root     2097: 
                   2098:   /* Copy the entire contents of the main input file into
                   2099:      the stacked input buffer previously allocated for it.  */
                   2100: 
                   2101:   /* JF check for stdin */
                   2102:   if (in_fname == NULL || *in_fname == 0) {
                   2103:     in_fname = "";
                   2104:     f = 0;
                   2105:   } else if ((f = open (in_fname, O_RDONLY, 0666)) < 0)
                   2106:     goto perror;
                   2107: 
1.1.1.7   root     2108:   /* -MG doesn't select the form of output and must be specified with one of
                   2109:      -M or -MM.  -MG doesn't make sense with -MD or -MMD since they don't
                   2110:      inhibit compilation.  */
                   2111:   if (print_deps_missing_files && (print_deps == 0 || !inhibit_output))
                   2112:     fatal ("-MG must be specified with one of -M or -MM");
                   2113: 
1.1       root     2114:   /* Either of two environment variables can specify output of deps.
                   2115:      Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
                   2116:      where OUTPUT_FILE is the file to write deps info to
                   2117:      and DEPS_TARGET is the target to mention in the deps.  */
                   2118: 
                   2119:   if (print_deps == 0
                   2120:       && (getenv ("SUNPRO_DEPENDENCIES") != 0
                   2121:          || getenv ("DEPENDENCIES_OUTPUT") != 0)) {
                   2122:     char *spec = getenv ("DEPENDENCIES_OUTPUT");
                   2123:     char *s;
                   2124:     char *output_file;
                   2125: 
                   2126:     if (spec == 0) {
                   2127:       spec = getenv ("SUNPRO_DEPENDENCIES");
                   2128:       print_deps = 2;
                   2129:     }
                   2130:     else
                   2131:       print_deps = 1;
                   2132: 
                   2133:     s = spec;
                   2134:     /* Find the space before the DEPS_TARGET, if there is one.  */
1.1.1.4   root     2135:     /* This should use index.  (mrs) */
1.1       root     2136:     while (*s != 0 && *s != ' ') s++;
                   2137:     if (*s != 0) {
                   2138:       deps_target = s + 1;
1.1.1.8 ! root     2139:       output_file = xmalloc (s - spec + 1);
1.1       root     2140:       bcopy (spec, output_file, s - spec);
                   2141:       output_file[s - spec] = 0;
                   2142:     }
                   2143:     else {
                   2144:       deps_target = 0;
                   2145:       output_file = spec;
                   2146:     }
                   2147:       
                   2148:     deps_file = output_file;
1.1.1.5   root     2149:     deps_mode = "a";
1.1       root     2150:   }
                   2151: 
                   2152:   /* For -M, print the expected object file name
                   2153:      as the target of this Make-rule.  */
                   2154:   if (print_deps) {
                   2155:     deps_allocated_size = 200;
1.1.1.8 ! root     2156:     deps_buffer = xmalloc (deps_allocated_size);
1.1       root     2157:     deps_buffer[0] = 0;
                   2158:     deps_size = 0;
                   2159:     deps_column = 0;
                   2160: 
                   2161:     if (deps_target) {
1.1.1.7   root     2162:       deps_output (deps_target, ':');
                   2163:     } else if (*in_fname == 0) {
                   2164:       deps_output ("-", ':');
                   2165:     } else {
                   2166:       char *p, *q;
1.1       root     2167:       int len;
1.1.1.7   root     2168: 
                   2169:       /* Discard all directory prefixes from filename.  */
                   2170:       if ((q = rindex (in_fname, '/')) != NULL
                   2171: #ifdef DIR_SEPARATOR
                   2172:          && (q = rindex (in_fname, DIR_SEPARATOR)) != NULL
                   2173: #endif
                   2174:          )
                   2175:        ++q;
                   2176:       else
                   2177:        q = in_fname;
                   2178: 
                   2179:       /* Copy remainder to mungable area.  */
                   2180:       p = (char *) alloca (strlen(q) + 8);
                   2181:       strcpy (p, q);
                   2182: 
1.1       root     2183:       /* Output P, but remove known suffixes.  */
                   2184:       len = strlen (p);
1.1.1.7   root     2185:       q = p + len;
                   2186:       if (len >= 2
                   2187:          && p[len - 2] == '.'
                   2188:          && index("cCsSm", p[len - 1]))
                   2189:        q = p + (len - 2);
                   2190:       else if (len >= 3
                   2191:               && p[len - 3] == '.'
1.1       root     2192:               && p[len - 2] == 'c'
                   2193:               && p[len - 1] == 'c')
1.1.1.7   root     2194:        q = p + (len - 3);
                   2195:       else if (len >= 4
                   2196:               && p[len - 4] == '.'
1.1.1.5   root     2197:               && p[len - 3] == 'c'
                   2198:               && p[len - 2] == 'x'
                   2199:               && p[len - 1] == 'x')
1.1.1.7   root     2200:        q = p + (len - 4);
                   2201:       else if (len >= 4
                   2202:               && p[len - 4] == '.'
                   2203:               && p[len - 3] == 'c'
                   2204:               && p[len - 2] == 'p'
                   2205:               && p[len - 1] == 'p')
                   2206:        q = p + (len - 4);
                   2207: 
1.1       root     2208:       /* Supply our own suffix.  */
1.1.1.4   root     2209: #ifndef VMS
1.1.1.7   root     2210:       strcpy (q, ".o");
1.1.1.4   root     2211: #else
1.1.1.7   root     2212:       strcpy (q, ".obj");
1.1.1.4   root     2213: #endif
1.1.1.7   root     2214: 
                   2215:       deps_output (p, ':');
                   2216:       deps_output (in_fname, ' ');
1.1       root     2217:     }
                   2218:   }
                   2219: 
                   2220:   file_size_and_mode (f, &st_mode, &st_size);
                   2221:   fp->nominal_fname = fp->fname = in_fname;
                   2222:   fp->lineno = 1;
                   2223:   fp->system_header_p = 0;
                   2224:   /* JF all this is mine about reading pipes and ttys */
                   2225:   if (! S_ISREG (st_mode)) {
                   2226:     /* Read input from a file that is not a normal disk file.
                   2227:        We cannot preallocate a buffer with the correct size,
                   2228:        so we must read in the file a piece at the time and make it bigger.  */
                   2229:     int size;
                   2230:     int bsize;
                   2231:     int cnt;
                   2232: 
                   2233:     bsize = 2000;
                   2234:     size = 0;
                   2235:     fp->buf = (U_CHAR *) xmalloc (bsize + 2);
                   2236:     for (;;) {
1.1.1.8 ! root     2237:       cnt = safe_read (f, (char *) fp->buf + size, bsize - size);
1.1       root     2238:       if (cnt < 0) goto perror;        /* error! */
                   2239:       size += cnt;
1.1.1.7   root     2240:       if (size != bsize) break;        /* End of file */
                   2241:       bsize *= 2;
                   2242:       fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
1.1       root     2243:     }
                   2244:     fp->length = size;
                   2245:   } else {
                   2246:     /* Read a file whose size we can determine in advance.
                   2247:        For the sake of VMS, st_size is just an upper bound.  */
                   2248:     fp->buf = (U_CHAR *) xmalloc (st_size + 2);
1.1.1.8 ! root     2249:     fp->length = safe_read (f, (char *) fp->buf, st_size);
1.1.1.7   root     2250:     if (fp->length < 0) goto perror;
1.1       root     2251:   }
                   2252:   fp->bufp = fp->buf;
                   2253:   fp->if_stack = if_stack;
                   2254: 
                   2255:   /* Make sure data ends with a newline.  And put a null after it.  */
                   2256: 
                   2257:   if ((fp->length > 0 && fp->buf[fp->length - 1] != '\n')
                   2258:       /* Backslash-newline at end is not good enough.  */
                   2259:       || (fp->length > 1 && fp->buf[fp->length - 2] == '\\')) {
                   2260:     fp->buf[fp->length++] = '\n';
                   2261:     missing_newline = 1;
                   2262:   }
                   2263:   fp->buf[fp->length] = '\0';
                   2264: 
                   2265:   /* Unless inhibited, convert trigraphs in the input.  */
                   2266: 
                   2267:   if (!no_trigraphs)
                   2268:     trigraph_pcp (fp);
                   2269: 
                   2270:   /* Now that we know the input file is valid, open the output.  */
                   2271: 
                   2272:   if (!out_fname || !strcmp (out_fname, ""))
                   2273:     out_fname = "stdout";
                   2274:   else if (! freopen (out_fname, "w", stdout))
                   2275:     pfatal_with_name (out_fname);
                   2276: 
1.1.1.8 ! root     2277:   output_line_directive (fp, &outbuf, 0, same_file);
1.1       root     2278: 
                   2279:   /* Scan the -include files before the main input.  */
                   2280: 
1.1.1.7   root     2281:   no_record_file++;
1.1       root     2282:   for (i = 1; i < argc; i++)
                   2283:     if (pend_includes[i]) {
                   2284:       int fd = open (pend_includes[i], O_RDONLY, 0666);
                   2285:       if (fd < 0) {
                   2286:        perror_with_name (pend_includes[i]);
1.1.1.8 ! root     2287:        return FATAL_EXIT_CODE;
1.1       root     2288:       }
1.1.1.4   root     2289:       finclude (fd, pend_includes[i], &outbuf, 0, NULL_PTR);
1.1       root     2290:     }
1.1.1.7   root     2291:   no_record_file--;
1.1       root     2292: 
                   2293:   /* Scan the input, processing macros and directives.  */
                   2294: 
                   2295:   rescan (&outbuf, 0);
                   2296: 
1.1.1.5   root     2297:   if (missing_newline)
                   2298:     fp->lineno--;
                   2299: 
1.1       root     2300:   if (pedantic && missing_newline)
                   2301:     pedwarn ("file does not end in newline");
                   2302: 
                   2303:   /* Now we have processed the entire input
                   2304:      Write whichever kind of output has been requested.  */
                   2305: 
                   2306:   if (dump_macros == dump_only)
                   2307:     dump_all_macros ();
                   2308:   else if (! inhibit_output) {
                   2309:     write_output ();
                   2310:   }
                   2311: 
                   2312:   if (print_deps) {
1.1.1.4   root     2313:     /* Don't actually write the deps file if compilation has failed.  */
                   2314:     if (errors == 0) {
1.1.1.5   root     2315:       if (deps_file && ! (deps_stream = fopen (deps_file, deps_mode)))
1.1.1.4   root     2316:        pfatal_with_name (deps_file);
1.1       root     2317:       fputs (deps_buffer, deps_stream);
                   2318:       putc ('\n', deps_stream);
1.1.1.4   root     2319:       if (deps_file) {
                   2320:        if (ferror (deps_stream) || fclose (deps_stream) != 0)
1.1       root     2321:          fatal ("I/O error on output");
                   2322:       }
                   2323:     }
                   2324:   }
                   2325: 
1.1.1.5   root     2326:   if (pcp_outfile && pcp_outfile != stdout
                   2327:       && (ferror (pcp_outfile) || fclose (pcp_outfile) != 0))
                   2328:     fatal ("I/O error on `-pcp' output");
                   2329: 
1.1.1.4   root     2330:   if (ferror (stdout) || fclose (stdout) != 0)
1.1       root     2331:     fatal ("I/O error on output");
                   2332: 
                   2333:   if (errors)
1.1.1.8 ! root     2334:     exit (FATAL_EXIT_CODE);
1.1       root     2335:   exit (SUCCESS_EXIT_CODE);
                   2336: 
                   2337:  perror:
                   2338:   pfatal_with_name (in_fname);
                   2339:   return 0;
                   2340: }
                   2341: 
                   2342: /* Given a colon-separated list of file names PATH,
                   2343:    add all the names to the search path for include files.  */
                   2344: 
                   2345: static void
                   2346: path_include (path)
                   2347:      char *path;
                   2348: {
                   2349:   char *p;
                   2350: 
                   2351:   p = path;
                   2352: 
                   2353:   if (*p)
                   2354:     while (1) {
                   2355:       char *q = p;
                   2356:       char *name;
                   2357:       struct file_name_list *dirtmp;
                   2358: 
                   2359:       /* Find the end of this name.  */
1.1.1.3   root     2360:       while (*q != 0 && *q != PATH_SEPARATOR) q++;
1.1       root     2361:       if (p == q) {
                   2362:        /* An empty name in the path stands for the current directory.  */
1.1.1.8 ! root     2363:        name = xmalloc (2);
1.1       root     2364:        name[0] = '.';
                   2365:        name[1] = 0;
                   2366:       } else {
                   2367:        /* Otherwise use the directory that is named.  */
1.1.1.8 ! root     2368:        name = xmalloc (q - p + 1);
1.1       root     2369:        bcopy (p, name, q - p);
                   2370:        name[q - p] = 0;
                   2371:       }
                   2372: 
                   2373:       dirtmp = (struct file_name_list *)
                   2374:        xmalloc (sizeof (struct file_name_list));
                   2375:       dirtmp->next = 0;                /* New one goes on the end */
                   2376:       dirtmp->control_macro = 0;
1.1.1.6   root     2377:       dirtmp->c_system_include_path = 0;
1.1       root     2378:       dirtmp->fname = name;
1.1.1.7   root     2379:       dirtmp->got_name_map = 0;
1.1.1.4   root     2380:       append_include_chain (dirtmp, dirtmp);
1.1       root     2381: 
                   2382:       /* Advance past this name.  */
                   2383:       p = q;
                   2384:       if (*p == 0)
                   2385:        break;
                   2386:       /* Skip the colon.  */
                   2387:       p++;
                   2388:     }
                   2389: }
                   2390: 
1.1.1.7   root     2391: /* Return the address of the first character in S that equals C.
                   2392:    S is an array of length N, possibly containing '\0's, and followed by '\0'.
                   2393:    Return 0 if there is no such character.  Assume that C itself is not '\0'.
                   2394:    If we knew we could use memchr, we could just invoke memchr (S, C, N),
                   2395:    but unfortunately memchr isn't autoconfigured yet.  */
                   2396: 
                   2397: static U_CHAR *
                   2398: index0 (s, c, n)
                   2399:      U_CHAR *s;
                   2400:      int c;
1.1.1.8 ! root     2401:      size_t n;
1.1.1.7   root     2402: {
1.1.1.8 ! root     2403:   char *p = (char *) s;
1.1.1.7   root     2404:   for (;;) {
1.1.1.8 ! root     2405:     char *q = index (p, c);
1.1.1.7   root     2406:     if (q)
                   2407:       return (U_CHAR *) q;
                   2408:     else {
1.1.1.8 ! root     2409:       size_t l = strlen (p);
1.1.1.7   root     2410:       if (l == n)
                   2411:        return 0;
                   2412:       l++;
1.1.1.8 ! root     2413:       p += l;
1.1.1.7   root     2414:       n -= l;
                   2415:     }
                   2416:   }
                   2417: }
                   2418: 
1.1       root     2419: /* Pre-C-Preprocessor to translate ANSI trigraph idiocy in BUF
                   2420:    before main CCCP processing.  Name `pcp' is also in honor of the
                   2421:    drugs the trigraph designers must have been on.
                   2422: 
                   2423:    Using an extra pass through the buffer takes a little extra time,
                   2424:    but is infinitely less hairy than trying to handle trigraphs inside
                   2425:    strings, etc. everywhere, and also makes sure that trigraphs are
                   2426:    only translated in the top level of processing. */
                   2427: 
                   2428: static void
                   2429: trigraph_pcp (buf)
                   2430:      FILE_BUF *buf;
                   2431: {
1.1.1.7   root     2432:   register U_CHAR c, *fptr, *bptr, *sptr, *lptr;
1.1       root     2433:   int len;
                   2434: 
                   2435:   fptr = bptr = sptr = buf->buf;
1.1.1.7   root     2436:   lptr = fptr + buf->length;
1.1.1.8 ! root     2437:   while ((sptr = index0 (sptr, '?', (size_t) (lptr - sptr))) != NULL) {
1.1       root     2438:     if (*++sptr != '?')
                   2439:       continue;
                   2440:     switch (*++sptr) {
                   2441:       case '=':
                   2442:       c = '#';
                   2443:       break;
                   2444:     case '(':
                   2445:       c = '[';
                   2446:       break;
                   2447:     case '/':
                   2448:       c = '\\';
                   2449:       break;
                   2450:     case ')':
                   2451:       c = ']';
                   2452:       break;
                   2453:     case '\'':
                   2454:       c = '^';
                   2455:       break;
                   2456:     case '<':
                   2457:       c = '{';
                   2458:       break;
                   2459:     case '!':
                   2460:       c = '|';
                   2461:       break;
                   2462:     case '>':
                   2463:       c = '}';
                   2464:       break;
                   2465:     case '-':
                   2466:       c  = '~';
                   2467:       break;
                   2468:     case '?':
                   2469:       sptr--;
                   2470:       continue;
                   2471:     default:
                   2472:       continue;
                   2473:     }
                   2474:     len = sptr - fptr - 2;
1.1.1.7   root     2475: 
                   2476:     /* BSD doc says bcopy () works right for overlapping strings.  In ANSI
                   2477:        C, this will be memmove (). */
1.1       root     2478:     if (bptr != fptr && len > 0)
1.1.1.7   root     2479:       bcopy ((char *) fptr, (char *) bptr, len);
                   2480: 
1.1       root     2481:     bptr += len;
                   2482:     *bptr++ = c;
                   2483:     fptr = ++sptr;
                   2484:   }
                   2485:   len = buf->length - (fptr - buf->buf);
                   2486:   if (bptr != fptr && len > 0)
1.1.1.7   root     2487:     bcopy ((char *) fptr, (char *) bptr, len);
1.1       root     2488:   buf->length -= fptr - bptr;
                   2489:   buf->buf[buf->length] = '\0';
                   2490:   if (warn_trigraphs && fptr != bptr)
1.1.1.8 ! root     2491:     warning_with_line (0, "%d trigraph(s) encountered", (fptr - bptr) / 2);
1.1       root     2492: }
                   2493: 
                   2494: /* Move all backslash-newline pairs out of embarrassing places.
                   2495:    Exchange all such pairs following BP
1.1.1.2   root     2496:    with any potentially-embarrassing characters that follow them.
1.1       root     2497:    Potentially-embarrassing characters are / and *
                   2498:    (because a backslash-newline inside a comment delimiter
                   2499:    would cause it not to be recognized).  */
                   2500: 
                   2501: static void
                   2502: newline_fix (bp)
                   2503:      U_CHAR *bp;
                   2504: {
                   2505:   register U_CHAR *p = bp;
                   2506: 
                   2507:   /* First count the backslash-newline pairs here.  */
                   2508: 
1.1.1.7   root     2509:   while (p[0] == '\\' && p[1] == '\n')
                   2510:     p += 2;
1.1       root     2511: 
                   2512:   /* What follows the backslash-newlines is not embarrassing.  */
                   2513: 
1.1.1.7   root     2514:   if (*p != '/' && *p != '*')
1.1       root     2515:     return;
                   2516: 
                   2517:   /* Copy all potentially embarrassing characters
                   2518:      that follow the backslash-newline pairs
                   2519:      down to where the pairs originally started.  */
                   2520: 
                   2521:   while (*p == '*' || *p == '/')
                   2522:     *bp++ = *p++;
                   2523: 
                   2524:   /* Now write the same number of pairs after the embarrassing chars.  */
1.1.1.7   root     2525:   while (bp < p) {
1.1       root     2526:     *bp++ = '\\';
                   2527:     *bp++ = '\n';
                   2528:   }
                   2529: }
                   2530: 
                   2531: /* Like newline_fix but for use within a directive-name.
                   2532:    Move any backslash-newlines up past any following symbol constituents.  */
                   2533: 
                   2534: static void
                   2535: name_newline_fix (bp)
                   2536:      U_CHAR *bp;
                   2537: {
                   2538:   register U_CHAR *p = bp;
                   2539: 
                   2540:   /* First count the backslash-newline pairs here.  */
1.1.1.7   root     2541:   while (p[0] == '\\' && p[1] == '\n')
                   2542:     p += 2;
1.1       root     2543: 
                   2544:   /* What follows the backslash-newlines is not embarrassing.  */
                   2545: 
1.1.1.7   root     2546:   if (!is_idchar[*p])
1.1       root     2547:     return;
                   2548: 
                   2549:   /* Copy all potentially embarrassing characters
                   2550:      that follow the backslash-newline pairs
                   2551:      down to where the pairs originally started.  */
                   2552: 
                   2553:   while (is_idchar[*p])
                   2554:     *bp++ = *p++;
                   2555: 
                   2556:   /* Now write the same number of pairs after the embarrassing chars.  */
1.1.1.7   root     2557:   while (bp < p) {
1.1       root     2558:     *bp++ = '\\';
                   2559:     *bp++ = '\n';
                   2560:   }
                   2561: }
                   2562: 
                   2563: /* Look for lint commands in comments.
                   2564: 
                   2565:    When we come in here, ibp points into a comment.  Limit is as one expects.
                   2566:    scan within the comment -- it should start, after lwsp, with a lint command.
                   2567:    If so that command is returned as a (constant) string.
                   2568: 
                   2569:    Upon return, any arg will be pointed to with argstart and will be
                   2570:    arglen long.  Note that we don't parse that arg since it will just
                   2571:    be printed out again.
                   2572: */
                   2573: 
                   2574: static char *
                   2575: get_lintcmd (ibp, limit, argstart, arglen, cmdlen)
                   2576:      register U_CHAR *ibp;
                   2577:      register U_CHAR *limit;
                   2578:      U_CHAR **argstart;                /* point to command arg */
                   2579:      int *arglen, *cmdlen;     /* how long they are */
                   2580: {
                   2581:   long linsize;
                   2582:   register U_CHAR *numptr;     /* temp for arg parsing */
                   2583: 
                   2584:   *arglen = 0;
                   2585: 
                   2586:   SKIP_WHITE_SPACE (ibp);
                   2587: 
                   2588:   if (ibp >= limit) return NULL;
                   2589: 
                   2590:   linsize = limit - ibp;
                   2591:   
                   2592:   /* Oh, I wish C had lexical functions... hell, I'll just open-code the set */
1.1.1.8 ! root     2593:   if ((linsize >= 10) && !bcmp (ibp, "NOTREACHED", 10)) {
1.1       root     2594:     *cmdlen = 10;
                   2595:     return "NOTREACHED";
                   2596:   }
1.1.1.8 ! root     2597:   if ((linsize >= 8) && !bcmp (ibp, "ARGSUSED", 8)) {
1.1       root     2598:     *cmdlen = 8;
                   2599:     return "ARGSUSED";
                   2600:   }
1.1.1.8 ! root     2601:   if ((linsize >= 11) && !bcmp (ibp, "LINTLIBRARY", 11)) {
1.1.1.4   root     2602:     *cmdlen = 11;
1.1       root     2603:     return "LINTLIBRARY";
                   2604:   }
1.1.1.8 ! root     2605:   if ((linsize >= 7) && !bcmp (ibp, "VARARGS", 7)) {
1.1       root     2606:     *cmdlen = 7;
                   2607:     ibp += 7; linsize -= 7;
                   2608:     if ((linsize == 0) || ! isdigit (*ibp)) return "VARARGS";
                   2609: 
                   2610:     /* OK, read a number */
                   2611:     for (numptr = *argstart = ibp; (numptr < limit) && isdigit (*numptr);
                   2612:         numptr++);
                   2613:     *arglen = numptr - *argstart;
                   2614:     return "VARARGS";
                   2615:   }
                   2616:   return NULL;
                   2617: }
                   2618: 
                   2619: /*
                   2620:  * The main loop of the program.
                   2621:  *
                   2622:  * Read characters from the input stack, transferring them to the
                   2623:  * output buffer OP.
                   2624:  *
                   2625:  * Macros are expanded and push levels on the input stack.
                   2626:  * At the end of such a level it is popped off and we keep reading.
                   2627:  * At the end of any other kind of level, we return.
                   2628:  * #-directives are handled, except within macros.
                   2629:  *
                   2630:  * If OUTPUT_MARKS is nonzero, keep Newline markers found in the input
                   2631:  * and insert them when appropriate.  This is set while scanning macro
                   2632:  * arguments before substitution.  It is zero when scanning for final output.
                   2633:  *   There are three types of Newline markers:
                   2634:  *   * Newline -  follows a macro name that was not expanded
                   2635:  *     because it appeared inside an expansion of the same macro.
                   2636:  *     This marker prevents future expansion of that identifier.
                   2637:  *     When the input is rescanned into the final output, these are deleted.
                   2638:  *     These are also deleted by ## concatenation.
                   2639:  *   * Newline Space (or Newline and any other whitespace character)
                   2640:  *     stands for a place that tokens must be separated or whitespace
                   2641:  *     is otherwise desirable, but where the ANSI standard specifies there
                   2642:  *     is no whitespace.  This marker turns into a Space (or whichever other
                   2643:  *     whitespace char appears in the marker) in the final output,
                   2644:  *     but it turns into nothing in an argument that is stringified with #.
                   2645:  *     Such stringified arguments are the only place where the ANSI standard
                   2646:  *     specifies with precision that whitespace may not appear.
                   2647:  *
                   2648:  * During this function, IP->bufp is kept cached in IBP for speed of access.
                   2649:  * Likewise, OP->bufp is kept in OBP.  Before calling a subroutine
                   2650:  * IBP, IP and OBP must be copied back to memory.  IP and IBP are
                   2651:  * copied back with the RECACHE macro.  OBP must be copied back from OP->bufp
                   2652:  * explicitly, and before RECACHE, since RECACHE uses OBP.
                   2653:  */
                   2654: 
                   2655: static void
                   2656: rescan (op, output_marks)
                   2657:      FILE_BUF *op;
                   2658:      int output_marks;
                   2659: {
                   2660:   /* Character being scanned in main loop.  */
                   2661:   register U_CHAR c;
                   2662: 
                   2663:   /* Length of pending accumulated identifier.  */
                   2664:   register int ident_length = 0;
                   2665: 
                   2666:   /* Hash code of pending accumulated identifier.  */
                   2667:   register int hash = 0;
                   2668: 
                   2669:   /* Current input level (&instack[indepth]).  */
                   2670:   FILE_BUF *ip;
                   2671: 
                   2672:   /* Pointer for scanning input.  */
                   2673:   register U_CHAR *ibp;
                   2674: 
                   2675:   /* Pointer to end of input.  End of scan is controlled by LIMIT.  */
                   2676:   register U_CHAR *limit;
                   2677: 
                   2678:   /* Pointer for storing output.  */
                   2679:   register U_CHAR *obp;
                   2680: 
                   2681:   /* REDO_CHAR is nonzero if we are processing an identifier
                   2682:      after backing up over the terminating character.
                   2683:      Sometimes we process an identifier without backing up over
                   2684:      the terminating character, if the terminating character
                   2685:      is not special.  Backing up is done so that the terminating character
                   2686:      will be dispatched on again once the identifier is dealt with.  */
                   2687:   int redo_char = 0;
                   2688: 
                   2689:   /* 1 if within an identifier inside of which a concatenation
                   2690:      marker (Newline -) has been seen.  */
                   2691:   int concatenated = 0;
                   2692: 
                   2693:   /* While scanning a comment or a string constant,
                   2694:      this records the line it started on, for error messages.  */
                   2695:   int start_line;
                   2696: 
                   2697:   /* Record position of last `real' newline.  */
                   2698:   U_CHAR *beg_of_line;
                   2699: 
                   2700: /* Pop the innermost input stack level, assuming it is a macro expansion.  */
                   2701: 
                   2702: #define POPMACRO \
                   2703: do { ip->macro->type = T_MACRO;                \
                   2704:      if (ip->free_ptr) free (ip->free_ptr);    \
                   2705:      --indepth; } while (0)
                   2706: 
                   2707: /* Reload `rescan's local variables that describe the current
                   2708:    level of the input stack.  */
                   2709: 
                   2710: #define RECACHE  \
                   2711: do { ip = &instack[indepth];           \
                   2712:      ibp = ip->bufp;                   \
                   2713:      limit = ip->buf + ip->length;     \
                   2714:      op->bufp = obp;                   \
                   2715:      check_expand (op, limit - ibp);   \
                   2716:      beg_of_line = 0;                  \
                   2717:      obp = op->bufp; } while (0)
                   2718: 
                   2719:   if (no_output && instack[indepth].fname != 0)
1.1.1.7   root     2720:     skip_if_group (&instack[indepth], 1, NULL);
1.1       root     2721: 
                   2722:   obp = op->bufp;
                   2723:   RECACHE;
1.1.1.4   root     2724: 
1.1       root     2725:   beg_of_line = ibp;
                   2726: 
                   2727:   /* Our caller must always put a null after the end of
                   2728:      the input at each input stack level.  */
                   2729:   if (*limit != 0)
                   2730:     abort ();
                   2731: 
                   2732:   while (1) {
                   2733:     c = *ibp++;
                   2734:     *obp++ = c;
                   2735: 
                   2736:     switch (c) {
                   2737:     case '\\':
1.1.1.7   root     2738:       if (*ibp == '\n' && !ip->macro) {
                   2739:        /* At the top level, always merge lines ending with backslash-newline,
                   2740:           even in middle of identifier.  But do not merge lines in a macro,
                   2741:           since backslash might be followed by a newline-space marker.  */
1.1       root     2742:        ++ibp;
                   2743:        ++ip->lineno;
                   2744:        --obp;          /* remove backslash from obuf */
                   2745:        break;
                   2746:       }
1.1.1.7   root     2747:       /* If ANSI, backslash is just another character outside a string.  */
                   2748:       if (!traditional)
                   2749:        goto randomchar;
1.1       root     2750:       /* Otherwise, backslash suppresses specialness of following char,
                   2751:         so copy it here to prevent the switch from seeing it.
                   2752:         But first get any pending identifier processed.  */
                   2753:       if (ident_length > 0)
                   2754:        goto specialchar;
1.1.1.7   root     2755:       if (ibp < limit)
                   2756:        *obp++ = *ibp++;
1.1       root     2757:       break;
                   2758: 
1.1.1.8 ! root     2759:     case '%':
        !          2760:       if (ident_length || ip->macro || traditional)
        !          2761:        goto randomchar;
        !          2762:       while (*ibp == '\\' && ibp[1] == '\n') {
        !          2763:        ibp += 2;
        !          2764:        ++ip->lineno;
        !          2765:       }
        !          2766:       if (*ibp != ':')
        !          2767:        break;
        !          2768:       /* Treat this %: digraph as if it were #.  */
        !          2769:       /* Fall through.  */
        !          2770: 
1.1       root     2771:     case '#':
                   2772:       if (assertions_flag) {
1.1.1.8 ! root     2773:        if (ident_length)
        !          2774:          goto specialchar;
1.1       root     2775:        /* Copy #foo (bar lose) without macro expansion.  */
1.1.1.8 ! root     2776:        obp[-1] = '#';  /* In case it was '%'. */
1.1       root     2777:        SKIP_WHITE_SPACE (ibp);
                   2778:        while (is_idchar[*ibp])
                   2779:          *obp++ = *ibp++;
                   2780:        SKIP_WHITE_SPACE (ibp);
                   2781:        if (*ibp == '(') {
                   2782:          ip->bufp = ibp;
                   2783:          skip_paren_group (ip);
1.1.1.7   root     2784:          bcopy ((char *) ibp, (char *) obp, ip->bufp - ibp);
1.1       root     2785:          obp += ip->bufp - ibp;
                   2786:          ibp = ip->bufp;
                   2787:        }
1.1.1.8 ! root     2788:        break;
1.1       root     2789:       }
                   2790: 
                   2791:       /* If this is expanding a macro definition, don't recognize
1.1.1.8 ! root     2792:         preprocessing directives.  */
1.1       root     2793:       if (ip->macro != 0)
                   2794:        goto randomchar;
1.1.1.8 ! root     2795:       /* If this is expand_into_temp_buffer,
        !          2796:         don't recognize them either.  Warn about them
1.1.1.4   root     2797:         only after an actual newline at this level,
                   2798:         not at the beginning of the input level.  */
1.1.1.8 ! root     2799:       if (! ip->fname) {
        !          2800:        if (ip->buf != beg_of_line)
        !          2801:          warning ("preprocessing directive not recognized within macro arg");
1.1.1.4   root     2802:        goto randomchar;
1.1.1.8 ! root     2803:       }
1.1       root     2804:       if (ident_length)
                   2805:        goto specialchar;
                   2806: 
1.1.1.4   root     2807:       
1.1       root     2808:       /* # keyword: a # must be first nonblank char on the line */
                   2809:       if (beg_of_line == 0)
                   2810:        goto randomchar;
                   2811:       {
                   2812:        U_CHAR *bp;
                   2813: 
                   2814:        /* Scan from start of line, skipping whitespace, comments
                   2815:           and backslash-newlines, and see if we reach this #.
                   2816:           If not, this # is not special.  */
                   2817:        bp = beg_of_line;
1.1.1.4   root     2818:        /* If -traditional, require # to be at beginning of line.  */
1.1.1.8 ! root     2819:        if (!traditional) {
1.1.1.4   root     2820:          while (1) {
                   2821:            if (is_hor_space[*bp])
1.1       root     2822:              bp++;
1.1.1.4   root     2823:            else if (*bp == '\\' && bp[1] == '\n')
                   2824:              bp += 2;
                   2825:            else if (*bp == '/' && bp[1] == '*') {
                   2826:              bp += 2;
                   2827:              while (!(*bp == '*' && bp[1] == '/'))
                   2828:                bp++;
                   2829:              bp += 2;
                   2830:            }
1.1.1.7   root     2831:            /* There is no point in trying to deal with C++ // comments here,
                   2832:               because if there is one, then this # must be part of the
                   2833:               comment and we would never reach here.  */
1.1.1.4   root     2834:            else break;
1.1       root     2835:          }
1.1.1.8 ! root     2836:          if (c == '%') {
        !          2837:            if (bp[0] != '%')
        !          2838:              break;
        !          2839:            while (bp[1] == '\\' && bp[2] == '\n')
        !          2840:              bp += 2;
        !          2841:            if (bp + 1 != ibp)
        !          2842:              break;
        !          2843:            /* %: appears at start of line; skip past the ':' too.  */
        !          2844:            bp++;
        !          2845:            ibp++;
        !          2846:          }
        !          2847:        }
1.1       root     2848:        if (bp + 1 != ibp)
                   2849:          goto randomchar;
                   2850:       }
                   2851: 
                   2852:       /* This # can start a directive.  */
                   2853: 
                   2854:       --obp;           /* Don't copy the '#' */
                   2855: 
                   2856:       ip->bufp = ibp;
                   2857:       op->bufp = obp;
                   2858:       if (! handle_directive (ip, op)) {
                   2859: #ifdef USE_C_ALLOCA
                   2860:        alloca (0);
                   2861: #endif
                   2862:        /* Not a known directive: treat it as ordinary text.
                   2863:           IP, OP, IBP, etc. have not been changed.  */
                   2864:        if (no_output && instack[indepth].fname) {
                   2865:          /* If not generating expanded output,
                   2866:             what we do with ordinary text is skip it.
                   2867:             Discard everything until next # directive.  */
1.1.1.7   root     2868:          skip_if_group (&instack[indepth], 1, 0);
1.1       root     2869:          RECACHE;
                   2870:          beg_of_line = ibp;
                   2871:          break;
                   2872:        }
1.1.1.8 ! root     2873:        *obp++ = '#';   /* Copy # (even if it was originally %:).  */
1.1.1.6   root     2874:        /* Don't expand an identifier that could be a macro directive.
                   2875:           (Section 3.8.3 of the ANSI C standard)                       */
                   2876:        SKIP_WHITE_SPACE (ibp);
                   2877:        if (is_idstart[*ibp])
                   2878:          {
                   2879:            *obp++ = *ibp++;
                   2880:            while (is_idchar[*ibp])
                   2881:              *obp++ = *ibp++;
                   2882:          }
1.1       root     2883:        goto randomchar;
                   2884:       }
                   2885: #ifdef USE_C_ALLOCA
                   2886:       alloca (0);
                   2887: #endif
                   2888:       /* A # directive has been successfully processed.  */
                   2889:       /* If not generating expanded output, ignore everything until
                   2890:         next # directive.  */
                   2891:       if (no_output && instack[indepth].fname)
1.1.1.7   root     2892:        skip_if_group (&instack[indepth], 1, 0);
1.1       root     2893:       obp = op->bufp;
                   2894:       RECACHE;
                   2895:       beg_of_line = ibp;
                   2896:       break;
                   2897: 
                   2898:     case '\"':                 /* skip quoted string */
                   2899:     case '\'':
                   2900:       /* A single quoted string is treated like a double -- some
                   2901:         programs (e.g., troff) are perverse this way */
                   2902: 
                   2903:       if (ident_length)
                   2904:        goto specialchar;
                   2905: 
                   2906:       start_line = ip->lineno;
                   2907: 
                   2908:       /* Skip ahead to a matching quote.  */
                   2909: 
                   2910:       while (1) {
                   2911:        if (ibp >= limit) {
1.1.1.4   root     2912:          if (ip->macro != 0) {
                   2913:            /* try harder: this string crosses a macro expansion boundary.
                   2914:               This can happen naturally if -traditional.
                   2915:               Otherwise, only -D can make a macro with an unmatched quote.  */
                   2916:            POPMACRO;
                   2917:            RECACHE;
                   2918:            continue;
                   2919:          }
                   2920:          if (!traditional) {
1.1       root     2921:            error_with_line (line_for_error (start_line),
                   2922:                             "unterminated string or character constant");
                   2923:            error_with_line (multiline_string_line,
                   2924:                             "possible real start of unterminated constant");
                   2925:            multiline_string_line = 0;
                   2926:          }
                   2927:          break;
                   2928:        }
                   2929:        *obp++ = *ibp;
                   2930:        switch (*ibp++) {
                   2931:        case '\n':
                   2932:          ++ip->lineno;
                   2933:          ++op->lineno;
                   2934:          /* Traditionally, end of line ends a string constant with no error.
                   2935:             So exit the loop and record the new line.  */
                   2936:          if (traditional) {
                   2937:            beg_of_line = ibp;
                   2938:            goto while2end;
                   2939:          }
1.1.1.5   root     2940:          if (c == '\'') {
1.1       root     2941:            error_with_line (line_for_error (start_line),
1.1.1.5   root     2942:                             "unterminated character constant");
1.1       root     2943:            goto while2end;
                   2944:          }
1.1.1.5   root     2945:          if (pedantic && multiline_string_line == 0) {
                   2946:            pedwarn_with_line (line_for_error (start_line),
                   2947:                               "string constant runs past end of line");
                   2948:          }
1.1       root     2949:          if (multiline_string_line == 0)
                   2950:            multiline_string_line = ip->lineno - 1;
                   2951:          break;
                   2952: 
                   2953:        case '\\':
                   2954:          if (ibp >= limit)
                   2955:            break;
                   2956:          if (*ibp == '\n') {
                   2957:            /* Backslash newline is replaced by nothing at all,
                   2958:               but keep the line counts correct.  */
                   2959:            --obp;
                   2960:            ++ibp;
                   2961:            ++ip->lineno;
                   2962:          } else {
                   2963:            /* ANSI stupidly requires that in \\ the second \
                   2964:               is *not* prevented from combining with a newline.  */
                   2965:            while (*ibp == '\\' && ibp[1] == '\n') {
                   2966:              ibp += 2;
                   2967:              ++ip->lineno;
                   2968:            }
                   2969:            *obp++ = *ibp++;
                   2970:          }
                   2971:          break;
                   2972: 
                   2973:        case '\"':
                   2974:        case '\'':
                   2975:          if (ibp[-1] == c)
                   2976:            goto while2end;
                   2977:          break;
                   2978:        }
                   2979:       }
                   2980:     while2end:
                   2981:       break;
                   2982: 
                   2983:     case '/':
                   2984:       if (*ibp == '\\' && ibp[1] == '\n')
                   2985:        newline_fix (ibp);
                   2986: 
                   2987:       if (*ibp != '*'
1.1.1.4   root     2988:          && !(cplusplus_comments && *ibp == '/'))
1.1       root     2989:        goto randomchar;
                   2990:       if (ip->macro != 0)
                   2991:        goto randomchar;
                   2992:       if (ident_length)
                   2993:        goto specialchar;
                   2994: 
                   2995:       if (*ibp == '/') {
                   2996:        /* C++ style comment... */
                   2997:        start_line = ip->lineno;
                   2998: 
                   2999:        /* Comments are equivalent to spaces. */
                   3000:        if (! put_out_comments)
1.1.1.8 ! root     3001:          obp[-1] = ' ';
        !          3002: 
1.1       root     3003:        {
1.1.1.8 ! root     3004:          U_CHAR *before_bp = ibp;
1.1       root     3005: 
1.1.1.8 ! root     3006:          while (++ibp < limit) {
        !          3007:            if (*ibp == '\n') {
        !          3008:              if (ibp[-1] != '\\') {
        !          3009:                if (put_out_comments) {
        !          3010:                  bcopy ((char *) before_bp, (char *) obp, ibp - before_bp);
        !          3011:                  obp += ibp - before_bp;
        !          3012:                }
        !          3013:                break;
1.1.1.7   root     3014:              }
1.1.1.8 ! root     3015:              ++ip->lineno;
        !          3016:              /* Copy the newline into the output buffer, in order to
        !          3017:                 avoid the pain of a #line every time a multiline comment
        !          3018:                 is seen.  */
        !          3019:              if (!put_out_comments)
        !          3020:                *obp++ = '\n';
        !          3021:              ++op->lineno;
1.1       root     3022:            }
                   3023:          }
                   3024:          break;
                   3025:        }
                   3026:       }
                   3027: 
                   3028:       /* Ordinary C comment.  Skip it, optionally copying it to output.  */
                   3029: 
                   3030:       start_line = ip->lineno;
                   3031: 
                   3032:       ++ibp;                   /* Skip the star. */
                   3033: 
                   3034:       /* If this cpp is for lint, we peek inside the comments: */
1.1.1.7   root     3035:       if (for_lint) {
1.1       root     3036:        U_CHAR *argbp;
                   3037:        int cmdlen, arglen;
                   3038:        char *lintcmd = get_lintcmd (ibp, limit, &argbp, &arglen, &cmdlen);
                   3039: 
                   3040:        if (lintcmd != NULL) {
1.1.1.7   root     3041:          op->bufp = obp;
                   3042:          check_expand (op, cmdlen + arglen + 14);
                   3043:          obp = op->bufp;
1.1       root     3044:          /* I believe it is always safe to emit this newline: */
                   3045:          obp[-1] = '\n';
1.1.1.7   root     3046:          bcopy ("#pragma lint ", (char *) obp, 13);
1.1       root     3047:          obp += 13;
1.1.1.7   root     3048:          bcopy (lintcmd, (char *) obp, cmdlen);
1.1       root     3049:          obp += cmdlen;
                   3050: 
                   3051:          if (arglen != 0) {
                   3052:            *(obp++) = ' ';
1.1.1.7   root     3053:            bcopy (argbp, (char *) obp, arglen);
1.1       root     3054:            obp += arglen;
                   3055:          }
                   3056: 
                   3057:          /* OK, now bring us back to the state we were in before we entered
1.1.1.7   root     3058:             this branch.  We need #line because the #pragma's newline always
                   3059:             messes up the line count.  */
                   3060:          op->bufp = obp;
1.1.1.8 ! root     3061:          output_line_directive (ip, op, 0, same_file);
1.1.1.7   root     3062:          check_expand (op, limit - ibp + 2);
                   3063:          obp = op->bufp;
1.1       root     3064:          *(obp++) = '/';
                   3065:        }
                   3066:       }
                   3067: 
                   3068:       /* Comments are equivalent to spaces.
                   3069:         Note that we already output the slash; we might not want it.
                   3070:         For -traditional, a comment is equivalent to nothing.  */
                   3071:       if (! put_out_comments) {
                   3072:        if (traditional)
                   3073:          obp--;
                   3074:        else
                   3075:          obp[-1] = ' ';
                   3076:       }
                   3077:       else
                   3078:        *obp++ = '*';
                   3079: 
                   3080:       {
                   3081:        U_CHAR *before_bp = ibp;
                   3082: 
                   3083:        while (ibp < limit) {
                   3084:          switch (*ibp++) {
                   3085:          case '/':
1.1.1.8 ! root     3086:            if (warn_comments && *ibp == '*')
1.1.1.5   root     3087:              warning ("`/*' within comment");
1.1       root     3088:            break;
                   3089:          case '*':
                   3090:            if (*ibp == '\\' && ibp[1] == '\n')
                   3091:              newline_fix (ibp);
                   3092:            if (ibp >= limit || *ibp == '/')
                   3093:              goto comment_end;
                   3094:            break;
                   3095:          case '\n':
                   3096:            ++ip->lineno;
                   3097:            /* Copy the newline into the output buffer, in order to
                   3098:               avoid the pain of a #line every time a multiline comment
                   3099:               is seen.  */
                   3100:            if (!put_out_comments)
                   3101:              *obp++ = '\n';
                   3102:            ++op->lineno;
                   3103:          }
                   3104:        }
                   3105:       comment_end:
                   3106: 
                   3107:        if (ibp >= limit)
                   3108:          error_with_line (line_for_error (start_line),
                   3109:                           "unterminated comment");
                   3110:        else {
                   3111:          ibp++;
                   3112:          if (put_out_comments) {
1.1.1.7   root     3113:            bcopy ((char *) before_bp, (char *) obp, ibp - before_bp);
1.1       root     3114:            obp += ibp - before_bp;
                   3115:          }
                   3116:        }
                   3117:       }
                   3118:       break;
                   3119: 
                   3120:     case '$':
                   3121:       if (!dollars_in_ident)
                   3122:        goto randomchar;
                   3123:       goto letter;
                   3124: 
                   3125:     case '0': case '1': case '2': case '3': case '4':
                   3126:     case '5': case '6': case '7': case '8': case '9':
                   3127:       /* If digit is not part of identifier, it starts a number,
                   3128:         which means that following letters are not an identifier.
                   3129:         "0x5" does not refer to an identifier "x5".
                   3130:         So copy all alphanumerics that follow without accumulating
                   3131:         as an identifier.  Periods also, for sake of "3.e7".  */
                   3132: 
                   3133:       if (ident_length == 0) {
1.1.1.8 ! root     3134:        for (;;) {
        !          3135:          while (ibp[0] == '\\' && ibp[1] == '\n') {
1.1       root     3136:            ++ip->lineno;
                   3137:            ibp += 2;
                   3138:          }
                   3139:          c = *ibp++;
1.1.1.7   root     3140:          if (!is_idchar[c] && c != '.') {
1.1       root     3141:            --ibp;
                   3142:            break;
                   3143:          }
                   3144:          *obp++ = c;
                   3145:          /* A sign can be part of a preprocessing number
                   3146:             if it follows an e.  */
                   3147:          if (c == 'e' || c == 'E') {
1.1.1.8 ! root     3148:            while (ibp[0] == '\\' && ibp[1] == '\n') {
1.1       root     3149:              ++ip->lineno;
                   3150:              ibp += 2;
                   3151:            }
1.1.1.8 ! root     3152:            if (*ibp == '+' || *ibp == '-') {
1.1       root     3153:              *obp++ = *ibp++;
                   3154:              /* But traditional C does not let the token go past the sign.  */
                   3155:              if (traditional)
                   3156:                break;
                   3157:            }
                   3158:          }
                   3159:        }
                   3160:        break;
                   3161:       }
                   3162:       /* fall through */
                   3163: 
                   3164:     case '_':
                   3165:     case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
                   3166:     case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
                   3167:     case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
                   3168:     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
                   3169:     case 'y': case 'z':
                   3170:     case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
                   3171:     case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
                   3172:     case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
                   3173:     case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
                   3174:     case 'Y': case 'Z':
                   3175:     letter:
                   3176:       ident_length++;
                   3177:       /* Compute step of hash function, to avoid a proc call on every token */
                   3178:       hash = HASHSTEP (hash, c);
                   3179:       break;
                   3180: 
                   3181:     case '\n':
1.1.1.5   root     3182:       if (ip->fname == 0 && *ibp == '-') {
                   3183:        /* Newline - inhibits expansion of preceding token.
                   3184:           If expanding a macro arg, we keep the newline -.
                   3185:           In final output, it is deleted.
                   3186:           We recognize Newline - in macro bodies and macro args.  */
                   3187:        if (! concatenated) {
                   3188:          ident_length = 0;
                   3189:          hash = 0;
                   3190:        }
                   3191:        ibp++;
                   3192:        if (!output_marks) {
                   3193:          obp--;
                   3194:        } else {
                   3195:          /* If expanding a macro arg, keep the newline -.  */
                   3196:          *obp++ = '-';
                   3197:        }
                   3198:        break;
                   3199:       }
                   3200: 
1.1       root     3201:       /* If reprocessing a macro expansion, newline is a special marker.  */
1.1.1.5   root     3202:       else if (ip->macro != 0) {
1.1       root     3203:        /* Newline White is a "funny space" to separate tokens that are
                   3204:           supposed to be separate but without space between.
                   3205:           Here White means any whitespace character.
                   3206:           Newline - marks a recursive macro use that is not
                   3207:           supposed to be expandable.  */
                   3208: 
1.1.1.5   root     3209:        if (is_space[*ibp]) {
1.1       root     3210:          /* Newline Space does not prevent expansion of preceding token
                   3211:             so expand the preceding token and then come back.  */
                   3212:          if (ident_length > 0)
                   3213:            goto specialchar;
                   3214: 
                   3215:          /* If generating final output, newline space makes a space.  */
                   3216:          if (!output_marks) {
                   3217:            obp[-1] = *ibp++;
                   3218:            /* And Newline Newline makes a newline, so count it.  */
                   3219:            if (obp[-1] == '\n')
                   3220:              op->lineno++;
                   3221:          } else {
                   3222:            /* If expanding a macro arg, keep the newline space.
                   3223:               If the arg gets stringified, newline space makes nothing.  */
                   3224:            *obp++ = *ibp++;
                   3225:          }
                   3226:        } else abort ();        /* Newline followed by something random?  */
                   3227:        break;
                   3228:       }
                   3229: 
                   3230:       /* If there is a pending identifier, handle it and come back here.  */
                   3231:       if (ident_length > 0)
                   3232:        goto specialchar;
                   3233: 
                   3234:       beg_of_line = ibp;
                   3235: 
                   3236:       /* Update the line counts and output a #line if necessary.  */
                   3237:       ++ip->lineno;
                   3238:       ++op->lineno;
                   3239:       if (ip->lineno != op->lineno) {
                   3240:        op->bufp = obp;
1.1.1.8 ! root     3241:        output_line_directive (ip, op, 1, same_file);
1.1.1.7   root     3242:        check_expand (op, limit - ibp);
1.1       root     3243:        obp = op->bufp;
                   3244:       }
                   3245:       break;
                   3246: 
                   3247:       /* Come here either after (1) a null character that is part of the input
                   3248:         or (2) at the end of the input, because there is a null there.  */
                   3249:     case 0:
                   3250:       if (ibp <= limit)
                   3251:        /* Our input really contains a null character.  */
                   3252:        goto randomchar;
                   3253: 
                   3254:       /* At end of a macro-expansion level, pop it and read next level.  */
                   3255:       if (ip->macro != 0) {
                   3256:        obp--;
                   3257:        ibp--;
                   3258:        /* If traditional, and we have an identifier that ends here,
                   3259:           process it now, so we get the right error for recursion.  */
                   3260:        if (traditional && ident_length
                   3261:            && ! is_idchar[*instack[indepth - 1].bufp]) {
                   3262:          redo_char = 1;
                   3263:          goto randomchar;
                   3264:        }
                   3265:        POPMACRO;
                   3266:        RECACHE;
                   3267:        break;
                   3268:       }
                   3269: 
                   3270:       /* If we don't have a pending identifier,
                   3271:         return at end of input.  */
                   3272:       if (ident_length == 0) {
                   3273:        obp--;
                   3274:        ibp--;
                   3275:        op->bufp = obp;
                   3276:        ip->bufp = ibp;
                   3277:        goto ending;
                   3278:       }
                   3279: 
                   3280:       /* If we do have a pending identifier, just consider this null
                   3281:         a special character and arrange to dispatch on it again.
                   3282:         The second time, IDENT_LENGTH will be zero so we will return.  */
                   3283: 
                   3284:       /* Fall through */
                   3285: 
                   3286: specialchar:
                   3287: 
                   3288:       /* Handle the case of a character such as /, ', " or null
                   3289:         seen following an identifier.  Back over it so that
                   3290:         after the identifier is processed the special char
                   3291:         will be dispatched on again.  */
                   3292: 
                   3293:       ibp--;
                   3294:       obp--;
                   3295:       redo_char = 1;
                   3296: 
                   3297:     default:
                   3298: 
                   3299: randomchar:
                   3300: 
                   3301:       if (ident_length > 0) {
                   3302:        register HASHNODE *hp;
                   3303: 
                   3304:        /* We have just seen an identifier end.  If it's a macro, expand it.
                   3305: 
                   3306:           IDENT_LENGTH is the length of the identifier
                   3307:           and HASH is its hash code.
                   3308: 
                   3309:           The identifier has already been copied to the output,
                   3310:           so if it is a macro we must remove it.
                   3311: 
                   3312:           If REDO_CHAR is 0, the char that terminated the identifier
                   3313:           has been skipped in the output and the input.
                   3314:           OBP-IDENT_LENGTH-1 points to the identifier.
                   3315:           If the identifier is a macro, we must back over the terminator.
                   3316: 
                   3317:           If REDO_CHAR is 1, the terminating char has already been
                   3318:           backed over.  OBP-IDENT_LENGTH points to the identifier.  */
                   3319: 
                   3320:        if (!pcp_outfile || pcp_inside_if) {
                   3321:          for (hp = hashtab[MAKE_POS (hash) % HASHSIZE]; hp != NULL;
                   3322:               hp = hp->next) {
                   3323:            
                   3324:            if (hp->length == ident_length) {
                   3325:              int obufp_before_macroname;
                   3326:              int op_lineno_before_macroname;
                   3327:              register int i = ident_length;
                   3328:              register U_CHAR *p = hp->name;
                   3329:              register U_CHAR *q = obp - i;
                   3330:              int disabled;
                   3331:              
                   3332:              if (! redo_char)
                   3333:                q--;
                   3334:              
                   3335:              do {              /* All this to avoid a strncmp () */
                   3336:                if (*p++ != *q++)
                   3337:                  goto hashcollision;
                   3338:              } while (--i);
                   3339:              
                   3340:              /* We found a use of a macro name.
                   3341:                 see if the context shows it is a macro call.  */
                   3342:              
                   3343:              /* Back up over terminating character if not already done.  */
                   3344:              if (! redo_char) {
                   3345:                ibp--;
                   3346:                obp--;
                   3347:              }
                   3348:              
                   3349:              /* Save this as a displacement from the beginning of the output
                   3350:                 buffer.  We can not save this as a position in the output
                   3351:                 buffer, because it may get realloc'ed by RECACHE.  */
                   3352:              obufp_before_macroname = (obp - op->buf) - ident_length;
                   3353:              op_lineno_before_macroname = op->lineno;
                   3354:              
                   3355:              if (hp->type == T_PCSTRING) {
                   3356:                pcstring_used (hp); /* Mark the definition of this key
                   3357:                                       as needed, ensuring that it
                   3358:                                       will be output.  */
                   3359:                break;          /* Exit loop, since the key cannot have a
                   3360:                                   definition any longer.  */
                   3361:              }
                   3362: 
                   3363:              /* Record whether the macro is disabled.  */
                   3364:              disabled = hp->type == T_DISABLED;
                   3365:              
                   3366:              /* This looks like a macro ref, but if the macro was disabled,
                   3367:                 just copy its name and put in a marker if requested.  */
                   3368:              
                   3369:              if (disabled) {
                   3370: #if 0
                   3371:                /* This error check caught useful cases such as
1.1.1.5   root     3372:                   #define foo(x,y) bar (x (y,0), y)
                   3373:                   foo (foo, baz)  */
1.1       root     3374:                if (traditional)
                   3375:                  error ("recursive use of macro `%s'", hp->name);
                   3376: #endif
                   3377:                
                   3378:                if (output_marks) {
                   3379:                  check_expand (op, limit - ibp + 2);
                   3380:                  *obp++ = '\n';
                   3381:                  *obp++ = '-';
                   3382:                }
                   3383:                break;
                   3384:              }
                   3385:              
                   3386:              /* If macro wants an arglist, verify that a '(' follows.
                   3387:                 first skip all whitespace, copying it to the output
                   3388:                 after the macro name.  Then, if there is no '(',
                   3389:                 decide this is not a macro call and leave things that way.  */
                   3390:              if ((hp->type == T_MACRO || hp->type == T_DISABLED)
                   3391:                  && hp->value.defn->nargs >= 0)
                   3392:                {
                   3393:                  U_CHAR *old_ibp = ibp;
                   3394:                  U_CHAR *old_obp = obp;
                   3395:                  int old_iln = ip->lineno;
                   3396:                  int old_oln = op->lineno;
                   3397:                  
                   3398:                  while (1) {
                   3399:                    /* Scan forward over whitespace, copying it to the output.  */
                   3400:                    if (ibp == limit && ip->macro != 0) {
                   3401:                      POPMACRO;
                   3402:                      RECACHE;
                   3403:                      old_ibp = ibp;
                   3404:                      old_obp = obp;
                   3405:                      old_iln = ip->lineno;
                   3406:                      old_oln = op->lineno;
                   3407:                    }
                   3408:                    /* A comment: copy it unchanged or discard it.  */
1.1.1.8 ! root     3409:                    else if (*ibp == '/' && ibp[1] == '*') {
1.1       root     3410:                      if (put_out_comments) {
                   3411:                        *obp++ = '/';
                   3412:                        *obp++ = '*';
                   3413:                      } else if (! traditional) {
                   3414:                        *obp++ = ' ';
                   3415:                      }
                   3416:                      ibp += 2;
                   3417:                      while (ibp + 1 != limit
                   3418:                             && !(ibp[0] == '*' && ibp[1] == '/')) {
                   3419:                        /* We need not worry about newline-marks,
                   3420:                           since they are never found in comments.  */
                   3421:                        if (*ibp == '\n') {
                   3422:                          /* Newline in a file.  Count it.  */
                   3423:                          ++ip->lineno;
                   3424:                          ++op->lineno;
                   3425:                        }
                   3426:                        if (put_out_comments)
                   3427:                          *obp++ = *ibp++;
                   3428:                        else
                   3429:                          ibp++;
                   3430:                      }
                   3431:                      ibp += 2;
                   3432:                      if (put_out_comments) {
                   3433:                        *obp++ = '*';
                   3434:                        *obp++ = '/';
                   3435:                      }
                   3436:                    }
                   3437:                    else if (is_space[*ibp]) {
                   3438:                      *obp++ = *ibp++;
                   3439:                      if (ibp[-1] == '\n') {
                   3440:                        if (ip->macro == 0) {
                   3441:                          /* Newline in a file.  Count it.  */
                   3442:                          ++ip->lineno;
                   3443:                          ++op->lineno;
                   3444:                        } else if (!output_marks) {
                   3445:                          /* A newline mark, and we don't want marks
                   3446:                             in the output.  If it is newline-hyphen,
                   3447:                             discard it entirely.  Otherwise, it is
                   3448:                             newline-whitechar, so keep the whitechar.  */
                   3449:                          obp--;
                   3450:                          if (*ibp == '-')
                   3451:                            ibp++;
                   3452:                          else {
                   3453:                            if (*ibp == '\n')
                   3454:                              ++op->lineno;
                   3455:                            *obp++ = *ibp++;
                   3456:                          }
                   3457:                        } else {
                   3458:                          /* A newline mark; copy both chars to the output.  */
                   3459:                          *obp++ = *ibp++;
                   3460:                        }
                   3461:                      }
                   3462:                    }
                   3463:                    else break;
                   3464:                  }
                   3465:                  if (*ibp != '(') {
                   3466:                    /* It isn't a macro call.
                   3467:                       Put back the space that we just skipped.  */
                   3468:                    ibp = old_ibp;
                   3469:                    obp = old_obp;
                   3470:                    ip->lineno = old_iln;
                   3471:                    op->lineno = old_oln;
                   3472:                    /* Exit the for loop.  */
                   3473:                    break;
                   3474:                  }
                   3475:                }
                   3476:              
                   3477:              /* This is now known to be a macro call.
                   3478:                 Discard the macro name from the output,
1.1.1.7   root     3479:                 along with any following whitespace just copied,
                   3480:                 but preserve newlines if not outputting marks since this
                   3481:                 is more likely to do the right thing with line numbers.  */
1.1       root     3482:              obp = op->buf + obufp_before_macroname;
1.1.1.7   root     3483:              if (output_marks)
                   3484:                op->lineno = op_lineno_before_macroname;
                   3485:              else {
                   3486:                int newlines = op->lineno - op_lineno_before_macroname;
                   3487:                while (0 < newlines--)
                   3488:                  *obp++ = '\n';
                   3489:              }
1.1.1.5   root     3490: 
                   3491:              /* Prevent accidental token-pasting with a character
                   3492:                 before the macro call.  */
1.1.1.8 ! root     3493:              if (!traditional && obp != op->buf) {
        !          3494:                switch (obp[-1]) {
        !          3495:                case '!':  case '%':  case '&':  case '*':
        !          3496:                case '+':  case '-':  case '/':  case ':':
        !          3497:                case '<':  case '=':  case '>':  case '^':
        !          3498:                case '|':
        !          3499:                  /* If we are expanding a macro arg, make a newline marker
        !          3500:                     to separate the tokens.  If we are making real output,
        !          3501:                     a plain space will do.  */
        !          3502:                  if (output_marks)
        !          3503:                    *obp++ = '\n';
        !          3504:                  *obp++ = ' ';
        !          3505:                }
1.1.1.5   root     3506:              }
                   3507: 
1.1       root     3508:              /* Expand the macro, reading arguments as needed,
                   3509:                 and push the expansion on the input stack.  */
                   3510:              ip->bufp = ibp;
                   3511:              op->bufp = obp;
                   3512:              macroexpand (hp, op);
                   3513:              
                   3514:              /* Reexamine input stack, since macroexpand has pushed
                   3515:                 a new level on it.  */
                   3516:              obp = op->bufp;
                   3517:              RECACHE;
                   3518:              break;
                   3519:            }
                   3520: hashcollision:
                   3521:            ;
                   3522:          }                     /* End hash-table-search loop */
                   3523:        }
                   3524:        ident_length = hash = 0; /* Stop collecting identifier */
                   3525:        redo_char = 0;
                   3526:        concatenated = 0;
                   3527:       }                                /* End if (ident_length > 0) */
                   3528:     }                          /* End switch */
                   3529:   }                            /* End per-char loop */
                   3530: 
                   3531:   /* Come here to return -- but first give an error message
                   3532:      if there was an unterminated successful conditional.  */
                   3533:  ending:
1.1.1.7   root     3534:   if (if_stack != ip->if_stack)
                   3535:     {
1.1.1.8 ! root     3536:       char *str;
1.1.1.7   root     3537: 
                   3538:       switch (if_stack->type)
                   3539:        {
                   3540:        case T_IF:
                   3541:          str = "if";
                   3542:          break;
                   3543:        case T_IFDEF:
                   3544:          str = "ifdef";
                   3545:          break;
                   3546:        case T_IFNDEF:
                   3547:          str = "ifndef";
                   3548:          break;
                   3549:        case T_ELSE:
                   3550:          str = "else";
                   3551:          break;
                   3552:        case T_ELIF:
                   3553:          str = "elif";
                   3554:          break;
1.1.1.8 ! root     3555:        default:
        !          3556:          abort ();
1.1.1.7   root     3557:        }
                   3558: 
                   3559:       error_with_line (line_for_error (if_stack->lineno),
                   3560:                       "unterminated `#%s' conditional", str);
1.1       root     3561:   }
                   3562:   if_stack = ip->if_stack;
                   3563: }
                   3564: 
                   3565: /*
                   3566:  * Rescan a string into a temporary buffer and return the result
                   3567:  * as a FILE_BUF.  Note this function returns a struct, not a pointer.
                   3568:  *
                   3569:  * OUTPUT_MARKS nonzero means keep Newline markers found in the input
                   3570:  * and insert such markers when appropriate.  See `rescan' for details.
                   3571:  * OUTPUT_MARKS is 1 for macroexpanding a macro argument separately
                   3572:  * before substitution; it is 0 for other uses.
                   3573:  */
                   3574: static FILE_BUF
                   3575: expand_to_temp_buffer (buf, limit, output_marks, assertions)
                   3576:      U_CHAR *buf, *limit;
                   3577:      int output_marks, assertions;
                   3578: {
                   3579:   register FILE_BUF *ip;
                   3580:   FILE_BUF obuf;
                   3581:   int length = limit - buf;
                   3582:   U_CHAR *buf1;
                   3583:   int odepth = indepth;
                   3584:   int save_assertions_flag = assertions_flag;
                   3585: 
                   3586:   assertions_flag = assertions;
                   3587: 
                   3588:   if (length < 0)
                   3589:     abort ();
                   3590: 
                   3591:   /* Set up the input on the input stack.  */
                   3592: 
                   3593:   buf1 = (U_CHAR *) alloca (length + 1);
                   3594:   {
                   3595:     register U_CHAR *p1 = buf;
                   3596:     register U_CHAR *p2 = buf1;
                   3597: 
                   3598:     while (p1 != limit)
                   3599:       *p2++ = *p1++;
                   3600:   }
                   3601:   buf1[length] = 0;
                   3602: 
                   3603:   /* Set up to receive the output.  */
                   3604: 
                   3605:   obuf.length = length * 2 + 100; /* Usually enough.  Why be stingy?  */
                   3606:   obuf.bufp = obuf.buf = (U_CHAR *) xmalloc (obuf.length);
                   3607:   obuf.fname = 0;
                   3608:   obuf.macro = 0;
                   3609:   obuf.free_ptr = 0;
                   3610: 
                   3611:   CHECK_DEPTH ({return obuf;});
                   3612: 
                   3613:   ++indepth;
                   3614: 
                   3615:   ip = &instack[indepth];
                   3616:   ip->fname = 0;
                   3617:   ip->nominal_fname = 0;
                   3618:   ip->system_header_p = 0;
                   3619:   ip->macro = 0;
                   3620:   ip->free_ptr = 0;
                   3621:   ip->length = length;
                   3622:   ip->buf = ip->bufp = buf1;
                   3623:   ip->if_stack = if_stack;
                   3624: 
                   3625:   ip->lineno = obuf.lineno = 1;
                   3626: 
                   3627:   /* Scan the input, create the output.  */
                   3628:   rescan (&obuf, output_marks);
                   3629: 
                   3630:   /* Pop input stack to original state.  */
                   3631:   --indepth;
                   3632: 
                   3633:   if (indepth != odepth)
                   3634:     abort ();
                   3635: 
                   3636:   /* Record the output.  */
                   3637:   obuf.length = obuf.bufp - obuf.buf;
                   3638: 
                   3639:   assertions_flag = save_assertions_flag;
                   3640:   return obuf;
                   3641: }
                   3642: 
                   3643: /*
                   3644:  * Process a # directive.  Expects IP->bufp to point after the '#', as in
1.1.1.8 ! root     3645:  * `#define foo bar'.  Passes to the directive handler
1.1       root     3646:  * (do_define, do_include, etc.): the addresses of the 1st and
1.1.1.8 ! root     3647:  * last chars of the directive (starting immediately after the #
        !          3648:  * keyword), plus op and the keyword table pointer.  If the directive
1.1       root     3649:  * contains comments it is copied into a temporary buffer sans comments
1.1.1.8 ! root     3650:  * and the temporary buffer is passed to the directive handler instead.
1.1       root     3651:  * Likewise for backslash-newlines.
                   3652:  *
                   3653:  * Returns nonzero if this was a known # directive.
                   3654:  * Otherwise, returns zero, without advancing the input pointer.
                   3655:  */
                   3656: 
                   3657: static int
                   3658: handle_directive (ip, op)
                   3659:      FILE_BUF *ip, *op;
                   3660: {
                   3661:   register U_CHAR *bp, *cp;
                   3662:   register struct directive *kt;
                   3663:   register int ident_length;
                   3664:   U_CHAR *resume_p;
                   3665: 
1.1.1.8 ! root     3666:   /* Nonzero means we must copy the entire directive
1.1       root     3667:      to get rid of comments or backslash-newlines.  */
1.1.1.8 ! root     3668:   int copy_directive = 0;
1.1       root     3669: 
                   3670:   U_CHAR *ident, *after_ident;
                   3671: 
                   3672:   bp = ip->bufp;
                   3673: 
                   3674:   /* Record where the directive started.  do_xifdef needs this.  */
                   3675:   directive_start = bp - 1;
                   3676: 
                   3677:   /* Skip whitespace and \-newline.  */
                   3678:   while (1) {
                   3679:     if (is_hor_space[*bp]) {
1.1.1.8 ! root     3680:       if (*bp != ' ' && *bp != '\t' && pedantic)
        !          3681:        pedwarn ("%s in preprocessing directive", char_name[*bp]);
1.1       root     3682:       bp++;
1.1.1.7   root     3683:     } else if (*bp == '/' && (bp[1] == '*'
                   3684:                              || (cplusplus_comments && bp[1] == '/'))) {
                   3685:       ip->bufp = bp + 2;
1.1.1.2   root     3686:       skip_to_end_of_comment (ip, &ip->lineno, 0);
1.1       root     3687:       bp = ip->bufp;
                   3688:     } else if (*bp == '\\' && bp[1] == '\n') {
                   3689:       bp += 2; ip->lineno++;
                   3690:     } else break;
                   3691:   }
                   3692: 
                   3693:   /* Now find end of directive name.
                   3694:      If we encounter a backslash-newline, exchange it with any following
                   3695:      symbol-constituents so that we end up with a contiguous name.  */
                   3696: 
                   3697:   cp = bp;
                   3698:   while (1) {
                   3699:     if (is_idchar[*cp])
                   3700:       cp++;
                   3701:     else {
                   3702:       if (*cp == '\\' && cp[1] == '\n')
                   3703:        name_newline_fix (cp);
                   3704:       if (is_idchar[*cp])
                   3705:        cp++;
                   3706:       else break;
                   3707:     }
                   3708:   }
                   3709:   ident_length = cp - bp;
                   3710:   ident = bp;
                   3711:   after_ident = cp;
                   3712: 
                   3713:   /* A line of just `#' becomes blank.  */
                   3714: 
                   3715:   if (ident_length == 0 && *after_ident == '\n') {
                   3716:     ip->bufp = after_ident;
                   3717:     return 1;
                   3718:   }
                   3719: 
                   3720:   if (ident_length == 0 || !is_idstart[*ident]) {
                   3721:     U_CHAR *p = ident;
                   3722:     while (is_idchar[*p]) {
                   3723:       if (*p < '0' || *p > '9')
                   3724:        break;
                   3725:       p++;
                   3726:     }
                   3727:     /* Handle # followed by a line number.  */
                   3728:     if (p != ident && !is_idchar[*p]) {
                   3729:       static struct directive line_directive_table[] = {
                   3730:        {  4, do_line, "line", T_LINE},
                   3731:       };
                   3732:       if (pedantic)
                   3733:        pedwarn ("`#' followed by integer");
                   3734:       after_ident = ident;
                   3735:       kt = line_directive_table;
                   3736:       goto old_linenum;
                   3737:     }
                   3738: 
                   3739:     /* Avoid error for `###' and similar cases unless -pedantic.  */
                   3740:     if (p == ident) {
                   3741:       while (*p == '#' || is_hor_space[*p]) p++;
                   3742:       if (*p == '\n') {
                   3743:        if (pedantic && !lang_asm)
1.1.1.8 ! root     3744:          warning ("invalid preprocessing directive");
1.1       root     3745:        return 0;
                   3746:       }
                   3747:     }
                   3748: 
                   3749:     if (!lang_asm)
1.1.1.8 ! root     3750:       error ("invalid preprocessing directive name");
1.1       root     3751: 
                   3752:     return 0;
                   3753:   }
                   3754: 
                   3755:   /*
                   3756:    * Decode the keyword and call the appropriate expansion
                   3757:    * routine, after moving the input pointer up to the next line.
                   3758:    */
                   3759:   for (kt = directive_table; kt->length > 0; kt++) {
1.1.1.8 ! root     3760:     if (kt->length == ident_length && !bcmp (kt->name, ident, ident_length)) {
1.1       root     3761:       register U_CHAR *buf;
                   3762:       register U_CHAR *limit;
                   3763:       int unterminated;
                   3764:       int junk;
1.1.1.5   root     3765:       int *already_output;
1.1       root     3766: 
                   3767:       /* Nonzero means do not delete comments within the directive.
                   3768:         #define needs this when -traditional.  */
                   3769:       int keep_comments;
                   3770: 
                   3771:     old_linenum:
                   3772: 
                   3773:       limit = ip->buf + ip->length;
                   3774:       unterminated = 0;
1.1.1.5   root     3775:       already_output = 0;
1.1       root     3776:       keep_comments = traditional && kt->traditional_comments;
                   3777:       /* #import is defined only in Objective C, or when on the NeXT.  */
1.1.1.8 ! root     3778:       if (kt->type == T_IMPORT
        !          3779:          && !(objc || lookup ((U_CHAR *) "__NeXT__", -1, -1)))
1.1       root     3780:        break;
                   3781: 
1.1.1.8 ! root     3782:       /* Find the end of this directive (first newline not backslashed
1.1       root     3783:         and not in a string or comment).
1.1.1.8 ! root     3784:         Set COPY_DIRECTIVE if the directive must be copied
1.1       root     3785:         (it contains a backslash-newline or a comment).  */
                   3786: 
                   3787:       buf = bp = after_ident;
                   3788:       while (bp < limit) {
                   3789:        register U_CHAR c = *bp++;
                   3790:        switch (c) {
                   3791:        case '\\':
                   3792:          if (bp < limit) {
                   3793:            if (*bp == '\n') {
                   3794:              ip->lineno++;
1.1.1.8 ! root     3795:              copy_directive = 1;
1.1.1.7   root     3796:              bp++;
                   3797:            } else if (traditional)
                   3798:              bp++;
1.1       root     3799:          }
                   3800:          break;
                   3801: 
                   3802:        case '\'':
                   3803:        case '\"':
1.1.1.8 ! root     3804:          bp = skip_quoted_string (bp - 1, limit, ip->lineno, &ip->lineno, &copy_directive, &unterminated);
1.1       root     3805:          /* Don't bother calling the directive if we already got an error
                   3806:             message due to unterminated string.  Skip everything and pretend
                   3807:             we called the directive.  */
                   3808:          if (unterminated) {
                   3809:            if (traditional) {
                   3810:              /* Traditional preprocessing permits unterminated strings.  */
                   3811:              ip->bufp = bp;
                   3812:              goto endloop1;
                   3813:            }
                   3814:            ip->bufp = bp;
                   3815:            return 1;
                   3816:          }
                   3817:          break;
                   3818: 
                   3819:          /* <...> is special for #include.  */
                   3820:        case '<':
                   3821:          if (!kt->angle_brackets)
                   3822:            break;
1.1.1.7   root     3823:          while (bp < limit && *bp != '>' && *bp != '\n') {
                   3824:            if (*bp == '\\' && bp[1] == '\n') {
                   3825:              ip->lineno++;
1.1.1.8 ! root     3826:              copy_directive = 1;
1.1.1.7   root     3827:              bp++;
                   3828:            }
                   3829:            bp++;
                   3830:          }
1.1       root     3831:          break;
                   3832: 
                   3833:        case '/':
                   3834:          if (*bp == '\\' && bp[1] == '\n')
                   3835:            newline_fix (bp);
                   3836:          if (*bp == '*'
1.1.1.4   root     3837:              || (cplusplus_comments && *bp == '/')) {
1.1       root     3838:            U_CHAR *obp = bp - 1;
                   3839:            ip->bufp = bp + 1;
1.1.1.2   root     3840:            skip_to_end_of_comment (ip, &ip->lineno, 0);
1.1       root     3841:            bp = ip->bufp;
1.1.1.8 ! root     3842:            /* No need to copy the directive because of a comment at the end;
1.1       root     3843:               just don't include the comment in the directive.  */
                   3844:            if (bp == limit || *bp == '\n') {
                   3845:              bp = obp;
                   3846:              goto endloop1;
                   3847:            }
                   3848:            /* Don't remove the comments if -traditional.  */
                   3849:            if (! keep_comments)
1.1.1.8 ! root     3850:              copy_directive++;
1.1       root     3851:          }
                   3852:          break;
                   3853: 
                   3854:        case '\f':
1.1.1.8 ! root     3855:        case '\r':
1.1       root     3856:        case '\v':
                   3857:          if (pedantic)
1.1.1.8 ! root     3858:            pedwarn ("%s in preprocessing directive", char_name[c]);
1.1       root     3859:          break;
                   3860: 
                   3861:        case '\n':
                   3862:          --bp;         /* Point to the newline */
                   3863:          ip->bufp = bp;
                   3864:          goto endloop1;
                   3865:        }
                   3866:       }
                   3867:       ip->bufp = bp;
                   3868: 
                   3869:     endloop1:
                   3870:       resume_p = ip->bufp;
                   3871:       /* BP is the end of the directive.
                   3872:         RESUME_P is the next interesting data after the directive.
                   3873:         A comment may come between.  */
                   3874: 
                   3875:       /* If a directive should be copied through, and -E was given,
                   3876:         pass it through before removing comments.  */
                   3877:       if (!no_output && kt->pass_thru && put_out_comments) {
                   3878:         int len;
                   3879: 
                   3880:        /* Output directive name.  */
                   3881:         check_expand (op, kt->length + 2);
                   3882:        /* Make sure # is at the start of a line */
                   3883:        if (op->bufp > op->buf && op->bufp[-1] != '\n') {
                   3884:          op->lineno++;
                   3885:          *op->bufp++ = '\n';
                   3886:        }
                   3887:         *op->bufp++ = '#';
                   3888:         bcopy (kt->name, op->bufp, kt->length);
                   3889:         op->bufp += kt->length;
                   3890: 
                   3891:        /* Output arguments.  */
                   3892:        len = (bp - buf);
                   3893:        check_expand (op, len);
1.1.1.7   root     3894:        bcopy (buf, (char *) op->bufp, len);
1.1       root     3895:        op->bufp += len;
                   3896:        /* Take account of any (escaped) newlines just output.  */
                   3897:        while (--len >= 0)
                   3898:          if (buf[len] == '\n')
                   3899:            op->lineno++;
                   3900: 
                   3901:        already_output = &junk;
                   3902:       }                                /* Don't we need a newline or #line? */
                   3903: 
1.1.1.8 ! root     3904:       if (copy_directive) {
1.1       root     3905:        register U_CHAR *xp = buf;
1.1.1.8 ! root     3906:        /* Need to copy entire directive into temp buffer before dispatching */
1.1       root     3907: 
1.1.1.8 ! root     3908:        cp = (U_CHAR *) alloca (bp - buf + 5); /* room for directive plus
1.1       root     3909:                                                  some slop */
                   3910:        buf = cp;
                   3911: 
                   3912:        /* Copy to the new buffer, deleting comments
                   3913:           and backslash-newlines (and whitespace surrounding the latter).  */
                   3914: 
                   3915:        while (xp < bp) {
                   3916:          register U_CHAR c = *xp++;
                   3917:          *cp++ = c;
                   3918: 
                   3919:          switch (c) {
                   3920:          case '\n':
                   3921:            abort ();  /* A bare newline should never part of the line.  */
                   3922:            break;
                   3923: 
                   3924:            /* <...> is special for #include.  */
                   3925:          case '<':
                   3926:            if (!kt->angle_brackets)
                   3927:              break;
                   3928:            while (xp < bp && c != '>') {
                   3929:              c = *xp++;
                   3930:              if (c == '\\' && xp < bp && *xp == '\n')
                   3931:                xp++;
                   3932:              else
                   3933:                *cp++ = c;
                   3934:            }
                   3935:            break;
                   3936: 
                   3937:          case '\\':
                   3938:            if (*xp == '\n') {
                   3939:              xp++;
                   3940:              cp--;
1.1.1.8 ! root     3941:              if (cp != buf && is_hor_space[cp[-1]]) {
        !          3942:                while (cp - 1 != buf && is_hor_space[cp[-2]])
        !          3943:                  cp--;
1.1       root     3944:                SKIP_WHITE_SPACE (xp);
1.1.1.8 ! root     3945:              } else if (is_hor_space[*xp]) {
1.1       root     3946:                *cp++ = *xp++;
                   3947:                SKIP_WHITE_SPACE (xp);
                   3948:              }
1.1.1.8 ! root     3949:            } else if (traditional && xp < bp) {
1.1.1.3   root     3950:              *cp++ = *xp++;
1.1       root     3951:            }
                   3952:            break;
                   3953: 
                   3954:          case '\'':
                   3955:          case '\"':
                   3956:            {
                   3957:              register U_CHAR *bp1
1.1.1.4   root     3958:                = skip_quoted_string (xp - 1, bp, ip->lineno,
                   3959:                                      NULL_PTR, NULL_PTR, NULL_PTR);
1.1       root     3960:              while (xp != bp1)
                   3961:                if (*xp == '\\') {
                   3962:                  if (*++xp != '\n')
                   3963:                    *cp++ = '\\';
                   3964:                  else
                   3965:                    xp++;
                   3966:                } else
                   3967:                  *cp++ = *xp++;
                   3968:            }
                   3969:            break;
                   3970: 
                   3971:          case '/':
                   3972:            if (*xp == '*'
1.1.1.4   root     3973:                || (cplusplus_comments && *xp == '/')) {
1.1       root     3974:              ip->bufp = xp + 1;
1.1.1.8 ! root     3975:              /* If we already copied the directive through,
1.1       root     3976:                 already_output != 0 prevents outputting comment now.  */
1.1.1.2   root     3977:              skip_to_end_of_comment (ip, already_output, 0);
1.1       root     3978:              if (keep_comments)
                   3979:                while (xp != ip->bufp)
                   3980:                  *cp++ = *xp++;
                   3981:              /* Delete or replace the slash.  */
                   3982:              else if (traditional)
                   3983:                cp--;
                   3984:              else
                   3985:                cp[-1] = ' ';
                   3986:              xp = ip->bufp;
                   3987:            }
                   3988:          }
                   3989:        }
                   3990: 
                   3991:        /* Null-terminate the copy.  */
                   3992: 
                   3993:        *cp = 0;
                   3994:       } else
                   3995:        cp = bp;
                   3996: 
                   3997:       ip->bufp = resume_p;
                   3998: 
                   3999:       /* Some directives should be written out for cc1 to process,
                   4000:         just as if they were not defined.  And sometimes we're copying
                   4001:         definitions through.  */
                   4002: 
                   4003:       if (!no_output && already_output == 0
                   4004:          && (kt->pass_thru
                   4005:              || (kt->type == T_DEFINE
                   4006:                  && (dump_macros == dump_names
                   4007:                      || dump_macros == dump_definitions)))) {
                   4008:         int len;
                   4009: 
                   4010:        /* Output directive name.  */
                   4011:         check_expand (op, kt->length + 1);
                   4012:         *op->bufp++ = '#';
1.1.1.7   root     4013:         bcopy (kt->name, (char *) op->bufp, kt->length);
1.1       root     4014:         op->bufp += kt->length;
                   4015: 
                   4016:        if (kt->pass_thru || dump_macros == dump_definitions) {
                   4017:          /* Output arguments.  */
                   4018:          len = (cp - buf);
                   4019:          check_expand (op, len);
1.1.1.7   root     4020:          bcopy (buf, (char *) op->bufp, len);
1.1       root     4021:          op->bufp += len;
1.1.1.4   root     4022:        } else if (kt->type == T_DEFINE && dump_macros == dump_names) {
                   4023:          U_CHAR *xp = buf;
                   4024:          U_CHAR *yp;
                   4025:          SKIP_WHITE_SPACE (xp);
                   4026:          yp = xp;
                   4027:          while (is_idchar[*xp]) xp++;
                   4028:          len = (xp - yp);
                   4029:          check_expand (op, len + 1);
                   4030:          *op->bufp++ = ' ';
                   4031:          bcopy (yp, op->bufp, len);
                   4032:          op->bufp += len;
1.1       root     4033:        }
                   4034:       }                                /* Don't we need a newline or #line? */
                   4035: 
1.1.1.8 ! root     4036:       /* Call the appropriate directive handler.  buf now points to
1.1       root     4037:         either the appropriate place in the input buffer, or to
                   4038:         the temp buffer if it was necessary to make one.  cp
                   4039:         points to the first char after the contents of the (possibly
1.1.1.8 ! root     4040:         copied) directive, in either case. */
1.1       root     4041:       (*kt->func) (buf, cp, op, kt);
                   4042:       check_expand (op, ip->length - (ip->bufp - ip->buf));
                   4043: 
                   4044:       return 1;
                   4045:     }
                   4046:   }
                   4047: 
                   4048:   /* It is deliberate that we don't warn about undefined directives.
                   4049:      That is the responsibility of cc1.  */
                   4050:   return 0;
                   4051: }
                   4052: 
1.1.1.3   root     4053: static struct tm *
                   4054: timestamp ()
                   4055: {
                   4056:   static struct tm *timebuf;
                   4057:   if (!timebuf) {
1.1.1.7   root     4058:     time_t t = time ((time_t *)0);
1.1.1.3   root     4059:     timebuf = localtime (&t);
                   4060:   }
                   4061:   return timebuf;
                   4062: }
                   4063: 
1.1       root     4064: static char *monthnames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
                   4065:                             "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
                   4066:                            };
                   4067: 
                   4068: /*
                   4069:  * expand things like __FILE__.  Place the expansion into the output
                   4070:  * buffer *without* rescanning.
                   4071:  */
                   4072: 
                   4073: static void
                   4074: special_symbol (hp, op)
                   4075:      HASHNODE *hp;
                   4076:      FILE_BUF *op;
                   4077: {
                   4078:   char *buf;
                   4079:   int i, len;
                   4080:   int true_indepth;
                   4081:   FILE_BUF *ip = NULL;
1.1.1.3   root     4082:   struct tm *timebuf;
1.1       root     4083: 
                   4084:   int paren = 0;               /* For special `defined' keyword */
                   4085: 
                   4086:   if (pcp_outfile && pcp_inside_if
                   4087:       && hp->type != T_SPEC_DEFINED && hp->type != T_CONST)
                   4088:     error ("Predefined macro `%s' used inside `#if' during precompilation",
                   4089:           hp->name);
                   4090:     
                   4091:   for (i = indepth; i >= 0; i--)
                   4092:     if (instack[i].fname != NULL) {
                   4093:       ip = &instack[i];
                   4094:       break;
                   4095:     }
                   4096:   if (ip == NULL) {
                   4097:     error ("cccp error: not in any file?!");
                   4098:     return;                    /* the show must go on */
                   4099:   }
                   4100: 
                   4101:   switch (hp->type) {
                   4102:   case T_FILE:
                   4103:   case T_BASE_FILE:
                   4104:     {
                   4105:       char *string;
                   4106:       if (hp->type == T_FILE)
                   4107:        string = ip->nominal_fname;
                   4108:       else
                   4109:        string = instack[0].nominal_fname;
                   4110: 
                   4111:       if (string)
                   4112:        {
1.1.1.6   root     4113:          buf = (char *) alloca (3 + 4 * strlen (string));
                   4114:          quote_string (buf, string);
1.1       root     4115:        }
                   4116:       else
                   4117:        buf = "\"\"";
                   4118: 
                   4119:       break;
                   4120:     }
                   4121: 
                   4122:   case T_INCLUDE_LEVEL:
                   4123:     true_indepth = 0;
                   4124:     for (i = indepth; i >= 0; i--)
                   4125:       if (instack[i].fname != NULL)
                   4126:         true_indepth++;
                   4127: 
                   4128:     buf = (char *) alloca (8); /* Eight bytes ought to be more than enough */
                   4129:     sprintf (buf, "%d", true_indepth - 1);
                   4130:     break;
                   4131: 
                   4132:   case T_VERSION:
                   4133:     buf = (char *) alloca (3 + strlen (version_string));
                   4134:     sprintf (buf, "\"%s\"", version_string);
                   4135:     break;
                   4136: 
1.1.1.6   root     4137: #ifndef NO_BUILTIN_SIZE_TYPE
1.1       root     4138:   case T_SIZE_TYPE:
1.1.1.7   root     4139:     buf = SIZE_TYPE;
1.1       root     4140:     break;
1.1.1.6   root     4141: #endif
1.1       root     4142: 
1.1.1.6   root     4143: #ifndef NO_BUILTIN_PTRDIFF_TYPE
1.1       root     4144:   case T_PTRDIFF_TYPE:
1.1.1.7   root     4145:     buf = PTRDIFF_TYPE;
1.1       root     4146:     break;
1.1.1.6   root     4147: #endif
1.1       root     4148: 
                   4149:   case T_WCHAR_TYPE:
1.1.1.7   root     4150:     buf = wchar_type;
1.1       root     4151:     break;
                   4152: 
1.1.1.5   root     4153:   case T_USER_LABEL_PREFIX_TYPE:
1.1.1.7   root     4154:     buf = USER_LABEL_PREFIX;
1.1.1.5   root     4155:     break;
                   4156: 
                   4157:   case T_REGISTER_PREFIX_TYPE:
1.1.1.7   root     4158:     buf = REGISTER_PREFIX;
1.1.1.5   root     4159:     break;
                   4160: 
1.1.1.8 ! root     4161:   case T_IMMEDIATE_PREFIX_TYPE:
        !          4162:     buf = IMMEDIATE_PREFIX;
        !          4163:     break;
        !          4164: 
1.1       root     4165:   case T_CONST:
1.1.1.8 ! root     4166:     buf = hp->value.cpval;
1.1       root     4167:     if (pcp_inside_if && pcp_outfile)
                   4168:       /* Output a precondition for this macro use */
1.1.1.8 ! root     4169:       fprintf (pcp_outfile, "#define %s %s\n", hp->name, buf);
1.1       root     4170:     break;
                   4171: 
                   4172:   case T_SPECLINE:
                   4173:     buf = (char *) alloca (10);
                   4174:     sprintf (buf, "%d", ip->lineno);
                   4175:     break;
                   4176: 
                   4177:   case T_DATE:
                   4178:   case T_TIME:
                   4179:     buf = (char *) alloca (20);
1.1.1.3   root     4180:     timebuf = timestamp ();
1.1       root     4181:     if (hp->type == T_DATE)
                   4182:       sprintf (buf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon],
                   4183:              timebuf->tm_mday, timebuf->tm_year + 1900);
                   4184:     else
                   4185:       sprintf (buf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,
                   4186:              timebuf->tm_sec);
                   4187:     break;
                   4188: 
                   4189:   case T_SPEC_DEFINED:
                   4190:     buf = " 0 ";               /* Assume symbol is not defined */
                   4191:     ip = &instack[indepth];
                   4192:     SKIP_WHITE_SPACE (ip->bufp);
                   4193:     if (*ip->bufp == '(') {
                   4194:       paren++;
                   4195:       ip->bufp++;                      /* Skip over the paren */
                   4196:       SKIP_WHITE_SPACE (ip->bufp);
                   4197:     }
                   4198: 
                   4199:     if (!is_idstart[*ip->bufp])
                   4200:       goto oops;
1.1.1.8 ! root     4201:     if ((hp = lookup (ip->bufp, -1, -1))) {
1.1       root     4202:       if (pcp_outfile && pcp_inside_if
1.1.1.7   root     4203:          && (hp->type == T_CONST
                   4204:              || (hp->type == T_MACRO && hp->value.defn->predefined)))
1.1       root     4205:        /* Output a precondition for this macro use. */
                   4206:        fprintf (pcp_outfile, "#define %s\n", hp->name);
                   4207:       buf = " 1 ";
                   4208:     }
                   4209:     else
                   4210:       if (pcp_outfile && pcp_inside_if)        {
                   4211:        /* Output a precondition for this macro use */
                   4212:        U_CHAR *cp = ip->bufp;
                   4213:        fprintf (pcp_outfile, "#undef ");
                   4214:        while (is_idchar[*cp]) /* Ick! */
                   4215:          fputc (*cp++, pcp_outfile);
                   4216:        putc ('\n', pcp_outfile);
                   4217:       }
                   4218:     while (is_idchar[*ip->bufp])
                   4219:       ++ip->bufp;
                   4220:     SKIP_WHITE_SPACE (ip->bufp);
                   4221:     if (paren) {
                   4222:       if (*ip->bufp != ')')
                   4223:        goto oops;
                   4224:       ++ip->bufp;
                   4225:     }
                   4226:     break;
                   4227: 
                   4228: oops:
                   4229: 
                   4230:     error ("`defined' without an identifier");
                   4231:     break;
                   4232: 
                   4233:   default:
                   4234:     error ("cccp error: invalid special hash type"); /* time for gdb */
                   4235:     abort ();
                   4236:   }
                   4237:   len = strlen (buf);
                   4238:   check_expand (op, len);
1.1.1.7   root     4239:   bcopy (buf, (char *) op->bufp, len);
1.1       root     4240:   op->bufp += len;
                   4241: 
                   4242:   return;
                   4243: }
                   4244: 
                   4245: 
                   4246: /* Routines to handle #directives */
                   4247: 
                   4248: /* Handle #include and #import.
                   4249:    This function expects to see "fname" or <fname> on the input.  */
                   4250: 
                   4251: static int
                   4252: do_include (buf, limit, op, keyword)
                   4253:      U_CHAR *buf, *limit;
                   4254:      FILE_BUF *op;
                   4255:      struct directive *keyword;
                   4256: {
                   4257:   int importing = (keyword->type == T_IMPORT);
                   4258:   int skip_dirs = (keyword->type == T_INCLUDE_NEXT);
                   4259:   static int import_warning = 0;
                   4260:   char *fname;         /* Dynamically allocated fname buffer */
                   4261:   char *pcftry;
                   4262:   char *pcfname;
                   4263:   U_CHAR *fbeg, *fend;         /* Beginning and end of fname */
                   4264: 
                   4265:   struct file_name_list *search_start = include; /* Chain of dirs to search */
                   4266:   struct file_name_list dsp[1];        /* First in chain, if #include "..." */
1.1.1.4   root     4267:   struct file_name_list *searchptr = 0;
1.1.1.8 ! root     4268:   size_t flen;
1.1       root     4269: 
                   4270:   int f;                       /* file number */
                   4271: 
                   4272:   int retried = 0;             /* Have already tried macro
                   4273:                                   expanding the include line*/
1.1.1.4   root     4274:   int angle_brackets = 0;      /* 0 for "...", 1 for <...> */
1.1       root     4275:   int pcf = -1;
                   4276:   char *pcfbuf;
1.1.1.8 ! root     4277:   char *pcfbuflimit;
1.1       root     4278:   int pcfnum;
                   4279:   f= -1;                       /* JF we iz paranoid! */
                   4280: 
1.1.1.4   root     4281:   if (importing && warn_import && !inhibit_warnings
1.1.1.2   root     4282:       && !instack[indepth].system_header_p && !import_warning) {
1.1       root     4283:     import_warning = 1;
                   4284:     warning ("using `#import' is not recommended");
                   4285:     fprintf (stderr, "The fact that a certain header file need not be processed more than once\n");
                   4286:     fprintf (stderr, "should be indicated in the header file, not where it is used.\n");
                   4287:     fprintf (stderr, "The best way to do this is with a conditional of this form:\n\n");
                   4288:     fprintf (stderr, "  #ifndef _FOO_H_INCLUDED\n");
                   4289:     fprintf (stderr, "  #define _FOO_H_INCLUDED\n");
                   4290:     fprintf (stderr, "  ... <real contents of file> ...\n");
                   4291:     fprintf (stderr, "  #endif /* Not _FOO_H_INCLUDED */\n\n");
                   4292:     fprintf (stderr, "Then users can use `#include' any number of times.\n");
                   4293:     fprintf (stderr, "GNU C automatically avoids processing the file more than once\n");
                   4294:     fprintf (stderr, "when it is equipped with such a conditional.\n");
                   4295:   }
                   4296: 
                   4297: get_filename:
                   4298: 
                   4299:   fbeg = buf;
                   4300:   SKIP_WHITE_SPACE (fbeg);
                   4301:   /* Discard trailing whitespace so we can easily see
                   4302:      if we have parsed all the significant chars we were given.  */
                   4303:   while (limit != fbeg && is_hor_space[limit[-1]]) limit--;
                   4304: 
                   4305:   switch (*fbeg++) {
                   4306:   case '\"':
1.1.1.4   root     4307:     {
1.1       root     4308:       FILE_BUF *fp;
1.1.1.4   root     4309:       /* Copy the operand text, concatenating the strings.  */
                   4310:       {
                   4311:        U_CHAR *fin = fbeg;
                   4312:        fbeg = (U_CHAR *) alloca (limit - fbeg + 1);
                   4313:        fend = fbeg;
                   4314:        while (fin != limit) {
                   4315:          while (fin != limit && *fin != '\"')
                   4316:            *fend++ = *fin++;
                   4317:          fin++;
                   4318:          if (fin == limit)
                   4319:            break;
                   4320:          /* If not at the end, there had better be another string.  */
                   4321:          /* Skip just horiz space, and don't go past limit.  */
                   4322:          while (fin != limit && is_hor_space[*fin]) fin++;
                   4323:          if (fin != limit && *fin == '\"')
                   4324:            fin++;
                   4325:          else
                   4326:            goto fail;
                   4327:        }
                   4328:       }
1.1.1.5   root     4329:       *fend = 0;
1.1       root     4330: 
                   4331:       /* We have "filename".  Figure out directory this source
                   4332:         file is coming from and put it on the front of the list. */
                   4333: 
                   4334:       /* If -I- was specified, don't search current dir, only spec'd ones. */
                   4335:       if (ignore_srcdir) break;
                   4336: 
                   4337:       for (fp = &instack[indepth]; fp >= instack; fp--)
                   4338:        {
                   4339:          int n;
                   4340:          char *ep,*nam;
                   4341: 
                   4342:          if ((nam = fp->nominal_fname) != NULL) {
                   4343:            /* Found a named file.  Figure out dir of the file,
                   4344:               and put it in front of the search list.  */
                   4345:            dsp[0].next = search_start;
                   4346:            search_start = dsp;
                   4347: #ifndef VMS
                   4348:            ep = rindex (nam, '/');
1.1.1.8 ! root     4349: #ifdef DIR_SEPARATOR
        !          4350:            if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR);
        !          4351:            else {
        !          4352:              char *tmp = rindex (nam, DIR_SEPARATOR);
        !          4353:              if (tmp != NULL && tmp > ep) ep = tmp;
        !          4354:            }
        !          4355: #endif
1.1       root     4356: #else                          /* VMS */
                   4357:            ep = rindex (nam, ']');
                   4358:            if (ep == NULL) ep = rindex (nam, '>');
                   4359:            if (ep == NULL) ep = rindex (nam, ':');
                   4360:            if (ep != NULL) ep++;
                   4361: #endif                         /* VMS */
                   4362:            if (ep != NULL) {
                   4363:              n = ep - nam;
                   4364:              dsp[0].fname = (char *) alloca (n + 1);
                   4365:              strncpy (dsp[0].fname, nam, n);
                   4366:              dsp[0].fname[n] = '\0';
1.1.1.4   root     4367:              if (n + INCLUDE_LEN_FUDGE > max_include_len)
                   4368:                max_include_len = n + INCLUDE_LEN_FUDGE;
1.1       root     4369:            } else {
                   4370:              dsp[0].fname = 0; /* Current directory */
                   4371:            }
1.1.1.7   root     4372:            dsp[0].got_name_map = 0;
1.1       root     4373:            break;
                   4374:          }
                   4375:        }
                   4376:       break;
                   4377:     }
                   4378: 
                   4379:   case '<':
                   4380:     fend = fbeg;
                   4381:     while (fend != limit && *fend != '>') fend++;
                   4382:     if (*fend == '>' && fend + 1 == limit) {
1.1.1.4   root     4383:       angle_brackets = 1;
1.1       root     4384:       /* If -I-, start with the first -I dir after the -I-.  */
                   4385:       if (first_bracket_include)
                   4386:        search_start = first_bracket_include;
                   4387:       break;
                   4388:     }
                   4389:     goto fail;
                   4390: 
                   4391:   default:
1.1.1.7   root     4392: #ifdef VMS
                   4393:     /*
                   4394:      * Support '#include xyz' like VAX-C to allow for easy use of all the
                   4395:      * decwindow include files. It defaults to '#include <xyz.h>' (so the
                   4396:      * code from case '<' is repeated here) and generates a warning.
1.1.1.8 ! root     4397:      * (Note: macro expansion of `xyz' takes precedence.)
1.1.1.7   root     4398:      */
1.1.1.8 ! root     4399:     if (retried && isalpha(*(--fbeg))) {
1.1.1.7   root     4400:       fend = fbeg;
                   4401:       while (fend != limit && (!isspace(*fend))) fend++;
                   4402:       warning ("VAX-C-style include specification found, use '#include <filename.h>' !");
                   4403:       if (fend  == limit) {
                   4404:        angle_brackets = 1;
                   4405:        /* If -I-, start with the first -I dir after the -I-.  */
                   4406:        if (first_bracket_include)
                   4407:          search_start = first_bracket_include;
                   4408:        break;
                   4409:       }
                   4410:     }
                   4411: #endif
                   4412: 
1.1       root     4413:   fail:
                   4414:     if (retried) {
1.1.1.5   root     4415:       error ("`#%s' expects \"FILENAME\" or <FILENAME>", keyword->name);
1.1       root     4416:       return 0;
                   4417:     } else {
1.1.1.8 ! root     4418:       /* Expand buffer and then remove any newline markers.
        !          4419:         We can't just tell expand_to_temp_buffer to omit the markers,
        !          4420:         since it would put extra spaces in include file names.  */
        !          4421:       FILE_BUF trybuf;
        !          4422:       U_CHAR *src;
        !          4423:       trybuf = expand_to_temp_buffer (buf, limit, 1, 0);
        !          4424:       src = trybuf.buf;
1.1       root     4425:       buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1);
1.1.1.8 ! root     4426:       limit = buf;
        !          4427:       while (src != trybuf.bufp) {
        !          4428:        switch ((*limit++ = *src++)) {
        !          4429:          case '\n':
        !          4430:            limit--;
        !          4431:            src++;
        !          4432:            break;
        !          4433: 
        !          4434:          case '\'':
        !          4435:          case '\"':
        !          4436:            {
        !          4437:              U_CHAR *src1 = skip_quoted_string (src - 1, trybuf.bufp, 0,
        !          4438:                                                 NULL_PTR, NULL_PTR, NULL_PTR);
        !          4439:              while (src != src1)
        !          4440:                *limit++ = *src++;
        !          4441:            }
        !          4442:            break;
        !          4443:        }
        !          4444:       }
        !          4445:       *limit = 0;
1.1       root     4446:       free (trybuf.buf);
                   4447:       retried++;
                   4448:       goto get_filename;
                   4449:     }
                   4450:   }
                   4451: 
                   4452:   /* For #include_next, skip in the search path
                   4453:      past the dir in which the containing file was found.  */
                   4454:   if (skip_dirs) {
                   4455:     FILE_BUF *fp;
                   4456:     for (fp = &instack[indepth]; fp >= instack; fp--)
                   4457:       if (fp->fname != NULL) {
                   4458:        /* fp->dir is null if the containing file was specified
                   4459:           with an absolute file name.  In that case, don't skip anything.  */
                   4460:        if (fp->dir)
                   4461:          search_start = fp->dir->next;
                   4462:        break;
                   4463:       }
                   4464:   }
                   4465: 
                   4466:   flen = fend - fbeg;
1.1.1.5   root     4467: 
                   4468:   if (flen == 0)
                   4469:     {
                   4470:       error ("empty file name in `#%s'", keyword->name);
                   4471:       return 0;
                   4472:     }
                   4473: 
1.1       root     4474:   /* Allocate this permanently, because it gets stored in the definitions
                   4475:      of macros.  */
1.1.1.8 ! root     4476:   fname = xmalloc (max_include_len + flen + 4);
1.1       root     4477:   /* + 2 above for slash and terminating null.  */
1.1.1.7   root     4478:   /* + 2 added for '.h' on VMS (to support '#include filename') */
1.1       root     4479: 
                   4480:   /* If specified file name is absolute, just open it.  */
                   4481: 
1.1.1.8 ! root     4482:   if (*fbeg == '/'
        !          4483: #ifdef DIR_SEPARATOR
        !          4484:       || *fbeg == DIR_SEPARATOR
        !          4485: #endif
        !          4486:       ) {
        !          4487:     strncpy (fname, (char *) fbeg, flen);
1.1       root     4488:     fname[flen] = 0;
1.1.1.4   root     4489:     if (redundant_include_p (fname))
1.1.1.2   root     4490:       return 0;
1.1       root     4491:     if (importing)
1.1.1.7   root     4492:       f = lookup_import (fname, NULL_PTR);
1.1       root     4493:     else
1.1.1.7   root     4494:       f = open_include_file (fname, NULL_PTR);
1.1       root     4495:     if (f == -2)
                   4496:       return 0;                /* Already included this file */
                   4497:   } else {
                   4498:     /* Search directory path, trying to open the file.
                   4499:        Copy each filename tried into FNAME.  */
                   4500: 
                   4501:     for (searchptr = search_start; searchptr; searchptr = searchptr->next) {
                   4502:       if (searchptr->fname) {
                   4503:        /* The empty string in a search path is ignored.
                   4504:           This makes it possible to turn off entirely
                   4505:           a standard piece of the list.  */
                   4506:        if (searchptr->fname[0] == 0)
                   4507:          continue;
1.1.1.8 ! root     4508:        strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
        !          4509:        if (fname[0] && fname[strlen (fname) - 1] != '/')
        !          4510:          strcat (fname, "/");
1.1       root     4511:       } else {
                   4512:        fname[0] = 0;
                   4513:       }
1.1.1.8 ! root     4514:       strncat (fname, (char *) fbeg, flen);
1.1       root     4515: #ifdef VMS
                   4516:       /* Change this 1/2 Unix 1/2 VMS file specification into a
                   4517:          full VMS file specification */
                   4518:       if (searchptr->fname && (searchptr->fname[0] != 0)) {
                   4519:        /* Fix up the filename */
                   4520:        hack_vms_include_specification (fname);
                   4521:       } else {
                   4522:        /* This is a normal VMS filespec, so use it unchanged.  */
                   4523:        strncpy (fname, fbeg, flen);
                   4524:        fname[flen] = 0;
1.1.1.7   root     4525:        /* if it's '#include filename', add the missing .h */
                   4526:        if (index(fname,'.')==NULL) {
                   4527:          strcat (fname, ".h");
                   4528:        }
1.1       root     4529:       }
                   4530: #endif /* VMS */
1.1.1.8 ! root     4531:       /* ??? There are currently 3 separate mechanisms for avoiding processing
        !          4532:         of redundant include files: #import, #pragma once, and
        !          4533:         redundant_include_p.  It would be nice if they were unified.  */
        !          4534:       if (redundant_include_p (fname))
        !          4535:        return 0;
1.1       root     4536:       if (importing)
1.1.1.7   root     4537:        f = lookup_import (fname, searchptr);
1.1       root     4538:       else
1.1.1.7   root     4539:        f = open_include_file (fname, searchptr);
1.1       root     4540:       if (f == -2)
                   4541:        return 0;                       /* Already included this file */
1.1.1.5   root     4542: #ifdef EACCES
                   4543:       else if (f == -1 && errno == EACCES)
                   4544:        warning ("Header file %s exists, but is not readable", fname);
                   4545: #endif
1.1       root     4546:       if (f >= 0)
                   4547:        break;
                   4548:     }
                   4549:   }
                   4550: 
                   4551:   if (f < 0) {
                   4552:     /* A file that was not found.  */
                   4553: 
1.1.1.8 ! root     4554:     strncpy (fname, (char *) fbeg, flen);
1.1       root     4555:     fname[flen] = 0;
1.1.1.7   root     4556:     /* If generating dependencies and -MG was specified, we assume missing
                   4557:        files are leaf files, living in the same directory as the source file
                   4558:        or other similar place; these missing files may be generated from
                   4559:        other files and may not exist yet (eg: y.tab.h).  */
                   4560:     if (print_deps_missing_files
                   4561:        && print_deps > (angle_brackets || (system_include_depth > 0)))
                   4562:       {
                   4563:        /* If it was requested as a system header file,
                   4564:           then assume it belongs in the first place to look for such.  */
                   4565:        if (angle_brackets)
                   4566:          {
                   4567:            for (searchptr = search_start; searchptr; searchptr = searchptr->next)
                   4568:              {
                   4569:                if (searchptr->fname)
                   4570:                  {
                   4571:                    char *p;
                   4572: 
                   4573:                    if (searchptr->fname[0] == 0)
                   4574:                      continue;
1.1.1.8 ! root     4575:                    p = (char *) alloca (strlen (searchptr->fname)
        !          4576:                                         + strlen (fname) + 2);
        !          4577:                    strcpy (p, skip_redundant_dir_prefix (searchptr->fname));
        !          4578:                    if (p[0] && p[strlen (p) - 1] != '/')
        !          4579:                      strcat (p, "/");
1.1.1.7   root     4580:                    strcat (p, fname);
                   4581:                    deps_output (p, ' ');
                   4582:                    break;
                   4583:                  }
                   4584:              }
                   4585:          }
                   4586:        else
                   4587:          {
                   4588:            /* Otherwise, omit the directory, as if the file existed
                   4589:               in the directory with the source.  */
                   4590:            deps_output (fname, ' ');
                   4591:          }
                   4592:       }
1.1.1.5   root     4593:     /* If -M was specified, and this header file won't be added to the
                   4594:        dependency list, then don't count this as an error, because we can
                   4595:        still produce correct output.  Otherwise, we can't produce correct
                   4596:        output, because there may be dependencies we need inside the missing
                   4597:        file, and we don't know what directory this missing file exists in.  */
1.1.1.7   root     4598:     else if (print_deps
1.1.1.5   root     4599:        && (print_deps <= (angle_brackets || (system_include_depth > 0))))
                   4600:       warning ("No include path in which to find %s", fname);
                   4601:     else if (search_start)
1.1.1.4   root     4602:       error_from_errno (fname);
                   4603:     else
                   4604:       error ("No include path in which to find %s", fname);
1.1       root     4605:   } else {
                   4606:     /* Check to see if this include file is a once-only include file.
                   4607:        If so, give up.  */
                   4608: 
                   4609:     struct file_name_list* ptr;
                   4610: 
                   4611:     for (ptr = dont_repeat_files; ptr; ptr = ptr->next) {
                   4612:       if (!strcmp (ptr->fname, fname)) {
                   4613:        close (f);
                   4614:         return 0;                              /* This file was once'd. */
                   4615:       }
                   4616:     }
                   4617: 
                   4618:     for (ptr = all_include_files; ptr; ptr = ptr->next) {
                   4619:       if (!strcmp (ptr->fname, fname))
                   4620:         break;                         /* This file was included before. */
                   4621:     }
                   4622: 
                   4623:     if (ptr == 0) {
                   4624:       /* This is the first time for this file.  */
                   4625:       /* Add it to list of files included.  */
                   4626: 
                   4627:       ptr = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
                   4628:       ptr->control_macro = 0;
1.1.1.6   root     4629:       ptr->c_system_include_path = 0;
1.1       root     4630:       ptr->next = all_include_files;
                   4631:       all_include_files = ptr;
                   4632:       ptr->fname = savestring (fname);
1.1.1.7   root     4633:       ptr->got_name_map = 0;
1.1       root     4634: 
                   4635:       /* For -M, add this file to the dependencies.  */
1.1.1.7   root     4636:       if (print_deps > (angle_brackets || (system_include_depth > 0)))
                   4637:        deps_output (fname, ' ');
1.1       root     4638:     }   
                   4639: 
                   4640:     /* Handle -H option.  */
1.1.1.8 ! root     4641:     if (print_include_names)
        !          4642:       fprintf (stderr, "%*s%s\n", indepth, "", fname);
1.1       root     4643: 
1.1.1.4   root     4644:     if (angle_brackets)
1.1       root     4645:       system_include_depth++;
                   4646: 
                   4647:     /* Actually process the file.  */
                   4648:     add_import (f, fname);     /* Record file on "seen" list for #import. */
                   4649: 
                   4650:     pcftry = (char *) alloca (strlen (fname) + 30);
                   4651:     pcfbuf = 0;
                   4652:     pcfnum = 0;
                   4653: 
                   4654:     if (!no_precomp)
1.1.1.8 ! root     4655:       {
        !          4656:        struct stat stat_f;
1.1       root     4657: 
1.1.1.8 ! root     4658:        fstat (f, &stat_f);
        !          4659: 
        !          4660:        do {
        !          4661:          sprintf (pcftry, "%s%d", fname, pcfnum++);
        !          4662: 
        !          4663:          pcf = open (pcftry, O_RDONLY, 0666);
        !          4664:          if (pcf != -1)
        !          4665:            {
        !          4666:              struct stat s;
        !          4667: 
        !          4668:              fstat (pcf, &s);
        !          4669:              if (bcmp ((char *) &stat_f.st_ino, (char *) &s.st_ino,
        !          4670:                        sizeof (s.st_ino))
        !          4671:                  || stat_f.st_dev != s.st_dev)
        !          4672:                {
        !          4673:                  pcfbuf = check_precompiled (pcf, fname, &pcfbuflimit);
        !          4674:                  /* Don't need it any more.  */
        !          4675:                  close (pcf);
        !          4676:                }
        !          4677:              else
        !          4678:                {
        !          4679:                  /* Don't need it at all.  */
        !          4680:                  close (pcf);
        !          4681:                  break;
        !          4682:                }
        !          4683:            }
        !          4684:        } while (pcf != -1 && !pcfbuf);
        !          4685:       }
1.1       root     4686:     
                   4687:     /* Actually process the file */
                   4688:     if (pcfbuf) {
                   4689:       pcfname = xmalloc (strlen (pcftry) + 1);
                   4690:       strcpy (pcfname, pcftry);
1.1.1.8 ! root     4691:       pcfinclude ((U_CHAR *) pcfbuf, (U_CHAR *) pcfbuflimit,
        !          4692:                  (U_CHAR *) fname, op);
1.1       root     4693:     }
                   4694:     else
1.1.1.4   root     4695:       finclude (f, fname, op, is_system_include (fname), searchptr);
1.1       root     4696: 
1.1.1.4   root     4697:     if (angle_brackets)
1.1       root     4698:       system_include_depth--;
                   4699:   }
                   4700:   return 0;
                   4701: }
                   4702: 
1.1.1.2   root     4703: /* Return nonzero if there is no need to include file NAME
                   4704:    because it has already been included and it contains a conditional
                   4705:    to make a repeated include do nothing.  */
                   4706: 
                   4707: static int
1.1.1.4   root     4708: redundant_include_p (name)
1.1.1.2   root     4709:      char *name;
                   4710: {
                   4711:   struct file_name_list *l = all_include_files;
                   4712:   for (; l; l = l->next)
                   4713:     if (! strcmp (name, l->fname)
                   4714:        && l->control_macro
                   4715:        && lookup (l->control_macro, -1, -1))
                   4716:       return 1;
                   4717:   return 0;
                   4718: }
                   4719: 
1.1.1.4   root     4720: /* Return nonzero if the given FILENAME is an absolute pathname which
                   4721:    designates a file within one of the known "system" include file
                   4722:    directories.  We assume here that if the given FILENAME looks like
                   4723:    it is the name of a file which resides either directly in a "system"
                   4724:    include file directory, or within any subdirectory thereof, then the
                   4725:    given file must be a "system" include file.  This function tells us
1.1.1.6   root     4726:    if we should suppress pedantic errors/warnings for the given FILENAME.
                   4727: 
                   4728:    The value is 2 if the file is a C-language system header file
                   4729:    for which C++ should (on most systems) assume `extern "C"'.  */
1.1.1.4   root     4730: 
                   4731: static int
                   4732: is_system_include (filename)
                   4733:     register char *filename;
                   4734: {
                   4735:   struct file_name_list *searchptr;
                   4736: 
                   4737:   for (searchptr = first_system_include; searchptr;
                   4738:        searchptr = searchptr->next)
                   4739:     if (searchptr->fname) {
1.1.1.8 ! root     4740:       register char *sys_dir = skip_redundant_dir_prefix (searchptr->fname);
1.1.1.4   root     4741:       register unsigned length = strlen (sys_dir);
                   4742: 
1.1.1.8 ! root     4743:       if (! strncmp (sys_dir, filename, length)
        !          4744:          && (filename[length] == '/'
        !          4745: #ifdef DIR_SEPARATOR
        !          4746:              || filename[length] == DIR_SEPARATOR
        !          4747: #endif
        !          4748:              )) {
        !          4749:        if (searchptr->c_system_include_path)
        !          4750:          return 2;
        !          4751:        else
        !          4752:          return 1;
        !          4753:       }
1.1.1.4   root     4754:     }
                   4755:   return 0;
                   4756: }
                   4757: 
1.1.1.8 ! root     4758: /* Skip leading "./" from a directory name.
        !          4759:    This may yield the empty string, which represents the current directory.  */
        !          4760: 
        !          4761: static char *
        !          4762: skip_redundant_dir_prefix (dir)
        !          4763:      char *dir;
        !          4764: {
        !          4765:   while (dir[0] == '.' && dir[1] == '/')
        !          4766:     for (dir += 2; *dir == '/'; dir++)
        !          4767:       continue;
        !          4768:   if (dir[0] == '.' && !dir[1])
        !          4769:     dir++;
        !          4770:   return dir;
        !          4771: }
        !          4772: 
1.1.1.7   root     4773: /* The file_name_map structure holds a mapping of file names for a
                   4774:    particular directory.  This mapping is read from the file named
                   4775:    FILE_NAME_MAP_FILE in that directory.  Such a file can be used to
                   4776:    map filenames on a file system with severe filename restrictions,
                   4777:    such as DOS.  The format of the file name map file is just a series
                   4778:    of lines with two tokens on each line.  The first token is the name
                   4779:    to map, and the second token is the actual name to use.  */
                   4780: 
                   4781: struct file_name_map
                   4782: {
                   4783:   struct file_name_map *map_next;
                   4784:   char *map_from;
                   4785:   char *map_to;
                   4786: };
                   4787: 
                   4788: #define FILE_NAME_MAP_FILE "header.gcc"
                   4789: 
                   4790: /* Read a space delimited string of unlimited length from a stdio
                   4791:    file.  */
                   4792: 
                   4793: static char *
                   4794: read_filename_string (ch, f)
                   4795:      int ch;
                   4796:      FILE *f;
                   4797: {
                   4798:   char *alloc, *set;
                   4799:   int len;
                   4800: 
                   4801:   len = 20;
                   4802:   set = alloc = xmalloc (len + 1);
                   4803:   if (! is_space[ch])
                   4804:     {
                   4805:       *set++ = ch;
                   4806:       while ((ch = getc (f)) != EOF && ! is_space[ch])
                   4807:        {
                   4808:          if (set - alloc == len)
                   4809:            {
                   4810:              len *= 2;
                   4811:              alloc = xrealloc (alloc, len + 1);
                   4812:              set = alloc + len / 2;
                   4813:            }
                   4814:          *set++ = ch;
                   4815:        }
                   4816:     }
                   4817:   *set = '\0';
                   4818:   ungetc (ch, f);
                   4819:   return alloc;
                   4820: }
                   4821: 
                   4822: /* Read the file name map file for DIRNAME.  */
                   4823: 
                   4824: static struct file_name_map *
                   4825: read_name_map (dirname)
                   4826:      char *dirname;
                   4827: {
                   4828:   /* This structure holds a linked list of file name maps, one per
                   4829:      directory.  */
                   4830:   struct file_name_map_list
                   4831:     {
                   4832:       struct file_name_map_list *map_list_next;
                   4833:       char *map_list_name;
                   4834:       struct file_name_map *map_list_map;
                   4835:     };
                   4836:   static struct file_name_map_list *map_list;
                   4837:   register struct file_name_map_list *map_list_ptr;
                   4838:   char *name;
                   4839:   FILE *f;
1.1.1.8 ! root     4840:   size_t dirlen;
        !          4841:   int separator_needed;
        !          4842: 
        !          4843:   dirname = skip_redundant_dir_prefix (dirname);
1.1.1.7   root     4844: 
                   4845:   for (map_list_ptr = map_list; map_list_ptr;
                   4846:        map_list_ptr = map_list_ptr->map_list_next)
                   4847:     if (! strcmp (map_list_ptr->map_list_name, dirname))
                   4848:       return map_list_ptr->map_list_map;
                   4849: 
                   4850:   map_list_ptr = ((struct file_name_map_list *)
                   4851:                  xmalloc (sizeof (struct file_name_map_list)));
                   4852:   map_list_ptr->map_list_name = savestring (dirname);
                   4853:   map_list_ptr->map_list_map = NULL;
                   4854: 
1.1.1.8 ! root     4855:   dirlen = strlen (dirname);
        !          4856:   separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
        !          4857:   name = (char *) alloca (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
1.1.1.7   root     4858:   strcpy (name, dirname);
1.1.1.8 ! root     4859:   name[dirlen] = '/';
        !          4860:   strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
1.1.1.7   root     4861:   f = fopen (name, "r");
                   4862:   if (!f)
                   4863:     map_list_ptr->map_list_map = NULL;
                   4864:   else
                   4865:     {
                   4866:       int ch;
                   4867: 
                   4868:       while ((ch = getc (f)) != EOF)
                   4869:        {
                   4870:          char *from, *to;
                   4871:          struct file_name_map *ptr;
                   4872: 
                   4873:          if (is_space[ch])
                   4874:            continue;
                   4875:          from = read_filename_string (ch, f);
                   4876:          while ((ch = getc (f)) != EOF && is_hor_space[ch])
                   4877:            ;
                   4878:          to = read_filename_string (ch, f);
                   4879: 
                   4880:          ptr = ((struct file_name_map *)
                   4881:                 xmalloc (sizeof (struct file_name_map)));
                   4882:          ptr->map_from = from;
                   4883: 
                   4884:          /* Make the real filename absolute.  */
                   4885:          if (*to == '/')
                   4886:            ptr->map_to = to;
                   4887:          else
                   4888:            {
                   4889:              ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
                   4890:              strcpy (ptr->map_to, dirname);
                   4891:              ptr->map_to[dirlen] = '/';
1.1.1.8 ! root     4892:              strcpy (ptr->map_to + dirlen + separator_needed, to);
1.1.1.7   root     4893:              free (to);
                   4894:            }         
                   4895: 
                   4896:          ptr->map_next = map_list_ptr->map_list_map;
                   4897:          map_list_ptr->map_list_map = ptr;
                   4898: 
                   4899:          while ((ch = getc (f)) != '\n')
                   4900:            if (ch == EOF)
                   4901:              break;
                   4902:        }
                   4903:       fclose (f);
                   4904:     }
                   4905:   
                   4906:   map_list_ptr->map_list_next = map_list;
                   4907:   map_list = map_list_ptr;
                   4908: 
                   4909:   return map_list_ptr->map_list_map;
                   4910: }  
                   4911: 
                   4912: /* Try to open include file FILENAME.  SEARCHPTR is the directory
                   4913:    being tried from the include file search path.  This function maps
                   4914:    filenames on file systems based on information read by
                   4915:    read_name_map.  */
                   4916: 
                   4917: static int
                   4918: open_include_file (filename, searchptr)
                   4919:      char *filename;
                   4920:      struct file_name_list *searchptr;
                   4921: {
                   4922:   register struct file_name_map *map;
                   4923:   register char *from;
                   4924:   char *p, *dir;
                   4925: 
                   4926:   if (searchptr && ! searchptr->got_name_map)
                   4927:     {
                   4928:       searchptr->name_map = read_name_map (searchptr->fname
                   4929:                                           ? searchptr->fname : ".");
                   4930:       searchptr->got_name_map = 1;
                   4931:     }
                   4932: 
                   4933:   /* First check the mapping for the directory we are using.  */
                   4934:   if (searchptr && searchptr->name_map)
                   4935:     {
                   4936:       from = filename;
                   4937:       if (searchptr->fname)
                   4938:        from += strlen (searchptr->fname) + 1;
                   4939:       for (map = searchptr->name_map; map; map = map->map_next)
                   4940:        {
                   4941:          if (! strcmp (map->map_from, from))
                   4942:            {
                   4943:              /* Found a match.  */
                   4944:              return open (map->map_to, O_RDONLY, 0666);
                   4945:            }
                   4946:        }
                   4947:     }
                   4948: 
                   4949:   /* Try to find a mapping file for the particular directory we are
                   4950:      looking in.  Thus #include <sys/types.h> will look up sys/types.h
                   4951:      in /usr/include/header.gcc and look up types.h in
                   4952:      /usr/include/sys/header.gcc.  */
                   4953:   p = rindex (filename, '/');
1.1.1.8 ! root     4954: #ifdef DIR_SEPARATOR
        !          4955:   if (! p) p = rindex (filename, DIR_SEPARATOR);
        !          4956:   else {
        !          4957:     char *tmp = rindex (filename, DIR_SEPARATOR);
        !          4958:     if (tmp != NULL && tmp > p) p = tmp;
        !          4959:   }
        !          4960: #endif
1.1.1.7   root     4961:   if (! p)
                   4962:     p = filename;
                   4963:   if (searchptr
                   4964:       && searchptr->fname
                   4965:       && strlen (searchptr->fname) == p - filename
                   4966:       && ! strncmp (searchptr->fname, filename, p - filename))
                   4967:     {
                   4968:       /* FILENAME is in SEARCHPTR, which we've already checked.  */
                   4969:       return open (filename, O_RDONLY, 0666);
                   4970:     }
                   4971: 
                   4972:   if (p == filename)
                   4973:     {
                   4974:       dir = ".";
                   4975:       from = filename;
                   4976:     }
                   4977:   else
                   4978:     {
                   4979:       dir = (char *) alloca (p - filename + 1);
                   4980:       bcopy (filename, dir, p - filename);
                   4981:       dir[p - filename] = '\0';
                   4982:       from = p + 1;
                   4983:     }
                   4984:   for (map = read_name_map (dir); map; map = map->map_next)
                   4985:     if (! strcmp (map->map_from, from))
                   4986:       return open (map->map_to, O_RDONLY, 0666);
                   4987: 
                   4988:   return open (filename, O_RDONLY, 0666);
                   4989: }
                   4990: 
1.1       root     4991: /* Process the contents of include file FNAME, already open on descriptor F,
                   4992:    with output to OP.
1.1.1.5   root     4993:    SYSTEM_HEADER_P is 1 if this file resides in any one of the known
                   4994:    "system" include directories (as decided by the `is_system_include'
                   4995:    function above).
1.1       root     4996:    DIRPTR is the link in the dir path through which this file was found,
                   4997:    or 0 if the file name was absolute.  */
                   4998: 
                   4999: static void
                   5000: finclude (f, fname, op, system_header_p, dirptr)
                   5001:      int f;
                   5002:      char *fname;
                   5003:      FILE_BUF *op;
                   5004:      int system_header_p;
                   5005:      struct file_name_list *dirptr;
                   5006: {
                   5007:   int st_mode;
                   5008:   long st_size;
                   5009:   long i;
                   5010:   FILE_BUF *fp;                        /* For input stack frame */
                   5011:   int missing_newline = 0;
                   5012: 
                   5013:   CHECK_DEPTH (return;);
                   5014: 
                   5015:   if (file_size_and_mode (f, &st_mode, &st_size) < 0)
1.1.1.4   root     5016:     {
                   5017:       perror_with_name (fname);
                   5018:       close (f);
                   5019:       return;
                   5020:     }
1.1       root     5021: 
                   5022:   fp = &instack[indepth + 1];
1.1.1.7   root     5023:   bzero ((char *) fp, sizeof (FILE_BUF));
1.1       root     5024:   fp->nominal_fname = fp->fname = fname;
                   5025:   fp->length = 0;
                   5026:   fp->lineno = 1;
                   5027:   fp->if_stack = if_stack;
                   5028:   fp->system_header_p = system_header_p;
                   5029:   fp->dir = dirptr;
                   5030: 
                   5031:   if (S_ISREG (st_mode)) {
1.1.1.3   root     5032:     fp->buf = (U_CHAR *) xmalloc (st_size + 2);
1.1       root     5033:     fp->bufp = fp->buf;
                   5034: 
                   5035:     /* Read the file contents, knowing that st_size is an upper bound
                   5036:        on the number of bytes we can read.  */
1.1.1.8 ! root     5037:     fp->length = safe_read (f, (char *) fp->buf, st_size);
1.1.1.7   root     5038:     if (fp->length < 0) goto nope;
1.1       root     5039:   }
1.1.1.5   root     5040:   else if (S_ISDIR (st_mode)) {
                   5041:     error ("directory `%s' specified in #include", fname);
                   5042:     close (f);
                   5043:     return;
                   5044:   } else {
1.1       root     5045:     /* Cannot count its file size before reading.
                   5046:        First read the entire file into heap and
                   5047:        copy them into buffer on stack. */
                   5048: 
                   5049:     int bsize = 2000;
                   5050: 
                   5051:     st_size = 0;
1.1.1.7   root     5052:     fp->buf = (U_CHAR *) xmalloc (bsize + 2);
1.1       root     5053: 
                   5054:     for (;;) {
1.1.1.8 ! root     5055:       i = safe_read (f, (char *) fp->buf + st_size, bsize - st_size);
1.1       root     5056:       if (i < 0)
                   5057:        goto nope;      /* error! */
                   5058:       st_size += i;
1.1.1.7   root     5059:       if (st_size != bsize)
                   5060:        break;  /* End of file */
                   5061:       bsize *= 2;
                   5062:       fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
1.1       root     5063:     }
                   5064:     fp->bufp = fp->buf;
                   5065:     fp->length = st_size;
                   5066:   }
                   5067: 
1.1.1.5   root     5068:   if ((fp->length > 0 && fp->buf[fp->length - 1] != '\n')
                   5069:       /* Backslash-newline at end is not good enough.  */
                   5070:       || (fp->length > 1 && fp->buf[fp->length - 2] == '\\')) {
                   5071:     fp->buf[fp->length++] = '\n';
                   5072:     missing_newline = 1;
                   5073:   }
                   5074:   fp->buf[fp->length] = '\0';
                   5075: 
1.1       root     5076:   /* Close descriptor now, so nesting does not use lots of descriptors.  */
                   5077:   close (f);
                   5078: 
1.1.1.4   root     5079:   /* Must do this before calling trigraph_pcp, so that the correct file name
                   5080:      will be printed in warning messages.  */
                   5081: 
                   5082:   indepth++;
                   5083:   input_file_stack_tick++;
                   5084: 
1.1       root     5085:   if (!no_trigraphs)
                   5086:     trigraph_pcp (fp);
                   5087: 
1.1.1.8 ! root     5088:   output_line_directive (fp, op, 0, enter_file);
1.1       root     5089:   rescan (op, 0);
                   5090: 
1.1.1.5   root     5091:   if (missing_newline)
                   5092:     fp->lineno--;
                   5093: 
1.1       root     5094:   if (pedantic && missing_newline)
                   5095:     pedwarn ("file does not end in newline");
                   5096: 
                   5097:   indepth--;
                   5098:   input_file_stack_tick++;
1.1.1.8 ! root     5099:   output_line_directive (&instack[indepth], op, 0, leave_file);
1.1.1.3   root     5100:   free (fp->buf);
1.1       root     5101:   return;
                   5102: 
                   5103:  nope:
                   5104: 
                   5105:   perror_with_name (fname);
                   5106:   close (f);
1.1.1.3   root     5107:   free (fp->buf);
1.1       root     5108: }
                   5109: 
                   5110: /* Record that inclusion of the file named FILE
                   5111:    should be controlled by the macro named MACRO_NAME.
                   5112:    This means that trying to include the file again
                   5113:    will do something if that macro is defined.  */
                   5114: 
                   5115: static void
                   5116: record_control_macro (file, macro_name)
                   5117:      char *file;
                   5118:      U_CHAR *macro_name;
                   5119: {
                   5120:   struct file_name_list *new;
                   5121: 
                   5122:   for (new = all_include_files; new; new = new->next) {
                   5123:     if (!strcmp (new->fname, file)) {
                   5124:       new->control_macro = macro_name;
                   5125:       return;
                   5126:     }
                   5127:   }
                   5128: 
                   5129:   /* If the file is not in all_include_files, something's wrong.  */
                   5130:   abort ();
                   5131: }
                   5132: 
                   5133: /* Maintain and search list of included files, for #import.  */
                   5134: 
                   5135: #define IMPORT_HASH_SIZE 31
                   5136: 
                   5137: struct import_file {
                   5138:   char *name;
                   5139:   ino_t inode;
                   5140:   dev_t dev;
                   5141:   struct import_file *next;
                   5142: };
                   5143: 
                   5144: /* Hash table of files already included with #include or #import.  */
                   5145: 
                   5146: static struct import_file *import_hash_table[IMPORT_HASH_SIZE];
                   5147: 
                   5148: /* Hash a file name for import_hash_table.  */
                   5149: 
                   5150: static int 
                   5151: import_hash (f)
                   5152:      char *f;
                   5153: {
                   5154:   int val = 0;
                   5155: 
                   5156:   while (*f) val += *f++;
                   5157:   return (val%IMPORT_HASH_SIZE);
                   5158: }
                   5159: 
                   5160: /* Search for file FILENAME in import_hash_table.
                   5161:    Return -2 if found, either a matching name or a matching inode.
                   5162:    Otherwise, open the file and return a file descriptor if successful
                   5163:    or -1 if unsuccessful.  */
                   5164: 
                   5165: static int
1.1.1.7   root     5166: lookup_import (filename, searchptr)
1.1       root     5167:      char *filename;
1.1.1.7   root     5168:      struct file_name_list *searchptr;
1.1       root     5169: {
                   5170:   struct import_file *i;
                   5171:   int h;
                   5172:   int hashval;
                   5173:   struct stat sb;
                   5174:   int fd;
                   5175: 
                   5176:   hashval = import_hash (filename);
                   5177: 
                   5178:   /* Attempt to find file in list of already included files */
                   5179:   i = import_hash_table[hashval];
                   5180: 
                   5181:   while (i) {
                   5182:     if (!strcmp (filename, i->name))
                   5183:       return -2;               /* return found */
                   5184:     i = i->next;
                   5185:   }
                   5186:   /* Open it and try a match on inode/dev */
1.1.1.7   root     5187:   fd = open_include_file (filename, searchptr);
1.1       root     5188:   if (fd < 0)
                   5189:     return fd;
                   5190:   fstat (fd, &sb);
                   5191:   for (h = 0; h < IMPORT_HASH_SIZE; h++) {
                   5192:     i = import_hash_table[h];
                   5193:     while (i) {
                   5194:       /* Compare the inode and the device.
                   5195:         Supposedly on some systems the inode is not a scalar.  */
1.1.1.7   root     5196:       if (!bcmp ((char *) &i->inode, (char *) &sb.st_ino, sizeof (sb.st_ino))
1.1       root     5197:          && i->dev == sb.st_dev) {
                   5198:         close (fd);
                   5199:         return -2;             /* return found */
                   5200:       }
                   5201:       i = i->next;
                   5202:     }
                   5203:   }
                   5204:   return fd;                   /* Not found, return open file */
                   5205: }
                   5206: 
                   5207: /* Add the file FNAME, open on descriptor FD, to import_hash_table.  */
                   5208: 
                   5209: static void
                   5210: add_import (fd, fname)
                   5211:      int fd;
                   5212:      char *fname;
                   5213: {
                   5214:   struct import_file *i;
                   5215:   int hashval;
                   5216:   struct stat sb;
                   5217: 
                   5218:   hashval = import_hash (fname);
                   5219:   fstat (fd, &sb);
                   5220:   i = (struct import_file *)xmalloc (sizeof (struct import_file));
1.1.1.8 ! root     5221:   i->name = xmalloc (strlen (fname)+1);
1.1       root     5222:   strcpy (i->name, fname);
1.1.1.7   root     5223:   bcopy ((char *) &sb.st_ino, (char *) &i->inode, sizeof (sb.st_ino));
1.1       root     5224:   i->dev = sb.st_dev;
                   5225:   i->next = import_hash_table[hashval];
                   5226:   import_hash_table[hashval] = i;
                   5227: }
                   5228: 
                   5229: /* Load the specified precompiled header into core, and verify its
                   5230:    preconditions.  PCF indicates the file descriptor to read, which must
                   5231:    be a regular file.  FNAME indicates the file name of the original 
                   5232:    header.  *LIMIT will be set to an address one past the end of the file.
                   5233:    If the preconditions of the file are not satisfied, the buffer is 
                   5234:    freed and we return 0.  If the preconditions are satisfied, return
                   5235:    the address of the buffer following the preconditions.  The buffer, in
                   5236:    this case, should never be freed because various pieces of it will
                   5237:    be referred to until all precompiled strings are output at the end of
                   5238:    the run.
                   5239: */
                   5240: static char *
                   5241: check_precompiled (pcf, fname, limit)
                   5242:      int pcf;
                   5243:      char *fname;
                   5244:      char **limit;
                   5245: {
                   5246:   int st_mode;
                   5247:   long st_size;
                   5248:   int length = 0;
                   5249:   char *buf;
                   5250:   char *cp;
                   5251: 
                   5252:   if (pcp_outfile)
                   5253:     return 0;
                   5254:   
                   5255:   if (file_size_and_mode (pcf, &st_mode, &st_size) < 0)
                   5256:     return 0;
                   5257: 
                   5258:   if (S_ISREG (st_mode))
                   5259:     {
                   5260:       buf = xmalloc (st_size + 2);
1.1.1.7   root     5261:       length = safe_read (pcf, buf, st_size);
                   5262:       if (length < 0)
                   5263:        goto nope;
1.1       root     5264:     }
                   5265:   else
                   5266:     abort ();
                   5267:     
                   5268:   if (length > 0 && buf[length-1] != '\n')
                   5269:     buf[length++] = '\n';
                   5270:   buf[length] = '\0';
                   5271:   
                   5272:   *limit = buf + length;
                   5273: 
                   5274:   /* File is in core.  Check the preconditions. */
                   5275:   if (!check_preconditions (buf))
                   5276:     goto nope;
                   5277:   for (cp = buf; *cp; cp++)
                   5278:     ;
                   5279: #ifdef DEBUG_PCP
                   5280:   fprintf (stderr, "Using preinclude %s\n", fname);
                   5281: #endif
                   5282:   return cp + 1;
                   5283: 
                   5284:  nope:
                   5285: #ifdef DEBUG_PCP
                   5286:   fprintf (stderr, "Cannot use preinclude %s\n", fname);
                   5287: #endif
                   5288:   free (buf);
                   5289:   return 0;
                   5290: }
                   5291: 
                   5292: /* PREC (null terminated) points to the preconditions of a
                   5293:    precompiled header.  These are a series of #define and #undef
                   5294:    lines which must match the current contents of the hash
                   5295:    table.  */
                   5296: static int 
                   5297: check_preconditions (prec)
                   5298:      char *prec;
                   5299: {
                   5300:   MACRODEF mdef;
                   5301:   char *lineend;
                   5302:   
                   5303:   while (*prec) {
1.1.1.8 ! root     5304:     lineend = index (prec, '\n');
1.1       root     5305:     
                   5306:     if (*prec++ != '#') {
                   5307:       error ("Bad format encountered while reading precompiled file");
                   5308:       return 0;
                   5309:     }
                   5310:     if (!strncmp (prec, "define", 6)) {
                   5311:       HASHNODE *hp;
                   5312:       
                   5313:       prec += 6;
1.1.1.8 ! root     5314:       mdef = create_definition ((U_CHAR *) prec, (U_CHAR *) lineend, NULL_PTR);
1.1.1.4   root     5315: 
1.1       root     5316:       if (mdef.defn == 0)
1.1.1.5   root     5317:        abort ();
1.1       root     5318:       
                   5319:       if ((hp = lookup (mdef.symnam, mdef.symlen, -1)) == NULL
                   5320:          || (hp->type != T_MACRO && hp->type != T_CONST)
                   5321:          || (hp->type == T_MACRO
                   5322:              && !compare_defs (mdef.defn, hp->value.defn)
                   5323:              && (mdef.defn->length != 2
                   5324:                  || mdef.defn->expansion[0] != '\n'
                   5325:                  || mdef.defn->expansion[1] != ' ')))
                   5326:        return 0;
                   5327:     } else if (!strncmp (prec, "undef", 5)) {
                   5328:       char *name;
                   5329:       int len;
                   5330:       
                   5331:       prec += 5;
1.1.1.5   root     5332:       while (is_hor_space[(U_CHAR) *prec])
1.1       root     5333:        prec++;
                   5334:       name = prec;
1.1.1.5   root     5335:       while (is_idchar[(U_CHAR) *prec])
1.1       root     5336:        prec++;
                   5337:       len = prec - name;
                   5338:       
1.1.1.8 ! root     5339:       if (lookup ((U_CHAR *) name, len, -1))
1.1       root     5340:        return 0;
                   5341:     } else {
                   5342:       error ("Bad format encountered while reading precompiled file");
                   5343:       return 0;
                   5344:     }
                   5345:     prec = lineend + 1;
                   5346:   }
                   5347:   /* They all passed successfully */
                   5348:   return 1;
                   5349: }
                   5350: 
                   5351: /* Process the main body of a precompiled file.  BUF points to the
                   5352:    string section of the file, following the preconditions.  LIMIT is one
                   5353:    character past the end.  NAME is the name of the file being read
                   5354:    in.  OP is the main output buffer */
                   5355: static void
                   5356: pcfinclude (buf, limit, name, op)
                   5357:      U_CHAR *buf, *limit, *name;
                   5358:      FILE_BUF *op;
                   5359: {
                   5360:   FILE_BUF tmpbuf;
                   5361:   int nstrings;
                   5362:   U_CHAR *cp = buf;
                   5363: 
                   5364:   /* First in the file comes 4 bytes indicating the number of strings, */
                   5365:   /* in network byte order. (MSB first).  */
                   5366:   nstrings = *cp++;
                   5367:   nstrings = (nstrings << 8) | *cp++;
                   5368:   nstrings = (nstrings << 8) | *cp++;
                   5369:   nstrings = (nstrings << 8) | *cp++;
                   5370:   
                   5371:   /* Looping over each string... */
                   5372:   while (nstrings--) {
                   5373:     U_CHAR *string_start;
                   5374:     U_CHAR *endofthiskey;
                   5375:     STRINGDEF *str;
                   5376:     int nkeys;
                   5377:     
                   5378:     /* Each string starts with a STRINGDEF structure (str), followed */
                   5379:     /* by the text of the string (string_start) */
                   5380: 
                   5381:     /* First skip to a longword boundary */
1.1.1.4   root     5382:     /* ??? Why a 4-byte boundary?  On all machines? */
                   5383:     /* NOTE: This works correctly even if HOST_WIDE_INT
                   5384:        is narrower than a pointer.
                   5385:        Do not try risky measures here to get another type to use!
1.1.1.7   root     5386:        Do not include stddef.h--it will fail!  */
1.1.1.4   root     5387:     if ((HOST_WIDE_INT) cp & 3)
                   5388:       cp += 4 - ((HOST_WIDE_INT) cp & 3);
1.1       root     5389:     
                   5390:     /* Now get the string. */
1.1.1.8 ! root     5391:     str = (STRINGDEF *) (GENERIC_PTR) cp;
1.1       root     5392:     string_start = cp += sizeof (STRINGDEF);
                   5393:     
                   5394:     for (; *cp; cp++)          /* skip the string */
                   5395:       ;
                   5396:     
                   5397:     /* We need to macro expand the string here to ensure that the
                   5398:        proper definition environment is in place.  If it were only
                   5399:        expanded when we find out it is needed, macros necessary for
                   5400:        its proper expansion might have had their definitions changed. */
                   5401:     tmpbuf = expand_to_temp_buffer (string_start, cp++, 0, 0);
                   5402:     /* Lineno is already set in the precompiled file */
                   5403:     str->contents = tmpbuf.buf;
                   5404:     str->len = tmpbuf.length;
                   5405:     str->writeflag = 0;
                   5406:     str->filename = name;
                   5407:     str->output_mark = outbuf.bufp - outbuf.buf;
                   5408:     
                   5409:     str->chain = 0;
                   5410:     *stringlist_tailp = str;
                   5411:     stringlist_tailp = &str->chain;
                   5412:     
                   5413:     /* Next comes a fourbyte number indicating the number of keys */
                   5414:     /* for this string. */
                   5415:     nkeys = *cp++;
                   5416:     nkeys = (nkeys << 8) | *cp++;
                   5417:     nkeys = (nkeys << 8) | *cp++;
                   5418:     nkeys = (nkeys << 8) | *cp++;
                   5419: 
                   5420:     /* If this number is -1, then the string is mandatory. */
                   5421:     if (nkeys == -1)
                   5422:       str->writeflag = 1;
                   5423:     else
1.1.1.2   root     5424:       /* Otherwise, for each key, */
1.1       root     5425:       for (; nkeys--; free (tmpbuf.buf), cp = endofthiskey + 1) {
1.1.1.8 ! root     5426:        KEYDEF *kp = (KEYDEF *) (GENERIC_PTR) cp;
1.1       root     5427:        HASHNODE *hp;
                   5428:        
                   5429:        /* It starts with a KEYDEF structure */
                   5430:        cp += sizeof (KEYDEF);
                   5431:        
                   5432:        /* Find the end of the key.  At the end of this for loop we
                   5433:           advance CP to the start of the next key using this variable. */
1.1.1.8 ! root     5434:        endofthiskey = cp + strlen ((char *) cp);
1.1       root     5435:        kp->str = str;
                   5436:        
                   5437:        /* Expand the key, and enter it into the hash table. */
                   5438:        tmpbuf = expand_to_temp_buffer (cp, endofthiskey, 0, 0);
                   5439:        tmpbuf.bufp = tmpbuf.buf;
                   5440:        
                   5441:        while (is_hor_space[*tmpbuf.bufp])
                   5442:          tmpbuf.bufp++;
                   5443:        if (!is_idstart[*tmpbuf.bufp]
                   5444:            || tmpbuf.bufp == tmpbuf.buf + tmpbuf.length) {
                   5445:          str->writeflag = 1;
                   5446:          continue;
                   5447:        }
                   5448:            
                   5449:        hp = lookup (tmpbuf.bufp, -1, -1);
                   5450:        if (hp == NULL) {
                   5451:          kp->chain = 0;
1.1.1.8 ! root     5452:          install (tmpbuf.bufp, -1, T_PCSTRING, (char *) kp, -1);
1.1       root     5453:        }
                   5454:        else if (hp->type == T_PCSTRING) {
                   5455:          kp->chain = hp->value.keydef;
                   5456:          hp->value.keydef = kp;
                   5457:        }
                   5458:        else
                   5459:          str->writeflag = 1;
                   5460:       }
                   5461:   }
1.1.1.8 ! root     5462:   /* This output_line_directive serves to switch us back to the current
1.1       root     5463:      input file in case some of these strings get output (which will 
1.1.1.8 ! root     5464:      result in line directives for the header file being output). */
        !          5465:   output_line_directive (&instack[indepth], op, 0, enter_file);
1.1       root     5466: }
                   5467: 
                   5468: /* Called from rescan when it hits a key for strings.  Mark them all */
                   5469:  /* used and clean up. */
                   5470: static void
                   5471: pcstring_used (hp)
                   5472:      HASHNODE *hp;
                   5473: {
1.1.1.7   root     5474:   KEYDEF *kp;
1.1       root     5475:   
                   5476:   for (kp = hp->value.keydef; kp; kp = kp->chain)
                   5477:     kp->str->writeflag = 1;
                   5478:   delete_macro (hp);
                   5479: }
                   5480: 
                   5481: /* Write the output, interspersing precompiled strings in their */
                   5482:  /* appropriate places. */
                   5483: static void
                   5484: write_output ()
                   5485: {
                   5486:   STRINGDEF *next_string;
                   5487:   U_CHAR *cur_buf_loc;
1.1.1.8 ! root     5488:   int line_directive_len = 80;
        !          5489:   char *line_directive = xmalloc (line_directive_len);
1.1       root     5490:   int len;
                   5491: 
                   5492:   /* In each run through the loop, either cur_buf_loc == */
                   5493:   /* next_string_loc, in which case we print a series of strings, or */
                   5494:   /* it is less than next_string_loc, in which case we write some of */
                   5495:   /* the buffer. */
                   5496:   cur_buf_loc = outbuf.buf; 
                   5497:   next_string = stringlist;
                   5498:   
                   5499:   while (cur_buf_loc < outbuf.bufp || next_string) {
                   5500:     if (next_string
                   5501:        && cur_buf_loc - outbuf.buf == next_string->output_mark) {
                   5502:       if (next_string->writeflag) {
1.1.1.8 ! root     5503:        len = 4 * strlen ((char *) next_string->filename) + 32;
        !          5504:        while (len > line_directive_len)
        !          5505:          line_directive = xrealloc (line_directive, 
        !          5506:                                     line_directive_len *= 2);
        !          5507:        sprintf (line_directive, "\n# %d ", next_string->lineno);
        !          5508:        strcpy (quote_string (line_directive + strlen (line_directive),
        !          5509:                              (char *) next_string->filename),
1.1.1.6   root     5510:                "\n");
1.1.1.8 ! root     5511:        safe_write (fileno (stdout), line_directive, strlen (line_directive));
        !          5512:        safe_write (fileno (stdout),
        !          5513:                    (char *) next_string->contents, next_string->len);
1.1       root     5514:       }              
                   5515:       next_string = next_string->chain;
                   5516:     }
                   5517:     else {
                   5518:       len = (next_string
                   5519:             ? (next_string->output_mark 
                   5520:                - (cur_buf_loc - outbuf.buf))
                   5521:             : outbuf.bufp - cur_buf_loc);
                   5522:       
1.1.1.8 ! root     5523:       safe_write (fileno (stdout), (char *) cur_buf_loc, len);
1.1       root     5524:       cur_buf_loc += len;
                   5525:     }
                   5526:   }
1.1.1.8 ! root     5527:   free (line_directive);
1.1       root     5528: }
                   5529: 
                   5530: /* Pass a directive through to the output file.
1.1.1.2   root     5531:    BUF points to the contents of the directive, as a contiguous string.
1.1       root     5532:    LIMIT points to the first character past the end of the directive.
                   5533:    KEYWORD is the keyword-table entry for the directive.  */
                   5534: 
                   5535: static void
                   5536: pass_thru_directive (buf, limit, op, keyword)
                   5537:      U_CHAR *buf, *limit;
                   5538:      FILE_BUF *op;
                   5539:      struct directive *keyword;
                   5540: {
                   5541:   register unsigned keyword_length = keyword->length;
                   5542: 
                   5543:   check_expand (op, 1 + keyword_length + (limit - buf));
                   5544:   *op->bufp++ = '#';
1.1.1.7   root     5545:   bcopy (keyword->name, (char *) op->bufp, keyword_length);
1.1       root     5546:   op->bufp += keyword_length;
                   5547:   if (limit != buf && buf[0] != ' ')
                   5548:     *op->bufp++ = ' ';
1.1.1.7   root     5549:   bcopy ((char *) buf, (char *) op->bufp, limit - buf);
1.1       root     5550:   op->bufp += (limit - buf);
1.1.1.3   root     5551: #if 0
1.1       root     5552:   *op->bufp++ = '\n';
1.1.1.3   root     5553:   /* Count the line we have just made in the output,
                   5554:      to get in sync properly.  */
                   5555:   op->lineno++;
                   5556: #endif
1.1       root     5557: }
                   5558: 
                   5559: /* The arglist structure is built by do_define to tell
                   5560:    collect_definition where the argument names begin.  That
                   5561:    is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist
                   5562:    would contain pointers to the strings x, y, and z.
                   5563:    Collect_definition would then build a DEFINITION node,
                   5564:    with reflist nodes pointing to the places x, y, and z had
                   5565:    appeared.  So the arglist is just convenience data passed
                   5566:    between these two routines.  It is not kept around after
                   5567:    the current #define has been processed and entered into the
                   5568:    hash table. */
                   5569: 
                   5570: struct arglist {
                   5571:   struct arglist *next;
                   5572:   U_CHAR *name;
                   5573:   int length;
                   5574:   int argno;
1.1.1.3   root     5575:   char rest_args;
1.1       root     5576: };
                   5577: 
                   5578: /* Create a DEFINITION node from a #define directive.  Arguments are 
                   5579:    as for do_define. */
                   5580: static MACRODEF
                   5581: create_definition (buf, limit, op)
                   5582:      U_CHAR *buf, *limit;
                   5583:      FILE_BUF *op;
                   5584: {
                   5585:   U_CHAR *bp;                  /* temp ptr into input buffer */
                   5586:   U_CHAR *symname;             /* remember where symbol name starts */
                   5587:   int sym_length;              /* and how long it is */
                   5588:   int line = instack[indepth].lineno;
                   5589:   char *file = instack[indepth].nominal_fname;
1.1.1.3   root     5590:   int rest_args = 0;
1.1       root     5591: 
                   5592:   DEFINITION *defn;
                   5593:   int arglengths = 0;          /* Accumulate lengths of arg names
                   5594:                                   plus number of args.  */
                   5595:   MACRODEF mdef;
                   5596: 
                   5597:   bp = buf;
                   5598: 
                   5599:   while (is_hor_space[*bp])
                   5600:     bp++;
                   5601: 
                   5602:   symname = bp;                        /* remember where it starts */
                   5603:   sym_length = check_macro_name (bp, "macro");
                   5604:   bp += sym_length;
                   5605: 
                   5606:   /* Lossage will occur if identifiers or control keywords are broken
                   5607:      across lines using backslash.  This is not the right place to take
                   5608:      care of that. */
                   5609: 
                   5610:   if (*bp == '(') {
                   5611:     struct arglist *arg_ptrs = NULL;
                   5612:     int argno = 0;
                   5613: 
                   5614:     bp++;                      /* skip '(' */
                   5615:     SKIP_WHITE_SPACE (bp);
                   5616: 
                   5617:     /* Loop over macro argument names.  */
                   5618:     while (*bp != ')') {
                   5619:       struct arglist *temp;
                   5620: 
                   5621:       temp = (struct arglist *) alloca (sizeof (struct arglist));
                   5622:       temp->name = bp;
                   5623:       temp->next = arg_ptrs;
                   5624:       temp->argno = argno++;
1.1.1.3   root     5625:       temp->rest_args = 0;
1.1       root     5626:       arg_ptrs = temp;
                   5627: 
1.1.1.3   root     5628:       if (rest_args)
                   5629:        pedwarn ("another parameter follows `%s'",
                   5630:                 rest_extension);
1.1       root     5631: 
1.1.1.3   root     5632:       if (!is_idstart[*bp])
                   5633:        pedwarn ("invalid character in macro parameter name");
                   5634:       
1.1       root     5635:       /* Find the end of the arg name.  */
                   5636:       while (is_idchar[*bp]) {
                   5637:        bp++;
1.1.1.3   root     5638:        /* do we have a "special" rest-args extension here? */
                   5639:        if (limit - bp > REST_EXTENSION_LENGTH &&
1.1.1.8 ! root     5640:            bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
1.1.1.3   root     5641:          rest_args = 1;
                   5642:          temp->rest_args = 1;
                   5643:          break;
                   5644:        }
1.1       root     5645:       }
                   5646:       temp->length = bp - temp->name;
1.1.1.3   root     5647:       if (rest_args == 1)
                   5648:        bp += REST_EXTENSION_LENGTH;
1.1       root     5649:       arglengths += temp->length + 2;
                   5650:       SKIP_WHITE_SPACE (bp);
                   5651:       if (temp->length == 0 || (*bp != ',' && *bp != ')')) {
                   5652:        error ("badly punctuated parameter list in `#define'");
                   5653:        goto nope;
                   5654:       }
                   5655:       if (*bp == ',') {
                   5656:        bp++;
                   5657:        SKIP_WHITE_SPACE (bp);
1.1.1.8 ! root     5658:        /* A comma at this point can only be followed by an identifier.  */
        !          5659:        if (!is_idstart[*bp]) {
        !          5660:          error ("badly punctuated parameter list in `#define'");
        !          5661:          goto nope;
        !          5662:        }
1.1       root     5663:       }
                   5664:       if (bp >= limit) {
                   5665:        error ("unterminated parameter list in `#define'");
                   5666:        goto nope;
                   5667:       }
                   5668:       {
                   5669:        struct arglist *otemp;
                   5670: 
                   5671:        for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
                   5672:          if (temp->length == otemp->length &&
1.1.1.8 ! root     5673:              bcmp (temp->name, otemp->name, temp->length) == 0) {
        !          5674:              error ("duplicate argument name `%.*s' in `#define'",
        !          5675:                     temp->length, temp->name);
1.1       root     5676:              goto nope;
                   5677:          }
                   5678:       }
                   5679:     }
                   5680: 
                   5681:     ++bp;                      /* skip paren */
1.1.1.8 ! root     5682:     SKIP_WHITE_SPACE (bp);
1.1       root     5683:     /* now everything from bp before limit is the definition. */
                   5684:     defn = collect_expansion (bp, limit, argno, arg_ptrs);
1.1.1.3   root     5685:     defn->rest_args = rest_args;
1.1       root     5686: 
                   5687:     /* Now set defn->args.argnames to the result of concatenating
                   5688:        the argument names in reverse order
                   5689:        with comma-space between them.  */
                   5690:     defn->args.argnames = (U_CHAR *) xmalloc (arglengths + 1);
                   5691:     {
                   5692:       struct arglist *temp;
                   5693:       int i = 0;
                   5694:       for (temp = arg_ptrs; temp; temp = temp->next) {
                   5695:        bcopy (temp->name, &defn->args.argnames[i], temp->length);
                   5696:        i += temp->length;
                   5697:        if (temp->next != 0) {
                   5698:          defn->args.argnames[i++] = ',';
                   5699:          defn->args.argnames[i++] = ' ';
                   5700:        }
                   5701:       }
                   5702:       defn->args.argnames[i] = 0;
                   5703:     }
                   5704:   } else {
1.1.1.7   root     5705:     /* Simple expansion or empty definition.  */
                   5706: 
                   5707:     if (bp < limit)
                   5708:       {
1.1.1.8 ! root     5709:        if (is_hor_space[*bp]) {
        !          5710:          bp++;
        !          5711:          SKIP_WHITE_SPACE (bp);
        !          5712:        } else {
        !          5713:          switch (*bp) {
1.1.1.7   root     5714:            case '!':  case '"':  case '#':  case '%':  case '&':  case '\'':
                   5715:            case ')':  case '*':  case '+':  case ',':  case '-':  case '.':
                   5716:            case '/':  case ':':  case ';':  case '<':  case '=':  case '>':
                   5717:            case '?':  case '[':  case '\\': case ']':  case '^':  case '{':
                   5718:            case '|':  case '}':  case '~':
                   5719:              warning ("missing white space after `#define %.*s'",
                   5720:                       sym_length, symname);
                   5721:              break;
                   5722: 
                   5723:            default:
                   5724:              pedwarn ("missing white space after `#define %.*s'",
                   5725:                       sym_length, symname);
                   5726:              break;
                   5727:          }
1.1.1.8 ! root     5728:        }
1.1.1.7   root     5729:       }
                   5730:     /* Now everything from bp before limit is the definition. */
1.1.1.4   root     5731:     defn = collect_expansion (bp, limit, -1, NULL_PTR);
1.1       root     5732:     defn->args.argnames = (U_CHAR *) "";
                   5733:   }
                   5734: 
                   5735:   defn->line = line;
                   5736:   defn->file = file;
                   5737: 
                   5738:   /* OP is null if this is a predefinition */
                   5739:   defn->predefined = !op;
                   5740:   mdef.defn = defn;
                   5741:   mdef.symnam = symname;
                   5742:   mdef.symlen = sym_length;
                   5743: 
                   5744:   return mdef;
                   5745: 
                   5746:  nope:
                   5747:   mdef.defn = 0;
                   5748:   return mdef;
                   5749: }
                   5750:  
1.1.1.8 ! root     5751: /* Process a #define directive.
        !          5752: BUF points to the contents of the #define directive, as a contiguous string.
1.1       root     5753: LIMIT points to the first character past the end of the definition.
                   5754: KEYWORD is the keyword-table entry for #define.  */
                   5755: 
                   5756: static int
                   5757: do_define (buf, limit, op, keyword)
                   5758:      U_CHAR *buf, *limit;
                   5759:      FILE_BUF *op;
                   5760:      struct directive *keyword;
                   5761: {
                   5762:   int hashcode;
                   5763:   MACRODEF mdef;
                   5764: 
1.1.1.8 ! root     5765:   /* If this is a precompiler run (with -pcp) pass thru #define directives.  */
1.1       root     5766:   if (pcp_outfile && op)
                   5767:     pass_thru_directive (buf, limit, op, keyword);
                   5768: 
                   5769:   mdef = create_definition (buf, limit, op);
                   5770:   if (mdef.defn == 0)
                   5771:     goto nope;
                   5772: 
                   5773:   hashcode = hashf (mdef.symnam, mdef.symlen, HASHSIZE);
                   5774: 
                   5775:   {
                   5776:     HASHNODE *hp;
                   5777:     if ((hp = lookup (mdef.symnam, mdef.symlen, hashcode)) != NULL) {
                   5778:       int ok = 0;
                   5779:       /* Redefining a precompiled key is ok.  */
                   5780:       if (hp->type == T_PCSTRING)
                   5781:        ok = 1;
                   5782:       /* Redefining a macro is ok if the definitions are the same.  */
                   5783:       else if (hp->type == T_MACRO)
                   5784:        ok = ! compare_defs (mdef.defn, hp->value.defn);
                   5785:       /* Redefining a constant is ok with -D.  */
                   5786:       else if (hp->type == T_CONST)
                   5787:         ok = ! done_initializing;
                   5788:       /* Print the warning if it's not ok.  */
                   5789:       if (!ok) {
                   5790:         /* If we are passing through #define and #undef directives, do
                   5791:           that for this re-definition now.  */
                   5792:         if (debug_output && op)
                   5793:          pass_thru_directive (buf, limit, op, keyword);
                   5794: 
1.1.1.8 ! root     5795:        pedwarn ("`%.*s' redefined", mdef.symlen, mdef.symnam);
1.1       root     5796:        if (hp->type == T_MACRO)
                   5797:          pedwarn_with_file_and_line (hp->value.defn->file, hp->value.defn->line,
                   5798:                                      "this is the location of the previous definition");
                   5799:       }
                   5800:       /* Replace the old definition.  */
                   5801:       hp->type = T_MACRO;
                   5802:       hp->value.defn = mdef.defn;
                   5803:     } else {
                   5804:       /* If we are passing through #define and #undef directives, do
                   5805:         that for this new definition now.  */
                   5806:       if (debug_output && op)
                   5807:        pass_thru_directive (buf, limit, op, keyword);
1.1.1.8 ! root     5808:       install (mdef.symnam, mdef.symlen, T_MACRO,
1.1.1.4   root     5809:               (char *) mdef.defn, hashcode);
1.1       root     5810:     }
                   5811:   }
                   5812: 
                   5813:   return 0;
                   5814: 
                   5815: nope:
                   5816: 
                   5817:   return 1;
                   5818: }
                   5819: 
                   5820: /* Check a purported macro name SYMNAME, and yield its length.
                   5821:    USAGE is the kind of name this is intended for.  */
                   5822: 
                   5823: static int
                   5824: check_macro_name (symname, usage)
                   5825:      U_CHAR *symname;
                   5826:      char *usage;
                   5827: {
                   5828:   U_CHAR *p;
                   5829:   int sym_length;
                   5830: 
                   5831:   for (p = symname; is_idchar[*p]; p++)
                   5832:     ;
                   5833:   sym_length = p - symname;
                   5834:   if (sym_length == 0)
                   5835:     error ("invalid %s name", usage);
1.1.1.8 ! root     5836:   else if (!is_idstart[*symname]
        !          5837:           || (sym_length == 7 && ! bcmp (symname, "defined", 7)))
        !          5838:     error ("invalid %s name `%.*s'", usage, sym_length, symname);
1.1       root     5839:   return sym_length;
                   5840: }
                   5841: 
                   5842: /*
                   5843:  * return zero if two DEFINITIONs are isomorphic
                   5844:  */
                   5845: static int
                   5846: compare_defs (d1, d2)
                   5847:      DEFINITION *d1, *d2;
                   5848: {
                   5849:   register struct reflist *a1, *a2;
                   5850:   register U_CHAR *p1 = d1->expansion;
                   5851:   register U_CHAR *p2 = d2->expansion;
                   5852:   int first = 1;
                   5853: 
                   5854:   if (d1->nargs != d2->nargs)
                   5855:     return 1;
                   5856:   if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
                   5857:     return 1;
                   5858:   for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
                   5859:        a1 = a1->next, a2 = a2->next) {
1.1.1.8 ! root     5860:     if (!((a1->nchars == a2->nchars && ! bcmp (p1, p2, a1->nchars))
1.1       root     5861:          || ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
                   5862:        || a1->argno != a2->argno
                   5863:        || a1->stringify != a2->stringify
                   5864:        || a1->raw_before != a2->raw_before
                   5865:        || a1->raw_after != a2->raw_after)
                   5866:       return 1;
                   5867:     first = 0;
                   5868:     p1 += a1->nchars;
                   5869:     p2 += a2->nchars;
                   5870:   }
                   5871:   if (a1 != a2)
                   5872:     return 1;
                   5873:   if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
                   5874:                     p2, d2->length - (p2 - d2->expansion), 1))
                   5875:     return 1;
                   5876:   return 0;
                   5877: }
                   5878: 
                   5879: /* Return 1 if two parts of two macro definitions are effectively different.
                   5880:    One of the parts starts at BEG1 and has LEN1 chars;
                   5881:    the other has LEN2 chars at BEG2.
                   5882:    Any sequence of whitespace matches any other sequence of whitespace.
                   5883:    FIRST means these parts are the first of a macro definition;
                   5884:     so ignore leading whitespace entirely.
                   5885:    LAST means these parts are the last of a macro definition;
                   5886:     so ignore trailing whitespace entirely.  */
                   5887: 
                   5888: static int
                   5889: comp_def_part (first, beg1, len1, beg2, len2, last)
                   5890:      int first;
                   5891:      U_CHAR *beg1, *beg2;
                   5892:      int len1, len2;
                   5893:      int last;
                   5894: {
                   5895:   register U_CHAR *end1 = beg1 + len1;
                   5896:   register U_CHAR *end2 = beg2 + len2;
                   5897:   if (first) {
                   5898:     while (beg1 != end1 && is_space[*beg1]) beg1++;
                   5899:     while (beg2 != end2 && is_space[*beg2]) beg2++;
                   5900:   }
                   5901:   if (last) {
                   5902:     while (beg1 != end1 && is_space[end1[-1]]) end1--;
                   5903:     while (beg2 != end2 && is_space[end2[-1]]) end2--;
                   5904:   }
                   5905:   while (beg1 != end1 && beg2 != end2) {
                   5906:     if (is_space[*beg1] && is_space[*beg2]) {
                   5907:       while (beg1 != end1 && is_space[*beg1]) beg1++;
                   5908:       while (beg2 != end2 && is_space[*beg2]) beg2++;
                   5909:     } else if (*beg1 == *beg2) {
                   5910:       beg1++; beg2++;
                   5911:     } else break;
                   5912:   }
                   5913:   return (beg1 != end1) || (beg2 != end2);
                   5914: }
                   5915: 
                   5916: /* Read a replacement list for a macro with parameters.
                   5917:    Build the DEFINITION structure.
                   5918:    Reads characters of text starting at BUF until END.
                   5919:    ARGLIST specifies the formal parameters to look for
                   5920:    in the text of the definition; NARGS is the number of args
                   5921:    in that list, or -1 for a macro name that wants no argument list.
                   5922:    MACRONAME is the macro name itself (so we can avoid recursive expansion)
                   5923:    and NAMELEN is its length in characters.
                   5924:    
1.1.1.8 ! root     5925: Note that comments, backslash-newlines, and leading white space
        !          5926: have already been deleted from the argument.  */
1.1       root     5927: 
1.1.1.8 ! root     5928: /* If there is no trailing whitespace, a Newline Space is added at the end
1.1       root     5929:    to prevent concatenation that would be contrary to the standard.  */
                   5930: 
                   5931: static DEFINITION *
                   5932: collect_expansion (buf, end, nargs, arglist)
                   5933:      U_CHAR *buf, *end;
                   5934:      int nargs;
                   5935:      struct arglist *arglist;
                   5936: {
                   5937:   DEFINITION *defn;
                   5938:   register U_CHAR *p, *limit, *lastp, *exp_p;
                   5939:   struct reflist *endpat = NULL;
                   5940:   /* Pointer to first nonspace after last ## seen.  */
                   5941:   U_CHAR *concat = 0;
                   5942:   /* Pointer to first nonspace after last single-# seen.  */
                   5943:   U_CHAR *stringify = 0;
1.1.1.8 ! root     5944:   /* How those tokens were spelled.  */
        !          5945:   enum sharp_token_type concat_sharp_token_type = NO_SHARP_TOKEN;
        !          5946:   enum sharp_token_type stringify_sharp_token_type = NO_SHARP_TOKEN;
1.1       root     5947:   int maxsize;
                   5948:   int expected_delimiter = '\0';
                   5949: 
                   5950:   /* Scan thru the replacement list, ignoring comments and quoted
                   5951:      strings, picking up on the macro calls.  It does a linear search
                   5952:      thru the arg list on every potential symbol.  Profiling might say
                   5953:      that something smarter should happen. */
                   5954: 
                   5955:   if (end < buf)
                   5956:     abort ();
                   5957: 
                   5958:   /* Find the beginning of the trailing whitespace.  */
                   5959:   limit = end;
                   5960:   p = buf;
                   5961:   while (p < limit && is_space[limit[-1]]) limit--;
                   5962: 
                   5963:   /* Allocate space for the text in the macro definition.
1.1.1.8 ! root     5964:      Each input char may or may not need 1 byte,
1.1       root     5965:      so this is an upper bound.
1.1.1.8 ! root     5966:      The extra 3 are for invented trailing newline-marker and final null.  */
1.1       root     5967:   maxsize = (sizeof (DEFINITION)
                   5968:             + (limit - p) + 3);
                   5969:   defn = (DEFINITION *) xcalloc (1, maxsize);
                   5970: 
                   5971:   defn->nargs = nargs;
                   5972:   exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION);
                   5973:   lastp = exp_p;
                   5974: 
1.1.1.8 ! root     5975:   if (p[0] == '#'
        !          5976:       ? p[1] == '#'
        !          5977:       : p[0] == '%' && p[1] == ':' && p[2] == '%' && p[3] == ':') {
1.1       root     5978:     error ("`##' at start of macro definition");
1.1.1.8 ! root     5979:     p += p[0] == '#' ? 2 : 4;
1.1       root     5980:   }
                   5981: 
                   5982:   /* Process the main body of the definition.  */
                   5983:   while (p < limit) {
                   5984:     int skipped_arg = 0;
                   5985:     register U_CHAR c = *p++;
                   5986: 
                   5987:     *exp_p++ = c;
                   5988: 
                   5989:     if (!traditional) {
                   5990:       switch (c) {
                   5991:       case '\'':
                   5992:       case '\"':
                   5993:         if (expected_delimiter != '\0') {
                   5994:           if (c == expected_delimiter)
                   5995:             expected_delimiter = '\0';
                   5996:         } else
                   5997:           expected_delimiter = c;
                   5998:        break;
                   5999: 
                   6000:       case '\\':
1.1.1.7   root     6001:        if (p < limit && expected_delimiter) {
1.1       root     6002:          /* In a string, backslash goes through
                   6003:             and makes next char ordinary.  */
                   6004:          *exp_p++ = *p++;
                   6005:        }
                   6006:        break;
                   6007: 
1.1.1.8 ! root     6008:       case '%':
        !          6009:        if (!expected_delimiter && *p == ':') {
        !          6010:          /* %: is not a digraph if preceded by an odd number of '<'s.  */
        !          6011:          U_CHAR *p0 = p - 1;
        !          6012:          while (buf < p0 && p0[-1] == '<')
        !          6013:            p0--;
        !          6014:          if ((p - p0) & 1) {
        !          6015:            /* Treat %:%: as ## and %: as #.  */
        !          6016:            if (p[1] == '%' && p[2] == ':') {
        !          6017:              p += 2;
        !          6018:              goto sharp_sharp_token;
        !          6019:            }
        !          6020:            if (nargs >= 0) {
        !          6021:              p++;
        !          6022:              goto sharp_token;
        !          6023:            }
        !          6024:          }
        !          6025:        }
        !          6026:        break;
        !          6027: 
1.1       root     6028:       case '#':
                   6029:        /* # is ordinary inside a string.  */
                   6030:        if (expected_delimiter)
                   6031:          break;
1.1.1.8 ! root     6032:        if (*p == '#') {
        !          6033:        sharp_sharp_token:
1.1       root     6034:          /* ##: concatenate preceding and following tokens.  */
                   6035:          /* Take out the first #, discard preceding whitespace.  */
                   6036:          exp_p--;
                   6037:          while (exp_p > lastp && is_hor_space[exp_p[-1]])
                   6038:            --exp_p;
                   6039:          /* Skip the second #.  */
                   6040:          p++;
1.1.1.8 ! root     6041:          concat_sharp_token_type = c;
        !          6042:          if (is_hor_space[*p]) {
        !          6043:            concat_sharp_token_type = c + 1;
        !          6044:            p++;
        !          6045:            SKIP_WHITE_SPACE (p);
        !          6046:          }
1.1       root     6047:          concat = p;
                   6048:          if (p == limit)
                   6049:            error ("`##' at end of macro definition");
1.1.1.5   root     6050:        } else if (nargs >= 0) {
1.1       root     6051:          /* Single #: stringify following argument ref.
                   6052:             Don't leave the # in the expansion.  */
1.1.1.8 ! root     6053:        sharp_token:
1.1       root     6054:          exp_p--;
1.1.1.8 ! root     6055:          stringify_sharp_token_type = c;
        !          6056:          if (is_hor_space[*p]) {
        !          6057:            stringify_sharp_token_type = c + 1;
        !          6058:            p++;
        !          6059:            SKIP_WHITE_SPACE (p);
        !          6060:          }
        !          6061:          if (! is_idstart[*p] || nargs == 0)
1.1       root     6062:            error ("`#' operator is not followed by a macro argument name");
                   6063:          else
                   6064:            stringify = p;
                   6065:        }
                   6066:        break;
                   6067:       }
                   6068:     } else {
                   6069:       /* In -traditional mode, recognize arguments inside strings and
                   6070:         and character constants, and ignore special properties of #.
                   6071:         Arguments inside strings are considered "stringified", but no
                   6072:         extra quote marks are supplied.  */
                   6073:       switch (c) {
                   6074:       case '\'':
                   6075:       case '\"':
                   6076:        if (expected_delimiter != '\0') {
                   6077:          if (c == expected_delimiter)
                   6078:            expected_delimiter = '\0';
                   6079:        } else
                   6080:          expected_delimiter = c;
                   6081:        break;
                   6082: 
                   6083:       case '\\':
                   6084:        /* Backslash quotes delimiters and itself, but not macro args.  */
                   6085:        if (expected_delimiter != 0 && p < limit
                   6086:            && (*p == expected_delimiter || *p == '\\')) {
                   6087:          *exp_p++ = *p++;
                   6088:          continue;
                   6089:        }
                   6090:        break;
                   6091: 
                   6092:       case '/':
                   6093:        if (expected_delimiter != '\0') /* No comments inside strings.  */
                   6094:          break;
                   6095:        if (*p == '*') {
                   6096:          /* If we find a comment that wasn't removed by handle_directive,
                   6097:             this must be -traditional.  So replace the comment with
                   6098:             nothing at all.  */
                   6099:          exp_p--;
                   6100:          p += 1;
                   6101:          while (p < limit && !(p[-2] == '*' && p[-1] == '/'))
                   6102:            p++;
                   6103: #if 0
                   6104:          /* Mark this as a concatenation-point, as if it had been ##.  */
                   6105:          concat = p;
                   6106: #endif
                   6107:        }
                   6108:        break;
                   6109:       }
                   6110:     }
                   6111: 
                   6112:     /* Handle the start of a symbol.  */
                   6113:     if (is_idchar[c] && nargs > 0) {
                   6114:       U_CHAR *id_beg = p - 1;
                   6115:       int id_len;
                   6116: 
                   6117:       --exp_p;
                   6118:       while (p != limit && is_idchar[*p]) p++;
                   6119:       id_len = p - id_beg;
                   6120: 
                   6121:       if (is_idstart[c]) {
                   6122:        register struct arglist *arg;
                   6123: 
                   6124:        for (arg = arglist; arg != NULL; arg = arg->next) {
                   6125:          struct reflist *tpat;
                   6126: 
                   6127:          if (arg->name[0] == c
                   6128:              && arg->length == id_len
1.1.1.8 ! root     6129:              && bcmp (arg->name, id_beg, id_len) == 0) {
        !          6130:            enum sharp_token_type tpat_stringify;
        !          6131:            if (expected_delimiter) {
        !          6132:              if (warn_stringify) {
        !          6133:                if (traditional) {
        !          6134:                  warning ("macro argument `%.*s' is stringified.",
        !          6135:                           id_len, arg->name);
        !          6136:                } else {
        !          6137:                  warning ("macro arg `%.*s' would be stringified with -traditional.",
        !          6138:                           id_len, arg->name);
        !          6139:                }
1.1       root     6140:              }
1.1.1.8 ! root     6141:              /* If ANSI, don't actually substitute inside a string.  */
        !          6142:              if (!traditional)
        !          6143:                break;
        !          6144:              tpat_stringify = SHARP_TOKEN;
        !          6145:            } else {
        !          6146:              tpat_stringify
        !          6147:                = (stringify == id_beg
        !          6148:                   ? stringify_sharp_token_type : NO_SHARP_TOKEN);
1.1       root     6149:            }
                   6150:            /* make a pat node for this arg and append it to the end of
                   6151:               the pat list */
                   6152:            tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
                   6153:            tpat->next = NULL;
1.1.1.8 ! root     6154:            tpat->raw_before
        !          6155:              = concat == id_beg ? concat_sharp_token_type : NO_SHARP_TOKEN;
        !          6156:            tpat->raw_after = NO_SHARP_TOKEN;
1.1.1.3   root     6157:            tpat->rest_args = arg->rest_args;
1.1.1.8 ! root     6158:            tpat->stringify = tpat_stringify;
1.1       root     6159: 
                   6160:            if (endpat == NULL)
                   6161:              defn->pattern = tpat;
                   6162:            else
                   6163:              endpat->next = tpat;
                   6164:            endpat = tpat;
                   6165: 
                   6166:            tpat->argno = arg->argno;
                   6167:            tpat->nchars = exp_p - lastp;
                   6168:            {
                   6169:              register U_CHAR *p1 = p;
                   6170:              SKIP_WHITE_SPACE (p1);
1.1.1.8 ! root     6171:              if (p1[0]=='#'
        !          6172:                  ? p1[1]=='#'
        !          6173:                  : p1[0]=='%' && p1[1]==':' && p1[2]=='%' && p1[3]==':')
        !          6174:                tpat->raw_after = p1[0] + (p != p1);
1.1       root     6175:            }
                   6176:            lastp = exp_p;      /* place to start copying from next time */
                   6177:            skipped_arg = 1;
                   6178:            break;
                   6179:          }
                   6180:        }
                   6181:       }
                   6182: 
                   6183:       /* If this was not a macro arg, copy it into the expansion.  */
                   6184:       if (! skipped_arg) {
                   6185:        register U_CHAR *lim1 = p;
                   6186:        p = id_beg;
                   6187:        while (p != lim1)
                   6188:          *exp_p++ = *p++;
                   6189:        if (stringify == id_beg)
                   6190:          error ("`#' operator should be followed by a macro argument name");
                   6191:       }
                   6192:     }
                   6193:   }
                   6194: 
1.1.1.7   root     6195:   if (!traditional && expected_delimiter == 0) {
1.1.1.8 ! root     6196:     /* If ANSI, put in a newline-space marker to prevent token pasting.
        !          6197:        But not if "inside a string" (which in ANSI mode happens only for
        !          6198:        -D option).  */
1.1       root     6199:     *exp_p++ = '\n';
                   6200:     *exp_p++ = ' ';
                   6201:   }
                   6202: 
                   6203:   *exp_p = '\0';
                   6204: 
                   6205:   defn->length = exp_p - defn->expansion;
                   6206: 
                   6207:   /* Crash now if we overrun the allocated size.  */
                   6208:   if (defn->length + 1 > maxsize)
                   6209:     abort ();
                   6210: 
                   6211: #if 0
                   6212: /* This isn't worth the time it takes.  */
                   6213:   /* give back excess storage */
                   6214:   defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1);
                   6215: #endif
                   6216: 
                   6217:   return defn;
                   6218: }
                   6219: 
                   6220: static int
                   6221: do_assert (buf, limit, op, keyword)
                   6222:      U_CHAR *buf, *limit;
                   6223:      FILE_BUF *op;
                   6224:      struct directive *keyword;
                   6225: {
                   6226:   U_CHAR *bp;                  /* temp ptr into input buffer */
                   6227:   U_CHAR *symname;             /* remember where symbol name starts */
                   6228:   int sym_length;              /* and how long it is */
                   6229:   struct arglist *tokens = NULL;
                   6230: 
                   6231:   if (pedantic && done_initializing && !instack[indepth].system_header_p)
                   6232:     pedwarn ("ANSI C does not allow `#assert'");
                   6233: 
                   6234:   bp = buf;
                   6235: 
                   6236:   while (is_hor_space[*bp])
                   6237:     bp++;
                   6238: 
                   6239:   symname = bp;                        /* remember where it starts */
                   6240:   sym_length = check_macro_name (bp, "assertion");
                   6241:   bp += sym_length;
                   6242:   /* #define doesn't do this, but we should.  */
                   6243:   SKIP_WHITE_SPACE (bp);
                   6244: 
                   6245:   /* Lossage will occur if identifiers or control tokens are broken
                   6246:      across lines using backslash.  This is not the right place to take
                   6247:      care of that. */
                   6248: 
                   6249:   if (*bp != '(') {
                   6250:     error ("missing token-sequence in `#assert'");
                   6251:     return 1;
                   6252:   }
                   6253: 
                   6254:   {
                   6255:     int error_flag = 0;
                   6256: 
                   6257:     bp++;                      /* skip '(' */
                   6258:     SKIP_WHITE_SPACE (bp);
                   6259: 
                   6260:     tokens = read_token_list (&bp, limit, &error_flag);
                   6261:     if (error_flag)
                   6262:       return 1;
                   6263:     if (tokens == 0) {
                   6264:       error ("empty token-sequence in `#assert'");
                   6265:       return 1;
                   6266:     }
                   6267: 
                   6268:     ++bp;                      /* skip paren */
                   6269:     SKIP_WHITE_SPACE (bp);
                   6270:   }
                   6271: 
                   6272:   /* If this name isn't already an assertion name, make it one.
                   6273:      Error if it was already in use in some other way.  */
                   6274: 
                   6275:   {
                   6276:     ASSERTION_HASHNODE *hp;
                   6277:     int hashcode = hashf (symname, sym_length, ASSERTION_HASHSIZE);
                   6278:     struct tokenlist_list *value
                   6279:       = (struct tokenlist_list *) xmalloc (sizeof (struct tokenlist_list));
                   6280: 
                   6281:     hp = assertion_lookup (symname, sym_length, hashcode);
                   6282:     if (hp == NULL) {
1.1.1.8 ! root     6283:       if (sym_length == 7 && ! bcmp (symname, "defined", 7))
1.1       root     6284:        error ("`defined' redefined as assertion");
                   6285:       hp = assertion_install (symname, sym_length, hashcode);
                   6286:     }
                   6287: 
                   6288:     /* Add the spec'd token-sequence to the list of such.  */
                   6289:     value->tokens = tokens;
                   6290:     value->next = hp->value;
                   6291:     hp->value = value;
                   6292:   }
                   6293: 
                   6294:   return 0;
                   6295: }
                   6296: 
                   6297: static int
                   6298: do_unassert (buf, limit, op, keyword)
                   6299:      U_CHAR *buf, *limit;
                   6300:      FILE_BUF *op;
                   6301:      struct directive *keyword;
                   6302: {
                   6303:   U_CHAR *bp;                  /* temp ptr into input buffer */
                   6304:   U_CHAR *symname;             /* remember where symbol name starts */
                   6305:   int sym_length;              /* and how long it is */
                   6306: 
                   6307:   struct arglist *tokens = NULL;
                   6308:   int tokens_specified = 0;
                   6309: 
                   6310:   if (pedantic && done_initializing && !instack[indepth].system_header_p)
                   6311:     pedwarn ("ANSI C does not allow `#unassert'");
                   6312: 
                   6313:   bp = buf;
                   6314: 
                   6315:   while (is_hor_space[*bp])
                   6316:     bp++;
                   6317: 
                   6318:   symname = bp;                        /* remember where it starts */
                   6319:   sym_length = check_macro_name (bp, "assertion");
                   6320:   bp += sym_length;
                   6321:   /* #define doesn't do this, but we should.  */
                   6322:   SKIP_WHITE_SPACE (bp);
                   6323: 
                   6324:   /* Lossage will occur if identifiers or control tokens are broken
                   6325:      across lines using backslash.  This is not the right place to take
                   6326:      care of that. */
                   6327: 
                   6328:   if (*bp == '(') {
                   6329:     int error_flag = 0;
                   6330: 
                   6331:     bp++;                      /* skip '(' */
                   6332:     SKIP_WHITE_SPACE (bp);
                   6333: 
                   6334:     tokens = read_token_list (&bp, limit, &error_flag);
                   6335:     if (error_flag)
                   6336:       return 1;
                   6337:     if (tokens == 0) {
                   6338:       error ("empty token list in `#unassert'");
                   6339:       return 1;
                   6340:     }
                   6341: 
                   6342:     tokens_specified = 1;
                   6343: 
                   6344:     ++bp;                      /* skip paren */
                   6345:     SKIP_WHITE_SPACE (bp);
                   6346:   }
                   6347: 
                   6348:   {
                   6349:     ASSERTION_HASHNODE *hp;
                   6350:     int hashcode = hashf (symname, sym_length, ASSERTION_HASHSIZE);
                   6351:     struct tokenlist_list *tail, *prev;
                   6352: 
                   6353:     hp = assertion_lookup (symname, sym_length, hashcode);
                   6354:     if (hp == NULL)
                   6355:       return 1;
                   6356: 
                   6357:     /* If no token list was specified, then eliminate this assertion
                   6358:        entirely.  */
                   6359:     if (! tokens_specified) {
                   6360:       struct tokenlist_list *next;
                   6361:       for (tail = hp->value; tail; tail = next) {
                   6362:        next = tail->next;
                   6363:        free_token_list (tail->tokens);
                   6364:        free (tail);
                   6365:       }
                   6366:       delete_assertion (hp);
                   6367:     } else {
                   6368:       /* If a list of tokens was given, then delete any matching list.  */
                   6369: 
                   6370:       tail = hp->value;
                   6371:       prev = 0;
                   6372:       while (tail) {
                   6373:        struct tokenlist_list *next = tail->next;
                   6374:        if (compare_token_lists (tail->tokens, tokens)) {
                   6375:          if (prev)
                   6376:            prev->next = next;
                   6377:          else
                   6378:            hp->value = tail->next;
                   6379:          free_token_list (tail->tokens);
                   6380:          free (tail);
                   6381:        } else {
                   6382:          prev = tail;
                   6383:        }
                   6384:        tail = next;
                   6385:       }
                   6386:     }
                   6387:   }
                   6388: 
                   6389:   return 0;
                   6390: }
                   6391: 
                   6392: /* Test whether there is an assertion named NAME
                   6393:    and optionally whether it has an asserted token list TOKENS.
                   6394:    NAME is not null terminated; its length is SYM_LENGTH.
                   6395:    If TOKENS_SPECIFIED is 0, then don't check for any token list.  */
                   6396: 
                   6397: int
                   6398: check_assertion (name, sym_length, tokens_specified, tokens)
                   6399:      U_CHAR *name;
                   6400:      int sym_length;
                   6401:      int tokens_specified;
                   6402:      struct arglist *tokens;
                   6403: {
                   6404:   ASSERTION_HASHNODE *hp;
                   6405:   int hashcode = hashf (name, sym_length, ASSERTION_HASHSIZE);
                   6406: 
                   6407:   if (pedantic && !instack[indepth].system_header_p)
                   6408:     pedwarn ("ANSI C does not allow testing assertions");
                   6409: 
                   6410:   hp = assertion_lookup (name, sym_length, hashcode);
                   6411:   if (hp == NULL)
                   6412:     /* It is not an assertion; just return false.  */
                   6413:     return 0;
                   6414: 
                   6415:   /* If no token list was specified, then value is 1.  */
                   6416:   if (! tokens_specified)
                   6417:     return 1;
                   6418: 
                   6419:   {
                   6420:     struct tokenlist_list *tail;
                   6421: 
                   6422:     tail = hp->value;
                   6423: 
                   6424:     /* If a list of tokens was given,
                   6425:        then succeed if the assertion records a matching list.  */
                   6426: 
                   6427:     while (tail) {
                   6428:       if (compare_token_lists (tail->tokens, tokens))
                   6429:        return 1;
                   6430:       tail = tail->next;
                   6431:     }
                   6432: 
                   6433:     /* Fail if the assertion has no matching list.  */
                   6434:     return 0;
                   6435:   }
                   6436: }
                   6437: 
                   6438: /* Compare two lists of tokens for equality including order of tokens.  */
                   6439: 
                   6440: static int
                   6441: compare_token_lists (l1, l2)
                   6442:      struct arglist *l1, *l2;
                   6443: {
                   6444:   while (l1 && l2) {
                   6445:     if (l1->length != l2->length)
                   6446:       return 0;
1.1.1.8 ! root     6447:     if (bcmp (l1->name, l2->name, l1->length))
1.1       root     6448:       return 0;
                   6449:     l1 = l1->next;
                   6450:     l2 = l2->next;
                   6451:   }
                   6452: 
                   6453:   /* Succeed if both lists end at the same time.  */
                   6454:   return l1 == l2;
                   6455: }
                   6456: 
                   6457: /* Read a space-separated list of tokens ending in a close parenthesis.
                   6458:    Return a list of strings, in the order they were written.
                   6459:    (In case of error, return 0 and store -1 in *ERROR_FLAG.)
                   6460:    Parse the text starting at *BPP, and update *BPP.
                   6461:    Don't parse beyond LIMIT.  */
                   6462: 
                   6463: static struct arglist *
                   6464: read_token_list (bpp, limit, error_flag)
                   6465:      U_CHAR **bpp;
                   6466:      U_CHAR *limit;
                   6467:      int *error_flag;
                   6468: {
                   6469:   struct arglist *token_ptrs = 0;
                   6470:   U_CHAR *bp = *bpp;
                   6471:   int depth = 1;
                   6472: 
                   6473:   *error_flag = 0;
                   6474: 
                   6475:   /* Loop over the assertion value tokens.  */
                   6476:   while (depth > 0) {
                   6477:     struct arglist *temp;
                   6478:     int eofp = 0;
                   6479:     U_CHAR *beg = bp;
                   6480: 
                   6481:     /* Find the end of the token.  */
                   6482:     if (*bp == '(') {
                   6483:       bp++;
                   6484:       depth++;
                   6485:     } else if (*bp == ')') {
                   6486:       depth--;
                   6487:       if (depth == 0)
                   6488:        break;
                   6489:       bp++;
                   6490:     } else if (*bp == '"' || *bp == '\'')
1.1.1.4   root     6491:       bp = skip_quoted_string (bp, limit, 0, NULL_PTR, NULL_PTR, &eofp);
1.1       root     6492:     else
                   6493:       while (! is_hor_space[*bp] && *bp != '(' && *bp != ')'
                   6494:             && *bp != '"' && *bp != '\'' && bp != limit)
                   6495:        bp++;
                   6496: 
                   6497:     temp = (struct arglist *) xmalloc (sizeof (struct arglist));
                   6498:     temp->name = (U_CHAR *) xmalloc (bp - beg + 1);
1.1.1.7   root     6499:     bcopy ((char *) beg, (char *) temp->name, bp - beg);
1.1       root     6500:     temp->name[bp - beg] = 0;
                   6501:     temp->next = token_ptrs;
                   6502:     token_ptrs = temp;
                   6503:     temp->length = bp - beg;
                   6504: 
                   6505:     SKIP_WHITE_SPACE (bp);
                   6506: 
                   6507:     if (bp >= limit) {
                   6508:       error ("unterminated token sequence in `#assert' or `#unassert'");
                   6509:       *error_flag = -1;
                   6510:       return 0;
                   6511:     }
                   6512:   }
                   6513:   *bpp = bp;
                   6514: 
                   6515:   /* We accumulated the names in reverse order.
                   6516:      Now reverse them to get the proper order.  */
                   6517:   {
                   6518:     register struct arglist *prev = 0, *this, *next;
                   6519:     for (this = token_ptrs; this; this = next) {
                   6520:       next = this->next;
                   6521:       this->next = prev;
                   6522:       prev = this;
                   6523:     }
                   6524:     return prev;
                   6525:   }
                   6526: }
                   6527: 
                   6528: static void
                   6529: free_token_list (tokens)
                   6530:      struct arglist *tokens;
                   6531: {
                   6532:   while (tokens) {
                   6533:     struct arglist *next = tokens->next;
                   6534:     free (tokens->name);
                   6535:     free (tokens);
                   6536:     tokens = next;
                   6537:   }
                   6538: }
                   6539: 
                   6540: /*
                   6541:  * Install a name in the assertion hash table.
                   6542:  *
                   6543:  * If LEN is >= 0, it is the length of the name.
                   6544:  * Otherwise, compute the length by scanning the entire name.
                   6545:  *
                   6546:  * If HASH is >= 0, it is the precomputed hash code.
                   6547:  * Otherwise, compute the hash code.
                   6548:  */
                   6549: static ASSERTION_HASHNODE *
                   6550: assertion_install (name, len, hash)
                   6551:      U_CHAR *name;
                   6552:      int len;
                   6553:      int hash;
                   6554: {
                   6555:   register ASSERTION_HASHNODE *hp;
                   6556:   register int i, bucket;
                   6557:   register U_CHAR *p, *q;
                   6558: 
                   6559:   i = sizeof (ASSERTION_HASHNODE) + len + 1;
                   6560:   hp = (ASSERTION_HASHNODE *) xmalloc (i);
                   6561:   bucket = hash;
                   6562:   hp->bucket_hdr = &assertion_hashtab[bucket];
                   6563:   hp->next = assertion_hashtab[bucket];
                   6564:   assertion_hashtab[bucket] = hp;
                   6565:   hp->prev = NULL;
                   6566:   if (hp->next != NULL)
                   6567:     hp->next->prev = hp;
                   6568:   hp->length = len;
                   6569:   hp->value = 0;
                   6570:   hp->name = ((U_CHAR *) hp) + sizeof (ASSERTION_HASHNODE);
                   6571:   p = hp->name;
                   6572:   q = name;
                   6573:   for (i = 0; i < len; i++)
                   6574:     *p++ = *q++;
                   6575:   hp->name[len] = 0;
                   6576:   return hp;
                   6577: }
                   6578: 
                   6579: /*
                   6580:  * find the most recent hash node for name name (ending with first
                   6581:  * non-identifier char) installed by install
                   6582:  *
                   6583:  * If LEN is >= 0, it is the length of the name.
                   6584:  * Otherwise, compute the length by scanning the entire name.
                   6585:  *
                   6586:  * If HASH is >= 0, it is the precomputed hash code.
                   6587:  * Otherwise, compute the hash code.
                   6588:  */
                   6589: static ASSERTION_HASHNODE *
                   6590: assertion_lookup (name, len, hash)
                   6591:      U_CHAR *name;
                   6592:      int len;
                   6593:      int hash;
                   6594: {
                   6595:   register ASSERTION_HASHNODE *bucket;
                   6596: 
                   6597:   bucket = assertion_hashtab[hash];
                   6598:   while (bucket) {
1.1.1.8 ! root     6599:     if (bucket->length == len && bcmp (bucket->name, name, len) == 0)
1.1       root     6600:       return bucket;
                   6601:     bucket = bucket->next;
                   6602:   }
                   6603:   return NULL;
                   6604: }
                   6605: 
                   6606: static void
                   6607: delete_assertion (hp)
                   6608:      ASSERTION_HASHNODE *hp;
                   6609: {
                   6610: 
                   6611:   if (hp->prev != NULL)
                   6612:     hp->prev->next = hp->next;
                   6613:   if (hp->next != NULL)
                   6614:     hp->next->prev = hp->prev;
                   6615: 
                   6616:   /* make sure that the bucket chain header that
                   6617:      the deleted guy was on points to the right thing afterwards. */
                   6618:   if (hp == *hp->bucket_hdr)
                   6619:     *hp->bucket_hdr = hp->next;
                   6620: 
                   6621:   free (hp);
                   6622: }
                   6623: 
                   6624: /*
1.1.1.8 ! root     6625:  * interpret #line directive.  Remembers previously seen fnames
1.1       root     6626:  * in its very own hash table.
                   6627:  */
                   6628: #define FNAME_HASHSIZE 37
                   6629: 
                   6630: static int
                   6631: do_line (buf, limit, op, keyword)
                   6632:      U_CHAR *buf, *limit;
                   6633:      FILE_BUF *op;
                   6634:      struct directive *keyword;
                   6635: {
                   6636:   register U_CHAR *bp;
                   6637:   FILE_BUF *ip = &instack[indepth];
                   6638:   FILE_BUF tem;
                   6639:   int new_lineno;
                   6640:   enum file_change_code file_change = same_file;
                   6641: 
                   6642:   /* Expand any macros.  */
                   6643:   tem = expand_to_temp_buffer (buf, limit, 0, 0);
                   6644: 
                   6645:   /* Point to macroexpanded line, which is null-terminated now.  */
                   6646:   bp = tem.buf;
                   6647:   SKIP_WHITE_SPACE (bp);
                   6648: 
                   6649:   if (!isdigit (*bp)) {
1.1.1.8 ! root     6650:     error ("invalid format `#line' directive");
1.1       root     6651:     return 0;
                   6652:   }
                   6653: 
                   6654:   /* The Newline at the end of this line remains to be processed.
                   6655:      To put the next line at the specified line number,
                   6656:      we must store a line number now that is one less.  */
1.1.1.8 ! root     6657:   new_lineno = atoi ((char *) bp) - 1;
1.1       root     6658: 
1.1.1.5   root     6659:   /* NEW_LINENO is one less than the actual line number here.  */
                   6660:   if (pedantic && new_lineno < 0)
1.1.1.8 ! root     6661:     pedwarn ("line number out of range in `#line' directive");
1.1.1.5   root     6662: 
1.1       root     6663:   /* skip over the line number.  */
                   6664:   while (isdigit (*bp))
                   6665:     bp++;
                   6666: 
                   6667: #if 0 /* #line 10"foo.c" is supposed to be allowed.  */
                   6668:   if (*bp && !is_space[*bp]) {
1.1.1.8 ! root     6669:     error ("invalid format `#line' directive");
1.1       root     6670:     return;
                   6671:   }
                   6672: #endif
                   6673: 
                   6674:   SKIP_WHITE_SPACE (bp);
                   6675: 
                   6676:   if (*bp == '\"') {
                   6677:     static HASHNODE *fname_table[FNAME_HASHSIZE];
                   6678:     HASHNODE *hp, **hash_bucket;
1.1.1.6   root     6679:     U_CHAR *fname, *p;
1.1       root     6680:     int fname_length;
                   6681: 
                   6682:     fname = ++bp;
                   6683: 
1.1.1.6   root     6684:     /* Turn the file name, which is a character string literal,
                   6685:        into a null-terminated string.  Do this in place.  */
                   6686:     p = bp;
                   6687:     for (;;)
                   6688:       switch ((*p++ = *bp++)) {
                   6689:       case '\0':
1.1.1.8 ! root     6690:        error ("invalid format `#line' directive");
1.1.1.6   root     6691:        return 0;
1.1       root     6692: 
1.1.1.6   root     6693:       case '\\':
                   6694:        {
                   6695:          char *bpc = (char *) bp;
                   6696:          int c = parse_escape (&bpc);
                   6697:          bp = (U_CHAR *) bpc;
                   6698:          if (c < 0)
                   6699:            p--;
                   6700:          else
                   6701:            p[-1] = c;
                   6702:        }
                   6703:        break;
                   6704: 
                   6705:       case '\"':
                   6706:        p[-1] = 0;
                   6707:        goto fname_done;
                   6708:       }
                   6709:   fname_done:
                   6710:     fname_length = p - fname;
1.1       root     6711: 
                   6712:     SKIP_WHITE_SPACE (bp);
                   6713:     if (*bp) {
1.1.1.5   root     6714:       if (pedantic)
1.1.1.8 ! root     6715:        pedwarn ("garbage at end of `#line' directive");
1.1       root     6716:       if (*bp == '1')
                   6717:        file_change = enter_file;
                   6718:       else if (*bp == '2')
                   6719:        file_change = leave_file;
1.1.1.2   root     6720:       else if (*bp == '3')
                   6721:        ip->system_header_p = 1;
1.1.1.6   root     6722:       else if (*bp == '4')
                   6723:        ip->system_header_p = 2;
1.1       root     6724:       else {
1.1.1.8 ! root     6725:        error ("invalid format `#line' directive");
1.1       root     6726:        return 0;
                   6727:       }
                   6728: 
                   6729:       bp++;
                   6730:       SKIP_WHITE_SPACE (bp);
1.1.1.2   root     6731:       if (*bp == '3') {
                   6732:        ip->system_header_p = 1;
                   6733:        bp++;
                   6734:        SKIP_WHITE_SPACE (bp);
                   6735:       }
1.1.1.6   root     6736:       if (*bp == '4') {
                   6737:        ip->system_header_p = 2;
                   6738:        bp++;
                   6739:        SKIP_WHITE_SPACE (bp);
                   6740:       }
1.1       root     6741:       if (*bp) {
1.1.1.8 ! root     6742:        error ("invalid format `#line' directive");
1.1       root     6743:        return 0;
                   6744:       }
                   6745:     }
                   6746: 
                   6747:     hash_bucket =
                   6748:       &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
                   6749:     for (hp = *hash_bucket; hp != NULL; hp = hp->next)
                   6750:       if (hp->length == fname_length &&
1.1.1.8 ! root     6751:          bcmp (hp->value.cpval, fname, fname_length) == 0) {
1.1       root     6752:        ip->nominal_fname = hp->value.cpval;
                   6753:        break;
                   6754:       }
                   6755:     if (hp == 0) {
                   6756:       /* Didn't find it; cons up a new one.  */
                   6757:       hp = (HASHNODE *) xcalloc (1, sizeof (HASHNODE) + fname_length + 1);
                   6758:       hp->next = *hash_bucket;
                   6759:       *hash_bucket = hp;
                   6760: 
                   6761:       hp->length = fname_length;
                   6762:       ip->nominal_fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE);
                   6763:       bcopy (fname, hp->value.cpval, fname_length);
                   6764:     }
                   6765:   } else if (*bp) {
1.1.1.8 ! root     6766:     error ("invalid format `#line' directive");
1.1       root     6767:     return 0;
                   6768:   }
                   6769: 
                   6770:   ip->lineno = new_lineno;
1.1.1.8 ! root     6771:   output_line_directive (ip, op, 0, file_change);
1.1       root     6772:   check_expand (op, ip->length - (ip->bufp - ip->buf));
                   6773:   return 0;
                   6774: }
                   6775: 
                   6776: /*
                   6777:  * remove the definition of a symbol from the symbol table.
                   6778:  * according to un*x /lib/cpp, it is not an error to undef
                   6779:  * something that has no definitions, so it isn't one here either.
                   6780:  */
                   6781: 
                   6782: static int
                   6783: do_undef (buf, limit, op, keyword)
                   6784:      U_CHAR *buf, *limit;
                   6785:      FILE_BUF *op;
                   6786:      struct directive *keyword;
                   6787: {
                   6788:   int sym_length;
                   6789:   HASHNODE *hp;
                   6790:   U_CHAR *orig_buf = buf;
                   6791: 
1.1.1.8 ! root     6792:   /* If this is a precompiler run (with -pcp) pass thru #undef directives.  */
1.1       root     6793:   if (pcp_outfile && op)
                   6794:     pass_thru_directive (buf, limit, op, keyword);
                   6795: 
                   6796:   SKIP_WHITE_SPACE (buf);
                   6797:   sym_length = check_macro_name (buf, "macro");
                   6798: 
                   6799:   while ((hp = lookup (buf, sym_length, -1)) != NULL) {
                   6800:     /* If we are generating additional info for debugging (with -g) we
1.1.1.8 ! root     6801:        need to pass through all effective #undef directives.  */
1.1       root     6802:     if (debug_output && op)
                   6803:       pass_thru_directive (orig_buf, limit, op, keyword);
                   6804:     if (hp->type != T_MACRO)
                   6805:       warning ("undefining `%s'", hp->name);
                   6806:     delete_macro (hp);
                   6807:   }
                   6808: 
                   6809:   if (pedantic) {
                   6810:     buf += sym_length;
                   6811:     SKIP_WHITE_SPACE (buf);
                   6812:     if (buf != limit)
                   6813:       pedwarn ("garbage after `#undef' directive");
                   6814:   }
                   6815:   return 0;
                   6816: }
                   6817: 
                   6818: /*
1.1.1.7   root     6819:  * Report an error detected by the program we are processing.
                   6820:  * Use the text of the line in the error message.
1.1.1.5   root     6821:  * (We use error because it prints the filename & line#.)
1.1       root     6822:  */
                   6823: 
                   6824: static int
                   6825: do_error (buf, limit, op, keyword)
                   6826:      U_CHAR *buf, *limit;
                   6827:      FILE_BUF *op;
                   6828:      struct directive *keyword;
                   6829: {
                   6830:   int length = limit - buf;
1.1.1.5   root     6831:   U_CHAR *copy = (U_CHAR *) xmalloc (length + 1);
1.1.1.7   root     6832:   bcopy ((char *) buf, (char *) copy, length);
1.1       root     6833:   copy[length] = 0;
                   6834:   SKIP_WHITE_SPACE (copy);
                   6835:   error ("#error %s", copy);
                   6836:   return 0;
                   6837: }
                   6838: 
                   6839: /*
                   6840:  * Report a warning detected by the program we are processing.
                   6841:  * Use the text of the line in the warning message, then continue.
1.1.1.5   root     6842:  * (We use error because it prints the filename & line#.)
1.1       root     6843:  */
                   6844: 
                   6845: static int
                   6846: do_warning (buf, limit, op, keyword)
                   6847:      U_CHAR *buf, *limit;
                   6848:      FILE_BUF *op;
                   6849:      struct directive *keyword;
                   6850: {
                   6851:   int length = limit - buf;
1.1.1.5   root     6852:   U_CHAR *copy = (U_CHAR *) xmalloc (length + 1);
1.1.1.7   root     6853:   bcopy ((char *) buf, (char *) copy, length);
1.1       root     6854:   copy[length] = 0;
                   6855:   SKIP_WHITE_SPACE (copy);
1.1.1.3   root     6856:   warning ("#warning %s", copy);
1.1       root     6857:   return 0;
                   6858: }
                   6859: 
                   6860: /* Remember the name of the current file being read from so that we can
                   6861:    avoid ever including it again.  */
                   6862: 
1.1.1.8 ! root     6863: static void
1.1       root     6864: do_once ()
                   6865: {
                   6866:   int i;
                   6867:   FILE_BUF *ip = NULL;
                   6868: 
                   6869:   for (i = indepth; i >= 0; i--)
                   6870:     if (instack[i].fname != NULL) {
                   6871:       ip = &instack[i];
                   6872:       break;
                   6873:     }
                   6874: 
                   6875:   if (ip != NULL) {
                   6876:     struct file_name_list *new;
                   6877:     
                   6878:     new = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
                   6879:     new->next = dont_repeat_files;
                   6880:     dont_repeat_files = new;
                   6881:     new->fname = savestring (ip->fname);
                   6882:     new->control_macro = 0;
1.1.1.7   root     6883:     new->got_name_map = 0;
1.1.1.6   root     6884:     new->c_system_include_path = 0;
1.1       root     6885:   }
                   6886: }
                   6887: 
                   6888: /* #ident has already been copied to the output file, so just ignore it.  */
                   6889: 
                   6890: static int
1.1.1.8 ! root     6891: do_ident (buf, limit, op, keyword)
1.1       root     6892:      U_CHAR *buf, *limit;
1.1.1.8 ! root     6893:      FILE_BUF *op;
        !          6894:      struct directive *keyword;
1.1       root     6895: {
1.1.1.6   root     6896:   FILE_BUF trybuf;
                   6897:   int len;
                   6898: 
1.1       root     6899:   /* Allow #ident in system headers, since that's not user's fault.  */
                   6900:   if (pedantic && !instack[indepth].system_header_p)
                   6901:     pedwarn ("ANSI C does not allow `#ident'");
1.1.1.6   root     6902: 
                   6903:   trybuf = expand_to_temp_buffer (buf, limit, 0, 0);
                   6904:   buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1);
1.1.1.7   root     6905:   bcopy ((char *) trybuf.buf, (char *) buf, trybuf.bufp - trybuf.buf);
1.1.1.6   root     6906:   limit = buf + (trybuf.bufp - trybuf.buf);
                   6907:   len = (limit - buf);
                   6908:   free (trybuf.buf);
                   6909: 
                   6910:   /* Output directive name.  */
1.1.1.7   root     6911:   check_expand (op, 7);
                   6912:   bcopy ("#ident ", (char *) op->bufp, 7);
1.1.1.6   root     6913:   op->bufp += 7;
                   6914: 
                   6915:   /* Output the expanded argument line.  */
                   6916:   check_expand (op, len);
1.1.1.7   root     6917:   bcopy ((char *) buf, (char *) op->bufp, len);
1.1.1.6   root     6918:   op->bufp += len;
                   6919: 
1.1       root     6920:   return 0;
                   6921: }
                   6922: 
                   6923: /* #pragma and its argument line have already been copied to the output file.
1.1.1.4   root     6924:    Just check for some recognized pragmas that need validation here.  */
1.1       root     6925: 
                   6926: static int
1.1.1.8 ! root     6927: do_pragma (buf, limit, op, keyword)
1.1       root     6928:      U_CHAR *buf, *limit;
1.1.1.8 ! root     6929:      FILE_BUF *op;
        !          6930:      struct directive *keyword;
1.1       root     6931: {
1.1.1.8 ! root     6932:   SKIP_WHITE_SPACE (buf);
        !          6933:   if (!strncmp ((char *) buf, "once", 4)) {
1.1.1.3   root     6934:     /* Allow #pragma once in system headers, since that's not the user's
                   6935:        fault.  */
                   6936:     if (!instack[indepth].system_header_p)
                   6937:       warning ("`#pragma once' is obsolete");
1.1       root     6938:     do_once ();
                   6939:   }
1.1.1.4   root     6940: 
1.1.1.8 ! root     6941:   if (!strncmp ((char *) buf, "implementation", 14)) {
1.1.1.4   root     6942:     /* Be quiet about `#pragma implementation' for a file only if it hasn't
                   6943:        been included yet.  */
                   6944:     struct file_name_list *ptr;
                   6945:     U_CHAR *p = buf + 14, *fname, *inc_fname;
                   6946:     SKIP_WHITE_SPACE (p);
                   6947:     if (*p == '\n' || *p != '\"')
                   6948:       return 0;
                   6949: 
                   6950:     fname = p + 1;
1.1.1.8 ! root     6951:     if ((p = (U_CHAR *) index ((char *) fname, '\"')))
1.1.1.4   root     6952:       *p = '\0';
                   6953:     
                   6954:     for (ptr = all_include_files; ptr; ptr = ptr->next) {
                   6955:       inc_fname = (U_CHAR *) rindex (ptr->fname, '/');
                   6956:       inc_fname = inc_fname ? inc_fname + 1 : (U_CHAR *) ptr->fname;
1.1.1.8 ! root     6957:       if (inc_fname && !strcmp ((char *) inc_fname, (char *) fname))
1.1.1.4   root     6958:        warning ("`#pragma implementation' for `%s' appears after file is included",
                   6959:                 fname);
                   6960:     }
                   6961:   }
                   6962: 
1.1       root     6963:   return 0;
                   6964: }
                   6965: 
                   6966: #if 0
                   6967: /* This was a fun hack, but #pragma seems to start to be useful.
                   6968:    By failing to recognize it, we pass it through unchanged to cc1.  */
                   6969: 
                   6970: /*
                   6971:  * the behavior of the #pragma directive is implementation defined.
                   6972:  * this implementation defines it as follows.
                   6973:  */
                   6974: 
                   6975: static int
                   6976: do_pragma ()
                   6977: {
                   6978:   close (0);
                   6979:   if (open ("/dev/tty", O_RDONLY, 0666) != 0)
                   6980:     goto nope;
                   6981:   close (1);
                   6982:   if (open ("/dev/tty", O_WRONLY, 0666) != 1)
                   6983:     goto nope;
                   6984:   execl ("/usr/games/hack", "#pragma", 0);
                   6985:   execl ("/usr/games/rogue", "#pragma", 0);
                   6986:   execl ("/usr/new/emacs", "-f", "hanoi", "9", "-kill", 0);
                   6987:   execl ("/usr/local/emacs", "-f", "hanoi", "9", "-kill", 0);
                   6988: nope:
                   6989:   fatal ("You are in a maze of twisty compiler features, all different");
                   6990: }
                   6991: #endif
                   6992: 
1.1.1.8 ! root     6993: #ifdef SCCS_DIRECTIVE
        !          6994: 
1.1       root     6995: /* Just ignore #sccs, on systems where we define it at all.  */
                   6996: 
                   6997: static int
1.1.1.8 ! root     6998: do_sccs (buf, limit, op, keyword)
        !          6999:      U_CHAR *buf, *limit;
        !          7000:      FILE_BUF *op;
        !          7001:      struct directive *keyword;
1.1       root     7002: {
                   7003:   if (pedantic)
                   7004:     pedwarn ("ANSI C does not allow `#sccs'");
                   7005:   return 0;
                   7006: }
1.1.1.8 ! root     7007: 
        !          7008: #endif /* defined (SCCS_DIRECTIVE) */
1.1       root     7009: 
                   7010: /*
1.1.1.8 ! root     7011:  * handle #if directive by
1.1       root     7012:  *   1) inserting special `defined' keyword into the hash table
                   7013:  *     that gets turned into 0 or 1 by special_symbol (thus,
                   7014:  *     if the luser has a symbol called `defined' already, it won't
1.1.1.8 ! root     7015:  *      work inside the #if directive)
1.1       root     7016:  *   2) rescan the input into a temporary output buffer
                   7017:  *   3) pass the output buffer to the yacc parser and collect a value
                   7018:  *   4) clean up the mess left from steps 1 and 2.
                   7019:  *   5) call conditional_skip to skip til the next #endif (etc.),
                   7020:  *      or not, depending on the value from step 3.
                   7021:  */
                   7022: 
                   7023: static int
                   7024: do_if (buf, limit, op, keyword)
                   7025:      U_CHAR *buf, *limit;
                   7026:      FILE_BUF *op;
                   7027:      struct directive *keyword;
                   7028: {
1.1.1.7   root     7029:   HOST_WIDE_INT value;
1.1       root     7030:   FILE_BUF *ip = &instack[indepth];
                   7031: 
                   7032:   value = eval_if_expression (buf, limit - buf);
1.1.1.7   root     7033:   conditional_skip (ip, value == 0, T_IF, NULL_PTR, op);
1.1       root     7034:   return 0;
                   7035: }
                   7036: 
                   7037: /*
                   7038:  * handle a #elif directive by not changing  if_stack  either.
                   7039:  * see the comment above do_else.
                   7040:  */
                   7041: 
                   7042: static int
                   7043: do_elif (buf, limit, op, keyword)
                   7044:      U_CHAR *buf, *limit;
                   7045:      FILE_BUF *op;
                   7046:      struct directive *keyword;
                   7047: {
1.1.1.7   root     7048:   HOST_WIDE_INT value;
1.1       root     7049:   FILE_BUF *ip = &instack[indepth];
                   7050: 
                   7051:   if (if_stack == instack[indepth].if_stack) {
                   7052:     error ("`#elif' not within a conditional");
                   7053:     return 0;
                   7054:   } else {
                   7055:     if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
                   7056:       error ("`#elif' after `#else'");
                   7057:       fprintf (stderr, " (matches line %d", if_stack->lineno);
                   7058:       if (if_stack->fname != NULL && ip->fname != NULL &&
                   7059:          strcmp (if_stack->fname, ip->nominal_fname) != 0)
                   7060:        fprintf (stderr, ", file %s", if_stack->fname);
                   7061:       fprintf (stderr, ")\n");
                   7062:     }
                   7063:     if_stack->type = T_ELIF;
                   7064:   }
                   7065: 
                   7066:   if (if_stack->if_succeeded)
1.1.1.7   root     7067:     skip_if_group (ip, 0, op);
1.1       root     7068:   else {
                   7069:     value = eval_if_expression (buf, limit - buf);
                   7070:     if (value == 0)
1.1.1.7   root     7071:       skip_if_group (ip, 0, op);
1.1       root     7072:     else {
                   7073:       ++if_stack->if_succeeded;        /* continue processing input */
1.1.1.8 ! root     7074:       output_line_directive (ip, op, 1, same_file);
1.1       root     7075:     }
                   7076:   }
                   7077:   return 0;
                   7078: }
                   7079: 
                   7080: /*
                   7081:  * evaluate a #if expression in BUF, of length LENGTH,
                   7082:  * then parse the result as a C expression and return the value as an int.
                   7083:  */
1.1.1.7   root     7084: static HOST_WIDE_INT
1.1       root     7085: eval_if_expression (buf, length)
                   7086:      U_CHAR *buf;
                   7087:      int length;
                   7088: {
                   7089:   FILE_BUF temp_obuf;
                   7090:   HASHNODE *save_defined;
1.1.1.7   root     7091:   HOST_WIDE_INT value;
1.1       root     7092: 
1.1.1.8 ! root     7093:   save_defined = install ((U_CHAR *) "defined", -1, T_SPEC_DEFINED,
        !          7094:                          NULL_PTR, -1);
1.1       root     7095:   pcp_inside_if = 1;
                   7096:   temp_obuf = expand_to_temp_buffer (buf, buf + length, 0, 1);
                   7097:   pcp_inside_if = 0;
                   7098:   delete_macro (save_defined); /* clean up special symbol */
                   7099: 
1.1.1.8 ! root     7100:   value = parse_c_expression ((char *) temp_obuf.buf);
1.1       root     7101: 
                   7102:   free (temp_obuf.buf);
                   7103: 
                   7104:   return value;
                   7105: }
                   7106: 
                   7107: /*
                   7108:  * routine to handle ifdef/ifndef.  Try to look up the symbol,
                   7109:  * then do or don't skip to the #endif/#else/#elif depending
                   7110:  * on what directive is actually being processed.
                   7111:  */
                   7112: 
                   7113: static int
                   7114: do_xifdef (buf, limit, op, keyword)
                   7115:      U_CHAR *buf, *limit;
                   7116:      FILE_BUF *op;
                   7117:      struct directive *keyword;
                   7118: {
                   7119:   int skip;
                   7120:   FILE_BUF *ip = &instack[indepth];
                   7121:   U_CHAR *end; 
                   7122:   int start_of_file = 0;
                   7123:   U_CHAR *control_macro = 0;
                   7124: 
                   7125:   /* Detect a #ifndef at start of file (not counting comments).  */
                   7126:   if (ip->fname != 0 && keyword->type == T_IFNDEF) {
                   7127:     U_CHAR *p = ip->buf;
                   7128:     while (p != directive_start) {
1.1.1.5   root     7129:       U_CHAR c = *p++;
1.1.1.4   root     7130:       if (is_space[c])
                   7131:        ;
1.1.1.8 ! root     7132:       /* Make no special provision for backslash-newline here; this is
        !          7133:         slower if backslash-newlines are present, but it's correct,
        !          7134:         and it's not worth it to tune for the rare backslash-newline.  */
        !          7135:       else if (c == '/'
        !          7136:               && (*p == '*' || (cplusplus_comments && *p == '/'))) {
1.1.1.4   root     7137:        /* Skip this comment.  */
1.1.1.7   root     7138:        int junk = 0;
1.1.1.4   root     7139:        U_CHAR *save_bufp = ip->bufp;
                   7140:        ip->bufp = p + 1;
                   7141:        p = skip_to_end_of_comment (ip, &junk, 1);
                   7142:        ip->bufp = save_bufp;
                   7143:       } else {
1.1       root     7144:        goto fail;
                   7145:       }
                   7146:     }
                   7147:     /* If we get here, this conditional is the beginning of the file.  */
                   7148:     start_of_file = 1;
                   7149:   fail: ;
                   7150:   }
                   7151: 
                   7152:   /* Discard leading and trailing whitespace.  */
                   7153:   SKIP_WHITE_SPACE (buf);
                   7154:   while (limit != buf && is_hor_space[limit[-1]]) limit--;
                   7155: 
                   7156:   /* Find the end of the identifier at the beginning.  */
                   7157:   for (end = buf; is_idchar[*end]; end++);
                   7158: 
                   7159:   if (end == buf) {
                   7160:     skip = (keyword->type == T_IFDEF);
                   7161:     if (! traditional)
                   7162:       pedwarn (end == limit ? "`#%s' with no argument"
                   7163:               : "`#%s' argument starts with punctuation",
                   7164:               keyword->name);
                   7165:   } else {
                   7166:     HASHNODE *hp;
                   7167: 
                   7168:     if (pedantic && buf[0] >= '0' && buf[0] <= '9')
                   7169:       pedwarn ("`#%s' argument starts with a digit", keyword->name);
                   7170:     else if (end != limit && !traditional)
                   7171:       pedwarn ("garbage at end of `#%s' argument", keyword->name);
                   7172: 
                   7173:     hp = lookup (buf, end-buf, -1);
                   7174: 
                   7175:     if (pcp_outfile) {
                   7176:       /* Output a precondition for this macro.  */
1.1.1.7   root     7177:       if (hp &&
                   7178:          (hp->type == T_CONST
                   7179:           || (hp->type == T_MACRO && hp->value.defn->predefined)))
1.1.1.5   root     7180:        fprintf (pcp_outfile, "#define %s\n", hp->name);
1.1       root     7181:       else {
                   7182:        U_CHAR *cp = buf;
1.1.1.5   root     7183:        fprintf (pcp_outfile, "#undef ");
1.1       root     7184:        while (is_idchar[*cp]) /* Ick! */
                   7185:          fputc (*cp++, pcp_outfile);
                   7186:        putc ('\n', pcp_outfile);
                   7187:       }
                   7188:     }
                   7189: 
                   7190:     skip = (hp == NULL) ^ (keyword->type == T_IFNDEF);
                   7191:     if (start_of_file && !skip) {
                   7192:       control_macro = (U_CHAR *) xmalloc (end - buf + 1);
1.1.1.7   root     7193:       bcopy ((char *) buf, (char *) control_macro, end - buf);
1.1       root     7194:       control_macro[end - buf] = 0;
                   7195:     }
                   7196:   }
                   7197:   
1.1.1.7   root     7198:   conditional_skip (ip, skip, T_IF, control_macro, op);
1.1       root     7199:   return 0;
                   7200: }
                   7201: 
                   7202: /* Push TYPE on stack; then, if SKIP is nonzero, skip ahead.
                   7203:    If this is a #ifndef starting at the beginning of a file,
                   7204:    CONTROL_MACRO is the macro name tested by the #ifndef.
                   7205:    Otherwise, CONTROL_MACRO is 0.  */
                   7206: 
                   7207: static void
1.1.1.7   root     7208: conditional_skip (ip, skip, type, control_macro, op)
1.1       root     7209:      FILE_BUF *ip;
                   7210:      int skip;
                   7211:      enum node_type type;
                   7212:      U_CHAR *control_macro;
1.1.1.7   root     7213:      FILE_BUF *op;
1.1       root     7214: {
                   7215:   IF_STACK_FRAME *temp;
                   7216: 
                   7217:   temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
                   7218:   temp->fname = ip->nominal_fname;
                   7219:   temp->lineno = ip->lineno;
                   7220:   temp->next = if_stack;
                   7221:   temp->control_macro = control_macro;
                   7222:   if_stack = temp;
                   7223: 
                   7224:   if_stack->type = type;
                   7225: 
                   7226:   if (skip != 0) {
1.1.1.7   root     7227:     skip_if_group (ip, 0, op);
1.1       root     7228:     return;
                   7229:   } else {
                   7230:     ++if_stack->if_succeeded;
1.1.1.8 ! root     7231:     output_line_directive (ip, &outbuf, 1, same_file);
1.1       root     7232:   }
                   7233: }
                   7234: 
                   7235: /*
                   7236:  * skip to #endif, #else, or #elif.  adjust line numbers, etc.
                   7237:  * leaves input ptr at the sharp sign found.
                   7238:  * If ANY is nonzero, return at next directive of any sort.
                   7239:  */
                   7240: static void
1.1.1.7   root     7241: skip_if_group (ip, any, op)
1.1       root     7242:      FILE_BUF *ip;
                   7243:      int any;
1.1.1.7   root     7244:      FILE_BUF *op;
1.1       root     7245: {
                   7246:   register U_CHAR *bp = ip->bufp, *cp;
                   7247:   register U_CHAR *endb = ip->buf + ip->length;
                   7248:   struct directive *kt;
                   7249:   IF_STACK_FRAME *save_if_stack = if_stack; /* don't pop past here */
                   7250:   U_CHAR *beg_of_line = bp;
                   7251:   register int ident_length;
                   7252:   U_CHAR *ident, *after_ident;
1.1.1.7   root     7253:   /* Save info about where the group starts.  */
                   7254:   U_CHAR *beg_of_group = bp;
                   7255:   int beg_lineno = ip->lineno;
                   7256: 
                   7257:   if (output_conditionals && op != 0) {
                   7258:     char *ptr = "#failed\n";
                   7259:     int len = strlen (ptr);
                   7260: 
                   7261:     if (op->bufp > op->buf && op->bufp[-1] != '\n')
                   7262:       {
                   7263:        *op->bufp++ = '\n';
                   7264:        op->lineno++;
                   7265:       }
                   7266:     check_expand (op, len);
                   7267:     bcopy (ptr, (char *) op->bufp, len);
                   7268:     op->bufp += len;
                   7269:     op->lineno++;
1.1.1.8 ! root     7270:     output_line_directive (ip, op, 1, 0);
1.1.1.7   root     7271:   }
1.1       root     7272: 
                   7273:   while (bp < endb) {
                   7274:     switch (*bp++) {
                   7275:     case '/':                  /* possible comment */
                   7276:       if (*bp == '\\' && bp[1] == '\n')
                   7277:        newline_fix (bp);
                   7278:       if (*bp == '*'
1.1.1.4   root     7279:          || (cplusplus_comments && *bp == '/')) {
1.1       root     7280:        ip->bufp = ++bp;
1.1.1.2   root     7281:        bp = skip_to_end_of_comment (ip, &ip->lineno, 0);
1.1       root     7282:       }
                   7283:       break;
                   7284:     case '\"':
                   7285:     case '\'':
1.1.1.4   root     7286:       bp = skip_quoted_string (bp - 1, endb, ip->lineno, &ip->lineno,
                   7287:                               NULL_PTR, NULL_PTR);
1.1       root     7288:       break;
                   7289:     case '\\':
                   7290:       /* Char after backslash loses its special meaning.  */
                   7291:       if (bp < endb) {
                   7292:        if (*bp == '\n')
                   7293:          ++ip->lineno;         /* But do update the line-count.  */
                   7294:        bp++;
                   7295:       }
                   7296:       break;
                   7297:     case '\n':
                   7298:       ++ip->lineno;
                   7299:       beg_of_line = bp;
                   7300:       break;
1.1.1.8 ! root     7301:     case '%':
        !          7302:       if (beg_of_line == 0 || traditional)
        !          7303:        break;
1.1       root     7304:       ip->bufp = bp - 1;
1.1.1.8 ! root     7305:       while (bp[0] == '\\' && bp[1] == '\n')
        !          7306:        bp += 2;
        !          7307:       if (*bp == ':')
        !          7308:        goto sharp_token;
        !          7309:       break;
        !          7310:     case '#':
1.1       root     7311:       /* # keyword: a # must be first nonblank char on the line */
                   7312:       if (beg_of_line == 0)
                   7313:        break;
1.1.1.8 ! root     7314:       ip->bufp = bp - 1;
        !          7315:     sharp_token:
1.1       root     7316:       /* Scan from start of line, skipping whitespace, comments
                   7317:         and backslash-newlines, and see if we reach this #.
                   7318:         If not, this # is not special.  */
                   7319:       bp = beg_of_line;
1.1.1.6   root     7320:       /* If -traditional, require # to be at beginning of line.  */
1.1.1.8 ! root     7321:       if (!traditional) {
1.1.1.6   root     7322:        while (1) {
                   7323:          if (is_hor_space[*bp])
1.1       root     7324:            bp++;
1.1.1.6   root     7325:          else if (*bp == '\\' && bp[1] == '\n')
                   7326:            bp += 2;
                   7327:          else if (*bp == '/' && bp[1] == '*') {
                   7328:            bp += 2;
                   7329:            while (!(*bp == '*' && bp[1] == '/'))
                   7330:              bp++;
                   7331:            bp += 2;
                   7332:          }
1.1.1.7   root     7333:          /* There is no point in trying to deal with C++ // comments here,
                   7334:             because if there is one, then this # must be part of the
                   7335:             comment and we would never reach here.  */
1.1.1.6   root     7336:          else break;
                   7337:        }
1.1.1.8 ! root     7338:       }
1.1       root     7339:       if (bp != ip->bufp) {
                   7340:        bp = ip->bufp + 1;      /* Reset bp to after the #.  */
                   7341:        break;
                   7342:       }
                   7343: 
                   7344:       bp = ip->bufp + 1;       /* Point after the '#' */
1.1.1.8 ! root     7345:       if (ip->bufp[0] == '%') {
        !          7346:        /* Skip past the ':' again.  */
        !          7347:        while (*bp == '\\') {
        !          7348:          ip->lineno++;
        !          7349:          bp += 2;
        !          7350:        }
        !          7351:        bp++;
        !          7352:       }
1.1       root     7353: 
                   7354:       /* Skip whitespace and \-newline.  */
                   7355:       while (1) {
                   7356:        if (is_hor_space[*bp])
                   7357:          bp++;
                   7358:        else if (*bp == '\\' && bp[1] == '\n')
                   7359:          bp += 2;
                   7360:        else if (*bp == '/' && bp[1] == '*') {
                   7361:          bp += 2;
                   7362:          while (!(*bp == '*' && bp[1] == '/')) {
                   7363:            if (*bp == '\n')
                   7364:              ip->lineno++;
                   7365:            bp++;
                   7366:          }
                   7367:          bp += 2;
1.1.1.4   root     7368:        } else if (cplusplus_comments && *bp == '/' && bp[1] == '/') {
1.1       root     7369:          bp += 2;
1.1.1.7   root     7370:          while (bp[-1] == '\\' || *bp != '\n') {
                   7371:            if (*bp == '\n')
                   7372:              ip->lineno++;
                   7373:            bp++;
                   7374:          }
1.1       root     7375:         }
                   7376:        else break;
                   7377:       }
                   7378: 
                   7379:       cp = bp;
                   7380: 
                   7381:       /* Now find end of directive name.
                   7382:         If we encounter a backslash-newline, exchange it with any following
                   7383:         symbol-constituents so that we end up with a contiguous name.  */
                   7384: 
                   7385:       while (1) {
                   7386:        if (is_idchar[*bp])
                   7387:          bp++;
                   7388:        else {
                   7389:          if (*bp == '\\' && bp[1] == '\n')
                   7390:            name_newline_fix (bp);
                   7391:          if (is_idchar[*bp])
                   7392:            bp++;
                   7393:          else break;
                   7394:        }
                   7395:       }
                   7396:       ident_length = bp - cp;
                   7397:       ident = cp;
                   7398:       after_ident = bp;
                   7399: 
                   7400:       /* A line of just `#' becomes blank.  */
                   7401: 
                   7402:       if (ident_length == 0 && *after_ident == '\n') {
                   7403:        continue;
                   7404:       }
                   7405: 
                   7406:       if (ident_length == 0 || !is_idstart[*ident]) {
                   7407:        U_CHAR *p = ident;
                   7408:        while (is_idchar[*p]) {
                   7409:          if (*p < '0' || *p > '9')
                   7410:            break;
                   7411:          p++;
                   7412:        }
                   7413:        /* Handle # followed by a line number.  */
                   7414:        if (p != ident && !is_idchar[*p]) {
                   7415:          if (pedantic)
                   7416:            pedwarn ("`#' followed by integer");
                   7417:          continue;
                   7418:        }
                   7419: 
                   7420:        /* Avoid error for `###' and similar cases unless -pedantic.  */
                   7421:        if (p == ident) {
                   7422:          while (*p == '#' || is_hor_space[*p]) p++;
                   7423:          if (*p == '\n') {
                   7424:            if (pedantic && !lang_asm)
1.1.1.8 ! root     7425:              pedwarn ("invalid preprocessing directive");
1.1       root     7426:            continue;
                   7427:          }
                   7428:        }
                   7429: 
                   7430:        if (!lang_asm && pedantic)
1.1.1.8 ! root     7431:          pedwarn ("invalid preprocessing directive name");
1.1       root     7432:        continue;
                   7433:       }
                   7434: 
                   7435:       for (kt = directive_table; kt->length >= 0; kt++) {
                   7436:        IF_STACK_FRAME *temp;
                   7437:        if (ident_length == kt->length
1.1.1.8 ! root     7438:            && bcmp (cp, kt->name, kt->length) == 0) {
1.1       root     7439:          /* If we are asked to return on next directive, do so now.  */
                   7440:          if (any)
1.1.1.7   root     7441:            goto done;
1.1       root     7442: 
                   7443:          switch (kt->type) {
                   7444:          case T_IF:
                   7445:          case T_IFDEF:
                   7446:          case T_IFNDEF:
                   7447:            temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
                   7448:            temp->next = if_stack;
                   7449:            if_stack = temp;
                   7450:            temp->lineno = ip->lineno;
                   7451:            temp->fname = ip->nominal_fname;
                   7452:            temp->type = kt->type;
                   7453:            break;
                   7454:          case T_ELSE:
                   7455:          case T_ENDIF:
                   7456:            if (pedantic && if_stack != save_if_stack)
                   7457:              validate_else (bp);
                   7458:          case T_ELIF:
                   7459:            if (if_stack == instack[indepth].if_stack) {
                   7460:              error ("`#%s' not within a conditional", kt->name);
                   7461:              break;
                   7462:            }
                   7463:            else if (if_stack == save_if_stack)
1.1.1.7   root     7464:              goto done;                /* found what we came for */
1.1       root     7465: 
                   7466:            if (kt->type != T_ENDIF) {
                   7467:              if (if_stack->type == T_ELSE)
                   7468:                error ("`#else' or `#elif' after `#else'");
                   7469:              if_stack->type = kt->type;
                   7470:              break;
                   7471:            }
                   7472: 
                   7473:            temp = if_stack;
                   7474:            if_stack = if_stack->next;
                   7475:            free (temp);
                   7476:            break;
1.1.1.8 ! root     7477: 
        !          7478:           default:
        !          7479:            break;
1.1       root     7480:          }
                   7481:          break;
                   7482:        }
                   7483:       }
                   7484:       /* Don't let erroneous code go by.  */
                   7485:       if (kt->length < 0 && !lang_asm && pedantic)
1.1.1.8 ! root     7486:        pedwarn ("invalid preprocessing directive name");
1.1       root     7487:     }
                   7488:   }
1.1.1.7   root     7489: 
1.1       root     7490:   ip->bufp = bp;
                   7491:   /* after this returns, rescan will exit because ip->bufp
                   7492:      now points to the end of the buffer.
                   7493:      rescan is responsible for the error message also.  */
1.1.1.7   root     7494: 
                   7495:  done:
                   7496:   if (output_conditionals && op != 0) {
                   7497:     char *ptr = "#endfailed\n";
                   7498:     int len = strlen (ptr);
                   7499: 
                   7500:     if (op->bufp > op->buf && op->bufp[-1] != '\n')
                   7501:       {
                   7502:        *op->bufp++ = '\n';
                   7503:        op->lineno++;
                   7504:       }
                   7505:     check_expand (op, beg_of_line - beg_of_group);
                   7506:     bcopy ((char *) beg_of_group, (char *) op->bufp,
                   7507:           beg_of_line - beg_of_group);
                   7508:     op->bufp += beg_of_line - beg_of_group;
                   7509:     op->lineno += ip->lineno - beg_lineno;
                   7510:     check_expand (op, len);
                   7511:     bcopy (ptr, (char *) op->bufp, len);
                   7512:     op->bufp += len;
                   7513:     op->lineno++;
                   7514:   }
1.1       root     7515: }
                   7516: 
                   7517: /*
                   7518:  * handle a #else directive.  Do this by just continuing processing
                   7519:  * without changing  if_stack ;  this is so that the error message
                   7520:  * for missing #endif's etc. will point to the original #if.  It
                   7521:  * is possible that something different would be better.
                   7522:  */
                   7523: 
                   7524: static int
                   7525: do_else (buf, limit, op, keyword)
                   7526:      U_CHAR *buf, *limit;
                   7527:      FILE_BUF *op;
                   7528:      struct directive *keyword;
                   7529: {
                   7530:   FILE_BUF *ip = &instack[indepth];
                   7531: 
                   7532:   if (pedantic) {
                   7533:     SKIP_WHITE_SPACE (buf);
                   7534:     if (buf != limit)
                   7535:       pedwarn ("text following `#else' violates ANSI standard");
                   7536:   }
                   7537: 
                   7538:   if (if_stack == instack[indepth].if_stack) {
                   7539:     error ("`#else' not within a conditional");
                   7540:     return 0;
                   7541:   } else {
                   7542:     /* #ifndef can't have its special treatment for containing the whole file
                   7543:        if it has a #else clause.  */
                   7544:     if_stack->control_macro = 0;
                   7545: 
                   7546:     if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
                   7547:       error ("`#else' after `#else'");
                   7548:       fprintf (stderr, " (matches line %d", if_stack->lineno);
                   7549:       if (strcmp (if_stack->fname, ip->nominal_fname) != 0)
                   7550:        fprintf (stderr, ", file %s", if_stack->fname);
                   7551:       fprintf (stderr, ")\n");
                   7552:     }
                   7553:     if_stack->type = T_ELSE;
                   7554:   }
                   7555: 
                   7556:   if (if_stack->if_succeeded)
1.1.1.7   root     7557:     skip_if_group (ip, 0, op);
1.1       root     7558:   else {
                   7559:     ++if_stack->if_succeeded;  /* continue processing input */
1.1.1.8 ! root     7560:     output_line_directive (ip, op, 1, same_file);
1.1       root     7561:   }
                   7562:   return 0;
                   7563: }
                   7564: 
                   7565: /*
1.1.1.8 ! root     7566:  * unstack after #endif directive
1.1       root     7567:  */
                   7568: 
                   7569: static int
                   7570: do_endif (buf, limit, op, keyword)
                   7571:      U_CHAR *buf, *limit;
                   7572:      FILE_BUF *op;
                   7573:      struct directive *keyword;
                   7574: {
                   7575:   if (pedantic) {
                   7576:     SKIP_WHITE_SPACE (buf);
                   7577:     if (buf != limit)
                   7578:       pedwarn ("text following `#endif' violates ANSI standard");
                   7579:   }
                   7580: 
                   7581:   if (if_stack == instack[indepth].if_stack)
                   7582:     error ("unbalanced `#endif'");
                   7583:   else {
                   7584:     IF_STACK_FRAME *temp = if_stack;
                   7585:     if_stack = if_stack->next;
                   7586:     if (temp->control_macro != 0) {
                   7587:       /* This #endif matched a #ifndef at the start of the file.
                   7588:         See if it is at the end of the file.  */
                   7589:       FILE_BUF *ip = &instack[indepth];
                   7590:       U_CHAR *p = ip->bufp;
                   7591:       U_CHAR *ep = ip->buf + ip->length;
                   7592: 
                   7593:       while (p != ep) {
                   7594:        U_CHAR c = *p++;
1.1.1.8 ! root     7595:        if (!is_space[c]) {
        !          7596:          if (c == '/'
        !          7597:              && (*p == '*' || (cplusplus_comments && *p == '/'))) {
1.1       root     7598:            /* Skip this comment.  */
1.1.1.7   root     7599:            int junk = 0;
1.1       root     7600:            U_CHAR *save_bufp = ip->bufp;
                   7601:            ip->bufp = p + 1;
1.1.1.2   root     7602:            p = skip_to_end_of_comment (ip, &junk, 1);
1.1       root     7603:            ip->bufp = save_bufp;
1.1.1.8 ! root     7604:          } else
        !          7605:            goto fail;
1.1       root     7606:        }
                   7607:       }
                   7608:       /* If we get here, this #endif ends a #ifndef
                   7609:         that contains all of the file (aside from whitespace).
                   7610:         Arrange not to include the file again
1.1.1.7   root     7611:         if the macro that was tested is defined.
                   7612: 
                   7613:         Do not do this for the top-level file in a -include or any
                   7614:         file in a -imacros.  */
                   7615:       if (indepth != 0
                   7616:          && ! (indepth == 1 && no_record_file)
                   7617:          && ! (no_record_file && no_output))
1.1       root     7618:        record_control_macro (ip->fname, temp->control_macro);
                   7619:     fail: ;
                   7620:     }
                   7621:     free (temp);
1.1.1.8 ! root     7622:     output_line_directive (&instack[indepth], op, 1, same_file);
1.1       root     7623:   }
                   7624:   return 0;
                   7625: }
                   7626: 
                   7627: /* When an #else or #endif is found while skipping failed conditional,
                   7628:    if -pedantic was specified, this is called to warn about text after
1.1.1.8 ! root     7629:    the directive name.  P points to the first char after the directive name.  */
1.1       root     7630: 
                   7631: static void
                   7632: validate_else (p)
                   7633:      register U_CHAR *p;
                   7634: {
                   7635:   /* Advance P over whitespace and comments.  */
                   7636:   while (1) {
                   7637:     if (*p == '\\' && p[1] == '\n')
                   7638:       p += 2;
                   7639:     if (is_hor_space[*p])
                   7640:       p++;
                   7641:     else if (*p == '/') {
                   7642:       if (p[1] == '\\' && p[2] == '\n')
                   7643:        newline_fix (p + 1);
                   7644:       if (p[1] == '*') {
                   7645:        p += 2;
                   7646:        /* Don't bother warning about unterminated comments
                   7647:           since that will happen later.  Just be sure to exit.  */
                   7648:        while (*p) {
                   7649:          if (p[1] == '\\' && p[2] == '\n')
                   7650:            newline_fix (p + 1);
                   7651:          if (*p == '*' && p[1] == '/') {
                   7652:            p += 2;
                   7653:            break;
                   7654:          }
                   7655:          p++;
                   7656:        }
                   7657:       }
1.1.1.4   root     7658:       else if (cplusplus_comments && p[1] == '/') {
1.1       root     7659:        p += 2;
1.1.1.7   root     7660:        while (*p && (*p != '\n' || p[-1] == '\\'))
                   7661:          p++;
1.1       root     7662:       }
                   7663:     } else break;
                   7664:   }
                   7665:   if (*p && *p != '\n')
                   7666:     pedwarn ("text following `#else' or `#endif' violates ANSI standard");
                   7667: }
                   7668: 
1.1.1.2   root     7669: /* Skip a comment, assuming the input ptr immediately follows the
                   7670:    initial slash-star.  Bump *LINE_COUNTER for each newline.
                   7671:    (The canonical line counter is &ip->lineno.)
                   7672:    Don't use this routine (or the next one) if bumping the line
                   7673:    counter is not sufficient to deal with newlines in the string.
                   7674: 
                   7675:    If NOWARN is nonzero, don't warn about slash-star inside a comment.
                   7676:    This feature is useful when processing a comment that is going to be
                   7677:    processed or was processed at another point in the preprocessor,
1.1.1.7   root     7678:    to avoid a duplicate warning.  Likewise for unterminated comment errors.  */
                   7679: 
1.1       root     7680: static U_CHAR *
1.1.1.2   root     7681: skip_to_end_of_comment (ip, line_counter, nowarn)
1.1       root     7682:      register FILE_BUF *ip;
                   7683:      int *line_counter;                /* place to remember newlines, or NULL */
1.1.1.2   root     7684:      int nowarn;
1.1       root     7685: {
                   7686:   register U_CHAR *limit = ip->buf + ip->length;
                   7687:   register U_CHAR *bp = ip->bufp;
                   7688:   FILE_BUF *op = &outbuf;      /* JF */
                   7689:   int output = put_out_comments && !line_counter;
1.1.1.7   root     7690:   int start_line = line_counter ? *line_counter : 0;
1.1       root     7691: 
                   7692:        /* JF this line_counter stuff is a crock to make sure the
                   7693:           comment is only put out once, no matter how many times
                   7694:           the comment is skipped.  It almost works */
                   7695:   if (output) {
                   7696:     *op->bufp++ = '/';
                   7697:     *op->bufp++ = '*';
                   7698:   }
1.1.1.4   root     7699:   if (cplusplus_comments && bp[-1] == '/') {
1.1       root     7700:     if (output) {
1.1.1.7   root     7701:       while (bp < limit) {
                   7702:        *op->bufp++ = *bp;
                   7703:        if (*bp == '\n' && bp[-1] != '\\')
1.1       root     7704:          break;
1.1.1.7   root     7705:        if (*bp == '\n') {
                   7706:          ++*line_counter;
                   7707:          ++op->lineno;
1.1       root     7708:        }
1.1.1.7   root     7709:        bp++;
                   7710:       }
1.1       root     7711:       op->bufp[-1] = '*';
                   7712:       *op->bufp++ = '/';
                   7713:       *op->bufp++ = '\n';
                   7714:     } else {
                   7715:       while (bp < limit) {
1.1.1.7   root     7716:        if (bp[-1] != '\\' && *bp == '\n') {
1.1       root     7717:          break;
1.1.1.7   root     7718:        } else {
                   7719:          if (*bp == '\n' && line_counter)
                   7720:            ++*line_counter;
                   7721:          bp++;
1.1       root     7722:        }
                   7723:       }
                   7724:     }
                   7725:     ip->bufp = bp;
                   7726:     return bp;
                   7727:   }
                   7728:   while (bp < limit) {
                   7729:     if (output)
                   7730:       *op->bufp++ = *bp;
                   7731:     switch (*bp++) {
                   7732:     case '/':
1.1.1.2   root     7733:       if (warn_comments && !nowarn && bp < limit && *bp == '*')
1.1       root     7734:        warning ("`/*' within comment");
                   7735:       break;
                   7736:     case '\n':
1.1.1.7   root     7737:       /* If this is the end of the file, we have an unterminated comment.
                   7738:         Don't swallow the newline.  We are guaranteed that there will be a
                   7739:         trailing newline and various pieces assume it's there.  */
                   7740:       if (bp == limit)
                   7741:        {
                   7742:          --bp;
                   7743:          --limit;
                   7744:          break;
                   7745:        }
1.1       root     7746:       if (line_counter != NULL)
                   7747:        ++*line_counter;
                   7748:       if (output)
                   7749:        ++op->lineno;
                   7750:       break;
                   7751:     case '*':
                   7752:       if (*bp == '\\' && bp[1] == '\n')
                   7753:        newline_fix (bp);
                   7754:       if (*bp == '/') {
                   7755:         if (output)
                   7756:          *op->bufp++ = '/';
                   7757:        ip->bufp = ++bp;
                   7758:        return bp;
                   7759:       }
                   7760:       break;
                   7761:     }
                   7762:   }
1.1.1.7   root     7763: 
                   7764:   if (!nowarn)
                   7765:     error_with_line (line_for_error (start_line), "unterminated comment");
1.1       root     7766:   ip->bufp = bp;
                   7767:   return bp;
                   7768: }
                   7769: 
                   7770: /*
                   7771:  * Skip over a quoted string.  BP points to the opening quote.
                   7772:  * Returns a pointer after the closing quote.  Don't go past LIMIT.
                   7773:  * START_LINE is the line number of the starting point (but it need
                   7774:  * not be valid if the starting point is inside a macro expansion).
                   7775:  *
                   7776:  * The input stack state is not changed.
                   7777:  *
                   7778:  * If COUNT_NEWLINES is nonzero, it points to an int to increment
                   7779:  * for each newline passed.
                   7780:  *
                   7781:  * If BACKSLASH_NEWLINES_P is nonzero, store 1 thru it
                   7782:  * if we pass a backslash-newline.
                   7783:  *
                   7784:  * If EOFP is nonzero, set *EOFP to 1 if the string is unterminated.
                   7785:  */
                   7786: static U_CHAR *
                   7787: skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, eofp)
                   7788:      register U_CHAR *bp;
                   7789:      register U_CHAR *limit;
                   7790:      int start_line;
                   7791:      int *count_newlines;
                   7792:      int *backslash_newlines_p;
                   7793:      int *eofp;
                   7794: {
                   7795:   register U_CHAR c, match;
                   7796: 
                   7797:   match = *bp++;
                   7798:   while (1) {
                   7799:     if (bp >= limit) {
                   7800:       error_with_line (line_for_error (start_line),
                   7801:                       "unterminated string or character constant");
1.1.1.5   root     7802:       error_with_line (multiline_string_line,
                   7803:                       "possible real start of unterminated constant");
                   7804:       multiline_string_line = 0;
1.1       root     7805:       if (eofp)
                   7806:        *eofp = 1;
                   7807:       break;
                   7808:     }
                   7809:     c = *bp++;
                   7810:     if (c == '\\') {
                   7811:       while (*bp == '\\' && bp[1] == '\n') {
                   7812:        if (backslash_newlines_p)
                   7813:          *backslash_newlines_p = 1;
                   7814:        if (count_newlines)
                   7815:          ++*count_newlines;
                   7816:        bp += 2;
                   7817:       }
                   7818:       if (*bp == '\n' && count_newlines) {
                   7819:        if (backslash_newlines_p)
                   7820:          *backslash_newlines_p = 1;
                   7821:        ++*count_newlines;
                   7822:       }
                   7823:       bp++;
                   7824:     } else if (c == '\n') {
                   7825:       if (traditional) {
1.1.1.8 ! root     7826:        /* Unterminated strings and character constants are 'valid'.  */
1.1       root     7827:        bp--;   /* Don't consume the newline. */
                   7828:        if (eofp)
                   7829:          *eofp = 1;
                   7830:        break;
                   7831:       }
1.1.1.5   root     7832:       if (pedantic || match == '\'') {
1.1       root     7833:        error_with_line (line_for_error (start_line),
1.1.1.5   root     7834:                         "unterminated string or character constant");
1.1       root     7835:        bp--;
                   7836:        if (eofp)
                   7837:          *eofp = 1;
                   7838:        break;
                   7839:       }
                   7840:       /* If not traditional, then allow newlines inside strings.  */
                   7841:       if (count_newlines)
                   7842:        ++*count_newlines;
1.1.1.5   root     7843:       if (multiline_string_line == 0)
                   7844:        multiline_string_line = start_line;
1.1       root     7845:     } else if (c == match)
                   7846:       break;
                   7847:   }
                   7848:   return bp;
                   7849: }
                   7850: 
1.1.1.6   root     7851: /* Place into DST a quoted string representing the string SRC.
                   7852:    Return the address of DST's terminating null.  */
                   7853: static char *
                   7854: quote_string (dst, src)
                   7855:      char *dst, *src;
                   7856: {
                   7857:   U_CHAR c;
                   7858: 
                   7859:   *dst++ = '\"';
                   7860:   for (;;)
                   7861:     switch ((c = *src++))
                   7862:       {
                   7863:       default:
                   7864:         if (isprint (c))
                   7865:          *dst++ = c;
                   7866:        else
                   7867:          {
                   7868:            sprintf (dst, "\\%03o", c);
                   7869:            dst += 4;
                   7870:          }
                   7871:        break;
                   7872: 
                   7873:       case '\"':
                   7874:       case '\\':
                   7875:        *dst++ = '\\';
                   7876:        *dst++ = c;
                   7877:        break;
                   7878:       
                   7879:       case '\0':
                   7880:        *dst++ = '\"';
                   7881:        *dst = '\0';
                   7882:        return dst;
                   7883:       }
                   7884: }
                   7885: 
1.1       root     7886: /* Skip across a group of balanced parens, starting from IP->bufp.
                   7887:    IP->bufp is updated.  Use this with IP->bufp pointing at an open-paren.
                   7888: 
                   7889:    This does not handle newlines, because it's used for the arg of #if,
1.1.1.2   root     7890:    where there aren't any newlines.  Also, backslash-newline can't appear.  */
1.1       root     7891: 
                   7892: static U_CHAR *
                   7893: skip_paren_group (ip)
                   7894:      register FILE_BUF *ip;
                   7895: {
                   7896:   U_CHAR *limit = ip->buf + ip->length;
                   7897:   U_CHAR *p = ip->bufp;
                   7898:   int depth = 0;
                   7899:   int lines_dummy = 0;
                   7900: 
                   7901:   while (p != limit) {
                   7902:     int c = *p++;
                   7903:     switch (c) {
                   7904:     case '(':
                   7905:       depth++;
                   7906:       break;
                   7907: 
                   7908:     case ')':
                   7909:       depth--;
                   7910:       if (depth == 0)
                   7911:        return ip->bufp = p;
                   7912:       break;
                   7913: 
                   7914:     case '/':
                   7915:       if (*p == '*') {
                   7916:        ip->bufp = p;
1.1.1.2   root     7917:        p = skip_to_end_of_comment (ip, &lines_dummy, 0);
1.1       root     7918:        p = ip->bufp;
                   7919:       }
                   7920: 
                   7921:     case '"':
                   7922:     case '\'':
                   7923:       {
                   7924:        int eofp = 0;
1.1.1.4   root     7925:        p = skip_quoted_string (p - 1, limit, 0, NULL_PTR, NULL_PTR, &eofp);
1.1       root     7926:        if (eofp)
                   7927:          return ip->bufp = p;
                   7928:       }
                   7929:       break;
                   7930:     }
                   7931:   }
                   7932: 
                   7933:   ip->bufp = p;
                   7934:   return p;
                   7935: }
                   7936: 
                   7937: /*
1.1.1.8 ! root     7938:  * write out a #line directive, for instance, after an #include file.
1.1       root     7939:  * If CONDITIONAL is nonzero, we can omit the #line if it would
                   7940:  * appear to be a no-op, and we can output a few newlines instead
                   7941:  * if we want to increase the line number by a small amount.
                   7942:  * FILE_CHANGE says whether we are entering a file, leaving, or neither.
                   7943:  */
                   7944: 
                   7945: static void
1.1.1.8 ! root     7946: output_line_directive (ip, op, conditional, file_change)
1.1       root     7947:      FILE_BUF *ip, *op;
                   7948:      int conditional;
                   7949:      enum file_change_code file_change;
                   7950: {
                   7951:   int len;
1.1.1.8 ! root     7952:   char *line_directive_buf, *line_end;
1.1       root     7953: 
1.1.1.8 ! root     7954:   if (no_line_directives
1.1       root     7955:       || ip->fname == NULL
                   7956:       || no_output) {
                   7957:     op->lineno = ip->lineno;
                   7958:     return;
                   7959:   }
                   7960: 
                   7961:   if (conditional) {
                   7962:     if (ip->lineno == op->lineno)
                   7963:       return;
                   7964: 
                   7965:     /* If the inherited line number is a little too small,
1.1.1.8 ! root     7966:        output some newlines instead of a #line directive.  */
1.1       root     7967:     if (ip->lineno > op->lineno && ip->lineno < op->lineno + 8) {
                   7968:       check_expand (op, 10);
                   7969:       while (ip->lineno > op->lineno) {
                   7970:        *op->bufp++ = '\n';
                   7971:        op->lineno++;
                   7972:       }
                   7973:       return;
                   7974:     }
                   7975:   }
                   7976: 
1.1.1.2   root     7977:   /* Don't output a line number of 0 if we can help it.  */
                   7978:   if (ip->lineno == 0 && ip->bufp - ip->buf < ip->length
                   7979:       && *ip->bufp == '\n') {
                   7980:     ip->lineno++;
                   7981:     ip->bufp++;
                   7982:   }
                   7983: 
1.1.1.8 ! root     7984:   line_directive_buf = (char *) alloca (4 * strlen (ip->nominal_fname) + 100);
        !          7985:   sprintf (line_directive_buf, "# %d ", ip->lineno);
        !          7986:   line_end = quote_string (line_directive_buf + strlen (line_directive_buf),
1.1.1.6   root     7987:                           ip->nominal_fname);
                   7988:   if (file_change != same_file) {
                   7989:     *line_end++ = ' ';
                   7990:     *line_end++ = file_change == enter_file ? '1' : '2';
                   7991:   }
1.1       root     7992:   /* Tell cc1 if following text comes from a system header file.  */
1.1.1.6   root     7993:   if (ip->system_header_p) {
                   7994:     *line_end++ = ' ';
                   7995:     *line_end++ = '3';
                   7996:   }
                   7997: #ifndef NO_IMPLICIT_EXTERN_C
                   7998:   /* Tell cc1plus if following text should be treated as C.  */
                   7999:   if (ip->system_header_p == 2 && cplusplus) {
                   8000:     *line_end++ = ' ';
                   8001:     *line_end++ = '4';
                   8002:   }
                   8003: #endif
                   8004:   *line_end++ = '\n';
1.1.1.8 ! root     8005:   len = line_end - line_directive_buf;
1.1       root     8006:   check_expand (op, len + 1);
                   8007:   if (op->bufp > op->buf && op->bufp[-1] != '\n')
                   8008:     *op->bufp++ = '\n';
1.1.1.8 ! root     8009:   bcopy ((char *) line_directive_buf, (char *) op->bufp, len);
1.1       root     8010:   op->bufp += len;
                   8011:   op->lineno = ip->lineno;
                   8012: }
                   8013: 
                   8014: /* This structure represents one parsed argument in a macro call.
                   8015:    `raw' points to the argument text as written (`raw_length' is its length).
                   8016:    `expanded' points to the argument's macro-expansion
                   8017:    (its length is `expand_length').
                   8018:    `stringified_length' is the length the argument would have
                   8019:    if stringified.
                   8020:    `use_count' is the number of times this macro arg is substituted
                   8021:    into the macro.  If the actual use count exceeds 10, 
                   8022:    the value stored is 10.
                   8023:    `free1' and `free2', if nonzero, point to blocks to be freed
                   8024:    when the macro argument data is no longer needed.  */
                   8025: 
                   8026: struct argdata {
                   8027:   U_CHAR *raw, *expanded;
                   8028:   int raw_length, expand_length;
                   8029:   int stringified_length;
                   8030:   U_CHAR *free1, *free2;
                   8031:   char newlines;
                   8032:   char use_count;
                   8033: };
                   8034: 
                   8035: /* Expand a macro call.
                   8036:    HP points to the symbol that is the macro being called.
                   8037:    Put the result of expansion onto the input stack
                   8038:    so that subsequent input by our caller will use it.
                   8039: 
                   8040:    If macro wants arguments, caller has already verified that
                   8041:    an argument list follows; arguments come from the input stack.  */
                   8042: 
                   8043: static void
                   8044: macroexpand (hp, op)
                   8045:      HASHNODE *hp;
                   8046:      FILE_BUF *op;
                   8047: {
                   8048:   int nargs;
                   8049:   DEFINITION *defn = hp->value.defn;
                   8050:   register U_CHAR *xbuf;
                   8051:   int xbuf_len;
                   8052:   int start_line = instack[indepth].lineno;
1.1.1.3   root     8053:   int rest_args, rest_zero;
1.1       root     8054: 
                   8055:   CHECK_DEPTH (return;);
                   8056: 
                   8057:   /* it might not actually be a macro.  */
                   8058:   if (hp->type != T_MACRO) {
                   8059:     special_symbol (hp, op);
                   8060:     return;
                   8061:   }
                   8062: 
                   8063:   /* This macro is being used inside a #if, which means it must be */
                   8064:   /* recorded as a precondition.  */
                   8065:   if (pcp_inside_if && pcp_outfile && defn->predefined)
                   8066:     dump_single_macro (hp, pcp_outfile);
                   8067:   
                   8068:   nargs = defn->nargs;
                   8069: 
                   8070:   if (nargs >= 0) {
                   8071:     register int i;
                   8072:     struct argdata *args;
                   8073:     char *parse_error = 0;
                   8074: 
                   8075:     args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
                   8076: 
                   8077:     for (i = 0; i < nargs; i++) {
1.1.1.5   root     8078:       args[i].raw = (U_CHAR *) "";
                   8079:       args[i].expanded = 0;
1.1       root     8080:       args[i].raw_length = args[i].expand_length
                   8081:        = args[i].stringified_length = 0;
                   8082:       args[i].free1 = args[i].free2 = 0;
                   8083:       args[i].use_count = 0;
                   8084:     }
                   8085: 
                   8086:     /* Parse all the macro args that are supplied.  I counts them.
                   8087:        The first NARGS args are stored in ARGS.
1.1.1.3   root     8088:        The rest are discarded.
                   8089:        If rest_args is set then we assume macarg absorbed the rest of the args.
                   8090:        */
1.1       root     8091:     i = 0;
1.1.1.3   root     8092:     rest_args = 0;
1.1       root     8093:     do {
                   8094:       /* Discard the open-parenthesis or comma before the next arg.  */
                   8095:       ++instack[indepth].bufp;
1.1.1.3   root     8096:       if (rest_args)
                   8097:        continue;
                   8098:       if (i < nargs || (nargs == 0 && i == 0)) {
1.1.1.4   root     8099:        /* if we are working on last arg which absorbs rest of args... */
1.1.1.3   root     8100:        if (i == nargs - 1 && defn->rest_args)
                   8101:          rest_args = 1;
                   8102:        parse_error = macarg (&args[i], rest_args);
                   8103:       }
                   8104:       else
1.1.1.4   root     8105:        parse_error = macarg (NULL_PTR, 0);
1.1       root     8106:       if (parse_error) {
                   8107:        error_with_line (line_for_error (start_line), parse_error);
                   8108:        break;
                   8109:       }
                   8110:       i++;
                   8111:     } while (*instack[indepth].bufp != ')');
                   8112: 
                   8113:     /* If we got one arg but it was just whitespace, call that 0 args.  */
                   8114:     if (i == 1) {
                   8115:       register U_CHAR *bp = args[0].raw;
                   8116:       register U_CHAR *lim = bp + args[0].raw_length;
1.1.1.5   root     8117:       /* cpp.texi says for foo ( ) we provide one argument.
                   8118:         However, if foo wants just 0 arguments, treat this as 0.  */
                   8119:       if (nargs == 0)
                   8120:        while (bp != lim && is_space[*bp]) bp++;
1.1       root     8121:       if (bp == lim)
                   8122:        i = 0;
                   8123:     }
                   8124: 
1.1.1.4   root     8125:     /* Don't output an error message if we have already output one for
                   8126:        a parse error above.  */
1.1.1.3   root     8127:     rest_zero = 0;
1.1.1.4   root     8128:     if (nargs == 0 && i > 0) {
                   8129:       if (! parse_error)
                   8130:        error ("arguments given to macro `%s'", hp->name);
                   8131:     } else if (i < nargs) {
1.1       root     8132:       /* traditional C allows foo() if foo wants one argument.  */
                   8133:       if (nargs == 1 && i == 0 && traditional)
                   8134:        ;
1.1.1.3   root     8135:       /* the rest args token is allowed to absorb 0 tokens */
                   8136:       else if (i == nargs - 1 && defn->rest_args)
                   8137:        rest_zero = 1;
1.1.1.4   root     8138:       else if (parse_error)
                   8139:        ;
1.1       root     8140:       else if (i == 0)
                   8141:        error ("macro `%s' used without args", hp->name);
                   8142:       else if (i == 1)
                   8143:        error ("macro `%s' used with just one arg", hp->name);
                   8144:       else
                   8145:        error ("macro `%s' used with only %d args", hp->name, i);
1.1.1.4   root     8146:     } else if (i > nargs) {
                   8147:       if (! parse_error)
                   8148:        error ("macro `%s' used with too many (%d) args", hp->name, i);
                   8149:     }
1.1       root     8150: 
                   8151:     /* Swallow the closeparen.  */
                   8152:     ++instack[indepth].bufp;
                   8153: 
                   8154:     /* If macro wants zero args, we parsed the arglist for checking only.
                   8155:        Read directly from the macro definition.  */
                   8156:     if (nargs == 0) {
                   8157:       xbuf = defn->expansion;
                   8158:       xbuf_len = defn->length;
                   8159:     } else {
                   8160:       register U_CHAR *exp = defn->expansion;
                   8161:       register int offset;     /* offset in expansion,
                   8162:                                   copied a piece at a time */
                   8163:       register int totlen;     /* total amount of exp buffer filled so far */
                   8164: 
1.1.1.3   root     8165:       register struct reflist *ap, *last_ap;
1.1       root     8166: 
                   8167:       /* Macro really takes args.  Compute the expansion of this call.  */
                   8168: 
                   8169:       /* Compute length in characters of the macro's expansion.
                   8170:         Also count number of times each arg is used.  */
                   8171:       xbuf_len = defn->length;
                   8172:       for (ap = defn->pattern; ap != NULL; ap = ap->next) {
                   8173:        if (ap->stringify)
                   8174:          xbuf_len += args[ap->argno].stringified_length;
1.1.1.8 ! root     8175:        else if (ap->raw_before != 0 || ap->raw_after != 0 || traditional)
1.1.1.5   root     8176:          /* Add 4 for two newline-space markers to prevent
                   8177:             token concatenation.  */
                   8178:          xbuf_len += args[ap->argno].raw_length + 4;
                   8179:        else {
                   8180:          /* We have an ordinary (expanded) occurrence of the arg.
                   8181:             So compute its expansion, if we have not already.  */
                   8182:          if (args[ap->argno].expanded == 0) {
                   8183:            FILE_BUF obuf;
                   8184:            obuf = expand_to_temp_buffer (args[ap->argno].raw,
                   8185:                                          args[ap->argno].raw + args[ap->argno].raw_length,
                   8186:                                          1, 0);
                   8187: 
                   8188:            args[ap->argno].expanded = obuf.buf;
                   8189:            args[ap->argno].expand_length = obuf.length;
                   8190:            args[ap->argno].free2 = obuf.buf;
                   8191:          }
                   8192: 
                   8193:          /* Add 4 for two newline-space markers to prevent
                   8194:             token concatenation.  */
                   8195:          xbuf_len += args[ap->argno].expand_length + 4;
                   8196:        }
1.1       root     8197:        if (args[ap->argno].use_count < 10)
                   8198:          args[ap->argno].use_count++;
                   8199:       }
                   8200: 
                   8201:       xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
                   8202: 
                   8203:       /* Generate in XBUF the complete expansion
                   8204:         with arguments substituted in.
                   8205:         TOTLEN is the total size generated so far.
                   8206:         OFFSET is the index in the definition
                   8207:         of where we are copying from.  */
                   8208:       offset = totlen = 0;
1.1.1.3   root     8209:       for (last_ap = NULL, ap = defn->pattern; ap != NULL;
                   8210:           last_ap = ap, ap = ap->next) {
1.1       root     8211:        register struct argdata *arg = &args[ap->argno];
1.1.1.5   root     8212:        int count_before = totlen;
1.1       root     8213: 
1.1.1.5   root     8214:        /* Add chars to XBUF.  */
1.1.1.3   root     8215:        for (i = 0; i < ap->nchars; i++, offset++)
1.1.1.5   root     8216:          xbuf[totlen++] = exp[offset];
                   8217: 
                   8218:        /* If followed by an empty rest arg with concatenation,
                   8219:           delete the last run of nonwhite chars.  */
                   8220:        if (rest_zero && totlen > count_before
1.1.1.8 ! root     8221:            && ((ap->rest_args && ap->raw_before != 0)
1.1.1.5   root     8222:                || (last_ap != NULL && last_ap->rest_args
1.1.1.8 ! root     8223:                    && last_ap->raw_after != 0))) {
1.1.1.5   root     8224:          /* Delete final whitespace.  */
                   8225:          while (totlen > count_before && is_space[xbuf[totlen - 1]]) {
                   8226:            totlen--;
                   8227:          }
                   8228: 
                   8229:          /* Delete the nonwhites before them.  */
                   8230:          while (totlen > count_before && ! is_space[xbuf[totlen - 1]]) {
                   8231:            totlen--;
                   8232:          }
                   8233:        }
1.1       root     8234: 
                   8235:        if (ap->stringify != 0) {
                   8236:          int arglen = arg->raw_length;
                   8237:          int escaped = 0;
                   8238:          int in_string = 0;
                   8239:          int c;
                   8240:          i = 0;
                   8241:          while (i < arglen
                   8242:                 && (c = arg->raw[i], is_space[c]))
                   8243:            i++;
                   8244:          while (i < arglen
                   8245:                 && (c = arg->raw[arglen - 1], is_space[c]))
                   8246:            arglen--;
                   8247:          if (!traditional)
                   8248:            xbuf[totlen++] = '\"'; /* insert beginning quote */
                   8249:          for (; i < arglen; i++) {
                   8250:            c = arg->raw[i];
                   8251: 
                   8252:            /* Special markers Newline Space
                   8253:               generate nothing for a stringified argument.  */
                   8254:            if (c == '\n' && arg->raw[i+1] != '\n') {
                   8255:              i++;
                   8256:              continue;
                   8257:            }
                   8258: 
                   8259:            /* Internal sequences of whitespace are replaced by one space
                   8260:               except within an string or char token.  */
                   8261:            if (! in_string
                   8262:                && (c == '\n' ? arg->raw[i+1] == '\n' : is_space[c])) {
                   8263:              while (1) {
                   8264:                /* Note that Newline Space does occur within whitespace
                   8265:                   sequences; consider it part of the sequence.  */
                   8266:                if (c == '\n' && is_space[arg->raw[i+1]])
                   8267:                  i += 2;
                   8268:                else if (c != '\n' && is_space[c])
                   8269:                  i++;
                   8270:                else break;
                   8271:                c = arg->raw[i];
                   8272:              }
                   8273:              i--;
                   8274:              c = ' ';
                   8275:            }
                   8276: 
                   8277:            if (escaped)
                   8278:              escaped = 0;
                   8279:            else {
                   8280:              if (c == '\\')
                   8281:                escaped = 1;
                   8282:              if (in_string) {
                   8283:                if (c == in_string)
                   8284:                  in_string = 0;
                   8285:              } else if (c == '\"' || c == '\'')
                   8286:                in_string = c;
                   8287:            }
                   8288: 
                   8289:            /* Escape these chars */
                   8290:            if (c == '\"' || (in_string && c == '\\'))
                   8291:              xbuf[totlen++] = '\\';
                   8292:            if (isprint (c))
                   8293:              xbuf[totlen++] = c;
                   8294:            else {
                   8295:              sprintf ((char *) &xbuf[totlen], "\\%03o", (unsigned int) c);
                   8296:              totlen += 4;
                   8297:            }
                   8298:          }
                   8299:          if (!traditional)
                   8300:            xbuf[totlen++] = '\"'; /* insert ending quote */
1.1.1.8 ! root     8301:        } else if (ap->raw_before != 0 || ap->raw_after != 0 || traditional) {
1.1       root     8302:          U_CHAR *p1 = arg->raw;
                   8303:          U_CHAR *l1 = p1 + arg->raw_length;
1.1.1.8 ! root     8304:          if (ap->raw_before != 0) {
1.1       root     8305:            while (p1 != l1 && is_space[*p1]) p1++;
                   8306:            while (p1 != l1 && is_idchar[*p1])
                   8307:              xbuf[totlen++] = *p1++;
                   8308:            /* Delete any no-reexpansion marker that follows
                   8309:               an identifier at the beginning of the argument
                   8310:               if the argument is concatenated with what precedes it.  */
                   8311:            if (p1[0] == '\n' && p1[1] == '-')
                   8312:              p1 += 2;
1.1.1.5   root     8313:          } else if (!traditional) {
                   8314:          /* Ordinary expanded use of the argument.
                   8315:             Put in newline-space markers to prevent token pasting.  */
                   8316:            xbuf[totlen++] = '\n';
                   8317:            xbuf[totlen++] = ' ';
1.1       root     8318:          }
1.1.1.8 ! root     8319:          if (ap->raw_after != 0) {
1.1       root     8320:            /* Arg is concatenated after: delete trailing whitespace,
                   8321:               whitespace markers, and no-reexpansion markers.  */
                   8322:            while (p1 != l1) {
                   8323:              if (is_space[l1[-1]]) l1--;
                   8324:              else if (l1[-1] == '-') {
                   8325:                U_CHAR *p2 = l1 - 1;
                   8326:                /* If a `-' is preceded by an odd number of newlines then it
                   8327:                   and the last newline are a no-reexpansion marker.  */
                   8328:                while (p2 != p1 && p2[-1] == '\n') p2--;
                   8329:                if ((l1 - 1 - p2) & 1) {
                   8330:                  l1 -= 2;
                   8331:                }
                   8332:                else break;
                   8333:              }
                   8334:              else break;
                   8335:            }
                   8336:          }
1.1.1.5   root     8337: 
1.1.1.7   root     8338:          bcopy ((char *) p1, (char *) (xbuf + totlen), l1 - p1);
1.1       root     8339:          totlen += l1 - p1;
1.1.1.8 ! root     8340:          if (!traditional && ap->raw_after == 0) {
1.1.1.5   root     8341:            /* Ordinary expanded use of the argument.
                   8342:               Put in newline-space markers to prevent token pasting.  */
                   8343:            xbuf[totlen++] = '\n';
                   8344:            xbuf[totlen++] = ' ';
                   8345:          }
1.1       root     8346:        } else {
1.1.1.5   root     8347:          /* Ordinary expanded use of the argument.
                   8348:             Put in newline-space markers to prevent token pasting.  */
                   8349:          if (!traditional) {
                   8350:            xbuf[totlen++] = '\n';
                   8351:            xbuf[totlen++] = ' ';
                   8352:          }
1.1.1.7   root     8353:          bcopy ((char *) arg->expanded, (char *) (xbuf + totlen),
                   8354:                 arg->expand_length);
1.1       root     8355:          totlen += arg->expand_length;
1.1.1.5   root     8356:          if (!traditional) {
                   8357:            xbuf[totlen++] = '\n';
                   8358:            xbuf[totlen++] = ' ';
                   8359:          }
1.1       root     8360:          /* If a macro argument with newlines is used multiple times,
                   8361:             then only expand the newlines once.  This avoids creating output
                   8362:             lines which don't correspond to any input line, which confuses
                   8363:             gdb and gcov.  */
                   8364:          if (arg->use_count > 1 && arg->newlines > 0) {
1.1.1.5   root     8365:            /* Don't bother doing change_newlines for subsequent
1.1       root     8366:               uses of arg.  */
                   8367:            arg->use_count = 1;
                   8368:            arg->expand_length
1.1.1.5   root     8369:              = change_newlines (arg->expanded, arg->expand_length);
1.1       root     8370:          }
                   8371:        }
                   8372: 
                   8373:        if (totlen > xbuf_len)
                   8374:          abort ();
                   8375:       }
                   8376: 
                   8377:       /* if there is anything left of the definition
                   8378:         after handling the arg list, copy that in too. */
                   8379: 
1.1.1.3   root     8380:       for (i = offset; i < defn->length; i++) {
                   8381:        /* if we've reached the end of the macro */
                   8382:        if (exp[i] == ')')
                   8383:          rest_zero = 0;
                   8384:        if (! (rest_zero && last_ap != NULL && last_ap->rest_args
1.1.1.8 ! root     8385:               && last_ap->raw_after != 0))
1.1.1.3   root     8386:          xbuf[totlen++] = exp[i];
                   8387:       }
1.1       root     8388: 
                   8389:       xbuf[totlen] = 0;
                   8390:       xbuf_len = totlen;
                   8391: 
                   8392:       for (i = 0; i < nargs; i++) {
                   8393:        if (args[i].free1 != 0)
                   8394:          free (args[i].free1);
                   8395:        if (args[i].free2 != 0)
                   8396:          free (args[i].free2);
                   8397:       }
                   8398:     }
                   8399:   } else {
                   8400:     xbuf = defn->expansion;
                   8401:     xbuf_len = defn->length;
                   8402:   }
                   8403: 
                   8404:   /* Now put the expansion on the input stack
                   8405:      so our caller will commence reading from it.  */
                   8406:   {
                   8407:     register FILE_BUF *ip2;
                   8408: 
                   8409:     ip2 = &instack[++indepth];
                   8410: 
                   8411:     ip2->fname = 0;
                   8412:     ip2->nominal_fname = 0;
1.1.1.7   root     8413:     /* This may not be exactly correct, but will give much better error
                   8414:        messages for nested macro calls than using a line number of zero.  */
                   8415:     ip2->lineno = start_line;
1.1       root     8416:     ip2->buf = xbuf;
                   8417:     ip2->length = xbuf_len;
                   8418:     ip2->bufp = xbuf;
                   8419:     ip2->free_ptr = (nargs > 0) ? xbuf : 0;
                   8420:     ip2->macro = hp;
                   8421:     ip2->if_stack = if_stack;
                   8422:     ip2->system_header_p = 0;
                   8423: 
                   8424:     /* Recursive macro use sometimes works traditionally.
1.1.1.5   root     8425:        #define foo(x,y) bar (x (y,0), y)
                   8426:        foo (foo, baz)  */
1.1       root     8427: 
                   8428:     if (!traditional)
                   8429:       hp->type = T_DISABLED;
                   8430:   }
                   8431: }
                   8432: 
                   8433: /*
                   8434:  * Parse a macro argument and store the info on it into *ARGPTR.
1.1.1.3   root     8435:  * REST_ARGS is passed to macarg1 to make it absorb the rest of the args.
1.1       root     8436:  * Return nonzero to indicate a syntax error.
                   8437:  */
                   8438: 
                   8439: static char *
1.1.1.3   root     8440: macarg (argptr, rest_args)
1.1       root     8441:      register struct argdata *argptr;
1.1.1.3   root     8442:      int rest_args;
1.1       root     8443: {
                   8444:   FILE_BUF *ip = &instack[indepth];
                   8445:   int paren = 0;
                   8446:   int newlines = 0;
                   8447:   int comments = 0;
1.1.1.8 ! root     8448:   char *result = 0;
1.1       root     8449: 
                   8450:   /* Try to parse as much of the argument as exists at this
                   8451:      input stack level.  */
                   8452:   U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length,
1.1.1.3   root     8453:                        &paren, &newlines, &comments, rest_args);
1.1       root     8454: 
                   8455:   /* If we find the end of the argument at this level,
                   8456:      set up *ARGPTR to point at it in the input stack.  */
                   8457:   if (!(ip->fname != 0 && (newlines != 0 || comments != 0))
                   8458:       && bp != ip->buf + ip->length) {
                   8459:     if (argptr != 0) {
                   8460:       argptr->raw = ip->bufp;
                   8461:       argptr->raw_length = bp - ip->bufp;
                   8462:       argptr->newlines = newlines;
                   8463:     }
                   8464:     ip->bufp = bp;
                   8465:   } else {
                   8466:     /* This input stack level ends before the macro argument does.
                   8467:        We must pop levels and keep parsing.
                   8468:        Therefore, we must allocate a temporary buffer and copy
                   8469:        the macro argument into it.  */
                   8470:     int bufsize = bp - ip->bufp;
                   8471:     int extra = newlines;
                   8472:     U_CHAR *buffer = (U_CHAR *) xmalloc (bufsize + extra + 1);
                   8473:     int final_start = 0;
                   8474: 
1.1.1.7   root     8475:     bcopy ((char *) ip->bufp, (char *) buffer, bufsize);
1.1       root     8476:     ip->bufp = bp;
                   8477:     ip->lineno += newlines;
                   8478: 
                   8479:     while (bp == ip->buf + ip->length) {
                   8480:       if (instack[indepth].macro == 0) {
1.1.1.8 ! root     8481:        result = "unterminated macro call";
        !          8482:        break;
1.1       root     8483:       }
                   8484:       ip->macro->type = T_MACRO;
                   8485:       if (ip->free_ptr)
                   8486:        free (ip->free_ptr);
                   8487:       ip = &instack[--indepth];
                   8488:       newlines = 0;
                   8489:       comments = 0;
                   8490:       bp = macarg1 (ip->bufp, ip->buf + ip->length, &paren,
1.1.1.3   root     8491:                    &newlines, &comments, rest_args);
1.1       root     8492:       final_start = bufsize;
                   8493:       bufsize += bp - ip->bufp;
                   8494:       extra += newlines;
                   8495:       buffer = (U_CHAR *) xrealloc (buffer, bufsize + extra + 1);
1.1.1.7   root     8496:       bcopy ((char *) ip->bufp, (char *) (buffer + bufsize - (bp - ip->bufp)),
                   8497:             bp - ip->bufp);
1.1       root     8498:       ip->bufp = bp;
                   8499:       ip->lineno += newlines;
                   8500:     }
                   8501: 
                   8502:     /* Now, if arg is actually wanted, record its raw form,
                   8503:        discarding comments and duplicating newlines in whatever
                   8504:        part of it did not come from a macro expansion.
                   8505:        EXTRA space has been preallocated for duplicating the newlines.
                   8506:        FINAL_START is the index of the start of that part.  */
                   8507:     if (argptr != 0) {
                   8508:       argptr->raw = buffer;
                   8509:       argptr->raw_length = bufsize;
                   8510:       argptr->free1 = buffer;
                   8511:       argptr->newlines = newlines;
                   8512:       if ((newlines || comments) && ip->fname != 0)
                   8513:        argptr->raw_length
                   8514:          = final_start +
                   8515:            discard_comments (argptr->raw + final_start,
                   8516:                              argptr->raw_length - final_start,
                   8517:                              newlines);
                   8518:       argptr->raw[argptr->raw_length] = 0;
                   8519:       if (argptr->raw_length > bufsize + extra)
                   8520:        abort ();
                   8521:     }
                   8522:   }
                   8523: 
                   8524:   /* If we are not discarding this argument,
                   8525:      macroexpand it and compute its length as stringified.
                   8526:      All this info goes into *ARGPTR.  */
                   8527: 
                   8528:   if (argptr != 0) {
                   8529:     register U_CHAR *buf, *lim;
                   8530:     register int totlen;
                   8531: 
                   8532:     buf = argptr->raw;
                   8533:     lim = buf + argptr->raw_length;
                   8534: 
                   8535:     while (buf != lim && is_space[*buf])
                   8536:       buf++;
                   8537:     while (buf != lim && is_space[lim[-1]])
                   8538:       lim--;
                   8539:     totlen = traditional ? 0 : 2;      /* Count opening and closing quote.  */
                   8540:     while (buf != lim) {
                   8541:       register U_CHAR c = *buf++;
                   8542:       totlen++;
                   8543:       /* Internal sequences of whitespace are replaced by one space
                   8544:         in most cases, but not always.  So count all the whitespace
                   8545:         in case we need to keep it all.  */
                   8546: #if 0
                   8547:       if (is_space[c])
                   8548:        SKIP_ALL_WHITE_SPACE (buf);
                   8549:       else
                   8550: #endif
                   8551:       if (c == '\"' || c == '\\') /* escape these chars */
                   8552:        totlen++;
                   8553:       else if (!isprint (c))
                   8554:        totlen += 3;
                   8555:     }
                   8556:     argptr->stringified_length = totlen;
                   8557:   }
1.1.1.8 ! root     8558:   return result;
1.1       root     8559: }
                   8560: 
                   8561: /* Scan text from START (inclusive) up to LIMIT (exclusive),
                   8562:    counting parens in *DEPTHPTR,
                   8563:    and return if reach LIMIT
                   8564:    or before a `)' that would make *DEPTHPTR negative
                   8565:    or before a comma when *DEPTHPTR is zero.
                   8566:    Single and double quotes are matched and termination
                   8567:    is inhibited within them.  Comments also inhibit it.
                   8568:    Value returned is pointer to stopping place.
                   8569: 
                   8570:    Increment *NEWLINES each time a newline is passed.
1.1.1.3   root     8571:    REST_ARGS notifies macarg1 that it should absorb the rest of the args.
1.1       root     8572:    Set *COMMENTS to 1 if a comment is seen.  */
                   8573: 
                   8574: static U_CHAR *
1.1.1.3   root     8575: macarg1 (start, limit, depthptr, newlines, comments, rest_args)
1.1       root     8576:      U_CHAR *start;
                   8577:      register U_CHAR *limit;
                   8578:      int *depthptr, *newlines, *comments;
1.1.1.3   root     8579:      int rest_args;
1.1       root     8580: {
                   8581:   register U_CHAR *bp = start;
                   8582: 
                   8583:   while (bp < limit) {
                   8584:     switch (*bp) {
                   8585:     case '(':
                   8586:       (*depthptr)++;
                   8587:       break;
                   8588:     case ')':
                   8589:       if (--(*depthptr) < 0)
                   8590:        return bp;
                   8591:       break;
                   8592:     case '\\':
                   8593:       /* Traditionally, backslash makes following char not special.  */
                   8594:       if (bp + 1 < limit && traditional)
                   8595:        {
                   8596:          bp++;
                   8597:          /* But count source lines anyway.  */
                   8598:          if (*bp == '\n')
                   8599:            ++*newlines;
                   8600:        }
                   8601:       break;
                   8602:     case '\n':
                   8603:       ++*newlines;
                   8604:       break;
                   8605:     case '/':
                   8606:       if (bp[1] == '\\' && bp[2] == '\n')
                   8607:        newline_fix (bp + 1);
1.1.1.4   root     8608:       if (cplusplus_comments && bp[1] == '/') {
1.1       root     8609:        *comments = 1;
                   8610:        bp += 2;
1.1.1.7   root     8611:        while (bp < limit && (*bp != '\n' || bp[-1] == '\\')) {
                   8612:          if (*bp == '\n') ++*newlines;
                   8613:          bp++;
                   8614:        }
1.1.1.8 ! root     8615:        /* Now count the newline that we are about to skip.  */
        !          8616:        ++*newlines;
1.1       root     8617:        break;
                   8618:       }
                   8619:       if (bp[1] != '*' || bp + 1 >= limit)
                   8620:        break;
                   8621:       *comments = 1;
                   8622:       bp += 2;
                   8623:       while (bp + 1 < limit) {
                   8624:        if (bp[0] == '*'
                   8625:            && bp[1] == '\\' && bp[2] == '\n')
                   8626:          newline_fix (bp + 1);
                   8627:        if (bp[0] == '*' && bp[1] == '/')
                   8628:          break;
                   8629:        if (*bp == '\n') ++*newlines;
                   8630:        bp++;
                   8631:       }
                   8632:       break;
                   8633:     case '\'':
                   8634:     case '\"':
                   8635:       {
                   8636:        int quotec;
                   8637:        for (quotec = *bp++; bp + 1 < limit && *bp != quotec; bp++) {
                   8638:          if (*bp == '\\') {
                   8639:            bp++;
                   8640:            if (*bp == '\n')
                   8641:              ++*newlines;
                   8642:            while (*bp == '\\' && bp[1] == '\n') {
                   8643:              bp += 2;
                   8644:            }
                   8645:          } else if (*bp == '\n') {
                   8646:            ++*newlines;
                   8647:            if (quotec == '\'')
                   8648:              break;
                   8649:          }
                   8650:        }
                   8651:       }
                   8652:       break;
                   8653:     case ',':
1.1.1.3   root     8654:       /* if we've returned to lowest level and we aren't absorbing all args */
                   8655:       if ((*depthptr) == 0 && rest_args == 0)
1.1       root     8656:        return bp;
                   8657:       break;
                   8658:     }
                   8659:     bp++;
                   8660:   }
                   8661: 
                   8662:   return bp;
                   8663: }
                   8664: 
                   8665: /* Discard comments and duplicate newlines
                   8666:    in the string of length LENGTH at START,
                   8667:    except inside of string constants.
                   8668:    The string is copied into itself with its beginning staying fixed.  
                   8669: 
                   8670:    NEWLINES is the number of newlines that must be duplicated.
                   8671:    We assume that that much extra space is available past the end
                   8672:    of the string.  */
                   8673: 
                   8674: static int
                   8675: discard_comments (start, length, newlines)
                   8676:      U_CHAR *start;
                   8677:      int length;
                   8678:      int newlines;
                   8679: {
                   8680:   register U_CHAR *ibp;
                   8681:   register U_CHAR *obp;
                   8682:   register U_CHAR *limit;
                   8683:   register int c;
                   8684: 
                   8685:   /* If we have newlines to duplicate, copy everything
                   8686:      that many characters up.  Then, in the second part,
                   8687:      we will have room to insert the newlines
                   8688:      while copying down.
                   8689:      NEWLINES may actually be too large, because it counts
                   8690:      newlines in string constants, and we don't duplicate those.
                   8691:      But that does no harm.  */
                   8692:   if (newlines > 0) {
                   8693:     ibp = start + length;
                   8694:     obp = ibp + newlines;
                   8695:     limit = start;
                   8696:     while (limit != ibp)
                   8697:       *--obp = *--ibp;
                   8698:   }
                   8699: 
                   8700:   ibp = start + newlines;
                   8701:   limit = start + length + newlines;
                   8702:   obp = start;
                   8703: 
                   8704:   while (ibp < limit) {
                   8705:     *obp++ = c = *ibp++;
                   8706:     switch (c) {
                   8707:     case '\n':
                   8708:       /* Duplicate the newline.  */
                   8709:       *obp++ = '\n';
                   8710:       break;
                   8711: 
                   8712:     case '\\':
                   8713:       if (*ibp == '\n') {
                   8714:        obp--;
                   8715:        ibp++;
                   8716:       }
                   8717:       break;
                   8718: 
                   8719:     case '/':
                   8720:       if (*ibp == '\\' && ibp[1] == '\n')
                   8721:        newline_fix (ibp);
                   8722:       /* Delete any comment.  */
1.1.1.4   root     8723:       if (cplusplus_comments && ibp[0] == '/') {
1.1.1.7   root     8724:        /* Comments are equivalent to spaces.  */
                   8725:        obp[-1] = ' ';
1.1       root     8726:        ibp++;
1.1.1.7   root     8727:        while (ibp < limit && (*ibp != '\n' || ibp[-1] == '\\'))
                   8728:          ibp++;
1.1       root     8729:        break;
                   8730:       }
                   8731:       if (ibp[0] != '*' || ibp + 1 >= limit)
                   8732:        break;
1.1.1.8 ! root     8733:       /* Comments are equivalent to spaces.
        !          8734:         For -traditional, a comment is equivalent to nothing.  */
        !          8735:       if (traditional)
        !          8736:        obp--;
        !          8737:       else
        !          8738:        obp[-1] = ' ';
1.1       root     8739:       ibp++;
                   8740:       while (ibp + 1 < limit) {
                   8741:        if (ibp[0] == '*'
                   8742:            && ibp[1] == '\\' && ibp[2] == '\n')
                   8743:          newline_fix (ibp + 1);
                   8744:        if (ibp[0] == '*' && ibp[1] == '/')
                   8745:          break;
                   8746:        ibp++;
                   8747:       }
                   8748:       ibp += 2;
                   8749:       break;
                   8750: 
                   8751:     case '\'':
                   8752:     case '\"':
                   8753:       /* Notice and skip strings, so that we don't
                   8754:         think that comments start inside them,
                   8755:         and so we don't duplicate newlines in them.  */
                   8756:       {
                   8757:        int quotec = c;
                   8758:        while (ibp < limit) {
                   8759:          *obp++ = c = *ibp++;
                   8760:          if (c == quotec)
                   8761:            break;
                   8762:          if (c == '\n' && quotec == '\'')
                   8763:            break;
                   8764:          if (c == '\\' && ibp < limit) {
                   8765:            while (*ibp == '\\' && ibp[1] == '\n')
                   8766:              ibp += 2;
                   8767:            *obp++ = *ibp++;
                   8768:          }
                   8769:        }
                   8770:       }
                   8771:       break;
                   8772:     }
                   8773:   }
                   8774: 
                   8775:   return obp - start;
                   8776: }
                   8777: 
1.1.1.5   root     8778: /* Turn newlines to spaces in the string of length LENGTH at START,
                   8779:    except inside of string constants.
                   8780:    The string is copied into itself with its beginning staying fixed.  */
1.1       root     8781: 
                   8782: static int
1.1.1.5   root     8783: change_newlines (start, length)
1.1       root     8784:      U_CHAR *start;
                   8785:      int length;
                   8786: {
                   8787:   register U_CHAR *ibp;
                   8788:   register U_CHAR *obp;
                   8789:   register U_CHAR *limit;
                   8790:   register int c;
                   8791: 
                   8792:   ibp = start;
                   8793:   limit = start + length;
                   8794:   obp = start;
                   8795: 
                   8796:   while (ibp < limit) {
                   8797:     *obp++ = c = *ibp++;
                   8798:     switch (c) {
                   8799:     case '\n':
                   8800:       /* If this is a NEWLINE NEWLINE, then this is a real newline in the
1.1.1.5   root     8801:         string.  Skip past the newline and its duplicate.
                   8802:         Put a space in the output.  */
1.1       root     8803:       if (*ibp == '\n')
                   8804:        {
                   8805:          ibp++;
                   8806:          obp--;
1.1.1.5   root     8807:          *obp++ = ' ';
1.1       root     8808:        }
                   8809:       break;
                   8810: 
                   8811:     case '\'':
                   8812:     case '\"':
                   8813:       /* Notice and skip strings, so that we don't delete newlines in them.  */
                   8814:       {
                   8815:        int quotec = c;
                   8816:        while (ibp < limit) {
                   8817:          *obp++ = c = *ibp++;
                   8818:          if (c == quotec)
                   8819:            break;
                   8820:          if (c == '\n' && quotec == '\'')
                   8821:            break;
                   8822:        }
                   8823:       }
                   8824:       break;
                   8825:     }
                   8826:   }
                   8827: 
                   8828:   return obp - start;
                   8829: }
                   8830: 
                   8831: /*
1.1.1.7   root     8832:  * my_strerror - return the descriptive text associated with an `errno' code.
                   8833:  */
                   8834: 
                   8835: char *
                   8836: my_strerror (errnum)
                   8837:      int errnum;
                   8838: {
                   8839:   char *result;
                   8840: 
                   8841: #ifndef VMS
                   8842: #ifndef HAVE_STRERROR
                   8843:   result = (char *) ((errnum < sys_nerr) ? sys_errlist[errnum] : 0);
                   8844: #else
                   8845:   result = strerror (errnum);
                   8846: #endif
                   8847: #else  /* VMS */
                   8848:   /* VAXCRTL's strerror() takes an optional second argument, which only
                   8849:      matters when the first argument is EVMSERR.  However, it's simplest
                   8850:      just to pass it unconditionally.  `vaxc$errno' is declared in
                   8851:      <errno.h>, and maintained by the library in parallel with `errno'.
                   8852:      We assume that caller's `errnum' either matches the last setting of
                   8853:      `errno' by the library or else does not have the value `EVMSERR'.  */
                   8854: 
                   8855:   result = strerror (errnum, vaxc$errno);
                   8856: #endif
                   8857: 
                   8858:   if (!result)
                   8859:     result = "undocumented I/O error";
                   8860: 
                   8861:   return result;
                   8862: }
                   8863: 
                   8864: /*
1.1       root     8865:  * error - print error message and increment count of errors.
                   8866:  */
                   8867: 
                   8868: void
1.1.1.8 ! root     8869: error (PRINTF_ALIST (msg))
        !          8870:      PRINTF_DCL (msg)
        !          8871: {
        !          8872:   va_list args;
        !          8873: 
        !          8874:   VA_START (args, msg);
        !          8875:   verror (msg, args);
        !          8876:   va_end (args);
        !          8877: }
        !          8878: 
        !          8879: static void
        !          8880: verror (msg, args)
1.1       root     8881:      char *msg;
1.1.1.8 ! root     8882:      va_list args;
1.1       root     8883: {
                   8884:   int i;
                   8885:   FILE_BUF *ip = NULL;
                   8886: 
                   8887:   print_containing_files ();
                   8888: 
                   8889:   for (i = indepth; i >= 0; i--)
                   8890:     if (instack[i].fname != NULL) {
                   8891:       ip = &instack[i];
                   8892:       break;
                   8893:     }
                   8894: 
                   8895:   if (ip != NULL)
                   8896:     fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
1.1.1.8 ! root     8897:   vfprintf (stderr, msg, args);
1.1       root     8898:   fprintf (stderr, "\n");
                   8899:   errors++;
                   8900: }
                   8901: 
                   8902: /* Error including a message from `errno'.  */
                   8903: 
                   8904: static void
                   8905: error_from_errno (name)
                   8906:      char *name;
                   8907: {
                   8908:   int i;
                   8909:   FILE_BUF *ip = NULL;
                   8910: 
                   8911:   print_containing_files ();
                   8912: 
                   8913:   for (i = indepth; i >= 0; i--)
                   8914:     if (instack[i].fname != NULL) {
                   8915:       ip = &instack[i];
                   8916:       break;
                   8917:     }
                   8918: 
                   8919:   if (ip != NULL)
                   8920:     fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
                   8921: 
1.1.1.7   root     8922:   fprintf (stderr, "%s: %s\n", name, my_strerror (errno));
1.1       root     8923: 
                   8924:   errors++;
                   8925: }
                   8926: 
                   8927: /* Print error message but don't count it.  */
                   8928: 
                   8929: void
1.1.1.8 ! root     8930: warning (PRINTF_ALIST (msg))
        !          8931:      PRINTF_DCL (msg)
        !          8932: {
        !          8933:   va_list args;
        !          8934: 
        !          8935:   VA_START (args, msg);
        !          8936:   vwarning (msg, args);
        !          8937:   va_end (args);
        !          8938: }
        !          8939: 
        !          8940: static void
        !          8941: vwarning (msg, args)
1.1       root     8942:      char *msg;
1.1.1.8 ! root     8943:      va_list args;
1.1       root     8944: {
                   8945:   int i;
                   8946:   FILE_BUF *ip = NULL;
                   8947: 
                   8948:   if (inhibit_warnings)
                   8949:     return;
                   8950: 
                   8951:   if (warnings_are_errors)
                   8952:     errors++;
                   8953: 
                   8954:   print_containing_files ();
                   8955: 
                   8956:   for (i = indepth; i >= 0; i--)
                   8957:     if (instack[i].fname != NULL) {
                   8958:       ip = &instack[i];
                   8959:       break;
                   8960:     }
                   8961: 
                   8962:   if (ip != NULL)
                   8963:     fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
                   8964:   fprintf (stderr, "warning: ");
1.1.1.8 ! root     8965:   vfprintf (stderr, msg, args);
1.1       root     8966:   fprintf (stderr, "\n");
                   8967: }
                   8968: 
                   8969: static void
1.1.1.8 ! root     8970: #if defined (__STDC__) && defined (HAVE_VPRINTF)
        !          8971: error_with_line (int line, PRINTF_ALIST (msg))
        !          8972: #else
        !          8973: error_with_line (line, PRINTF_ALIST (msg))
        !          8974:      int line;
        !          8975:      PRINTF_DCL (msg)
        !          8976: #endif
        !          8977: {
        !          8978:   va_list args;
        !          8979: 
        !          8980:   VA_START (args, msg);
        !          8981:   verror_with_line (line, msg, args);
        !          8982:   va_end (args);
        !          8983: }
        !          8984: 
        !          8985: static void
        !          8986: verror_with_line (line, msg, args)
1.1       root     8987:      int line;
                   8988:      char *msg;
1.1.1.8 ! root     8989:      va_list args;
1.1       root     8990: {
                   8991:   int i;
                   8992:   FILE_BUF *ip = NULL;
                   8993: 
                   8994:   print_containing_files ();
                   8995: 
                   8996:   for (i = indepth; i >= 0; i--)
                   8997:     if (instack[i].fname != NULL) {
                   8998:       ip = &instack[i];
                   8999:       break;
                   9000:     }
                   9001: 
                   9002:   if (ip != NULL)
                   9003:     fprintf (stderr, "%s:%d: ", ip->nominal_fname, line);
1.1.1.8 ! root     9004:   vfprintf (stderr, msg, args);
1.1       root     9005:   fprintf (stderr, "\n");
                   9006:   errors++;
                   9007: }
                   9008: 
1.1.1.5   root     9009: static void
1.1.1.8 ! root     9010: #if defined (__STDC__) && defined (HAVE_VPRINTF)
        !          9011: warning_with_line (int line, PRINTF_ALIST (msg))
        !          9012: #else
        !          9013: warning_with_line (line, PRINTF_ALIST (msg))
        !          9014:      int line;
        !          9015:      PRINTF_DCL (msg)
        !          9016: #endif
        !          9017: {
        !          9018:   va_list args;
        !          9019: 
        !          9020:   VA_START (args, msg);
        !          9021:   vwarning_with_line (line, msg, args);
        !          9022:   va_end (args);
        !          9023: }
        !          9024: 
        !          9025: static void
        !          9026: vwarning_with_line (line, msg, args)
1.1.1.5   root     9027:      int line;
                   9028:      char *msg;
1.1.1.8 ! root     9029:      va_list args;
1.1.1.5   root     9030: {
                   9031:   int i;
                   9032:   FILE_BUF *ip = NULL;
                   9033: 
                   9034:   if (inhibit_warnings)
                   9035:     return;
                   9036: 
                   9037:   if (warnings_are_errors)
                   9038:     errors++;
                   9039: 
                   9040:   print_containing_files ();
                   9041: 
                   9042:   for (i = indepth; i >= 0; i--)
                   9043:     if (instack[i].fname != NULL) {
                   9044:       ip = &instack[i];
                   9045:       break;
                   9046:     }
                   9047: 
                   9048:   if (ip != NULL)
1.1.1.8 ! root     9049:     fprintf (stderr, line ? "%s:%d: " : "%s: ", ip->nominal_fname, line);
1.1.1.5   root     9050:   fprintf (stderr, "warning: ");
1.1.1.8 ! root     9051:   vfprintf (stderr, msg, args);
1.1.1.5   root     9052:   fprintf (stderr, "\n");
                   9053: }
                   9054: 
1.1       root     9055: /* print an error message and maybe count it.  */
                   9056: 
                   9057: void
1.1.1.8 ! root     9058: pedwarn (PRINTF_ALIST (msg))
        !          9059:      PRINTF_DCL (msg)
1.1       root     9060: {
1.1.1.8 ! root     9061:   va_list args;
        !          9062: 
        !          9063:   VA_START (args, msg);
1.1       root     9064:   if (pedantic_errors)
1.1.1.8 ! root     9065:     verror (msg, args);
1.1       root     9066:   else
1.1.1.8 ! root     9067:     vwarning (msg, args);
        !          9068:   va_end (args);
1.1       root     9069: }
                   9070: 
1.1.1.5   root     9071: void
1.1.1.8 ! root     9072: #if defined (__STDC__) && defined (HAVE_VPRINTF)
        !          9073: pedwarn_with_line (int line, PRINTF_ALIST (msg))
        !          9074: #else
        !          9075: pedwarn_with_line (line, PRINTF_ALIST (msg))
1.1.1.5   root     9076:      int line;
1.1.1.8 ! root     9077:      PRINTF_DCL (msg)
        !          9078: #endif
1.1.1.5   root     9079: {
1.1.1.8 ! root     9080:   va_list args;
        !          9081: 
        !          9082:   VA_START (args, msg);
1.1.1.5   root     9083:   if (pedantic_errors)
1.1.1.8 ! root     9084:     verror_with_line (line, msg, args);
1.1.1.5   root     9085:   else
1.1.1.8 ! root     9086:     vwarning_with_line (line, msg, args);
        !          9087:   va_end (args);
1.1.1.5   root     9088: }
                   9089: 
1.1       root     9090: /* Report a warning (or an error if pedantic_errors)
                   9091:    giving specified file name and line number, not current.  */
                   9092: 
                   9093: static void
1.1.1.8 ! root     9094: #if defined (__STDC__) && defined (HAVE_VPRINTF)
        !          9095: pedwarn_with_file_and_line (char *file, int line, PRINTF_ALIST (msg))
        !          9096: #else
        !          9097: pedwarn_with_file_and_line (file, line, PRINTF_ALIST (msg))
1.1       root     9098:      char *file;
                   9099:      int line;
1.1.1.8 ! root     9100:      PRINTF_DCL (msg)
        !          9101: #endif
1.1       root     9102: {
1.1.1.8 ! root     9103:   va_list args;
        !          9104: 
1.1       root     9105:   if (!pedantic_errors && inhibit_warnings)
                   9106:     return;
                   9107:   if (file != NULL)
                   9108:     fprintf (stderr, "%s:%d: ", file, line);
1.1.1.5   root     9109:   if (pedantic_errors)
1.1       root     9110:     errors++;
                   9111:   if (!pedantic_errors)
                   9112:     fprintf (stderr, "warning: ");
1.1.1.8 ! root     9113:   VA_START (args, msg);
        !          9114:   vfprintf (stderr, msg, args);
        !          9115:   va_end (args);
1.1       root     9116:   fprintf (stderr, "\n");
                   9117: }
                   9118: 
                   9119: /* Print the file names and line numbers of the #include
1.1.1.8 ! root     9120:    directives which led to the current file.  */
1.1       root     9121: 
                   9122: static void
                   9123: print_containing_files ()
                   9124: {
                   9125:   FILE_BUF *ip = NULL;
                   9126:   int i;
                   9127:   int first = 1;
                   9128: 
                   9129:   /* If stack of files hasn't changed since we last printed
                   9130:      this info, don't repeat it.  */
                   9131:   if (last_error_tick == input_file_stack_tick)
                   9132:     return;
                   9133: 
                   9134:   for (i = indepth; i >= 0; i--)
                   9135:     if (instack[i].fname != NULL) {
                   9136:       ip = &instack[i];
                   9137:       break;
                   9138:     }
                   9139: 
                   9140:   /* Give up if we don't find a source file.  */
                   9141:   if (ip == NULL)
                   9142:     return;
                   9143: 
                   9144:   /* Find the other, outer source files.  */
                   9145:   for (i--; i >= 0; i--)
                   9146:     if (instack[i].fname != NULL) {
                   9147:       ip = &instack[i];
                   9148:       if (first) {
                   9149:        first = 0;
                   9150:        fprintf (stderr, "In file included");
                   9151:       } else {
1.1.1.6   root     9152:        fprintf (stderr, ",\n                ");
1.1       root     9153:       }
                   9154: 
                   9155:       fprintf (stderr, " from %s:%d", ip->nominal_fname, ip->lineno);
                   9156:     }
                   9157:   if (! first)
                   9158:     fprintf (stderr, ":\n");
                   9159: 
                   9160:   /* Record we have printed the status as of this time.  */
                   9161:   last_error_tick = input_file_stack_tick;
                   9162: }
                   9163: 
                   9164: /* Return the line at which an error occurred.
                   9165:    The error is not necessarily associated with the current spot
                   9166:    in the input stack, so LINE says where.  LINE will have been
                   9167:    copied from ip->lineno for the current input level.
                   9168:    If the current level is for a file, we return LINE.
                   9169:    But if the current level is not for a file, LINE is meaningless.
                   9170:    In that case, we return the lineno of the innermost file.  */
                   9171: 
                   9172: static int
                   9173: line_for_error (line)
                   9174:      int line;
                   9175: {
                   9176:   int i;
                   9177:   int line1 = line;
                   9178: 
                   9179:   for (i = indepth; i >= 0; ) {
                   9180:     if (instack[i].fname != 0)
                   9181:       return line1;
                   9182:     i--;
                   9183:     if (i < 0)
                   9184:       return 0;
                   9185:     line1 = instack[i].lineno;
                   9186:   }
                   9187:   abort ();
                   9188:   /*NOTREACHED*/
                   9189:   return 0;
                   9190: }
                   9191: 
                   9192: /*
                   9193:  * If OBUF doesn't have NEEDED bytes after OPTR, make it bigger.
                   9194:  *
                   9195:  * As things stand, nothing is ever placed in the output buffer to be
                   9196:  * removed again except when it's KNOWN to be part of an identifier,
                   9197:  * so flushing and moving down everything left, instead of expanding,
                   9198:  * should work ok.
                   9199:  */
                   9200: 
                   9201: /* You might think void was cleaner for the return type,
                   9202:    but that would get type mismatch in check_expand in strict ANSI.  */
                   9203: static int
                   9204: grow_outbuf (obuf, needed)
                   9205:      register FILE_BUF *obuf;
                   9206:      register int needed;
                   9207: {
                   9208:   register U_CHAR *p;
                   9209:   int minsize;
                   9210: 
                   9211:   if (obuf->length - (obuf->bufp - obuf->buf) > needed)
                   9212:     return 0;
                   9213: 
                   9214:   /* Make it at least twice as big as it is now.  */
                   9215:   obuf->length *= 2;
                   9216:   /* Make it have at least 150% of the free space we will need.  */
                   9217:   minsize = (3 * needed) / 2 + (obuf->bufp - obuf->buf);
                   9218:   if (minsize > obuf->length)
                   9219:     obuf->length = minsize;
                   9220: 
                   9221:   if ((p = (U_CHAR *) xrealloc (obuf->buf, obuf->length)) == NULL)
                   9222:     memory_full ();
                   9223: 
                   9224:   obuf->bufp = p + (obuf->bufp - obuf->buf);
                   9225:   obuf->buf = p;
                   9226: 
                   9227:   return 0;
                   9228: }
                   9229: 
                   9230: /* Symbol table for macro names and special symbols */
                   9231: 
                   9232: /*
                   9233:  * install a name in the main hash table, even if it is already there.
                   9234:  *   name stops with first non alphanumeric, except leading '#'.
                   9235:  * caller must check against redefinition if that is desired.
                   9236:  * delete_macro () removes things installed by install () in fifo order.
                   9237:  * this is important because of the `defined' special symbol used
                   9238:  * in #if, and also if pushdef/popdef directives are ever implemented.
                   9239:  *
                   9240:  * If LEN is >= 0, it is the length of the name.
                   9241:  * Otherwise, compute the length by scanning the entire name.
                   9242:  *
                   9243:  * If HASH is >= 0, it is the precomputed hash code.
                   9244:  * Otherwise, compute the hash code.
                   9245:  */
                   9246: static HASHNODE *
1.1.1.8 ! root     9247: install (name, len, type, value, hash)
1.1       root     9248:      U_CHAR *name;
                   9249:      int len;
                   9250:      enum node_type type;
1.1.1.4   root     9251:      char *value;
1.1       root     9252:      int hash;
                   9253: {
                   9254:   register HASHNODE *hp;
                   9255:   register int i, bucket;
                   9256:   register U_CHAR *p, *q;
                   9257: 
                   9258:   if (len < 0) {
                   9259:     p = name;
                   9260:     while (is_idchar[*p])
                   9261:       p++;
                   9262:     len = p - name;
                   9263:   }
                   9264: 
                   9265:   if (hash < 0)
                   9266:     hash = hashf (name, len, HASHSIZE);
                   9267: 
                   9268:   i = sizeof (HASHNODE) + len + 1;
                   9269:   hp = (HASHNODE *) xmalloc (i);
                   9270:   bucket = hash;
                   9271:   hp->bucket_hdr = &hashtab[bucket];
                   9272:   hp->next = hashtab[bucket];
                   9273:   hashtab[bucket] = hp;
                   9274:   hp->prev = NULL;
                   9275:   if (hp->next != NULL)
                   9276:     hp->next->prev = hp;
                   9277:   hp->type = type;
                   9278:   hp->length = len;
1.1.1.8 ! root     9279:   hp->value.cpval = value;
1.1       root     9280:   hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
                   9281:   p = hp->name;
                   9282:   q = name;
                   9283:   for (i = 0; i < len; i++)
                   9284:     *p++ = *q++;
                   9285:   hp->name[len] = 0;
                   9286:   return hp;
                   9287: }
                   9288: 
                   9289: /*
                   9290:  * find the most recent hash node for name name (ending with first
                   9291:  * non-identifier char) installed by install
                   9292:  *
                   9293:  * If LEN is >= 0, it is the length of the name.
                   9294:  * Otherwise, compute the length by scanning the entire name.
                   9295:  *
                   9296:  * If HASH is >= 0, it is the precomputed hash code.
                   9297:  * Otherwise, compute the hash code.
                   9298:  */
                   9299: HASHNODE *
                   9300: lookup (name, len, hash)
                   9301:      U_CHAR *name;
                   9302:      int len;
                   9303:      int hash;
                   9304: {
                   9305:   register U_CHAR *bp;
                   9306:   register HASHNODE *bucket;
                   9307: 
                   9308:   if (len < 0) {
                   9309:     for (bp = name; is_idchar[*bp]; bp++) ;
                   9310:     len = bp - name;
                   9311:   }
                   9312: 
                   9313:   if (hash < 0)
                   9314:     hash = hashf (name, len, HASHSIZE);
                   9315: 
                   9316:   bucket = hashtab[hash];
                   9317:   while (bucket) {
1.1.1.8 ! root     9318:     if (bucket->length == len && bcmp (bucket->name, name, len) == 0)
1.1       root     9319:       return bucket;
                   9320:     bucket = bucket->next;
                   9321:   }
                   9322:   return NULL;
                   9323: }
                   9324: 
                   9325: /*
                   9326:  * Delete a hash node.  Some weirdness to free junk from macros.
                   9327:  * More such weirdness will have to be added if you define more hash
                   9328:  * types that need it.
                   9329:  */
                   9330: 
                   9331: /* Note that the DEFINITION of a macro is removed from the hash table
                   9332:    but its storage is not freed.  This would be a storage leak
                   9333:    except that it is not reasonable to keep undefining and redefining
                   9334:    large numbers of macros many times.
                   9335:    In any case, this is necessary, because a macro can be #undef'd
                   9336:    in the middle of reading the arguments to a call to it.
                   9337:    If #undef freed the DEFINITION, that would crash.  */
                   9338: 
                   9339: static void
                   9340: delete_macro (hp)
                   9341:      HASHNODE *hp;
                   9342: {
                   9343: 
                   9344:   if (hp->prev != NULL)
                   9345:     hp->prev->next = hp->next;
                   9346:   if (hp->next != NULL)
                   9347:     hp->next->prev = hp->prev;
                   9348: 
                   9349:   /* make sure that the bucket chain header that
                   9350:      the deleted guy was on points to the right thing afterwards. */
                   9351:   if (hp == *hp->bucket_hdr)
                   9352:     *hp->bucket_hdr = hp->next;
                   9353: 
                   9354: #if 0
                   9355:   if (hp->type == T_MACRO) {
                   9356:     DEFINITION *d = hp->value.defn;
                   9357:     struct reflist *ap, *nextap;
                   9358: 
                   9359:     for (ap = d->pattern; ap != NULL; ap = nextap) {
                   9360:       nextap = ap->next;
                   9361:       free (ap);
                   9362:     }
                   9363:     free (d);
                   9364:   }
                   9365: #endif
                   9366:   free (hp);
                   9367: }
                   9368: 
                   9369: /*
                   9370:  * return hash function on name.  must be compatible with the one
                   9371:  * computed a step at a time, elsewhere
                   9372:  */
                   9373: static int
                   9374: hashf (name, len, hashsize)
                   9375:      register U_CHAR *name;
                   9376:      register int len;
                   9377:      int hashsize;
                   9378: {
                   9379:   register int r = 0;
                   9380: 
                   9381:   while (len--)
                   9382:     r = HASHSTEP (r, *name++);
                   9383: 
                   9384:   return MAKE_POS (r) % hashsize;
                   9385: }
                   9386: 
                   9387: 
                   9388: /* Dump the definition of a single macro HP to OF.  */
                   9389: static void
                   9390: dump_single_macro (hp, of)
                   9391:      register HASHNODE *hp;
                   9392:      FILE *of;
                   9393: {
                   9394:   register DEFINITION *defn = hp->value.defn;
                   9395:   struct reflist *ap;
                   9396:   int offset;
                   9397:   int concat;
                   9398: 
                   9399: 
                   9400:   /* Print the definition of the macro HP.  */
                   9401: 
                   9402:   fprintf (of, "#define %s", hp->name);
                   9403: 
                   9404:   if (defn->nargs >= 0) {
                   9405:     int i;
                   9406: 
                   9407:     fprintf (of, "(");
                   9408:     for (i = 0; i < defn->nargs; i++) {
                   9409:       dump_arg_n (defn, i, of);
                   9410:       if (i + 1 < defn->nargs)
                   9411:        fprintf (of, ", ");
                   9412:     }
                   9413:     fprintf (of, ")");
                   9414:   }
                   9415: 
                   9416:   fprintf (of, " ");
                   9417: 
                   9418:   offset = 0;
                   9419:   concat = 0;
                   9420:   for (ap = defn->pattern; ap != NULL; ap = ap->next) {
                   9421:     dump_defn_1 (defn->expansion, offset, ap->nchars, of);
                   9422:     offset += ap->nchars;
1.1.1.7   root     9423:     if (!traditional) {
                   9424:       if (ap->nchars != 0)
                   9425:        concat = 0;
1.1.1.8 ! root     9426:       if (ap->stringify) {
        !          9427:        switch (ap->stringify) {
        !          9428:         case SHARP_TOKEN: fprintf (of, "#"); break;
        !          9429:         case WHITE_SHARP_TOKEN: fprintf (of, "# "); break;
        !          9430:         case PERCENT_COLON_TOKEN: fprintf (of, "%%:"); break;
        !          9431:         case WHITE_PERCENT_COLON_TOKEN: fprintf (of, "%%: "); break;
        !          9432:         default: abort ();
        !          9433:        }
        !          9434:       }
        !          9435:       if (ap->raw_before != 0) {
        !          9436:        if (concat) {
        !          9437:          switch (ap->raw_before) {
        !          9438:           case WHITE_SHARP_TOKEN:
        !          9439:           case WHITE_PERCENT_COLON_TOKEN:
        !          9440:            fprintf (of, " ");
        !          9441:            break;
        !          9442:           default:
        !          9443:            break;
        !          9444:          }
        !          9445:        } else {
        !          9446:          switch (ap->raw_before) {
        !          9447:           case SHARP_TOKEN: fprintf (of, "##"); break;
        !          9448:           case WHITE_SHARP_TOKEN: fprintf (of, "## "); break;
        !          9449:           case PERCENT_COLON_TOKEN: fprintf (of, "%%:%%:"); break;
        !          9450:           case WHITE_PERCENT_COLON_TOKEN: fprintf (of, "%%:%%: "); break;
        !          9451:           default: abort ();
        !          9452:          }
        !          9453:        }
        !          9454:       }
1.1.1.7   root     9455:       concat = 0;
                   9456:     }
1.1       root     9457:     dump_arg_n (defn, ap->argno, of);
1.1.1.8 ! root     9458:     if (!traditional && ap->raw_after != 0) {
        !          9459:       switch (ap->raw_after) {
        !          9460:        case SHARP_TOKEN: fprintf (of, "##"); break;
        !          9461:        case WHITE_SHARP_TOKEN: fprintf (of, " ##"); break;
        !          9462:        case PERCENT_COLON_TOKEN: fprintf (of, "%%:%%:"); break;
        !          9463:        case WHITE_PERCENT_COLON_TOKEN: fprintf (of, " %%:%%:"); break;
        !          9464:        default: abort ();
        !          9465:       }
1.1       root     9466:       concat = 1;
                   9467:     }
                   9468:   }
                   9469:   dump_defn_1 (defn->expansion, offset, defn->length - offset, of);
                   9470:   fprintf (of, "\n");
                   9471: }
                   9472: 
                   9473: /* Dump all macro definitions as #defines to stdout.  */
                   9474: 
                   9475: static void
                   9476: dump_all_macros ()
                   9477: {
                   9478:   int bucket;
                   9479: 
                   9480:   for (bucket = 0; bucket < HASHSIZE; bucket++) {
                   9481:     register HASHNODE *hp;
                   9482: 
                   9483:     for (hp = hashtab[bucket]; hp; hp= hp->next) {
                   9484:       if (hp->type == T_MACRO)
                   9485:        dump_single_macro (hp, stdout);
                   9486:     }
                   9487:   }
                   9488: }
                   9489: 
                   9490: /* Output to OF a substring of a macro definition.
                   9491:    BASE is the beginning of the definition.
                   9492:    Output characters START thru LENGTH.
1.1.1.7   root     9493:    Unless traditional, discard newlines outside of strings, thus
1.1       root     9494:    converting funny-space markers to ordinary spaces.  */
                   9495: 
                   9496: static void
                   9497: dump_defn_1 (base, start, length, of)
                   9498:      U_CHAR *base;
                   9499:      int start;
                   9500:      int length;
                   9501:      FILE *of;
                   9502: {
                   9503:   U_CHAR *p = base + start;
                   9504:   U_CHAR *limit = base + start + length;
                   9505: 
1.1.1.7   root     9506:   if (traditional)
                   9507:     fwrite (p, sizeof (*p), length, of);
                   9508:   else {
                   9509:     while (p < limit) {
                   9510:       if (*p == '\"' || *p =='\'') {
                   9511:        U_CHAR *p1 = skip_quoted_string (p, limit, 0, NULL_PTR,
                   9512:                                         NULL_PTR, NULL_PTR);
                   9513:        fwrite (p, sizeof (*p), p1 - p, of);
                   9514:        p = p1;
                   9515:       } else {
                   9516:        if (*p != '\n')
                   9517:          putc (*p, of);
                   9518:        p++;
                   9519:       }
1.1       root     9520:     }
                   9521:   }
                   9522: }
                   9523: 
                   9524: /* Print the name of argument number ARGNUM of macro definition DEFN
                   9525:    to OF.
                   9526:    Recall that DEFN->args.argnames contains all the arg names
                   9527:    concatenated in reverse order with comma-space in between.  */
                   9528: 
                   9529: static void
                   9530: dump_arg_n (defn, argnum, of)
                   9531:      DEFINITION *defn;
                   9532:      int argnum;
                   9533:      FILE *of;
                   9534: {
                   9535:   register U_CHAR *p = defn->args.argnames;
                   9536:   while (argnum + 1 < defn->nargs) {
1.1.1.8 ! root     9537:     p = (U_CHAR *) index ((char *) p, ' ') + 1;
1.1       root     9538:     argnum++;
                   9539:   }
                   9540: 
                   9541:   while (*p && *p != ',') {
                   9542:     putc (*p, of);
                   9543:     p++;
                   9544:   }
                   9545: }
                   9546: 
                   9547: /* Initialize syntactic classifications of characters.  */
                   9548: 
                   9549: static void
                   9550: initialize_char_syntax ()
                   9551: {
                   9552:   register int i;
                   9553: 
                   9554:   /*
                   9555:    * Set up is_idchar and is_idstart tables.  These should be
                   9556:    * faster than saying (is_alpha (c) || c == '_'), etc.
                   9557:    * Set up these things before calling any routines tthat
                   9558:    * refer to them.
                   9559:    */
                   9560:   for (i = 'a'; i <= 'z'; i++) {
                   9561:     is_idchar[i - 'a' + 'A'] = 1;
                   9562:     is_idchar[i] = 1;
                   9563:     is_idstart[i - 'a' + 'A'] = 1;
                   9564:     is_idstart[i] = 1;
                   9565:   }
                   9566:   for (i = '0'; i <= '9'; i++)
                   9567:     is_idchar[i] = 1;
                   9568:   is_idchar['_'] = 1;
                   9569:   is_idstart['_'] = 1;
                   9570:   is_idchar['$'] = dollars_in_ident;
                   9571:   is_idstart['$'] = dollars_in_ident;
                   9572: 
                   9573:   /* horizontal space table */
                   9574:   is_hor_space[' '] = 1;
                   9575:   is_hor_space['\t'] = 1;
                   9576:   is_hor_space['\v'] = 1;
                   9577:   is_hor_space['\f'] = 1;
                   9578:   is_hor_space['\r'] = 1;
                   9579: 
                   9580:   is_space[' '] = 1;
                   9581:   is_space['\t'] = 1;
                   9582:   is_space['\v'] = 1;
                   9583:   is_space['\f'] = 1;
                   9584:   is_space['\n'] = 1;
                   9585:   is_space['\r'] = 1;
1.1.1.8 ! root     9586: 
        !          9587:   char_name['\v'] = "vertical tab";
        !          9588:   char_name['\f'] = "formfeed";
        !          9589:   char_name['\r'] = "carriage return";
1.1       root     9590: }
                   9591: 
                   9592: /* Initialize the built-in macros.  */
                   9593: 
                   9594: static void
                   9595: initialize_builtins (inp, outp)
                   9596:      FILE_BUF *inp;
                   9597:      FILE_BUF *outp;
                   9598: {
1.1.1.8 ! root     9599:   install ((U_CHAR *) "__LINE__", -1, T_SPECLINE, NULL_PTR, -1);
        !          9600:   install ((U_CHAR *) "__DATE__", -1, T_DATE, NULL_PTR, -1);
        !          9601:   install ((U_CHAR *) "__FILE__", -1, T_FILE, NULL_PTR, -1);
        !          9602:   install ((U_CHAR *) "__BASE_FILE__", -1, T_BASE_FILE, NULL_PTR, -1);
        !          9603:   install ((U_CHAR *) "__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, NULL_PTR, -1);
        !          9604:   install ((U_CHAR *) "__VERSION__", -1, T_VERSION, NULL_PTR, -1);
1.1.1.5   root     9605: #ifndef NO_BUILTIN_SIZE_TYPE
1.1.1.8 ! root     9606:   install ((U_CHAR *) "__SIZE_TYPE__", -1, T_SIZE_TYPE, NULL_PTR, -1);
1.1.1.5   root     9607: #endif
                   9608: #ifndef NO_BUILTIN_PTRDIFF_TYPE
1.1.1.8 ! root     9609:   install ((U_CHAR *) "__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, NULL_PTR, -1);
1.1.1.5   root     9610: #endif
1.1.1.8 ! root     9611:   install ((U_CHAR *) "__WCHAR_TYPE__", -1, T_WCHAR_TYPE, NULL_PTR, -1);
        !          9612:   install ((U_CHAR *) "__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE,
        !          9613:           NULL_PTR, -1);
        !          9614:   install ((U_CHAR *) "__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE,
        !          9615:           NULL_PTR, -1);
        !          9616:   install ((U_CHAR *) "__IMMEDIATE_PREFIX__", -1, T_IMMEDIATE_PREFIX_TYPE,
        !          9617:           NULL_PTR, -1);
        !          9618:   install ((U_CHAR *) "__TIME__", -1, T_TIME, NULL_PTR, -1);
        !          9619:   if (!traditional) {
        !          9620:     install ((U_CHAR *) "__STDC__", -1, T_CONST, "1", -1);
        !          9621:     install ((U_CHAR *) "__STDC_VERSION__", -1, T_CONST, "199409L", -1);
        !          9622:   }
1.1       root     9623:   if (objc)
1.1.1.8 ! root     9624:     install ((U_CHAR *) "__OBJC__", -1, T_CONST, "1", -1);
1.1       root     9625: /*  This is supplied using a -D by the compiler driver
                   9626:     so that it is present only when truly compiling with GNU C.  */
1.1.1.8 ! root     9627: /*  install ((U_CHAR *) "__GNUC__", -1, T_CONST, "2", -1);  */
1.1       root     9628: 
                   9629:   if (debug_output)
                   9630:     {
                   9631:       char directive[2048];
1.1.1.8 ! root     9632:       U_CHAR *udirective = (U_CHAR *) directive;
1.1       root     9633:       register struct directive *dp = &directive_table[0];
1.1.1.3   root     9634:       struct tm *timebuf = timestamp ();
1.1       root     9635: 
1.1.1.3   root     9636:       sprintf (directive, " __BASE_FILE__ \"%s\"\n",
1.1       root     9637:               instack[0].nominal_fname);
1.1.1.8 ! root     9638:       output_line_directive (inp, outp, 0, same_file);
        !          9639:       pass_thru_directive (udirective, &udirective[strlen (directive)],
        !          9640:                           outp, dp);
1.1       root     9641: 
1.1.1.3   root     9642:       sprintf (directive, " __VERSION__ \"%s\"\n", version_string);
1.1.1.8 ! root     9643:       output_line_directive (inp, outp, 0, same_file);
        !          9644:       pass_thru_directive (udirective, &udirective[strlen (directive)],
        !          9645:                           outp, dp);
1.1       root     9646: 
1.1.1.6   root     9647: #ifndef NO_BUILTIN_SIZE_TYPE
1.1.1.3   root     9648:       sprintf (directive, " __SIZE_TYPE__ %s\n", SIZE_TYPE);
1.1.1.8 ! root     9649:       output_line_directive (inp, outp, 0, same_file);
        !          9650:       pass_thru_directive (udirective, &udirective[strlen (directive)],
        !          9651:                           outp, dp);
1.1.1.6   root     9652: #endif
1.1       root     9653: 
1.1.1.6   root     9654: #ifndef NO_BUILTIN_PTRDIFF_TYPE
1.1.1.3   root     9655:       sprintf (directive, " __PTRDIFF_TYPE__ %s\n", PTRDIFF_TYPE);
1.1.1.8 ! root     9656:       output_line_directive (inp, outp, 0, same_file);
        !          9657:       pass_thru_directive (udirective, &udirective[strlen (directive)],
        !          9658:                           outp, dp);
1.1.1.6   root     9659: #endif
1.1       root     9660: 
1.1.1.7   root     9661:       sprintf (directive, " __WCHAR_TYPE__ %s\n", wchar_type);
1.1.1.8 ! root     9662:       output_line_directive (inp, outp, 0, same_file);
        !          9663:       pass_thru_directive (udirective, &udirective[strlen (directive)],
        !          9664:                           outp, dp);
1.1       root     9665: 
1.1.1.3   root     9666:       sprintf (directive, " __DATE__ \"%s %2d %4d\"\n",
1.1       root     9667:               monthnames[timebuf->tm_mon],
                   9668:               timebuf->tm_mday, timebuf->tm_year + 1900);
1.1.1.8 ! root     9669:       output_line_directive (inp, outp, 0, same_file);
        !          9670:       pass_thru_directive (udirective, &udirective[strlen (directive)],
        !          9671:                           outp, dp);
1.1       root     9672: 
1.1.1.3   root     9673:       sprintf (directive, " __TIME__ \"%02d:%02d:%02d\"\n",
1.1       root     9674:               timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec);
1.1.1.8 ! root     9675:       output_line_directive (inp, outp, 0, same_file);
        !          9676:       pass_thru_directive (udirective, &udirective[strlen (directive)],
        !          9677:                           outp, dp);
1.1       root     9678: 
                   9679:       if (!traditional)
                   9680:        {
                   9681:           sprintf (directive, " __STDC__ 1");
1.1.1.8 ! root     9682:           output_line_directive (inp, outp, 0, same_file);
        !          9683:           pass_thru_directive (udirective, &udirective[strlen (directive)],
1.1       root     9684:                               outp, dp);
                   9685:        }
                   9686:       if (objc)
                   9687:        {
                   9688:           sprintf (directive, " __OBJC__ 1");
1.1.1.8 ! root     9689:           output_line_directive (inp, outp, 0, same_file);
        !          9690:           pass_thru_directive (udirective, &udirective[strlen (directive)],
1.1       root     9691:                               outp, dp);
                   9692:        }
                   9693:     }
                   9694: }
                   9695: 
                   9696: /*
                   9697:  * process a given definition string, for initialization
                   9698:  * If STR is just an identifier, define it with value 1.
                   9699:  * If STR has anything after the identifier, then it should
                   9700:  * be identifier=definition.
                   9701:  */
                   9702: 
                   9703: static void
                   9704: make_definition (str, op)
1.1.1.8 ! root     9705:      char *str;
1.1       root     9706:      FILE_BUF *op;
                   9707: {
                   9708:   FILE_BUF *ip;
                   9709:   struct directive *kt;
                   9710:   U_CHAR *buf, *p;
                   9711: 
1.1.1.8 ! root     9712:   p = buf = (U_CHAR *) str;
1.1       root     9713:   if (!is_idstart[*p]) {
                   9714:     error ("malformed option `-D %s'", str);
                   9715:     return;
                   9716:   }
                   9717:   while (is_idchar[*++p])
                   9718:     ;
1.1.1.7   root     9719:   if (*p == '(') {
                   9720:     while (is_idchar[*++p] || *p == ',' || is_hor_space[*p])
                   9721:       ;
                   9722:     if (*p++ != ')')
1.1.1.8 ! root     9723:       p = (U_CHAR *) str;                      /* Error */
1.1.1.7   root     9724:   }
1.1       root     9725:   if (*p == 0) {
                   9726:     buf = (U_CHAR *) alloca (p - buf + 4);
                   9727:     strcpy ((char *)buf, str);
                   9728:     strcat ((char *)buf, " 1");
                   9729:   } else if (*p != '=') {
                   9730:     error ("malformed option `-D %s'", str);
                   9731:     return;
                   9732:   } else {
                   9733:     U_CHAR *q;
                   9734:     /* Copy the entire option so we can modify it.  */
                   9735:     buf = (U_CHAR *) alloca (2 * strlen (str) + 1);
1.1.1.8 ! root     9736:     strncpy ((char *) buf, str, p - (U_CHAR *) str);
1.1       root     9737:     /* Change the = to a space.  */
1.1.1.8 ! root     9738:     buf[p - (U_CHAR *) str] = ' ';
1.1       root     9739:     /* Scan for any backslash-newline and remove it.  */
                   9740:     p++;
1.1.1.8 ! root     9741:     q = &buf[p - (U_CHAR *) str];
1.1       root     9742:     while (*p) {
1.1.1.7   root     9743:       if (*p == '\"' || *p == '\'') {
                   9744:        int unterminated = 0;
1.1.1.8 ! root     9745:        U_CHAR *p1 = skip_quoted_string (p, p + strlen ((char *) p), 0,
1.1.1.7   root     9746:                                         NULL_PTR, NULL_PTR, &unterminated);
                   9747:        if (unterminated)
                   9748:          return;
                   9749:        while (p != p1)
                   9750:          if (*p == '\\' && p[1] == '\n')
                   9751:            p += 2;
                   9752:          else
                   9753:            *q++ = *p++;
                   9754:       } else if (*p == '\\' && p[1] == '\n')
1.1       root     9755:        p += 2;
                   9756:       /* Change newline chars into newline-markers.  */
                   9757:       else if (*p == '\n')
                   9758:        {
                   9759:          *q++ = '\n';
                   9760:          *q++ = '\n';
                   9761:          p++;
                   9762:        }
                   9763:       else
                   9764:        *q++ = *p++;
                   9765:     }
                   9766:     *q = 0;
                   9767:   }
                   9768:   
                   9769:   ip = &instack[++indepth];
                   9770:   ip->nominal_fname = ip->fname = "*Initialization*";
                   9771: 
                   9772:   ip->buf = ip->bufp = buf;
1.1.1.8 ! root     9773:   ip->length = strlen ((char *) buf);
1.1       root     9774:   ip->lineno = 1;
                   9775:   ip->macro = 0;
                   9776:   ip->free_ptr = 0;
                   9777:   ip->if_stack = if_stack;
                   9778:   ip->system_header_p = 0;
                   9779: 
                   9780:   for (kt = directive_table; kt->type != T_DEFINE; kt++)
                   9781:     ;
                   9782: 
1.1.1.5   root     9783:   /* Pass NULL instead of OP, since this is a "predefined" macro.  */
1.1.1.8 ! root     9784:   do_define (buf, buf + strlen ((char *) buf), NULL_PTR, kt);
1.1       root     9785:   --indepth;
                   9786: }
                   9787: 
                   9788: /* JF, this does the work for the -U option */
                   9789: 
                   9790: static void
                   9791: make_undef (str, op)
1.1.1.8 ! root     9792:      char *str;
1.1       root     9793:      FILE_BUF *op;
                   9794: {
                   9795:   FILE_BUF *ip;
                   9796:   struct directive *kt;
                   9797: 
                   9798:   ip = &instack[++indepth];
                   9799:   ip->nominal_fname = ip->fname = "*undef*";
                   9800: 
1.1.1.8 ! root     9801:   ip->buf = ip->bufp = (U_CHAR *) str;
1.1       root     9802:   ip->length = strlen (str);
                   9803:   ip->lineno = 1;
                   9804:   ip->macro = 0;
                   9805:   ip->free_ptr = 0;
                   9806:   ip->if_stack = if_stack;
                   9807:   ip->system_header_p = 0;
                   9808: 
                   9809:   for (kt = directive_table; kt->type != T_UNDEF; kt++)
                   9810:     ;
                   9811: 
1.1.1.8 ! root     9812:   do_undef ((U_CHAR *) str, (U_CHAR *) str + strlen (str), op, kt);
1.1       root     9813:   --indepth;
                   9814: }
                   9815: 
                   9816: /* Process the string STR as if it appeared as the body of a #assert.
                   9817:    OPTION is the option name for which STR was the argument.  */
                   9818: 
                   9819: static void
                   9820: make_assertion (option, str)
                   9821:      char *option;
1.1.1.8 ! root     9822:      char *str;
1.1       root     9823: {
                   9824:   FILE_BUF *ip;
                   9825:   struct directive *kt;
                   9826:   U_CHAR *buf, *p, *q;
                   9827: 
                   9828:   /* Copy the entire option so we can modify it.  */
                   9829:   buf = (U_CHAR *) alloca (strlen (str) + 1);
                   9830:   strcpy ((char *) buf, str);
                   9831:   /* Scan for any backslash-newline and remove it.  */
                   9832:   p = q = buf;
                   9833:   while (*p) {
                   9834:     if (*p == '\\' && p[1] == '\n')
                   9835:       p += 2;
                   9836:     else
                   9837:       *q++ = *p++;
                   9838:   }
                   9839:   *q = 0;
                   9840: 
                   9841:   p = buf;
                   9842:   if (!is_idstart[*p]) {
                   9843:     error ("malformed option `%s %s'", option, str);
                   9844:     return;
                   9845:   }
                   9846:   while (is_idchar[*++p])
                   9847:     ;
1.1.1.8 ! root     9848:   SKIP_WHITE_SPACE (p);
1.1       root     9849:   if (! (*p == 0 || *p == '(')) {
                   9850:     error ("malformed option `%s %s'", option, str);
                   9851:     return;
                   9852:   }
                   9853:   
                   9854:   ip = &instack[++indepth];
                   9855:   ip->nominal_fname = ip->fname = "*Initialization*";
                   9856: 
                   9857:   ip->buf = ip->bufp = buf;
1.1.1.8 ! root     9858:   ip->length = strlen ((char *) buf);
1.1       root     9859:   ip->lineno = 1;
                   9860:   ip->macro = 0;
                   9861:   ip->free_ptr = 0;
                   9862:   ip->if_stack = if_stack;
                   9863:   ip->system_header_p = 0;
                   9864: 
                   9865:   for (kt = directive_table; kt->type != T_ASSERT; kt++)
                   9866:     ;
                   9867: 
                   9868:   /* pass NULL as output ptr to do_define since we KNOW it never
                   9869:      does any output.... */
1.1.1.8 ! root     9870:   do_assert (buf, buf + strlen ((char *) buf) , NULL_PTR, kt);
1.1       root     9871:   --indepth;
                   9872: }
                   9873: 
1.1.1.4   root     9874: /* Append a chain of `struct file_name_list's
                   9875:    to the end of the main include chain.
                   9876:    FIRST is the beginning of the chain to append, and LAST is the end.  */
                   9877: 
                   9878: static void
                   9879: append_include_chain (first, last)
                   9880:      struct file_name_list *first, *last;
                   9881: {
                   9882:   struct file_name_list *dir;
                   9883: 
                   9884:   if (!first || !last)
                   9885:     return;
                   9886: 
                   9887:   if (include == 0)
                   9888:     include = first;
                   9889:   else
                   9890:     last_include->next = first;
                   9891: 
                   9892:   if (first_bracket_include == 0)
                   9893:     first_bracket_include = first;
                   9894: 
                   9895:   for (dir = first; ; dir = dir->next) {
                   9896:     int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
                   9897:     if (len > max_include_len)
                   9898:       max_include_len = len;
                   9899:     if (dir == last)
                   9900:       break;
                   9901:   }
                   9902: 
                   9903:   last->next = NULL;
                   9904:   last_include = last;
                   9905: }
                   9906: 
1.1       root     9907: /* Add output to `deps_buffer' for the -M switch.
                   9908:    STRING points to the text to be output.
1.1.1.8 ! root     9909:    SPACER is ':' for targets, ' ' for dependencies.  */
1.1       root     9910: 
                   9911: static void
1.1.1.7   root     9912: deps_output (string, spacer)
1.1       root     9913:      char *string;
1.1.1.7   root     9914:      int spacer;
1.1       root     9915: {
1.1.1.7   root     9916:   int size = strlen (string);
                   9917: 
1.1       root     9918:   if (size == 0)
1.1.1.7   root     9919:     return;
1.1       root     9920: 
                   9921: #ifndef MAX_OUTPUT_COLUMNS
1.1.1.7   root     9922: #define MAX_OUTPUT_COLUMNS 72
1.1       root     9923: #endif
1.1.1.8 ! root     9924:   if (MAX_OUTPUT_COLUMNS - 1 /*spacer*/ - 2 /*` \'*/ < deps_column + size
        !          9925:       && 1 < deps_column) {
        !          9926:     bcopy (" \\\n ", &deps_buffer[deps_size], 4);
        !          9927:     deps_size += 4;
        !          9928:     deps_column = 1;
        !          9929:     if (spacer == ' ')
        !          9930:       spacer = 0;
1.1       root     9931:   }
                   9932: 
1.1.1.7   root     9933:   if (deps_size + size + 8 > deps_allocated_size) {
                   9934:     deps_allocated_size = (deps_size + size + 50) * 2;
1.1.1.8 ! root     9935:     deps_buffer = xrealloc (deps_buffer, deps_allocated_size);
1.1       root     9936:   }
1.1.1.8 ! root     9937:   if (spacer == ' ') {
1.1.1.7   root     9938:     deps_buffer[deps_size++] = ' ';
1.1.1.8 ! root     9939:     deps_column++;
        !          9940:   }
1.1       root     9941:   bcopy (string, &deps_buffer[deps_size], size);
                   9942:   deps_size += size;
                   9943:   deps_column += size;
1.1.1.8 ! root     9944:   if (spacer == ':') {
1.1.1.7   root     9945:     deps_buffer[deps_size++] = ':';
1.1.1.8 ! root     9946:     deps_column++;
        !          9947:   }
1.1       root     9948:   deps_buffer[deps_size] = 0;
                   9949: }
                   9950: 
                   9951: static void
1.1.1.8 ! root     9952: fatal (PRINTF_ALIST (msg))
        !          9953:      PRINTF_DCL (msg)
1.1       root     9954: {
1.1.1.8 ! root     9955:   va_list args;
        !          9956: 
1.1       root     9957:   fprintf (stderr, "%s: ", progname);
1.1.1.8 ! root     9958:   VA_START (args, msg);
        !          9959:   vfprintf (stderr, msg, args);
        !          9960:   va_end (args);
1.1       root     9961:   fprintf (stderr, "\n");
1.1.1.8 ! root     9962:   exit (FATAL_EXIT_CODE);
1.1       root     9963: }
                   9964: 
                   9965: /* More 'friendly' abort that prints the line and file.
                   9966:    config.h can #define abort fancy_abort if you like that sort of thing.  */
                   9967: 
                   9968: void
                   9969: fancy_abort ()
                   9970: {
                   9971:   fatal ("Internal gcc abort.");
                   9972: }
                   9973: 
                   9974: static void
                   9975: perror_with_name (name)
                   9976:      char *name;
                   9977: {
                   9978:   fprintf (stderr, "%s: ", progname);
1.1.1.7   root     9979:   fprintf (stderr, "%s: %s\n", name, my_strerror (errno));
1.1       root     9980:   errors++;
                   9981: }
                   9982: 
                   9983: static void
                   9984: pfatal_with_name (name)
                   9985:      char *name;
                   9986: {
                   9987:   perror_with_name (name);
                   9988: #ifdef VMS
                   9989:   exit (vaxc$errno);
                   9990: #else
1.1.1.8 ! root     9991:   exit (FATAL_EXIT_CODE);
1.1       root     9992: #endif
                   9993: }
                   9994: 
1.1.1.5   root     9995: /* Handler for SIGPIPE.  */
                   9996: 
                   9997: static void
                   9998: pipe_closed (signo)
                   9999:      /* If this is missing, some compilers complain.  */
                   10000:      int signo;
                   10001: {
                   10002:   fatal ("output pipe has been closed");
                   10003: }
1.1       root     10004: 
                   10005: static void
                   10006: memory_full ()
                   10007: {
                   10008:   fatal ("Memory exhausted.");
                   10009: }
                   10010: 
                   10011: 
1.1.1.8 ! root     10012: GENERIC_PTR
1.1       root     10013: xmalloc (size)
1.1.1.8 ! root     10014:      size_t size;
1.1       root     10015: {
1.1.1.8 ! root     10016:   register GENERIC_PTR ptr = (GENERIC_PTR) malloc (size);
        !          10017:   if (!ptr)
        !          10018:     memory_full ();
        !          10019:   return ptr;
1.1       root     10020: }
                   10021: 
1.1.1.8 ! root     10022: static GENERIC_PTR
1.1       root     10023: xrealloc (old, size)
1.1.1.8 ! root     10024:      GENERIC_PTR old;
        !          10025:      size_t size;
1.1       root     10026: {
1.1.1.8 ! root     10027:   register GENERIC_PTR ptr = (GENERIC_PTR) realloc (old, size);
        !          10028:   if (!ptr)
        !          10029:     memory_full ();
        !          10030:   return ptr;
1.1       root     10031: }
                   10032: 
1.1.1.8 ! root     10033: static GENERIC_PTR
1.1       root     10034: xcalloc (number, size)
1.1.1.8 ! root     10035:      size_t number, size;
1.1       root     10036: {
1.1.1.8 ! root     10037:   register size_t total = number * size;
        !          10038:   register GENERIC_PTR ptr = (GENERIC_PTR) malloc (total);
        !          10039:   if (!ptr)
        !          10040:     memory_full ();
        !          10041:   bzero (ptr, total);
        !          10042:   return ptr;
1.1       root     10043: }
                   10044: 
                   10045: static char *
                   10046: savestring (input)
                   10047:      char *input;
                   10048: {
1.1.1.8 ! root     10049:   size_t size = strlen (input);
1.1       root     10050:   char *output = xmalloc (size + 1);
                   10051:   strcpy (output, input);
                   10052:   return output;
                   10053: }
                   10054: 
                   10055: /* Get the file-mode and data size of the file open on FD
                   10056:    and store them in *MODE_POINTER and *SIZE_POINTER.  */
                   10057: 
                   10058: static int
                   10059: file_size_and_mode (fd, mode_pointer, size_pointer)
                   10060:      int fd;
                   10061:      int *mode_pointer;
                   10062:      long int *size_pointer;
                   10063: {
                   10064:   struct stat sbuf;
                   10065: 
                   10066:   if (fstat (fd, &sbuf) < 0) return (-1);
                   10067:   if (mode_pointer) *mode_pointer = sbuf.st_mode;
                   10068:   if (size_pointer) *size_pointer = sbuf.st_size;
                   10069:   return 0;
                   10070: }
                   10071: 
                   10072: #ifdef VMS
                   10073: 
                   10074: /* Under VMS we need to fix up the "include" specification
                   10075:    filename so that everything following the 1st slash is
                   10076:    changed into its correct VMS file specification. */
                   10077: 
                   10078: static void
                   10079: hack_vms_include_specification (fname)
                   10080:      char *fname;
                   10081: {
                   10082:   register char *cp, *cp1, *cp2;
                   10083:   int f, check_filename_before_returning, no_prefix_seen;
                   10084:   char Local[512];
                   10085: 
                   10086:   check_filename_before_returning = 0;
                   10087:   no_prefix_seen = 0;
                   10088: 
                   10089:   /* Ignore leading "./"s */
                   10090:   while (fname[0] == '.' && fname[1] == '/') {
                   10091:     strcpy (fname, fname+2);
                   10092:     no_prefix_seen = 1;                /* mark this for later */
                   10093:   }
                   10094:   /* Look for the boundary between the VMS and UNIX filespecs */
                   10095:   cp = rindex (fname, ']');    /* Look for end of dirspec. */
                   10096:   if (cp == 0) cp = rindex (fname, '>'); /* ... Ditto              */
                   10097:   if (cp == 0) cp = rindex (fname, ':'); /* Look for end of devspec. */
                   10098:   if (cp) {
                   10099:     cp++;
                   10100:   } else {
                   10101:     cp = index (fname, '/');   /* Look for the "/" */
                   10102:   }
                   10103: 
1.1.1.7   root     10104:   /*
                   10105:    * Check if we have a vax-c style '#include filename'
                   10106:    * and add the missing .h
                   10107:    */
                   10108:   if (cp == 0) {
                   10109:     if (index(fname,'.') == 0)
                   10110:       strcat(fname, ".h");
                   10111:   } else {
                   10112:     if (index(cp,'.') == 0)
                   10113:       strcat(cp, ".h");
                   10114:   }
                   10115: 
1.1       root     10116:   cp2 = Local;                 /* initialize */
                   10117: 
                   10118:   /* We are trying to do a number of things here.  First of all, we are
                   10119:      trying to hammer the filenames into a standard format, such that later
                   10120:      processing can handle them.
                   10121:      
                   10122:      If the file name contains something like [dir.], then it recognizes this
                   10123:      as a root, and strips the ".]".  Later processing will add whatever is
                   10124:      needed to get things working properly.
                   10125:      
                   10126:      If no device is specified, then the first directory name is taken to be
                   10127:      a device name (or a rooted logical). */
                   10128: 
                   10129:   /* See if we found that 1st slash */
                   10130:   if (cp == 0) return;         /* Nothing to do!!! */
                   10131:   if (*cp != '/') return;      /* Nothing to do!!! */
                   10132:   /* Point to the UNIX filename part (which needs to be fixed!) */
                   10133:   cp1 = cp+1;
                   10134:   /* If the directory spec is not rooted, we can just copy
                   10135:      the UNIX filename part and we are done */
                   10136:   if (((cp - fname) > 1) && ((cp[-1] == ']') || (cp[-1] == '>'))) {
                   10137:     if (cp[-2] != '.') {
                   10138:       /*
1.1.1.2   root     10139:        * The VMS part ends in a `]', and the preceding character is not a `.'.
1.1       root     10140:        * We strip the `]', and then splice the two parts of the name in the
                   10141:        * usual way.  Given the default locations for include files in cccp.c,
                   10142:        * we will only use this code if the user specifies alternate locations
                   10143:        * with the /include (-I) switch on the command line.  */
                   10144:       cp -= 1;                 /* Strip "]" */
                   10145:       cp1--;                   /* backspace */
                   10146:     } else {
                   10147:       /*
                   10148:        * The VMS part has a ".]" at the end, and this will not do.  Later
                   10149:        * processing will add a second directory spec, and this would be a syntax
                   10150:        * error.  Thus we strip the ".]", and thus merge the directory specs.
                   10151:        * We also backspace cp1, so that it points to a '/'.  This inhibits the
                   10152:        * generation of the 000000 root directory spec (which does not belong here
                   10153:        * in this case).
                   10154:        */
                   10155:       cp -= 2;                 /* Strip ".]" */
                   10156:       cp1--; };                        /* backspace */
                   10157:   } else {
                   10158: 
                   10159:     /* We drop in here if there is no VMS style directory specification yet.
                   10160:      * If there is no device specification either, we make the first dir a
                   10161:      * device and try that.  If we do not do this, then we will be essentially
                   10162:      * searching the users default directory (as if they did a #include "asdf.h").
                   10163:      *
                   10164:      * Then all we need to do is to push a '[' into the output string. Later
                   10165:      * processing will fill this in, and close the bracket.
                   10166:      */
1.1.1.5   root     10167:     if (cp[-1] != ':') *cp2++ = ':'; /* dev not in spec.  take first dir */
1.1       root     10168:     *cp2++ = '[';              /* Open the directory specification */
                   10169:   }
                   10170: 
                   10171:   /* at this point we assume that we have the device spec, and (at least
                   10172:      the opening "[" for a directory specification.  We may have directories
                   10173:      specified already */
                   10174: 
                   10175:   /* If there are no other slashes then the filename will be
                   10176:      in the "root" directory.  Otherwise, we need to add
                   10177:      directory specifications. */
                   10178:   if (index (cp1, '/') == 0) {
                   10179:     /* Just add "000000]" as the directory string */
                   10180:     strcpy (cp2, "000000]");
                   10181:     cp2 += strlen (cp2);
                   10182:     check_filename_before_returning = 1; /* we might need to fool with this later */
                   10183:   } else {
                   10184:     /* As long as there are still subdirectories to add, do them. */
                   10185:     while (index (cp1, '/') != 0) {
                   10186:       /* If this token is "." we can ignore it */
                   10187:       if ((cp1[0] == '.') && (cp1[1] == '/')) {
                   10188:        cp1 += 2;
                   10189:        continue;
                   10190:       }
                   10191:       /* Add a subdirectory spec. Do not duplicate "." */
                   10192:       if (cp2[-1] != '.' && cp2[-1] != '[' && cp2[-1] != '<')
                   10193:        *cp2++ = '.';
                   10194:       /* If this is ".." then the spec becomes "-" */
                   10195:       if ((cp1[0] == '.') && (cp1[1] == '.') && (cp[2] == '/')) {
                   10196:        /* Add "-" and skip the ".." */
                   10197:        *cp2++ = '-';
                   10198:        cp1 += 3;
                   10199:        continue;
                   10200:       }
                   10201:       /* Copy the subdirectory */
                   10202:       while (*cp1 != '/') *cp2++= *cp1++;
                   10203:       cp1++;                   /* Skip the "/" */
                   10204:     }
                   10205:     /* Close the directory specification */
1.1.1.5   root     10206:     if (cp2[-1] == '.')                /* no trailing periods */
1.1       root     10207:       cp2--;
                   10208:     *cp2++ = ']';
                   10209:   }
                   10210:   /* Now add the filename */
                   10211:   while (*cp1) *cp2++ = *cp1++;
                   10212:   *cp2 = 0;
                   10213:   /* Now append it to the original VMS spec. */
                   10214:   strcpy (cp, Local);
                   10215: 
                   10216:   /* If we put a [000000] in the filename, try to open it first. If this fails,
                   10217:      remove the [000000], and return that name.  This provides flexibility
                   10218:      to the user in that they can use both rooted and non-rooted logical names
                   10219:      to point to the location of the file.  */
                   10220: 
                   10221:   if (check_filename_before_returning && no_prefix_seen) {
                   10222:     f = open (fname, O_RDONLY, 0666);
                   10223:     if (f >= 0) {
                   10224:       /* The file name is OK as it is, so return it as is.  */
                   10225:       close (f);
                   10226:       return;
                   10227:     }
                   10228:     /* The filename did not work.  Try to remove the [000000] from the name,
                   10229:        and return it.  */
                   10230:     cp = index (fname, '[');
                   10231:     cp2 = index (fname, ']') + 1;
                   10232:     strcpy (cp, cp2);          /* this gets rid of it */
                   10233:   }
                   10234:   return;
                   10235: }
                   10236: #endif /* VMS */
                   10237: 
                   10238: #ifdef VMS
                   10239: 
                   10240: /* These are the read/write replacement routines for
                   10241:    VAX-11 "C".  They make read/write behave enough
                   10242:    like their UNIX counterparts that CCCP will work */
                   10243: 
                   10244: static int
                   10245: read (fd, buf, size)
                   10246:      int fd;
                   10247:      char *buf;
                   10248:      int size;
                   10249: {
                   10250: #undef read    /* Get back the REAL read routine */
                   10251:   register int i;
                   10252:   register int total = 0;
                   10253: 
                   10254:   /* Read until the buffer is exhausted */
                   10255:   while (size > 0) {
                   10256:     /* Limit each read to 32KB */
                   10257:     i = (size > (32*1024)) ? (32*1024) : size;
                   10258:     i = read (fd, buf, i);
                   10259:     if (i <= 0) {
                   10260:       if (i == 0) return (total);
1.1.1.5   root     10261:       return (i);
1.1       root     10262:     }
                   10263:     /* Account for this read */
                   10264:     total += i;
                   10265:     buf += i;
                   10266:     size -= i;
                   10267:   }
                   10268:   return (total);
                   10269: }
                   10270: 
                   10271: static int
                   10272: write (fd, buf, size)
                   10273:      int fd;
                   10274:      char *buf;
                   10275:      int size;
                   10276: {
                   10277: #undef write   /* Get back the REAL write routine */
                   10278:   int i;
                   10279:   int j;
                   10280: 
                   10281:   /* Limit individual writes to 32Kb */
                   10282:   i = size;
                   10283:   while (i > 0) {
                   10284:     j = (i > (32*1024)) ? (32*1024) : i;
                   10285:     if (write (fd, buf, j) < 0) return (-1);
                   10286:     /* Account for the data written */
                   10287:     buf += j;
                   10288:     i -= j;
                   10289:   }
                   10290:   return (size);
                   10291: }
                   10292: 
                   10293: /* The following wrapper functions supply additional arguments to the VMS
                   10294:    I/O routines to optimize performance with file handling.  The arguments
                   10295:    are:
                   10296:      "mbc=16" - Set multi-block count to 16 (use a 8192 byte buffer).
                   10297:      "deq=64" - When extending the file, extend it in chunks of 32Kbytes.
                   10298:      "fop=tef"- Truncate unused portions of file when closing file.
                   10299:      "shr=nil"- Disallow file sharing while file is open.
                   10300:  */
                   10301: 
                   10302: static FILE *
                   10303: freopen (fname, type, oldfile)
                   10304:      char *fname;
                   10305:      char *type;
                   10306:      FILE *oldfile;
                   10307: {
                   10308: #undef freopen /* Get back the REAL fopen routine */
                   10309:   if (strcmp (type, "w") == 0)
                   10310:     return freopen (fname, type, oldfile, "mbc=16", "deq=64", "fop=tef", "shr=nil");
                   10311:   return freopen (fname, type, oldfile, "mbc=16");
                   10312: }
                   10313: 
                   10314: static FILE *
                   10315: fopen (fname, type)
                   10316:      char *fname;
                   10317:      char *type;
                   10318: {
                   10319: #undef fopen   /* Get back the REAL fopen routine */
1.1.1.8 ! root     10320:   /* The gcc-vms-1.42 distribution's header files prototype fopen with two
        !          10321:      fixed arguments, which matches ANSI's specification but not VAXCRTL's
        !          10322:      pre-ANSI implementation.  This hack circumvents the mismatch problem.  */
        !          10323:   FILE *(*vmslib_fopen)() = (FILE *(*)()) fopen;
        !          10324: 
        !          10325:   if (*type == 'w')
        !          10326:     return (*vmslib_fopen) (fname, type, "mbc=32",
        !          10327:                            "deq=64", "fop=tef", "shr=nil");
        !          10328:   else
        !          10329:     return (*vmslib_fopen) (fname, type, "mbc=32");
1.1       root     10330: }
                   10331: 
                   10332: static int 
                   10333: open (fname, flags, prot)
                   10334:      char *fname;
                   10335:      int flags;
                   10336:      int prot;
                   10337: {
                   10338: #undef open    /* Get back the REAL open routine */
                   10339:   return open (fname, flags, prot, "mbc=16", "deq=64", "fop=tef");
                   10340: }
                   10341: 
1.1.1.4   root     10342: /* Avoid run-time library bug, where copying M out of N+M characters with
                   10343:    N >= 65535 results in VAXCRTL's strncat falling into an infinite loop.
1.1.1.8 ! root     10344:    gcc-cpp exercises this particular bug.  [Fixed in V5.5-2's VAXCRTL.]  */
1.1.1.4   root     10345: 
                   10346: static char *
                   10347: strncat (dst, src, cnt)
                   10348:      char *dst;
                   10349:      const char *src;
                   10350:      unsigned cnt;
                   10351: {
                   10352:   register char *d = dst, *s = (char *) src;
                   10353:   register int n = cnt;        /* convert to _signed_ type */
                   10354: 
                   10355:   while (*d) d++;      /* advance to end */
                   10356:   while (--n >= 0)
                   10357:     if (!(*d++ = *s++)) break;
                   10358:   if (n < 0) *d = '\0';
                   10359:   return dst;
                   10360: }
1.1.1.8 ! root     10361: 
        !          10362: /* more VMS hackery */
        !          10363: #include <fab.h>
        !          10364: #include <nam.h>
        !          10365: 
        !          10366: extern unsigned long sys$parse(), sys$search();
        !          10367: 
        !          10368: /* Work around another library bug.  If a file is located via a searchlist,
        !          10369:    and if the device it's on is not the same device as the one specified
        !          10370:    in the first element of that searchlist, then both stat() and fstat()
        !          10371:    will fail to return info about it.  `errno' will be set to EVMSERR, and
        !          10372:    `vaxc$errno' will be set to SS$_NORMAL due yet another bug in stat()!
        !          10373:    We can get around this by fully parsing the filename and then passing
        !          10374:    that absolute name to stat().
        !          10375: 
        !          10376:    Without this fix, we can end up failing to find header files, which is
        !          10377:    bad enough, but then compounding the problem by reporting the reason for
        !          10378:    failure as "normal successful completion."  */
        !          10379: 
        !          10380: #undef fstat   /* get back to library version */
        !          10381: 
        !          10382: static int
        !          10383: VMS_fstat (fd, statbuf)
        !          10384:      int fd;
        !          10385:      struct stat *statbuf;
        !          10386: {
        !          10387:   int result = fstat (fd, statbuf);
        !          10388: 
        !          10389:   if (result < 0)
        !          10390:     {
        !          10391:       FILE *fp;
        !          10392:       char nambuf[NAM$C_MAXRSS+1];
        !          10393: 
        !          10394:       if ((fp = fdopen (fd, "r")) != 0 && fgetname (fp, nambuf) != 0)
        !          10395:        result = VMS_stat (nambuf, statbuf);
        !          10396:       /* No fclose(fp) here; that would close(fd) as well.  */
        !          10397:     }
        !          10398: 
        !          10399:   return result;
        !          10400: }
        !          10401: 
        !          10402: static int
        !          10403: VMS_stat (name, statbuf)
        !          10404:      const char *name;
        !          10405:      struct stat *statbuf;
        !          10406: {
        !          10407:   int result = stat (name, statbuf);
        !          10408: 
        !          10409:   if (result < 0)
        !          10410:     {
        !          10411:       struct FAB fab;
        !          10412:       struct NAM nam;
        !          10413:       char exp_nam[NAM$C_MAXRSS+1],  /* expanded name buffer for sys$parse */
        !          10414:           res_nam[NAM$C_MAXRSS+1];  /* resultant name buffer for sys$search */
        !          10415: 
        !          10416:       fab = cc$rms_fab;
        !          10417:       fab.fab$l_fna = (char *) name;
        !          10418:       fab.fab$b_fns = (unsigned char) strlen (name);
        !          10419:       fab.fab$l_nam = (void *) &nam;
        !          10420:       nam = cc$rms_nam;
        !          10421:       nam.nam$l_esa = exp_nam,  nam.nam$b_ess = sizeof exp_nam - 1;
        !          10422:       nam.nam$l_rsa = res_nam,  nam.nam$b_rss = sizeof res_nam - 1;
        !          10423:       nam.nam$b_nop = NAM$M_PWD | NAM$M_NOCONCEAL;
        !          10424:       if (sys$parse (&fab) & 1)
        !          10425:        {
        !          10426:          if (sys$search (&fab) & 1)
        !          10427:            {
        !          10428:              res_nam[nam.nam$b_rsl] = '\0';
        !          10429:              result = stat (res_nam, statbuf);
        !          10430:            }
        !          10431:          /* Clean up searchlist context cached by the system.  */
        !          10432:          nam.nam$b_nop = NAM$M_SYNCHK;
        !          10433:          fab.fab$l_fna = 0,  fab.fab$b_fns = 0;
        !          10434:          (void) sys$parse (&fab);
        !          10435:        }
        !          10436:     }
        !          10437: 
        !          10438:   return result;
        !          10439: }
1.1       root     10440: #endif /* VMS */

unix.superglobalmegacorp.com

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