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 >= "e_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>