Annotation of OpenXM_contrib2/windows/mcpp/main.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: * M A I N . C
! 33: * M C P P M a i n P r o g r a m
! 34: *
! 35: * The main routine and it's supplementary routines are placed here.
! 36: * The post-preprocessing routines are also placed here.
! 37: */
! 38:
! 39: #if PREPROCESSED /* Use "pre-preprocessed" header */
! 40: #include "mcpp.H"
! 41: #else
! 42: #include "system.H"
! 43: #include "internal.H"
! 44: #endif
! 45:
! 46: /* Function pointer to expand_macro() functions. */
! 47: char * (*expand_macro)( DEFBUF * defp, char * out, char * out_end
! 48: , LINE_COL line_col, int * pragma_op);
! 49:
! 50: /* The boolean flags specified by the execution options. */
! 51: struct option_flags_ option_flags = {
! 52: FALSE, /* c: -C (keep comments) */
! 53: FALSE, /* k: -k (keep horizontal white spaces) */
! 54: FALSE, /* z: -z (no output of included files) */
! 55: FALSE, /* p: -P (no #line output) */
! 56: FALSE, /* q: -Q (output diagnosis to mcpp.err) */
! 57: FALSE, /* v: -v (verbose, affects macro notification) */
! 58: TRIGRAPHS_INIT, /* trig: -3 (toggle trigraphs) */
! 59: DIGRAPHS_INIT, /* dig: -2 (toggle digraphs recognition) */
! 60: /*
! 61: * lang_asm allows the following non-standard features.
! 62: * 1. #non-directive.
! 63: * 2. <newline> in a string-literal.
! 64: * 3. invalid pp-token generated by ## operator.
! 65: * lang_asm is not available in POST_STD mode.
! 66: * When COMPILER == GNUC, -x assembler-with-cpp or -lang-asm options
! 67: * are used instead of -a.
! 68: */
! 69: FALSE, /* lang_asm: -a (assembler source) */
! 70: FALSE /* no_source_line: -j (no source line in diag) */
! 71: };
! 72:
! 73: int mcpp_mode = STD; /* Mode of preprocessing */
! 74:
! 75: long cplus_val = 0L; /* Value of __cplusplus for C++ */
! 76: long stdc_ver = 0L; /* Value of __STDC_VERSION__ */
! 77: int stdc_val = 0; /* Value of __STDC__ */
! 78: int stdc2; /* cplus_val || stdc_ver >= 199901L */
! 79: int stdc3; /* cplus_val >= 199901L || stdc_ver >= 199901L.
! 80: (cplus_val >= 199901L) specifies compatible mode to C99 (extended
! 81: feature of this preprocessor) */
! 82: int standard = TRUE; /* TRUE, if mcpp_mode is STD or POST_STD */
! 83: int std_line_prefix = STD_LINE_PREFIX;
! 84: /* Output line and file information in C source style */
! 85:
! 86: /*
! 87: * Commonly used global variables:
! 88: * src_line is the current input line number.
! 89: * wrong_line is set in many places when the actual output line is out of
! 90: * sync with the numbering, e.g, when expanding a macro with an
! 91: * embedded newline.
! 92: * identifier holds the last identifier scanned (which might be a candidate
! 93: * for macro expansion).
! 94: * errors is the running mcpp error counter.
! 95: * infile is the head of a linked list of input files (extended by
! 96: * #include and macros being expanded). 'infile' always points
! 97: * to the current file/macro. 'infile->parent' to the includer,
! 98: * etc. 'infile->fp' is NULL if this input stream is not a file.
! 99: * inc_dirp Directory of #includer with trailing PATH_DELIM. This points
! 100: * to one of incdir[] or to the current directory (represented as
! 101: * "". This should not be NULL.
! 102: */
! 103: long src_line; /* Current line number */
! 104: int wrong_line; /* Force #line to compiler */
! 105: int newlines; /* Count of blank lines */
! 106: int errors = 0; /* Cpp error counter */
! 107: int warn_level = -1; /* Level of warning (have to initialize)*/
! 108: FILEINFO * infile = NULL; /* Current input file */
! 109: int include_nest = 0; /* Nesting level of #include */
! 110: const char * null = ""; /* "" string for convenience */
! 111: const char ** inc_dirp; /* Directory of #includer */
! 112: const char * cur_fname; /* Current source file name */
! 113: /* cur_fname is not rewritten by #line directive */
! 114: char * cur_fullname;
! 115: /* Full path of current source file (i.e. infile->full_fname) */
! 116: int no_source_line; /* Do not output line in diag. */
! 117: char identifier[ IDMAX + IDMAX/8]; /* Current identifier */
! 118: int mcpp_debug = 0; /* != 0 if debugging now */
! 119:
! 120: /*
! 121: * in_directive is set TRUE while a directive line is scanned by directive().
! 122: * It modifies the behavior of squeeze_ws() in expand.c so that newline is
! 123: * not skipped even if getting macro arguments.
! 124: */
! 125: int in_directive = FALSE; /* TRUE scanning directive line */
! 126: int in_define = FALSE; /* TRUE scanning #define line */
! 127: int in_getarg = FALSE; /* TRUE collecting macro arguments */
! 128: int in_include = FALSE; /* TRUE scanning #include line */
! 129: int in_if = FALSE; /* TRUE scanning #if and in non-skipped expr. */
! 130: long in_asm = 0L; /* Starting line of #asm - #endasm block*/
! 131:
! 132: /*
! 133: * macro_line is set to the line number of start of a macro call while
! 134: * expanding the macro, else set to 0. Line number is remembered for
! 135: * diagnostics of unterminated macro call. On unterminated macro call
! 136: * macro_line is set to MACRO_ERROR.
! 137: */
! 138: long macro_line = 0L;
! 139: /*
! 140: * macro_name is the currently expanding macro.
! 141: */
! 142: char * macro_name;
! 143:
! 144: /*
! 145: * openum is the return value of scan_op() in support.c.
! 146: */
! 147: int openum;
! 148:
! 149: /*
! 150: * mkdep means to output source file dependency line, specified by -M*
! 151: * option. The OR of the following values is used.
! 152: * MD_MKDEP (1) : Output dependency line.
! 153: * MD_SYSHEADER(2) : Print also system headers or headers with
! 154: * absolute path not only user headers.
! 155: * MD_FILE (4) : Output to the file named *.d instead of fp_out.
! 156: * Normal output is done to fp_out as usual.
! 157: */
! 158: int mkdep = 0;
! 159:
! 160: /*
! 161: * If option_flags.z is TRUE, no_output is incremented when a file is
! 162: * #included, and decremented when the file is finished.
! 163: * If no_output is larger than 0, processed files are not output, meanwhile
! 164: * the macros in the files are defined.
! 165: * If mkdep != 0 && (mkdep & MD_FILE) == 0, no_output is set to 1 initially.
! 166: */
! 167: int no_output = 0;
! 168:
! 169: /*
! 170: * keep_comments is set TRUE by the -C option. If TRUE, comments are written
! 171: * directly to the output stream. option_flags.c contains the permanent state
! 172: * of the -C option. keep_comments is always falsified when compilation is
! 173: * supressed by a false #if or when no_output is TRUE.
! 174: */
! 175: int keep_comments = 0; /* Write out comments flag */
! 176:
! 177: /*
! 178: * keep_spaces is set to TRUE by the -k option. If TRUE, spaces and tabs in
! 179: * an input line are written out to the output line without squeezing to one
! 180: * space. option_flags.k contains the permanent state of the -k option.
! 181: * keep_spaces is falsified when compilation is suppressed by a false #if.
! 182: */
! 183: int keep_spaces = 0; /* Keep white spaces of line*/
! 184:
! 185: /*
! 186: * ifstack[] holds information about nested #if's. It is always accessed via
! 187: * ifptr->stat. The information is as follows:
! 188: * WAS_COMPILING state of compiling flag at outer level.
! 189: * ELSE_SEEN set TRUE when #else seen to prevent 2nd #else.
! 190: * TRUE_SEEN set TRUE when #if or #elif succeeds
! 191: * ifstack[0].stat holds the compiling flag. It is WAS_COMPILING if compila-
! 192: * tion is currently enabled. Note that this must be initialized to
! 193: * WAS_COMPILING.
! 194: */
! 195: IFINFO ifstack[ BLK_NEST + 1] = { {WAS_COMPILING, 0L, 0L}, };
! 196: /* Note: '+1' is necessary for the initial state. */
! 197: IFINFO * ifptr = ifstack; /* -> current ifstack[] */
! 198:
! 199: /*
! 200: * In POST_STD mode, insert_sep is set to INSERT_SEP when :
! 201: * 1. the next get_ch() shall insert a token separator.
! 202: * 2. unget_ch() has been called when insert_sep == INSERTED_SEP.
! 203: * set to INSERTED_SEP when :
! 204: * get_ch() has been called when insert_sep == INSERT_SEP.
! 205: * set to NO_SEP when :
! 206: * get_ch() has been called when insert_sep == INSERTED_SEP.
! 207: */
! 208: int insert_sep = NO_SEP;
! 209:
! 210: /* File pointers for input and output. */
! 211: FILE * fp_in; /* Input stream to preprocess */
! 212: FILE * fp_out; /* Output stream preprocessed */
! 213: FILE * fp_err; /* Diagnostics stream */
! 214: FILE * fp_debug; /* Debugging information stream */
! 215:
! 216: /* Variables on multi-byte character encodings. */
! 217: int mbchar = MBCHAR; /* Encoding of multi-byte char */
! 218: int mbchk; /* Character type of possible multi-byte char */
! 219: int bsl_in_mbchar; /* 2nd byte of mbchar possibly has '\\' */
! 220: int bsl_need_escape; /* '\\' in MBCHAR should be escaped */
! 221: /* Function pointer to mb_read_*() functions. */
! 222: size_t (*mb_read)( int c1, char ** in_pp, char ** out_pp);
! 223:
! 224: jmp_buf error_exit; /* Exit on fatal error */
! 225:
! 226: /*
! 227: * Translation limits specified by C90, C99 or C++.
! 228: */
! 229: struct std_limits_ std_limits = {
! 230: /* The following three are temporarily set for do_options() */
! 231: NBUFF, /* Least maximum of string length */
! 232: IDMAX, /* Least maximum of identifier length */
! 233: NMACPARS, /* Least maximum of number of macro params */
! 234: };
! 235:
! 236: /*
! 237: * work_buf[] and workp are used to store one piece of text as a temporary
! 238: * buffer.
! 239: * To initialize storage, set workp = work_buf. Note that the work buffer is
! 240: * used by several subroutines -- be sure that your data won't be overwritten.
! 241: * work_buf[] is used for:
! 242: * 1. macro expansion (def_special(), prescan(), catenate(),
! 243: * stringize()).
! 244: * 2. processing directive line (directive.c, eval.c, get_unexpandable(),
! 245: * do_pragma() and its subroutines).
! 246: * 3. processing _Pragma() operator (do_pragma_op()).
! 247: * 4. miscellaneous (init_gcc_macro(), curfile()).
! 248: */
! 249: char work_buf[ NWORK + IDMAX]; /* Work buffer */
! 250: char * workp; /* Pointer into work_buf[] */
! 251: char * const work_end = & work_buf[ NWORK];
! 252: /* End of buffer of work_buf[] */
! 253:
! 254: /*
! 255: * src_col is the current input column number, but is rarely used.
! 256: * It is used to put spaces after #line line in keep_spaces mode
! 257: * on some special cases.
! 258: */
! 259: static int src_col = 0; /* Column number of source line */
! 260:
! 261: #define MBCHAR_IS_ESCAPE_FREE (SJIS_IS_ESCAPE_FREE && \
! 262: BIGFIVE_IS_ESCAPE_FREE && ISO2022_JP_IS_ESCAPE_FREE)
! 263:
! 264: #if MCPP_LIB
! 265: static void init_main( void);
! 266: /* Initialize static variables */
! 267: #endif
! 268: static void init_defines( void);
! 269: /* Predefine macros */
! 270: static void mcpp_main( void);
! 271: /* Main loop to process input lines */
! 272: static void do_pragma_op( void);
! 273: /* Execute the _Pragma() operator */
! 274: static void put_seq( char * begin, char * seq);
! 275: /* Put out the failed sequence */
! 276: static char * de_stringize( char * in, char * out);
! 277: /* "De-stringize" for _Pragma() op. */
! 278: static void putout( char * out);
! 279: /* May concatenate adjacent string */
! 280: #if COMPILER != GNUC && COMPILER != MSC
! 281: static void devide_line( char * out);
! 282: /* Devide long line for compiler */
! 283: #endif
! 284: static void put_a_line( char * out);
! 285: /* Put out the processed line */
! 286: #if ! HAVE_DIGRAPHS || ! MBCHAR_IS_ESCAPE_FREE
! 287: static int post_preproc( char * out);
! 288: /* Post-preprocess for older comps */
! 289: #if ! HAVE_DIGRAPHS
! 290: static char * conv_a_digraph( char * cp);
! 291: /* Convert a digraph in place */
! 292: #endif
! 293: #if ! MBCHAR_IS_ESCAPE_FREE
! 294: static char * esc_mbchar( char * str, char * str_end);
! 295: /* Double \ as 2nd byte of SJIS */
! 296: #endif
! 297: #endif
! 298:
! 299:
! 300: #if MCPP_LIB
! 301: static void init_main( void)
! 302: /* Initialize global variables on re-entering. */
! 303: {
! 304: mcpp_mode = STD;
! 305: cplus_val = stdc_ver = 0L;
! 306: stdc_val = 0;
! 307: standard = TRUE;
! 308: std_line_prefix = STD_LINE_PREFIX;
! 309: errors = src_col = 0;
! 310: warn_level = -1;
! 311: infile = NULL;
! 312: in_directive = in_define = in_getarg = in_include = in_if = FALSE;
! 313: src_line = macro_line = in_asm = 0L;
! 314: mcpp_debug = mkdep = no_output = keep_comments = keep_spaces = 0;
! 315: include_nest = 0;
! 316: insert_sep = NO_SEP;
! 317: mbchar = MBCHAR;
! 318: ifptr = ifstack;
! 319: ifstack[0].stat = WAS_COMPILING;
! 320: ifstack[0].ifline = ifstack[0].elseline = 0L;
! 321: std_limits.str_len = NBUFF;
! 322: std_limits.id_len = IDMAX;
! 323: std_limits.n_mac_pars = NMACPARS;
! 324: option_flags.c = option_flags.k = option_flags.z = option_flags.p
! 325: = option_flags.q = option_flags.v = option_flags.lang_asm
! 326: = option_flags.no_source_line = option_flags.dollar_in_name
! 327: = FALSE;
! 328: option_flags.trig = TRIGRAPHS_INIT;
! 329: option_flags.dig = DIGRAPHS_INIT;
! 330: }
! 331:
! 332: int mcpp_lib_main
! 333: #else
! 334: int main
! 335: #endif
! 336: (
! 337: int argc,
! 338: char ** argv
! 339: )
! 340: {
! 341: char * in_file = NULL;
! 342: char * out_file = NULL;
! 343: char * stdin_name = "<stdin>";
! 344:
! 345: if (setjmp( error_exit) == -1) {
! 346: errors++;
! 347: goto fatal_error_exit;
! 348: }
! 349:
! 350: #if MCPP_LIB
! 351: /* Initialize global and static variables. */
! 352: init_main();
! 353: init_directive();
! 354: init_eval();
! 355: init_support();
! 356: init_system();
! 357: #endif
! 358:
! 359: fp_in = stdin;
! 360: fp_out = stdout;
! 361: fp_err = stderr;
! 362: fp_debug = stdout;
! 363: /*
! 364: * Debugging information is output to stdout in order to
! 365: * synchronize with preprocessed output.
! 366: */
! 367:
! 368: inc_dirp = &null; /* Initialize to current (null) directory */
! 369: cur_fname = cur_fullname = "(predefined)"; /* For predefined macros */
! 370: init_defines(); /* Predefine macros */
! 371: mb_init(); /* Should be initialized prior to get options */
! 372: do_options( argc, argv, &in_file, &out_file); /* Command line options */
! 373:
! 374: /* Open input file, "-" means stdin. */
! 375: if (in_file != NULL && ! str_eq( in_file, "-")) {
! 376: if ((fp_in = fopen( in_file, "r")) == NULL) {
! 377: mcpp_fprintf( ERR, "Can't open input file \"%s\".\n", in_file);
! 378: errors++;
! 379: #if MCPP_LIB
! 380: goto fatal_error_exit;
! 381: #else
! 382: return( IO_ERROR);
! 383: #endif
! 384: }
! 385: } else {
! 386: in_file = stdin_name;
! 387: }
! 388: /* Open output file, "-" means stdout. */
! 389: if (out_file != NULL && ! str_eq( out_file, "-")) {
! 390: if ((fp_out = fopen( out_file, "w")) == NULL) {
! 391: mcpp_fprintf( ERR, "Can't open output file \"%s\".\n", out_file);
! 392: errors++;
! 393: #if MCPP_LIB
! 394: goto fatal_error_exit;
! 395: #else
! 396: return( IO_ERROR);
! 397: #endif
! 398: }
! 399: fp_debug = fp_out;
! 400: }
! 401: if (option_flags.q) { /* Redirect diagnostics */
! 402: if ((fp_err = fopen( "mcpp.err", "a")) == NULL) {
! 403: errors++;
! 404: mcpp_fprintf( OUT, "Can't open \"mcpp.err\"\n");
! 405: #if MCPP_LIB
! 406: goto fatal_error_exit;
! 407: #else
! 408: return( IO_ERROR);
! 409: #endif
! 410: }
! 411: }
! 412: init_sys_macro(); /* Initialize system-specific macros */
! 413: add_file( fp_in, NULL, in_file, in_file, FALSE);
! 414: /* "open" main input file */
! 415: infile->dirp = inc_dirp;
! 416: infile->sys_header = FALSE;
! 417: cur_fullname = in_file;
! 418: if (mkdep && str_eq( infile->real_fname, stdin_name) == FALSE)
! 419: put_depend( in_file); /* Putout target file name */
! 420: at_start(); /* Do the pre-main commands */
! 421:
! 422: mcpp_main(); /* Process main file */
! 423:
! 424: if (mkdep)
! 425: put_depend( NULL); /* Append '\n' to dependency line */
! 426: at_end(); /* Do the final commands */
! 427:
! 428: fatal_error_exit:
! 429: #if MCPP_LIB
! 430: /* Free malloced memory */
! 431: if (mcpp_debug & MACRO_CALL) {
! 432: if (in_file != stdin_name)
! 433: free( in_file);
! 434: }
! 435: clear_filelist();
! 436: clear_symtable();
! 437: #endif
! 438:
! 439: if (fp_in != stdin)
! 440: fclose( fp_in);
! 441: if (fp_out != stdout)
! 442: fclose( fp_out);
! 443: if (fp_err != stderr)
! 444: fclose( fp_err);
! 445:
! 446: if (mcpp_debug & MEMORY)
! 447: print_heap();
! 448: if (errors > 0 && option_flags.no_source_line == FALSE) {
! 449: mcpp_fprintf( ERR, "%d error%s in preprocessor.\n",
! 450: errors, (errors == 1) ? "" : "s");
! 451: return IO_ERROR;
! 452: }
! 453: return IO_SUCCESS; /* No errors */
! 454: }
! 455:
! 456: /*
! 457: * This is the table used to predefine target machine, operating system and
! 458: * compiler designators. It may need hacking for specific circumstances.
! 459: * The -N option supresses these definitions.
! 460: */
! 461: typedef struct pre_set {
! 462: const char * name;
! 463: const char * val;
! 464: } PRESET;
! 465:
! 466: static PRESET preset[] = {
! 467:
! 468: #ifdef SYSTEM_OLD
! 469: { SYSTEM_OLD, "1"},
! 470: #endif
! 471: #ifdef SYSTEM_SP_OLD
! 472: { SYSTEM_SP_OLD, "1"},
! 473: #endif
! 474: #ifdef COMPILER_OLD
! 475: { COMPILER_OLD, "1"},
! 476: #endif
! 477: #ifdef COMPILER_SP_OLD
! 478: { COMPILER_SP_OLD, "1"},
! 479: #endif
! 480:
! 481: { NULL, NULL}, /* End of macros beginning with alphabet */
! 482:
! 483: #ifdef SYSTEM_STD
! 484: { SYSTEM_STD, "1"},
! 485: #endif
! 486: #ifdef SYSTEM_STD1
! 487: { SYSTEM_STD1, "1"},
! 488: #endif
! 489: #ifdef SYSTEM_STD2
! 490: { SYSTEM_STD2, "1"},
! 491: #endif
! 492:
! 493: #ifdef SYSTEM_EXT
! 494: { SYSTEM_EXT, SYSTEM_EXT_VAL},
! 495: #endif
! 496: #ifdef SYSTEM_EXT2
! 497: { SYSTEM_EXT2, SYSTEM_EXT2_VAL},
! 498: #endif
! 499: #ifdef SYSTEM_SP_STD
! 500: { SYSTEM_SP_STD, SYSTEM_SP_STD_VAL},
! 501: #endif
! 502: #ifdef COMPILER_STD
! 503: { COMPILER_STD, COMPILER_STD_VAL},
! 504: #endif
! 505: #ifdef COMPILER_STD1
! 506: { COMPILER_STD1, COMPILER_STD1_VAL},
! 507: #endif
! 508: #ifdef COMPILER_STD2
! 509: { COMPILER_STD2, COMPILER_STD2_VAL},
! 510: #endif
! 511: #ifdef COMPILER_EXT
! 512: { COMPILER_EXT, COMPILER_EXT_VAL},
! 513: #endif
! 514: #ifdef COMPILER_EXT2
! 515: { COMPILER_EXT2, COMPILER_EXT2_VAL},
! 516: #endif
! 517: #ifdef COMPILER_SP_STD
! 518: { COMPILER_SP_STD, COMPILER_SP_STD_VAL},
! 519: #endif
! 520: #ifdef COMPILER_SP1
! 521: { COMPILER_SP1, COMPILER_SP1_VAL},
! 522: #endif
! 523: #ifdef COMPILER_SP2
! 524: { COMPILER_SP2, COMPILER_SP2_VAL},
! 525: #endif
! 526: #ifdef COMPILER_SP3
! 527: { COMPILER_SP3, COMPILER_SP3_VAL},
! 528: #endif
! 529: #ifdef COMPILER_CPLUS
! 530: { COMPILER_CPLUS, COMPILER_CPLUS_VAL},
! 531: #endif
! 532: { NULL, NULL}, /* End of macros with value of any integer */
! 533: };
! 534:
! 535: static void init_defines( void)
! 536: /*
! 537: * Initialize the built-in #define's.
! 538: * Called only on cpp startup prior to do_options().
! 539: *
! 540: * Note: the built-in static definitions are removed by the -N option.
! 541: */
! 542: {
! 543: int n = sizeof preset / sizeof (PRESET);
! 544: int nargs;
! 545: PRESET * pp;
! 546:
! 547: /* Predefine the built-in symbols. */
! 548: nargs = DEF_NOARGS_PREDEF_OLD;
! 549: for (pp = preset; pp < preset + n; pp++) {
! 550: if (pp->name && *(pp->name))
! 551: look_and_install( pp->name, nargs, null, pp->val);
! 552: else if (! pp->name)
! 553: nargs = DEF_NOARGS_PREDEF;
! 554: }
! 555:
! 556: look_and_install( "__MCPP", DEF_NOARGS_PREDEF, null, "2");
! 557: /* MCPP V.2.x */
! 558: /* This macro is predefined and is not undefined by -N option, */
! 559: /* yet can be undefined by -U or #undef. */
! 560: }
! 561:
! 562: void un_predefine(
! 563: int clearall /* TRUE for -N option */
! 564: )
! 565: /*
! 566: * Remove predefined symbols from the symbol table.
! 567: */
! 568: {
! 569: PRESET * pp;
! 570: DEFBUF * defp;
! 571: int n = sizeof preset / sizeof (PRESET);
! 572:
! 573: for (pp = preset; pp < preset + n; pp++) {
! 574: if (pp->name) {
! 575: if (*(pp->name) && (defp = look_id( pp->name)) != NULL
! 576: && defp->nargs >= DEF_NOARGS_PREDEF)
! 577: undefine( pp->name);
! 578: } else if (clearall == FALSE) { /* -S<n> option */
! 579: break;
! 580: }
! 581: }
! 582: }
! 583:
! 584: /*
! 585: * output[] and out_ptr are used for:
! 586: * buffer to store preprocessed line (this line is put out or handed to
! 587: * post_preproc() via putout() in some cases)
! 588: */
! 589: static char output[ NMACWORK]; /* Buffer for preprocessed line */
! 590: static char * const out_end = & output[ NWORK - 2];
! 591: /* Limit of output line for other than GCC and VC */
! 592: static char * const out_wend = & output[ NMACWORK - 2];
! 593: /* Buffer end of output line */
! 594: static char * out_ptr; /* Current pointer into output[]*/
! 595:
! 596: static void mcpp_main( void)
! 597: /*
! 598: * Main process for mcpp -- copies tokens from the current input stream
! 599: * (main file or included file) to the output file.
! 600: */
! 601: {
! 602: int c; /* Current character */
! 603: char * wp; /* Temporary pointer */
! 604: DEFBUF * defp; /* Macro definition */
! 605: int line_top; /* Is in the line top, possibly spaces */
! 606: LINE_COL line_col; /* Location of macro call in source */
! 607:
! 608: keep_comments = option_flags.c && !no_output;
! 609: keep_spaces = option_flags.k; /* Will be turned off if !compiling */
! 610: line_col.col = line_col.line = 0L;
! 611:
! 612: /*
! 613: * This loop is started "from the top" at the beginning of each line.
! 614: * 'wrong_line' is set TRUE in many places if it is necessary to write
! 615: * a #line record. (But we don't write them when expanding macros.)
! 616: *
! 617: * 'newlines' variable counts the number of blank lines that have been
! 618: * skipped over. These are then either output via #line records or
! 619: * by outputting explicit blank lines.
! 620: * 'newlines' will be cleared on end of an included file by get_ch().
! 621: */
! 622: while (1) { /* For the whole input */
! 623: newlines = 0; /* Count empty lines */
! 624:
! 625: while (1) { /* For each line, ... */
! 626: out_ptr = output; /* Top of the line buf */
! 627: c = get_ch();
! 628: if (src_col)
! 629: break; /* There is a residual tokens on the line */
! 630: while (char_type[ c] & HSP) { /* ' ' or '\t' */
! 631: if (c != COM_SEP)
! 632: *out_ptr++ = c; /* Retain line top white spaces */
! 633: /* Else skip 0-length comment */
! 634: c = get_ch();
! 635: }
! 636: if (c == '#') { /* Is 1st non-space '#' */
! 637: directive(); /* Do a #directive */
! 638: } else if (mcpp_mode == STD && option_flags.dig && c == '%') {
! 639: /* In POST_STD digraphs are already converted */
! 640: if (get_ch() == ':') { /* '%:' i.e. '#' */
! 641: directive(); /* Do a #directive */
! 642: } else {
! 643: unget_ch();
! 644: if (! compiling) {
! 645: skip_nl();
! 646: newlines++;
! 647: } else {
! 648: break;
! 649: }
! 650: }
! 651: } else if (c == CHAR_EOF) { /* End of input */
! 652: break;
! 653: } else if (! compiling) { /* #ifdef false? */
! 654: skip_nl(); /* Skip to newline */
! 655: newlines++; /* Count it, too. */
! 656: } else if (in_asm && ! no_output) { /* In #asm block */
! 657: put_asm(); /* Put out as it is */
! 658: } else if (c == '\n') { /* Blank line */
! 659: if (keep_comments)
! 660: mcpp_fputc( '\n', OUT); /* May flush comments */
! 661: else
! 662: newlines++; /* Wait for a token */
! 663: } else {
! 664: break; /* Actual token */
! 665: }
! 666: }
! 667:
! 668: if (c == CHAR_EOF) /* Exit process at */
! 669: break; /* end of input */
! 670:
! 671: /*
! 672: * If the loop didn't terminate because of end of file, we
! 673: * know there is a token to compile. First, clean up after
! 674: * absorbing newlines. newlines has the number we skipped.
! 675: */
! 676: if (no_output) {
! 677: wrong_line = FALSE;
! 678: } else {
! 679: if (wrong_line || newlines > 10) {
! 680: sharp( NULL, 0); /* Output # line number */
! 681: if (keep_spaces && src_col) {
! 682: while (src_col--) /* Adjust columns */
! 683: mcpp_fputc( ' ', OUT);
! 684: src_col = 0;
! 685: }
! 686: } else { /* If just a few, stuff */
! 687: while (newlines-- > 0) /* them out ourselves */
! 688: mcpp_fputc('\n', OUT);
! 689: }
! 690: }
! 691:
! 692: /*
! 693: * Process each token on this line.
! 694: */
! 695: line_top = TRUE;
! 696: while (c != '\n' && c != CHAR_EOF) { /* For the whole line */
! 697: /*
! 698: * has_pragma is set to TRUE so as to execute _Pragma() operator
! 699: * when the psuedo macro _Pragma() is found.
! 700: */
! 701: int has_pragma;
! 702:
! 703: if ((mcpp_debug & MACRO_CALL) && ! in_directive) {
! 704: line_col.line = src_line; /* Location in source */
! 705: line_col.col = infile->bptr - infile->buffer - 1;
! 706: }
! 707: if (scan_token( c, (wp = out_ptr, &wp), out_wend) == NAM
! 708: && (defp = is_macro( &wp)) != NULL) { /* A macro */
! 709: wp = expand_macro( defp, out_ptr, out_wend, line_col
! 710: , & has_pragma); /* Expand it completely */
! 711: if (line_top) { /* The first token is a macro */
! 712: char * tp = out_ptr;
! 713: while (char_type[ *tp & UCHARMAX] & HSP)
! 714: tp++; /* Remove excessive spaces */
! 715: memmove( out_ptr, tp, strlen( tp) + 1);
! 716: wp -= (tp - out_ptr);
! 717: }
! 718: if (has_pragma) { /* Found _Pramga() */
! 719: do_pragma_op(); /* Do _Pragma() operator*/
! 720: out_ptr = output; /* Do the rest of line */
! 721: wrong_line = TRUE; /* Line-num out of sync */
! 722: } else {
! 723: out_ptr = wp;
! 724: }
! 725: if (keep_spaces && wrong_line && infile
! 726: && *(infile->bptr) != '\n' && *(infile->bptr) != EOS) {
! 727: src_col = infile->bptr - infile->buffer;
! 728: /* Remember the current colums */
! 729: break; /* Do sharp() now */
! 730: }
! 731: } else { /* Not a macro call */
! 732: out_ptr = wp; /* Advance the place */
! 733: if (wrong_line) /* is_macro() swallowed */
! 734: break; /* the newline */
! 735: }
! 736: while (char_type[ c = get_ch()] & HSP) { /* Horizontal space */
! 737: if (c != COM_SEP) /* Skip 0-length comment*/
! 738: *out_ptr++ = c;
! 739: }
! 740: line_top = FALSE; /* Read over some token */
! 741: } /* Loop for line */
! 742:
! 743: putout( output); /* Output the line */
! 744: } /* Continue until EOF */
! 745: }
! 746:
! 747: static void do_pragma_op( void)
! 748: /*
! 749: * Execute the _Pragma() operator contained in an expanded macro.
! 750: * Note: _Pragma() operator is also implemented as a special macro. Therefore
! 751: * it is always searched as a macro.
! 752: * There might be more than one _Pragma() in a expanded macro and those may be
! 753: * surrounded by other token sequences.
! 754: * Since all the macros have been expanded completely, any name identical to
! 755: * macro should not be re-expanded.
! 756: * However, a macro in the string argument of _Pragma() may be expanded by
! 757: * do_pragma() after de_stringize(), if EXPAND_PRAGMA == TRUE.
! 758: */
! 759: {
! 760: FILEINFO * file;
! 761: DEFBUF * defp;
! 762: int prev = output < out_ptr; /* There is a previous sequence */
! 763: int token_type;
! 764: char * cp1, * cp2;
! 765: int c;
! 766:
! 767: file = unget_string( out_ptr, NULL);
! 768: while (c = get_ch(), file == infile) {
! 769: if (char_type[ c] & HSP) {
! 770: *out_ptr++ = c;
! 771: continue;
! 772: }
! 773: if (scan_token( c, (cp1 = out_ptr, &cp1), out_wend)
! 774: == NAM && (defp = is_macro( &cp1)) != NULL
! 775: && defp->nargs == DEF_PRAGMA) { /* _Pragma() operator */
! 776: if (prev) {
! 777: putout( output); /* Putout the previous sequence */
! 778: cp1 = stpcpy( output, "pragma "); /* From top of buffer */
! 779: }
! 780: /* is_macro() already read over possible spaces after _Pragma */
! 781: *cp1++ = get_ch(); /* '(' */
! 782: while (char_type[ c = get_ch()] & HSP)
! 783: *cp1++ = c;
! 784: if (((token_type = scan_token( c, (cp2 = cp1, &cp1), out_wend))
! 785: != STR && token_type != WSTR)) {
! 786: /* Not a string literal */
! 787: put_seq( output, cp1);
! 788: return;
! 789: }
! 790: workp = de_stringize( cp2, work_buf);
! 791: while (char_type[ c = get_ch()] & HSP)
! 792: *cp1++ = c;
! 793: if (c != ')') { /* More than a string literal */
! 794: unget_ch();
! 795: put_seq( output, cp1);
! 796: return;
! 797: }
! 798: strcpy( workp, "\n"); /* Terminate with <newline> */
! 799: unget_string( work_buf, NULL);
! 800: do_pragma(); /* Do the #pragma "line" */
! 801: infile->bptr += strlen( infile->bptr); /* Clear sequence */
! 802: cp1 = out_ptr = output; /* From the top of buffer */
! 803: prev = FALSE;
! 804: } else { /* Not pragma sequence */
! 805: out_ptr = cp1;
! 806: prev = TRUE;
! 807: }
! 808: }
! 809: unget_ch();
! 810: if (prev)
! 811: putout( output);
! 812: }
! 813:
! 814: static void put_seq(
! 815: char * begin, /* Sequence already in buffer */
! 816: char * seq /* Sequence to be read */
! 817: )
! 818: /*
! 819: * Put out the failed sequence as it is.
! 820: */
! 821: {
! 822: FILEINFO * file = infile;
! 823: int c;
! 824:
! 825: cerror( "Operand of _Pragma() is not a string literal" /* _E_ */
! 826: , NULL, 0L, NULL);
! 827: while (c = get_ch(), file == infile)
! 828: *seq++ = c;
! 829: unget_ch();
! 830: out_ptr = seq;
! 831: putout( begin);
! 832: }
! 833:
! 834: static char * de_stringize(
! 835: char * in, /* Null terminated string literal */
! 836: char * out /* Output buffer */
! 837: )
! 838: /*
! 839: * Make token sequence from a string literal for _Pragma() operator.
! 840: */
! 841: {
! 842: char * in_p;
! 843: int c1, c;
! 844:
! 845: in_p = in;
! 846: if (*in_p == 'L')
! 847: in_p++; /* Skip 'L' prefix */
! 848: while ((c = *++in_p) != EOS) {
! 849: if (c == '\\' && ((c1 = *(in_p + 1), c1 == '\\') || c1 == '"'))
! 850: c = *++in_p; /* "De-escape" escape sequence */
! 851: *out++ = c;
! 852: }
! 853: *--out = EOS; /* Remove the closing '"' */
! 854: return out;
! 855: }
! 856:
! 857: static void putout(
! 858: char * out /* Output line (line-end is always 'out_ptr') */
! 859: )
! 860: /*
! 861: * Put out a line with or without "post-preprocessing".
! 862: */
! 863: {
! 864: size_t len;
! 865:
! 866: *out_ptr++ = '\n'; /* Put out a newline */
! 867: *out_ptr = EOS;
! 868:
! 869: #if ! MBCHAR_IS_ESCAPE_FREE
! 870: post_preproc( out);
! 871: #elif ! HAVE_DIGRAPHS
! 872: if (mcpp_mode == STD && option_flag.dig)
! 873: post_preproc( out);
! 874: #endif
! 875: /* Else no post-preprocess */
! 876: #if COMPILER != GNUC && COMPILER != MSC
! 877: /* GCC and Visual C can accept very long line */
! 878: len = strlen( out);
! 879: if (len > NWORK - 1)
! 880: devide_line( out); /* Devide a too long line */
! 881: else
! 882: #endif
! 883: put_a_line( out);
! 884: }
! 885:
! 886: #if COMPILER != GNUC && COMPILER != MSC
! 887:
! 888: static void devide_line(
! 889: char * out /* 'out' is 'output' in actual */
! 890: )
! 891: /*
! 892: * Devide a too long line into output lines shorter than NWORK.
! 893: * This routine is called from putout().
! 894: */
! 895: {
! 896: FILEINFO * file;
! 897: char * save;
! 898: char * wp;
! 899: int c;
! 900:
! 901: file = unget_string( out, NULL); /* To re-read the line */
! 902: wp = out_ptr = out;
! 903:
! 904: while ((c = get_ch()), file == infile) {
! 905: if (char_type[ c] & HSP) {
! 906: if (keep_spaces || out == out_ptr
! 907: || (char_type[ *(out_ptr - 1) & UCHARMAX] & HSP)) {
! 908: *out_ptr++ = c;
! 909: wp++;
! 910: }
! 911: continue;
! 912: }
! 913: scan_token( c, &wp, out_wend); /* Read a token */
! 914: if (NWORK-2 < wp - out_ptr) { /* Too long a token */
! 915: cfatal( "Too long token %s", out_ptr, 0L, NULL); /* _F_ */
! 916: } else if (out_end <= wp) { /* Too long line */
! 917: if (mcpp_debug & MACRO_CALL) { /* -K option */
! 918: /* Other than GCC or Visual C */
! 919: /* scan_token() scans a comment as sequence of some */
! 920: /* tokens such as '/', '*', ..., '*', '/', since it */
! 921: /* does not expect comment. */
! 922: save = out_ptr;
! 923: while ((save = strrchr( save, '/')) != NULL) {
! 924: if (*(save - 1) == '*') { /* '*' '/' sequence */
! 925: out_ptr = save + 1; /* Devide at the end*/
! 926: break; /* of a comment*/
! 927: }
! 928: }
! 929: }
! 930: save = save_string( out_ptr); /* Save the token */
! 931: *out_ptr++ = '\n'; /* Append newline */
! 932: *out_ptr = EOS;
! 933: put_a_line( out); /* Putout the former tokens */
! 934: wp = out_ptr = stpcpy( out, save); /* Restore the token */
! 935: free( save);
! 936: } else { /* Still in size */
! 937: out_ptr = wp; /* Advance the pointer */
! 938: }
! 939: }
! 940:
! 941: unget_ch(); /* Push back the source character */
! 942: put_a_line( out); /* Putout the last tokens */
! 943: sharp( NULL, 0); /* Correct line number */
! 944: }
! 945:
! 946: #endif
! 947:
! 948: static void put_a_line(
! 949: char * out
! 950: )
! 951: /*
! 952: * Finally put out the preprocessed line.
! 953: */
! 954: {
! 955: size_t len;
! 956: char * out_p;
! 957: char * tp;
! 958:
! 959: if (no_output)
! 960: return;
! 961: len = strlen( out);
! 962: tp = out_p = out + len - 2; /* Just before '\n' */
! 963: while (char_type[ *out_p & UCHARMAX] & SPA)
! 964: out_p--; /* Remove trailing white spaces */
! 965: if (out_p < tp) {
! 966: *++out_p = '\n';
! 967: *++out_p = EOS;
! 968: }
! 969: if (mcpp_fputs( out, OUT) == EOF)
! 970: cfatal( "File write error", NULL, 0L, NULL); /* _F_ */
! 971: }
! 972:
! 973:
! 974: /*
! 975: * Routines to P O S T - P R E P R O C E S S
! 976: *
! 977: * 1998/08 created kmatsui (revised 1998/09, 2004/02, 2006/07)
! 978: * Supplementary phase for the older compiler-propers.
! 979: * 1. Convert digraphs to usual tokens.
! 980: * 2. Double '\\' of the second byte of multi-byte characters.
! 981: * These conversions are done selectively according to the macros defined
! 982: * in system.H.
! 983: * 1. Digraphs are converted if ! HAVE_DIGRAPHS and digraph recoginition
! 984: * is enabled by DIGRAPHS_INIT and/or -2 option on execution.
! 985: * 2. '\\' of the second byte of SJIS (BIGFIVE or ISO2022_JP) is doubled
! 986: * if bsl_need_escape == TRUE.
! 987: */
! 988:
! 989: #if HAVE_DIGRAPHS && MBCHAR_IS_ESCAPE_FREE
! 990: /* No post_preproc() */
! 991: #else
! 992:
! 993: static int post_preproc(
! 994: char * out
! 995: )
! 996: /*
! 997: * Convert digraphs and double '\\' of the second byte of SJIS (BIGFIVE or
! 998: * ISO2022_JP).
! 999: * Note: Output of -K option embeds macro informations into comments.
! 1000: * scan_token() does not recognize comment and parses it as '/', '*', etc.
! 1001: */
! 1002: {
! 1003: #if ! HAVE_DIGRAPHS
! 1004: int di_count = 0;
! 1005: #endif
! 1006: int token_type;
! 1007: int c;
! 1008: char * str;
! 1009: char * cp = out;
! 1010:
! 1011: unget_string( out, NULL);
! 1012: while ((c = get_ch()) != '\n') { /* Not to read over to next line */
! 1013: if (char_type[ c] & HSP) {
! 1014: *cp++ = c;
! 1015: continue;
! 1016: }
! 1017: str = cp;
! 1018: token_type = scan_token( c, &cp, out_wend);
! 1019: switch (token_type) {
! 1020: #if ! MBCHAR_IS_ESCAPE_FREE
! 1021: case WSTR :
! 1022: case WCHR :
! 1023: str++; /* Skip prefix 'L' */
! 1024: /* Fall through */
! 1025: case STR :
! 1026: case CHR :
! 1027: if (bsl_need_escape)
! 1028: cp = esc_mbchar( str, cp);
! 1029: break;
! 1030: #endif /* ! MBCHAR_IS_ESCAPE_FREE */
! 1031: #if ! HAVE_DIGRAPHS
! 1032: case OPE :
! 1033: if (mcpp_mode == STD && (openum & OP_DIGRAPH)) {
! 1034: cp = conv_a_digraph( cp); /* Convert a digraph */
! 1035: di_count++;
! 1036: }
! 1037: break;
! 1038: #endif
! 1039: }
! 1040: }
! 1041: *cp++ = '\n';
! 1042: *cp = EOS;
! 1043: #if ! HAVE_DIGRAPHS
! 1044: if (mcpp_mode == STD && di_count && (warn_level & 16))
! 1045: cwarn( "%.0s%ld digraph(s) converted" /* _W16_ */
! 1046: , NULL, (long) di_count, NULL);
! 1047: #endif
! 1048: return 0;
! 1049: }
! 1050:
! 1051: #endif /* ! HAVE_DIGRAPHS || ! MBCHAR_IS_ESCAPE_FREE */
! 1052:
! 1053: #if ! HAVE_DIGRAPHS
! 1054: static char * conv_a_digraph(
! 1055: char * cp /* The end of the digraph token */
! 1056: )
! 1057: /*
! 1058: * Convert a digraph to usual token in place.
! 1059: * This routine is never called in POST_STD mode.
! 1060: */
! 1061: {
! 1062: cp -= 2;
! 1063: switch (openum) {
! 1064: case OP_LBRACE_D :
! 1065: *cp++ = '{';
! 1066: break;
! 1067: case OP_RBRACE_D :
! 1068: *cp++ = '}';
! 1069: break;
! 1070: case OP_LBRCK_D :
! 1071: *cp++ = '[';
! 1072: break;
! 1073: case OP_RBRCK_D :
! 1074: *cp++ = ']';
! 1075: break;
! 1076: case OP_SHARP_D : /* Error of source */
! 1077: *cp++ = '#';
! 1078: break;
! 1079: case OP_DSHARP_D : /* Error of source */
! 1080: cp -= 2;
! 1081: *cp++ = '#';
! 1082: *cp++ = '#';
! 1083: break;
! 1084: }
! 1085: return cp;
! 1086: }
! 1087: #endif /* ! HAVE_DIGRAPHS */
! 1088:
! 1089: #if ! MBCHAR_IS_ESCAPE_FREE
! 1090: static char * esc_mbchar(
! 1091: char * str, /* String literal or character constant without 'L' */
! 1092: char * str_end /* The end of the token */
! 1093: )
! 1094: /*
! 1095: * Insert \ before the byte of 0x5c('\\') of the SJIS, BIGFIVE or ISO2022_JP
! 1096: * multi-byte character code in string literal or character constant.
! 1097: * Insert \ also before the byte of 0x22('"') and 0x27('\'') of ISO2022_JP.
! 1098: * esc_mbchar() does in-place insertion.
! 1099: */
! 1100: {
! 1101: char * cp;
! 1102: int delim;
! 1103: int c;
! 1104:
! 1105: if (! bsl_need_escape)
! 1106: return str_end;
! 1107: if ((delim = *str++) == 'L')
! 1108: delim = *str++; /* The quote character */
! 1109: while ((c = *str++ & UCHARMAX) != delim) {
! 1110: if (char_type[ c] & mbchk) { /* MBCHAR */
! 1111: cp = str;
! 1112: mb_read( c, &str, (workp = work_buf, &workp));
! 1113: while (cp++ < str) {
! 1114: c = *(cp - 1);
! 1115: if (c == '\\' || c == '"' || c == '\'') {
! 1116: /* Insert \ before 0x5c, 0x22, 0x27 */
! 1117: memmove( cp, cp - 1, (size_t) (str_end - cp) + 2);
! 1118: *(cp++ - 1) = '\\';
! 1119: str++;
! 1120: str_end++;
! 1121: }
! 1122: }
! 1123: } else if (c == '\\' && ! (char_type[ *str & UCHARMAX] & mbchk)) {
! 1124: str++; /* Escape sequence */
! 1125: }
! 1126: }
! 1127: return str_end;
! 1128: }
! 1129: #endif /* ! MBCHAR_IS_ESCAPE_FREE */
! 1130:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>