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

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>