[BACK]Return to system.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / windows / mcpp

Annotation of OpenXM_contrib2/windows/mcpp/system.c, Revision 1.1

1.1     ! ohara       1: /* $OpenXM$ */
        !             2: /*-
        !             3:  * Copyright (c) 1998, 2002-2008 Kiyoshi Matsui <kmatsui@t3.rim.or.jp>
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * Some parts of this code are derived from the public domain software
        !             7:  * DECUS cpp (1984,1985) written by Martin Minow.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  *
        !            18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
        !            19:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            20:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            21:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
        !            22:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            23:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            24:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            25:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            26:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            27:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            28:  * SUCH DAMAGE.
        !            29:  */
        !            30:
        !            31: /*
        !            32:  *                          S Y S T E M . C
        !            33:  *          S y s t e m   D e p e n d e n t   R o u t i n e s
        !            34:  *
        !            35:  * Routines dependent on O.S., compiler or compiler-driver.
        !            36:  * To port MCPP for the systems not yet ported, you must
        !            37:  *      1. specify the constants in "configed.H" or "noconfig.H",
        !            38:  *      2. append the system-dependent routines in this file.
        !            39:  */
        !            40: #if PREPROCESSED
        !            41: #include    "mcpp.H"
        !            42: #else
        !            43: #include    "system.H"
        !            44: #include    "internal.H"
        !            45: #endif
        !            46:
        !            47: #if     HOST_SYS_FAMILY == SYS_UNIX
        !            48: #include    "unistd.h"              /* For getcwd(), readlink() */
        !            49: #elif   HOST_COMPILER == MSC || HOST_COMPILER == LCC
        !            50: #include    "direct.h"
        !            51: #define getcwd( buf, size)  _getcwd( buf, size)
        !            52: #elif   HOST_COMPILER == BORLANDC
        !            53: #include    "dir.h"
        !            54: #endif
        !            55:
        !            56: #include    "sys/types.h"
        !            57: #include    "sys/stat.h"                        /* For stat()       */
        !            58: #if     ! defined( S_ISREG)
        !            59: #define S_ISREG( mode)  (mode & S_IFREG)
        !            60: #define S_ISDIR( mode)  (mode & S_IFDIR)
        !            61: #endif
        !            62: #if     HOST_COMPILER == MSC
        !            63: #define S_IFREG     _S_IFREG
        !            64: #define S_IFDIR     _S_IFDIR
        !            65: #define stat( path, stbuf)  _stat( path, stbuf)
        !            66: #endif
        !            67:
        !            68: /* Function to compare path-list    */
        !            69: #if     FNAME_FOLD
        !            70: #if     HOST_COMPILER == GNUC   /* CYGWIN, MINGW, MAC   */
        !            71: #include    <strings.h>         /* POSIX 1, 2001        */
        !            72: #define str_case_eq( str1, str2)    (strcasecmp( str1, str2) == 0)
        !            73: #else   /* MSC, BORLANDC, LCC   */
        !            74: #if     HOST_COMPILER == MSC
        !            75: #define stricmp( str1, str2)        _stricmp( str1, str2)
        !            76: #endif
        !            77: #define str_case_eq( str1, str2)    (stricmp( str1, str2) == 0)
        !            78: #endif
        !            79: #else   /* ! FNAME_FOLD */
        !            80: #define str_case_eq( str1, str2)    (strcmp( str1, str2) == 0)
        !            81: #endif
        !            82:
        !            83: /*
        !            84:  * PATH_DELIM is defined for the O.S. which has single byte path-delimiter.
        !            85:  * Note: '\\' or any other character identical to second byte of MBCHAR should
        !            86:  * not be used for PATH_DELIM for convenience of path-list parsing.
        !            87:  */
        !            88: #if SYS_FAMILY == SYS_UNIX || SYS_FAMILY == SYS_WIN || SYSTEM == SYS_UNKNOWN
        !            89: #define PATH_DELIM      '/'
        !            90: #define SPECIAL_PATH_DELIM  FALSE
        !            91: #else   /* Any other path-delimiter, define PATH_DELIM by yourself  */
        !            92: #define SPECIAL_PATH_DELIM  TRUE    /* Any path-delimiter other than '/'    */
        !            93: #endif
        !            94:
        !            95: /*
        !            96:  * OBJEXT is the suffix to denote "object" file.
        !            97:  */
        !            98: #ifndef OBJEXT
        !            99: #if     SYS_FAMILY == SYS_UNIX || HOST_COMPILER == GNUC
        !           100: #define OBJEXT     "o"
        !           101: #elif   SYS_FAMILY == SYS_WIN
        !           102: #define OBJEXT     "obj"
        !           103: #elif   1
        !           104: /* Add here appropriate definitions for other systems.  */
        !           105: #endif
        !           106: #endif
        !           107:
        !           108: static void     version( void);
        !           109:                 /* Print version message            */
        !           110: static void     usage( int opt);
        !           111:                 /* Putout usage of MCPP             */
        !           112: static void     set_opt_list( char * optlist);
        !           113:                 /* Set list of legal option chars   */
        !           114: static int      parse_warn_level( const char * mcpp_optarg, int opt);
        !           115:                 /* Parse warning level option       */
        !           116: static void     def_a_macro( int opt, char * def);
        !           117:                 /* Do a -D option                   */
        !           118: static void     chk_opts( int sflag, int trad);
        !           119:                 /* Check consistency of options     */
        !           120: #if COMPILER != GNUC
        !           121: static void     init_cpu_macro( int gval, int sse);
        !           122:                 /* Predefine CPU-dependent macros   */
        !           123: #endif
        !           124: static void     init_predefines( void);
        !           125:                 /* Set and unset predefined macros  */
        !           126: static void     init_std_defines( void);
        !           127:                 /* Predefine Standard macros        */
        !           128: static void     set_limit( void);
        !           129:                 /* Set minimum translation limits   */
        !           130: static void     set_pragma_op( void);
        !           131:                 /* Set the _Pragma() operator       */
        !           132: static void     put_info( FILEINFO * sharp_file);
        !           133:                 /* Print compiler-specific-inf      */
        !           134: static char *   set_files( int argc, char ** argv, char ** in_pp
        !           135:         , char ** out_pp);
        !           136:                 /* Set input, output, diagnostic    */
        !           137: static void     set_sys_dirs( int set_cplus_dir);
        !           138:                 /* Set system-specific include dirs */
        !           139: static void     set_env_dirs( void);
        !           140:                 /* Set user-defined include dirs    */
        !           141: static void     parse_env( const char * env);
        !           142:                 /* Parse environment variables      */
        !           143: static void     set_a_dir( const char * dirname);
        !           144:                 /* Append an include directory      */
        !           145: static char *   norm_dir( const char * dirname, int framework);
        !           146:                 /* Normalize include directory path */
        !           147: static char *   norm_path( const char * dir, const char * fname, int inf
        !           148:         , int hmap);    /* Normalize pathname to compare    */
        !           149: #if SYS_FAMILY == SYS_UNIX
        !           150: static void     deref_syml( char * slbuf1, char * slbuf2, char * chk_start);
        !           151:                 /* Dereference symbolic linked directory and file   */
        !           152: #endif
        !           153: #if COMPILER == GNUC
        !           154: static void     init_gcc_macro( void);
        !           155:                 /* Predefine GCC-specific macros    */
        !           156: static void     chk_env( void);
        !           157:                 /* Check the environment variables  */
        !           158: #elif   COMPILER == MSC
        !           159: static void     init_msc_macro( void);
        !           160:                 /* Predefine Visual C-specific macros       */
        !           161: #endif
        !           162: static void     def_macros( void);
        !           163:                 /* Define macros specified by -D    */
        !           164: static void     undef_macros( void);
        !           165:                 /* Undefine macros specified by -U  */
        !           166: static char *   md_init( const char * filename, char * output);
        !           167:                 /* Initialize makefile dependency   */
        !           168: static char *   md_quote( char * output);
        !           169:                 /* 'Quote' special characters       */
        !           170: static int      open_include( char * filename, int searchlocal, int next);
        !           171:                 /* Open the file to include         */
        !           172: static int      has_directory( const char * source, char * directory);
        !           173:                 /* Get directory part of fname      */
        !           174: static int      is_full_path( const char * path);
        !           175:                 /* The path is absolute path list ? */
        !           176: static int      search_dir( char * filename, int searchlocal, int next);
        !           177:                 /* Search the include directories   */
        !           178: static int      open_file( const char ** dirp, const char * src_dir
        !           179:         , const char * filename, int local, int include_opt, int sys_frame);
        !           180:                 /* Open a source file       */
        !           181: static const char *     set_fname( const char * filename);
        !           182:                 /* Remember the source filename     */
        !           183: #if SYSTEM == SYS_MAC
        !           184: #if COMPILER == GNUC
        !           185: static char *   search_header_map( const char * hmap_file
        !           186:         , const char * filename, char * pathlist);
        !           187:                 /* Search header map file for a header  */
        !           188: static unsigned hmap_hash( const char * fname);
        !           189:                 /* Get hash value for the fname     */
        !           190: #endif
        !           191: static void     init_framework( void);
        !           192:                 /* Initialize framework[]           */
        !           193: static int      search_framework( char * filename);
        !           194:                 /* Search "Framework" directories   */
        !           195: static int      search_subdir( char * fullname, char * cp, char * frame
        !           196:         , char * fname, int sys_frame);
        !           197:                 /* Search "Headers" and other dirs  */
        !           198: #endif  /* SYSTEM == SYS_MAC    */
        !           199: #if 0   /* This function is only for debugging use  */
        !           200: static int      chk_dirp( const char ** dirp);
        !           201:                 /* Check validity of dirp arg for open_file()   */
        !           202: #endif
        !           203: static void     cur_file( FILEINFO * file, FILEINFO * sharp_file, int marker);
        !           204:                 /* Output current source file name  */
        !           205: #if SYS_FAMILY == SYS_WIN
        !           206: static char *   bsl2sl( char * filename);
        !           207:                 /* Convert \ to / in path-list      */
        !           208: #endif
        !           209: static int      is_junk( void);
        !           210:                 /* The directive has trailing junk? */
        !           211: static void     do_once( const char * fullname);
        !           212:                 /* Process #pragma once             */
        !           213: static int      included( const char * fullname);
        !           214:                 /* The file has been once included? */
        !           215: static void     push_or_pop( int direction);
        !           216:                 /* Push or pop a macro definition   */
        !           217: static int      do_prestd_directive( void);
        !           218:                 /* Process pre-Standard directives  */
        !           219: static void     do_preprocessed( void);
        !           220:                 /* Process preprocessed file        */
        !           221: static int      do_debug( int set);
        !           222:                 /* #pragma MCPP debug, #debug       */
        !           223: static void     dump_path( void);
        !           224:                 /* Print include search path        */
        !           225: static void     do_asm( int asm_start);
        !           226:                 /* Process #asm, #endasm            */
        !           227: static int      mcpp_getopt( int argc, char * const * argv, const char * opts);
        !           228:                 /* getopt() to prevent linking of glibc getopt  */
        !           229:
        !           230: /* for mcpp_getopt()    */
        !           231: static int      mcpp_optind = 1;
        !           232: static int      mcpp_opterr = 1;
        !           233: static int      mcpp_optopt;
        !           234: static char *   mcpp_optarg;
        !           235:
        !           236: static int      mb_changed = FALSE;     /* Flag of -e option        */
        !           237: static char     cur_work_dir[ PATHMAX + 1];     /* Current working directory*/
        !           238:
        !           239: /*
        !           240:  * incdir[] stores the -I directories (and the system-specific #include <...>
        !           241:  * directories).  This is set by set_a_dir().  A trailing PATH_DELIM is
        !           242:  * appended if absent.
        !           243:  */
        !           244: static const char **    incdir;         /* Include directories      */
        !           245: static const char **    incend;         /* -> active end of incdir  */
        !           246: static int          max_inc;            /* Number of incdir[]       */
        !           247:
        !           248: typedef struct inc_list {       /* List of directories or files     */
        !           249:     char *      name;           /* Filename or directory-name       */
        !           250:     size_t      len;                    /* Length of 'name'         */
        !           251: } INC_LIST;
        !           252:
        !           253: /*
        !           254:  * fnamelist[] stores the souce file names opened by #include directive for
        !           255:  * debugging information.
        !           256:  */
        !           257: static INC_LIST *   fnamelist;          /* Source file names        */
        !           258: static INC_LIST *   fname_end;          /* -> active end of fnamelist   */
        !           259: static int          max_fnamelist;      /* Number of fnamelist[]    */
        !           260:
        !           261: /* once_list[] stores the #pragma once file names.  */
        !           262: static INC_LIST *   once_list;          /* Once opened file         */
        !           263: static INC_LIST *   once_end;           /* -> active end of once_list   */
        !           264: static int          max_once;           /* Number of once_list[]    */
        !           265:
        !           266: #define INIT_NUM_INCLUDE    32          /* Initial number of incdir[]   */
        !           267: #define INIT_NUM_FNAMELIST  256         /* Initial number of fnamelist[]    */
        !           268: #define INIT_NUM_ONCE       64          /* Initial number of once_list[]    */
        !           269:
        !           270: /*
        !           271:  * 'search_rule' holds searching rule of #include "header.h" to search first
        !           272:  * before searching user specified or system-specific include directories.
        !           273:  * 'search_rule' is initialized to SEARCH_INIT.  It can be changed by -I1, -I2
        !           274:  * or -I3 option.  -I1 specifies CURRENT, -I2 SOURCE and -I3 both.
        !           275:  */
        !           276:
        !           277: static int      search_rule = SEARCH_INIT;  /* Rule to search include file  */
        !           278:
        !           279: static int      nflag = FALSE;          /* Flag of -N (-undef) option       */
        !           280: static long     std_val = -1L;  /* Value of __STDC_VERSION__ or __cplusplus */
        !           281:
        !           282: #define MAX_DEF   256
        !           283: #define MAX_UNDEF (MAX_DEF/4)
        !           284: static char *   def_list[ MAX_DEF];     /* Macros to be defined     */
        !           285: static char *   undef_list[ MAX_UNDEF]; /* Macros to be undefined   */
        !           286: static int      def_cnt;                /* Count of def_list        */
        !           287: static int      undef_cnt;              /* Count of undef_list      */
        !           288:
        !           289: /* Values of mkdep. */
        !           290: #define MD_MKDEP        1   /* Output source file dependency line   */
        !           291: #define MD_SYSHEADER    2   /* Print also system-header names       */
        !           292: #define MD_FILE         4   /* Output to the file named *.d         */
        !           293: #define MD_PHONY        8   /* Print also phony targets for each header */
        !           294: #define MD_QUOTE        16  /* 'Quote' $ and space in target name   */
        !           295:
        !           296: static FILE *   mkdep_fp;                       /* For -Mx option   */
        !           297: static char *   mkdep_target;
        !           298:     /* For -MT TARGET option and for GCC's queer environment variables.     */
        !           299: static char *   mkdep_mf;               /* Argument of -MF option   */
        !           300: static char *   mkdep_md;               /* Argument of -MD option   */
        !           301: static char *   mkdep_mq;               /* Argument of -MQ option   */
        !           302: static char *   mkdep_mt;               /* Argument of -MT option   */
        !           303:
        !           304: /* sharp_filename is filename for #line line, used only in cur_file()   */
        !           305: static char *   sharp_filename = NULL;
        !           306: static char *   argv0;      /* argv[ 0] for usage() and version()   */
        !           307: static int      ansi;           /* __STRICT_ANSI__ flag for GNUC    */
        !           308: static int      compat_mode;
        !           309:                 /* "Compatible" mode of recursive macro expansion   */
        !           310: #define MAX_ARCH_LEN    16
        !           311: static char     arch[ MAX_ARCH_LEN];    /* -arch or -m64, -m32 options      */
        !           312:
        !           313: #if COMPILER == GNUC
        !           314: #define N_QUOTE_DIR     8
        !           315: /* quote_dir[]:     Include directories for "header" specified by -iquote   */
        !           316: /* quote_dir_end:   Active end of quote_dir */
        !           317: static const char *     quote_dir[ N_QUOTE_DIR];
        !           318: static const char **    quote_dir_end = quote_dir;
        !           319: /* sys_dirp indicates the first directory to search for system headers.     */
        !           320: static const char **    sys_dirp = NULL;        /* System header directory  */
        !           321: static const char *     sysroot = NULL; /* Logical root directory of header */
        !           322: static int      i_split = FALSE;                /* For -I- option   */
        !           323: static int      gcc_work_dir = FALSE;           /* For -fworking-directory  */
        !           324: static int      gcc_maj_ver;                    /* __GNUC__         */
        !           325: static int      gcc_min_ver;                    /* __GNUC_MINOR__   */
        !           326: static int      dDflag = FALSE;         /* Flag of -dD option       */
        !           327: static int      dMflag = FALSE;         /* Flag of -dM option       */
        !           328: #endif
        !           329:
        !           330: #if COMPILER == GNUC || COMPILER == MSC
        !           331: /*
        !           332:  * preinclude points to the file specified by -include (-Fl for MSC) option,
        !           333:  * which is included prior to the main input file.
        !           334:  */
        !           335: #define         NPREINCLUDE 8
        !           336: static char *   preinclude[ NPREINCLUDE];       /* File to pre-include      */
        !           337: static char **  preinc_end = preinclude;    /* -> active end of preinclude  */
        !           338: #endif
        !           339:
        !           340: #if COMPILER == MSC
        !           341: static int      wchar_t_modified = FALSE;   /* -Zc:wchar_t flag     */
        !           342: #endif
        !           343:
        !           344: #if COMPILER == LCC
        !           345: static const char *     optim_name = "__LCCOPTIMLEVEL";
        !           346: #endif
        !           347:
        !           348: #if SYSTEM == SYS_CYGWIN
        !           349: static int      no_cygwin = FALSE;          /* -mno-cygwin          */
        !           350:
        !           351: #elif   SYSTEM == SYS_MAC
        !           352: #define         MAX_FRAMEWORK   8
        !           353: static char *   framework[ MAX_FRAMEWORK];  /* Framework directories*/
        !           354: static int      num_framework;          /* Current number of framework[]    */
        !           355: static int      sys_framework;          /* System framework dir     */
        !           356: static const char **    to_search_framework;
        !           357:                         /* Search framework[] next to the directory */
        !           358: static int      in_import;          /* #import rather than #include */
        !           359: #endif
        !           360:
        !           361: #define NO_DIR  FALSE
        !           362: #if NO_DIR
        !           363: /* Unofficial feature to strip directory part of include file   */
        !           364: static int      no_dir;
        !           365: #endif
        !           366:
        !           367: #if MCPP_LIB
        !           368: void    init_system( void)
        !           369: /* Initialize static variables  */
        !           370: {
        !           371:     if (sharp_filename)
        !           372:         free( sharp_filename);
        !           373:     sharp_filename = NULL;
        !           374:     incend = incdir = NULL;
        !           375:     fnamelist = once_list = NULL;
        !           376:     search_rule = SEARCH_INIT;
        !           377:     mb_changed = nflag = ansi = compat_mode = FALSE;
        !           378:     mkdep_fp = NULL;
        !           379:     mkdep_target = mkdep_mf = mkdep_md = mkdep_mq = mkdep_mt = NULL;
        !           380:     std_val = -1L;
        !           381:     def_cnt = undef_cnt = 0;
        !           382:     mcpp_optind = mcpp_opterr = 1;
        !           383: #if COMPILER == GNUC
        !           384:     sys_dirp = NULL;
        !           385:     sysroot = NULL;
        !           386:     gcc_work_dir = i_split = FALSE;
        !           387:     quote_dir_end = quote_dir;
        !           388:     dDflag = dMflag = FALSE;
        !           389: #endif
        !           390: #if COMPILER == MSC
        !           391:     wchar_t_modified = FALSE;
        !           392: #endif
        !           393: #if COMPILER == GNUC || COMPILER == MSC
        !           394:     preinc_end = preinclude;
        !           395: #endif
        !           396: #if SYSTEM == SYS_CYGWIN
        !           397:     no_cygwin = FALSE;
        !           398: #elif   SYSTEM == SYS_MAC
        !           399:     num_framework = sys_framework = 0;
        !           400:     to_search_framework = NULL;
        !           401: #endif
        !           402: #if NO_DIR
        !           403:     no_dir = FALSE;
        !           404: #endif
        !           405: }
        !           406:
        !           407: #endif
        !           408:
        !           409: #define OPTLISTLEN  80
        !           410:
        !           411: void    do_options(
        !           412:     int         argc,
        !           413:     char **     argv,
        !           414:     char **     in_pp,                      /* Input file name      */
        !           415:     char **     out_pp                      /* Output file name     */
        !           416: )
        !           417: /*
        !           418:  * Process command line arguments, called only at MCPP startup.
        !           419:  */
        !           420: {
        !           421:     char        optlist[ OPTLISTLEN];       /* List of option letter*/
        !           422:     const char *    warning = "warning: -%c%s option is ignored\n";
        !           423:     int         opt;
        !           424:     int         unset_sys_dirs;
        !           425:         /* Unset system-specific and site-specific include directories ?    */
        !           426:     int         set_cplus_dir;  /* Set C++ include directory ? (for GCC)*/
        !           427:     int         show_path;          /* Show include directory list  */
        !           428:     DEFBUF *    defp;
        !           429:     VAL_SIGN *  valp;
        !           430:     int         sflag;                      /* -S option or similar */
        !           431:     int         trad;                       /* -traditional         */
        !           432:     int         old_mode;                   /* backup of 'mcpp_mode'*/
        !           433:     int         gval, sse;
        !           434:     char *      cp;
        !           435:     int         i;
        !           436: #if COMPILER == GNUC
        !           437: #define NSYSDIR   8
        !           438:     /* System include directory specified by -isystem   */
        !           439:     char *      sysdir[ NSYSDIR] = { NULL, };
        !           440:     char **     sysdir_end = sysdir;
        !           441:     int         integrated_cpp; /* Flag of cc1 which integrates cpp in it   */
        !           442: #elif   COMPILER == LCC
        !           443:     const char *    debug_name = "__LCCDEBUGLEVEL";
        !           444: #endif
        !           445:
        !           446:     argv0 = argv[ 0];
        !           447:     nflag = unset_sys_dirs = show_path = sflag = trad = FALSE;
        !           448:     arch[ 0] = 0;
        !           449:     gval = sse = 0;
        !           450:     set_cplus_dir = TRUE;
        !           451:
        !           452:     /* Get current directory for -I option and #pragma once */
        !           453:     getcwd( cur_work_dir, PATHMAX);
        !           454: #if SYS_FAMILY == SYS_WIN
        !           455:     bsl2sl( cur_work_dir);
        !           456: #endif
        !           457:     sprintf( cur_work_dir + strlen( cur_work_dir), "%c%c", PATH_DELIM, EOS);
        !           458:         /* Append trailing path-delimiter   */
        !           459:
        !           460: #if COMPILER == GNUC
        !           461:     defp = look_id( "__GNUC__");    /* Already defined by init_defines()    */
        !           462:     gcc_maj_ver = atoi( defp->repl);
        !           463:     defp = look_id( "__GNUC_MINOR__");
        !           464:     gcc_min_ver = atoi( defp->repl);
        !           465:     integrated_cpp = ((gcc_maj_ver == 3 && gcc_min_ver >= 3)
        !           466:             || gcc_maj_ver == 4);
        !           467: #endif
        !           468: #if COMPILER == GNUC || COMPILER == MSC
        !           469:     option_flags.dollar_in_name = TRUE;
        !           470:     /* GCC and Visual C allows '$' in name by default   */
        !           471: #endif
        !           472:
        !           473:     set_opt_list( optlist);
        !           474:
        !           475: opt_search: ;
        !           476:     while (mcpp_optind < argc
        !           477:             && (opt = mcpp_getopt( argc, argv, optlist)) != EOF) {
        !           478:
        !           479:         switch (opt) {          /* Command line option character    */
        !           480:
        !           481: #if COMPILER == GNUC
        !           482:         case '$':                       /* Forbid '$' in identifier */
        !           483:             option_flags.dollar_in_name = FALSE;
        !           484:             break;
        !           485: #endif
        !           486:
        !           487:         case '+':
        !           488: #if COMPILER == GNUC
        !           489: plus:
        !           490: #endif
        !           491:             if (cplus_val || sflag) {
        !           492:                 mcpp_fputs( "warning: -+ option is ignored\n", ERR);
        !           493:                 break;
        !           494:             }
        !           495:             cplus_val = CPLUS;
        !           496:             break;
        !           497: #if COMPILER == GNUC
        !           498:         case '-':
        !           499:             if (memcmp( mcpp_optarg, "sysroot", 7) == 0) {
        !           500:                 if (mcpp_optarg[ 7] == '=')             /* --sysroot=DIR    */
        !           501:                     sysroot = mcpp_optarg + 8;
        !           502:                 else if (mcpp_optarg[ 7] == EOS)        /* --sysroot DIR    */
        !           503:                     sysroot = argv[ mcpp_optind++];
        !           504:                 else
        !           505:                     usage( opt);
        !           506:                 break;
        !           507:             } else {
        !           508:                 usage( opt);
        !           509:             }
        !           510: #endif
        !           511:         case '2':                   /* Reverse digraphs recognition */
        !           512:             option_flags.dig = ! option_flags.dig;
        !           513:             break;
        !           514:         case '3':                   /* Reverse trigraph recogniion  */
        !           515:             option_flags.trig = ! option_flags.trig;
        !           516:             break;
        !           517:
        !           518:         case '@':                   /* Special preprocessing mode   */
        !           519:             old_mode = mcpp_mode;
        !           520:             if (str_eq( mcpp_optarg, "post")
        !           521:                     || str_eq( mcpp_optarg, "poststd"))
        !           522:                 mcpp_mode = POST_STD;   /* 'post-Standard' mode     */
        !           523:             else if (str_eq( mcpp_optarg, "old")
        !           524:                     || str_eq( mcpp_optarg, "oldprep"))
        !           525:                 mcpp_mode = OLD_PREP;   /* 'old-Preprocessor' mode  */
        !           526:             else if (str_eq( mcpp_optarg, "kr"))
        !           527:                 mcpp_mode = KR;         /* 'K&R 1st' mode           */
        !           528:             else if (str_eq( mcpp_optarg, "std"))
        !           529:                 mcpp_mode = STD;        /* 'Standard' mode (default)*/
        !           530:             else if (str_eq( mcpp_optarg, "compat")) {
        !           531:                 compat_mode = TRUE;     /* 'compatible' mode        */
        !           532:                 mcpp_mode = STD;
        !           533:             }
        !           534:             else
        !           535:                 usage( opt);
        !           536:             standard = (mcpp_mode == STD || mcpp_mode == POST_STD);
        !           537:             if (old_mode != STD && old_mode != mcpp_mode)
        !           538:                 mcpp_fprintf( ERR, "Mode is redefined to: %s\n", mcpp_optarg);
        !           539:             break;
        !           540:
        !           541: #if COMPILER == GNUC
        !           542:         case 'A':       /* Ignore -A system(gnu), -A cpu(vax) or so */
        !           543:             break;
        !           544:         case 'a':
        !           545:             if (str_eq( mcpp_optarg, "nsi")) {      /* -ansi                */
        !           546:                 look_and_install( "__STRICT_ANSI__", DEF_NOARGS_PREDEF, null
        !           547:                         , "1");
        !           548:                 ansi = TRUE;
        !           549:                 break;
        !           550:             } else if (memcmp( mcpp_optarg, "uxbase", 6) == 0) {
        !           551:                 mcpp_optind++;
        !           552:                 break;  /* Ignore '-auxbase some' or such nonsence  */
        !           553: #if SYSTEM == SYS_MAC
        !           554:             } else if (str_eq( mcpp_optarg, "rch")) {   /* -arch    */
        !           555:                 strcpy( arch, argv[ mcpp_optind++]);
        !           556:                 if (str_eq( arch, "ppc") || str_eq( arch, "ppc7400")
        !           557:                         || str_eq( arch, "ppc64")
        !           558:                         || str_eq( arch, "i386") || str_eq( arch, "i686")
        !           559:                         || str_eq( arch, "x86_64") || str_eq( arch, "amd64")) {
        !           560:                     if (str_eq( arch, "i686"))
        !           561:                         strcpy( arch, "i386");
        !           562:                     else if (str_eq( arch, "amd64"))
        !           563:                         strcpy( arch, "x86_64");
        !           564:                     else if (str_eq( arch, "ppc7400"))
        !           565:                         strcpy( arch, "ppc");
        !           566:                     break;
        !           567:                 }   /* Else usage() */
        !           568: #endif
        !           569:             }
        !           570:             usage( opt);
        !           571: #elif   COMPILER == MSC
        !           572:         case 'a':
        !           573:             if (memcmp( mcpp_optarg, "rch", 3) == 0) {
        !           574:                 if (str_eq( mcpp_optarg + 3, ":SSE")        /* -arch:SSE    */
        !           575:                         || str_eq( mcpp_optarg + 3, ":sse"))
        !           576:                     sse = 1;
        !           577:                 else if (str_eq( mcpp_optarg + 3, ":SSE2")  /* -arch:SSE2   */
        !           578:                         || str_eq( mcpp_optarg + 3, ":sse2"))
        !           579:                     sse = 2;
        !           580:                 /* Else ignore  */
        !           581:             } else {
        !           582:                 usage( opt);
        !           583:             }
        !           584:             break;
        !           585:
        !           586:         case 'A':
        !           587:             option_flags.lang_asm = TRUE;   /* "assembler" source   */
        !           588:             break;
        !           589: #else
        !           590:         case 'a':
        !           591:             option_flags.lang_asm = TRUE;   /* "assembler" source   */
        !           592:             break;
        !           593: #endif
        !           594:
        !           595: #if ! STD_LINE_PREFIX
        !           596:         case 'b':
        !           597:             std_line_prefix = TRUE; /* Putout line and file infor-  */
        !           598:             break;                  /*   mation in C source style.  */
        !           599: #endif
        !           600:
        !           601:         case 'C':                           /* Keep comments        */
        !           602:             option_flags.c = TRUE;
        !           603:             break;
        !           604:
        !           605: #if COMPILER == GNUC
        !           606:         case 'c':
        !           607:             if (! integrated_cpp)
        !           608:                 usage( opt);
        !           609:             break;                  /* Else ignore this option      */
        !           610:         case 'd':
        !           611:             if (str_eq( mcpp_optarg, "M")) {                /* -dM          */
        !           612:                 dMflag = TRUE;
        !           613:                 no_output++;
        !           614:             } else if (str_eq( mcpp_optarg, "D")) {         /* -dD          */
        !           615:                 dDflag = TRUE;
        !           616:             } else if (str_eq( mcpp_optarg, "igraphs")) {   /* -digraphs    */
        !           617:                 option_flags.dig = TRUE;
        !           618:             } else if (str_eq( mcpp_optarg, "umpbase")) {   /* -dumpbase    */
        !           619:                 ;                                           /* Ignore       */
        !           620:             } else {
        !           621:                 usage( opt);
        !           622:             }
        !           623:             break;
        !           624: #endif  /* COMPILER == GNUC */
        !           625:
        !           626:         case 'D':                           /* Define symbol        */
        !           627:             if (def_cnt >= MAX_DEF) {
        !           628:                 mcpp_fputs( "Too many -D options.\n", ERR);
        !           629:                 longjmp( error_exit, -1);
        !           630:             }
        !           631:             def_list[ def_cnt++] = mcpp_optarg;
        !           632:             break;
        !           633:
        !           634:         case 'e':
        !           635:             /* Change the default MBCHAR encoding   */
        !           636:             if (set_encoding( mcpp_optarg, FALSE, 0) == NULL)
        !           637:                 usage( opt);
        !           638:             mb_changed = TRUE;
        !           639:             break;
        !           640:
        !           641: #if COMPILER == GNUC
        !           642:         case 'E':
        !           643:             if (! integrated_cpp)
        !           644:                 usage( opt);
        !           645:             break;                          /* Ignore this option   */
        !           646:         case 'f':
        !           647:             if (memcmp( mcpp_optarg, "input-charset=", 14) == 0) {
        !           648:                 /* Treat -finput-charset= as the same option as -e  */
        !           649:                 if (set_encoding( mcpp_optarg + 14, FALSE, 0) == NULL)
        !           650:                     usage( opt);
        !           651:                 mb_changed = TRUE;
        !           652:             } else if (str_eq( mcpp_optarg, "working-directory")) {
        !           653:                 gcc_work_dir = TRUE;
        !           654:             } else if (str_eq( mcpp_optarg, "no-working-directory")) {
        !           655:                 gcc_work_dir = FALSE;
        !           656:             } else if (str_eq( mcpp_optarg, "stack-protector")) {
        !           657:                 look_and_install( "__SSP__", DEF_NOARGS_PREDEF, null, "1");
        !           658:             } else if (str_eq( mcpp_optarg, "stack-protector-all")) {
        !           659:                 look_and_install( "__SSP_ALL__", DEF_NOARGS_PREDEF, null, "2");
        !           660:             } else if (str_eq( mcpp_optarg, "exceptions")) {
        !           661:                 look_and_install( "__EXCEPTIONS", DEF_NOARGS_PREDEF, null
        !           662:                         , "1");
        !           663:             } else if (str_eq( mcpp_optarg, "no-exceptions")) {
        !           664:                 undef_list[ undef_cnt++] = "__EXCEPTIONS";
        !           665:             } else if (str_eq( mcpp_optarg, "PIC")
        !           666:                     || str_eq( mcpp_optarg, "pic")
        !           667:                     || str_eq( mcpp_optarg, "PIE")
        !           668:                     || str_eq( mcpp_optarg, "pie")) {
        !           669:                 look_and_install( "__PIC__", DEF_NOARGS_PREDEF, null, "1");
        !           670:                 look_and_install( "__pic__", DEF_NOARGS_PREDEF, null, "1");
        !           671:             } else if (str_eq( mcpp_optarg, "no-dollars-in-identifiers")) {
        !           672:                 option_flags.dollar_in_name = FALSE;
        !           673:             } else if (str_eq( mcpp_optarg, "no-show-column")) {
        !           674:                 ;                           /* Ignore this option   */
        !           675:             } else if (! integrated_cpp) {
        !           676:                 usage( opt);
        !           677:             }
        !           678:             break;
        !           679:
        !           680:         case 'g':
        !           681:             if (!isdigit( *mcpp_optarg)
        !           682:                     && str_eq( argv[ mcpp_optind - 2], "-g"))
        !           683:                 /* Neither '-g 0' nor '-ggdb' -- No argument    */
        !           684:                 mcpp_optind--;
        !           685:             break;                          /* Ignore the option    */
        !           686: #elif COMPILER == LCC
        !           687:         case 'g':               /* Define __LCCDEBUGLEVEL as <n>    */
        !           688:             if (*(mcpp_optarg + 1) == EOS && isdigit( *mcpp_optarg)) {
        !           689:                 defp = look_id( debug_name);
        !           690:                 strcpy( defp->repl, mcpp_optarg);
        !           691:             } else {
        !           692:                 usage( opt);
        !           693:             }
        !           694:             break;
        !           695: #elif COMPILER == MSC
        !           696:         case 'G':
        !           697:             if (*(mcpp_optarg + 1) == EOS) {    /* -Gx              */
        !           698:                 switch (*mcpp_optarg) {
        !           699:                 case '3':   case '4':   case '5':   case '6':
        !           700:                     gval = *mcpp_optarg;
        !           701:                     break;
        !           702:                 case 'B':                   /* -GB                  */
        !           703:                     gval = '6';
        !           704:                     break;
        !           705:                 case 'R':
        !           706:                     look_and_install( "_CPPRTTI", DEF_NOARGS_PREDEF, null
        !           707:                             , "1");
        !           708:                     break;
        !           709:                 case 'X':
        !           710:                     look_and_install( "_CPPUNWIND", DEF_NOARGS_PREDEF, null
        !           711:                             , "1");
        !           712:                     break;
        !           713:                 case 'Z':
        !           714:                     look_and_install( "__MSVC_RUNTIME_CHECKS"
        !           715:                             , DEF_NOARGS_PREDEF, null, "1");
        !           716:                     break;
        !           717:                 default :
        !           718:                     mcpp_fprintf( ERR, warning, opt, mcpp_optarg);
        !           719:                 }
        !           720:             } else {
        !           721:                 usage( opt);
        !           722:             }
        !           723:             break;
        !           724: #endif
        !           725:
        !           726: #if SYSTEM == SYS_MAC
        !           727:         case 'F':
        !           728:             framework[ num_framework++] = mcpp_optarg;
        !           729:             break;
        !           730: #endif
        !           731:
        !           732:         case 'h':
        !           733:             if (*(mcpp_optarg + 1) == EOS && isdigit( *mcpp_optarg))
        !           734:                 /* a digit  */
        !           735:                 look_and_install( "__STDC_HOSTED__", DEF_NOARGS_PREDEF, null
        !           736:                         , mcpp_optarg);
        !           737:             else
        !           738:                 usage( opt);
        !           739:             break;
        !           740:
        !           741: #if COMPILER == MSC
        !           742:         case 'X':
        !           743:                 unset_sys_dirs = TRUE;
        !           744:                 break;
        !           745: #endif
        !           746:         case 'I':                           /* Include directory    */
        !           747:             if (str_eq( mcpp_optarg, "-")) {        /* -I-                  */
        !           748: #if COMPILER == GNUC
        !           749:                 sys_dirp = incend;  /* Split include directories    */
        !           750:                 i_split = TRUE;
        !           751: #else
        !           752:                 unset_sys_dirs = TRUE;
        !           753:                         /* Unset pre-specified include directories  */
        !           754: #endif
        !           755:             } else if (*(mcpp_optarg + 1) == EOS && isdigit( *mcpp_optarg)
        !           756:                     && (i = *mcpp_optarg - '0') != 0
        !           757:                     && (i & ~(CURRENT | SOURCE)) == 0) {
        !           758:                 search_rule = i;            /* -I1, -I2 or -I3      */
        !           759:             } else {                        /* Not '-' nor a digit  */
        !           760:                 set_a_dir( mcpp_optarg);    /* User-defined dir     */
        !           761:             }
        !           762:             break;
        !           763:
        !           764: #if COMPILER == MSC
        !           765:         case 'F':
        !           766:             if (str_eq( mcpp_optarg, "l")) {        /* -Fl          */
        !           767:                 if (preinc_end >= &preinclude[ NPREINCLUDE]) {
        !           768:                     mcpp_fputs( "Too many -Fl options.\n", ERR);
        !           769:                     longjmp( error_exit, -1);
        !           770:                 }
        !           771:                 *preinc_end++ = argv[ mcpp_optind++];
        !           772:             } else {
        !           773:                 usage( opt);
        !           774:             }
        !           775:             break;
        !           776: #endif
        !           777:
        !           778: #if COMPILER == GNUC
        !           779:         case 'i':
        !           780:             if (str_eq( mcpp_optarg, "nclude")) {   /* -include     */
        !           781:                 if (preinc_end >= &preinclude[ NPREINCLUDE]) {
        !           782:                     mcpp_fputs( "Too many -include options.\n", ERR);
        !           783:                     longjmp( error_exit, -1);
        !           784:                 }
        !           785:                 *preinc_end++ = argv[ mcpp_optind++];
        !           786:             } else if (str_eq( mcpp_optarg, "system")) {    /* -isystem     */
        !           787:                 if (sysdir_end >= &sysdir[ NSYSDIR]) {
        !           788:                     mcpp_fputs( "Too many -isystem options.\n", ERR);
        !           789:                     longjmp( error_exit, -1);
        !           790:                 }
        !           791:                 *sysdir_end++ = argv[ mcpp_optind++];
        !           792:                 /* Add the directory before system include directory*/
        !           793:             } else if (str_eq( mcpp_optarg, "quote")) {     /* -iquote      */
        !           794:                 if (quote_dir_end >= &quote_dir[ N_QUOTE_DIR]) {
        !           795:                     mcpp_fputs( "Too many -iquote options.\n", ERR);
        !           796:                     longjmp( error_exit, -1);
        !           797:                 }
        !           798:                 *quote_dir_end++ = argv[ mcpp_optind++];
        !           799:                 /* Add the directory for #include "header"          */
        !           800:             } else if (memcmp( mcpp_optarg, "sysroot", 7) == 0) {
        !           801:                 if (mcpp_optarg[ 7] == '=')     /* -isysroot=DIR    */
        !           802:                     sysroot = mcpp_optarg + 8;
        !           803:                 else if (mcpp_optarg[ 7] == EOS)        /* -isysroot DIR    */
        !           804:                     sysroot = argv[ mcpp_optind++];
        !           805:                 else
        !           806:                     usage( opt);
        !           807:             } else if (str_eq( mcpp_optarg, "prefix")       /* -iprefix     */
        !           808:                     || str_eq( mcpp_optarg, "withprefix")   /* -iwithprefix */
        !           809:                     || str_eq( mcpp_optarg, "withprefixbefore")
        !           810:                                             /* -iwithprefixbefore   */
        !           811:                     || str_eq( mcpp_optarg, "dirafter")     /* -idirafter   */
        !           812:                     || str_eq( mcpp_optarg, "multilib")) {  /* -imultilib   */
        !           813:                 mcpp_optind++;              /* Skip the argument    */
        !           814:                 /* Ignore these options */
        !           815:             } else {
        !           816:                 usage( opt);
        !           817:             }
        !           818:             break;
        !           819: #endif
        !           820:
        !           821:         case 'j':
        !           822:             option_flags.no_source_line = TRUE;
        !           823:             break;  /* Do not output the source line in diagnostics */
        !           824:
        !           825: #if COMPILER == MSC
        !           826:         case 'J':
        !           827:             look_and_install( "_CHAR_UNSIGNED", DEF_NOARGS_PREDEF, null, "1");
        !           828:             break;
        !           829: #endif
        !           830:
        !           831:         case 'K':
        !           832:             mcpp_debug |= MACRO_CALL;
        !           833:             /*
        !           834:              * Putout macro expansion informations embedded in comments.
        !           835:              * Same with '#pragma MCPP debug macro_call'.
        !           836:              */
        !           837:             /* Enable white spaces preservation, too    */
        !           838:             /* Fall through */
        !           839:         case 'k':
        !           840:             option_flags.k = TRUE;
        !           841:             /* Keep white spaces of input lines as they are */
        !           842:             break;
        !           843:
        !           844: #if COMPILER == GNUC
        !           845:         case 'l':
        !           846:             if (memcmp( mcpp_optarg, "ang-", 4) != 0) {
        !           847:                 usage( opt);
        !           848:             } else if (str_eq( mcpp_optarg + 4, "c")) {     /* -lang-c  */
        !           849:                 ;                           /* Ignore this option   */
        !           850:             } else if (str_eq( mcpp_optarg + 4, "c99")      /* -lang-c99*/
        !           851:                         || str_eq( mcpp_optarg + 4, "c9x")) {   /* -lang-c9x*/
        !           852:                 if (! sflag) {
        !           853:                     stdc_val = 1;           /* Define __STDC__ to 1 */
        !           854:                     std_val = 199901L;
        !           855:                     sflag = TRUE;
        !           856:                 }
        !           857:             } else if (str_eq( mcpp_optarg + 4, "c89")) {   /* -lang-c89*/
        !           858:                 if (! sflag) {
        !           859:                     stdc_val = 1;           /* Define __STDC__ to 1 */
        !           860:                     sflag = TRUE;
        !           861:                 }
        !           862:             } else if (str_eq( mcpp_optarg + 4, "c++")) {   /* -lang-c++*/
        !           863:                 goto  plus;
        !           864:             } else if (str_eq( mcpp_optarg + 4, "asm")) {   /* -lang-asm*/
        !           865:                 option_flags.lang_asm = TRUE;
        !           866:             } else {
        !           867:                 usage( opt);
        !           868:             }
        !           869:             break;
        !           870: #endif  /* COMPILER == GNUC */
        !           871:
        !           872:         case 'M':           /* Output source file dependency line   */
        !           873:             if (str_eq( mcpp_optarg, "M")) {                /* -MM  */
        !           874:                 ;
        !           875:             } else if (str_eq( mcpp_optarg, "D")) {         /* -MD  */
        !           876:                 mkdep |= (MD_SYSHEADER | MD_FILE);
        !           877:             } else if (str_eq( mcpp_optarg, "MD")) {         /* -MMD */
        !           878:                 mkdep |= MD_FILE;
        !           879:             } else if (str_eq( mcpp_optarg, "P")) {          /* -MP  */
        !           880:                 mkdep |= MD_PHONY;
        !           881:             } else if (str_eq( mcpp_optarg, "Q")) {  /* -MQ target   */
        !           882:                 mkdep |= MD_QUOTE;
        !           883:                 mkdep_mq = argv[ mcpp_optind++];
        !           884:             } else if (str_eq( mcpp_optarg, "T")) {  /* -MT target   */
        !           885:                 mkdep_mt = argv[ mcpp_optind++];
        !           886:             } else if (str_eq( mcpp_optarg, "F")) {  /* -MF file     */
        !           887:                 mkdep_mf = argv[ mcpp_optind++];
        !           888:             } else if (argv[ mcpp_optind - 1] == mcpp_optarg) {     /* -M   */
        !           889:                 mkdep |= MD_SYSHEADER;
        !           890:                 mcpp_optind--;
        !           891:             } else {
        !           892:                 usage( opt);
        !           893:             }
        !           894:             if (str_eq( mcpp_optarg, "D") || str_eq( mcpp_optarg, "MD")) {
        !           895:                 cp = argv[ mcpp_optind];
        !           896:                 if (cp && *cp != '-')           /* -MD (-MMD) file  */
        !           897:                     mkdep_md = argv[ mcpp_optind++];
        !           898:             }
        !           899:             mkdep |= MD_MKDEP;
        !           900:             break;
        !           901:
        !           902: #if SYS_FAMILY == SYS_UNIX
        !           903:         case 'm':
        !           904:             if (str_eq( mcpp_optarg, "64")) {               /* -m64 */
        !           905:                 if (str_eq( CPU, "i386"))
        !           906:                     strcpy( arch, "x86_64");
        !           907:                 else if (str_eq( CPU, "ppc"))
        !           908:                     strcpy( arch, "ppc64");
        !           909:                 /* Else ignore  */
        !           910:                 break;
        !           911:             } else if (str_eq( mcpp_optarg, "32")) {        /* -m32 */
        !           912:                 if (str_eq( CPU, "x86_64"))
        !           913:                     strcpy( arch, "i386");
        !           914:                 else if (str_eq( CPU, "ppc64"))
        !           915:                     strcpy( arch, "ppc");
        !           916:                 /* Else ignore  */
        !           917:                 break;
        !           918:             } else if (str_eq( mcpp_optarg, "mmx")) {   /* -mmmx    */
        !           919:                 look_and_install( "__MMX__", DEF_NOARGS_PREDEF, null, "1");
        !           920:                 break;
        !           921:             } else if (str_eq( mcpp_optarg, "no-mmx")) {    /* -mno-mmx     */
        !           922:                 undef_list[ undef_cnt++] = "__MMX__";
        !           923:                 break;
        !           924:             }
        !           925: #endif  /* SYS_FAMILY == UNIX   */
        !           926: #if COMPILER == GNUC
        !           927: #if SYSTEM == SYS_CYGWIN
        !           928:             if (str_eq( mcpp_optarg, "no-cygwin")) {    /* -mno-cygwin      */
        !           929:                 no_cygwin = TRUE;
        !           930:                 break;
        !           931:             }
        !           932: #endif
        !           933:             if (! integrated_cpp)
        !           934:                 usage( opt);
        !           935:             break;
        !           936:
        !           937:         case 'u':
        !           938:             if (! str_eq( mcpp_optarg, "ndef"))     /* -undef       */
        !           939:                 usage( opt);                /* Else fall through    */
        !           940: #endif  /* COMPILER == GNUC */
        !           941:
        !           942: #if COMPILER == MSC
        !           943:         case 'u':
        !           944: #endif
        !           945:         case 'N':
        !           946:             /* No predefines:   remove "unix", "__unix__" and friends.  */
        !           947:             nflag = TRUE;
        !           948:             break;
        !           949:
        !           950: #if COMPILER == GNUC || NO_DIR
        !           951:         case 'n':
        !           952: #if NO_DIR
        !           953:             if (str_eq( mcpp_optarg, "odir")) {     /* -nodir       */
        !           954:                 no_dir = TRUE;
        !           955:             }
        !           956: #endif
        !           957: #if COMPILER == GNUC
        !           958:             if (str_eq( mcpp_optarg, "ostdinc")) {  /* -nostdinc    */
        !           959:                 unset_sys_dirs = TRUE;  /* Unset pre-specified directories  */
        !           960:             } else if (str_eq( mcpp_optarg, "ostdinc++")) { /* -nostdinc++  */
        !           961:                 set_cplus_dir = FALSE;  /* Unset C++-specific directories   */
        !           962:             } else if (str_eq( mcpp_optarg, "oprecomp")) {  /* -noprecomp   */
        !           963:                 mcpp_fprintf( ERR, warning, opt, mcpp_optarg);
        !           964:                 break;
        !           965:             }
        !           966: #endif
        !           967:             else {
        !           968:                 usage( opt);
        !           969:             }
        !           970:             break;
        !           971: #endif
        !           972:
        !           973: #if COMPILER == GNUC
        !           974:         case 'O':
        !           975:             if (integrated_cpp) {
        !           976:                 if (*mcpp_optarg == '-')            /* No argument  */
        !           977:                     mcpp_optind--;
        !           978:                 else if ((isdigit( *mcpp_optarg) && *mcpp_optarg != '0')
        !           979:                         || *mcpp_optarg == 's' || *mcpp_optarg == 'z')
        !           980:                                             /* -O1, -O2 -Os, -Oz    */
        !           981:                     look_and_install( "__OPTIMIZE__", DEF_NOARGS_PREDEF, null
        !           982:                             , "1");
        !           983:                 else if (! isdigit( *mcpp_optarg))
        !           984:                     usage( opt);
        !           985:                 /* Else -O0: ignore */
        !           986:             } else {
        !           987:                 usage( opt);
        !           988:             }
        !           989:             break;                  /* Else ignore -Ox option       */
        !           990: #elif COMPILER == LCC
        !           991:         case 'O':                   /* Define __LCCOPTIMLEVEL as 1  */
        !           992:             defp = look_id( optim_name);
        !           993:             strcpy( defp->repl, "1");
        !           994:             break;
        !           995: #endif
        !           996:
        !           997:         case 'o':
        !           998:             *out_pp = mcpp_optarg;          /* Output file name     */
        !           999:             break;
        !          1000:
        !          1001:         case 'P':                           /* No #line output      */
        !          1002:             option_flags.p = TRUE;
        !          1003:             break;
        !          1004:
        !          1005: #if COMPILER == GNUC
        !          1006:         case 'p':
        !          1007:             if (str_eq( mcpp_optarg, "edantic")     /* -pedantic    */
        !          1008:                     || str_eq( mcpp_optarg, "edantic-errors")) {
        !          1009:                                             /* -pedantic-errors     */
        !          1010:                 /* This option does not imply -ansi */
        !          1011:                 if (warn_level == -1)
        !          1012:                     warn_level = 0;
        !          1013:                 warn_level |= (1 | 2 | 4);
        !          1014:                 if (! sflag && ! cplus_val) {
        !          1015:                     stdc_val = 1;
        !          1016:                     sflag = TRUE;
        !          1017:                 }
        !          1018:             } else {
        !          1019:                 usage( opt);
        !          1020:             }
        !          1021:             break;
        !          1022:         case 'q':
        !          1023:             if (str_eq( mcpp_optarg, "uiet"))
        !          1024:                 /* -quiet: GCC's undocumented, yet frequently specified opt */
        !          1025:                 break;                      /* Ignore the option    */
        !          1026:             else
        !          1027:                 usage( opt);
        !          1028:             break;
        !          1029: #endif  /* COMPILER == GNUC */
        !          1030:
        !          1031:         case 'Q':
        !          1032:             option_flags.q = TRUE;
        !          1033:             break;
        !          1034:
        !          1035: #if COMPILER == MSC
        !          1036:         case 'R':               /* -RTC1, -RTCc, -RTCs, -RTCu, etc. */
        !          1037:             if (memcmp( mcpp_optarg, "TC", 2) == 0
        !          1038:                     && *(mcpp_optarg + 2) != EOS)
        !          1039:                 look_and_install( "__MSVC_RUNTIME_CHECKS", DEF_NOARGS_PREDEF
        !          1040:                         , null, "1");
        !          1041:             else
        !          1042:                 usage( opt);
        !          1043:             break;
        !          1044: #endif
        !          1045:
        !          1046:         case 'S':
        !          1047:             if (cplus_val || sflag) {   /* C++ or the second time   */
        !          1048:                 mcpp_fprintf( ERR, warning, opt, mcpp_optarg);
        !          1049:                 break;
        !          1050:             }
        !          1051:             i = *mcpp_optarg;
        !          1052:             if (! isdigit( i) || *(mcpp_optarg + 1) != EOS)
        !          1053:                 usage( opt);
        !          1054:             stdc_val = i - '0';
        !          1055:             sflag = TRUE;
        !          1056:             break;
        !          1057:
        !          1058: #if COMPILER == GNUC
        !          1059:         case 'r':
        !          1060:             if (str_eq( mcpp_optarg, "emap"))
        !          1061:                 mcpp_fprintf( ERR, warning, opt, mcpp_optarg);
        !          1062:                                             /* Ignore -remap option */
        !          1063:             else
        !          1064:                 usage( opt);
        !          1065:             break;
        !          1066:
        !          1067:         case 's':
        !          1068:             if (memcmp( mcpp_optarg, "td=", 3) == 0
        !          1069:                     && strlen( mcpp_optarg) > 3) {  /* -std=STANDARD*/
        !          1070:                 cp = mcpp_optarg + 3;
        !          1071:                 if (str_eq( cp, "c89")              /* std=c89      */
        !          1072:                         || str_eq( cp, "c90")       /* std=c90      */
        !          1073:                         || str_eq( cp, "gnu89")     /* std=gnu89    */
        !          1074:                         || str_eq( cp, "iso9899:1990")) {
        !          1075:                     std_val = 0L;               /* C90 + extensions */
        !          1076:                 } else if (str_eq( cp, "c99")       /* std=c99      */
        !          1077:                         || str_eq( cp, "c9x")       /* std=c9x      */
        !          1078:                         || str_eq( cp, "gnu99")     /* std=gnu99    */
        !          1079:                         || str_eq( cp, "gnu9x")     /* std=gnu9x    */
        !          1080:                         || str_eq( cp, "iso9899:1999")
        !          1081:                         || str_eq( cp, "iso9899:199x")) {
        !          1082:                     std_val = 199901L;
        !          1083:                 } else if (str_eq( cp, "c++98")) {  /* std=c++98    */
        !          1084:                     cplus_val = std_val = 199711L;
        !          1085:                 } else if (memcmp( cp, "iso9899:", 8) == 0
        !          1086:                         && strlen( cp) >= 14) { /* std=iso9899:199409, etc. */
        !          1087:                     mcpp_optarg = cp + 8;
        !          1088:                     look_and_install( "__STRICT_ANSI__", DEF_NOARGS_PREDEF
        !          1089:                             , null, "1");
        !          1090:                     ansi = TRUE;
        !          1091:                     goto Version;
        !          1092:                 } else if (memcmp( cp, "iso14882", 8) == 0) {
        !          1093:                     cp += 8;
        !          1094:                     ansi = TRUE;
        !          1095:                     if (cp && *cp == ':' && strlen( cp) >= 7) {
        !          1096:                                     /* std=iso14882:199711, etc.    */
        !          1097:                         cplus_val = CPLUS;
        !          1098:                         mcpp_optarg = cp + 1;
        !          1099:                         goto Version;
        !          1100:                     } else {
        !          1101:                         goto plus;
        !          1102:                     }
        !          1103:                 } else {
        !          1104:                     usage( opt);
        !          1105:                 }
        !          1106:                 if (! cplus_val && memcmp( cp, "gnu", 3) != 0) {
        !          1107:                     /* 'std=gnu*' does not imply -ansi  */
        !          1108:                     look_and_install( "__STRICT_ANSI__", DEF_NOARGS_PREDEF
        !          1109:                             , null, "1");
        !          1110:                     ansi = TRUE;
        !          1111:                 }
        !          1112:                 stdc_val = 1;
        !          1113:                 sflag = TRUE;
        !          1114:             } else {
        !          1115:                 usage( opt);
        !          1116:             }
        !          1117:             break;
        !          1118:
        !          1119:         case 't':
        !          1120:             if (str_eq( mcpp_optarg, "raditional")
        !          1121:                     || str_eq( mcpp_optarg, "raditional-cpp")) {
        !          1122:                                 /* -traditional, -traditional-cpp   */
        !          1123:                 trad = TRUE;
        !          1124:                 mcpp_mode = OLD_PREP;
        !          1125:             } else if (str_eq( mcpp_optarg, "rigraphs")) {
        !          1126:                 option_flags.trig = TRUE;           /* -trigraphs   */
        !          1127:             } else {
        !          1128:                 usage( opt);
        !          1129:             }
        !          1130:             break;
        !          1131: #endif  /* COMPILER == GNUC */
        !          1132:
        !          1133: #if COMPILER == MSC
        !          1134:         case 'T':
        !          1135:             if (strlen( mcpp_optarg) > 1)
        !          1136:                 usage( opt);
        !          1137:             i = tolower( *mcpp_optarg);             /* Fold case    */
        !          1138:             if (i == 'c') {
        !          1139:                 ;                           /* Ignore this option   */
        !          1140:             } else if (i == 'p') {
        !          1141:                 cplus_val = CPLUS;
        !          1142:             } else {
        !          1143:                 usage( opt);
        !          1144:             }
        !          1145:             break;
        !          1146: #endif
        !          1147:
        !          1148:         case 'U':                           /* Undefine macro       */
        !          1149:             if (undef_cnt >= MAX_UNDEF) {
        !          1150:                 mcpp_fputs( "Too many -U options.\n", ERR);
        !          1151:                 longjmp( error_exit, -1);
        !          1152:             }
        !          1153:             undef_list[ undef_cnt++] = mcpp_optarg;
        !          1154:             break;
        !          1155:
        !          1156:         case 'V':
        !          1157: #if COMPILER == GNUC
        !          1158: Version:
        !          1159: #endif
        !          1160:             valp = eval_num( mcpp_optarg);
        !          1161:             if (valp->sign == VAL_ERROR)
        !          1162:                 usage( opt);
        !          1163:             std_val = (long) valp->val;
        !          1164:             break;
        !          1165:
        !          1166:         case 'v':
        !          1167:             option_flags.v = TRUE;
        !          1168:             show_path = TRUE;
        !          1169:             break;
        !          1170:
        !          1171:         case 'W':                           /* warning level        */
        !          1172:             if (warn_level == -1)           /* Have to initialize   */
        !          1173:                 warn_level = 0;
        !          1174: #if COMPILER == GNUC
        !          1175:             if (argv[ mcpp_optind - 1] == mcpp_optarg) {    /* No argument  */
        !          1176:                 /*
        !          1177:                  * Note: -W without argument is not officially supported.
        !          1178:                  *  It may cause an error.
        !          1179:                  */
        !          1180:                 warn_level |= (1 | 2 | 4 | 16);
        !          1181:                 mcpp_optind--;
        !          1182:             } else if (str_eq( mcpp_optarg, "comment")
        !          1183:                         || str_eq( mcpp_optarg, "comments")
        !          1184:                         || str_eq( mcpp_optarg, "sign-compare")) {
        !          1185:                 warn_level |= 1;
        !          1186:             } else if (str_eq( mcpp_optarg, "undef")) {
        !          1187:                 warn_level |= 4;
        !          1188:             } else if (str_eq( mcpp_optarg, "all")) {
        !          1189:                 warn_level |= (1 | 16);     /* Convert -Wall to -W17*/
        !          1190:             } else if (str_eq( mcpp_optarg, "trigraphs")) {
        !          1191:                 warn_level |= 16;
        !          1192:             }
        !          1193: #endif  /* COMPILER == GNUC */
        !          1194: #if COMPILER == MSC
        !          1195:             if (str_eq( mcpp_optarg, "all")) {
        !          1196:                 warn_level |= (1 | 16);     /* Convert -Wall to -W17*/
        !          1197:             } else if (str_eq( mcpp_optarg, "L")) {
        !          1198:                 option_flags.no_source_line = TRUE;
        !          1199:                                         /* Single-line diagnostic   */
        !          1200:             }
        !          1201: #endif
        !          1202:             if (isdigit( *mcpp_optarg)) {
        !          1203:                 warn_level |= parse_warn_level( mcpp_optarg, opt);
        !          1204:                 if (warn_level > 31 || warn_level < 0)
        !          1205:                     usage( opt);
        !          1206:             }
        !          1207:             if (warn_level == 0)
        !          1208:                 warn_level = 0xFF;          /* Remember this option */
        !          1209:             /* Else ignore the option   */
        !          1210:             break;
        !          1211:
        !          1212: #if COMPILER == GNUC || COMPILER == MSC
        !          1213:         case 'w':                           /* Same as -W0          */
        !          1214:             warn_level = 0xFF;              /* Remenber this option */
        !          1215:             break;
        !          1216: #endif
        !          1217:
        !          1218: #if COMPILER == GNUC
        !          1219:         case 'x':
        !          1220:             if (str_eq( mcpp_optarg, "c")) {
        !          1221:                 break;                      /* -x c -- ignore this  */
        !          1222:             } else if (str_eq( mcpp_optarg, "c++")) {
        !          1223:                 goto plus;
        !          1224:             } else if (str_eq( mcpp_optarg, "assembler-with-cpp")) {
        !          1225:                 option_flags.lang_asm = TRUE;
        !          1226:                 break;
        !          1227:             } else {
        !          1228:                 usage( opt);
        !          1229:             }
        !          1230:             break;
        !          1231: #endif
        !          1232:
        !          1233: #if COMPILER == MSC
        !          1234:         case 'Z':
        !          1235:             if (str_eq( mcpp_optarg, "c:wchar_t")) {        /* -Zc:wchar_t  */
        !          1236:                 look_and_install( "_NATIVE_WCHAR_T_DEFINED", DEF_NOARGS_PREDEF
        !          1237:                         , null, "1");
        !          1238:                 look_and_install( "_WCHAR_T_DEFINED", DEF_NOARGS_PREDEF, null
        !          1239:                         , "1");
        !          1240:                 wchar_t_modified = TRUE;
        !          1241:             } else if (str_eq( mcpp_optarg, "c:wchar_t-")) {/* -Zc:wchar_t- */
        !          1242:                 wchar_t_modified = TRUE;        /* Do not define the macros */
        !          1243:             } else if (str_eq( mcpp_optarg, "l")) {
        !          1244:                 look_and_install( "_VC_NODEFAULTLIB", DEF_NOARGS_PREDEF, null
        !          1245:                         , "1");
        !          1246:             } else if (str_eq( mcpp_optarg, "a")) {         /* -Za  */
        !          1247:                 undefine( "_MSC_EXTENSIONS");
        !          1248:                 option_flags.dollar_in_name = FALSE;
        !          1249:             } else if (str_eq( mcpp_optarg, "e")) {
        !          1250:                 /* Ignore -Ze silently  */
        !          1251:                 break;
        !          1252:             } else if (*(mcpp_optarg + 1) == EOS) {
        !          1253:                 /* -Z followed by one char  */
        !          1254:                 mcpp_fprintf( ERR, warning, opt, mcpp_optarg);
        !          1255:                 /* Ignore the option with warning   */
        !          1256:             } else {
        !          1257:                 usage( opt);
        !          1258:             }
        !          1259:             break;
        !          1260: #endif
        !          1261:
        !          1262:         case 'z':
        !          1263:             option_flags.z = TRUE;  /* No output of included file   */
        !          1264:             break;
        !          1265:
        !          1266:         default:                            /* What is this one?    */
        !          1267:             usage( opt);
        !          1268:             break;
        !          1269:         }                               /* Switch on all options    */
        !          1270:
        !          1271:     }                                   /* For all arguments        */
        !          1272:
        !          1273:     if (mcpp_optind < argc && set_files( argc, argv, in_pp, out_pp) != NULL)
        !          1274:         goto  opt_search;       /* More options after the filename  */
        !          1275:
        !          1276:     /* Check consistency of specified options, set some variables   */
        !          1277:     chk_opts( sflag, trad);
        !          1278:
        !          1279:     if (warn_level == -1)               /* No -W option             */
        !          1280:         warn_level = 1;                 /* Default warning level    */
        !          1281:     else if (warn_level == 0xFF)
        !          1282:         warn_level = 0;                 /* -W0 has high precedence  */
        !          1283:
        !          1284: #if SYSTEM == SYS_MAC
        !          1285:     set_a_dir( NULL);                       /* Initialize incdir[]  */
        !          1286:     to_search_framework = incend;
        !          1287:                         /* Search framework[] next to the directory */
        !          1288: #endif
        !          1289:
        !          1290: #if COMPILER == GNUC && SYSTEM == SYS_MAC
        !          1291:     if (arch[ 0]) {             /* -arch option has been specified  */
        !          1292:         if (((str_eq( CPU, "i386") || str_eq( CPU, "x86_64"))
        !          1293:                 && (! str_eq( arch, "i386") && ! str_eq( arch, "x86_64")))
        !          1294:             || ((str_eq( CPU, "ppc") || str_eq( CPU, "ppc64"))
        !          1295:                 && (! str_eq( arch, "ppc") && ! str_eq( arch, "ppc64")))) {
        !          1296:             mcpp_fprintf( ERR, "Wrong argument of -arch option: %s\n", arch);
        !          1297:             longjmp( error_exit, -1);
        !          1298:         }
        !          1299:     }
        !          1300: #endif
        !          1301:     if (! arch[ 0]) {
        !          1302:         /* None of -arch, -m32 or -m64 options has been specified.  */
        !          1303:         /* The CPU-specific-macros will be defined in init_cpu_macro(). */
        !          1304:         strcpy( arch, CPU);
        !          1305:     }
        !          1306: #if COMPILER != GNUC
        !          1307:     init_cpu_macro( gval, sse);
        !          1308: #endif
        !          1309:
        !          1310: #if COMPILER == GNUC
        !          1311:     if (sysdir < sysdir_end) {
        !          1312:         char **     dp = sysdir;
        !          1313:         if (! sys_dirp || sys_dirp == incdir)
        !          1314:             sys_dirp = dp;
        !          1315:         while (dp < sysdir_end)
        !          1316:             set_a_dir( *dp++);
        !          1317:     }
        !          1318:     if (*in_pp && str_eq( (*in_pp) + strlen( *in_pp) - 2, ".S"))
        !          1319:         option_flags.lang_asm = TRUE;   /* Input file name is *.S   */
        !          1320:     if (option_flags.lang_asm) {
        !          1321:         look_and_install( "__ASSEMBLER__", DEF_NOARGS_PREDEF, null, "1");
        !          1322:         option_flags.dollar_in_name = FALSE;        /* Disable '$' in name  */
        !          1323:     }
        !          1324:     if (! sys_dirp || sys_dirp == incdir)
        !          1325:         sys_dirp = incend;
        !          1326: #endif
        !          1327: #if SYSTEM == SYS_MAC
        !          1328:     init_framework();                   /* After setting sys_dirp   */
        !          1329: #endif
        !          1330:     set_env_dirs();
        !          1331:     if (! unset_sys_dirs)
        !          1332:         set_sys_dirs( set_cplus_dir);
        !          1333:
        !          1334:     if (mkdep_mf) {                         /* -MF overrides -MD    */
        !          1335:         mkdep_fp = fopen( mkdep_mf, "w");
        !          1336:     } else if (mkdep_md) {
        !          1337:         mkdep_fp = fopen( mkdep_md, "w");
        !          1338:     }
        !          1339:     if (mkdep_mq)                           /* -MQ overrides -MT    */
        !          1340:         mkdep_target = mkdep_mq;
        !          1341:     else if (mkdep_mt)
        !          1342:         mkdep_target = mkdep_mt;
        !          1343:
        !          1344:     /* Normalize the path-list  */
        !          1345:     if (*in_pp && ! str_eq( *in_pp, "-")) {
        !          1346:         char *  tmp = norm_path( null, *in_pp, FALSE, FALSE);
        !          1347:         if (tmp)                        /* The file exists          */
        !          1348:             *in_pp = tmp;
        !          1349:             /* Else mcpp_main() will diagnose *in_pp and exit   */
        !          1350:     }
        !          1351:     if (! (mcpp_debug & MACRO_CALL)) {
        !          1352:         /* -K option alters behavior of -v option   */
        !          1353:         if (option_flags.v)
        !          1354:             version();
        !          1355:         if (show_path) {
        !          1356:             fp_debug = stderr;
        !          1357:             dump_path();
        !          1358:             fp_debug = stdout;
        !          1359:         }
        !          1360:     }
        !          1361: }
        !          1362:
        !          1363: static void version( void)
        !          1364: /*
        !          1365:  * Print version message.
        !          1366:  */
        !          1367: {
        !          1368:     const char *    mes[] = {
        !          1369:
        !          1370: #if     MCPP_LIB
        !          1371: /* Write messages here, for example, "MySomeTool with ".    */
        !          1372: #endif
        !          1373:
        !          1374: #ifdef  VERSION_MSG
        !          1375:         "MCPP V.2.7.2 (2008/11) "
        !          1376: #else
        !          1377:         "MCPP V.", VERSION, " (", DATE, ") "
        !          1378: #endif
        !          1379: #if     COMPILER == INDEPENDENT
        !          1380:             , "compiler-independent-build "
        !          1381: #else
        !          1382: #ifdef  CMP_NAME
        !          1383:             , "for ", CMP_NAME, " "
        !          1384: #endif
        !          1385: #endif
        !          1386:             , "compiled by "
        !          1387: #ifdef  VERSION_MSG
        !          1388:             , VERSION_MSG
        !          1389: #else
        !          1390: #ifdef  HOST_CMP_NAME
        !          1391:             , HOST_CMP_NAME
        !          1392: #if     HOST_COMPILER == GNUC
        !          1393:             , " V.", GCC_MAJOR_VERSION, ".", GCC_MINOR_VERSION
        !          1394: #endif
        !          1395: #endif
        !          1396: #endif
        !          1397:             , "\n",
        !          1398:             NULL
        !          1399:         };
        !          1400:
        !          1401:     const char **   mpp = mes;
        !          1402:     while (*mpp)
        !          1403:         mcpp_fputs( *mpp++, ERR);
        !          1404: }
        !          1405:
        !          1406: static void usage(
        !          1407:     int     opt
        !          1408: )
        !          1409: /*
        !          1410:  * Print usage.
        !          1411:  */
        !          1412: {
        !          1413:     const char *     mes[] = {
        !          1414:
        !          1415: "Usage:  ",
        !          1416: "mcpp",
        !          1417: " [-<opts> [-<opts>]] [<infile> [-<opts>] [<outfile>] [-<opts>]]\n",
        !          1418: "    <infile> defaults to stdin and <outfile> defaults to stdout.\n",
        !          1419:
        !          1420: "\nCommonly used options:\n",
        !          1421:
        !          1422: "-@MODE      Specify preprocessing mode. MODE should be one of these 4:\n",
        !          1423: "    -@std               Standard conforming mode. (default)\n",
        !          1424: "    -@poststd, -@post   special 'post-Standard' mode.\n",
        !          1425: "    -@kr                K&R 1st mode.\n",
        !          1426: "    -@oldprep, -@old    'old_preprocessor' mode (i.e. 'Reiser model' cpp).\n",
        !          1427:
        !          1428: #if COMPILER == MSC
        !          1429: "-arch:SSE, -arch:SSE2   Define the macro _M_IX86_FP as 1, 2 respectively.\n",
        !          1430: #endif
        !          1431: #if SYSTEM == SYS_MAC && COMPILER == GNUC
        !          1432: "-arch <arch>        Change the target to <arch> (i386, x86_64, ppc, ppc64).\n",
        !          1433: #endif
        !          1434:
        !          1435: #if ! STD_LINE_PREFIX
        !          1436: "-b          Output #line lines in C source style.\n",
        !          1437: #endif
        !          1438:
        !          1439: "-C          Output also comments.\n",
        !          1440: "-D <macro>[=<value>]    Define <macro> as <value> (default:1).\n",
        !          1441: "-D <macro(args)>[=<replace>]    Define <macro(args)> as <replace>.\n",
        !          1442: "-e <encoding>   Change the default multi-byte character encoding to one of:\n",
        !          1443: "            euc_jp, gb2312, ksc5601, big5, sjis, iso2022_jp, utf8.\n",
        !          1444:
        !          1445: #if SYSTEM == SYS_MAC
        !          1446: "-F <framework>      Add <framework> to top of framework directory list.\n",
        !          1447: #endif
        !          1448: #if COMPILER == GNUC
        !          1449: "-finput-charset=<encoding>      Same as -e <encoding>.\n",
        !          1450: "            (Don't insert spaces around '=').\n",
        !          1451: #endif
        !          1452: #if COMPILER == MSC
        !          1453: "-Fl <file>  Include the <file> prior to the main input file.\n",
        !          1454: "-G<n>       Define the macro _M_IX86 according to <n>.\n",
        !          1455: #endif
        !          1456: #if COMPILER == LCC
        !          1457: "-g <n>      Define the macro __LCCDEBUGLEVEL as <n>.\n",
        !          1458: #endif
        !          1459:
        !          1460: "-I <directory>      Add <directory> to the #include search list.\n",
        !          1461:
        !          1462: #if COMPILER == GNUC
        !          1463: "-isysroot <dir>     Change root of system header directory to <dir>.\n",
        !          1464: "-include <file>     Include the <file> prior to the main input file.\n",
        !          1465: #else
        !          1466: "-I-         Unset system or site specific include directories.\n",
        !          1467: #endif
        !          1468: #if COMPILER == MSC
        !          1469: "-J          Define the macro _CHAR_UNSIGNED as 1.\n",
        !          1470: #endif
        !          1471:
        !          1472: "-j          Don't output the source line in diagnostics.\n",
        !          1473: "-M, -MM, -MD, -MMD, -MP, -MQ target, -MT target, -MF file\n",
        !          1474: "            Output source file dependency line for makefile.\n",
        !          1475: #if SYS_FAMILY == SYS_UNIX
        !          1476: "-m32        Change target CPU from x86_64, ppc64 to i386, ppc, respectively.\n",
        !          1477: "-m64        Change target CPU from i386, ppc to x86_64, ppc64, respectively.\n",
        !          1478: #endif
        !          1479: "-N          Don't predefine any non-standard macros.\n",
        !          1480:
        !          1481: #if COMPILER == GNUC
        !          1482: "-nostdinc   Unset system or site specific include directories.\n",
        !          1483: #endif
        !          1484: #if COMPILER == LCC
        !          1485: "-O          Define the macro __LCCOPTIMLEVEL as 1.\n",
        !          1486: #endif
        !          1487:
        !          1488: "-o <file>   Output to <file>.\n",
        !          1489: "-P          Don't output #line lines.\n",
        !          1490: "-Q          Output diagnostics to \"mcpp.err\" (default:stderr).\n",
        !          1491: #if COMPILER == MSC
        !          1492: "-RTC*       Define the macro __MSVC_RUNTIME_CHECKS as 1.\n",
        !          1493: #endif
        !          1494: #if COMPILER == GNUC
        !          1495: "-traditional, -traditional-cpp      Same as -@oldprep.\n",
        !          1496: #endif
        !          1497: "-U <macro>  Undefine <macro>.\n",
        !          1498:
        !          1499: #if COMPILER == GNUC
        !          1500: "-undef      Same as -N.\n",
        !          1501: #endif
        !          1502: #if COMPILER == MSC
        !          1503: "-u          Same as -N.\n",
        !          1504: #endif
        !          1505:
        !          1506: "-v          Show version and include directories of mcpp.\n",
        !          1507: "-W <level>  Set warning level to <level> (OR of {0,1,2,4,8,16}, default:1).\n",
        !          1508:
        !          1509: #if COMPILER == MSC
        !          1510: "-WL         Same as -j.\n",
        !          1511: #endif
        !          1512: #if COMPILER == MSC || COMPILER == GNUC
        !          1513: "-w          Same as -W0.\n",
        !          1514: #endif
        !          1515: #if COMPILER == MSC
        !          1516: "-X          Same as -I-.\n",
        !          1517: "-Zc:wchar_t     Define _NATIVE_WCHAR_T_DEFINED and _WCHAR_T_DEFINED as 1.\n",
        !          1518: "-Zl         Define the macro _VC_NODEFAULTLIB as 1.\n",
        !          1519: #endif
        !          1520:
        !          1521: "-z          Don't output the included file, only defining macros.\n",
        !          1522:
        !          1523: "\nOptions available with -@std (default) or -@poststd options:\n",
        !          1524:
        !          1525: "-+          Process C++ source.\n",
        !          1526:
        !          1527: #if DIGRAPHS_INIT
        !          1528: "-2          Disable digraphs.\n",
        !          1529: #else
        !          1530: "-2          Enable digraphs.\n",
        !          1531: #endif
        !          1532: #if COMPILER == GNUC
        !          1533: "-digraphs   Enable digraphs.\n",
        !          1534: #endif
        !          1535:
        !          1536: "-h <n>      Re-define the pre-defined macro __STDC_HOSTED__ as <n>.\n",
        !          1537:
        !          1538: #if COMPILER == GNUC
        !          1539: "-lang-c89   Same as -S1.\n",
        !          1540: "-lang-c++   Same as -+.\n",
        !          1541: "-pedantic, -pedantic-errors     Same as -W7.\n",
        !          1542: "-S <n>      Redefine __STDC__ to <n>.\n",
        !          1543: #else
        !          1544: "-S <n>      Redefine __STDC__ to <n>, undefine old style macros.\n",
        !          1545: #endif
        !          1546:
        !          1547: #if COMPILER == GNUC
        !          1548: "-std=<STANDARD>     Specify the standard to which the code should conform.\n",
        !          1549: "            <STANDARD> may be one of: c90, c99, iso9899:1990, iso14882, etc.\n",
        !          1550: "            iso9899:<n>, iso14882:<n> : Same as -V <n> (long in decimals).\n",
        !          1551: #endif
        !          1552: #if COMPILER == MSC
        !          1553: "-Tp         Same as -+.\n",
        !          1554: #endif
        !          1555:
        !          1556: "-V <n>      Redefine __STDC_VERSION__ or __cplusplus to <n>.\n",
        !          1557: "            C with -V199901L specifies C99 specs.\n",
        !          1558: "            C++ with -V199901L specifies C99 compatible specs.\n",
        !          1559:
        !          1560: #if COMPILER == GNUC
        !          1561: "-x c++      Same as -+.\n",
        !          1562: #endif
        !          1563:
        !          1564: "\nOptions available with only -@std (default) option:\n",
        !          1565:
        !          1566: "-@compat    Expand recursive macro more than Standard.\n",
        !          1567: #if TRIGRAPHS_INIT
        !          1568: "-3          Disable trigraphs.\n",
        !          1569: #else
        !          1570: "-3          Enable trigraphs.\n",
        !          1571: #endif
        !          1572: "-K          Output macro annotations embedding in comments.\n",
        !          1573: #if COMPILER == GNUC
        !          1574: "-trigraphs  Enable trigraphs.\n",
        !          1575: #endif
        !          1576:
        !          1577: "\nOptions available with -@std (default), -@kr or -@oldprep options:\n",
        !          1578:
        !          1579: #if COMPILER == GNUC
        !          1580: "-lang-asm   Same as -x assembler-with-cpp.\n",
        !          1581: "-x assembler-with-cpp   Process \"assembler\" source.\n",
        !          1582: #elif   COMPILER == MSC
        !          1583: "-A          Process \"assembler\" source.\n",
        !          1584: #else
        !          1585: "-a          Process \"assembler\" source.\n",
        !          1586: #endif
        !          1587:
        !          1588: "-k          Keep white spaces of input lines as they are.\n",
        !          1589:
        !          1590: "\nFor further details see mcpp-manual.html.\n",
        !          1591:         NULL,
        !          1592:     };
        !          1593:
        !          1594:     const char *    illegopt = "Incorrect option -%c%s\n";
        !          1595:     const char * const *    mpp = mes;
        !          1596:
        !          1597:     if (opt != '?')
        !          1598:         mcpp_fprintf( ERR, illegopt, opt, mcpp_optarg ? mcpp_optarg : null);
        !          1599:     version();
        !          1600: #if MCPP_LIB
        !          1601:     mes[ 1] = argv0;
        !          1602: #endif
        !          1603:     while (*mpp)
        !          1604:         mcpp_fputs( *mpp++, ERR);
        !          1605:     longjmp( error_exit, -1);
        !          1606: }
        !          1607:
        !          1608: static void set_opt_list(
        !          1609:     char *  optlist
        !          1610: )
        !          1611: /*
        !          1612:  * Set list of legal option characters.
        !          1613:  */
        !          1614: {
        !          1615:     const char *    list[] = {
        !          1616:
        !          1617: #if ! STD_LINE_PREFIX
        !          1618:     "b",
        !          1619: #endif
        !          1620:
        !          1621: #if SYS_FAMILY == SYS_UNIX
        !          1622:     "m:",
        !          1623: #endif
        !          1624:
        !          1625: #if COMPILER == GNUC
        !          1626:     "$A:a:cd:Ef:g:i:l:r:s:t:u:O:p:q:wx:",
        !          1627: #elif COMPILER == MSC
        !          1628:     "Aa:F:G:JR:T:XZ:uw",
        !          1629: #elif   COMPILER == LCC
        !          1630:     "g:O",
        !          1631: #endif
        !          1632:
        !          1633: #if COMPILER != GNUC && COMPILER != MSC
        !          1634:     "a",
        !          1635: #endif
        !          1636: #if SYSTEM == SYS_MAC
        !          1637:     "F:-:",
        !          1638: #endif
        !          1639:
        !          1640:     NULL
        !          1641:     };
        !          1642:
        !          1643:     const char * const *    lp = & list[ 0];
        !          1644:
        !          1645:     strcpy( optlist, "23+@:e:h:jkn:o:vzCD:I:KM:NPQS:U:V:W:");
        !          1646:                                                 /* Default options  */
        !          1647:     while (*lp)
        !          1648:         strcat( optlist, *lp++);
        !          1649:     if (strlen( optlist) >= OPTLISTLEN)
        !          1650:         cfatal( "Bug: Too long option list", NULL, 0L, NULL);       /* _F_  */
        !          1651: }
        !          1652:
        !          1653: static int  parse_warn_level(
        !          1654:     const char *    mcpp_optarg,
        !          1655:     int     opt
        !          1656: )
        !          1657: /*
        !          1658:  * Parse warn level option.
        !          1659:  * Warning level option is specified as '19' or '1|2|16' or even '3|16'.
        !          1660:  * Even spaces are allowed as ' 1 | 2|16 '.
        !          1661:  */
        !          1662: {
        !          1663:     const char *    cp = mcpp_optarg;
        !          1664:     int             w, i;
        !          1665:
        !          1666:     w = i = 0;
        !          1667:     while( *cp != EOS) {
        !          1668:         while( *cp == ' ')
        !          1669:             cp++;                           /* Skip spaces          */
        !          1670:         if (! isdigit( *cp))
        !          1671:             break;                          /* Error    */
        !          1672:         while (isdigit( *cp)) {
        !          1673:             i *= 10;
        !          1674:             i += (*cp++ - '0');
        !          1675:         }
        !          1676:         while (*cp == ' ')
        !          1677:             cp++;
        !          1678:         if (*cp == '|') {       /* Only digits or '|' are allowed   */
        !          1679:             w |= i;                         /* Take OR of the args  */
        !          1680:             i = 0;
        !          1681:             cp++;
        !          1682:         }
        !          1683:     }
        !          1684:     if (*cp != EOS) {               /* Not ending with digit        */
        !          1685:         mcpp_fprintf( ERR, "Illegal warning level option \"%s\"\n"
        !          1686:                 , mcpp_optarg);
        !          1687:         usage( opt);
        !          1688:     }
        !          1689:     w |= i;                                 /* Take the last arg    */
        !          1690:     return  w;
        !          1691: }
        !          1692:
        !          1693: static void def_a_macro(
        !          1694:     int     opt,                            /* 'D'  */
        !          1695:     char *  def                         /* Argument of -D option    */
        !          1696: )
        !          1697: /*
        !          1698:  * Define a macro specified by -D option.
        !          1699:  * The macro maybe either object-like or function-like (with parameter).
        !          1700:  */
        !          1701: {
        !          1702:     DEFBUF *    defp;
        !          1703:     char *      definition;             /* Argument of -D option    */
        !          1704:     char *      cp;
        !          1705:     int         i;
        !          1706:
        !          1707:     /* Convert trigraphs for the environment which need trigraphs   */
        !          1708:     if (mcpp_mode == STD && option_flags.trig)
        !          1709:         cnv_trigraph( def);
        !          1710:     if (mcpp_mode == POST_STD && option_flags.dig)
        !          1711:         cnv_digraph( def);  /* Convert prior to installing macro    */
        !          1712:     definition = xmalloc( strlen( def) + 4);
        !          1713:     strcpy( definition, def);
        !          1714:     if ((cp = strchr( definition, '=')) != NULL) {
        !          1715:         *cp = ' ';                          /* Remove the '='       */
        !          1716:         cp = "\n";                          /* Append <newline>     */
        !          1717:     } else {
        !          1718:         cp = " 1\n";                        /* With definition "1"  */
        !          1719:     }
        !          1720:     strcat( definition, cp);
        !          1721:     cp = definition;
        !          1722:     while ((char_type[ *cp & UCHARMAX] & SPA) == 0)
        !          1723:         cp++;
        !          1724:     i = *cp;
        !          1725:     *cp = EOS;
        !          1726:     if ((defp = look_id( definition)) != NULL)      /* Pre-defined  */
        !          1727:         undefine( definition);
        !          1728:     *cp = i;
        !          1729:     /* Now, save the definition.    */
        !          1730:     unget_string( definition, NULL);
        !          1731:     if (do_define( FALSE, 0) == NULL)       /* Define a macro       */
        !          1732:         usage( opt);
        !          1733:     *cp = EOS;
        !          1734:     if (str_eq( definition, "__STDC__")) {
        !          1735:         defp = look_id( definition);
        !          1736:         defp->nargs = DEF_NOARGS_STANDARD;
        !          1737:                                 /* Restore Standard-predefinedness  */
        !          1738:     }
        !          1739:     free( definition);
        !          1740:     skip_nl();                      /* Clear the appended <newline> */
        !          1741: }
        !          1742:
        !          1743: static void     chk_opts(
        !          1744:     int     sflag,      /* Flag of Standard or post-Standard mode   */
        !          1745:     int     trad                    /* -traditional (GCC only)      */
        !          1746: )
        !          1747: /*
        !          1748:  * Check consistency between the specified options.
        !          1749:  * Set default value of some variables for each 'mcpp_mode'.
        !          1750:  */
        !          1751: {
        !          1752:     int     incompat = FALSE;
        !          1753:
        !          1754:     switch (mcpp_mode) {
        !          1755:     case STD    :
        !          1756:     case POST_STD   :
        !          1757:         if (trad)
        !          1758:             incompat = TRUE;
        !          1759:         if (! stdc_val)
        !          1760:             stdc_val = STDC;
        !          1761:         break;
        !          1762:     case KR :
        !          1763:     case OLD_PREP   :
        !          1764: #if COMPILER == GNUC
        !          1765:         if (sflag || cplus_val || ansi || std_val != -1L)
        !          1766: #else
        !          1767:         if (sflag || cplus_val || std_val != -1L)
        !          1768: #endif
        !          1769:             incompat = TRUE;
        !          1770:         if (option_flags.dig) {
        !          1771:             if (option_flags.dig != DIGRAPHS_INIT)
        !          1772:                 incompat = TRUE;
        !          1773:             else
        !          1774:                 option_flags.dig = 0;
        !          1775:         }
        !          1776:         break;
        !          1777:     }
        !          1778:
        !          1779:     if (mcpp_mode == POST_STD
        !          1780:             && (option_flags.lang_asm || compat_mode || option_flags.k))
        !          1781:         incompat = TRUE;
        !          1782:     if (mcpp_mode != STD && option_flags.trig) {
        !          1783:         if (option_flags.trig != TRIGRAPHS_INIT)
        !          1784:             incompat = TRUE;
        !          1785:         else
        !          1786:             option_flags.trig = FALSE;
        !          1787:     }
        !          1788:     if (mcpp_mode != STD && (mcpp_debug & MACRO_CALL))
        !          1789:         incompat = TRUE;
        !          1790:     if ((mcpp_debug & MACRO_CALL)
        !          1791:                 && (option_flags.lang_asm || option_flags.c)) {
        !          1792:             mcpp_fputs( "Disabled -K option.\n", ERR);
        !          1793:             mcpp_debug &= ~MACRO_CALL;
        !          1794:             /* -a and -C options do not co-exist with -K    */
        !          1795:     }
        !          1796:     if (incompat) {
        !          1797:         mcpp_fputs( "Incompatible options are specified.\n", ERR);
        !          1798:         usage( '?');
        !          1799:     }
        !          1800:
        !          1801:     standard = (mcpp_mode == STD || mcpp_mode == POST_STD);
        !          1802:     /* Modify magic characters in character type table. */
        !          1803:     if (! standard)
        !          1804:         char_type[ DEF_MAGIC] = 0;
        !          1805:     if (mcpp_mode != STD)
        !          1806:         char_type[ IN_SRC] = 0;
        !          1807:     if (mcpp_mode == POST_STD || mcpp_mode == KR)
        !          1808:         char_type[ TOK_SEP] = 0;    /* TOK_SEP equals to COM_SEP    */
        !          1809:     if (mcpp_mode != STD)
        !          1810:         char_type[ MAC_INF] = 0;
        !          1811:
        !          1812:     expand_init( compat_mode, ansi);
        !          1813:                 /* Set function pointer to macro expansion routine  */
        !          1814: }
        !          1815:
        !          1816: #if COMPILER != GNUC
        !          1817:
        !          1818: static void init_cpu_macro (
        !          1819:     int     gval,               /* Argument of -G option for MSC    */
        !          1820:     int     sse                 /* Argument of -sse: option for MSC */
        !          1821: )
        !          1822: /*
        !          1823:  * Set predefined macros for CPU.
        !          1824:  * This routine is called from do_options() only once.
        !          1825:  * GCC-specific-build defines these macro by init_gcc_macro().
        !          1826:  */
        !          1827: {
        !          1828:     const char *    cpu_macro[][ 7] = {
        !          1829: #if SYS_FAMILY == SYS_UNIX
        !          1830:             { "__i386__"
        !          1831: #if SYSTEM == SYS_CYGWIN
        !          1832:                 , "_X86_"
        !          1833: #endif
        !          1834:                 , NULL,},
        !          1835:             { "__x86_64__", "__amd64__", NULL,},
        !          1836:             { "__ppc__", "__powerpc__", NULL,},
        !          1837:             { "__ppc64__", "__powerpc64__", NULL,}
        !          1838: #elif   SYS_FAMILY == SYS_WIN
        !          1839:             { "_WIN32", "__WIN32__", "_X86_"
        !          1840: #if SYSTEM == SYS_MINGW
        !          1841:                 , "__i386__"
        !          1842: #endif
        !          1843:                 , NULL,},
        !          1844:             { "_WIN32", "_WIN64", "__WIN64__", "_M_AMD64", "_AMD64_", "_X64_"
        !          1845:                 , NULL,},       /* "_WIN32" is defined even on Windows 64   */
        !          1846:             { NULL,},                               /* Not supported  */
        !          1847:             { NULL,}                                /* Not supported  */
        !          1848: #endif
        !          1849:         };
        !          1850:     const char **   macro;
        !          1851:     int             index;
        !          1852:
        !          1853:     if (str_eq( arch, "i386"))
        !          1854:         index = 0;
        !          1855:     else if (str_eq( arch, "x86_64"))
        !          1856:         index = 1;
        !          1857:     else if (str_eq( arch, "ppc"))
        !          1858:         index = 2;
        !          1859:     else if (str_eq( arch, "ppc64"))
        !          1860:         index = 3;
        !          1861:     else
        !          1862:         index = 9;
        !          1863:
        !          1864:     if (index == 9) {                               /* Unknown CPU  */
        !          1865:         look_and_install( "__" CPU "__", DEF_NOARGS_PREDEF, null, "1");
        !          1866:         return;
        !          1867:     }
        !          1868:     macro = cpu_macro[ index];
        !          1869:     while (*macro)
        !          1870:         look_and_install( *macro++, DEF_NOARGS_PREDEF, null, "1");
        !          1871: #if SYS_FAMILY == SYS_WIN
        !          1872:     if (index == 0) {
        !          1873:         char    val[] = "600";
        !          1874:         if (gval)
        !          1875:             val[ 0] = gval;
        !          1876:         look_and_install( "_M_IX86", DEF_NOARGS_PREDEF, null, val);
        !          1877:         val[ 0] = '0' + sse;
        !          1878:         val[ 1] = '\0';
        !          1879:         look_and_install( "_M_IX86_FP", DEF_NOARGS_PREDEF, null, val);
        !          1880:     }
        !          1881: #endif
        !          1882: }
        !          1883: #endif  /* COMPILER != GNUC */
        !          1884:
        !          1885: static void init_predefines( void)
        !          1886: /*
        !          1887:  * Set or unset predefined macros.
        !          1888:  */
        !          1889: {
        !          1890:     char    tmp[ 16];
        !          1891:
        !          1892:     if (std_val != -1L) {               /* Version is specified     */
        !          1893:         if (cplus_val)
        !          1894:             cplus_val = std_val;        /* Value of __cplusplus     */
        !          1895:         else
        !          1896:             stdc_ver = std_val;     /* Value of __STDC_VERSION__    */
        !          1897:     } else {
        !          1898:         if (! cplus_val)
        !          1899:             stdc_ver = stdc_val ? STDC_VERSION : 0L;
        !          1900:     }
        !          1901:
        !          1902:     if (nflag) {
        !          1903:         un_predefine( TRUE);
        !          1904:     } else if (stdc_val || cplus_val) {
        !          1905: #if COMPILER != GNUC
        !          1906:         un_predefine( FALSE);           /* Undefine "unix" or so    */
        !          1907: #endif
        !          1908:     }
        !          1909:     sprintf( tmp, "%ldL", cplus_val ? cplus_val : stdc_ver);
        !          1910:     if (cplus_val) {
        !          1911:         look_and_install( "__cplusplus", DEF_NOARGS_STANDARD, null, tmp);
        !          1912:     } else {
        !          1913:         if (stdc_ver)
        !          1914:             look_and_install( "__STDC_VERSION__", DEF_NOARGS_STANDARD, null
        !          1915:                     , tmp);
        !          1916: #ifdef  COMPILER_CPLUS
        !          1917:         if (! nflag)        /* Undefine pre-defined macro for C++   */
        !          1918:             undefine( COMPILER_CPLUS);
        !          1919: #endif
        !          1920:     }
        !          1921:     set_limit();
        !          1922:     stdc2 = cplus_val || stdc_ver >= 199901L;
        !          1923:     stdc3 = (cplus_val >= 199901L) || (stdc_ver >= 199901L);
        !          1924:         /* (cplus_val >= 199901L) makes C++ C99-compatible specs    */
        !          1925:     if (standard)
        !          1926:         init_std_defines();
        !          1927:     if (stdc3)
        !          1928:         set_pragma_op();
        !          1929: }
        !          1930:
        !          1931: static void init_std_defines( void)
        !          1932: /*
        !          1933:  * For STD and POST_STD modes.
        !          1934:  * The magic pre-defines are initialized with magic argument counts.
        !          1935:  * expand_macro() notices this and calls the appropriate routine.
        !          1936:  * DEF_NOARGS is one greater than the first "magic" definition.
        !          1937:  * 'DEF_NOARGS - n' are reserved for pre-defined macros.
        !          1938:  * __STDC_VERSION__ and __cplusplus are defined by chk_opts() and set_cplus().
        !          1939:  */
        !          1940: {
        !          1941:     char    tmp[ 16];
        !          1942:     char    timestr[ 14];
        !          1943:     time_t  tvec;
        !          1944:     char *  tstring;
        !          1945:
        !          1946:     look_and_install( "__LINE__", DEF_NOARGS_DYNAMIC - 1, null, "-1234567890");
        !          1947:     /* Room for 11 chars (10 for long and 1 for '-' in case of wrap round.  */
        !          1948:     look_and_install( "__FILE__", DEF_NOARGS_DYNAMIC - 2, null, null);
        !          1949:                                             /* Should be stuffed    */
        !          1950:
        !          1951:     /* Define __DATE__, __TIME__ as present date and time.          */
        !          1952:     time( &tvec);
        !          1953:     tstring = ctime( &tvec);
        !          1954:     sprintf( timestr, "\"%.3s %c%c %.4s\"",
        !          1955:         tstring + 4,
        !          1956:         *(tstring + 8) == '0' ? ' ' : *(tstring + 8),
        !          1957:         *(tstring + 9),
        !          1958:         tstring + 20);
        !          1959:     look_and_install( "__DATE__", DEF_NOARGS_DYNAMIC, null, timestr);
        !          1960:     sprintf( timestr, "\"%.8s\"", tstring + 11);
        !          1961:     look_and_install( "__TIME__", DEF_NOARGS_DYNAMIC, null, timestr);
        !          1962:
        !          1963:     if (! look_id( "__STDC_HOSTED__")) {
        !          1964:         /*
        !          1965:          * Some compilers, e.g. GCC older than 3.3, define this macro by
        !          1966:          * -D option.
        !          1967:          */
        !          1968:         sprintf( tmp, "%d", STDC_HOSTED);
        !          1969:         look_and_install( "__STDC_HOSTED__", DEF_NOARGS_PREDEF, null, tmp);
        !          1970:     }
        !          1971: #if COMPILER != GNUC        /* GCC do not undefine __STDC__ on C++  */
        !          1972:     if (cplus_val)
        !          1973:         return;
        !          1974: #endif
        !          1975:     /* Define __STDC__ as 1 or such for Standard conforming compiler.   */
        !          1976:     if (! look_id( "__STDC__")) {
        !          1977:         sprintf( tmp, "%d", stdc_val);
        !          1978:         look_and_install( "__STDC__", DEF_NOARGS_STANDARD, null, tmp);
        !          1979:     }
        !          1980: }
        !          1981:
        !          1982: #define LINE90LIMIT         32767
        !          1983: #define LINE_CPLUS_LIMIT    32767
        !          1984:
        !          1985: static void set_limit( void)
        !          1986: /*
        !          1987:  * Set the minimum translation limits specified by the Standards.
        !          1988:  */
        !          1989: {
        !          1990:     if (cplus_val) {            /* Specified by C++ 1998 Standard   */
        !          1991:         std_limits.str_len = SLEN_CPLUS_MIN;
        !          1992:         std_limits.id_len = IDLEN_CPLUS_MIN;
        !          1993:         std_limits.n_mac_pars = NMACPARS_CPLUS_MIN;
        !          1994:         std_limits.exp_nest = EXP_NEST_CPLUS_MIN;
        !          1995:         std_limits.blk_nest = BLK_NEST_CPLUS_MIN;
        !          1996:         std_limits.inc_nest = INCLUDE_NEST_CPLUS_MIN;
        !          1997:         std_limits.n_macro = NMACRO_CPLUS_MIN;
        !          1998:         std_limits.line_num = LINE_CPLUS_LIMIT;
        !          1999:     } else if (stdc_ver >= 199901L) {       /* Specified by C 1999 Standard */
        !          2000:         std_limits.str_len = SLEN99MIN;
        !          2001:         std_limits.id_len = IDLEN99MIN;
        !          2002:         std_limits.n_mac_pars = NMACPARS99MIN;
        !          2003:         std_limits.exp_nest = EXP_NEST99MIN;
        !          2004:         std_limits.blk_nest = BLK_NEST99MIN;
        !          2005:         std_limits.inc_nest = INCLUDE_NEST99MIN;
        !          2006:         std_limits.n_macro = NMACRO99MIN;
        !          2007:         std_limits.line_num = LINE99LIMIT;
        !          2008:     } else if (standard) {          /* Specified by C 1990 Standard */
        !          2009:         std_limits.str_len = SLEN90MIN;
        !          2010:         std_limits.id_len = IDLEN90MIN;
        !          2011:         std_limits.n_mac_pars = NMACPARS90MIN;
        !          2012:         std_limits.exp_nest = EXP_NEST90MIN;
        !          2013:         std_limits.blk_nest = BLK_NEST90MIN;
        !          2014:         std_limits.inc_nest = INCLUDE_NEST90MIN;
        !          2015:         std_limits.n_macro = NMACRO90MIN;
        !          2016:         std_limits.line_num = LINE90LIMIT;
        !          2017:     }
        !          2018:     /* Else pre-Standard mode   */
        !          2019: }
        !          2020:
        !          2021: static void set_pragma_op( void)
        !          2022: /*
        !          2023:  *      #define _Pragma(a)  _Pragma ( a )
        !          2024:  * Define _Pragma() operator as a special macro so as to be searched
        !          2025:  * easily.  The unusual 'DEF_PRAGMA' is a marker of this psuedo
        !          2026:  * macro.
        !          2027:  */
        !          2028: {
        !          2029:     char *  name = "_Pragma";
        !          2030:     char    tmp[ 16];
        !          2031:
        !          2032:     sprintf( tmp, "%c%s ( %c%c )", DEF_MAGIC, name, MAC_PARM, 1);
        !          2033:                                                 /* Replacement text */
        !          2034:     look_and_install( name, DEF_PRAGMA, "a", tmp);
        !          2035: }
        !          2036:
        !          2037: void    init_sys_macro( void)
        !          2038: /*
        !          2039:  * Define system-specific macros and some Standard required macros
        !          2040:  * and undefine macros specified by -U options.
        !          2041:  */
        !          2042: {
        !          2043:     /* This order is important. */
        !          2044:     def_macros();               /* Define macros specified by -D    */
        !          2045: #if COMPILER == GNUC
        !          2046:     chk_env();
        !          2047: #endif
        !          2048:     init_predefines();                  /* Define predefined macros */
        !          2049: #if COMPILER == GNUC
        !          2050:     init_gcc_macro();
        !          2051: #elif   COMPILER == MSC
        !          2052:     init_msc_macro();
        !          2053: #endif
        !          2054:     undef_macros();             /* Undefine macros specified by -U  */
        !          2055:     if (mcpp_debug & MACRO_CALL)
        !          2056:         dump_def( FALSE, TRUE);     /* Finally putout current macro names   */
        !          2057: }
        !          2058:
        !          2059: void    at_start( void)
        !          2060: /*
        !          2061:  * Do the commands prior to processing main source file after do_options().
        !          2062:  */
        !          2063: {
        !          2064:     char *  env;
        !          2065:     FILEINFO *      file_saved = infile;
        !          2066:
        !          2067:     /*
        !          2068:      * Set multi-byte character encoding according to environment variables
        !          2069:      * LC_ALL, LC_CTYPE and LANG -- with preference in this order.
        !          2070:      */
        !          2071:     if (! mb_changed) {                     /* -m option precedes   */
        !          2072:         if ((env = getenv( "LC_ALL")) != NULL)
        !          2073:             set_encoding( env, "LC_ALL", 0);
        !          2074:         else if ((env = getenv( "LC_CTYPE")) != NULL)
        !          2075:             set_encoding( env, "LC_CTYPE", 0);
        !          2076:         else if ((env = getenv( "LANG")) != NULL)
        !          2077:             set_encoding( env, "LANG", 0);
        !          2078:     }
        !          2079:
        !          2080: #if COMPILER == GNUC || COMPILER == MSC
        !          2081:     if (option_flags.dollar_in_name)
        !          2082:         char_type[ 0x24] |= LET;    /* Enable '$' in identifiers    */
        !          2083:     /*
        !          2084:      * Do the -include (-Fl for MSC) options in the specified order.
        !          2085:      * Note: This functionality is implemented as nested #includes
        !          2086:      *   which results the same effect as sequential #includes.
        !          2087:      */
        !          2088:     {
        !          2089:         char **         preinc;
        !          2090:         /*
        !          2091:          * Note: Here, 'infile' is the main input file, which is pseudo-
        !          2092:          * parent file of the files to pre-include.  So, we must
        !          2093:          * temporarily set the infile's directory to the current directory
        !          2094:          * in order to preinclude the files relative to it.
        !          2095:          */
        !          2096:         preinc = preinc_end;
        !          2097:         while (preinclude <= --preinc && *preinc != NULL)
        !          2098:             open_file( &null, NULL, *preinc, TRUE, TRUE, FALSE);
        !          2099:     }
        !          2100: #endif
        !          2101:
        !          2102:     put_info( file_saved);
        !          2103: }
        !          2104:
        !          2105: static void put_info(
        !          2106:     FILEINFO *  sharp_file
        !          2107: )
        !          2108: /*
        !          2109:  * Putout compiler-specific information.
        !          2110:  */
        !          2111: {
        !          2112:     if (no_output || option_flags.p)
        !          2113:         return;
        !          2114:     sharp_file->line++;
        !          2115:     sharp( sharp_file, 0);
        !          2116:     sharp_file->line--;
        !          2117: #if COMPILER == GNUC
        !          2118:     if (gcc_work_dir)
        !          2119:         mcpp_fprintf( OUT, "%s%ld \"%s%c\"\n"
        !          2120:                 , std_line_prefix ? "#line " : LINE_PREFIX
        !          2121:                 , 1, cur_work_dir, '/');
        !          2122:         /* Putout the current directory as a #line line as: */
        !          2123:         /* '# 1 "/abs-path/cur_dir//"'.                     */
        !          2124:     mcpp_fprintf( OUT, "%s%ld \"<built-in>\"\n"
        !          2125:                 , std_line_prefix ? "#line " : LINE_PREFIX , 1);
        !          2126:     mcpp_fprintf( OUT, "%s%ld \"<command line>\"\n"
        !          2127:                 , std_line_prefix ? "#line " : LINE_PREFIX , 1);
        !          2128:     mcpp_fprintf( OUT, "%s%ld \"%s\"%s\n"
        !          2129:             , std_line_prefix ? "#line " : LINE_PREFIX, 1, cur_fullname
        !          2130:             , ! str_eq( cur_fullname, sharp_file->full_fname) ? " 1" : null);
        !          2131:             /* Suffix " 1" for the file specified by -include   */
        !          2132: #endif
        !          2133: }
        !          2134:
        !          2135: static char *   set_files(
        !          2136:     int     argc,
        !          2137:     char ** argv,
        !          2138:     char ** in_pp,
        !          2139:     char ** out_pp
        !          2140: )
        !          2141: /*
        !          2142:  * Set input and/or output files.
        !          2143:  */
        !          2144: {
        !          2145:     char *      cp;
        !          2146:
        !          2147:     if (*in_pp == NULL) {                           /* Input file   */
        !          2148:         cp = argv[ mcpp_optind++];
        !          2149: #if SYS_FAMILY == SYS_WIN
        !          2150:         cp = bsl2sl( cp);
        !          2151: #endif
        !          2152:         *in_pp = cp;
        !          2153:     }
        !          2154:     if (mcpp_optind < argc && argv[ mcpp_optind][ 0] != '-'
        !          2155:             && *out_pp == NULL) {
        !          2156:         cp = argv[ mcpp_optind++];
        !          2157: #if SYS_FAMILY == SYS_WIN
        !          2158:         cp = bsl2sl( cp);
        !          2159: #endif
        !          2160:         *out_pp = cp;                               /* Output file  */
        !          2161:     }
        !          2162:     if (mcpp_optind >= argc)
        !          2163:         return  NULL;           /* Exhausted command line arguments */
        !          2164:     if (argv[ mcpp_optind][ 0] == '-')
        !          2165:         return  argv[ mcpp_optind];                 /* More options */
        !          2166:     cfatal( "Excessive file argument \"%s\"", argv[ mcpp_optind], 0L , NULL);
        !          2167:     return  NULL;
        !          2168: }
        !          2169:
        !          2170: static void set_env_dirs( void)
        !          2171: /*
        !          2172:  * Add to include path those specified by environment variables.
        !          2173:  */
        !          2174: {
        !          2175:     const char *    env;
        !          2176:
        !          2177:     if (cplus_val) {
        !          2178:         if ((env = getenv( ENV_CPLUS_INCLUDE_DIR)) != NULL)
        !          2179:             parse_env( env);
        !          2180:     }
        !          2181:     if ((env = getenv( ENV_C_INCLUDE_DIR)) != NULL)
        !          2182:         parse_env( env);
        !          2183: }
        !          2184:
        !          2185: static void parse_env(
        !          2186:     const char *    env
        !          2187: )
        !          2188: /*
        !          2189:  * Parse environmental variable and append the path to include-dir-list.
        !          2190:  */
        !          2191: {
        !          2192:     char *  save;
        !          2193:     char *  save_start;
        !          2194:     char *  p;
        !          2195:     int     sep;
        !          2196:
        !          2197:     save = save_start = save_string( env);
        !          2198:     while (*save) {
        !          2199:         p = save;
        !          2200:         while (*p && *p != ENV_SEP)
        !          2201:             p++;
        !          2202:         if (p != save)  {                   /* Variable separator   */
        !          2203:             sep = *p;
        !          2204:             *p = EOS;
        !          2205:             set_a_dir( save);
        !          2206:             if (sep == EOS)
        !          2207:                 break;
        !          2208:             save = ++p;
        !          2209:         }
        !          2210:         while (*save == ENV_SEP)
        !          2211:             ++save;
        !          2212:     }
        !          2213:     free( save_start);
        !          2214: }
        !          2215:
        !          2216: static void set_sys_dirs(
        !          2217:     int     set_cplus_dir       /* Set C++ include-directory too    */
        !          2218: )
        !          2219: /*
        !          2220:  * Set site-specific and system-specific directories to the include directory
        !          2221:  * list.
        !          2222:  */
        !          2223: {
        !          2224:     if (cplus_val && set_cplus_dir) {
        !          2225: #ifdef  CPLUS_INCLUDE_DIR1
        !          2226:         set_a_dir( CPLUS_INCLUDE_DIR1);
        !          2227: #endif
        !          2228: #ifdef  CPLUS_INCLUDE_DIR2
        !          2229:         set_a_dir( CPLUS_INCLUDE_DIR2);
        !          2230: #endif
        !          2231: #ifdef  CPLUS_INCLUDE_DIR3
        !          2232:         set_a_dir( CPLUS_INCLUDE_DIR3);
        !          2233: #endif
        !          2234: #ifdef  CPLUS_INCLUDE_DIR4
        !          2235:         set_a_dir( CPLUS_INCLUDE_DIR4);
        !          2236: #endif
        !          2237:     }
        !          2238:
        !          2239: #if SYS_FAMILY == SYS_UNIX
        !          2240:     set_a_dir( "/usr/local/include");
        !          2241: #endif
        !          2242:
        !          2243: #ifdef  C_INCLUDE_DIR1
        !          2244:     set_a_dir( C_INCLUDE_DIR1);
        !          2245: #endif
        !          2246: #ifdef  C_INCLUDE_DIR2
        !          2247:     set_a_dir( C_INCLUDE_DIR2);
        !          2248: #endif
        !          2249:
        !          2250: #if SYS_FAMILY == SYS_UNIX
        !          2251: #if SYSTEM == SYS_CYGWIN
        !          2252:     if (no_cygwin)                          /* -mno-cygwin          */
        !          2253:         set_a_dir( "/usr/include/mingw");
        !          2254:     else
        !          2255:         set_a_dir( "/usr/include");
        !          2256: #else
        !          2257:     set_a_dir( "/usr/include"); /* Should be placed after C_INCLUDE_DIR?    */
        !          2258: #endif
        !          2259: #endif
        !          2260: }
        !          2261:
        !          2262: static void set_a_dir(
        !          2263:     const char *    dirname                 /* The path-name        */
        !          2264: )
        !          2265: /*
        !          2266:  * Append an include directory.
        !          2267:  * This routine is called from the following routines (in this order).
        !          2268:  * 1. do_options() by -I option.
        !          2269:  * 2. do_options() by -isystem option (for GNUC).
        !          2270:  * 3. set_env_dirs() by environment variables.
        !          2271:  * 4. set_sys_dirs() by CPLUS_INCLUDE_DIR?, C_INCLUDE_DIR? and system-
        !          2272:  *    specifics (unless -I- or -nostdinc option is specified).
        !          2273:  * Ignore non-existent directory.
        !          2274:  * Note that this routine should be called only in initializing steps,
        !          2275:  *      because increase of include dirs causes reallocation of incdir[].
        !          2276:  * Note: a trailing PATH-DELIM is appended by norm_path().
        !          2277:  */
        !          2278: {
        !          2279:     char *  norm_name;
        !          2280:     const char **   ip;
        !          2281:
        !          2282:     if (incdir == NULL) {               /* Should be initialized    */
        !          2283:         max_inc = INIT_NUM_INCLUDE;
        !          2284:         incdir = (const char **) xmalloc( sizeof (char *) * max_inc);
        !          2285:         incend = &incdir[ 0];
        !          2286:     } else if (incend - incdir >= max_inc) {        /* Buffer full  */
        !          2287: #if SYSTEM == SYS_MAC
        !          2288:         size_t  framework_pos = to_search_framework - incdir;
        !          2289: #endif
        !          2290: #if COMPILER == GNUC
        !          2291:         size_t  sys_pos = 0;
        !          2292:         if (sys_dirp)
        !          2293:             sys_pos = sys_dirp - incdir;
        !          2294: #endif
        !          2295:         incdir = (const char **) xrealloc( (void *) incdir
        !          2296:                 , sizeof (char *) * max_inc * 2);
        !          2297:         incend = &incdir[ max_inc];
        !          2298: #if COMPILER == GNUC
        !          2299:         if (sys_pos)
        !          2300:             sys_dirp = &incdir[ sys_pos];
        !          2301: #endif
        !          2302: #if SYSTEM == SYS_MAC
        !          2303:         to_search_framework = &incdir[ framework_pos];
        !          2304: #endif
        !          2305:         max_inc *= 2;
        !          2306:     }
        !          2307:
        !          2308:     if (dirname == NULL)
        !          2309:         return;                     /* Only to initialize incdir[]  */
        !          2310:     norm_name = norm_dir( dirname, FALSE);
        !          2311:     if (! norm_name)                        /* Non-existent         */
        !          2312:         return;
        !          2313:     for (ip = incdir; ip < incend; ip++) {
        !          2314:         if (str_case_eq( *ip, norm_name)) {
        !          2315:             if (option_flags.v && ! (mcpp_debug & MACRO_CALL))
        !          2316:                 mcpp_fprintf( ERR, "Duplicate directory \"%s\" is ignored\n"
        !          2317:                         , norm_name);
        !          2318:             free( norm_name);               /* Already registered   */
        !          2319:             return;
        !          2320:         }
        !          2321:     }
        !          2322:     /* Register new directory   */
        !          2323:     *incend++ = norm_name;
        !          2324: }
        !          2325:
        !          2326: #if SYSTEM == SYS_MAC && COMPILER == GNUC
        !          2327: /* Definitions for "header map" file of Xcode / Apple-GCC.          */
        !          2328: /* These definitions were taken from cpplib.h of Apple-GCC-4.0.1    */
        !          2329:
        !          2330: #define HMAP_SAME_ENDIANNESS_MAGIC      \
        !          2331:         (((((('h' << 8) | 'm') << 8) | 'a') << 8) | 'p')
        !          2332:
        !          2333: typedef unsigned short  uint16;
        !          2334: typedef unsigned int    uint32;
        !          2335:
        !          2336: struct hmap_bucket
        !          2337: {
        !          2338:     uint32  key;            /* Offset (into strings) of key             */
        !          2339:     struct {
        !          2340:         uint32  prefix;     /* Offset (into strings) of value prefix    */
        !          2341:         uint32  suffix;     /* Offset (into strings) of value suffix    */
        !          2342:     } value;                /* Value (prefix- and suffix-strings)       */
        !          2343: };
        !          2344:
        !          2345: struct hmap_header_map
        !          2346: {
        !          2347:     uint32  magic;          /* Magic word, also indicates byte order    */
        !          2348:     uint16  version;        /* Version number -- currently 1            */
        !          2349:     uint16  _reserved;      /* Reserved for future use -- zero for now  */
        !          2350:     uint32  strings_offset; /* Offset to start of string pool           */
        !          2351:     uint32  count;          /* Number of entries in the string table    */
        !          2352:     uint32  capacity;       /* Number of buckets (always a power of 2)  */
        !          2353:     uint32  max_value_length;
        !          2354:                         /* Length of longest result path (excl. '\0')   */
        !          2355:     struct hmap_bucket  buckets[1];
        !          2356:                         /* Inline array of 'capacity' maptable buckets  */
        !          2357:     /* Strings follow the buckets, at strings_offset.  */
        !          2358: };
        !          2359: #endif
        !          2360:
        !          2361: static char *   norm_dir(
        !          2362:     const char *    dirname,        /* Directory path to normalize  */
        !          2363:     int             framework       /* Setting a framework directory*/
        !          2364: )
        !          2365: /*
        !          2366:  * Normalize include directory path.
        !          2367:  * Handle -isysroot option for GCC, including framework directory for SYS_MAC.
        !          2368:  */
        !          2369: {
        !          2370:     char *  norm_name;
        !          2371:
        !          2372: #if COMPILER == GNUC
        !          2373:     if (sysroot && sys_dirp) {
        !          2374:         /* Logical system root specified and dirname is system header dir   */
        !          2375:         char    delim[ 2] = { EOS, EOS};
        !          2376:         char *  dir;
        !          2377: #if SYSTEM == SYS_MAC
        !          2378:         if (! framework && memcmp( dirname, "/usr/", 5) != 0)
        !          2379:             return  NULL;           /* /Developer/usr/lib/gcc/      */
        !          2380: #endif
        !          2381:         if (dirname[ 0] != PATH_DELIM)
        !          2382:             delim[ 0] = PATH_DELIM;
        !          2383:         dir = xmalloc( strlen( sysroot) + strlen( dirname) + 2);
        !          2384:         sprintf( dir, "%s%s%s", sysroot, delim, dirname);
        !          2385:         dirname = dir;
        !          2386:     }
        !          2387: #endif
        !          2388: #if SYSTEM == SYS_MAC && COMPILER == GNUC
        !          2389:     if (strlen( dirname) > 5
        !          2390:             && str_case_eq( dirname + strlen( dirname) - 5, ".hmap")) {
        !          2391:         /* "header map" file (not an include directory) */
        !          2392:         norm_name = norm_path( null, dirname, FALSE, TRUE);
        !          2393:         if (! norm_name && option_flags.v)
        !          2394:             mcpp_fprintf( ERR, "Invalid header map file \"%s\" is ignored\n"
        !          2395:                     , dirname);
        !          2396:     } else
        !          2397: #endif
        !          2398:     {
        !          2399:         norm_name = norm_path( dirname, NULL, FALSE, FALSE);
        !          2400:                             /* Normalize the pathname to compare    */
        !          2401:         if (! norm_name && option_flags.v && ! (mcpp_debug & MACRO_CALL))
        !          2402:             mcpp_fprintf( ERR, "Non-existent directory \"%s\" is ignored\n"
        !          2403:                     , dirname);
        !          2404:     }
        !          2405: #if COMPILER == GNUC
        !          2406:     if (sysroot && sys_dirp)
        !          2407:         free( dirname);
        !          2408: #endif
        !          2409:
        !          2410:     return  norm_name;
        !          2411: }
        !          2412:
        !          2413: static char *   norm_path(
        !          2414:     const char *    dir,        /* Include directory (maybe "", never NULL) */
        !          2415:     const char *    fname,
        !          2416:         /* Filename (possibly has directory part, or maybe NULL)    */
        !          2417:     int     inf,    /* If TRUE, output some infs when (mcpp_debug & PATH)   */
        !          2418:     int     hmap            /* "header map" file of Apple-GCC       */
        !          2419: )
        !          2420: /*
        !          2421:  * Normalize the pathname removing redundant components such as
        !          2422:  * "foo/../", "./" and trailing "/.".
        !          2423:  * Append trailing "/" if 'fname' is NULL.
        !          2424:  * Change relative path to absolute path.
        !          2425:  * Dereference a symbolic linked file (or directory) to a real directory/file.
        !          2426:  * Return a malloc'ed buffer, if the directory/file exists.
        !          2427:  * Return NULL, if the specified directory/file does not exist or 'dir' is
        !          2428:  * not a directory or 'fname' is not a regular file.
        !          2429:  * This routine is called from set_a_dir(), init_gcc_macro(), do_once() and
        !          2430:  * open_file().
        !          2431:  */
        !          2432: {
        !          2433:     char *  norm_name;                  /* The path-list converted  */
        !          2434:     char *  start;
        !          2435:     char *  cp1;
        !          2436:     char *  cp2;
        !          2437:     char *  abs_path;
        !          2438:     int     len;                            /* Should not be size_t */
        !          2439:     size_t  start_pos = 0;
        !          2440:     char    slbuf1[ PATHMAX+1];             /* Working buffer       */
        !          2441: #if SYS_FAMILY == SYS_UNIX
        !          2442:     char    slbuf2[ PATHMAX+1]; /* Working buffer for dereferencing */
        !          2443: #endif
        !          2444: #if SYSTEM == SYS_CYGWIN || SYSTEM == SYS_MINGW
        !          2445:     static char *   root_dir;
        !          2446:                 /* System's root directory in Windows file system   */
        !          2447:     static size_t   root_dir_len;
        !          2448: #if SYSTEM == SYS_CYGWIN
        !          2449:     static char *   cygdrive = "/cygdrive/";    /* Prefix for drive letter  */
        !          2450: #else
        !          2451:     static char *   mingw_dir;          /* "/mingw" dir in Windows  */
        !          2452:     static size_t   mingw_dir_len;
        !          2453: #endif
        !          2454: #endif
        !          2455: #if HOST_COMPILER == MSC
        !          2456:     struct _stat    st_buf;
        !          2457: #else
        !          2458:     struct stat     st_buf;
        !          2459: #endif
        !          2460:
        !          2461:     if (! dir || (*dir && is_full_path( fname)))
        !          2462:         cfatal( "Bug: Wrong argument to norm_path()"        /* _F_  */
        !          2463:                 , NULL, 0L, NULL);
        !          2464:     inf = inf && (mcpp_debug & PATH);       /* Output information   */
        !          2465:
        !          2466:     strcpy( slbuf1, dir);                   /* Include directory    */
        !          2467:     len = strlen( slbuf1);
        !          2468:     if (fname && len && slbuf1[ len - 1] != PATH_DELIM) {
        !          2469:         slbuf1[ len] = PATH_DELIM;          /* Append PATH_DELIM    */
        !          2470:         slbuf1[ ++len] = EOS;
        !          2471:     } else if (! fname && len && slbuf1[ len - 1] == PATH_DELIM) {
        !          2472:         /* stat() of some systems do not like trailing '/'  */
        !          2473:         slbuf1[ --len] = EOS;
        !          2474:     }
        !          2475:     if (fname)
        !          2476:         strcat( slbuf1, fname);
        !          2477:     if (stat( slbuf1, & st_buf) != 0        /* Non-existent         */
        !          2478:             || (! fname && ! S_ISDIR( st_buf.st_mode))
        !          2479:                 /* Not a directory though 'fname' is not specified  */
        !          2480:             || (fname && ! S_ISREG( st_buf.st_mode)))
        !          2481:                 /* Not a regular file though 'fname' is specified   */
        !          2482:         return  NULL;
        !          2483: #if SYSTEM == SYS_MAC && COMPILER == GNUC
        !          2484:     if (hmap) {                         /* Dirty "header map" file  */
        !          2485:         struct hmap_header_map  hmap;
        !          2486:         size_t      cnt;
        !          2487:         FILE *      fp;
        !          2488:         fp = fopen( fname, "r");
        !          2489:         cnt = fread( & hmap, sizeof (struct hmap_header_map), 1, fp);
        !          2490:         fclose( fp);
        !          2491:         if (cnt == 0 || hmap.magic != HMAP_SAME_ENDIANNESS_MAGIC)
        !          2492:             return  NULL;
        !          2493:     }
        !          2494: #endif
        !          2495:     if (! fname) {
        !          2496:         slbuf1[ len] = PATH_DELIM;          /* Append PATH_DELIM    */
        !          2497:         slbuf1[ ++len] = EOS;
        !          2498:     }
        !          2499: #if SYS_FAMILY == SYS_UNIX
        !          2500:     /* Dereference symbolic linked directory or file, if any    */
        !          2501:     slbuf1[ len] = EOS;     /* Truncate PATH_DELIM and 'fname' part, if any */
        !          2502:     slbuf2[ 0] = EOS;
        !          2503:     if (*dir && ! fname) {      /* Registering include directory    */
        !          2504:         /* Symbolic link check of directories are required  */
        !          2505:         deref_syml( slbuf1, slbuf2, slbuf1);
        !          2506:     } else if (fname) {                             /* Regular file */
        !          2507:         len = strlen( slbuf1);
        !          2508:         strcat( slbuf1, fname);
        !          2509:         deref_syml( slbuf1, slbuf2, slbuf1 + len);
        !          2510:                                 /* Symbolic link check of directory */
        !          2511:         if ((len = readlink( slbuf1, slbuf2, PATHMAX)) > 0) {
        !          2512:             /* Dereference symbolic linked file (not directory) */
        !          2513:             *(slbuf2 + len) = EOS;
        !          2514:             cp1 = slbuf1;
        !          2515:             if (slbuf2[ 0] != PATH_DELIM) {     /* Relative path    */
        !          2516:                 cp2 = strrchr( slbuf1, PATH_DELIM);
        !          2517:                 if (cp2)        /* Append to the source directory   */
        !          2518:                     cp1 = cp2 + 1;
        !          2519:             }
        !          2520:             strcpy( cp1, slbuf2);
        !          2521:         }
        !          2522:     }
        !          2523:     if (inf) {
        !          2524:         if (slbuf2[ 0])
        !          2525:             mcpp_fprintf( DBG, "Dereferenced \"%s%s\" to \"%s\"\n"
        !          2526:                     , dir, fname ? fname : null, slbuf1);
        !          2527:     }
        !          2528: #endif
        !          2529:     len = strlen( slbuf1);
        !          2530:     start = norm_name = xmalloc( len + 1);  /* Need a new buffer    */
        !          2531:     strcpy( norm_name, slbuf1);
        !          2532: #if SYS_FAMILY == SYS_WIN
        !          2533:     bsl2sl( norm_name);
        !          2534: #endif
        !          2535: #if SPECIAL_PATH_DELIM                  /* ':' ?    */
        !          2536:     for (cp1 = norm_name; *cp1 != EOS; cp1++) {
        !          2537:         if (*cp1 == PATH_DELIM)
        !          2538:             *cp1 = '/';
        !          2539:     }
        !          2540: #endif
        !          2541:     cp1 = norm_name;
        !          2542:
        !          2543: #if SYSTEM == SYS_CYGWIN
        !          2544:     /* Convert to "/cygdirve/x/dir" style of absolute path-list     */
        !          2545:     if (len >= 8 && (memcmp( cp1, "/usr/bin", 8) == 0
        !          2546:                     || memcmp( cp1, "/usr/lib", 8) == 0)) {
        !          2547:         memmove( cp1, cp1 + 4, len - 4 + 1);    /* Remove "/usr"    */
        !          2548:         len -= 4;
        !          2549:     }
        !          2550:     if (*cp1 == '/' && (len < 10 || memcmp( cp1, cygdrive, 10) != 0)) {
        !          2551:         /* /dir, not /cygdrive/     */
        !          2552:         if (! root_dir_len) {           /* Should be initialized    */
        !          2553:             /* Convert "X:\DIR-list" to "/cygdrive/x/dir-list"      */
        !          2554:             root_dir = xmalloc( strlen( CYGWIN_ROOT_DIRECTORY) + 1);
        !          2555:             strcpy( root_dir, CYGWIN_ROOT_DIRECTORY);
        !          2556:             *(root_dir + 1) = *root_dir;        /* "x:/" to " x/"   */
        !          2557:             cp1 = xmalloc( strlen( cygdrive) + strlen( root_dir));
        !          2558:             strcpy( cp1, cygdrive);
        !          2559:             strcat( cp1, root_dir + 1);
        !          2560:             free( root_dir);
        !          2561:             root_dir = cp1;
        !          2562:             root_dir_len = strlen( root_dir);
        !          2563:         }
        !          2564:         cp1 = xmalloc( root_dir_len + len + 1);
        !          2565:         strcpy( cp1, root_dir);
        !          2566:         strcat( cp1, norm_name);        /* Convert to absolute path */
        !          2567:         free( norm_name);
        !          2568:         norm_name = start = cp1;
        !          2569:         len += root_dir_len;
        !          2570:     }
        !          2571: #endif
        !          2572:
        !          2573: #if SYSTEM == SYS_MINGW
        !          2574:     /* Handle the mess of MinGW's path-list */
        !          2575:     /* Convert to "x:/dir" style of absolute path-list  */
        !          2576:     if (*cp1 == PATH_DELIM && isalpha( *(cp1 + 1))
        !          2577:             && *(cp1 + 2) == PATH_DELIM) {          /* /c/, /d/, etc*/
        !          2578:         *cp1 = *(cp1 + 1);
        !          2579:         *(cp1 + 1) = ':';               /* Convert to c:/, d:/, etc */
        !          2580:     } else if (memcmp( cp1, "/mingw", 6) == 0) {
        !          2581:         if (! mingw_dir_len) {          /* Should be initialized    */
        !          2582:             mingw_dir_len = strlen( MINGW_DIRECTORY);
        !          2583:             mingw_dir = xmalloc( mingw_dir_len + 1);
        !          2584:             strcpy( mingw_dir, MINGW_DIRECTORY);
        !          2585:         }
        !          2586:         cp1 = xmalloc( mingw_dir_len + len + 1);
        !          2587:         strcpy( cp1, mingw_dir);
        !          2588:         strcat( cp1, norm_name + 6);    /* Convert to absolute path */
        !          2589:         free( norm_name);
        !          2590:         norm_name = start = cp1;
        !          2591:         len += mingw_dir_len;
        !          2592:     } else if (memcmp( cp1, "/usr", 4) == 0) {
        !          2593:         memmove( cp1, cp1 + 4, len - 4 + 1);    /* Remove "/usr"    */
        !          2594:         len -= 4;
        !          2595:     }
        !          2596:     if (*cp1 == '/') {                  /* /dir or /                */
        !          2597:         if (! root_dir_len) {           /* Should be initialized    */
        !          2598:             root_dir_len = strlen( MSYS_ROOT_DIRECTORY);
        !          2599:             root_dir = xmalloc( root_dir_len + 1);
        !          2600:             strcpy( root_dir, MSYS_ROOT_DIRECTORY);
        !          2601:         }
        !          2602:         cp1 = xmalloc( root_dir_len + len + 1);
        !          2603:         strcpy( cp1, root_dir);
        !          2604:         strcat( cp1, norm_name);        /* Convert to absolute path */
        !          2605:         free( norm_name);
        !          2606:         norm_name = start = cp1;
        !          2607:         len += root_dir_len;
        !          2608:     }
        !          2609: #endif
        !          2610:
        !          2611: #if SYS_FAMILY == SYS_WIN
        !          2612:     if (*(cp1 + 1) == ':')
        !          2613:         start = cp1 += 2;               /* Next to the drive letter */
        !          2614:     start_pos = 2;
        !          2615: #endif
        !          2616:     if (len == 1 && *norm_name == '/')              /* Only "/"     */
        !          2617:         return  norm_name;
        !          2618:
        !          2619:     if (strncmp( cp1, "./", 2) == 0)    /* Remove beginning "./"    */
        !          2620:         memmove( cp1, cp1 + 2, strlen( cp1 + 2) + 1);       /* +1 for EOS   */
        !          2621:     if (*start != '/') {    /* Relative path to current directory   */
        !          2622:         /* Make absolute path   */
        !          2623:         abs_path = xmalloc( len + strlen( cur_work_dir) + 1);
        !          2624:         cp1 = stpcpy( abs_path, cur_work_dir);
        !          2625:         strcpy( cp1, start);
        !          2626:         free( norm_name);
        !          2627:         norm_name = abs_path;
        !          2628:         start = cp1 = norm_name + start_pos;
        !          2629:     }
        !          2630:
        !          2631:     while ((cp1 = strstr( cp1, "/./")) != NULL)
        !          2632:         memmove( cp1, cp1 + 2, strlen( cp1 + 2) + 1);
        !          2633:                                         /* Remove "/." of "/./"     */
        !          2634:     cp1 = start;
        !          2635:     /* Remove redundant "foo/../"   */
        !          2636:     while ((cp1 = strstr( cp1, "/../")) != NULL) {
        !          2637:         *cp1 = EOS;
        !          2638:         if ((cp2 = strrchr( start, '/')) != NULL) {
        !          2639:             if (*(cp1 - 1) != '.') {
        !          2640:                 memmove( cp2 + 1, cp1 + 4, strlen( cp1 + 4) + 1);
        !          2641:                                         /* Remove "foo/../"         */
        !          2642:                 cp1 = cp2;
        !          2643:             } else {                                /* Impossible   */
        !          2644:                 break;
        !          2645:             }
        !          2646:         } else {                                    /* Impossible   */
        !          2647:             break;
        !          2648:         }
        !          2649:     }
        !          2650:
        !          2651: #if SPECIAL_PATH_DELIM
        !          2652:     for (cp1 = start; *cp1 != EOS; cp1++) {
        !          2653:         if (*cp1 == '/')
        !          2654:             *cp1 = PATH_DELIM;
        !          2655:     }
        !          2656: #endif
        !          2657:     if (inf) {
        !          2658:         char    debug_buf[ PATHMAX+1];
        !          2659:         strcpy( debug_buf, dir);
        !          2660:         strcat( debug_buf, fname ? fname : null);
        !          2661: #if SYS_FAMILY == SYS_WIN
        !          2662:         bsl2sl( debug_buf);
        !          2663: #endif
        !          2664:         if (! str_eq( debug_buf, norm_name))
        !          2665:             mcpp_fprintf( DBG, "Normalized the path \"%s\" to \"%s\"\n"
        !          2666:                     , debug_buf, norm_name);
        !          2667:     }
        !          2668:
        !          2669:     return  norm_name;
        !          2670: }
        !          2671:
        !          2672: #if SYS_FAMILY == SYS_UNIX
        !          2673:
        !          2674: static void     deref_syml(
        !          2675:     char *      slbuf1,                     /* Original path-list   */
        !          2676:     char *      slbuf2,                     /* Working buffer       */
        !          2677:     char *      chk_start                   /* Pointer into slbuf1  */
        !          2678: )
        !          2679: /* Dereference symbolic linked directory    */
        !          2680: {
        !          2681:     char *      cp2;
        !          2682:     int         len;                /* Should be int, not size_t    */
        !          2683:
        !          2684:     while ((chk_start = strchr( chk_start, PATH_DELIM)) != NULL) {
        !          2685:         *chk_start = EOS;
        !          2686:         if ((len = readlink( slbuf1, slbuf2, PATHMAX)) > 0) {
        !          2687:             /* Dereference symbolic linked directory    */
        !          2688:             cp2 = strrchr( slbuf1, PATH_DELIM); /* Previous delimiter       */
        !          2689:             *chk_start = PATH_DELIM;
        !          2690:             strcpy( slbuf2 + len, chk_start);
        !          2691:             if (slbuf2[ 0] == PATH_DELIM) {     /* Absolute path    */
        !          2692:                 strcpy( slbuf1, slbuf2);
        !          2693:                 chk_start = slbuf1 + len + 1;
        !          2694:             } else {
        !          2695:                 if (cp2)
        !          2696:                     chk_start = cp2 + 1;
        !          2697:                 else
        !          2698:                     chk_start = slbuf1;
        !          2699:                 strcpy( chk_start, slbuf2);     /* Rewrite the path */
        !          2700:                 chk_start += len;
        !          2701:             }
        !          2702:         } else {
        !          2703:             *chk_start++ = PATH_DELIM;
        !          2704:         }
        !          2705:     }
        !          2706: }
        !          2707: #endif
        !          2708:
        !          2709: #if COMPILER == GNUC
        !          2710:
        !          2711: static void init_gcc_macro( void)
        !          2712: /*
        !          2713:  * Predefine GCC macros.
        !          2714:  * This routine should be called after opening output file in order to putout
        !          2715:  * macro informations by -K option into the file.
        !          2716:  * Also this routine should be called before undef_macros() in order to
        !          2717:  * permit undefining a macro by -U option.
        !          2718:  */
        !          2719: {
        !          2720:     char        fname[ BUFSIZ];
        !          2721:     char        lbuf[ BUFSIZ];
        !          2722:     char *      include_dir;    /* The version-specific include directory   */
        !          2723:     char *      tmp;
        !          2724:     FILE *      fp;
        !          2725:     DEFBUF *    defp;
        !          2726:     const char *    cp;
        !          2727:     char *      tp;
        !          2728:     int         i;
        !          2729:
        !          2730:     if (nflag)                                  /* -undef option    */
        !          2731:         goto  undef_special;
        !          2732:
        !          2733:     tmp = xmalloc( strlen( INC_DIR) + strlen( "/mingw/mcpp-gcc-")
        !          2734:             + strlen( arch) + 1);
        !          2735: #if SYSTEM == SYS_CYGWIN
        !          2736:     if (no_cygwin) {
        !          2737:         sprintf( tmp, "%s/mingw/mcpp-gcc-%s", INC_DIR, arch);
        !          2738:     } else {
        !          2739:         sprintf( tmp, "%s/mcpp-gcc-%s", INC_DIR, arch);
        !          2740:     }
        !          2741: #else
        !          2742:     sprintf( tmp, "%s/mcpp-gcc-%s", INC_DIR, arch);
        !          2743: #endif
        !          2744:     include_dir = norm_path( tmp, NULL, TRUE, FALSE);
        !          2745:     free( tmp);
        !          2746:
        !          2747:     for (i = 0; i <= 1; i++) {
        !          2748:         int         nargs;
        !          2749:
        !          2750:         if ((mcpp_mode == POST_STD || ansi) && i == 0)
        !          2751:             continue;   /* POST_STD or __STRICT_ANSI__ does not     */
        !          2752:                         /*      predefine non-conforming macros     */
        !          2753:         /* The predefined macro file    */
        !          2754:         cp = i ? "std" : "old";
        !          2755:         sprintf( fname, "%sg%s%d%d_predef_%s.h"
        !          2756:                 , include_dir, cplus_val ? "xx" : "cc"
        !          2757:                 , gcc_maj_ver, gcc_min_ver, cp);
        !          2758:             /* Note that norm_path() append a PATH_DELIM.   */
        !          2759:         if ((fp = fopen( fname, "r")) == NULL) {
        !          2760:             mcpp_fprintf( ERR, "The mode for %s has not been installed.\n"
        !          2761:                     , arch);
        !          2762:             longjmp( error_exit, -1);
        !          2763:         }
        !          2764:         nargs = i ? 0 : DEF_NOARGS_PREDEF_OLD;
        !          2765:             /* g*_predef_std.h has DEF_NOARGS_PREDEF or non-negative args   */
        !          2766:             /* while g*_predef_old.h has only DEF_NOARGS_PREDEF_OLD args    */
        !          2767:         while (fgets( lbuf, BUFSIZ, fp) != NULL) {
        !          2768:             unget_string( lbuf, "gcc_predefine");
        !          2769:             if (skip_ws() == '#'
        !          2770:                 && scan_token( skip_ws(), (tp = work_buf, &tp), work_end)
        !          2771:                         == NAM
        !          2772:                     && str_eq( work_buf, "define")) {
        !          2773:                 defp = do_define( TRUE, nargs);     /* Ignore re-definition */
        !          2774:             }
        !          2775:             skip_nl();
        !          2776:         }
        !          2777:     }
        !          2778:     free( include_dir);
        !          2779:
        !          2780: undef_special:
        !          2781:     if (look_id( "__OPTIMIZE__"))       /* -O option is specified   */
        !          2782:         undefine( "__NO_INLINE__");
        !          2783: }
        !          2784:
        !          2785: static void chk_env( void)
        !          2786: /*
        !          2787:  * Check the environment variables to specify output of dependency lines.
        !          2788:  */
        !          2789: {
        !          2790:     char *  env;
        !          2791:     char *  cp;
        !          2792:
        !          2793:     /* Output of dependency lines   */
        !          2794:     if ((env = getenv( "DEPENDENCIES_OUTPUT")) == NULL) {
        !          2795:         if ((env = getenv( "SUNPRO_DEPENDENCIES")) == NULL)
        !          2796:             return;
        !          2797:         else
        !          2798:             mkdep |= MD_SYSHEADER;
        !          2799:     }
        !          2800:     mkdep |= MD_MKDEP;
        !          2801:     if ((cp = strchr( env, ' ')) != NULL) {
        !          2802:         *cp++ = EOS;
        !          2803:         while (*cp == ' ')
        !          2804:             cp++;
        !          2805:     }
        !          2806:     if (! mkdep_fp)                 /* Command line option precedes */
        !          2807:         mkdep_fp = fopen( env, "a");
        !          2808:     if (! mkdep_target)
        !          2809:         mkdep_target = cp;
        !          2810: }
        !          2811:
        !          2812: #elif   COMPILER == MSC
        !          2813:
        !          2814: static void init_msc_macro( void)
        !          2815: /*
        !          2816:  * Define a few MSC-specific predefined macros.
        !          2817:  */
        !          2818: {
        !          2819:     DEFBUF *    defp;
        !          2820:     int         i;
        !          2821:
        !          2822:     defp = look_id( "_MSC_VER");
        !          2823:     i = atoi( defp->repl);
        !          2824:     if (i >= 1400) {                        /* _MSC_VER >= 1400     */
        !          2825:         look_and_install( "_MT", DEF_NOARGS_PREDEF, null, "1");
        !          2826:         if (cplus_val && ! wchar_t_modified) {
        !          2827:             /* -Zc:wchar_t- was not specified   */
        !          2828:             look_and_install( "_NATIVE_WCHAR_T_DEFINED", DEF_NOARGS_PREDEF
        !          2829:                     , null, "1");
        !          2830:             look_and_install( "_WCHAR_T_DEFINED", DEF_NOARGS_PREDEF, null
        !          2831:                     , "1");
        !          2832:         }
        !          2833:     }
        !          2834: }
        !          2835:
        !          2836: #endif
        !          2837:
        !          2838: static void     def_macros( void)
        !          2839: /*
        !          2840:  * Define macros specified by -D option.
        !          2841:  * This routine should be called before undef_macros().
        !          2842:  */
        !          2843: {
        !          2844:     int         i;
        !          2845:
        !          2846:     for (i = 0; i < def_cnt; i++)
        !          2847:         def_a_macro( 'D', def_list[ i]);
        !          2848: }
        !          2849:
        !          2850: static void     undef_macros( void)
        !          2851: /*
        !          2852:  * Undefine macros specified by -U option.
        !          2853:  * This routine should be called after init_predefine().
        !          2854:  */
        !          2855: {
        !          2856:     char *      name;
        !          2857:     int         i;
        !          2858:
        !          2859:     for (i = 0; i < undef_cnt; i++) {
        !          2860:         name = undef_list[ i];
        !          2861:         if (look_id( name) != NULL)
        !          2862:             undefine( name);
        !          2863:         else if (warn_level & 8)
        !          2864:             mcpp_fprintf( ERR, "\"%s\" wasn't defined\n", name);
        !          2865:     }
        !          2866: }
        !          2867:
        !          2868: void    put_depend(
        !          2869:     const char *    filename
        !          2870: )
        !          2871: /*
        !          2872:  * Append a header name to the source file dependency line.
        !          2873:  */
        !          2874: {
        !          2875: #define MAX_OUT_LEN     76      /* Maximum length of output line    */
        !          2876: #define MKDEP_INITLEN   (MKDEP_INIT * 0x100)
        !          2877: #define MKDEP_MAX       (MKDEP_INIT * 0x10)
        !          2878: #define MKDEP_MAXLEN    (MKDEP_INITLEN * 0x10)
        !          2879:
        !          2880:     static char *   output = NULL;          /* File names           */
        !          2881:     static size_t * pos = NULL;             /* Offset to filenames  */
        !          2882:     static int      pos_num;                /* Index of pos[]       */
        !          2883:     static char *   out_p;                  /* Pointer to output[]  */
        !          2884:     static size_t   mkdep_len;              /* Size of output[]     */
        !          2885:     static size_t   pos_max;                /* Size of pos[]        */
        !          2886:     static FILE *   fp;         /* Path to output dependency line   */
        !          2887:     static size_t   llen;       /* Length of current physical output line   */
        !          2888:     size_t *        pos_p;                  /* Index into pos[]     */
        !          2889:     size_t          fnamlen;                /* Length of filename   */
        !          2890:
        !          2891:     if (fp == NULL) {   /* Main source file.  Have to initialize.   */
        !          2892: #if MCPP_LIB
        !          2893:         if (output != NULL) {
        !          2894:             free( output);
        !          2895:             free( pos);
        !          2896:         }
        !          2897: #endif
        !          2898:         output = xmalloc( mkdep_len = MKDEP_INITLEN);
        !          2899:         pos = (size_t *) xmalloc( (pos_max = MKDEP_INIT) * sizeof (size_t));
        !          2900:         out_p = md_init( filename, output);
        !          2901:         fp = mkdep_fp;
        !          2902:         llen = strlen( output);
        !          2903:         pos_num = 0;            /* Initialize for MCPP_LIB build    */
        !          2904:     } else if (filename == NULL) {              /* End of input     */
        !          2905:         out_p = stpcpy( out_p, "\n\n");
        !          2906:         if (mkdep & MD_PHONY) {
        !          2907:             /* Output the phony target line for each recorded header files. */
        !          2908:             char *  cp;
        !          2909:             int     c;
        !          2910:
        !          2911:             if (strlen( output) * 2 + (pos_num * 2) >= MKDEP_MAXLEN) {
        !          2912:                 cerror( "Too long dependency line"          /* _E_  */
        !          2913:                         , NULL, 0L, NULL);
        !          2914:                 if (fp == fp_out)
        !          2915:                     mcpp_fputs( output, OUT);
        !          2916:                 else
        !          2917:                     fputs( output, fp);
        !          2918:                 return;
        !          2919:             } else if (strlen( output) * 2 + (pos_num * 2) >= mkdep_len) {
        !          2920:                 /* Enlarge the buffer   */
        !          2921:                 size_t  len = out_p - output;
        !          2922:                 output = xrealloc( output, mkdep_len *= 2);
        !          2923:                 out_p = output + len;
        !          2924:             }
        !          2925:             pos_num--;
        !          2926:             for (pos_p = &pos[ 0]; pos_p <= &pos[ pos_num]; pos_p++) {
        !          2927:                 if (pos_p == &pos[ pos_num]) {      /* End of output    */
        !          2928:                     for (cp = output + *pos_p; *cp != '\n'; cp++)
        !          2929:                         ;
        !          2930:                     c = '\n';                       /* Append newline   */
        !          2931:                 } else {
        !          2932:                     cp = output + *(pos_p + 1) - 1;
        !          2933:                     while( *cp == ' ' || *cp == '\\' || *cp == '\n')
        !          2934:                         cp--;               /* Remove trailing spaces   */
        !          2935:                     c = *(++cp);
        !          2936:                 }
        !          2937:                 *cp = EOS;
        !          2938:                 out_p = stpcpy( out_p, output + *pos_p);
        !          2939:                 out_p = stpcpy( out_p, ":\n\n");
        !          2940:                 *cp = c;
        !          2941:             }
        !          2942:         }
        !          2943:         if (fp == fp_out) { /* To the same path with normal preprocessing   */
        !          2944:             mcpp_fputs( output, OUT);
        !          2945:         } else {        /* To the file specified by -MF, -MD, -MMD options  */
        !          2946:             fputs( output, fp);
        !          2947:             fclose( fp);
        !          2948:         }
        !          2949:         fp = NULL;      /* Clear for the next call in MCPP_LIB build        */
        !          2950:         return;
        !          2951:     }
        !          2952:
        !          2953:     fnamlen = strlen( filename);
        !          2954:     /* Check the recorded filename  */
        !          2955:     for (pos_p = pos; pos_p < &pos[ pos_num]; pos_p++) {
        !          2956:         if (memcmp( output + *pos_p, filename, fnamlen) == 0)
        !          2957:             return;                 /* Already recorded filename    */
        !          2958:     }
        !          2959:     /* Any new header.  Append its name to output.  */
        !          2960:     if (llen + fnamlen > MAX_OUT_LEN) {         /* Line is long     */
        !          2961:         out_p = stpcpy( out_p, " \\\n ");       /* Fold it          */
        !          2962:         llen = 1;
        !          2963:     }
        !          2964:     llen += fnamlen + 1;
        !          2965:     if (pos_num >= MKDEP_MAX
        !          2966:             || out_p + fnamlen + 1 >= output + MKDEP_MAXLEN)
        !          2967:         cfatal( "Too long dependency line: %s", output, 0L, NULL);
        !          2968:     /* Need to enlarge the buffer   */
        !          2969:     if (pos_num >= pos_max) {
        !          2970:         pos = (size_t *) xrealloc( (char *) pos
        !          2971:                 , (pos_max *= 2) * sizeof (size_t *));
        !          2972:     }
        !          2973:     if (output + mkdep_len <= out_p + fnamlen + 1) {
        !          2974:         size_t  len = out_p - output;
        !          2975:         output = xrealloc( output, mkdep_len *= 2);
        !          2976:         out_p = output + len;
        !          2977:     }
        !          2978:     *out_p++ = ' ';
        !          2979:     pos[ pos_num++] = out_p - output;       /* Remember the offset  */
        !          2980:             /* Don't use pointer, since 'output' may be reallocated later.  */
        !          2981:     out_p = stpcpy( out_p, filename);
        !          2982: }
        !          2983:
        !          2984: static char *   md_init(
        !          2985:     const char *    filename,   /* The source file name             */
        !          2986:     char *  output              /* Output to dependency file        */
        !          2987: )
        !          2988: /*
        !          2989:  * Initialize output file and target.
        !          2990:  */
        !          2991: {
        !          2992:     char    prefix[ PATHMAX];
        !          2993:     char *  cp = NULL;
        !          2994:     size_t  len;
        !          2995:     char *  out_p;
        !          2996:     const char *    target = filename;
        !          2997:     const char *    cp0;
        !          2998:
        !          2999:     if (! mkdep_target || ! mkdep_fp) {         /* Make target name */
        !          3000: #ifdef  PATH_DELIM
        !          3001:         if ((cp0 = strrchr( target, PATH_DELIM)) != NULL)
        !          3002:             target = cp0 + 1;
        !          3003: #endif
        !          3004:         if ((cp0 = strrchr( target, '.')) == NULL)
        !          3005:             len = strlen( target);
        !          3006:         else
        !          3007:             len = (size_t) (cp0 - target);
        !          3008:         memcpy( prefix, target, len);
        !          3009:         cp = prefix + len;
        !          3010:         *cp++ = '.';
        !          3011:     }
        !          3012:
        !          3013:     if (! mkdep_fp) {   /* Unless already opened by -MF, -MD, -MMD options  */
        !          3014:         if (mkdep & MD_FILE) {
        !          3015:             strcpy( cp, "d");
        !          3016:             mkdep_fp = fopen( prefix, "w");
        !          3017:         } else {
        !          3018:             mkdep_fp = fp_out;  /* Output dependency line to normal output  */
        !          3019:             no_output++;                /* Without normal output    */
        !          3020:         }
        !          3021:     }
        !          3022:
        !          3023:     if (mkdep_target) {         /* -MT or -MQ option is specified   */
        !          3024:         if (mkdep & MD_QUOTE) {         /* 'Quote' $, \t and space  */
        !          3025:             out_p = md_quote( output);
        !          3026:         } else {
        !          3027:             out_p = stpcpy( output, mkdep_target);
        !          3028:         }
        !          3029:     } else {
        !          3030:         strcpy( cp, OBJEXT);
        !          3031:         out_p = stpcpy( output, prefix);
        !          3032:     }
        !          3033:
        !          3034:     *out_p++ = ':';
        !          3035:     *out_p = EOS;
        !          3036:     return  out_p;
        !          3037: }
        !          3038:
        !          3039: static char *   md_quote(
        !          3040:     char *  output
        !          3041: )
        !          3042: /*
        !          3043:  * 'Quote' $, tab and space.
        !          3044:  * This function was written referring to GCC V.3.2 source.
        !          3045:  */
        !          3046: {
        !          3047:     char *  p;
        !          3048:     char *  q;
        !          3049:
        !          3050:     for (p = mkdep_target; *p; p++, output++) {
        !          3051:         switch (*p) {
        !          3052:         case ' ':
        !          3053:         case '\t':
        !          3054:             /* GNU-make treats backslash-space sequence peculiarly  */
        !          3055:             for (q = p - 1; mkdep_target <= q && *q == '\\'; q--)
        !          3056:                 *output++ = '\\';
        !          3057:             *output++ = '\\';
        !          3058:             break;
        !          3059:         case '$':
        !          3060:             *output++ = '$';
        !          3061:             break;
        !          3062:         default:
        !          3063:             break;
        !          3064:         }
        !          3065:         *output = *p;
        !          3066:     }
        !          3067:     *output = EOS;
        !          3068:     return  output;
        !          3069: }
        !          3070:
        !          3071: static const char *     toolong_fname =
        !          3072:         "Too long header name \"%s%.0ld%s\"";               /* _F_  */
        !          3073: static const char *     excess_token =
        !          3074:         "Excessive token sequence \"%s\"";          /* _E_, _W1_    */
        !          3075:
        !          3076: int     do_include(
        !          3077:     int     next        /* TRUE if the directive is #include_next   */
        !          3078: )
        !          3079: /*
        !          3080:  * Process the #include line.
        !          3081:  * There are three variations:
        !          3082:  *      #include "file"         search somewhere relative to the
        !          3083:  *                              current (or source) directory, if not
        !          3084:  *                              found, treat as #include <file>.
        !          3085:  *      #include <file>         Search in an implementation-dependent
        !          3086:  *                              list of places.
        !          3087:  *      #include macro-call     Expand the macro call, it must be one of
        !          3088:  *                              "file" or <file>, process as such.
        !          3089:  * On success : return TRUE;
        !          3090:  * On failure of syntax : return FALSE;
        !          3091:  * On failure of file opening : return FALSE.
        !          3092:  * do_include() always absorbs the line (including the <newline>).
        !          3093:  */
        !          3094: {
        !          3095:     const char * const  no_name = "No header name";         /* _E_  */
        !          3096:     char    header[ PATHMAX + 16];
        !          3097:     int     token_type;
        !          3098:     char *  fname;
        !          3099:     char *  filename;
        !          3100:     int     delim;                          /* " or <, >            */
        !          3101:
        !          3102:     if ((delim = skip_ws()) == '\n') {      /* No argument          */
        !          3103:         cerror( no_name, NULL, 0L, NULL);
        !          3104:         return  FALSE;
        !          3105:     }
        !          3106:     fname = infile->bptr - 1;       /* Current token for diagnosis  */
        !          3107:
        !          3108:     if (standard && (char_type[ delim] & LET)) {    /* Maybe macro  */
        !          3109:         int     c;
        !          3110:         char    *hp;
        !          3111:
        !          3112:         hp = header;
        !          3113:         *hp = EOS;
        !          3114:         c = delim;
        !          3115:         while (get_unexpandable( c, FALSE) != NO_TOKEN) {
        !          3116:                                 /* Expand any macros in the line    */
        !          3117:             if (header + PATHMAX < hp + (int) (workp - work_buf))
        !          3118:                 cfatal( toolong_fname, header, 0L, work_buf);
        !          3119:             hp = stpcpy( hp, work_buf);
        !          3120:             while (char_type[ c = get_ch()] & HSP)
        !          3121:                 *hp++ = c;
        !          3122:         }
        !          3123:         *hp = EOS;                          /* Ensure to terminate  */
        !          3124:         if (macro_line == MACRO_ERROR)      /* Unterminated macro   */
        !          3125:             return  FALSE;                  /*   already diagnosed. */
        !          3126:         unget_string( header, NULL);        /* To re-read           */
        !          3127:         delim = skip_ws();
        !          3128:         if (delim == '\n') {
        !          3129:             cerror( no_name, NULL, 0L, NULL);       /* Expanded to  */
        !          3130:             return  FALSE;                          /*   0 token.   */
        !          3131:         }
        !          3132:     }
        !          3133:
        !          3134:     token_type = scan_token( delim, (workp = work_buf, &workp)
        !          3135:             , work_buf + PATHMAX);
        !          3136:     if (token_type == STR)                  /* String literal form  */
        !          3137:         goto  found_name;
        !          3138:     else if (token_type == OPE && openum == OP_LT)          /* '<'  */
        !          3139:         workp = scan_quote( delim, work_buf, work_buf + PATHMAX, TRUE);
        !          3140:                                         /* Re-construct or diagnose */
        !          3141:     else                                    /* Any other token in-  */
        !          3142:         goto  not_header;                   /*   cluding <=, <<, <% */
        !          3143:
        !          3144:     if (workp == NULL)                      /* Missing closing '>'  */
        !          3145:         goto  syntax_error;
        !          3146:
        !          3147: found_name:
        !          3148:     *--workp = EOS;                         /* Remove the closing and   */
        !          3149:     fname = save_string( &work_buf[ 1]);    /*  the starting delimiter. */
        !          3150:
        !          3151:     if (skip_ws() != '\n') {
        !          3152:         if (standard) {
        !          3153:             cerror( excess_token, infile->bptr-1, 0L, NULL);
        !          3154:             skip_nl();
        !          3155:             goto  error;
        !          3156:         } else if (mcpp_mode == OLD_PREP) {
        !          3157:             skip_nl();
        !          3158:         } else {
        !          3159:             if (warn_level & 1)
        !          3160:                 cwarn( excess_token, infile->bptr-1, 0L, NULL);
        !          3161:             skip_nl();
        !          3162:         }
        !          3163:     }
        !          3164:
        !          3165: #if SYS_FAMILY == SYS_WIN
        !          3166:     bsl2sl( fname);
        !          3167: #endif
        !          3168:     filename = fname;
        !          3169: #if NO_DIR                              /* Unofficial feature           */
        !          3170:     if (no_dir) {                       /* Strip directory components   */
        !          3171:         char    src_dir[ PATHMAX] = { EOS, };
        !          3172:         if (has_directory( fname, src_dir))
        !          3173:             filename = fname + strlen( src_dir);
        !          3174:         delim = '"';    /* Even a system header is handled as a local one   */
        !          3175:     }
        !          3176: #endif
        !          3177:     if (open_include( filename, (delim == '"'), next)) {
        !          3178:         /* 'fname' should not be free()ed, it is used as file->         */
        !          3179:         /*      real_fname and has been registered into fnamelist[]     */
        !          3180:         return  TRUE;
        !          3181:     }
        !          3182:
        !          3183:     cerror( "Can't open include file \"%s\"", filename, 0L, NULL);  /* _E_  */
        !          3184: error:
        !          3185:     free( fname);
        !          3186:     return  FALSE;
        !          3187:
        !          3188: not_header:
        !          3189:     cerror( "Not a header name \"%s\"", fname, 0L, NULL);   /* _E_  */
        !          3190: syntax_error:
        !          3191:     skip_nl();
        !          3192:     return  FALSE;
        !          3193: }
        !          3194:
        !          3195: static int  open_include(
        !          3196:     char *  filename,               /* File name to include         */
        !          3197:     int     searchlocal,            /* TRUE if #include "file"      */
        !          3198:     int     next                    /* TRUE if #include_next        */
        !          3199: )
        !          3200: /*
        !          3201:  * Open an include file.  This routine is only called from do_include() above.
        !          3202:  * It searches the list of directories via search_dir() and opens the file
        !          3203:  * via open_file(), linking it into the list of active files.
        !          3204:  * Returns TRUE if the file was opened, FALSE if it fails.
        !          3205:  */
        !          3206: {
        !          3207:     char    src_dir[ PATHMAX] = { EOS, };   /* Directory part of includer   */
        !          3208:     int     full_path;              /* Filename is full-path-list   */
        !          3209:     int     has_dir = FALSE;        /* Includer has directory part  */
        !          3210:     int     has_dir_src = FALSE;
        !          3211:     int     has_dir_fname = FALSE;
        !          3212:
        !          3213:     full_path = is_full_path( filename);
        !          3214:
        !          3215:     if (!full_path && searchlocal && (search_rule & SOURCE)) {
        !          3216:         has_dir_src  = has_directory( infile->src_dir, src_dir);
        !          3217:         has_dir_fname = has_directory( infile->real_fname
        !          3218:                 , src_dir + strlen( src_dir));
        !          3219:         /* Get directory part of the parent file of the file to include.*/
        !          3220:         /* Note that infile->dirp of main input file is set to "" and   */
        !          3221:         /* remains the same even if -include options are processed.     */
        !          3222:         has_dir = has_dir_src || has_dir_fname
        !          3223:                 || (**(infile->dirp) != EOS);
        !          3224:     }
        !          3225:     if (mcpp_debug & PATH)
        !          3226:         mcpp_fprintf( DBG, "filename: %s\n", filename);
        !          3227:
        !          3228: #if COMPILER == GNUC
        !          3229:     if (! full_path) {
        !          3230:         if (i_split                     /* -I- option is specified  */
        !          3231:                 || next)                        /* or #include_next */
        !          3232:         goto  search_dirs;
        !          3233:     }
        !          3234: #endif
        !          3235:
        !          3236:     if ((searchlocal && ((search_rule & CURRENT) || !has_dir)) || full_path) {
        !          3237:         /*
        !          3238:          * Look in local directory first.
        !          3239:          * Try to open filename relative to the "current directory".
        !          3240:          */
        !          3241:         if (open_file( &null, NULL, filename, searchlocal && !full_path
        !          3242:                 , FALSE, FALSE))
        !          3243:             return  TRUE;
        !          3244:         if (full_path)
        !          3245:             return  FALSE;
        !          3246:     }
        !          3247:
        !          3248:     if (searchlocal && (search_rule & SOURCE) && has_dir) {
        !          3249:         /*
        !          3250:          * Look in local directory of source file.
        !          3251:          * Try to open filename relative to the "source directory".
        !          3252:          */
        !          3253:         if (open_file( infile->dirp, src_dir, filename, TRUE, FALSE, FALSE))
        !          3254:             return  TRUE;
        !          3255:     }
        !          3256:
        !          3257: #if COMPILER == MSC
        !          3258:     if (searchlocal) {
        !          3259:         /* Visual C searches ancestor source's directory, too.  */
        !          3260:         FILEINFO *  file = infile;
        !          3261:         while ((file = file->parent) != NULL) {
        !          3262:             /* Search each parent includer's directory  */
        !          3263:             if (open_file( file->dirp, src_dir, filename, TRUE, FALSE, FALSE))
        !          3264:                 return  TRUE;
        !          3265:         }
        !          3266:     }
        !          3267: #endif
        !          3268: #if COMPILER == GNUC
        !          3269: search_dirs:
        !          3270:     if (searchlocal) {
        !          3271:         /* Search the directories specified by -iquote option, if any.  */
        !          3272:         const char **   qdir;
        !          3273:         for (qdir = quote_dir; qdir < quote_dir_end; qdir++) {
        !          3274:             if (open_file( qdir, NULL, filename, FALSE, FALSE, FALSE))
        !          3275:                 return  TRUE;
        !          3276:         }
        !          3277:     }
        !          3278: #endif
        !          3279:     /* Search the include directories   */
        !          3280:     if (search_dir( filename, searchlocal, next))
        !          3281:         return  TRUE;
        !          3282:
        !          3283:     return  FALSE;
        !          3284: }
        !          3285:
        !          3286: static int  has_directory(
        !          3287:     const char *    source,         /* Filename to examine          */
        !          3288:     char *  directory               /* Put directory stuff here     */
        !          3289: )
        !          3290: /*
        !          3291:  * If a directory is found in the 'source' filename string (i.e. "includer"),
        !          3292:  * the directory part of the string is copied to 'directory' and
        !          3293:  * has_directory() returns TRUE.
        !          3294:  * Else, nothing is copied and it returns FALSE.
        !          3295:  */
        !          3296: {
        !          3297:     const char *    sp;
        !          3298:     size_t  len;
        !          3299:
        !          3300:     if (! source)
        !          3301:         return  FALSE;
        !          3302:     if ((sp = strrchr( source, PATH_DELIM)) == NULL) {
        !          3303:         return  FALSE;
        !          3304:     } else {
        !          3305:         len = (size_t)(sp - source) + 1;    /* With path-delimiter  */
        !          3306:         memcpy( directory, source, len);
        !          3307:         directory[ len] = EOS;
        !          3308:         return  TRUE;
        !          3309:     }
        !          3310: }
        !          3311:
        !          3312: static int  is_full_path(
        !          3313:     const char *    path
        !          3314: )
        !          3315: /*
        !          3316:  * Check whether the path is a full (absolute) path list or not.
        !          3317:  */
        !          3318: {
        !          3319:     if (! path)
        !          3320:         return  FALSE;
        !          3321: #if SYS_FAMILY == SYS_UNIX
        !          3322:     if (path[0] == PATH_DELIM)
        !          3323: #elif   SYS_FAMILY == SYS_WIN
        !          3324:     if ((path[1] == ':' && path[2] == PATH_DELIM)   /* "C:/path"    */
        !          3325:             || path[0] == PATH_DELIM)       /* Root dir of current drive    */
        !          3326: #elif   1
        !          3327: /* For other systems you should write code here.    */
        !          3328:     if (path[0] == PATH_DELIM)
        !          3329: #endif
        !          3330:         return  TRUE;
        !          3331:     else
        !          3332:         return  FALSE;
        !          3333: }
        !          3334:
        !          3335: static int  search_dir(
        !          3336:     char *  filename,               /* File name to include         */
        !          3337:     int     searchlocal,            /* #include "header.h"          */
        !          3338:     int     next                    /* TRUE if #include_next        */
        !          3339: )
        !          3340: /*
        !          3341:  * Look in any directories specified by -I command line arguments,
        !          3342:  * specified by environment variable, then in the builtin search list.
        !          3343:  */
        !          3344: {
        !          3345:     const char **   incptr;                 /* -> inlcude directory */
        !          3346:
        !          3347:     incptr = incdir;
        !          3348: #if COMPILER == GNUC
        !          3349:     if (next && **inc_dirp != EOS)
        !          3350:         incptr = inc_dirp + 1;
        !          3351:         /* In case of include_next search after the includer's directory    */
        !          3352: #endif
        !          3353:
        !          3354:     for ( ; incptr < incend; incptr++) {
        !          3355:         if (strlen( *incptr) + strlen( filename) >= PATHMAX)
        !          3356:             cfatal( toolong_fname, *incptr, 0L, filename);  /* _F_  */
        !          3357: #if SYSTEM == SYS_MAC
        !          3358:         if (incptr == to_search_framework && ! searchlocal) {
        !          3359:                                 /* Now search the framework dirs    */
        !          3360:             if (search_framework( filename)) {          /* Found    */
        !          3361:                 if (in_import)  /* "#import"ed file is once only    */
        !          3362:                     do_once( infile->full_fname);
        !          3363:                 return  TRUE;
        !          3364:             }
        !          3365:             /* Else continue to search incptr   */
        !          3366:         }
        !          3367: #endif
        !          3368:         if (open_file( incptr, NULL, filename, FALSE, FALSE, FALSE))
        !          3369:             /* Now infile has been renewed  */
        !          3370:             return  TRUE;
        !          3371:     }
        !          3372:
        !          3373:     return  FALSE;
        !          3374: }
        !          3375:
        !          3376: static int  open_file(
        !          3377:     const char **   dirp,           /* Pointer to include directory */
        !          3378:     const char *    src_dir,        /* Source directory of includer */
        !          3379:     const char *    filename,       /* Filename (possibly has directory)    */
        !          3380:     int         local,                      /* #include "file"      */
        !          3381:     int         include_opt,        /* Specified by -include option */
        !          3382:     int         sys_frame           /* System framework header (for SYS_MAC)*/
        !          3383: )
        !          3384: /*
        !          3385:  * Open a file, add it to the linked list of open files, close the includer
        !          3386:  * if nessesary and truncate the includer's buffer.
        !          3387:  * This is called from open_include() and at_start().
        !          3388:  */
        !          3389: {
        !          3390:     char        dir_fname[ PATHMAX] = { EOS, };
        !          3391: #if HOST_COMPILER == BORLANDC
        !          3392:     /* Borland's fopen() does not set errno.    */
        !          3393:     static int  max_open = FOPEN_MAX - 5;
        !          3394: #else
        !          3395:     static int  max_open;
        !          3396: #endif
        !          3397:     int         len;
        !          3398:     FILEINFO *  file = infile;
        !          3399:     FILE *      fp;
        !          3400:     char *      fullname;
        !          3401:     const char *    fname;
        !          3402:
        !          3403:     errno = 0;      /* Clear errno possibly set by path searching   */
        !          3404: #if SYSTEM == SYS_MAC && COMPILER == GNUC
        !          3405:     if (strlen( *dirp) > 5
        !          3406:             && str_case_eq( *dirp + strlen( *dirp) - 5, ".hmap")) {
        !          3407:         /* Search header map file for a header  */
        !          3408:         if (! search_header_map( *dirp, filename, dir_fname))
        !          3409:             return  NULL;
        !          3410:         fname = dir_fname;                  /* Found a path-list    */
        !          3411:         dirp = &null;
        !          3412:         goto  search;
        !          3413:     } else
        !          3414: #endif
        !          3415:     {
        !          3416:         if (mcpp_debug & PATH)
        !          3417:             mcpp_fprintf( DBG, "Searching %s%s%s\n", *dirp
        !          3418:                     , src_dir ? src_dir : null, filename);
        !          3419:     }
        !          3420:     /* src_dir is usually NULL.  This is specified to   */
        !          3421:     /* search the source directory of the includer.     */
        !          3422:     if (src_dir && *src_dir != EOS) {
        !          3423:         strcpy( dir_fname, src_dir);
        !          3424:         strcat( dir_fname, filename);
        !          3425:         fname = dir_fname;
        !          3426:     } else {
        !          3427:         fname = filename;
        !          3428:     }
        !          3429: search:
        !          3430:     fullname = norm_path( *dirp, fname, TRUE, FALSE);
        !          3431:                                     /* Convert to absolute path     */
        !          3432:     if (! fullname)                 /* Non-existent or directory    */
        !          3433:         return  FALSE;
        !          3434:     if (standard && included( fullname))        /* Once included    */
        !          3435:         goto  true;
        !          3436:
        !          3437:     if ((max_open != 0 && max_open <= include_nest)
        !          3438:                             /* Exceed the known limit of open files */
        !          3439:             || ((fp = fopen( fullname, "r")) == NULL && errno == EMFILE)) {
        !          3440:                             /* Reached the limit for the first time */
        !          3441:         if (mcpp_debug & PATH) {
        !          3442: #if HOST_COMPILER == BORLANDC
        !          3443:             if (include_nest == FOPEN_MAX - 5)
        !          3444: #else
        !          3445:             if (max_open == 0)
        !          3446: #endif
        !          3447:                 mcpp_fprintf( DBG,
        !          3448:     "#include nest reached at the maximum of system: %d, returned errno: %d\n"
        !          3449:                     , include_nest, errno);
        !          3450:         }
        !          3451:         /*
        !          3452:          * Table of open files is full.
        !          3453:          * Remember the file position and close the includer.
        !          3454:          * The state will be restored by get_line() on end of the included.
        !          3455:          */
        !          3456:         file->pos = ftell( file->fp);
        !          3457:         fclose( file->fp);
        !          3458:         /* In case of failure, re-open the includer */
        !          3459:         if ((fp = fopen( fullname, "r")) == NULL) {
        !          3460:             file->fp = fopen( cur_fullname, "r");
        !          3461:             fseek( file->fp, file->pos, SEEK_SET);
        !          3462:             goto  false;
        !          3463:         }
        !          3464:         if (max_open == 0)      /* Remember the limit of the system */
        !          3465:             max_open = include_nest;
        !          3466:     } else if (fp == NULL)                  /* No read permission   */
        !          3467:         goto  false;
        !          3468:     /* Truncate buffer of the includer to save memory   */
        !          3469:     len = (int) (file->bptr - file->buffer);
        !          3470:     if (len) {
        !          3471:         file->buffer = xrealloc( file->buffer, len + 1);
        !          3472:         file->bptr = file->buffer + len;
        !          3473:     }
        !          3474:
        !          3475:     if (! include_opt)
        !          3476:         sharp( NULL, 0);    /* Print includer's line num and fname  */
        !          3477:     add_file( fp, src_dir, filename, fullname, include_opt);
        !          3478:     /* Add file-info to the linked list.  'infile' has been just renewed    */
        !          3479:     /*
        !          3480:      * Remember the directory for #include_next.
        !          3481:      * Note: inc_dirp is restored to the parent includer's directory
        !          3482:      *   by get_ch() when the current includer is finished.
        !          3483:      */
        !          3484:     infile->dirp = inc_dirp = dirp;
        !          3485: #if 0   /* This part is only for debugging  */
        !          3486:     chk_dirp( dirp);
        !          3487: #endif
        !          3488: #if COMPILER == GNUC
        !          3489:     if ((**dirp != EOS && sys_dirp <= dirp && dirp <= incend)
        !          3490: #if SYSTEM == SYS_MAC
        !          3491:             || sys_frame
        !          3492: #endif
        !          3493:             )
        !          3494:         infile->sys_header = TRUE;      /* Found in a system header dir     */
        !          3495:     else
        !          3496:         infile->sys_header = FALSE;
        !          3497: #endif
        !          3498:     cur_fullname = fullname;
        !          3499:
        !          3500:     if (option_flags.z) {
        !          3501:         no_output++;        /* Don't output the included file       */
        !          3502:         if (include_nest == 2)
        !          3503:             mcpp_fprintf( OUT, "#include \"%s\"\n", fullname);
        !          3504:             /* Output #include line instead, if it is in main source file   */
        !          3505:     } else if (! include_opt) {     /* Do not sharp() on -include   */
        !          3506:         src_line = 1;                   /* Working on line 1 now    */
        !          3507:         sharp( NULL, 1);    /* Print out the included file name     */
        !          3508:     }
        !          3509:     src_line = 0;                       /* To read the first line   */
        !          3510:
        !          3511:     if (mkdep && ((mkdep & MD_SYSHEADER) || ! infile->sys_header))
        !          3512:         put_depend( fullname);          /* Output dependency line   */
        !          3513:
        !          3514: true:
        !          3515:     return  TRUE;
        !          3516: false:
        !          3517:     free( fullname);
        !          3518:     return  FALSE;
        !          3519: }
        !          3520:
        !          3521: void    add_file(
        !          3522:     FILE *      fp,                         /* Open file pointer    */
        !          3523:     const char *    src_dir,                /* Directory of source  */
        !          3524:     const char *    filename,               /* Name of the file     */
        !          3525:     const char *    fullname,               /* Full path list       */
        !          3526:     int         include_opt         /* File specified by -include option    */
        !          3527: )
        !          3528: /*
        !          3529:  * Initialize tables for this open file.  This is called from open_file()
        !          3530:  * (for #include files), and from the entry to MCPP to open the main input
        !          3531:  * file.  It calls a common routine get_file() to build the FILEINFO
        !          3532:  * structure which is used to read characters.
        !          3533:  */
        !          3534: {
        !          3535:     FILEINFO *      file;
        !          3536:     const char *    too_many_include_nest =
        !          3537:             "More than %.0s%ld nesting of #include";    /* _F_ _W4_ */
        !          3538:
        !          3539:     filename = set_fname( filename);    /* Search or append to fnamelist[]  */
        !          3540:     fullname = set_fname( fullname);    /* Search or append to fnamelist[]  */
        !          3541:     file = get_file( filename, src_dir, fullname, (size_t) NBUFF, include_opt);
        !          3542:                                         /* file == infile           */
        !          3543:     file->fp = fp;                      /* Better remember FILE *   */
        !          3544:     cur_fname = filename;
        !          3545:
        !          3546:     if (include_nest >= INCLUDE_NEST)   /* Probably recursive #include      */
        !          3547:         cfatal( too_many_include_nest, NULL, (long) INCLUDE_NEST, NULL);
        !          3548:     if (standard && (warn_level & 4)
        !          3549:             && include_nest == std_limits.inc_nest + 1)
        !          3550:         cwarn( too_many_include_nest, NULL, (long) std_limits.inc_nest, NULL);
        !          3551:     include_nest++;
        !          3552: }
        !          3553:
        !          3554: static const char *     set_fname(
        !          3555:     const char *    filename
        !          3556: )
        !          3557: /*
        !          3558:  * Register the source filename to fnamelist[].
        !          3559:  * Search fnamelist[] for filename or append filename to fnamelist[].
        !          3560:  * Returns the pointer.
        !          3561:  * file->real_fname and file->full_fname points into fnamelist[].
        !          3562:  */
        !          3563: {
        !          3564:     INC_LIST *  fnamep;
        !          3565:     size_t      fnamelen;
        !          3566:
        !          3567:     if (fnamelist == NULL) {            /* Should be initialized    */
        !          3568:         max_fnamelist = INIT_NUM_FNAMELIST;
        !          3569:         fnamelist = (INC_LIST *) xmalloc( sizeof (INC_LIST) * max_fnamelist);
        !          3570:         fname_end = &fnamelist[ 0];
        !          3571:     } else if (fname_end - fnamelist >= max_fnamelist) {
        !          3572:                                 /* Buffer full: double the elements */
        !          3573:         fnamelist = (INC_LIST *) xrealloc( (void *) fnamelist
        !          3574:                 , sizeof (INC_LIST) * max_fnamelist * 2);
        !          3575:         fname_end = &fnamelist[ max_fnamelist];
        !          3576:         max_fnamelist *= 2;
        !          3577:     }
        !          3578:
        !          3579:     /* Register the filename in fnamelist[] */
        !          3580:     fnamelen = strlen( filename);
        !          3581:     for (fnamep = fnamelist; fnamep < fname_end; fnamep++) {
        !          3582:         if (fnamep->len == fnamelen && str_case_eq( fnamep->name, filename))
        !          3583:             return  filename;           /* Already registered       */
        !          3584:     }
        !          3585:     fname_end->name = xmalloc( fnamelen + 1);
        !          3586:     filename = strcpy( fname_end->name, filename);
        !          3587:                                 /* Global pointer for get_file()    */
        !          3588:     fname_end->len = fnamelen;
        !          3589:     fname_end++;
        !          3590:
        !          3591:     return  filename;
        !          3592: }
        !          3593:
        !          3594: #if SYSTEM == SYS_MAC
        !          3595: #if COMPILER == GNUC
        !          3596:
        !          3597: /* Routines to search "header map" file of Xcode / Apple-GCC.       */
        !          3598: /* search_header_map() and hmap_hash() were written referring to    */
        !          3599: /* c-incpath.c of Apple-GCC-4.0.1.                                  */
        !          3600:
        !          3601: static char *   search_header_map(
        !          3602:     const char *    hmap_file,              /* Header map file      */
        !          3603:     const char *    filename,               /* Filename to search   */
        !          3604:     char *          pathlist        /* Buffer for a found pathlist  */
        !          3605: )
        !          3606: /*
        !          3607:  * Search a table in "header map" file for a header.
        !          3608:  */
        !          3609: {
        !          3610:     struct stat     stat_buf;
        !          3611:     FILE *          fp;
        !          3612:     size_t          fsize;
        !          3613:     const char *    contents;
        !          3614:     struct hmap_header_map *    hmap;
        !          3615:     struct hmap_bucket *        buckets;
        !          3616:     const char *    strings;
        !          3617:     uint32          mask;
        !          3618:     uint32          key_offs;
        !          3619:     uint32          i;
        !          3620:
        !          3621:     stat( hmap_file, &stat_buf);            /* Get size of the file */
        !          3622:     fsize = stat_buf.st_size;
        !          3623:     contents = xmalloc( fsize + 1);
        !          3624:     fp = fopen( hmap_file, "r");
        !          3625:     fread( contents, fsize, 1, fp);     /* Read whole of the file at once   */
        !          3626:     hmap = (struct hmap_header_map *) contents;
        !          3627:
        !          3628:     strings = ((const char *) hmap) + hmap->strings_offset;
        !          3629:     buckets = hmap->buckets;
        !          3630:     mask = hmap->capacity - 1;
        !          3631:     i = hmap_hash( filename) & mask;
        !          3632:     while ((key_offs = buckets[ i].key) != 0) {
        !          3633:         if (str_case_eq( filename, strings + key_offs)) {
        !          3634:             /* The names match.  Make path-list.    */
        !          3635:             char *  cp = stpcpy( pathlist, strings + buckets[ i].value.prefix);
        !          3636:             strcpy( cp, strings + buckets[ i].value.suffix);
        !          3637:             break;
        !          3638:         }
        !          3639:         i = ++i & mask;
        !          3640:     }
        !          3641:     free( contents);
        !          3642:     return  key_offs ? pathlist : NULL;
        !          3643: }
        !          3644:
        !          3645: static unsigned hmap_hash(
        !          3646:     const char *    fname                   /* header name          */
        !          3647: )
        !          3648: /*
        !          3649:  * Get hash value for the fname.
        !          3650:  */
        !          3651: {
        !          3652:     const char *    sp;
        !          3653:     unsigned        hash_code = 0;
        !          3654:
        !          3655:     for (sp = fname; *sp; sp++)
        !          3656:         hash_code += tolower( *sp & 0xFF) * 13;
        !          3657:     return  hash_code;
        !          3658: }
        !          3659: #endif  /* COMPILER == GNUC */
        !          3660:
        !          3661: static void     init_framework( void)
        !          3662: /*
        !          3663:  * Initialize framework[].
        !          3664:  */
        !          3665: {
        !          3666:     char *  framework_dir;
        !          3667:     /* Some frameworks may have been already specified by -F option.    */
        !          3668:     sys_framework = num_framework;      /* These are system frameworks  */
        !          3669: #ifdef  FRAMEWORK1
        !          3670:     framework_dir = norm_dir( FRAMEWORK1, TRUE);
        !          3671:     if (framework_dir)
        !          3672:         framework[ num_framework++] = framework_dir;
        !          3673: #endif
        !          3674: #ifdef  FRAMEWORK2
        !          3675:     framework_dir = norm_dir( FRAMEWORK2, TRUE);
        !          3676:     if (framework_dir)
        !          3677:         framework[ num_framework++] = framework_dir;
        !          3678: #endif
        !          3679: #ifdef  FRAMEWORK3
        !          3680:     framework_dir = norm_dir( FRAMEWORK3, TRUE);
        !          3681:     if (framework_dir)
        !          3682:         framework[ num_framework++] = framework_dir;
        !          3683: #endif
        !          3684:     if (num_framework >= MAX_FRAMEWORK) {
        !          3685:         mcpp_fputs( "Too many Framework directories.", ERR);
        !          3686:         longjmp( error_exit, -1);
        !          3687:     }
        !          3688: }
        !          3689:
        !          3690: static const char *     dot_frame = ".framework";
        !          3691:
        !          3692: static int      search_framework(
        !          3693:     char *  filename
        !          3694: )
        !          3695: /*
        !          3696:  * Search "Framework" directories.
        !          3697:  * 'frame/header.h' is converted to
        !          3698:  * '/System/Library/Frameworks/frame.framework/Headers/header.h',
        !          3699:  * '/System/Library/Frameworks/frame.framework/PrivateHeaders/header.h',
        !          3700:  * and so on.
        !          3701:  */
        !          3702: {
        !          3703:     char        fullname[ PATHMAX + 1];
        !          3704:     FILEINFO *  file;
        !          3705:     char *      frame, * fname, * cp1, * cp2;
        !          3706:     int         sys_frame = FALSE;
        !          3707:     int         i;
        !          3708:
        !          3709:     cp1 = cp2 = strchr( filename, PATH_DELIM);
        !          3710:     /*
        !          3711:      * 'filename' should be <frame/header> format or sometimes
        !          3712:      *      <frame/dir/header>.
        !          3713:      * e.g.: <Foundation/Foundation.h>, <CarbonCore/OSUtils.h>
        !          3714:      *      or <IOKit/pwr_mgt/IOPMLib.h>.
        !          3715:      */
        !          3716:     if (! cp1)
        !          3717:         return  FALSE;
        !          3718:     *cp1 = EOS;
        !          3719:     frame = filename;
        !          3720:     fname = cp1 + 1;
        !          3721:
        !          3722:     /* Search framework[] directories   */
        !          3723:     for (i = 0; i < num_framework; i++) {
        !          3724:         cp1 = stpcpy( fullname, framework[ i]);
        !          3725:                     /* 'fullname' e.g.: /System/Library/Frameworks/ */
        !          3726:         if (search_subdir( fullname, cp1, frame, fname, sys_framework <= i))
        !          3727:             return  TRUE;
        !          3728:     }
        !          3729:
        !          3730:     /*
        !          3731:      * Search subframework dirs searching its possible parent framework
        !          3732:      * starting from current file's directory to its ancestors.
        !          3733:      * Header file in subframework directories should be included only
        !          3734:      * by its parent or sibling framework headers.
        !          3735:      */
        !          3736:     for (i = sys_framework; i < num_framework; i++) {
        !          3737:         size_t  frame_len, fname_len;
        !          3738:         frame_len = strlen( framework[ i]);
        !          3739:         fname_len = strlen( infile->real_fname);
        !          3740:         if (fname_len <= frame_len)
        !          3741:             continue;
        !          3742:         if (memcmp( framework[ i], infile->real_fname, frame_len) == 0) {
        !          3743:             sys_frame = TRUE;
        !          3744:             break;
        !          3745:         }
        !          3746:     }
        !          3747:     for (file = infile; file; file = file->parent) {
        !          3748:         const char *    dot;
        !          3749:         size_t  len;
        !          3750:
        !          3751:         if (! file->fp)
        !          3752:             continue;
        !          3753:         dot = strstr( file->real_fname, dot_frame);
        !          3754:         if (! dot)
        !          3755:             continue;
        !          3756:         len = dot - file->real_fname + strlen( dot_frame) + 1;
        !          3757:         memcpy( fullname, file->real_fname, len);
        !          3758:         cp1 = fullname + len;
        !          3759:         cp1 = stpcpy( cp1, "Frameworks/");
        !          3760:         /* 'fullname' e.g.:                                             */
        !          3761:         /* /System/Library/Frameworks/Foundation.framework/Frameworks/  */
        !          3762:         if (search_subdir( fullname, cp1, frame, fname, sys_frame))
        !          3763:             return  TRUE;
        !          3764:     }
        !          3765:
        !          3766:     *cp2 = PATH_DELIM;      /* Restore original include file format */
        !          3767:
        !          3768:     return  FALSE;
        !          3769: }
        !          3770:
        !          3771: static int      search_subdir(
        !          3772:     char *  fullname,               /* Buffer for path-list to open */
        !          3773:     char *  cp,                     /* Latter half of 'fullname'    */
        !          3774:     char *  frame,                  /* 'frame' of <frame/header>    */
        !          3775:     char *  fname,                  /* 'header' of <frame/header>   */
        !          3776:                 /* or sometimes 'dir/header' of <frame/dir/header>  */
        !          3777:     int     sys_frame               /* System framework header ?    */
        !          3778: )
        !          3779: /*
        !          3780:  * Make path-list and try to open.
        !          3781:  */
        !          3782: {
        !          3783:     static const char *     subdir[] = { "Headers", "PrivateHeaders", NULL};
        !          3784:     int     j, n;
        !          3785:
        !          3786:     cp += sprintf( cp, "%s%s%c", frame, dot_frame, PATH_DELIM);
        !          3787:     for (j = 0; subdir[ j] != NULL; j++) {
        !          3788:         n = sprintf( cp, "%s%c%s", subdir[ j], PATH_DELIM, fname);
        !          3789:         /*
        !          3790:          * 'fullname' is for example:
        !          3791:          * /System/Library/Frameworks/Foundation.framework/Headers/
        !          3792:          *      Foundation.h,
        !          3793:          * /System/Library/Frameworks/Foundation.framework/Frameworks/
        !          3794:          *      CarbonCore.framework/Headers/OSUtils.h,
        !          3795:          * or /System/Library/Frameworks/IOKit.framework/Headers/
        !          3796:          *      pwr_mgt/IOPMLib.h.
        !          3797:          * Pass this as one filename argument to open_file() rather than
        !          3798:          * deviding to directory part and file part.  The first argument to
        !          3799:          * open_file() which is a pointer to the directory part is remembered
        !          3800:          * by FILEINFO struct.  But, 'fullname' is over-written each time,
        !          3801:          * and the former path-list is lost soon.  Therefore, it cannot be
        !          3802:          * passed as the first argument.  In addition, though the first
        !          3803:          * argument to open_file() is needed for #include_next, this directive
        !          3804:          * has no meaning in framework.
        !          3805:          */
        !          3806:         if ((cp - fullname) + n > PATHMAX)
        !          3807:             cfatal( "Too long framework path", NULL, 0L, NULL); /* _F_  */
        !          3808:         if (open_file( &null, NULL, fullname, FALSE, FALSE, sys_frame))
        !          3809:             return  TRUE;
        !          3810:     }
        !          3811:     return  FALSE;
        !          3812: }
        !          3813:
        !          3814: #endif  /* SYSTEM == SYS_MAC    */
        !          3815:
        !          3816: #if 0   /* This part is only for debugging  */
        !          3817: static int  chk_dirp(
        !          3818:     const char **   dirp
        !          3819: )
        !          3820: /*
        !          3821:  * Check the validity of include directory specified for open_file().
        !          3822:  * Called only from open_file().
        !          3823:  */
        !          3824: {
        !          3825:     const char **   ip;
        !          3826:
        !          3827:     if (dirp == &null)
        !          3828:         return  TRUE;
        !          3829:
        !          3830:     for (ip = incdir; ip < incend; ip++)
        !          3831:         if (dirp == ip)
        !          3832:             break;
        !          3833:     if (ip == incend) {
        !          3834: #if COMPILER == MSC
        !          3835:         FILEINFO *  pfile = infile->parent;
        !          3836:         if (pfile) {
        !          3837:             while ((pfile = pfile->parent) != NULL) {
        !          3838:                 /* Search each parent includer's directory  */
        !          3839:                 if (dirp == pfile->dirp)
        !          3840:                     break;
        !          3841:             }
        !          3842:         }
        !          3843:         if (! pfile)
        !          3844: #endif
        !          3845: #if COMPILER == GNUC
        !          3846:         const char **   qdir;
        !          3847:         for (qdir = quote_dir; qdir < quote_dir_end; qdir++) {
        !          3848:             if (dirp == qdir)
        !          3849:                 break;
        !          3850:         }
        !          3851:         if (qdir == quote_dir_end)
        !          3852: #endif
        !          3853:         {
        !          3854:             cfatal( "Bug: *dirp:%s is invalid", *dirp, 0L, NULL);
        !          3855:             return  FALSE;
        !          3856:         }
        !          3857:     }
        !          3858:     return  TRUE;
        !          3859: }
        !          3860: #endif
        !          3861:
        !          3862: void    sharp(
        !          3863:     FILEINFO *  sharp_file,
        !          3864:     int         flag        /* Flag to append to the line for GCC   */
        !          3865: )
        !          3866: /*
        !          3867:  * Output a line number line.
        !          3868:  * 'file' is 'sharp_file' if specified,
        !          3869:  * else (i.e. 'sharp_file' is NULL) 'infile'.
        !          3870:  */
        !          3871: {
        !          3872:     static FILEINFO *   sh_file;
        !          3873:     static int  sh_line;
        !          3874:     FILEINFO *  file;
        !          3875:     int         line;
        !          3876:
        !          3877:     file = sharp_file ? sharp_file : infile;
        !          3878:     if (! file)
        !          3879:         return;
        !          3880:     while (! file->fp)
        !          3881:         file = file->parent;
        !          3882:     line = sharp_file ? sharp_file->line : src_line;
        !          3883:     if (no_output || option_flags.p || file == NULL
        !          3884:             || (file == sh_file && line == sh_line))
        !          3885:         goto  sharp_exit;
        !          3886:     sh_file = file;
        !          3887:     sh_line = line;
        !          3888:     if (keep_comments)
        !          3889:         mcpp_fputc( '\n', OUT);         /* Ensure to be on line top */
        !          3890:     if (std_line_prefix)
        !          3891:         mcpp_fprintf( OUT, "#line %ld", line);
        !          3892:     else
        !          3893:         mcpp_fprintf( OUT, "%s%ld", LINE_PREFIX, line);
        !          3894:     cur_file( file, sharp_file, flag);
        !          3895:     mcpp_fputc( '\n', OUT);
        !          3896: sharp_exit:
        !          3897:     wrong_line = FALSE;
        !          3898: }
        !          3899:
        !          3900: static void cur_file(
        !          3901:     FILEINFO *  file,                   /* infile or sharp_file     */
        !          3902:     FILEINFO *  sharp_file,             /* The 'file' or NULL       */
        !          3903:     int         flag                    /* Flag to append for GCC   */
        !          3904: )
        !          3905: /*
        !          3906:  * Output current source file name and line number.
        !          3907:  * Called only from sharp() above.
        !          3908:  */
        !          3909: {
        !          3910:     const char *    name;
        !          3911:
        !          3912:     if (mcpp_debug & MACRO_CALL) {  /* In macro notification mode   */
        !          3913:         if (sharp_file)                         /* Main input file  */
        !          3914:             name = file->filename;
        !          3915:         else                /* Output full-path-list, normalized    */
        !          3916:             name = cur_fullname;
        !          3917:     } else {                /* Usually, the path not "normalized"   */
        !          3918:         if (sharp_file) {                       /* Main input file  */
        !          3919:             name = file->filename;
        !          3920:         } else if (str_eq( file->filename, file->real_fname)) {
        !          3921:             sprintf( work_buf, "%s%s", *(file->dirp), cur_fname);
        !          3922:             name = work_buf;
        !          3923:         } else {            /* Changed by '#line fname' directive   */
        !          3924:             name = file->filename;
        !          3925:         }
        !          3926:     }
        !          3927:     if (sharp_filename == NULL || ! str_eq( name, sharp_filename)) {
        !          3928:         if (sharp_filename != NULL)
        !          3929:             free( sharp_filename);
        !          3930:         sharp_filename = save_string( name);
        !          3931:     }
        !          3932:     mcpp_fprintf( OUT, " \"%s\"", name);
        !          3933: #if COMPILER == GNUC
        !          3934:     if (! std_line_prefix) {
        !          3935:         if (flag) {
        !          3936:             mcpp_fputc( ' ', OUT);
        !          3937:             mcpp_fputc( '0' + flag, OUT);
        !          3938:         }
        !          3939:         if (file->sys_header)
        !          3940:             mcpp_fputs( " 3", OUT);
        !          3941:     }
        !          3942: #endif
        !          3943: }
        !          3944:
        !          3945: #if SYS_FAMILY == SYS_WIN
        !          3946:
        !          3947: static char *   bsl2sl(
        !          3948:     char * filename
        !          3949: )
        !          3950: /*
        !          3951:  * Convert '\\' in the path-list to '/'.
        !          3952:  */
        !          3953: {
        !          3954:     static int  diagnosed = FALSE;
        !          3955:     char *  cp;
        !          3956:
        !          3957:     cp = filename;
        !          3958:
        !          3959:     while (*cp) {
        !          3960:         if (bsl_in_mbchar) {
        !          3961:             int     c;
        !          3962:             c = *cp & UCHARMAX;
        !          3963:             if (char_type[ c] & mbchk) {    /* First byte of MBCHAR */
        !          3964:                 char    tmp[ PATHMAX];
        !          3965:                 char *  tp = tmp;
        !          3966:                 *tp++ = *cp++;
        !          3967:                 mb_read( c, &cp, &tp);
        !          3968:                             /* Read over the multi-byte characters  */
        !          3969:                 continue;
        !          3970:             }
        !          3971:         }
        !          3972:         if (*cp == '\\') {
        !          3973:             *cp++ = PATH_DELIM;
        !          3974:             if (!diagnosed && (warn_level & 2) && (warn_level != -1)) {
        !          3975:                             /* Backslash in source program          */
        !          3976:                 cwarn( "Converted \\ to %s", "/", 0L, NULL);        /* _W2_ */
        !          3977:                     diagnosed = TRUE;       /* Diagnose only once   */
        !          3978:             }
        !          3979:         } else {
        !          3980:             cp++;
        !          3981:         }
        !          3982:     }
        !          3983:
        !          3984:     return  filename;
        !          3985: }
        !          3986:
        !          3987: #endif  /* SYS_FAMILY == SYS_WIN    */
        !          3988:
        !          3989: static const char * const   unknown_arg =
        !          3990:         "Unknown argument \"%s\"";      /*_W1_*/
        !          3991: static const char * const   not_ident =
        !          3992:         "Not an identifier \"%s\"";     /*_W1_*/
        !          3993:
        !          3994: static int  is_junk( void)
        !          3995: /*
        !          3996:  * Check the trailing junk in a directive line.
        !          3997:  * This routine is never called in OLD_PREP mode.
        !          3998:  */
        !          3999: {
        !          4000:     int     c;
        !          4001:
        !          4002:     c = skip_ws();
        !          4003:     unget_ch();
        !          4004:     if (c != '\n') {                        /* Trailing junk        */
        !          4005:         if (warn_level & 1)
        !          4006:             cwarn( unknown_arg, infile->bptr, 0L, NULL);
        !          4007:         return TRUE;
        !          4008:     } else {
        !          4009:         return FALSE;
        !          4010:     }
        !          4011: }
        !          4012:
        !          4013: #define PUSH    1
        !          4014: #define POP    -1
        !          4015:
        !          4016: #define __SETLOCALE     1       /* #pragma __setlocale( "encoding") */
        !          4017: #define SETLOCALE       2       /* #pragma setlocale( "encoding")   */
        !          4018:
        !          4019: void    do_pragma( void)
        !          4020: /*
        !          4021:  * Process the #pragma lines.
        !          4022:  * 1. Process the sub-directive for MCPP.
        !          4023:  * 2. Pass the line to the compiler-proper.
        !          4024:  *      #pragma MCPP put_defines, #pragma MCPP preprocess,
        !          4025:  *      #pragma MCPP preprocessed and #pragma once are, however, not put
        !          4026:  *      out so as not to duplicate output when re-preprocessed.
        !          4027:  * When EXPAND_PRAGMA == TRUE and (__STDC_VERSION__ >= 199901L or
        !          4028:  * __cplusplus >= 199901L), the line is subject to macro expansion unless
        !          4029:  * the next to 'pragma' token is one of 'STDC', 'GCC' or 'MCPP'.
        !          4030:  */
        !          4031: {
        !          4032:     int         c;
        !          4033:     int         warn = FALSE;               /* Necessity of warning */
        !          4034:     int         token_type;
        !          4035:     char *      bp;                         /* Pointer to argument  */
        !          4036:     char *      tp;
        !          4037:     FILEINFO *  file;
        !          4038:
        !          4039:     wrong_line = TRUE;                      /* In case of error     */
        !          4040:     c = skip_ws();
        !          4041:     bp = infile->bptr - 1;  /* Remember token to pass to compiler   */
        !          4042:     if (c == '\n') {
        !          4043:         if (warn_level & 1)
        !          4044:             cwarn( "No sub-directive", NULL, 0L, NULL);     /* _W1_ */
        !          4045:         unget_ch();
        !          4046:         return;
        !          4047:     }
        !          4048:     token_type = scan_token( c, (tp = work_buf, &tp), work_end);
        !          4049: #if EXPAND_PRAGMA
        !          4050: #if COMPILER == MSC
        !          4051:     if (token_type == NAM
        !          4052:             && !str_eq( identifier, "STDC") && !str_eq( identifier, "MCPP")) {
        !          4053: #else
        !          4054:     if (stdc3 && token_type == NAM
        !          4055:             && !str_eq( identifier, "STDC") && !str_eq( identifier, "MCPP")) {
        !          4056: #endif
        !          4057:         DEFBUF *        defp;
        !          4058:         char *          mp;
        !          4059:         char *          mp_end;
        !          4060:         LINE_COL        line_col = { 0L, 0};
        !          4061:
        !          4062:         bp = mp = xmalloc( (size_t)(NMACWORK + IDMAX));
        !          4063:                                     /* Buffer for macro expansion   */
        !          4064:         mp_end = mp + NMACWORK;
        !          4065:         tp = stpcpy( mp, identifier);
        !          4066:         do {                /* Expand all the macros in the line    */
        !          4067:             int     has_pragma;
        !          4068:             if (token_type == NAM && (defp = is_macro( &tp)) != NULL) {
        !          4069:                 tp = expand_macro( defp, bp, mp_end, line_col, & has_pragma);
        !          4070:                 if (has_pragma)
        !          4071:                 cerror( "_Pragma operator found in #pragma line"    /* _E_  */
        !          4072:                             , NULL, 0L, NULL);
        !          4073:                 if (! stdc3 && (warn_level & 2))
        !          4074:                     cwarn(
        !          4075:                 "\"%s\" is macro expanded in other than C99 mode"   /* _W2_ */
        !          4076:                             , identifier, 0L, NULL);
        !          4077:             }
        !          4078:             token_type = scan_token( c = get_ch(), (bp = tp, &tp), mp_end);
        !          4079:         } while (c != '\n');
        !          4080:         unget_string( mp, NULL);                    /* To re-read   */
        !          4081:         free( mp);
        !          4082:         c = skip_ws();
        !          4083:         bp = infile->bptr - 1;
        !          4084:         token_type = scan_token( c, (tp = work_buf, &tp), work_end);
        !          4085:     }
        !          4086: #endif
        !          4087:     if (token_type != NAM) {
        !          4088:         if (warn_level & 1)
        !          4089:             cwarn( not_ident, work_buf, 0L, NULL);
        !          4090:         goto  skip_nl;
        !          4091:     } else if (str_eq( identifier, "once")) {   /* #pragma once     */
        !          4092:        if (! is_junk()) {
        !          4093:             file = infile;
        !          4094:             while (file->fp == NULL)
        !          4095:                 file = file->parent;
        !          4096:             do_once( file->full_fname);
        !          4097:             goto  skip_nl;
        !          4098:         }
        !          4099:     } else if (str_eq( identifier, "MCPP")) {
        !          4100:         if (scan_token( skip_ws(), (tp = work_buf, &tp), work_end) != NAM) {
        !          4101:             if (warn_level & 1)
        !          4102:                 cwarn( not_ident, work_buf, 0L, NULL);
        !          4103:         }
        !          4104:         if (str_eq( identifier, "put_defines")) {
        !          4105:             if (! is_junk())
        !          4106:                 dump_def( TRUE, FALSE); /* #pragma MCPP put_defines */
        !          4107:         } else if (str_eq( identifier, "preprocess")) {
        !          4108:             if (! is_junk())            /* #pragma MCPP preprocess  */
        !          4109:                 mcpp_fputs( "#pragma MCPP preprocessed\n", OUT);
        !          4110:                     /* Just putout the directive    */
        !          4111:         } else if (str_eq( identifier, "preprocessed")) {
        !          4112:             if (! is_junk()) {          /* #pragma MCPP preprocessed*/
        !          4113:                 skip_nl();
        !          4114:                 do_preprocessed();
        !          4115:                 return;
        !          4116:             }
        !          4117:         } else if (str_eq( identifier, "warning")) {
        !          4118:                                         /* #pragma MCPP warning     */
        !          4119:             cwarn( infile->buffer, NULL, 0L, NULL);
        !          4120:         } else if (str_eq( identifier, "push_macro")) {
        !          4121:             push_or_pop( PUSH);         /* #pragma MCPP push_macro  */
        !          4122:         } else if (str_eq( identifier, "pop_macro")) {
        !          4123:             push_or_pop( POP);          /* #pragma MCPP pop_macro   */
        !          4124:         } else if (str_eq( identifier, "debug")) {
        !          4125:             do_debug( TRUE);            /* #pragma MCPP debug       */
        !          4126:         } else if (str_eq( identifier, "end_debug")) {
        !          4127:             do_debug( FALSE);           /* #pragma MCPP end_debug   */
        !          4128:         } else {
        !          4129:             warn = TRUE;
        !          4130:         }
        !          4131:         if (warn && (warn_level & 1))
        !          4132:             cwarn( unknown_arg, identifier, 0L, NULL);
        !          4133:         goto  skip_nl;                  /* Do not putout the line   */
        !          4134: #if COMPILER == GNUC
        !          4135:     /* The #pragma lines for GCC is skipped not to confuse cc1.     */
        !          4136:     } else if (str_eq( identifier, "GCC")) {    /* #pragma GCC *    */
        !          4137:         if (scan_token( skip_ws(), (tp = work_buf, &tp), work_end) == NAM) {
        !          4138:             if (str_eq( identifier, "poison")
        !          4139:                     || str_eq( identifier, "dependency")) {
        !          4140:                 if (warn_level & 2)
        !          4141:                     cwarn( "Skipped the #pragma line"       /*_W2_  */
        !          4142:                             , NULL, 0L, NULL);
        !          4143:                 goto skip_nl;
        !          4144:             } else if (str_eq( identifier, "system_header")) {
        !          4145:                 infile->sys_header = TRUE;      /* Mark as a system header  */
        !          4146:                 goto skip_nl;
        !          4147:             }
        !          4148:         }
        !          4149: #endif
        !          4150:
        !          4151: #if COMPILER == MSC
        !          4152:     } else if (str_eq( identifier, "setlocale")) {
        !          4153:         if (skip_ws() == '('
        !          4154:                 && scan_token( skip_ws(), (tp = work_buf, &tp), work_end)
        !          4155:                     == STR
        !          4156:                 && skip_ws() == ')') {
        !          4157:             if (! is_junk()) {
        !          4158:                 work_buf[ 0] = *(tp - 1) = '\0';
        !          4159:                 set_encoding( work_buf + 1, NULL, SETLOCALE);
        !          4160:                 work_buf[ 0] = *(tp - 1) = '"';
        !          4161:             }   /* else warned by is_junk() */
        !          4162:         } else {
        !          4163:             warn = TRUE;
        !          4164:         }
        !          4165: #else   /* COMPILER != MSC  */
        !          4166:     } else if (str_eq( identifier, "__setlocale")) {
        !          4167:         if (skip_ws() == '('
        !          4168:                 && scan_token( skip_ws(), (tp = work_buf, &tp), work_end)
        !          4169:                         == STR
        !          4170:                 && skip_ws() == ')') {
        !          4171:             if (! is_junk()) {              /* #pragma __setlocale  */
        !          4172:                 work_buf[ 0] = *(tp - 1) = '\0';
        !          4173:                 set_encoding( work_buf + 1, NULL, __SETLOCALE);
        !          4174:                 work_buf[ 0] = *(tp - 1) = '"';
        !          4175:             }   /* else warned by is_junk() */
        !          4176:         } else {
        !          4177:             warn = TRUE;
        !          4178:         }
        !          4179: #endif
        !          4180:
        !          4181: #if COMPILER == MSC
        !          4182:     } else if (str_eq( identifier, "push_macro")) {
        !          4183:         push_or_pop( PUSH);
        !          4184:         goto  skip_nl;
        !          4185:     } else if (str_eq( identifier, "pop_macro")) {
        !          4186:         push_or_pop( POP);
        !          4187:         goto  skip_nl;
        !          4188: #endif
        !          4189:
        !          4190: #if COMPILER == LCC
        !          4191:     } else if (str_eq( identifier, "optimize")
        !          4192:                 && (skip_ws() == '(')
        !          4193:                 && (char_type[ (c = skip_ws()) & UCHARMAX] == DIG)
        !          4194:                 && (skip_ws() == ')')) {
        !          4195:         char    tmp[ 2];
        !          4196:
        !          4197:         tmp[ 0] = c;
        !          4198:         tmp[ 1] = EOS;
        !          4199:         look_and_install( optim_name, DEF_NOARGS_PREDEF, null, tmp);
        !          4200: #endif
        !          4201:
        !          4202: #if COMPILER == COMPILER_UNKNOWN
        !          4203:     /*
        !          4204:      * Write here any compiler-specific #pragma sub-directive which should
        !          4205:      * be processed by preprocessor.
        !          4206:      */
        !          4207: #endif
        !          4208:     }
        !          4209:
        !          4210:     if (warn) {
        !          4211:         if (warn_level & 1)
        !          4212:             cwarn( unknown_arg, identifier, 0L, NULL);
        !          4213:         goto  skip_nl;                  /* Do not putout the line   */
        !          4214:     }
        !          4215:
        !          4216:     sharp( NULL, 0);    /* Synchronize line number before output    */
        !          4217:     if (! no_output) {
        !          4218:         mcpp_fputs( "#pragma ", OUT);
        !          4219:         mcpp_fputs( bp, OUT);           /* Line is put out          */
        !          4220:     }
        !          4221: skip_nl: /* Don't use skip_nl() which skips to the newline in source file */
        !          4222:     while (get_ch() != '\n')
        !          4223:         ;
        !          4224: }
        !          4225:
        !          4226: static void do_once(
        !          4227:     const char *    fullname        /* Full-path-list of the header */
        !          4228: )
        !          4229: /*
        !          4230:  * Process #pragma once so as not to re-include the file later.
        !          4231:  * This directive has been imported from GCC V.1.* / cpp as an extension.
        !          4232:  */
        !          4233: {
        !          4234:     if (once_list == NULL) {                /* Should initialize    */
        !          4235:         max_once = INIT_NUM_ONCE;
        !          4236:         once_list = (INC_LIST *) xmalloc( sizeof (INC_LIST) * max_once);
        !          4237:         once_end = &once_list[ 0];
        !          4238:     } else if (once_end - once_list >= max_once) {
        !          4239:                                             /* Double the elements  */
        !          4240:         once_list = (INC_LIST *) xrealloc( (void *) once_list
        !          4241:                 , sizeof (INC_LIST) * max_once * 2);
        !          4242:         once_end = &once_list[ max_once];
        !          4243:         max_once *= 2;
        !          4244:     }
        !          4245:     once_end->name = fullname;
        !          4246:     once_end->len = strlen( fullname);
        !          4247:     once_end++;
        !          4248: }
        !          4249:
        !          4250: static int  included(
        !          4251:     const char *    fullname
        !          4252: )
        !          4253: /*
        !          4254:  * Has the file been once included ?
        !          4255:  * This routine is only called from open_file().
        !          4256:  */
        !          4257: {
        !          4258:     INC_LIST *  inc;
        !          4259:     size_t      fnamelen;
        !          4260:
        !          4261:     if (once_list == NULL)              /* No once file registered  */
        !          4262:         return  FALSE;
        !          4263:     fnamelen = strlen( fullname);
        !          4264:     for (inc = once_list; inc < once_end; inc++) {
        !          4265:         if (inc->len == fnamelen && str_case_eq( inc->name, fullname)) {
        !          4266:             /* Already included */
        !          4267:             if (mcpp_debug & PATH)
        !          4268:                 mcpp_fprintf( DBG, "Once included \"%s\"\n", fullname);
        !          4269:             return  TRUE;
        !          4270:         }
        !          4271:     }
        !          4272:     return  FALSE;                          /* Not yet included     */
        !          4273: }
        !          4274:
        !          4275: static void push_or_pop(
        !          4276:     int     direction
        !          4277: )
        !          4278: /* Process #pragma MCPP push_macro( "MACRO"),
        !          4279:  * #pragma MCPP pop_macro( "MACRO") for other compilers than Visual C,
        !          4280:  * and #pragma push_macro( "MACRO"), #pragma pop_macro( "MACRO") for Visual C.
        !          4281:  * Note:1. "push" count is set in defp->push.
        !          4282:  *      2. pushed definitions are inserted immediatly after the current
        !          4283:  *          definition of the same name.
        !          4284:  *      3. the definitions of a same name macro can be pushed multiple times.
        !          4285:  */
        !          4286: {
        !          4287:     char *          tp;
        !          4288:     DEFBUF **       prevp;
        !          4289:     DEFBUF *        defp;
        !          4290:     DEFBUF *        dp;
        !          4291:     int             cmp;
        !          4292:     size_t          s_name, s_def;
        !          4293:
        !          4294:     if (skip_ws() == '('
        !          4295:             && scan_token( skip_ws(), (tp = work_buf, &tp), work_end) == STR
        !          4296:             && skip_ws() == ')') {          /* Correct syntax       */
        !          4297:
        !          4298:         if (is_junk())
        !          4299:             return;
        !          4300:         s_name = strlen( work_buf) - 2;
        !          4301:         *(work_buf + s_name + 1) = '\0';
        !          4302:         memcpy( identifier, work_buf + 1, s_name + 1);
        !          4303:                                             /* Remove enclosing '"' */
        !          4304:         prevp = look_prev( identifier, &cmp);
        !          4305:         if (cmp == 0) { /* Current definition or pushed definition exists   */
        !          4306:             defp = *prevp;
        !          4307:             if (direction == PUSH) {/* #pragma push_macro( "MACRO") */
        !          4308:                 if (defp->push) {           /* No current definition*/
        !          4309:                     if (warn_level & 1)
        !          4310:                         cwarn( "\"%s\" is already pushed"   /* _W1_ */
        !          4311:                                 , identifier, 0L, NULL);
        !          4312:                     return;
        !          4313:                 }
        !          4314:                 /* Else the current definition exists.  Push it     */
        !          4315:                 s_def = sizeof (DEFBUF) + 3 + s_name
        !          4316:                         + strlen( defp->repl) + strlen( defp->fname);
        !          4317:                 if (mcpp_mode == STD)
        !          4318:                     s_def += strlen( defp->parmnames);
        !          4319:                 dp = (DEFBUF *) xmalloc( s_def);
        !          4320:                 memcpy( dp, defp, s_def);   /* Copy the definition  */
        !          4321:                 dp->link = *prevp;          /* Insert to linked-list*/
        !          4322:                 *prevp = dp;                /*      the pushed def  */
        !          4323:                 prevp = &dp->link;          /* Next link to search  */
        !          4324:             } else {                /* #pragma pop_macro( "MACRO")  */
        !          4325:                 if (defp->push == 0) {      /* Current definition   */
        !          4326:                     if (defp->link == NULL
        !          4327:                             || ! str_eq( identifier, defp->link->name)) {
        !          4328:                         if (warn_level & 1)
        !          4329:                             cwarn( "\"%s\" has not been pushed"     /* _W1_ */
        !          4330:                                     , identifier, 0L, NULL);
        !          4331:                         return;
        !          4332:                     } else {
        !          4333:                         *prevp = defp->link;
        !          4334:                                 /* Link the previous and the next   */
        !          4335:                         free( defp);
        !          4336:                             /* Delete the definition to enable popped def   */
        !          4337:                     }
        !          4338:                 }   /* Else no current definition exists    */
        !          4339:             }
        !          4340:             while ((defp = *prevp) != NULL) {
        !          4341:                 /* Increment or decrement "push" count of all pushed defs   */
        !          4342:                 if ((cmp = memcmp( defp->name, identifier, s_name)) > 0)
        !          4343:                     break;
        !          4344:                 defp->push += direction;        /* Increment or decrement   */
        !          4345:                 prevp = &defp->link;
        !          4346:             }
        !          4347:         } else {    /* No current definition nor pushed definition  */
        !          4348:             if (warn_level & 1)
        !          4349:                 cwarn( "\"%s\" has not been defined"        /* _W1_ */
        !          4350:                         , identifier, 0L, NULL);
        !          4351:         }
        !          4352:     } else {        /* Wrong syntax */
        !          4353:         if (warn_level & 1)
        !          4354:             cwarn( "Bad %s syntax", direction == PUSH       /* _W1_ */
        !          4355:                     ? "push_macro" : "pop_macro", 0L, NULL);
        !          4356:     }
        !          4357: }
        !          4358:
        !          4359: static void do_asm(
        !          4360:     int     asm_start                       /* #asm ?               */
        !          4361: )
        !          4362: /*
        !          4363:  * #asm, #endasm
        !          4364:  * Originally written for OS-9/09 Microware C.
        !          4365:  */
        !          4366: {
        !          4367:     if (! compiling)
        !          4368:         return;
        !          4369:     if (asm_start == (in_asm != 0L)) {
        !          4370:         if (in_asm)
        !          4371:             cerror( "In #asm block started at line %.0s%ld" /* _E_  */
        !          4372:                     , NULL, in_asm, NULL);
        !          4373:         else
        !          4374:             cerror( "Without #asm", NULL, 0L, NULL);        /* _E_  */
        !          4375:         skip_nl();
        !          4376:         unget_ch();
        !          4377:         return;
        !          4378:     }
        !          4379:     in_asm = asm_start ? src_line : 0L;
        !          4380: }
        !          4381:
        !          4382: void    do_old( void)
        !          4383: /*
        !          4384:  * Process the out-of-standard directives.
        !          4385:  * GCC permits #include_next and #warning even in STANDARD mode.
        !          4386:  */
        !          4387: {
        !          4388:     static const char * const   unknown
        !          4389:             = "Unknown #directive \"%s\"%.0ld%s";       /* _E_ _W8_ */
        !          4390:     static const char * const   ext
        !          4391:             = "%s is not allowed by Standard%.0ld%s";   /* _W2_ _W8_*/
        !          4392:
        !          4393: #if COMPILER == GNUC
        !          4394:     if (str_eq( identifier, "include_next")) {
        !          4395:         if ((compiling && (warn_level & 2))
        !          4396:                 || (! compiling && (warn_level & 8)))
        !          4397:             cwarn( ext, "#include_next", 0L
        !          4398:                     , compiling ? NULL : " (in skipped block)");
        !          4399:         if (! compiling)
        !          4400:             return;
        !          4401:         in_include = TRUE;
        !          4402:         do_include( TRUE);
        !          4403:         in_include = FALSE;
        !          4404:         return;
        !          4405:     } else if (str_eq( identifier, "warning")) {
        !          4406:         if ((compiling && (warn_level & 2))
        !          4407:                 || (! compiling && (warn_level & 8)))
        !          4408:             cwarn( ext, "#warning", 0L
        !          4409:                     , compiling ? NULL : " (in skipped block)");
        !          4410:         if (! compiling)
        !          4411:             return;
        !          4412:         cwarn( infile->buffer, NULL, 0L, NULL);
        !          4413:                                     /* Always output the warning    */
        !          4414:         skip_nl();
        !          4415:         unget_ch();
        !          4416:         return;
        !          4417:     } else if (str_eq( identifier, "ident") || str_eq( identifier, "sccs")) {
        !          4418:         if ((compiling && (warn_level & 1))
        !          4419:                 || (! compiling && (warn_level & 8))) {
        !          4420:             if (str_eq( identifier, "ident"))
        !          4421:                 cwarn(
        !          4422:     compiling ? "Ignored #ident" : "#ident (in skipped block)"  /* _W1_ _W8_*/
        !          4423:                         , NULL, 0L, NULL);
        !          4424:             else
        !          4425:                 cwarn(
        !          4426:     compiling ? "Ignored #sccs" : "#sccs (in skipped block)"    /* _W1_ _W8_*/
        !          4427:                         , NULL, 0L, NULL);
        !          4428:         }
        !          4429:         if (! compiling)
        !          4430:             return;
        !          4431:         skip_nl();
        !          4432:         unget_ch();
        !          4433:         return;
        !          4434:     }
        !          4435: #endif  /* COMPILER == GNUC */
        !          4436:
        !          4437: #if COMPILER == MSC
        !          4438:     if (str_eq( identifier, "using") || str_eq( identifier, "import")) {
        !          4439:                                             /* #using or #import    */
        !          4440:         if (! compiling)
        !          4441:             return;
        !          4442:         mcpp_fputs( infile->buffer, OUT);   /* Putout the line as is*/
        !          4443:         skip_nl();
        !          4444:         unget_ch();
        !          4445:         return;
        !          4446:     }
        !          4447: #endif
        !          4448:
        !          4449: #if SYSTEM == SYS_MAC
        !          4450:     if (str_eq( identifier, "import")) {
        !          4451:         if ((compiling && (warn_level & 2))
        !          4452:                 || (! compiling && (warn_level & 8)))
        !          4453:             cwarn( ext, "#import", 0L
        !          4454:                     , compiling ? NULL : " (in skipped block)");
        !          4455:         if (! compiling)
        !          4456:             return;
        !          4457:         in_import = in_include = TRUE;
        !          4458:         do_include( FALSE);
        !          4459:         in_import = in_include = FALSE;
        !          4460:         return;
        !          4461:     }
        !          4462: #endif
        !          4463:
        !          4464:     if (! standard && do_prestd_directive())
        !          4465:         return;
        !          4466:
        !          4467:     if (compiling) {
        !          4468:         if (option_flags.lang_asm) {        /* "Assembler" source   */
        !          4469:             if (warn_level & 1)
        !          4470:                 cwarn( unknown, identifier, 0L, NULL);
        !          4471:             mcpp_fputs( infile->buffer, OUT);   /* Putout the line  */
        !          4472:         } else {
        !          4473:             cerror( unknown, identifier, 0L, NULL);
        !          4474:         }
        !          4475:     } else if (warn_level & 8) {
        !          4476:         cwarn( unknown, identifier, 0L, " (in skipped block)");
        !          4477:     }
        !          4478:     skip_nl();
        !          4479:     unget_ch();
        !          4480:     return;
        !          4481: }
        !          4482:
        !          4483: static int  do_prestd_directive( void)
        !          4484: /*
        !          4485:  * Process directives for pre-Standard mode.
        !          4486:  */
        !          4487: {
        !          4488: #if COMPILER != GNUC
        !          4489:     if (str_eq( identifier, "assert")) {    /* #assert              */
        !          4490:         if (! compiling)                    /* Only validity check  */
        !          4491:             return  TRUE;
        !          4492:         if (eval_if() == 0L) {              /* Assert expression    */
        !          4493:             cerror( "Preprocessing assertion failed"        /* _E_  */
        !          4494:                     , NULL, 0L, NULL);
        !          4495:             skip_nl();
        !          4496:             unget_ch();
        !          4497:         }
        !          4498:         return  TRUE;
        !          4499:     } else
        !          4500: #endif
        !          4501:     if (str_eq( identifier, "put_defines")) {
        !          4502:         if (! compiling)                    /* Only validity check  */
        !          4503:             return  TRUE;
        !          4504:         if (mcpp_mode != OLD_PREP && ! is_junk())
        !          4505:             dump_def( TRUE, FALSE);         /* #put_defines         */
        !          4506:         skip_nl();
        !          4507:         unget_ch();
        !          4508:         return  TRUE;
        !          4509:     } else if (str_eq( identifier, "preprocess")) {
        !          4510:         if (! compiling)                    /* Only validity check  */
        !          4511:             return  TRUE;
        !          4512:         if (mcpp_mode != OLD_PREP && ! is_junk())
        !          4513:         /* Just putout the directive for the succeding preprocessor */
        !          4514:             mcpp_fputs( "#preprocessed\n", OUT);
        !          4515:         skip_nl();
        !          4516:         unget_ch();
        !          4517:         return  TRUE;
        !          4518:     } else if (str_eq( identifier, "preprocessed")) {
        !          4519:         if (! compiling)                    /* Only validity check  */
        !          4520:             return  TRUE;
        !          4521:         if (mcpp_mode != OLD_PREP && ! is_junk()) {
        !          4522:             skip_nl();
        !          4523:             do_preprocessed();              /* #preprocessed        */
        !          4524:             return  TRUE;
        !          4525:         }
        !          4526:         skip_nl();
        !          4527:         unget_ch();
        !          4528:         return  TRUE;
        !          4529:     }
        !          4530:
        !          4531:     if (str_eq( identifier, "debug")) {     /* #debug <args>        */
        !          4532:         if (! compiling)                    /* Only validity check  */
        !          4533:             return  TRUE;
        !          4534:         do_debug( TRUE);
        !          4535:         return  TRUE;
        !          4536:     } else if (str_eq( identifier, "end_debug")) {
        !          4537:         if (! compiling)
        !          4538:             return  TRUE;
        !          4539:         do_debug( FALSE);                   /* #end_debug <args>    */
        !          4540:         return  TRUE;
        !          4541:     }
        !          4542:
        !          4543:     if (str_eq( identifier, "asm")) {       /* #asm                 */
        !          4544:         do_asm( TRUE);
        !          4545:         return  TRUE;
        !          4546:     }
        !          4547:     if (str_eq( identifier, "endasm")) {    /* #endasm              */
        !          4548:         do_asm( FALSE);
        !          4549:         skip_nl();                          /* Skip comments, etc.  */
        !          4550:         unget_ch();
        !          4551:         return  TRUE;
        !          4552:     }
        !          4553:
        !          4554:     return  FALSE;                          /* Unknown directive    */
        !          4555: }
        !          4556:
        !          4557: static void do_preprocessed( void)
        !          4558: /*
        !          4559:  * The source file has been already preprocessed.
        !          4560:  * Copy the lines to output.
        !          4561:  * Install macros according the #define directives.
        !          4562:  */
        !          4563: {
        !          4564:     const char *    corrupted =
        !          4565:             "This preprocessed file is corrupted";          /* _F_  */
        !          4566:     FILEINFO *      file;
        !          4567:     char *          lbuf;
        !          4568:     char *          cp;
        !          4569:     const char **   incptr;
        !          4570:     char *          comment = NULL;
        !          4571:     char *          colon = NULL;
        !          4572:     const char *    dir;
        !          4573: #if STD_LINE_PREFIX == FALSE
        !          4574:     char            conv[ NBUFF];
        !          4575:     char *          arg;
        !          4576:
        !          4577:     /*
        !          4578:      * Compiler cannot accept C source style #line.
        !          4579:      * Convert it to the compiler-specific format.
        !          4580:      */
        !          4581:     strcpy( conv, LINE_PREFIX);
        !          4582:     arg = conv + strlen( conv);
        !          4583: #endif
        !          4584:     file = infile;
        !          4585:     lbuf = file->bptr = file->buffer;           /* Reset file->bptr */
        !          4586:
        !          4587:     /* Copy the input to output until a comment line appears.       */
        !          4588:     while (fgets( lbuf, NBUFF, file->fp) != NULL
        !          4589:             && memcmp( lbuf, "/*", 2) != 0) {
        !          4590: #if STD_LINE_PREFIX == FALSE
        !          4591:         if (memcmp( lbuf, "#line ", 6) == 0) {
        !          4592:             strcpy( arg, lbuf + 6);
        !          4593:             mcpp_fputs( conv, OUT);
        !          4594:         } else
        !          4595: #endif
        !          4596:         {
        !          4597:             mcpp_fputs( lbuf, OUT);
        !          4598:         }
        !          4599:     }
        !          4600:     if (! str_eq( lbuf, "/* Currently defined macros. */\n"))
        !          4601:         cfatal( "This is not a preprocessed source"         /* _F_  */
        !          4602:                 , NULL, 0L, NULL);
        !          4603:
        !          4604:     /* Define macros according to the #define lines.    */
        !          4605:     while (fgets( lbuf, NWORK, file->fp) != NULL) {
        !          4606:         if (memcmp( lbuf, "/*", 2) == 0) {
        !          4607:                                     /* Standard predefined macro    */
        !          4608:             continue;
        !          4609:         }
        !          4610:         if (memcmp( lbuf, "#define ", 8) != 0) {
        !          4611:             if (memcmp( lbuf, "#line", 5) == 0)
        !          4612:                 continue;
        !          4613:             else
        !          4614:                 cfatal( corrupted, NULL, 0L, NULL);
        !          4615:         }
        !          4616:         /* Filename and line-number information in comment as:  */
        !          4617:         /* dir/fname:1234\t*/
        !          4618:         cp = lbuf + strlen( lbuf);
        !          4619:         if ((memcmp( cp - 4, "\t*/\n", 4) != 0)
        !          4620:                 || (*(cp - 4) = EOS
        !          4621:                         , (comment = strrchr( lbuf, '*')) == NULL)
        !          4622:                 || (memcmp( --comment, "/* ", 3) != 0)
        !          4623:                 || ((colon = strrchr( comment, ':')) == NULL))
        !          4624:             cfatal( corrupted, NULL, 0L, NULL);
        !          4625:         src_line = atol( colon + 1);        /* Pseudo line number   */
        !          4626:         *colon = EOS;
        !          4627:         dir = comment + 3;
        !          4628:         inc_dirp = &null;
        !          4629:         /* Search the include directory list    */
        !          4630:         for (incptr = incdir ; incptr < incend; incptr++) {
        !          4631:             if (memcmp( *incptr, dir, strlen( *incptr)) == 0) {
        !          4632:                 inc_dirp = incptr;
        !          4633:                 break;
        !          4634:             }
        !          4635:         }
        !          4636:         /* Register the filename to fnamelist[] */
        !          4637:         /* inc_dirp may be NULL, and cur_fname may be "(predefined)"    */
        !          4638:         cur_fname = set_fname( dir + strlen( *inc_dirp));
        !          4639:         strcpy( comment - 2, "\n");         /* Remove the comment   */
        !          4640:         unget_string( lbuf + 8, NULL);
        !          4641:         do_define( FALSE, 0);
        !          4642:         get_ch();                               /* '\n' */
        !          4643:         get_ch();                               /* Clear the "file" */
        !          4644:         unget_ch();                             /* infile == file   */
        !          4645:     }
        !          4646:     file->bptr = file->buffer + strlen( file->buffer);
        !          4647: }
        !          4648:
        !          4649: static int  do_debug(
        !          4650:     int     set                         /* TRUE to set debugging    */
        !          4651: )
        !          4652: /*
        !          4653:  * #pragma MCPP debug, #pragma MCPP end_debug, #debug, #end_debug
        !          4654:  * Return TRUE when diagnostic is issued else return FALSE.
        !          4655:  */
        !          4656: {
        !          4657:     struct Debug_arg {
        !          4658:         const char *    arg_name;               /* Name of option   */
        !          4659:         int     arg_num;                        /* Value of 'debug' */
        !          4660:     };
        !          4661:     static struct Debug_arg     debug_args[] = {
        !          4662:         { "path",   PATH    },
        !          4663:         { "token",  TOKEN   },
        !          4664:         { "expand", EXPAND  },
        !          4665:         { "macro_call", MACRO_CALL  },      /* Implemented only in STD mode */
        !          4666:         { "if",     IF      },
        !          4667:         { "expression", EXPRESSION  },
        !          4668:         { "getc",   GETC    },
        !          4669:         { "memory", MEMORY  },
        !          4670:         { NULL,     0       },
        !          4671:     };
        !          4672:     struct Debug_arg    *argp;
        !          4673:     int     num;
        !          4674:     int     c;
        !          4675:
        !          4676:     c = skip_ws();
        !          4677:     if (c == '\n') {
        !          4678:         unget_ch();
        !          4679:         if (set) {
        !          4680:             if (warn_level & 1)
        !          4681:                 cwarn( "No argument", NULL, 0L, NULL);      /* _W1_ */
        !          4682:             return TRUE;
        !          4683:         } else {
        !          4684:             mcpp_debug = 0;                 /* Clear all the flags  */
        !          4685:             return FALSE;
        !          4686:         }
        !          4687:     }
        !          4688:     while (scan_token( c, (workp = work_buf, &workp), work_end) == NAM) {
        !          4689:         argp = debug_args;
        !          4690:         while (argp->arg_name) {
        !          4691:             if (str_eq( argp->arg_name, work_buf))
        !          4692:                 break;
        !          4693:             argp++;
        !          4694:         }
        !          4695:         if (argp->arg_name == NULL) {
        !          4696:             if (warn_level & 1)
        !          4697:                 cwarn( unknown_arg, work_buf, 0L, NULL);
        !          4698:             goto  diagnosed;
        !          4699:         } else {
        !          4700:             num = argp->arg_num;
        !          4701:             if (set) {
        !          4702:                 mcpp_debug |= num;
        !          4703:                 if (num == PATH)
        !          4704:                     dump_path();
        !          4705:                 else if (num == MEMORY)
        !          4706:                     print_heap();
        !          4707:                 else if (num == MACRO_CALL)
        !          4708:                     option_flags.k = TRUE;  /* This pragma needs this mode  */
        !          4709:             } else {
        !          4710:                 mcpp_debug &= ~num;
        !          4711:             }
        !          4712:         }
        !          4713:         c = skip_ws();
        !          4714:     }
        !          4715:     if ((mcpp_mode != STD && (mcpp_debug & MACRO_CALL)) || c != '\n') {
        !          4716:         if (warn_level & 1) {
        !          4717:             if (c != '\n') {
        !          4718:                 cwarn( not_ident, work_buf, 0L, NULL);
        !          4719:             } else {
        !          4720:                 cwarn( unknown_arg, work_buf, 0L, NULL);
        !          4721:                 mcpp_debug &= ~num;                     /* Disable  */
        !          4722:             }
        !          4723:         }
        !          4724:         skip_nl();
        !          4725:         unget_ch();
        !          4726:         goto  diagnosed;
        !          4727:     }
        !          4728:     unget_ch();
        !          4729:     return FALSE;
        !          4730: diagnosed:
        !          4731:     return TRUE;
        !          4732: }
        !          4733:
        !          4734: void    put_asm( void)
        !          4735: /*
        !          4736:  * Put out source line as it is.
        !          4737:  */
        !          4738: {
        !          4739: #if 0
        !          4740:     mcpp_fputs( "#2\n", OUT);
        !          4741:     mcpp_fputs( infile->buffer, OUT);
        !          4742:     skip_nl();
        !          4743: #endif
        !          4744: }
        !          4745:
        !          4746: static void dump_path( void)
        !          4747: /*
        !          4748:  * Show the include directories.
        !          4749:  */
        !          4750: {
        !          4751:     const char **   incptr;
        !          4752:     const char *    inc_dir;
        !          4753:     const char *    dir = "./";
        !          4754:     int             i;
        !          4755:
        !          4756:     mcpp_fputs( "Include paths are as follows --\n", DBG);
        !          4757:     for (incptr = incdir; incptr < incend; incptr++) {
        !          4758:         inc_dir = *incptr;
        !          4759:         if (*inc_dir == '\0')
        !          4760:             inc_dir = dir;
        !          4761:         mcpp_fprintf( DBG, "    %s\n", inc_dir);
        !          4762:     }
        !          4763:     mcpp_fputs( "End of include path list.\n", DBG);
        !          4764: #if SYSTEM == SYS_MAC
        !          4765:     mcpp_fputs( "Framework paths are as follows --\n", DBG);
        !          4766:     for (i = 0; i < num_framework; i++ )
        !          4767:         mcpp_fprintf( DBG, "    %s\n", framework[ i]);
        !          4768:     mcpp_fputs( "End of framework path list.\n", DBG);
        !          4769: #endif
        !          4770: }
        !          4771:
        !          4772: /*
        !          4773:  * Note: The getopt() of glibc should not be used since the specification
        !          4774:  *  differs from the standard one.
        !          4775:  *  Use this mcpp_getopt() for mcpp.
        !          4776:  */
        !          4777:
        !          4778: /* Based on the public-domain-software released by AT&T in 1985.    */
        !          4779:
        !          4780: #define OPTERR( s, c)   if (mcpp_opterr) {  \
        !          4781:     mcpp_fputs( argv[0], ERR);  \
        !          4782:     mcpp_fputs( s, ERR);        \
        !          4783:     mcpp_fputc( c, ERR);        \
        !          4784:     mcpp_fputc( '\n', ERR);     \
        !          4785:     }
        !          4786:
        !          4787: static int  mcpp_getopt(
        !          4788:     int         argc,
        !          4789:     char * const *  argv,
        !          4790:     const char *    opts
        !          4791: )
        !          4792: /*
        !          4793:  * Get the next option (and it's argument) from the command line.
        !          4794:  */
        !          4795: {
        !          4796:     const char * const   error1 = ": option requires an argument --";
        !          4797:     const char * const   error2 = ": illegal option --";
        !          4798:     static int      sp = 1;
        !          4799:     int             c;
        !          4800:     const char *    cp;
        !          4801:
        !          4802:     if (sp == 1) {
        !          4803:         if (argc <= mcpp_optind ||
        !          4804:                 argv[ mcpp_optind][ 0] != '-'
        !          4805:                     || argv[ mcpp_optind][ 1] == '\0') {
        !          4806:             return  EOF;
        !          4807:         } else if (strcmp( argv[ mcpp_optind], "--") == 0) {
        !          4808:             mcpp_optind++;
        !          4809:             return  EOF;
        !          4810:         }
        !          4811:     }
        !          4812: /*  mcpp_optopt = c = (unsigned char) argv[ mcpp_optind][ sp];  */
        !          4813:     mcpp_optopt = c = argv[ mcpp_optind][ sp] & UCHARMAX;
        !          4814:     if (c == ':' || (cp = strchr( opts, c)) == NULL) {
        !          4815:         OPTERR( error2, c)
        !          4816:         if (argv[ mcpp_optind][ ++sp] == '\0') {
        !          4817:             mcpp_optind++;
        !          4818:             sp = 1;
        !          4819:         }
        !          4820:         return  '?';
        !          4821:     }
        !          4822:     if (*++cp == ':') {
        !          4823:         if (argv[ mcpp_optind][ sp+1] != '\0') {
        !          4824:             mcpp_optarg = &argv[ mcpp_optind++][ sp+1];
        !          4825:         } else if (argc <= ++mcpp_optind) {
        !          4826:             OPTERR( error1, c)
        !          4827:             sp = 1;
        !          4828:             return  '?';
        !          4829:         } else {
        !          4830:             mcpp_optarg = argv[ mcpp_optind++];
        !          4831:         }
        !          4832:         sp = 1;
        !          4833:     } else {
        !          4834:         if (argv[ mcpp_optind][ ++sp] == '\0') {
        !          4835:             sp = 1;
        !          4836:             mcpp_optind++;
        !          4837:         }
        !          4838:         mcpp_optarg = NULL;
        !          4839:     }
        !          4840:     return  c;
        !          4841: }
        !          4842:
        !          4843: #if ! HOST_HAVE_STPCPY
        !          4844: char *  stpcpy(
        !          4845:     char *          dest,
        !          4846:     const char *    src
        !          4847: )
        !          4848: /*
        !          4849:  * Copy the string and return the advanced pointer.
        !          4850:  */
        !          4851: {
        !          4852:     const char * s;
        !          4853:     char *  d;
        !          4854:
        !          4855:     for (s = src, d = dest; (*d++ = *s++) != '\0'; )
        !          4856:         ;
        !          4857:     return  d - 1;
        !          4858: }
        !          4859: #endif
        !          4860:
        !          4861: /*
        !          4862:  * list_heap() is a function to print out information of heap-memory.
        !          4863:  * See "kmmalloc-2.5.3.zip" by kmatsui.
        !          4864:  */
        !          4865: #if     KMMALLOC
        !          4866:     int     list_heap( int);
        !          4867: #elif   BSD_MALLOC
        !          4868:     int     list_heap( char *);
        !          4869: #elif   DB_MALLOC || DMALLOC
        !          4870:     int     list_heap( FILE *);
        !          4871: #endif
        !          4872:
        !          4873: void    print_heap( void)
        !          4874: {
        !          4875: #if     KMMALLOC
        !          4876:     list_heap( 1);
        !          4877: #elif   BSD_MALLOC
        !          4878:     list_heap( ":cpp");
        !          4879: #elif   DB_MALLOC || DMALLOC || PHK_MALLOC || DLMALLOC
        !          4880:     list_heap( fp_debug);
        !          4881: #endif
        !          4882: }
        !          4883:
        !          4884: void    at_end( void)
        !          4885: /*
        !          4886:  * Handle the commands to be executed at the end of processing.
        !          4887:  */
        !          4888: {
        !          4889: #if COMPILER == GNUC
        !          4890:     if (dMflag || dDflag)
        !          4891:         dump_def( FALSE, FALSE);
        !          4892: #endif
        !          4893: }
        !          4894:
        !          4895: #if MCPP_LIB
        !          4896: void    clear_filelist( void)
        !          4897: /*
        !          4898:  * Free malloced memory for filename-list and directory-list.
        !          4899:  */
        !          4900: {
        !          4901:     const char **   incp;
        !          4902:     INC_LIST *  namep;
        !          4903:
        !          4904:     for (incp = incdir; incp < incend; incp++)
        !          4905:         free( (void *) *incp);
        !          4906:     free( (void *) incdir);
        !          4907:     for (namep = fnamelist; namep < fname_end; namep++)
        !          4908:         free( (void *) namep->name);
        !          4909:     free( (void *) fnamelist);
        !          4910:     if (standard)
        !          4911:         free( (void *) once_list);
        !          4912: }
        !          4913: #endif
        !          4914:

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>