Blame src/main.c

Packit Service 8bf002
/*-
Packit Service 8bf002
 * Copyright (c) 1998, 2002-2008 Kiyoshi Matsui <kmatsui@t3.rim.or.jp>
Packit Service 8bf002
 * All rights reserved.
Packit Service 8bf002
 *
Packit Service 8bf002
 * Some parts of this code are derived from the public domain software
Packit Service 8bf002
 * DECUS cpp (1984,1985) written by Martin Minow.
Packit Service 8bf002
 *
Packit Service 8bf002
 * Redistribution and use in source and binary forms, with or without
Packit Service 8bf002
 * modification, are permitted provided that the following conditions
Packit Service 8bf002
 * are met:
Packit Service 8bf002
 * 1. Redistributions of source code must retain the above copyright
Packit Service 8bf002
 *    notice, this list of conditions and the following disclaimer.
Packit Service 8bf002
 * 2. Redistributions in binary form must reproduce the above copyright
Packit Service 8bf002
 *    notice, this list of conditions and the following disclaimer in the
Packit Service 8bf002
 *    documentation and/or other materials provided with the distribution.
Packit Service 8bf002
 *
Packit Service 8bf002
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
Packit Service 8bf002
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit Service 8bf002
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit Service 8bf002
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
Packit Service 8bf002
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit Service 8bf002
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit Service 8bf002
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit Service 8bf002
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit Service 8bf002
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit Service 8bf002
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit Service 8bf002
 * SUCH DAMAGE.
Packit Service 8bf002
 */
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 *                              M A I N . C
Packit Service 8bf002
 *                  M C P P   M a i n   P r o g r a m
Packit Service 8bf002
 *
Packit Service 8bf002
 * The main routine and it's supplementary routines are placed here.
Packit Service 8bf002
 * The post-preprocessing routines are also placed here.
Packit Service 8bf002
 */
Packit Service 8bf002
Packit Service 8bf002
#if PREPROCESSED                /* Use "pre-preprocessed" header    */
Packit Service 8bf002
#include    "mcpp.H"
Packit Service 8bf002
#else
Packit Service 8bf002
#include    "system.H"
Packit Service 8bf002
#include    "internal.H"
Packit Service 8bf002
#endif
Packit Service 8bf002
Packit Service 8bf002
    /* Function pointer to expand_macro() functions.    */
Packit Service 8bf002
    char *   (*expand_macro)( DEFBUF * defp, char * out, char * out_end
Packit Service 8bf002
            , LINE_COL line_col, int * pragma_op);
Packit Service 8bf002
Packit Service 8bf002
    /* The boolean flags specified by the execution options.    */
Packit Service 8bf002
    struct option_flags_    option_flags = {
Packit Service 8bf002
        FALSE,          /* c:   -C (keep comments)                  */
Packit Service 8bf002
        FALSE,          /* k:   -k (keep horizontal white spaces)   */
Packit Service 8bf002
        FALSE,          /* z:   -z (no output of included files)    */
Packit Service 8bf002
        FALSE,          /* p:   -P (no #line output)                */
Packit Service 8bf002
        FALSE,          /* q:   -Q (output diagnosis to mcpp.err)   */
Packit Service 8bf002
        FALSE,          /* v:   -v (verbose, affects macro notification)    */
Packit Service 8bf002
        TRIGRAPHS_INIT, /* trig:    -3 (toggle trigraphs)           */
Packit Service 8bf002
        DIGRAPHS_INIT,  /* dig: -2 (toggle digraphs recognition)    */
Packit Service 8bf002
        /*
Packit Service 8bf002
         * lang_asm allows the following non-standard features.
Packit Service 8bf002
         * 1. #non-directive.
Packit Service 8bf002
         * 2. <newline> in a string-literal.
Packit Service 8bf002
         * 3. invalid pp-token generated by ## operator.
Packit Service 8bf002
         * lang_asm is not available in POST_STD mode.
Packit Service 8bf002
         * When COMPILER == GNUC, -x assembler-with-cpp or -lang-asm options
Packit Service 8bf002
         * are used instead of -a.
Packit Service 8bf002
         */
Packit Service 8bf002
        FALSE,          /* lang_asm:    -a (assembler source)       */
Packit Service 8bf002
        FALSE           /* no_source_line:  -j (no source line in diag)     */
Packit Service 8bf002
    };
Packit Service 8bf002
Packit Service 8bf002
    int     mcpp_mode = STD;        /* Mode of preprocessing        */
Packit Service 8bf002
Packit Service 8bf002
    long    cplus_val = 0L;         /* Value of __cplusplus for C++ */
Packit Service 8bf002
    long    stdc_ver = 0L;          /* Value of __STDC_VERSION__    */
Packit Service 8bf002
    int     stdc_val = 0;           /* Value of __STDC__            */
Packit Service 8bf002
    int     stdc2;              /* cplus_val || stdc_ver >= 199901L */
Packit Service 8bf002
    int     stdc3;              /* cplus_val >= 199901L || stdc_ver >= 199901L.
Packit Service 8bf002
        (cplus_val >= 199901L) specifies compatible mode to C99 (extended
Packit Service 8bf002
        feature of this preprocessor)   */
Packit Service 8bf002
    int     standard = TRUE;    /* TRUE, if mcpp_mode is STD or POST_STD    */
Packit Service 8bf002
    int     std_line_prefix = STD_LINE_PREFIX;
Packit Service 8bf002
            /* Output line and file information in C source style   */
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 * Commonly used global variables:
Packit Service 8bf002
 * src_line     is the current input line number.
Packit Service 8bf002
 * wrong_line   is set in many places when the actual output line is out of
Packit Service 8bf002
 *              sync with the numbering, e.g, when expanding a macro with an
Packit Service 8bf002
 *              embedded newline.
Packit Service 8bf002
 * identifier   holds the last identifier scanned (which might be a candidate
Packit Service 8bf002
 *              for macro expansion).
Packit Service 8bf002
 * errors       is the running mcpp error counter.
Packit Service 8bf002
 * infile       is the head of a linked list of input files (extended by
Packit Service 8bf002
 *              #include and macros being expanded).  'infile' always points
Packit Service 8bf002
 *              to the current file/macro.  'infile->parent' to the includer,
Packit Service 8bf002
 *              etc.  'infile->fp' is NULL if this input stream is not a file.
Packit Service 8bf002
 * inc_dirp     Directory of #includer with trailing PATH_DELIM.  This points
Packit Service 8bf002
 *              to one of incdir[] or to the current directory (represented as
Packit Service 8bf002
 *              "".  This should not be NULL.
Packit Service 8bf002
 */
Packit Service 8bf002
    long        src_line;           /* Current line number          */
Packit Service 8bf002
    int         wrong_line;         /* Force #line to compiler      */
Packit Service 8bf002
    int         newlines;           /* Count of blank lines         */
Packit Service 8bf002
    int         errors = 0;         /* Cpp error counter            */
Packit Service 8bf002
    int         warn_level = -1;    /* Level of warning (have to initialize)*/
Packit Service 8bf002
    FILEINFO *  infile = NULL;      /* Current input file           */
Packit Service 8bf002
    int         include_nest = 0;   /* Nesting level of #include    */
Packit Service 8bf002
    const char *    null = "";      /* "" string for convenience    */
Packit Service 8bf002
    const char **   inc_dirp;       /* Directory of #includer       */
Packit Service 8bf002
    const char *    cur_fname;      /* Current source file name     */
Packit Service 8bf002
                /* cur_fname is not rewritten by #line directive    */
Packit Service 8bf002
    char *      cur_fullname;
Packit Service 8bf002
        /* Full path of current source file (i.e. infile->full_fname)       */
Packit Service 8bf002
    int         no_source_line;     /* Do not output line in diag.  */
Packit Service 8bf002
    char        identifier[ IDMAX + IDMAX/8];       /* Current identifier   */
Packit Service 8bf002
    int         mcpp_debug = 0;     /* != 0 if debugging now        */
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 *   in_directive is set TRUE while a directive line is scanned by directive().
Packit Service 8bf002
 * It modifies the behavior of squeeze_ws() in expand.c so that newline is
Packit Service 8bf002
 * not skipped even if getting macro arguments.
Packit Service 8bf002
 */
Packit Service 8bf002
    int     in_directive = FALSE;   /* TRUE scanning directive line */
Packit Service 8bf002
    int     in_define = FALSE;      /* TRUE scanning #define line   */
Packit Service 8bf002
    int     in_getarg = FALSE;      /* TRUE collecting macro arguments      */
Packit Service 8bf002
    int     in_include = FALSE;     /* TRUE scanning #include line  */
Packit Service 8bf002
    int     in_if = FALSE;  /* TRUE scanning #if and in non-skipped expr.   */
Packit Service 8bf002
    long    in_asm = 0L;    /* Starting line of #asm - #endasm block*/
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 *   macro_line is set to the line number of start of a macro call while
Packit Service 8bf002
 * expanding the macro, else set to 0.  Line number is remembered for
Packit Service 8bf002
 * diagnostics of unterminated macro call.  On unterminated macro call
Packit Service 8bf002
 * macro_line is set to MACRO_ERROR.
Packit Service 8bf002
 */
Packit Service 8bf002
    long    macro_line = 0L;
Packit Service 8bf002
/*
Packit Service 8bf002
 *   macro_name is the currently expanding macro.
Packit Service 8bf002
 */
Packit Service 8bf002
    char *  macro_name;
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 * openum is the return value of scan_op() in support.c.
Packit Service 8bf002
 */
Packit Service 8bf002
    int     openum;
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 *   mkdep means to output source file dependency line, specified by -M*
Packit Service 8bf002
 * option.  The OR of the following values is used.
Packit Service 8bf002
 *      MD_MKDEP    (1) :   Output dependency line.
Packit Service 8bf002
 *      MD_SYSHEADER(2) :   Print also system headers or headers with
Packit Service 8bf002
 *          absolute path not only user headers.
Packit Service 8bf002
 *      MD_FILE     (4) :   Output to the file named *.d instead of fp_out.
Packit Service 8bf002
 *          Normal output is done to fp_out as usual.
Packit Service 8bf002
 */
Packit Service 8bf002
    int     mkdep = 0;
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 * If option_flags.z is TRUE, no_output is incremented when a file is
Packit Service 8bf002
 * #included, and decremented when the file is finished.
Packit Service 8bf002
 * If no_output is larger than 0, processed files are not output, meanwhile
Packit Service 8bf002
 * the macros in the files are defined.
Packit Service 8bf002
 * If mkdep != 0 && (mkdep & MD_FILE) == 0, no_output is set to 1 initially.
Packit Service 8bf002
 */
Packit Service 8bf002
    int     no_output = 0;
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 * keep_comments is set TRUE by the -C option.  If TRUE, comments are written
Packit Service 8bf002
 * directly to the output stream.  option_flags.c contains the permanent state
Packit Service 8bf002
 * of the -C option.  keep_comments is always falsified when compilation is
Packit Service 8bf002
 * supressed by a false #if or when no_output is TRUE.
Packit Service 8bf002
 */
Packit Service 8bf002
    int     keep_comments = 0;          /* Write out comments flag  */
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 * keep_spaces is set to TRUE by the -k option.  If TRUE, spaces and tabs in
Packit Service 8bf002
 * an input line are written out to the output line without squeezing to one
Packit Service 8bf002
 * space.  option_flags.k contains the permanent state of the -k option.
Packit Service 8bf002
 * keep_spaces is falsified when compilation is suppressed by a false #if.
Packit Service 8bf002
 */
Packit Service 8bf002
    int     keep_spaces = 0;            /* Keep white spaces of line*/
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 * ifstack[] holds information about nested #if's.  It is always accessed via
Packit Service 8bf002
 * ifptr->stat.  The information is as follows:
Packit Service 8bf002
 *      WAS_COMPILING   state of compiling flag at outer level.
Packit Service 8bf002
 *      ELSE_SEEN       set TRUE when #else seen to prevent 2nd #else.
Packit Service 8bf002
 *      TRUE_SEEN       set TRUE when #if or #elif succeeds
Packit Service 8bf002
 * ifstack[0].stat holds the compiling flag.  It is WAS_COMPILING if compila-
Packit Service 8bf002
 * tion is currently enabled.  Note that this must be initialized to
Packit Service 8bf002
 * WAS_COMPILING.
Packit Service 8bf002
 */
Packit Service 8bf002
    IFINFO      ifstack[ BLK_NEST + 1] = { {WAS_COMPILING, 0L, 0L}, };
Packit Service 8bf002
                /* Note: '+1' is necessary for the initial state.   */
Packit Service 8bf002
    IFINFO *    ifptr = ifstack;        /* -> current ifstack[]     */
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 * In POST_STD mode, insert_sep is set to INSERT_SEP when :
Packit Service 8bf002
 *  1. the next get_ch() shall insert a token separator.
Packit Service 8bf002
 *  2. unget_ch() has been called when insert_sep == INSERTED_SEP.
Packit Service 8bf002
 * set to INSERTED_SEP when :
Packit Service 8bf002
 *  get_ch() has been called when insert_sep == INSERT_SEP.
Packit Service 8bf002
 * set to NO_SEP when :
Packit Service 8bf002
 *  get_ch() has been called when insert_sep == INSERTED_SEP.
Packit Service 8bf002
 */
Packit Service 8bf002
    int     insert_sep = NO_SEP;
Packit Service 8bf002
Packit Service 8bf002
/* File pointers for input and output.  */
Packit Service 8bf002
    FILE *  fp_in;                  /* Input stream to preprocess   */
Packit Service 8bf002
    FILE *  fp_out;                 /* Output stream preprocessed   */
Packit Service 8bf002
    FILE *  fp_err;                 /* Diagnostics stream           */
Packit Service 8bf002
    FILE *  fp_debug;               /* Debugging information stream */
Packit Service 8bf002
Packit Service 8bf002
/* Variables on multi-byte character encodings. */
Packit Service 8bf002
    int     mbchar = MBCHAR;        /* Encoding of multi-byte char  */
Packit Service 8bf002
    int     mbchk;  /* Character type of possible multi-byte char   */
Packit Service 8bf002
    int     bsl_in_mbchar;  /* 2nd byte of mbchar possibly has '\\' */
Packit Service 8bf002
    int     bsl_need_escape;    /* '\\' in MBCHAR should be escaped */
Packit Service 8bf002
    /* Function pointer to mb_read_*() functions.   */
Packit Service 8bf002
    size_t  (*mb_read)( int c1, char ** in_pp, char ** out_pp);
Packit Service 8bf002
Packit Service 8bf002
    jmp_buf error_exit;             /* Exit on fatal error          */
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 * Translation limits specified by C90, C99 or C++.
Packit Service 8bf002
 */
Packit Service 8bf002
    struct std_limits_  std_limits = {
Packit Service 8bf002
        /* The following three are temporarily set for do_options() */
Packit Service 8bf002
        NBUFF,          /* Least maximum of string length           */
Packit Service 8bf002
        IDMAX,          /* Least maximum of identifier length       */
Packit Service 8bf002
        NMACPARS,       /* Least maximum of number of macro params  */
Packit Service 8bf002
    };
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 * work_buf[] and workp are used to store one piece of text as a temporary
Packit Service 8bf002
 * buffer.
Packit Service 8bf002
 * To initialize storage, set workp = work_buf.  Note that the work buffer is
Packit Service 8bf002
 * used by several subroutines -- be sure that your data won't be overwritten.
Packit Service 8bf002
 * work_buf[] is used for:
Packit Service 8bf002
 *      1. macro expansion (def_special(), prescan(), catenate(),
Packit Service 8bf002
 *         stringize()).
Packit Service 8bf002
 *      2. processing directive line (directive.c, eval.c, get_unexpandable(),
Packit Service 8bf002
 *         do_pragma() and its subroutines).
Packit Service 8bf002
 *      3. processing _Pragma() operator (do_pragma_op()).
Packit Service 8bf002
 *      4. miscellaneous (init_gcc_macro(), curfile()). 
Packit Service 8bf002
 */
Packit Service 8bf002
    char        work_buf[ NWORK + IDMAX];       /* Work buffer      */
Packit Service 8bf002
    char *      workp;              /* Pointer into work_buf[]      */
Packit Service 8bf002
    char * const     work_end = & work_buf[ NWORK];
Packit Service 8bf002
                                    /* End of buffer of work_buf[]  */
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 * src_col      is the current input column number, but is rarely used.
Packit Service 8bf002
 *              It is used to put spaces after #line line in keep_spaces mode
Packit Service 8bf002
 *              on some special cases.
Packit Service 8bf002
 */
Packit Service 8bf002
static int      src_col = 0;        /* Column number of source line */
Packit Service 8bf002
Packit Service 8bf002
#define MBCHAR_IS_ESCAPE_FREE   (SJIS_IS_ESCAPE_FREE && \
Packit Service 8bf002
            BIGFIVE_IS_ESCAPE_FREE && ISO2022_JP_IS_ESCAPE_FREE)
Packit Service 8bf002
Packit Service 8bf002
#if MCPP_LIB
Packit Service 8bf002
static void     init_main( void);
Packit Service 8bf002
                /* Initialize static variables      */
Packit Service 8bf002
#endif
Packit Service 8bf002
static void     init_defines( void);
Packit Service 8bf002
                /* Predefine macros                 */
Packit Service 8bf002
static void     mcpp_main( void);
Packit Service 8bf002
                /* Main loop to process input lines */
Packit Service 8bf002
static void     do_pragma_op( void);
Packit Service 8bf002
                /* Execute the _Pragma() operator   */
Packit Service 8bf002
static void     put_seq( char * begin, char * seq);
Packit Service 8bf002
                /* Put out the failed sequence      */
Packit Service 8bf002
static char *   de_stringize( char * in, char * out);
Packit Service 8bf002
                /* "De-stringize" for _Pragma() op. */
Packit Service 8bf002
static void     putout( char * out);
Packit Service 8bf002
                /* May concatenate adjacent string  */
Packit Service 8bf002
#if COMPILER != GNUC && COMPILER != MSC
Packit Service 8bf002
static void     devide_line( char * out);
Packit Service 8bf002
                /* Devide long line for compiler    */
Packit Service 8bf002
#endif
Packit Service 8bf002
static void     put_a_line( char * out);
Packit Service 8bf002
                /* Put out the processed line       */
Packit Service 8bf002
#if ! HAVE_DIGRAPHS || ! MBCHAR_IS_ESCAPE_FREE
Packit Service 8bf002
static int      post_preproc( char * out);
Packit Service 8bf002
                /* Post-preprocess for older comps  */
Packit Service 8bf002
#if ! HAVE_DIGRAPHS
Packit Service 8bf002
static char *   conv_a_digraph( char * cp);
Packit Service 8bf002
                /* Convert a digraph in place       */
Packit Service 8bf002
#endif
Packit Service 8bf002
#if ! MBCHAR_IS_ESCAPE_FREE
Packit Service 8bf002
static char *   esc_mbchar( char * str, char * str_end);
Packit Service 8bf002
                /* Double \ as 2nd byte of SJIS     */
Packit Service 8bf002
#endif
Packit Service 8bf002
#endif
Packit Service 8bf002
Packit Service 8bf002
Packit Service 8bf002
#if MCPP_LIB
Packit Service 8bf002
static void     init_main( void)
Packit Service 8bf002
/* Initialize global variables on re-entering.  */
Packit Service 8bf002
{
Packit Service 8bf002
    mcpp_mode = STD;
Packit Service 8bf002
    cplus_val = stdc_ver = 0L;
Packit Service 8bf002
    stdc_val = 0;
Packit Service 8bf002
    standard = TRUE;
Packit Service 8bf002
    std_line_prefix = STD_LINE_PREFIX;
Packit Service 8bf002
    errors = src_col = 0;
Packit Service 8bf002
    warn_level = -1;
Packit Service 8bf002
    infile = NULL;
Packit Service 8bf002
    in_directive = in_define = in_getarg = in_include = in_if = FALSE;
Packit Service 8bf002
    src_line = macro_line = in_asm = 0L;
Packit Service 8bf002
    mcpp_debug = mkdep = no_output = keep_comments = keep_spaces = 0;
Packit Service 8bf002
    include_nest = 0;
Packit Service 8bf002
    insert_sep = NO_SEP;
Packit Service 8bf002
    mbchar = MBCHAR;
Packit Service 8bf002
    ifptr = ifstack;
Packit Service 8bf002
    ifstack[0].stat = WAS_COMPILING;
Packit Service 8bf002
    ifstack[0].ifline = ifstack[0].elseline = 0L;
Packit Service 8bf002
    std_limits.str_len = NBUFF;
Packit Service 8bf002
    std_limits.id_len = IDMAX;
Packit Service 8bf002
    std_limits.n_mac_pars =  NMACPARS;
Packit Service 8bf002
    option_flags.c = option_flags.k = option_flags.z = option_flags.p
Packit Service 8bf002
            = option_flags.q = option_flags.v = option_flags.lang_asm
Packit Service 8bf002
            = option_flags.no_source_line = option_flags.dollar_in_name
Packit Service 8bf002
            = FALSE;
Packit Service 8bf002
    option_flags.trig = TRIGRAPHS_INIT;
Packit Service 8bf002
    option_flags.dig = DIGRAPHS_INIT;
Packit Service 15ba5b
    sh_file = NULL;
Packit Service 15ba5b
    sh_line = 0;
Packit Service 8bf002
}
Packit Service 8bf002
Packit Service 8bf002
int     mcpp_lib_main
Packit Service 8bf002
#else
Packit Service 8bf002
int     main
Packit Service 8bf002
#endif
Packit Service 8bf002
(
Packit Service 8bf002
    int argc,
Packit Service 8bf002
    char ** argv
Packit Service 8bf002
)
Packit Service 8bf002
{
Packit Service 8bf002
    char *  in_file = NULL;
Packit Service 8bf002
    char *  out_file = NULL;
Packit Service 8bf002
    char *  stdin_name = "<stdin>";
Packit Service 8bf002
Packit Service 8bf002
    if (setjmp( error_exit) == -1) {
Packit Service 8bf002
        errors++;
Packit Service 8bf002
        goto  fatal_error_exit;
Packit Service 8bf002
    }
Packit Service 8bf002
Packit Service 8bf002
#if MCPP_LIB
Packit Service 8bf002
    /* Initialize global and static variables.  */
Packit Service 8bf002
    init_main();
Packit Service 8bf002
    init_directive();
Packit Service 8bf002
    init_eval();
Packit Service 8bf002
    init_support();
Packit Service 8bf002
    init_system();
Packit Service 8bf002
#endif
Packit Service 8bf002
Packit Service 8bf002
    fp_in = stdin;
Packit Service 8bf002
    fp_out = stdout;
Packit Service 8bf002
    fp_err = stderr;
Packit Service 8bf002
    fp_debug = stdout;
Packit Service 8bf002
        /*
Packit Service 8bf002
         * Debugging information is output to stdout in order to
Packit Service 8bf002
         *      synchronize with preprocessed output.
Packit Service 8bf002
         */
Packit Service 8bf002
Packit Service 8bf002
    inc_dirp = &nul;;   /* Initialize to current (null) directory   */
Packit Service 8bf002
    cur_fname = cur_fullname = "(predefined)";  /* For predefined macros    */
Packit Service 8bf002
    init_defines();                         /* Predefine macros     */
Packit Service 8bf002
    mb_init();      /* Should be initialized prior to get options   */
Packit Service 8bf002
    do_options( argc, argv, &in_file, &out_file);   /* Command line options */
Packit Service 8bf002
Packit Service 8bf002
    /* Open input file, "-" means stdin.    */
Packit Service 8bf002
    if (in_file != NULL && ! str_eq( in_file, "-")) {
Packit Service 8bf002
        if ((fp_in = fopen( in_file, "r")) == NULL) {
Packit Service 8bf002
            mcpp_fprintf( ERR, "Can't open input file \"%s\".\n", in_file);
Packit Service 8bf002
            errors++;
Packit Service 8bf002
#if MCPP_LIB
Packit Service 8bf002
            goto  fatal_error_exit;
Packit Service 8bf002
#else
Packit Service 8bf002
            return( IO_ERROR);
Packit Service 8bf002
#endif
Packit Service 8bf002
        }
Packit Service 8bf002
    } else {
Packit Service 8bf002
        in_file = stdin_name;
Packit Service 8bf002
    }
Packit Service 8bf002
    /* Open output file, "-" means stdout.  */
Packit Service 8bf002
    if (out_file != NULL && ! str_eq( out_file, "-")) {
Packit Service 8bf002
        if ((fp_out = fopen( out_file, "w")) == NULL) {
Packit Service 8bf002
            mcpp_fprintf( ERR, "Can't open output file \"%s\".\n", out_file);
Packit Service 8bf002
            errors++;
Packit Service 8bf002
#if MCPP_LIB
Packit Service 8bf002
            goto  fatal_error_exit;
Packit Service 8bf002
#else
Packit Service 8bf002
            return( IO_ERROR);
Packit Service 8bf002
#endif
Packit Service 8bf002
        }
Packit Service 8bf002
        fp_debug = fp_out;
Packit Service 8bf002
    }
Packit Service 8bf002
    if (option_flags.q) {                   /* Redirect diagnostics */
Packit Service 8bf002
        if ((fp_err = fopen( "mcpp.err", "a")) == NULL) {
Packit Service 8bf002
            errors++;
Packit Service 8bf002
            mcpp_fprintf( OUT, "Can't open \"mcpp.err\"\n");
Packit Service 8bf002
#if MCPP_LIB
Packit Service 8bf002
            goto  fatal_error_exit;
Packit Service 8bf002
#else
Packit Service 8bf002
            return( IO_ERROR);
Packit Service 8bf002
#endif
Packit Service 8bf002
        }
Packit Service 8bf002
    }
Packit Service 8bf002
    init_sys_macro();       /* Initialize system-specific macros    */
Packit Service 8bf002
    add_file( fp_in, NULL, in_file, in_file, FALSE);
Packit Service 8bf002
                                        /* "open" main input file   */
Packit Service 8bf002
    infile->dirp = inc_dirp;
Packit Service 8bf002
    infile->sys_header = FALSE;
Packit Service 8bf002
    cur_fullname = in_file;
Packit Service 8bf002
    if (mkdep && str_eq( infile->real_fname, stdin_name) == FALSE)
Packit Service 8bf002
        put_depend( in_file);       /* Putout target file name      */
Packit Service 8bf002
    at_start();                     /* Do the pre-main commands     */
Packit Service 8bf002
Packit Service 8bf002
    mcpp_main();                    /* Process main file            */
Packit Service 8bf002
Packit Service 8bf002
    if (mkdep)
Packit Service 8bf002
        put_depend( NULL);      /* Append '\n' to dependency line   */
Packit Service 8bf002
    at_end();                       /* Do the final commands        */
Packit Service 8bf002
Packit Service 8bf002
fatal_error_exit:
Packit Service 8bf002
#if MCPP_LIB
Packit Service 8bf002
    /* Free malloced memory */
Packit Service 8bf002
    if (mcpp_debug & MACRO_CALL) {
Packit Service 8bf002
        if (in_file != stdin_name)
Packit Service 8bf002
            free( in_file);
Packit Service 8bf002
    }
Packit Service 8bf002
    clear_filelist();
Packit Service 8bf002
    clear_symtable();
Packit Service 8bf002
#endif
Packit Service 8bf002
Packit Service 8bf002
    if (fp_in != stdin)
Packit Service 8bf002
        fclose( fp_in);
Packit Service 8bf002
    if (fp_out != stdout)
Packit Service 8bf002
        fclose( fp_out);
Packit Service 8bf002
    if (fp_err != stderr)
Packit Service 8bf002
        fclose( fp_err);
Packit Service 8bf002
Packit Service 8bf002
    if (mcpp_debug & MEMORY)
Packit Service 8bf002
        print_heap();
Packit Service 8bf002
    if (errors > 0 && option_flags.no_source_line == FALSE) {
Packit Service 8bf002
        mcpp_fprintf( ERR, "%d error%s in preprocessor.\n",
Packit Service 8bf002
                errors, (errors == 1) ? "" : "s");
Packit Service 8bf002
        return  IO_ERROR;
Packit Service 8bf002
    }
Packit Service 8bf002
    return  IO_SUCCESS;                             /* No errors    */
Packit Service 8bf002
}
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 * This is the table used to predefine target machine, operating system and
Packit Service 8bf002
 * compiler designators.  It may need hacking for specific circumstances.
Packit Service 8bf002
 * The -N option supresses these definitions.
Packit Service 8bf002
 */
Packit Service 8bf002
typedef struct pre_set {
Packit Service 8bf002
    const char *    name;
Packit Service 8bf002
    const char *    val;
Packit Service 8bf002
} PRESET;
Packit Service 8bf002
Packit Service 8bf002
static PRESET   preset[] = {
Packit Service 8bf002
Packit Service 8bf002
#ifdef  SYSTEM_OLD
Packit Service 8bf002
        { SYSTEM_OLD, "1"},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  SYSTEM_SP_OLD
Packit Service 8bf002
        { SYSTEM_SP_OLD, "1"},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  COMPILER_OLD
Packit Service 8bf002
        { COMPILER_OLD, "1"},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  COMPILER_SP_OLD
Packit Service 8bf002
        { COMPILER_SP_OLD, "1"},
Packit Service 8bf002
#endif
Packit Service 8bf002
Packit Service 8bf002
        { NULL, NULL},  /* End of macros beginning with alphabet    */
Packit Service 8bf002
Packit Service 8bf002
#ifdef  SYSTEM_STD
Packit Service 8bf002
        { SYSTEM_STD, "1"},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  SYSTEM_STD1
Packit Service 8bf002
        { SYSTEM_STD1, "1"},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  SYSTEM_STD2
Packit Service 8bf002
        { SYSTEM_STD2, "1"},
Packit Service 8bf002
#endif
Packit Service 8bf002
Packit Service 8bf002
#ifdef  SYSTEM_EXT
Packit Service 8bf002
        { SYSTEM_EXT, SYSTEM_EXT_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  SYSTEM_EXT2
Packit Service 8bf002
        { SYSTEM_EXT2, SYSTEM_EXT2_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  SYSTEM_SP_STD
Packit Service 8bf002
        { SYSTEM_SP_STD, SYSTEM_SP_STD_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  COMPILER_STD
Packit Service 8bf002
        { COMPILER_STD, COMPILER_STD_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  COMPILER_STD1
Packit Service 8bf002
        { COMPILER_STD1, COMPILER_STD1_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  COMPILER_STD2
Packit Service 8bf002
        { COMPILER_STD2, COMPILER_STD2_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  COMPILER_EXT
Packit Service 8bf002
        { COMPILER_EXT, COMPILER_EXT_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  COMPILER_EXT2
Packit Service 8bf002
        { COMPILER_EXT2, COMPILER_EXT2_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  COMPILER_SP_STD
Packit Service 8bf002
        { COMPILER_SP_STD, COMPILER_SP_STD_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  COMPILER_SP1
Packit Service 8bf002
        { COMPILER_SP1, COMPILER_SP1_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  COMPILER_SP2
Packit Service 8bf002
        { COMPILER_SP2, COMPILER_SP2_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  COMPILER_SP3
Packit Service 8bf002
        { COMPILER_SP3, COMPILER_SP3_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
#ifdef  COMPILER_CPLUS
Packit Service 8bf002
        { COMPILER_CPLUS, COMPILER_CPLUS_VAL},
Packit Service 8bf002
#endif
Packit Service 8bf002
        { NULL, NULL},  /* End of macros with value of any integer  */
Packit Service 8bf002
};
Packit Service 8bf002
Packit Service 8bf002
static void init_defines( void)
Packit Service 8bf002
/*
Packit Service 8bf002
 * Initialize the built-in #define's.
Packit Service 8bf002
 * Called only on cpp startup prior to do_options().
Packit Service 8bf002
 *
Packit Service 8bf002
 * Note: the built-in static definitions are removed by the -N option.
Packit Service 8bf002
 */
Packit Service 8bf002
{
Packit Service 8bf002
    int     n = sizeof preset / sizeof (PRESET);
Packit Service 8bf002
    int     nargs;
Packit Service 8bf002
    PRESET *    pp;
Packit Service 8bf002
Packit Service 8bf002
    /* Predefine the built-in symbols.  */
Packit Service 8bf002
    nargs = DEF_NOARGS_PREDEF_OLD;
Packit Service 8bf002
    for (pp = preset; pp < preset + n; pp++) {
Packit Service 8bf002
        if (pp->name && *(pp->name))
Packit Service 8bf002
            look_and_install( pp->name, nargs, null, pp->val);
Packit Service 8bf002
        else if (! pp->name)
Packit Service 8bf002
            nargs = DEF_NOARGS_PREDEF;
Packit Service 8bf002
    }
Packit Service 8bf002
Packit Service 8bf002
    look_and_install( "__MCPP", DEF_NOARGS_PREDEF, null, "2");
Packit Service 8bf002
    /* MCPP V.2.x   */
Packit Service 8bf002
    /* This macro is predefined and is not undefined by -N option,  */
Packit Service 8bf002
    /*      yet can be undefined by -U or #undef.                   */
Packit Service 8bf002
}
Packit Service 8bf002
Packit Service 8bf002
void    un_predefine(
Packit Service 8bf002
    int clearall                            /* TRUE for -N option   */
Packit Service 8bf002
)
Packit Service 8bf002
/*
Packit Service 8bf002
 * Remove predefined symbols from the symbol table.
Packit Service 8bf002
 */
Packit Service 8bf002
{
Packit Service 8bf002
    PRESET *    pp;
Packit Service 8bf002
    DEFBUF *    defp;
Packit Service 8bf002
    int     n = sizeof preset / sizeof (PRESET);
Packit Service 8bf002
Packit Service 8bf002
    for (pp = preset; pp < preset + n; pp++) {
Packit Service 8bf002
        if (pp->name) {
Packit Service 8bf002
            if (*(pp->name) && (defp = look_id( pp->name)) != NULL
Packit Service 8bf002
                    && defp->nargs >= DEF_NOARGS_PREDEF)
Packit Service 8bf002
                undefine( pp->name);
Packit Service 8bf002
        } else if (clearall == FALSE) {             /* -S<n> option */
Packit Service 8bf002
            break;
Packit Service 8bf002
        }
Packit Service 8bf002
    }
Packit Service 8bf002
}
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 * output[] and out_ptr are used for:
Packit Service 8bf002
 *      buffer to store preprocessed line (this line is put out or handed to
Packit Service 8bf002
 *      post_preproc() via putout() in some cases)
Packit Service 8bf002
 */
Packit Service 8bf002
static char     output[ NMACWORK];  /* Buffer for preprocessed line */
Packit Service 8bf002
static char * const out_end = & output[ NWORK - 2];
Packit Service 8bf002
                /* Limit of output line for other than GCC and VC   */
Packit Service 8bf002
static char * const out_wend = & output[ NMACWORK - 2];
Packit Service 8bf002
                                    /* Buffer end of output line    */
Packit Service 8bf002
static char *       out_ptr;        /* Current pointer into output[]*/
Packit Service 8bf002
Packit Service 8bf002
static void mcpp_main( void)
Packit Service 8bf002
/*
Packit Service 8bf002
 * Main process for mcpp -- copies tokens from the current input stream
Packit Service 8bf002
 * (main file or included file) to the output file.
Packit Service 8bf002
 */
Packit Service 8bf002
{
Packit Service 8bf002
    int     c;                      /* Current character            */
Packit Service 8bf002
    char *  wp;                     /* Temporary pointer            */
Packit Service 8bf002
    DEFBUF *    defp;               /* Macro definition             */
Packit Service 8bf002
    int     line_top;       /* Is in the line top, possibly spaces  */
Packit Service 8bf002
    LINE_COL    line_col;   /* Location of macro call in source     */
Packit Service 8bf002
Packit Service 8bf002
    keep_comments = option_flags.c && !no_output;
Packit Service 8bf002
    keep_spaces = option_flags.k;       /* Will be turned off if !compiling */
Packit Service 8bf002
    line_col.col = line_col.line = 0L;
Packit Service 8bf002
Packit Service 8bf002
    /*
Packit Service 8bf002
     * This loop is started "from the top" at the beginning of each line.
Packit Service 8bf002
     * 'wrong_line' is set TRUE in many places if it is necessary to write
Packit Service 8bf002
     * a #line record.  (But we don't write them when expanding macros.)
Packit Service 8bf002
     *
Packit Service 8bf002
     * 'newlines' variable counts the number of blank lines that have been
Packit Service 8bf002
     * skipped over.  These are then either output via #line records or
Packit Service 8bf002
     * by outputting explicit blank lines.
Packit Service 8bf002
     * 'newlines' will be cleared on end of an included file by get_ch().
Packit Service 8bf002
     */
Packit Service 8bf002
    while (1) {                             /* For the whole input  */
Packit Service 8bf002
        newlines = 0;                       /* Count empty lines    */
Packit Service 8bf002
Packit Service 8bf002
        while (1) {                         /* For each line, ...   */
Packit Service 8bf002
            out_ptr = output;               /* Top of the line buf  */
Packit Service 8bf002
            c = get_ch();
Packit Service 8bf002
            if (src_col)
Packit Service 8bf002
                break;  /* There is a residual tokens on the line   */
Packit Service 8bf002
            while (char_type[ c] & HSP) {   /* ' ' or '\t'          */
Packit Service 8bf002
                if (c != COM_SEP)
Packit Service 8bf002
                    *out_ptr++ = c; /* Retain line top white spaces */
Packit Service 8bf002
                                    /* Else skip 0-length comment   */
Packit Service 8bf002
                c = get_ch();
Packit Service 8bf002
            }
Packit Service 8bf002
            if (c == '#') {                 /* Is 1st non-space '#' */
Packit Service 8bf002
                directive();                /* Do a #directive      */
Packit Service 8bf002
            } else if (mcpp_mode == STD && option_flags.dig && c == '%') {
Packit Service 8bf002
                    /* In POST_STD digraphs are already converted   */
Packit Service 8bf002
                if (get_ch() == ':') {      /* '%:' i.e. '#'        */
Packit Service 8bf002
                    directive();            /* Do a #directive      */
Packit Service 8bf002
                } else {
Packit Service 8bf002
                    unget_ch();
Packit Service 8bf002
                    if (! compiling) {
Packit Service 8bf002
                        skip_nl();
Packit Service 8bf002
                        newlines++;
Packit Service 8bf002
                    } else {
Packit Service 8bf002
                        break;
Packit Service 8bf002
                    }
Packit Service 8bf002
                }
Packit Service 8bf002
            } else if (c == CHAR_EOF) {     /* End of input         */
Packit Service 8bf002
                break;
Packit Service 8bf002
            } else if (! compiling) {       /* #ifdef false?        */
Packit Service 8bf002
                skip_nl();                  /* Skip to newline      */
Packit Service 8bf002
                newlines++;                 /* Count it, too.       */
Packit Service 8bf002
            } else if (in_asm && ! no_output) { /* In #asm block    */
Packit Service 8bf002
                put_asm();                  /* Put out as it is     */
Packit Service 8bf002
            } else if (c == '\n') {         /* Blank line           */
Packit Service 8bf002
                if (keep_comments)
Packit Service 8bf002
                    mcpp_fputc( '\n', OUT); /* May flush comments   */
Packit Service 8bf002
                else
Packit Service 8bf002
                    newlines++;             /* Wait for a token     */
Packit Service 8bf002
            } else {
Packit Service 8bf002
                break;                      /* Actual token         */
Packit Service 8bf002
            }
Packit Service 8bf002
        }
Packit Service 8bf002
Packit Service 8bf002
        if (c == CHAR_EOF)                  /* Exit process at      */
Packit Service 8bf002
            break;                          /*   end of input       */
Packit Service 8bf002
Packit Service 8bf002
        /*
Packit Service 8bf002
         * If the loop didn't terminate because of end of file, we
Packit Service 8bf002
         * know there is a token to compile.  First, clean up after
Packit Service 8bf002
         * absorbing newlines.  newlines has the number we skipped.
Packit Service 8bf002
         */
Packit Service 8bf002
        if (no_output) {
Packit Service 8bf002
            wrong_line = FALSE;
Packit Service 8bf002
        } else {
Packit Service 8bf002
            if (wrong_line || newlines > 10) {
Packit Service 8bf002
                sharp( NULL, 0);            /* Output # line number */
Packit Service 8bf002
                if (keep_spaces && src_col) {
Packit Service 8bf002
                    while (src_col--)       /* Adjust columns       */
Packit Service 8bf002
                        mcpp_fputc( ' ', OUT);
Packit Service 8bf002
                    src_col = 0;
Packit Service 8bf002
                }
Packit Service 8bf002
            } else {                        /* If just a few, stuff */
Packit Service 8bf002
                while (newlines-- > 0)      /* them out ourselves   */
Packit Service 8bf002
                    mcpp_fputc('\n', OUT);
Packit Service 8bf002
            }
Packit Service 8bf002
        }
Packit Service 8bf002
Packit Service 8bf002
        /*
Packit Service 8bf002
         * Process each token on this line.
Packit Service 8bf002
         */
Packit Service 8bf002
        line_top = TRUE;
Packit Service 8bf002
        while (c != '\n' && c != CHAR_EOF) {    /* For the whole line   */
Packit Service 8bf002
            /*
Packit Service 8bf002
             * has_pragma is set to TRUE so as to execute _Pragma() operator
Packit Service 8bf002
             * when the psuedo macro _Pragma() is found.
Packit Service 8bf002
             */
Packit Service 8bf002
            int     has_pragma;
Packit Service 8bf002
Packit Service 8bf002
            if ((mcpp_debug & MACRO_CALL) && ! in_directive) {
Packit Service 8bf002
                line_col.line = src_line;       /* Location in source   */
Packit Service 8bf002
                line_col.col = infile->bptr - infile->buffer - 1;
Packit Service 8bf002
            }
Packit Service 8bf002
            if (scan_token( c, (wp = out_ptr, &wp), out_wend) == NAM
Packit Service 8bf002
                    && (defp = is_macro( &wp)) != NULL) {   /* A macro  */
Packit Service 8bf002
                wp = expand_macro( defp, out_ptr, out_wend, line_col
Packit Service 8bf002
                        , & has_pragma);    /* Expand it completely */
Packit Service 8bf002
                if (line_top) {     /* The first token is a macro   */
Packit Service 8bf002
                    char *  tp = out_ptr;
Packit Service 8bf002
                    while (char_type[ *tp & UCHARMAX] & HSP)
Packit Service 8bf002
                        tp++;           /* Remove excessive spaces  */
Packit Service 8bf002
                    memmove( out_ptr, tp, strlen( tp) + 1);
Packit Service 8bf002
                    wp -= (tp - out_ptr);
Packit Service 8bf002
                }
Packit Service 8bf002
                if (has_pragma) {           /* Found _Pramga()      */
Packit Service 8bf002
                    do_pragma_op();         /* Do _Pragma() operator*/
Packit Service 8bf002
                    out_ptr = output;       /* Do the rest of line  */
Packit Service 8bf002
                    wrong_line = TRUE;      /* Line-num out of sync */
Packit Service 8bf002
                } else {
Packit Service 8bf002
                    out_ptr = wp;
Packit Service 8bf002
                }
Packit Service 8bf002
                if (keep_spaces && wrong_line && infile
Packit Service 8bf002
                        && *(infile->bptr) != '\n' && *(infile->bptr) != EOS) {
Packit Service 8bf002
                    src_col = infile->bptr - infile->buffer;
Packit Service 8bf002
                    /* Remember the current colums  */
Packit Service 8bf002
                    break;                  /* Do sharp() now       */
Packit Service 8bf002
                }
Packit Service 8bf002
            } else {                        /* Not a macro call     */
Packit Service 8bf002
                out_ptr = wp;               /* Advance the place    */
Packit Service 8bf002
                if (wrong_line)             /* is_macro() swallowed */
Packit Service 8bf002
                    break;                  /*      the newline     */
Packit Service 8bf002
            }
Packit Service 8bf002
            while (char_type[ c = get_ch()] & HSP) {    /* Horizontal space */
Packit Service 8bf002
                if (c != COM_SEP)           /* Skip 0-length comment*/
Packit Service 8bf002
                    *out_ptr++ = c;
Packit Service 8bf002
            }
Packit Service 8bf002
            line_top = FALSE;               /* Read over some token */
Packit Service 8bf002
        }                                   /* Loop for line        */
Packit Service 8bf002
Packit Service 8bf002
        putout( output);                    /* Output the line      */
Packit Service 8bf002
    }                                       /* Continue until EOF   */
Packit Service 8bf002
}
Packit Service 8bf002
Packit Service 8bf002
static void do_pragma_op( void)
Packit Service 8bf002
/*
Packit Service 8bf002
 * Execute the _Pragma() operator contained in an expanded macro.
Packit Service 8bf002
 * Note: _Pragma() operator is also implemented as a special macro.  Therefore
Packit Service 8bf002
 *      it is always searched as a macro.
Packit Service 8bf002
 * There might be more than one _Pragma() in a expanded macro and those may be
Packit Service 8bf002
 *      surrounded by other token sequences.
Packit Service 8bf002
 * Since all the macros have been expanded completely, any name identical to
Packit Service 8bf002
 *      macro should not be re-expanded.
Packit Service 8bf002
 * However, a macro in the string argument of _Pragma() may be expanded by
Packit Service 8bf002
 *      do_pragma() after de_stringize(), if EXPAND_PRAGMA == TRUE.
Packit Service 8bf002
 */
Packit Service 8bf002
{
Packit Service 8bf002
    FILEINFO *  file;
Packit Service 8bf002
    DEFBUF *    defp;
Packit Service 8bf002
    int     prev = output < out_ptr;        /* There is a previous sequence */
Packit Service 8bf002
    int     token_type;
Packit Service 8bf002
    char *  cp1, * cp2;
Packit Service 8bf002
    int     c;
Packit Service 8bf002
Packit Service 8bf002
    file = unget_string( out_ptr, NULL);
Packit Service 8bf002
    while (c = get_ch(), file == infile) {
Packit Service 8bf002
        if (char_type[ c] & HSP) {
Packit Service 8bf002
            *out_ptr++ = c;
Packit Service 8bf002
            continue;
Packit Service 8bf002
        }
Packit Service 8bf002
        if (scan_token( c, (cp1 = out_ptr, &cp1), out_wend)
Packit Service 8bf002
                    == NAM && (defp = is_macro( &cp1)) != NULL
Packit Service 8bf002
                && defp->nargs == DEF_PRAGMA) {     /* _Pragma() operator   */
Packit Service 8bf002
            if (prev) {
Packit Service 8bf002
                putout( output);    /* Putout the previous sequence */
Packit Service 8bf002
                cp1 = stpcpy( output, "pragma ");   /* From top of buffer   */
Packit Service 8bf002
            }
Packit Service 8bf002
            /* is_macro() already read over possible spaces after _Pragma   */
Packit Service 8bf002
            *cp1++ = get_ch();                              /* '('  */
Packit Service 8bf002
            while (char_type[ c = get_ch()] & HSP)
Packit Service 8bf002
                *cp1++ = c;
Packit Service 8bf002
            if (((token_type = scan_token( c, (cp2 = cp1, &cp1), out_wend))
Packit Service 8bf002
                    != STR && token_type != WSTR)) {
Packit Service 8bf002
                /* Not a string literal */
Packit Service 8bf002
                put_seq( output, cp1);
Packit Service 8bf002
                return;
Packit Service 8bf002
            }
Packit Service 8bf002
            workp = de_stringize( cp2, work_buf);
Packit Service 8bf002
            while (char_type[ c = get_ch()] & HSP)
Packit Service 8bf002
                *cp1++ = c;
Packit Service 8bf002
            if (c != ')') {         /* More than a string literal   */
Packit Service 8bf002
                unget_ch();
Packit Service 8bf002
                put_seq( output, cp1);
Packit Service 8bf002
                return;
Packit Service 8bf002
            }
Packit Service 8bf002
            strcpy( workp, "\n");       /* Terminate with <newline> */
Packit Service 8bf002
            unget_string( work_buf, NULL);
Packit Service 8bf002
            do_pragma();                /* Do the #pragma "line"    */
Packit Service 8bf002
            infile->bptr += strlen( infile->bptr);      /* Clear sequence   */
Packit Service 8bf002
            cp1 = out_ptr = output;     /* From the top of buffer   */
Packit Service 8bf002
            prev = FALSE;
Packit Service 8bf002
        } else {                        /* Not pragma sequence      */
Packit Service 8bf002
            out_ptr = cp1;
Packit Service 8bf002
            prev = TRUE;
Packit Service 8bf002
        }
Packit Service 8bf002
    }
Packit Service 8bf002
    unget_ch();
Packit Service 8bf002
    if (prev)
Packit Service 8bf002
        putout( output);
Packit Service 8bf002
}
Packit Service 8bf002
Packit Service 8bf002
static void put_seq(
Packit Service 8bf002
    char *  begin,                  /* Sequence already in buffer   */
Packit Service 8bf002
    char *  seq                     /* Sequence to be read          */
Packit Service 8bf002
)
Packit Service 8bf002
/*
Packit Service 8bf002
 * Put out the failed sequence as it is.
Packit Service 8bf002
 */
Packit Service 8bf002
{
Packit Service 8bf002
    FILEINFO *  file = infile;
Packit Service 8bf002
    int     c;
Packit Service 8bf002
Packit Service 8bf002
    cerror( "Operand of _Pragma() is not a string literal"  /* _E_  */
Packit Service 8bf002
            , NULL, 0L, NULL);
Packit Service 8bf002
    while (c = get_ch(), file == infile)
Packit Service 8bf002
        *seq++ = c;
Packit Service 8bf002
    unget_ch();
Packit Service 8bf002
    out_ptr = seq;
Packit Service 8bf002
    putout( begin);
Packit Service 8bf002
}
Packit Service 8bf002
Packit Service 8bf002
static char *   de_stringize(
Packit Service 8bf002
    char *  in,                 /* Null terminated string literal   */
Packit Service 8bf002
    char *  out                             /* Output buffer        */
Packit Service 8bf002
)
Packit Service 8bf002
/*
Packit Service 8bf002
 * Make token sequence from a string literal for _Pragma() operator.
Packit Service 8bf002
 */
Packit Service 8bf002
{
Packit Service 8bf002
    char *  in_p;
Packit Service 8bf002
    int     c1, c;
Packit Service 8bf002
Packit Service 8bf002
    in_p = in;
Packit Service 8bf002
    if (*in_p == 'L')
Packit Service 8bf002
        in_p++;                             /* Skip 'L' prefix      */
Packit Service 8bf002
    while ((c = *++in_p) != EOS) {
Packit Service 8bf002
        if (c == '\\' && ((c1 = *(in_p + 1), c1 == '\\') || c1 == '"'))
Packit Service 8bf002
            c = *++in_p;            /* "De-escape" escape sequence  */
Packit Service 8bf002
        *out++ = c;
Packit Service 8bf002
    }
Packit Service 8bf002
    *--out = EOS;                   /* Remove the closing '"'       */
Packit Service 8bf002
    return  out;
Packit Service 8bf002
}
Packit Service 8bf002
Packit Service 8bf002
static void putout(
Packit Service 8bf002
    char *  out     /* Output line (line-end is always 'out_ptr')   */
Packit Service 8bf002
)
Packit Service 8bf002
/*
Packit Service 8bf002
 * Put out a line with or without "post-preprocessing".
Packit Service 8bf002
 */
Packit Service 8bf002
{
Packit Service 8bf002
    size_t  len;
Packit Service 8bf002
Packit Service 8bf002
    *out_ptr++ = '\n';                      /* Put out a newline    */
Packit Service 8bf002
    *out_ptr = EOS;
Packit Service 8bf002
Packit Service 8bf002
#if ! MBCHAR_IS_ESCAPE_FREE
Packit Service 8bf002
    post_preproc( out);
Packit Service 8bf002
#elif   ! HAVE_DIGRAPHS
Packit Service 8bf002
    if (mcpp_mode == STD && option_flag.dig)
Packit Service 8bf002
        post_preproc( out);
Packit Service 8bf002
#endif
Packit Service 8bf002
    /* Else no post-preprocess  */
Packit Service 8bf002
#if COMPILER != GNUC && COMPILER != MSC
Packit Service 8bf002
    /* GCC and Visual C can accept very long line   */
Packit Service 8bf002
    len = strlen( out);
Packit Service 8bf002
    if (len > NWORK - 1)
Packit Service 8bf002
        devide_line( out);              /* Devide a too long line   */
Packit Service 8bf002
    else
Packit Service 8bf002
#endif
Packit Service 8bf002
        put_a_line( out);
Packit Service 8bf002
}
Packit Service 8bf002
Packit Service 8bf002
#if COMPILER != GNUC && COMPILER != MSC
Packit Service 8bf002
Packit Service 8bf002
static void devide_line(
Packit Service 8bf002
    char * out                      /* 'out' is 'output' in actual  */
Packit Service 8bf002
)
Packit Service 8bf002
/*
Packit Service 8bf002
 * Devide a too long line into output lines shorter than NWORK.
Packit Service 8bf002
 * This routine is called from putout().
Packit Service 8bf002
 */
Packit Service 8bf002
{
Packit Service 8bf002
    FILEINFO *  file;
Packit Service 8bf002
    char *  save;
Packit Service 8bf002
    char *  wp;
Packit Service 8bf002
    int     c;
Packit Service 8bf002
Packit Service 8bf002
    file = unget_string( out, NULL);        /* To re-read the line  */
Packit Service 8bf002
    wp = out_ptr = out;
Packit Service 8bf002
Packit Service 8bf002
    while ((c = get_ch()), file == infile) {
Packit Service 8bf002
        if (char_type[ c] & HSP) {
Packit Service 8bf002
            if (keep_spaces || out == out_ptr
Packit Service 8bf002
                    || (char_type[ *(out_ptr - 1) & UCHARMAX] & HSP)) {
Packit Service 8bf002
                *out_ptr++ = c;
Packit Service 8bf002
                wp++;
Packit Service 8bf002
            }
Packit Service 8bf002
            continue;
Packit Service 8bf002
        }
Packit Service 8bf002
        scan_token( c, &wp, out_wend);          /* Read a token     */
Packit Service 8bf002
        if (NWORK-2 < wp - out_ptr) {           /* Too long a token */
Packit Service 8bf002
            cfatal( "Too long token %s", out_ptr, 0L, NULL);        /* _F_  */
Packit Service 8bf002
        } else if (out_end <= wp) {             /* Too long line    */
Packit Service 8bf002
            if (mcpp_debug & MACRO_CALL) {      /* -K option        */
Packit Service 8bf002
                /* Other than GCC or Visual C   */
Packit Service 8bf002
                /* scan_token() scans a comment as sequence of some */
Packit Service 8bf002
                /* tokens such as '/', '*', ..., '*', '/', since it */
Packit Service 8bf002
                /* does not expect comment.                         */
Packit Service 8bf002
                save = out_ptr;
Packit Service 8bf002
                while ((save = strrchr( save, '/')) != NULL) {
Packit Service 8bf002
                    if (*(save - 1) == '*') {   /* '*' '/' sequence */
Packit Service 8bf002
                        out_ptr = save + 1;     /* Devide at the end*/
Packit Service 8bf002
                        break;                  /*      of a comment*/
Packit Service 8bf002
                    }
Packit Service 8bf002
                }
Packit Service 8bf002
            }
Packit Service 8bf002
            save = save_string( out_ptr);       /* Save the token   */
Packit Service 8bf002
            *out_ptr++ = '\n';                  /* Append newline   */
Packit Service 8bf002
            *out_ptr = EOS;
Packit Service 8bf002
            put_a_line( out);           /* Putout the former tokens */
Packit Service 8bf002
            wp = out_ptr = stpcpy( out, save);      /* Restore the token    */
Packit Service 8bf002
            free( save);
Packit Service 8bf002
        } else {                            /* Still in size        */
Packit Service 8bf002
            out_ptr = wp;                   /* Advance the pointer  */
Packit Service 8bf002
        }
Packit Service 8bf002
    }
Packit Service 8bf002
Packit Service 8bf002
    unget_ch();                 /* Push back the source character   */
Packit Service 8bf002
    put_a_line( out);                   /* Putout the last tokens   */
Packit Service 8bf002
    sharp( NULL, 0);                        /* Correct line number  */
Packit Service 8bf002
}
Packit Service 8bf002
Packit Service 8bf002
#endif
Packit Service 8bf002
Packit Service 8bf002
static void put_a_line(
Packit Service 8bf002
    char * out
Packit Service 8bf002
)
Packit Service 8bf002
/*
Packit Service 8bf002
 * Finally put out the preprocessed line.
Packit Service 8bf002
 */
Packit Service 8bf002
{
Packit Service 8bf002
    size_t  len;
Packit Service 8bf002
    char *  out_p;
Packit Service 8bf002
    char *  tp;
Packit Service 8bf002
Packit Service 8bf002
    if (no_output)
Packit Service 8bf002
        return;
Packit Service 8bf002
    len = strlen( out);
Packit Service 8bf002
    tp = out_p = out + len - 2;             /* Just before '\n'     */
Packit Service 8bf002
    while (char_type[ *out_p & UCHARMAX] & SPA)
Packit Service 8bf002
        out_p--;                    /* Remove trailing white spaces */
Packit Service 8bf002
    if (out_p < tp) {
Packit Service 8bf002
        *++out_p = '\n';
Packit Service 8bf002
        *++out_p = EOS;
Packit Service 8bf002
    }
Packit Service 8bf002
    if (mcpp_fputs( out, OUT) == EOF)
Packit Service 8bf002
        cfatal( "File write error", NULL, 0L, NULL);        /* _F_  */
Packit Service 8bf002
}
Packit Service 8bf002
Packit Service 8bf002
Packit Service 8bf002
/*
Packit Service 8bf002
 *      Routines to  P O S T - P R E P R O C E S S
Packit Service 8bf002
 *
Packit Service 8bf002
 * 1998/08      created     kmatsui     (revised 1998/09, 2004/02, 2006/07)
Packit Service 8bf002
 *    Supplementary phase for the older compiler-propers.
Packit Service 8bf002
 *      1. Convert digraphs to usual tokens.
Packit Service 8bf002
 *      2. Double '\\' of the second byte of multi-byte characters.
Packit Service 8bf002
 *    These conversions are done selectively according to the macros defined
Packit Service 8bf002
 *  in system.H.
Packit Service 8bf002
 *      1. Digraphs are converted if ! HAVE_DIGRAPHS and digraph recoginition
Packit Service 8bf002
 *  is enabled by DIGRAPHS_INIT and/or -2 option on execution.
Packit Service 8bf002
 *      2. '\\' of the second byte of SJIS (BIGFIVE or ISO2022_JP) is doubled
Packit Service 8bf002
 *  if bsl_need_escape == TRUE.
Packit Service 8bf002
 */
Packit Service 8bf002
Packit Service 8bf002
#if HAVE_DIGRAPHS && MBCHAR_IS_ESCAPE_FREE
Packit Service 8bf002
    /* No post_preproc()    */
Packit Service 8bf002
#else
Packit Service 8bf002
Packit Service 8bf002
static int  post_preproc(
Packit Service 8bf002
    char * out
Packit Service 8bf002
)
Packit Service 8bf002
/*
Packit Service 8bf002
 * Convert digraphs and double '\\' of the second byte of SJIS (BIGFIVE or
Packit Service 8bf002
 * ISO2022_JP).
Packit Service 8bf002
 * Note: Output of -K option embeds macro informations into comments.
Packit Service 8bf002
 * scan_token() does not recognize comment and parses it as '/', '*', etc.
Packit Service 8bf002
 */
Packit Service 8bf002
{
Packit Service 8bf002
#if ! HAVE_DIGRAPHS
Packit Service 8bf002
    int     di_count = 0;
Packit Service 8bf002
#endif
Packit Service 8bf002
    int     token_type;
Packit Service 8bf002
    int     c;
Packit Service 8bf002
    char *  str;
Packit Service 8bf002
    char *  cp = out;
Packit Service 8bf002
Packit Service 8bf002
    unget_string( out, NULL);
Packit Service 8bf002
    while ((c = get_ch()) != '\n') {    /* Not to read over to next line    */
Packit Service 8bf002
        if (char_type[ c] & HSP) {
Packit Service 8bf002
            *cp++ = c;
Packit Service 8bf002
            continue;
Packit Service 8bf002
        }
Packit Service 8bf002
        str = cp;
Packit Service 8bf002
        token_type = scan_token( c, &cp, out_wend);
Packit Service 8bf002
        switch (token_type) {
Packit Service 8bf002
#if ! MBCHAR_IS_ESCAPE_FREE
Packit Service 8bf002
        case WSTR   :
Packit Service 8bf002
        case WCHR   :
Packit Service 8bf002
            str++;                          /* Skip prefix 'L'      */
Packit Service 8bf002
            /* Fall through */
Packit Service 8bf002
        case STR    :
Packit Service 8bf002
        case CHR    :
Packit Service 8bf002
            if (bsl_need_escape)
Packit Service 8bf002
                cp = esc_mbchar( str, cp);
Packit Service 8bf002
            break;
Packit Service 8bf002
#endif  /* ! MBCHAR_IS_ESCAPE_FREE  */
Packit Service 8bf002
#if ! HAVE_DIGRAPHS
Packit Service 8bf002
        case OPE    :
Packit Service 8bf002
            if (mcpp_mode == STD && (openum & OP_DIGRAPH)) {
Packit Service 8bf002
                cp = conv_a_digraph( cp);   /* Convert a digraph    */
Packit Service 8bf002
                di_count++;
Packit Service 8bf002
            }
Packit Service 8bf002
            break;
Packit Service 8bf002
#endif
Packit Service 8bf002
        }
Packit Service 8bf002
    }
Packit Service 8bf002
    *cp++ = '\n';
Packit Service 8bf002
    *cp = EOS;
Packit Service 8bf002
#if ! HAVE_DIGRAPHS
Packit Service 8bf002
    if (mcpp_mode == STD && di_count && (warn_level & 16))
Packit Service 8bf002
        cwarn( "%.0s%ld digraph(s) converted"           /* _W16_    */
Packit Service 8bf002
                , NULL, (long) di_count, NULL);
Packit Service 8bf002
#endif
Packit Service 8bf002
    return  0;
Packit Service 8bf002
}
Packit Service 8bf002
Packit Service 8bf002
#endif  /* ! HAVE_DIGRAPHS || ! MBCHAR_IS_ESCAPE_FREE   */
Packit Service 8bf002
Packit Service 8bf002
#if ! HAVE_DIGRAPHS
Packit Service 8bf002
static char *   conv_a_digraph(
Packit Service 8bf002
    char *  cp                      /* The end of the digraph token */
Packit Service 8bf002
)
Packit Service 8bf002
/*
Packit Service 8bf002
 * Convert a digraph to usual token in place.
Packit Service 8bf002
 * This routine is never called in POST_STD mode.
Packit Service 8bf002
 */
Packit Service 8bf002
{
Packit Service 8bf002
    cp -= 2;
Packit Service 8bf002
    switch (openum) {
Packit Service 8bf002
    case OP_LBRACE_D    :
Packit Service 8bf002
        *cp++ = '{';
Packit Service 8bf002
        break;
Packit Service 8bf002
    case OP_RBRACE_D    :
Packit Service 8bf002
        *cp++ = '}';
Packit Service 8bf002
        break;
Packit Service 8bf002
    case OP_LBRCK_D     :
Packit Service 8bf002
        *cp++ = '[';
Packit Service 8bf002
        break;
Packit Service 8bf002
    case OP_RBRCK_D     :
Packit Service 8bf002
        *cp++ = ']';
Packit Service 8bf002
        break;
Packit Service 8bf002
    case OP_SHARP_D     :                       /* Error of source  */
Packit Service 8bf002
        *cp++ = '#';
Packit Service 8bf002
        break;
Packit Service 8bf002
    case OP_DSHARP_D    :                       /* Error of source  */
Packit Service 8bf002
        cp -= 2;
Packit Service 8bf002
        *cp++ = '#';
Packit Service 8bf002
        *cp++ = '#';
Packit Service 8bf002
        break;
Packit Service 8bf002
    }
Packit Service 8bf002
    return  cp;
Packit Service 8bf002
}
Packit Service 8bf002
#endif  /* ! HAVE_DIGRAPHS  */
Packit Service 8bf002
Packit Service 8bf002
#if ! MBCHAR_IS_ESCAPE_FREE
Packit Service 8bf002
static char *   esc_mbchar(
Packit Service 8bf002
    char *  str,        /* String literal or character constant without 'L' */
Packit Service 8bf002
    char *  str_end     /* The end of the token */
Packit Service 8bf002
)
Packit Service 8bf002
/*
Packit Service 8bf002
 * Insert \ before the byte of 0x5c('\\') of the SJIS, BIGFIVE or ISO2022_JP
Packit Service 8bf002
 * multi-byte character code in string literal or character constant.
Packit Service 8bf002
 * Insert \ also before the byte of 0x22('"') and 0x27('\'') of ISO2022_JP.
Packit Service 8bf002
 * esc_mbchar() does in-place insertion.
Packit Service 8bf002
 */
Packit Service 8bf002
{
Packit Service 8bf002
    char *  cp;
Packit Service 8bf002
    int     delim;
Packit Service 8bf002
    int     c;
Packit Service 8bf002
Packit Service 8bf002
    if (! bsl_need_escape)
Packit Service 8bf002
        return  str_end;
Packit Service 8bf002
    if ((delim = *str++) == 'L')
Packit Service 8bf002
        delim = *str++;                         /* The quote character  */
Packit Service 8bf002
    while ((c = *str++ & UCHARMAX) != delim) {
Packit Service 8bf002
        if (char_type[ c] & mbchk) {            /* MBCHAR   */
Packit Service 8bf002
            cp = str;
Packit Service 8bf002
            mb_read( c, &str, (workp = work_buf, &workp));
Packit Service 8bf002
            while (cp++ < str) {
Packit Service 8bf002
                c = *(cp - 1);
Packit Service 8bf002
                if (c == '\\' || c == '"' || c == '\'') {
Packit Service 8bf002
                                    /* Insert \ before 0x5c, 0x22, 0x27 */
Packit Service 8bf002
                    memmove( cp, cp - 1, (size_t) (str_end - cp) + 2);
Packit Service 8bf002
                    *(cp++ - 1) = '\\';
Packit Service 8bf002
                    str++;
Packit Service 8bf002
                    str_end++;
Packit Service 8bf002
                }
Packit Service 8bf002
            }
Packit Service 8bf002
        } else if (c == '\\' && ! (char_type[ *str & UCHARMAX] & mbchk)) {
Packit Service 8bf002
            str++;                              /* Escape sequence      */
Packit Service 8bf002
        }
Packit Service 8bf002
    }
Packit Service 8bf002
    return  str_end;
Packit Service 8bf002
}
Packit Service 8bf002
#endif  /* ! MBCHAR_IS_ESCAPE_FREE  */
Packit Service 8bf002