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

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

1.1     ! ohara       1: /* $OpenXM$ */
        !             2: /*-
        !             3:  * Copyright (c) 1998, 2002-2008 Kiyoshi Matsui <kmatsui@t3.rim.or.jp>
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * Some parts of this code are derived from the public domain software
        !             7:  * DECUS cpp (1984,1985) written by Martin Minow.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  *
        !            18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
        !            19:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            20:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            21:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
        !            22:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            23:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            24:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            25:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            26:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            27:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            28:  * SUCH DAMAGE.
        !            29:  */
        !            30:
        !            31: /*
        !            32:  *                          S U P P O R T . C
        !            33:  *                  S u p p o r t   R o u t i n e s
        !            34:  *
        !            35:  * The common routines used by several source files are placed here.
        !            36:  */
        !            37:
        !            38: /*
        !            39:  * The following are global functions.
        !            40:  *
        !            41:  * get_unexpandable()   Gets the next unexpandable token in the line, expanding
        !            42:  *              macros.
        !            43:  *              Called from #if, #line and #include processing routines.
        !            44:  * skip_nl()    Skips over a line.
        !            45:  * skip_ws()    Skips over white spaces but not skip over the end of the line.
        !            46:  *              skip_ws() skips also COM_SEP and TOK_SEP.
        !            47:  * scan_token() Reads the next token of any type into the specified output
        !            48:  *              pointer, advances the pointer, returns the type of token.
        !            49:  * scan_quote() Reads a string literal, character constant or header-name from
        !            50:  *              the input stream, writes out to the specified buffer and
        !            51:  *              returns the advanced output pointer.
        !            52:  * get_ch()     Reads the next byte from the current input stream, handling
        !            53:  *              end of (macro/file) input and embedded comments appropriately.
        !            54:  * cnv_trigraph()   Maps trigraph sequence to C character.
        !            55:  * cnv_digraph()    Maps digraph sequence to C character.
        !            56:  * id_operator()    See whether the identifier is an operator in C++.
        !            57:  * unget_ch()   Pushs last gotten character back on the input stream.
        !            58:  * unget_string()   Pushs sequence on the input stream.
        !            59:  * save_string() Saves a string in malloc() memory.
        !            60:  * get_file()   Initializes a new FILEINFO structure, called when #include
        !            61:  *              opens a new file, or from unget_string().
        !            62:  * xmalloc()    Gets a specified number of bytes from heap memory.
        !            63:  *              If malloc() returns NULL, exits with a message.
        !            64:  * xrealloc()   realloc().  If it fails, exits with a message.
        !            65:  * get_src_location()   Trace back line-column datum into pre-line-splicing
        !            66:  *              phase.  A function for -K option.
        !            67:  * cfatal(), cerror(), cwarn()
        !            68:  *              These routines format print messages to the user.
        !            69:  * mcpp_fputc(), mcpp_fputs(), mcpp_fprintf()
        !            70:  *              Wrap library functions to support alternate output to memory
        !            71:  *              buffer.
        !            72:  */
        !            73:
        !            74: #if PREPROCESSED
        !            75: #include    "mcpp.H"
        !            76: #else
        !            77: #include    "system.H"
        !            78: #include    "internal.H"
        !            79: #endif
        !            80:
        !            81: static void     scan_id( int c);
        !            82:                 /* Scan an identifier           */
        !            83: static char *   scan_number( int c, char * out, char * out_end);
        !            84:                 /* Scan a preprocessing number  */
        !            85: static char *   scan_number_prestd( int c, char * out, char * out_end);
        !            86:                 /* scan_number() for pre-Standard mode  */
        !            87: #if OK_UCN
        !            88: static char *   scan_ucn( int cnt, char * out);
        !            89:                 /* Scan an UCN sequence         */
        !            90: #endif
        !            91: static char *   scan_op( int c, char * out);
        !            92:                 /* Scan an operator or a punctuator     */
        !            93: static char *   parse_line( void);
        !            94:                 /* Parse a logical line and convert comments    */
        !            95: static char *   read_a_comment( char * sp, size_t * sizp);
        !            96:                 /* Read over a comment          */
        !            97: static char *   get_line( int in_comment);
        !            98:                 /* Get a logical line from file, handle line-splicing   */
        !            99: static char *   at_eof( int in_comment);
        !           100:                 /* Check erroneous end of file  */
        !           101: static void     do_msg( const char * severity, const char * format
        !           102:         , const char * arg1, long arg2, const char * arg3);
        !           103:                 /* Putout diagnostic message    */
        !           104: static char *   cat_line( int del_bsl);
        !           105:                 /* Splice the line              */
        !           106: static void     put_line( char * out, FILE * fp);
        !           107:                 /* Put out a logical line       */
        !           108: static void     dump_token( int token_type, const char * cp);
        !           109:                 /* Dump a token and its type    */
        !           110:
        !           111: #define EXP_MAC_IND_MAX     16
        !           112: /* Information of current expanding macros for diagnostic   */
        !           113: static struct {
        !           114:     const char *    name;       /* Name of the macro just expanded  */
        !           115:     int             to_be_freed;    /* Name should be freed later   */
        !           116: } expanding_macro[ EXP_MAC_IND_MAX];
        !           117: static int  exp_mac_ind = 0;        /* Index into expanding_macro[] */
        !           118:
        !           119: static int  in_token = FALSE;       /* For token scanning functions */
        !           120: static int  in_string = FALSE;      /* For get_ch() and parse_line()*/
        !           121: static int  squeezews = FALSE;
        !           122:
        !           123: #define MAX_CAT_LINE    256
        !           124: /* Information on line catenated by <backslash><newline>    */
        !           125: /* and by line-crossing comment.  This is for -K option.    */
        !           126: typedef struct catenated_line {
        !           127:     long    start_line;         /* Starting line of catenation      */
        !           128:     long    last_line;          /* Ending line of catanation        */
        !           129:     size_t  len[ MAX_CAT_LINE + 1];
        !           130:                         /* Length of successively catenated lines   */
        !           131: } CAT_LINE;
        !           132: static CAT_LINE bsl_cat_line;
        !           133:         /* Datum on the last catenated line by <backslash><newline> */
        !           134: static CAT_LINE com_cat_line;
        !           135:         /* Datum on the last catenated line by a line-crossing comment  */
        !           136:
        !           137: #if MCPP_LIB
        !           138: static int  use_mem_buffers = FALSE;
        !           139:
        !           140: void    init_support( void)
        !           141: {
        !           142:     in_token = in_string = squeezews = FALSE;
        !           143:     bsl_cat_line.len[ 0] = com_cat_line.len[ 0] = 0;
        !           144:     clear_exp_mac();
        !           145: }
        !           146:
        !           147: typedef struct  mem_buf {
        !           148:     char *  buffer;
        !           149:     char *  entry_pt;
        !           150:     size_t  size;
        !           151:     size_t  bytes_avail;
        !           152: } MEMBUF;
        !           153:
        !           154: static MEMBUF   mem_buffers[ NUM_OUTDEST];
        !           155:
        !           156: void    mcpp_use_mem_buffers(
        !           157:     int    tf
        !           158: )
        !           159: {
        !           160:     int i;
        !           161:
        !           162:     use_mem_buffers = tf ? TRUE : FALSE;
        !           163:
        !           164:     for (i = 0; i < NUM_OUTDEST; ++i) {
        !           165:         if (mem_buffers[ i].buffer)
        !           166:             /* Free previously allocated memory buffer  */
        !           167:             free( mem_buffers[ i].buffer);
        !           168:         if (use_mem_buffers) {
        !           169:             /* Output to memory buffers instead of files    */
        !           170:             mem_buffers[ i].buffer = NULL;
        !           171:             mem_buffers[ i].entry_pt = NULL;
        !           172:             mem_buffers[ i].size = 0;
        !           173:             mem_buffers[ i].bytes_avail = 0;
        !           174:         }
        !           175:     }
        !           176: }
        !           177:
        !           178: int    using_mem_buffers( void)
        !           179: {
        !           180:     return use_mem_buffers;
        !           181: }
        !           182:
        !           183: #define BUF_INCR_SIZE   (NWORK * 2)
        !           184: #define MAX( a, b)      (((a) > (b)) ? (a) : (b))
        !           185:
        !           186: static char *   append_to_buffer(
        !           187:     MEMBUF *    mem_buf_p,
        !           188:     const char *    string,
        !           189:     size_t      length
        !           190: )
        !           191: {
        !           192:     if (mem_buf_p->bytes_avail < length) {  /* Need to allocate more memory */
        !           193:         size_t size = MAX( BUF_INCR_SIZE, length);
        !           194:
        !           195:         if (mem_buf_p->buffer == NULL) {            /* 1st append   */
        !           196:             mem_buf_p->size = size;
        !           197:             mem_buf_p->bytes_avail = size;
        !           198:             mem_buf_p->buffer = xmalloc( mem_buf_p->size);
        !           199:             mem_buf_p->entry_pt = mem_buf_p->buffer;
        !           200:         } else {
        !           201:             mem_buf_p->size += size;
        !           202:             mem_buf_p->bytes_avail += size;
        !           203:             mem_buf_p->buffer = xrealloc( mem_buf_p->buffer, mem_buf_p->size);
        !           204:             mem_buf_p->entry_pt = mem_buf_p->buffer + mem_buf_p->size
        !           205:                     - mem_buf_p->bytes_avail;
        !           206:         }
        !           207:     }
        !           208:
        !           209:     /* Append the string to the tail of the buffer  */
        !           210:     memcpy( mem_buf_p->entry_pt, string, length);
        !           211:     mem_buf_p->entry_pt += length;
        !           212:     mem_buf_p->entry_pt[ 0] = '\0';     /* Terminate the string buffer  */
        !           213:     mem_buf_p->bytes_avail -= length;
        !           214:
        !           215:     return mem_buf_p->buffer;
        !           216: }
        !           217:
        !           218: static int  mem_putc(
        !           219:     int     c,
        !           220:     OUTDEST od
        !           221: )
        !           222: {
        !           223:     char string[ 1];
        !           224:
        !           225:     string[ 0] = (char) c;
        !           226:
        !           227:     if (append_to_buffer( &(mem_buffers[ od]), string, 1) != NULL)
        !           228:         return 0;
        !           229:     else
        !           230:         return !0;
        !           231: }
        !           232:
        !           233: static int  mem_puts(
        !           234:     const char *    s,
        !           235:     OUTDEST od
        !           236: )
        !           237: {
        !           238:     if (append_to_buffer( &(mem_buffers[od]), s, strlen(s)) != NULL)
        !           239:         return 0;
        !           240:     else
        !           241:         return !0;
        !           242: }
        !           243:
        !           244: char *  mcpp_get_mem_buffer(
        !           245:     OUTDEST od
        !           246: )
        !           247: {
        !           248:     return mem_buffers[ od].buffer;
        !           249: }
        !           250:
        !           251: #endif  /* MCPP_LIB */
        !           252:
        !           253: #define DEST2FP(od) \
        !           254:     (od == OUT) ? fp_out : \
        !           255:     ((od == ERR) ? fp_err : \
        !           256:     ((od == DBG) ? fp_debug : \
        !           257:     (NULL)))
        !           258:
        !           259: /*
        !           260:  * The following mcpp_*() wrapper functions are intended to centralize
        !           261:  * the output generated by MCPP.  They support memory buffer alternates to
        !           262:  * each of the primary output streams: out, err, debug.  The memory buffer
        !           263:  * output option would be used in a setup where MCPP has been built as a
        !           264:  * function call - i.e. mcpp_lib_main().
        !           265:  */
        !           266:
        !           267: int    mcpp_lib_fputc(
        !           268:     int     c,
        !           269:     OUTDEST od
        !           270: )
        !           271: {
        !           272: #if MCPP_LIB
        !           273:     if (use_mem_buffers) {
        !           274:         return mem_putc( c, od);
        !           275:     } else {
        !           276: #endif
        !           277:         FILE *  stream = DEST2FP( od);
        !           278:
        !           279:         return (stream != NULL) ? fputc( c, stream) : EOF;
        !           280: #if MCPP_LIB
        !           281:     }
        !           282: #endif
        !           283: }
        !           284:
        !           285: int (* mcpp_fputc)( int c, OUTDEST od) = mcpp_lib_fputc;
        !           286:
        !           287: int    mcpp_lib_fputs(
        !           288:     const char *    s,
        !           289:     OUTDEST od
        !           290: )
        !           291: {
        !           292: #if MCPP_LIB
        !           293:     if (use_mem_buffers) {
        !           294:         return mem_puts( s, od);
        !           295:     } else {
        !           296: #endif
        !           297:         FILE *  stream = DEST2FP( od);
        !           298:
        !           299:         return (stream != NULL) ? fputs( s, stream) : EOF;
        !           300: #if MCPP_LIB
        !           301:     }
        !           302: #endif
        !           303: }
        !           304:
        !           305: int (* mcpp_fputs)( const char * s, OUTDEST od) = mcpp_lib_fputs;
        !           306:
        !           307: #include <stdarg.h>
        !           308:
        !           309: int    mcpp_lib_fprintf(
        !           310:     OUTDEST od,
        !           311:     const char *    format,
        !           312:     ...
        !           313: )
        !           314: {
        !           315:     va_list ap;
        !           316:     FILE *  stream = DEST2FP( od);
        !           317:
        !           318:     if (stream != NULL) {
        !           319:         int rc;
        !           320:
        !           321:         va_start( ap, format);
        !           322: #if MCPP_LIB
        !           323:         if (use_mem_buffers) {
        !           324:             static char     mem_buffer[ NWORK];
        !           325:
        !           326:             rc = vsprintf( mem_buffer, format, ap);
        !           327:
        !           328:             if (rc != 0) {
        !           329:                 rc = mem_puts( mem_buffer, od);
        !           330:             }
        !           331:         } else {
        !           332: #endif
        !           333:             rc = vfprintf( stream, format, ap);
        !           334: #if MCPP_LIB
        !           335:         }
        !           336: #endif
        !           337:         va_end( ap);
        !           338:
        !           339:         return rc;
        !           340:
        !           341:     } else {
        !           342:         return EOF;
        !           343:     }
        !           344: }
        !           345:
        !           346: int (* mcpp_fprintf)( OUTDEST od, const char * format, ...) = mcpp_lib_fprintf;
        !           347:
        !           348: #if MCPP_LIB
        !           349: void    mcpp_reset_def_out_func( void)
        !           350: {
        !           351:     mcpp_fputc = mcpp_lib_fputc;
        !           352:     mcpp_fputs = mcpp_lib_fputs;
        !           353:     mcpp_fprintf = mcpp_lib_fprintf;
        !           354: }
        !           355:
        !           356: void    mcpp_set_out_func(
        !           357:     int (* func_fputc)( int c, OUTDEST od),
        !           358:     int (* func_fputs)( const char * s, OUTDEST od),
        !           359:     int (* func_fprintf)( OUTDEST od, const char * format, ...)
        !           360: )
        !           361: {
        !           362:     mcpp_fputc = func_fputc;
        !           363:     mcpp_fputs = func_fputs;
        !           364:     mcpp_fprintf = func_fprintf;
        !           365: }
        !           366: #endif
        !           367:
        !           368: int     get_unexpandable(
        !           369:     int     c,                              /* First char of token  */
        !           370:     int     diag                            /* Flag of diagnosis    */
        !           371: )
        !           372: /*
        !           373:  * Get the next unexpandable token in the line, expanding macros.
        !           374:  * Return the token type.  The token is written in work_buf[].
        !           375:  * The once expanded macro is never expanded again.
        !           376:  * Called only from the routines processing #if (#elif, #assert), #line and
        !           377:  * #include directives in order to diagnose some subtle macro expansions.
        !           378:  */
        !           379: {
        !           380:     DEFBUF *    defp = NULL;
        !           381:     FILEINFO *  file;
        !           382:     FILE *  fp = NULL;
        !           383:     LINE_COL    line_col = { 0L, 0};
        !           384:     int     token_type = NO_TOKEN;
        !           385:     int     has_pragma;
        !           386:
        !           387:     while (c != EOS && c != '\n'                /* In a line        */
        !           388:             && (fp = infile->fp         /* Preserve current state   */
        !           389:                 , (token_type
        !           390:                     = scan_token( c, (workp = work_buf, &workp), work_end))
        !           391:                     == NAM)                     /* Identifier       */
        !           392:             && fp != NULL                       /* In source !      */
        !           393:             && (defp = is_macro( NULL)) != NULL) {      /* Macro    */
        !           394:         expand_macro( defp, work_buf, work_end, line_col, & has_pragma);
        !           395:                                                 /* Expand macro     */
        !           396:         if (has_pragma)
        !           397:             cerror( "_Pragma operator found in directive line"      /* _E_  */
        !           398:                     , NULL, 0L, NULL);
        !           399:         file = unget_string( work_buf, defp->name);     /* Stack to re-read */
        !           400:         c = skip_ws();                          /* Skip TOK_SEP     */
        !           401:         if (file != infile && macro_line != MACRO_ERROR && (warn_level & 1)) {
        !           402:             /* This diagnostic is issued even if "diag" is FALSE.   */
        !           403:             cwarn( "Macro \"%s\" is expanded to 0 token"    /* _W1_ */
        !           404:                     , defp->name, 0L, NULL);
        !           405:             if (! option_flags.no_source_line)
        !           406:                 dump_a_def( "    macro", defp, FALSE, TRUE, fp_err);
        !           407:         }
        !           408:     }
        !           409:
        !           410:     if (c == '\n' || c == EOS) {
        !           411:         unget_ch();
        !           412:         return  NO_TOKEN;
        !           413:     }
        !           414:
        !           415:     if (diag && fp == NULL && defp && (warn_level & 1)) {
        !           416:         char    tmp[ NWORK + 16];
        !           417:         char *  tmp_end = tmp + NWORK;
        !           418:         char *  tmp_p;
        !           419:         file = unget_string( infile->buffer, defp->name);   /* To diagnose  */
        !           420:         c = get_ch();
        !           421:         while (file == infile) {    /* Search the expanded macro    */
        !           422:             if (scan_token( c, (tmp_p = tmp, &tmp_p), tmp_end) != NAM) {
        !           423:                 c = get_ch();
        !           424:                 continue;
        !           425:             }
        !           426:             if (standard && str_eq( identifier, "defined")) {
        !           427:                 cwarn( "Macro \"%s\" is expanded to \"defined\""    /* _W1_ */
        !           428:                         , defp->name, 0L, NULL);
        !           429:                 break;
        !           430:             }
        !           431:             if (! standard && str_eq( identifier, "sizeof")) {
        !           432:                 cwarn( "Macro \"%s\" is expanded to \"sizeof\""     /* _W1_ */
        !           433:                         , defp->name, 0L, NULL);
        !           434:                 break;
        !           435:             }
        !           436:             c = get_ch();
        !           437:         }
        !           438:         if (file == infile) {
        !           439:             infile->bptr += strlen( infile->bptr);
        !           440:             get_ch();
        !           441:         }
        !           442:         unget_ch();
        !           443:         if (token_type == OPE) {
        !           444:             unget_string( work_buf, NULL);  /* Set again 'openum'   */
        !           445:             scan_token( get_ch(), (workp = work_buf, &workp), work_end);
        !           446:         }
        !           447:     }
        !           448:
        !           449:     return  token_type;
        !           450: }
        !           451:
        !           452: void    skip_nl( void)
        !           453: /*
        !           454:  * Skip to the end of the current input line.
        !           455:  */
        !           456: {
        !           457:     insert_sep = NO_SEP;
        !           458:     while (infile && infile->fp == NULL) {  /* Stacked text         */
        !           459:         infile->bptr += strlen( infile->bptr);
        !           460:         get_ch();                           /* To the parent        */
        !           461:     }
        !           462:     if (infile)
        !           463:         infile->bptr += strlen( infile->bptr);  /* Source line      */
        !           464: }
        !           465:
        !           466: int     skip_ws( void)
        !           467: /*
        !           468:  * Skip over horizontal whitespaces.
        !           469:  */
        !           470: {
        !           471:     int     c;
        !           472:
        !           473:     do {
        !           474:         c = get_ch();
        !           475:     } while (char_type[ c] & HSP);
        !           476:
        !           477:     return  c;
        !           478: }
        !           479:
        !           480: #define MBMASK          0xFF    /* Mask to hide multibyte char      */
        !           481:
        !           482: int     scan_token(
        !           483:     int     c,                  /* The first character of the token */
        !           484:     char ** out_pp,             /* Pointer to pointer to output buf */
        !           485:     char *  out_end             /* End of output buffer             */
        !           486: )
        !           487: /*
        !           488:  *   Scan the next token of any type.
        !           489:  *   The token is written out to the specified buffer and the output pointer
        !           490:  * is advanced.  Token is terminated by EOS.  Return the type of token.
        !           491:  *   If the token is an identifier, the token is also in identifier[].
        !           492:  *   If the token is a operator or punctuator, return OPE.
        !           493:  *   If 'c' is token separator, then return SEP.
        !           494:  *   If 'c' is not the first character of any known token and not a token
        !           495:  * separator, return SPE.
        !           496:  *   In POST_STD mode, inserts token separator (a space) between any tokens of
        !           497:  * source.
        !           498:  */
        !           499: {
        !           500:     char *  out = *out_pp;              /* Output pointer           */
        !           501:     int     ch_type;                    /* Type of character        */
        !           502:     int     token_type = 0;             /* Type of token            */
        !           503:     int     ch;
        !           504:
        !           505:     if (standard)
        !           506:         in_token = TRUE;                /* While a token is scanned */
        !           507:     c = c & UCHARMAX;
        !           508:     ch_type = char_type[ c] & MBMASK;
        !           509:
        !           510:     switch (ch_type) {
        !           511:     case LET:                           /* Probably an identifier   */
        !           512:         switch (c) {
        !           513:         case 'L':
        !           514:             if (! standard)
        !           515:                 goto  ident;
        !           516:             ch = get_ch();
        !           517:             if (char_type[ ch] & QUO) { /* char_type[ ch] == QUO    */
        !           518:                 if (ch == '"')
        !           519:                     token_type = WSTR;  /* Wide-char string literal */
        !           520:                 else
        !           521:                     token_type = WCHR;  /* Wide-char constant       */
        !           522:                 c = ch;
        !           523:                 *out++ = 'L';
        !           524:                 break;                  /* Fall down to "case QUO:" */
        !           525:             } else {
        !           526:                 unget_ch();
        !           527:             }                           /* Fall through             */
        !           528:         default:                        /* An identifier            */
        !           529: ident:
        !           530:             scan_id( c);
        !           531:             out = stpcpy( out, identifier);
        !           532:             token_type = NAM;
        !           533:             break;
        !           534:         }
        !           535:         if (token_type == NAM)
        !           536:             break;
        !           537:         /* Else fall through    -- i.e. WSTR, WCHR  */
        !           538:     case QUO:                   /* String or character constant     */
        !           539:         out = scan_quote( c, out, out_end, FALSE);
        !           540:         if (token_type == 0) {                  /* Without prefix L */
        !           541:             if (c == '"')
        !           542:                 token_type = STR;
        !           543:             else
        !           544:                 token_type = CHR;
        !           545:         }   /* Else WSTR or WCHR    */
        !           546:         break;
        !           547:     case DOT:
        !           548:         ch = get_ch();
        !           549:         unget_ch();
        !           550:         if ((char_type[ ch] & DIG) == 0)        /* Operator '.' or '...'    */
        !           551:             goto  operat;
        !           552:         /* Else fall through    */
        !           553:     case DIG:                           /* Preprocessing number     */
        !           554:         out = (standard ? scan_number( c, out, out_end)
        !           555:                 : scan_number_prestd( c, out, out_end));
        !           556:         token_type = NUM;
        !           557:         break;
        !           558:     case PUNC:
        !           559: operat: out = scan_op( c, out);         /* Operator or punctuator   */
        !           560:         token_type = OPE;       /* Number is set in global "openum" */
        !           561:         break;
        !           562:     default:                /* Special tokens or special characters */
        !           563: #if OK_UCN
        !           564:         if (mcpp_mode == STD && c == '\\' && stdc2) {
        !           565:             ch = get_ch();
        !           566:             unget_ch();
        !           567:             if (ch == 'U' || ch == 'u')
        !           568:                 goto  ident;            /* Universal-Characte-Name  */
        !           569:         }
        !           570: #endif
        !           571: #if OK_MBIDENT
        !           572:         if (mcpp_mode == STD && (char_type[ c] & mbchk) && stdc3) {
        !           573:             char *  bptr = infile->bptr;
        !           574:             mb_read( c, &infile->bptr, &out);
        !           575:             infile->bptr = bptr;
        !           576:             out = *out_pp;
        !           577:             goto  ident;        /* An identifier with multi-byte characters */
        !           578:             /* Mbchar cheking has been done in scan_quote() and others. */
        !           579:         }
        !           580: #endif
        !           581:         if ((standard && (c == CAT || c == ST_QUOTE)) || (char_type[ c] & SPA))
        !           582:             token_type = SEP;       /* Token separator or magic char*/
        !           583:         else
        !           584:             token_type = SPE;
        !           585:             /* Unkown token ($, @, multi-byte character or Latin    */
        !           586:         *out++ = c;
        !           587:         *out = EOS;
        !           588:         break;
        !           589:     }
        !           590:
        !           591:     if (out_end < out)
        !           592:         cfatal( "Buffer overflow scanning token \"%s\""     /* _F_  */
        !           593:                 , *out_pp, 0L, NULL);
        !           594:     if (mcpp_debug & TOKEN)
        !           595:         dump_token( token_type, *out_pp);
        !           596:     if (mcpp_mode == POST_STD && token_type != SEP && infile->fp != NULL
        !           597:             && (char_type[ *infile->bptr & UCHARMAX] & SPA) == 0)
        !           598:         insert_sep = INSERT_SEP;    /* Insert token separator       */
        !           599:     *out_pp = out;
        !           600:
        !           601:     in_token = FALSE;               /* Token scanning has been done */
        !           602:     return  token_type;
        !           603: }
        !           604:
        !           605: static void scan_id(
        !           606:     int     c                               /* First char of id     */
        !           607: )
        !           608: /*
        !           609:  * Reads the next identifier and put it into identifier[].
        !           610:  * The caller has already read the first character of the identifier.
        !           611:  */
        !           612: {
        !           613:     static char * const     limit = &identifier[ IDMAX];
        !           614:     static int      dollar_diagnosed = FALSE;   /* Flag of diagnosing '$'   */
        !           615: #if OK_UCN
        !           616:     int     uc2 = 0, uc4 = 0;           /* Count of UCN16, UCN32    */
        !           617: #endif
        !           618: #if OK_MBIDENT
        !           619:     int     mb = 0;                     /* Count of MBCHAR  */
        !           620: #endif
        !           621:     size_t  len;                        /* Length of identifier     */
        !           622:     char *  bp = identifier;
        !           623:
        !           624:     if (c == IN_SRC) {                  /* Magic character  */
        !           625:         *bp++ = c;
        !           626:         if ((mcpp_debug & MACRO_CALL) && ! in_directive) {
        !           627:             *bp++ = get_ch();           /* Its 2-bytes      */
        !           628:             *bp++ = get_ch();           /*      argument    */
        !           629:         }
        !           630:         c = get_ch();
        !           631:     }
        !           632:
        !           633:     do {
        !           634:         if (bp < limit)
        !           635:             *bp++ = c;
        !           636: #if OK_UCN
        !           637:         if (mcpp_mode == STD && c == '\\' && stdc2) {
        !           638:             int     cnt;
        !           639:             char *  tp = bp;
        !           640:
        !           641:             if ((c = get_ch()) == 'u') {
        !           642:                 cnt = 4;
        !           643:             } else if (c == 'U') {
        !           644:                 cnt = 8;
        !           645:             } else {
        !           646:                 unget_ch();
        !           647:                 bp--;
        !           648:                 break;
        !           649:             }
        !           650:             *bp++ = c;
        !           651:             if ((bp = scan_ucn( cnt, bp)) == NULL)      /* Error    */
        !           652:                 return;
        !           653:             if (cnt == 4)
        !           654:                 uc2++;
        !           655:             else if (cnt == 8)
        !           656:                 uc4++;
        !           657:             if (limit <= tp)            /* Too long identifier      */
        !           658:                 bp = tp;                /* Back the pointer         */
        !           659:             goto  next_c;
        !           660:         }
        !           661: #endif  /* OK_UCN   */
        !           662: #if OK_MBIDENT
        !           663:         if (mcpp_mode == STD && (char_type[ c] & mbchk) && stdc3) {
        !           664:             len = mb_read( c, &infile->bptr, &bp);
        !           665:             if (len & MB_ERROR) {
        !           666:                 if (infile->fp)
        !           667:                     cerror(
        !           668:                     "Illegal multi-byte character sequence."    /* _E_  */
        !           669:                             , NULL, 0L, NULL);
        !           670:             } else {
        !           671:                 mb += len;
        !           672:             }
        !           673:         }
        !           674: #endif  /* OK_MBIDENT   */
        !           675: #if OK_UCN
        !           676: next_c:
        !           677: #endif
        !           678:         c = get_ch();
        !           679:     } while ((char_type[ c] & (LET | DIG))      /* Letter or digit  */
        !           680: #if OK_UCN
        !           681:             || (mcpp_mode == STD && c == '\\' && stdc2)
        !           682: #endif
        !           683: #if OK_MBIDENT
        !           684:             || (mcpp_mode == STD && (char_type[ c] & mbchk) && stdc3)
        !           685: #endif
        !           686:         );
        !           687:
        !           688:     unget_ch();
        !           689:     *bp = EOS;
        !           690:
        !           691:     if (bp >= limit && (warn_level & 1))        /* Limit of token   */
        !           692:         cwarn( "Too long identifier truncated to \"%s\""    /* _W1_ */
        !           693:                 , identifier, 0L, NULL);
        !           694:
        !           695:     len = bp - identifier;
        !           696: #if IDMAX > IDLEN90MIN
        !           697:     /* UCN16, UCN32, MBCHAR are counted as one character for each.  */
        !           698: #if OK_UCN
        !           699:     if (mcpp_mode == STD)
        !           700:         len -= (uc2 * 5) - (uc4 * 9);
        !           701: #endif
        !           702: #if OK_MBIDENT
        !           703:     if (mcpp_mode == STD)
        !           704:         len -= mb;
        !           705: #endif
        !           706:     if (standard && infile->fp && len > std_limits.id_len && (warn_level & 4))
        !           707:         cwarn( "Identifier longer than %.0s%ld characters \"%s\""   /* _W4_ */
        !           708:                 , NULL, (long) std_limits.id_len, identifier);
        !           709: #endif  /* IDMAX > IDLEN90MIN   */
        !           710:
        !           711:     if (option_flags.dollar_in_name && dollar_diagnosed == FALSE
        !           712:             && (warn_level & 2) && strchr( identifier, '$') != NULL) {
        !           713:         cwarn( "'$' in identifier \"%s\"", identifier, 0L, NULL); /* _W2_ */
        !           714:         dollar_diagnosed = TRUE;            /* Diagnose only once   */
        !           715:     }
        !           716: }
        !           717:
        !           718: char *  scan_quote(
        !           719:     int         delim,              /* ', " or < (header-name)      */
        !           720:     char *      out,                /* Output buffer                */
        !           721:     char *      out_end,            /* End of output buffer         */
        !           722:     int         diag                /* Diagnostic should be output  */
        !           723: )
        !           724: /*
        !           725:  * Scan off a string literal or character constant to the output buffer.
        !           726:  * Report diagnosis if the quotation is terminated by newline or character
        !           727:  * constant is empty (provided 'diag' is TRUE).
        !           728:  * Return the next output pointer or NULL (on error).
        !           729:  */
        !           730: {
        !           731:     const char * const      skip_line = ", skipped the line";   /* _E_  */
        !           732:     const char * const      unterm_string
        !           733:                         = "Unterminated string literal%s";
        !           734:     const char * const      unterm_char
        !           735:                         = "Unterminated character constant %s%.0ld%s";
        !           736:     const char * const      empty_const
        !           737:                         = "Empty character constant %s%.0ld%s";
        !           738:     const char *    skip;
        !           739:     size_t      len;
        !           740:     int         c;
        !           741:     char *      out_p = out;
        !           742:
        !           743:     /* Set again in case of called from routines other than scan_token().   */
        !           744:     if (standard)
        !           745:         in_token = TRUE;
        !           746:     *out_p++ = delim;
        !           747:     if (delim == '<')
        !           748:         delim = '>';
        !           749:
        !           750: scan:
        !           751:     while ((c = get_ch()) != EOS) {
        !           752:
        !           753: #if MBCHAR
        !           754:         if (char_type[ c] & mbchk) {
        !           755:             /* First of multi-byte character (or shift-sequence)    */
        !           756:             char *  bptr = infile->bptr;
        !           757:             len = mb_read( c, &infile->bptr, (*out_p++ = c, &out_p));
        !           758:             if (len & MB_ERROR) {
        !           759:                 if (infile->fp != NULL && compiling && diag) {
        !           760:                     if (warn_level & 1) {
        !           761:                         char *  buf;
        !           762:                         size_t  chlen;
        !           763:                         buf = xmalloc( chlen = infile->bptr - bptr + 2);
        !           764:                         memcpy( buf, bptr, chlen - 1);
        !           765:                         buf[ chlen - 1] = EOS;
        !           766:                         cwarn(
        !           767:     "Illegal multi-byte character sequence \"%s\" in quotation",    /* _W1_ */
        !           768:                         buf, 0L, NULL);
        !           769:                         free( buf);
        !           770:                     }
        !           771:                 }
        !           772:                 continue;
        !           773:             } else {        /* Valid multi-byte character (or sequence) */
        !           774:                 goto  chk_limit;
        !           775:             }
        !           776:         }
        !           777: #endif
        !           778:         if (c == delim) {
        !           779:             break;
        !           780:         } else if (c == '\\' && delim != '>') { /* In string literal    */
        !           781: #if OK_UCN
        !           782:             if (mcpp_mode == STD && stdc2) {
        !           783:                 int         cnt;
        !           784:                 char *      tp;
        !           785:
        !           786:                 *out_p++ = c;
        !           787:                 if ((c = get_ch()) == 'u') {
        !           788:                     cnt = 4;
        !           789:                 } else if (c == 'U') {
        !           790:                     cnt = 8;
        !           791:                 } else {
        !           792:                     goto  escape;
        !           793:                 }
        !           794:                 *out_p++ = c;
        !           795:                 if ((tp = scan_ucn( cnt, out_p)) != NULL)
        !           796:                     out_p = tp;
        !           797:                 /* Else error   */
        !           798:                 continue;       /* Error or not, anyway continue    */
        !           799:             }
        !           800: #endif  /* OK_UCN   */
        !           801:             *out_p++ = c;                   /* Escape sequence      */
        !           802:             c = get_ch();
        !           803: escape:
        !           804: #if MBCHAR
        !           805:             if (char_type[ c] & mbchk) {
        !           806:                                 /* '\\' followed by multi-byte char */
        !           807:                 unget_ch();
        !           808:                 continue;
        !           809:             }
        !           810: #endif
        !           811:             if (! standard && c == '\n') {  /* <backslash><newline> */
        !           812:                 out_p--;                    /* Splice the lines     */
        !           813:                 if (cat_line( TRUE) == NULL)        /* End of file  */
        !           814:                     break;
        !           815:                 c = get_ch();
        !           816:             }
        !           817:         } else if (mcpp_mode == POST_STD && c == ' ' && delim == '>'
        !           818:                 && infile->fp == NULL) {
        !           819:             continue;   /* Skip space possibly inserted by macro expansion  */
        !           820:         } else if (c == '\n') {
        !           821:             break;
        !           822:         }
        !           823:         if (diag && iscntrl( c) && ((char_type[ c] & SPA) == 0)
        !           824:                 && (warn_level & 1))
        !           825:             cwarn(
        !           826:             "Illegal control character %.0s0lx%02x in quotation"    /* _W1_ */
        !           827:                     , NULL, (long) c, NULL);
        !           828:         *out_p++ = c;
        !           829: chk_limit:
        !           830:         if (out_end < out_p) {
        !           831:             *out_end = EOS;
        !           832:             cfatal( "Too long quotation", NULL, 0L, NULL);  /* _F_  */
        !           833:         }
        !           834:     }
        !           835:
        !           836:     if (c == '\n' || c == EOS)
        !           837:         unget_ch();
        !           838:     if (c == delim)
        !           839:         *out_p++ = delim;
        !           840:     *out_p = EOS;
        !           841:     if (diag) {                         /* At translation phase 3   */
        !           842:         skip = (infile->fp == NULL) ? NULL : skip_line;
        !           843:         if (c != delim) {
        !           844:             if (mcpp_mode == OLD_PREP   /* Implicit closing of quote*/
        !           845:                     && (delim == '"' || delim == '\''))
        !           846:                 goto  done;
        !           847:             if (delim == '"') {
        !           848:                 if (mcpp_mode != POST_STD && option_flags.lang_asm) {
        !           849:                     /* STD, KR      */
        !           850:                     /* Concatenate the unterminated string to the next line */
        !           851:                     if (warn_level & 1)
        !           852:                         cwarn( unterm_string
        !           853:                                 , ", catenated to the next line"    /* _W1_ */
        !           854:                                 , 0L, NULL);
        !           855:                     if (cat_line( FALSE) != NULL)
        !           856:                         goto  scan;         /* Splice the lines     */
        !           857:                     /* Else end of file     */
        !           858:                 } else {
        !           859:                     cerror( unterm_string, skip, 0L, NULL); /* _E_  */
        !           860:                 }
        !           861:             } else if (delim == '\'') {
        !           862:                 if (mcpp_mode != POST_STD && option_flags.lang_asm) {
        !           863:                     /* STD, KR      */
        !           864:                     if (warn_level & 1)
        !           865:                         cwarn( unterm_char, out, 0L, NULL); /* _W1_ */
        !           866:                     goto  done;
        !           867:                 } else {
        !           868:                     cerror( unterm_char, out, 0L, skip);    /* _E_  */
        !           869:                 }
        !           870:             } else {
        !           871:                 cerror( "Unterminated header name %s%.0ld%s"        /* _E_  */
        !           872:                         , out, 0L, skip);
        !           873:             }
        !           874:             out_p = NULL;
        !           875:         } else if (delim == '\'' && out_p - out <= 2) {
        !           876:             if (mcpp_mode != POST_STD && option_flags.lang_asm) {
        !           877:                 /* STD, KR      */
        !           878:                 if (warn_level & 1)
        !           879:                     cwarn( empty_const, out, 0L, skip);     /* _W1_ */
        !           880:             } else {
        !           881:                 cerror( empty_const, out, 0L, skip);        /* _E_  */
        !           882:                 out_p = NULL;
        !           883:                 goto  done;
        !           884:             }
        !           885:         } else if (mcpp_mode == POST_STD && delim == '>' && (warn_level & 2)) {
        !           886:             cwarn(
        !           887:         "Header-name enclosed by <, > is an obsolescent feature %s" /* _W2_ */
        !           888:                     , out, 0L, skip);
        !           889:         }
        !           890: #if NWORK-2 > SLEN90MIN
        !           891:         if (standard && out_p - out > std_limits.str_len && (warn_level & 4))
        !           892:             cwarn( "Quotation longer than %.0s%ld bytes"    /* _W4_ */
        !           893:                     , NULL, std_limits.str_len, NULL);
        !           894: #endif
        !           895:     }
        !           896:
        !           897: done:
        !           898:     in_token = FALSE;
        !           899:     return  out_p;
        !           900: }
        !           901:
        !           902: static char *   cat_line(
        !           903:     int     del_bsl         /* Delete the <backslash><newline> ?    */
        !           904: )
        !           905: /*
        !           906:  * If del_bsl == TRUE:
        !           907:  *     Delete <backslash><newline> sequence in string literal.
        !           908:  * FALSE: Overwrite the <newline> with <backslash>'n'.
        !           909:  * Return NULL on end of file.  Called only from scan_quote().
        !           910:  * This routine is never called in POST_STD mode.
        !           911:  */
        !           912: {
        !           913:     size_t  len;
        !           914:     char *  save1, * save2;
        !           915:
        !           916:     if (del_bsl) {          /* Delete the <backslash><newline>      */
        !           917:         infile->bptr -= 2;
        !           918:         len = infile->bptr - infile->buffer;
        !           919:     } else {        /* Overwrite the <newline> with <backslash>'n'  */
        !           920:         strcpy( infile->bptr, "\\n");
        !           921:         len = strlen( infile->buffer);
        !           922:     }
        !           923:     save1 = save_string( infile->buffer);
        !           924:     save2 = get_line( FALSE);   /* infile->buffer is overwritten    */
        !           925:     if (save2 == NULL) {
        !           926:         free( save1);
        !           927:         return  NULL;
        !           928:     }
        !           929:     save2 = save_string( infile->buffer);
        !           930:     memcpy( infile->buffer, save1, len);
        !           931:     strcpy( infile->buffer + len, save2);               /* Catenate */
        !           932:     free( save1);
        !           933:     free( save2);
        !           934:     if (! del_bsl)
        !           935:         len -= 2;
        !           936:     infile->bptr = infile->buffer + len;
        !           937:     return  infile->bptr;
        !           938: }
        !           939:
        !           940: static char *   scan_number(
        !           941:     int     c,                              /* First char of number */
        !           942:     char *  out,                            /* Output buffer        */
        !           943:     char *  out_end                 /* Limit of output buffer       */
        !           944: )
        !           945: /*
        !           946:  * Read a preprocessing number.
        !           947:  * By scan_token() we know already that the first c is from 0 to 9 or dot,
        !           948:  * and if c is dot then the second character is digit.
        !           949:  * Returns the advanced output pointer.
        !           950:  * Note: preprocessing number permits non-numeric forms such as 3E+xy,
        !           951:  *   which are used in stringization or token-concatenation.
        !           952:  */
        !           953: {
        !           954:     char *      out_p = out;        /* Current output pointer       */
        !           955:
        !           956:     do {
        !           957:         *out_p++ = c;
        !           958:         if (c == 'E' || c == 'e'    /* Sign should follow 'E', 'e', */
        !           959:                 || (stdc3 && (c == 'P' || c == 'p'))
        !           960:                                             /* 'P' or 'p'.          */
        !           961:                 ) {
        !           962:             c = get_ch();
        !           963:             if (c == '+' || c == '-') {
        !           964:                 *out_p++ = c;
        !           965:                 c = get_ch();
        !           966:             }
        !           967: #if OK_UCN
        !           968:         } else if (mcpp_mode == STD && c == '\\' && stdc3) {
        !           969:             int     cnt;
        !           970:             char *  tp;
        !           971:
        !           972:             if ((c = get_ch()) == 'u') {
        !           973:                 cnt = 4;
        !           974:             } else if (c == 'U') {
        !           975:                 cnt = 8;
        !           976:             } else {
        !           977:                 unget_ch();
        !           978:                 out_p--;
        !           979:                 break;
        !           980:             }
        !           981:             *out_p++ = c;
        !           982:             if ((tp = scan_ucn( cnt, out_p)) == NULL)      /* Error    */
        !           983:                 break;
        !           984:             else
        !           985:                 out_p = tp;
        !           986:             c = get_ch();
        !           987: #endif  /* OK_UCN   */
        !           988: #if OK_MBIDENT
        !           989:         } else if (mcpp_mode == STD && (char_type[ c] & mbchk) && stdc3) {
        !           990:             len = mb_read( c, &infile->bptr, &out_p);
        !           991:             if (len & MB_ERROR) {
        !           992:                 if (infile->fp)
        !           993:                     cerror(
        !           994:                     "Illegal multi-byte character sequence."    /* _E_  */
        !           995:                             , NULL, 0L, NULL);
        !           996:             }
        !           997: #endif  /* OK_MBIDENT   */
        !           998:         } else {
        !           999:             c = get_ch();
        !          1000:         }
        !          1001:     } while ((char_type[ c] & (DIG | DOT | LET))    /* Digit, dot or letter */
        !          1002: #if OK_UCN
        !          1003:             || (mcpp_mode == STD && c == '\\' && stdc3)
        !          1004: #endif
        !          1005: #if OK_MBIDENT
        !          1006:             || (mcpp_mode == STD && (char_type[ c] & mbchk) && stdc3)
        !          1007: #endif
        !          1008:         );
        !          1009:
        !          1010:     *out_p = EOS;
        !          1011:     if (out_end < out_p)
        !          1012:         cfatal( "Too long pp-number token \"%s\""           /* _F_  */
        !          1013:                 , out, 0L, NULL);
        !          1014:     unget_ch();
        !          1015:     return  out_p;
        !          1016: }
        !          1017:
        !          1018: /* Original version of DECUS CPP with slight modifications, */
        !          1019: /* too exact for Standard preprocessing.                    */
        !          1020: static char *   scan_number_prestd(
        !          1021:     int         c,                          /* First char of number */
        !          1022:     char *      out,                        /* Output buffer        */
        !          1023:     char *      out_end             /* Limit of output buffer       */
        !          1024: )
        !          1025: /*
        !          1026:  * Process a number.  We know that c is from 0 to 9 or dot.
        !          1027:  * Algorithm from Dave Conroy's Decus C.
        !          1028:  * Returns the advanced output pointer.
        !          1029:  */
        !          1030: {
        !          1031:     char * const    out_s = out;            /* For diagnostics      */
        !          1032:     int             radix;                  /* 8, 10, or 16         */
        !          1033:     int             expseen;                /* 'e' seen in floater  */
        !          1034:     int             octal89;                /* For bad octal test   */
        !          1035:     int             dotflag;                /* TRUE if '.' was seen */
        !          1036:
        !          1037:     expseen = FALSE;                        /* No exponent seen yet */
        !          1038:     octal89 = FALSE;                        /* No bad octal yet     */
        !          1039:     radix = 10;                             /* Assume decimal       */
        !          1040:     if ((dotflag = (c == '.')) != FALSE) {  /* . something?         */
        !          1041:         *out++ = '.';                       /* Always out the dot   */
        !          1042:         if ((char_type[(c = get_ch())] & DIG) == 0) {
        !          1043:                                             /* If not a float numb, */
        !          1044:             goto  nomore;                   /* All done for now     */
        !          1045:         }
        !          1046:     }                                       /* End of float test    */
        !          1047:     else if (c == '0') {                    /* Octal or hex?        */
        !          1048:         *out++ = c;                         /* Stuff initial zero   */
        !          1049:         radix = 8;                          /* Assume it's octal    */
        !          1050:         c = get_ch();                       /* Look for an 'x'      */
        !          1051:         if (c == 'x' || c == 'X') {         /* Did we get one?      */
        !          1052:             radix = 16;                     /* Remember new radix   */
        !          1053:             *out++ = c;                     /* Stuff the 'x'        */
        !          1054:             c = get_ch();                   /* Get next character   */
        !          1055:         }
        !          1056:     }
        !          1057:     while (1) {                             /* Process curr. char.  */
        !          1058:         /*
        !          1059:          * Note that this algorithm accepts "012e4" and "03.4"
        !          1060:          * as legitimate floating-point numbers.
        !          1061:          */
        !          1062:         if (radix != 16 && (c == 'e' || c == 'E')) {
        !          1063:             if (expseen)                    /* Already saw 'E'?     */
        !          1064:                 break;                      /* Exit loop, bad nbr.  */
        !          1065:             expseen = TRUE;                 /* Set exponent seen    */
        !          1066:             radix = 10;                     /* Decimal exponent     */
        !          1067:             *out++ = c;                     /* Output the 'e'       */
        !          1068:             if ((c = get_ch()) != '+' && c != '-')
        !          1069:                 continue;
        !          1070:         }
        !          1071:         else if (radix != 16 && c == '.') {
        !          1072:             if (dotflag)                    /* Saw dot already?     */
        !          1073:                 break;                      /* Exit loop, two dots  */
        !          1074:             dotflag = TRUE;                 /* Remember the dot     */
        !          1075:             radix = 10;                     /* Decimal fraction     */
        !          1076:         }
        !          1077:         else {                              /* Check the digit      */
        !          1078:             switch (c) {
        !          1079:             case '8': case '9':             /* Sometimes wrong      */
        !          1080:                 octal89 = TRUE;             /* Do check later       */
        !          1081:             case '0': case '1': case '2': case '3':
        !          1082:             case '4': case '5': case '6': case '7':
        !          1083:                 break;                      /* Always ok            */
        !          1084:
        !          1085:             case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
        !          1086:             case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
        !          1087:                 if (radix == 16)            /* Alpha's are ok only  */
        !          1088:                     break;                  /* if reading hex.      */
        !          1089:             default:                        /* At number end        */
        !          1090:                 goto done;                  /* Break from for loop  */
        !          1091:             }                               /* End of switch        */
        !          1092:         }                                   /* End general case     */
        !          1093:         *out++ = c;                         /* Accept the character */
        !          1094:         c = get_ch();                       /* Read another char    */
        !          1095:     }                                       /* End of scan loop     */
        !          1096:
        !          1097:     if (out_end < out)                      /* Buffer overflow      */
        !          1098:         goto  nomore;
        !          1099:     /*
        !          1100:      * When we break out of the scan loop, c contains the first
        !          1101:      * character (maybe) not in the number.  If the number is an
        !          1102:      * integer, allow a trailing 'L' for long.  If not those, push
        !          1103:      * the trailing character back on the input stream.
        !          1104:      * Floating point numbers accept a trailing 'L' for "long double".
        !          1105:      */
        !          1106: done:
        !          1107:     if (! (dotflag || expseen)) {           /* Not floating point   */
        !          1108:         /*
        !          1109:          * We know that dotflag and expseen are both zero, now:
        !          1110:          *   dotflag signals "saw 'L'".
        !          1111:          */
        !          1112:         for (;;) {
        !          1113:             switch (c) {
        !          1114:             case 'l':
        !          1115:             case 'L':
        !          1116:                 if (dotflag)
        !          1117:                     goto nomore;
        !          1118:                 dotflag = TRUE;
        !          1119:                 break;
        !          1120:             default:
        !          1121:                 goto nomore;
        !          1122:             }
        !          1123:             *out++ = c;                     /* Got 'L' .            */
        !          1124:             c = get_ch();                   /* Look at next, too.   */
        !          1125:         }
        !          1126:     }
        !          1127:
        !          1128: nomore: *out = EOS;
        !          1129:     if (out_end < out)
        !          1130:         goto  overflow;
        !          1131:     unget_ch();                             /* Not part of a number */
        !          1132:     if (octal89 && radix == 8 && (warn_level & 1))
        !          1133:         cwarn( "Illegal digit in octal number \"%s\""       /* _W1_ */
        !          1134:                 , out_s, 0L, NULL);
        !          1135:     return  out;
        !          1136:
        !          1137: overflow:
        !          1138:     cfatal( "Too long number token \"%s\"", out_s, 0L, NULL);       /* _F_  */
        !          1139:     return  out;
        !          1140: }
        !          1141:
        !          1142: #if OK_UCN
        !          1143: static char *   scan_ucn(
        !          1144:     int     cnt,                            /* Bytes of sequence    */
        !          1145:     char *  out                             /* Output buffer        */
        !          1146: )
        !          1147: /*
        !          1148:  * Scan an UCN sequence and put the sequence to 'out'.
        !          1149:  * Return the advanced pointer or NULL on failure.
        !          1150:  * This routine is never called in POST_STD mode.
        !          1151:  */
        !          1152: {
        !          1153:     uexpr_t value;                              /* Value of UCN     */
        !          1154:     int     i, c;
        !          1155:
        !          1156:     value = 0L;
        !          1157:     for (i = 0; i < cnt; i++) {
        !          1158:         c = get_ch();
        !          1159:         if (! isxdigit( c)) {
        !          1160:             if (infile->fp)
        !          1161:                 cerror( "Illegal UCN sequence"              /* _E_  */
        !          1162:                         , NULL, 0L, NULL);
        !          1163:                 *out = EOS;
        !          1164:                 unget_ch();
        !          1165:                 return  NULL;
        !          1166:         }
        !          1167:         c = tolower( c);
        !          1168:         *out++ = c;
        !          1169:         c = (isdigit( c) ? (c - '0') : (c - 'a' + 10));
        !          1170:         value = (value << 4) | c;
        !          1171:     }
        !          1172:     if (infile->fp                              /* In source        */
        !          1173:             && ((value >= 0L && value <= 0x9FL
        !          1174:                 && value != 0x24L && value != 0x40L && value != 0x60L)
        !          1175:                                     /* Basic source character       */
        !          1176:             || (stdc3 && (value >= 0xD800L && value <= 0xDFFFL))))
        !          1177:                                     /* Reserved for special chars   */
        !          1178:         cerror( "UCN cannot specify the value %.0s\"%08lx\""    /* _E_    */
        !          1179:                     , NULL, (long) value, NULL);
        !          1180:     return  out;
        !          1181: }
        !          1182: #endif  /* OK_UCN   */
        !          1183:
        !          1184: static char *   scan_op(
        !          1185:     int     c,                          /* First char of the token  */
        !          1186:     char *  out                         /* Output buffer            */
        !          1187: )
        !          1188: /*
        !          1189:  * Scan C operator or punctuator into the specified buffer.
        !          1190:  * Return the advanced output pointer.
        !          1191:  * The code-number of the operator is stored to global variable 'openum'.
        !          1192:  * Note: '#' is not an operator nor a punctuator in other than directive line,
        !          1193:  *   nevertheless is handled as a punctuator in this cpp for convenience.
        !          1194:  */
        !          1195: {
        !          1196:     int     c2, c3, c4;
        !          1197:
        !          1198:     *out++ = c;
        !          1199:
        !          1200:     switch (c) {
        !          1201:     case '~':   openum = OP_COM;    break;
        !          1202:     case '(':   openum = OP_LPA;    break;
        !          1203:     case ')':   openum = OP_RPA;    break;
        !          1204:     case '?':   openum = OP_QUE;    break;
        !          1205:     case ';':    case '[':    case ']':    case '{':
        !          1206:     case '}':    case ',':
        !          1207:         openum = OP_1;
        !          1208:         break;
        !          1209:     default:
        !          1210:         openum = OP_2;                  /* Tentative guess          */
        !          1211:     }
        !          1212:
        !          1213:     if (openum != OP_2) {               /* Single byte operators    */
        !          1214:         *out = EOS;
        !          1215:         return  out;
        !          1216:     }
        !          1217:
        !          1218:     c2 = get_ch();                      /* Possibly two bytes ops   */
        !          1219:     *out++ = c2;
        !          1220:
        !          1221:     switch (c) {
        !          1222:     case '=':
        !          1223:         openum = ((c2 == '=') ? OP_EQ : OP_1);          /* ==, =    */
        !          1224:         break;
        !          1225:     case '!':
        !          1226:         openum = ((c2 == '=') ? OP_NE : OP_NOT);        /* !=, !    */
        !          1227:         break;
        !          1228:     case '&':
        !          1229:         switch (c2) {
        !          1230:         case '&':   openum = OP_ANA;        break;      /* &&       */
        !          1231:         case '=':   /* openum = OP_2; */    break;      /* &=       */
        !          1232:         default :   openum = OP_AND;        break;      /* &        */
        !          1233:         }
        !          1234:         break;
        !          1235:     case '|':
        !          1236:         switch (c2) {
        !          1237:         case '|':   openum = OP_ORO;        break;      /* ||       */
        !          1238:         case '=':   /* openum = OP_2; */    break;      /* |=       */
        !          1239:         default :   openum = OP_OR;         break;      /* |        */
        !          1240:         }
        !          1241:         break;
        !          1242:     case '<':
        !          1243:         switch (c2) {
        !          1244:         case '<':   c3 = get_ch();
        !          1245:             if (c3 == '=') {
        !          1246:                 openum = OP_3;                          /* <<=      */
        !          1247:                 *out++ = c3;
        !          1248:             } else {
        !          1249:                 openum = OP_SL;                         /* <<       */
        !          1250:                 unget_ch();
        !          1251:             }
        !          1252:             break;
        !          1253:         case '=':   openum = OP_LE;         break;      /* <=       */
        !          1254:         case ':':                                   /* <: i.e. [    */
        !          1255:             if (mcpp_mode == STD && option_flags.dig)
        !          1256:                 openum = OP_LBRCK_D;
        !          1257:             else
        !          1258:                 openum = OP_LT;
        !          1259:             break;
        !          1260:         case '%':                                   /* <% i.e. {    */
        !          1261:             if (mcpp_mode == STD && option_flags.dig)
        !          1262:                 openum = OP_LBRACE_D;
        !          1263:             else
        !          1264:                 openum = OP_LT;
        !          1265:             break;
        !          1266:         default :   openum = OP_LT;         break;      /* <        */
        !          1267:         }
        !          1268:         break;
        !          1269:     case '>':
        !          1270:         switch (c2) {
        !          1271:         case '>':   c3 = get_ch();
        !          1272:             if (c3 == '=') {
        !          1273:                 openum = OP_3;                          /* >>=      */
        !          1274:                 *out++ = c3;
        !          1275:             } else {
        !          1276:                 openum = OP_SR;                         /* >>       */
        !          1277:                 unget_ch();
        !          1278:             }
        !          1279:             break;
        !          1280:         case '=':   openum = OP_GE;     break;          /* >=       */
        !          1281:         default :   openum = OP_GT;     break;          /* >        */
        !          1282:         }
        !          1283:         break;
        !          1284:     case '#':
        !          1285:         if (standard && (in_define || macro_line))  /* in #define or macro  */
        !          1286:             openum = ((c2 == '#') ? OP_CAT : OP_STR);   /* ##, #    */
        !          1287:         else
        !          1288:             openum = OP_1;                              /* #        */
        !          1289:         break;
        !          1290:     case '+':
        !          1291:         switch (c2) {
        !          1292:         case '+':                                       /* ++       */
        !          1293:         case '=':   /* openum = OP_2; */    break;      /* +=       */
        !          1294:         default :   openum = OP_ADD;        break;      /* +        */
        !          1295:         }
        !          1296:         break;
        !          1297:     case '-':
        !          1298:         switch (c2) {
        !          1299:         case '-':                                       /* --       */
        !          1300:         case '=':                                       /* -=       */
        !          1301:             /* openum = OP_2;   */
        !          1302:             break;
        !          1303:         case '>':
        !          1304:             if (cplus_val) {
        !          1305:                 if ((c3 = get_ch()) == '*') {           /* ->*      */
        !          1306:                     openum = OP_3;
        !          1307:                     *out++ = c3;
        !          1308:                 } else {
        !          1309:                     /* openum = OP_2;   */
        !          1310:                     unget_ch();
        !          1311:                 }
        !          1312:             }   /* else openum = OP_2;  */              /* ->       */
        !          1313:             /* else openum = OP_2;      */
        !          1314:             break;
        !          1315:         default :   openum = OP_SUB;        break;      /* -        */
        !          1316:         }
        !          1317:         break;
        !          1318:     case '%':
        !          1319:         switch (c2) {
        !          1320:         case '=':                           break;      /* %=       */
        !          1321:         case '>':                                   /* %> i.e. }    */
        !          1322:             if (mcpp_mode == STD && option_flags.dig)
        !          1323:                 openum = OP_RBRACE_D;
        !          1324:             else
        !          1325:                 openum = OP_MOD;
        !          1326:             break;
        !          1327:         case ':':
        !          1328:             if (mcpp_mode == STD && option_flags.dig) {
        !          1329:                 if ((c3 = get_ch()) == '%') {
        !          1330:                     if ((c4 = get_ch()) == ':') {   /* %:%: i.e. ## */
        !          1331:                         openum = OP_DSHARP_D;
        !          1332:                         *out++ = c3;
        !          1333:                         *out++ = c4;
        !          1334:                     } else {
        !          1335:                         unget_ch();
        !          1336:                         unget_ch();
        !          1337:                         openum = OP_SHARP_D;        /* %: i.e. #    */
        !          1338:                     }
        !          1339:                 } else {
        !          1340:                     unget_ch();
        !          1341:                     openum = OP_SHARP_D;            /* %: i.e. #    */
        !          1342:                 }
        !          1343:                 if (in_define) {                    /* in #define   */
        !          1344:                     if (openum == OP_DSHARP_D)
        !          1345:                         openum = OP_CAT;
        !          1346:                     else
        !          1347:                         openum = OP_STR;
        !          1348:                 }
        !          1349:             } else {
        !          1350:                 openum = OP_MOD;
        !          1351:             }
        !          1352:             break;
        !          1353:         default :   openum = OP_MOD;        break;      /* %        */
        !          1354:         }
        !          1355:         break;
        !          1356:     case '*':
        !          1357:         if (c2 != '=')                                  /* *        */
        !          1358:             openum = OP_MUL;
        !          1359:         /* else openum = OP_2;  */                      /* *=       */
        !          1360:         break;
        !          1361:     case '/':
        !          1362:         if (c2 != '=')                                  /* /        */
        !          1363:             openum = OP_DIV;
        !          1364:         /* else openum = OP_2;  */                      /* /=       */
        !          1365:         break;
        !          1366:     case '^':
        !          1367:         if (c2 != '=')                                  /* ^        */
        !          1368:             openum = OP_XOR;
        !          1369:         /* else openum = OP_2;  */                      /* ^=       */
        !          1370:         break;
        !          1371:     case '.':
        !          1372:         if (standard) {
        !          1373:             if (c2 == '.') {
        !          1374:                 c3 = get_ch();
        !          1375:                 if (c3 == '.') {
        !          1376:                     openum = OP_ELL;                    /* ...      */
        !          1377:                     *out++ = c3;
        !          1378:                     break;
        !          1379:                 } else {
        !          1380:                     unget_ch();
        !          1381:                     openum = OP_1;
        !          1382:                 }
        !          1383:             } else if (cplus_val && c2 == '*') {        /* .*       */
        !          1384:                 /* openum = OP_2    */  ;
        !          1385:             } else {                                    /* .        */
        !          1386:                 openum = OP_1;
        !          1387:             }
        !          1388:         } else {
        !          1389:             openum = OP_1;
        !          1390:         }
        !          1391:         break;
        !          1392:     case ':':
        !          1393:         if (cplus_val && c2 == ':')                     /* ::       */
        !          1394:             /* openum = OP_2    */  ;
        !          1395:         else if (mcpp_mode == STD && c2 == '>' && option_flags.dig)
        !          1396:             openum = OP_RBRCK_D;                    /* :> i.e. ]    */
        !          1397:         else                                            /* :        */
        !          1398:             openum = OP_COL;
        !          1399:         break;
        !          1400:     default:                                    /* Never reach here */
        !          1401:         cfatal( "Bug: Punctuator is mis-implemented %.0s0lx%x"      /* _F_  */
        !          1402:                 , NULL, (long) c, NULL);
        !          1403:         openum = OP_1;
        !          1404:         break;
        !          1405:     }
        !          1406:
        !          1407:     switch (openum) {
        !          1408:     case OP_STR:
        !          1409:         if (mcpp_mode == STD && c == '%')    break;              /* %:   */
        !          1410:     case OP_1:
        !          1411:     case OP_NOT:    case OP_AND:    case OP_OR:     case OP_LT:
        !          1412:     case OP_GT:     case OP_ADD:    case OP_SUB:    case OP_MOD:
        !          1413:     case OP_MUL:    case OP_DIV:    case OP_XOR:    case OP_COM:
        !          1414:     case OP_COL:    /* Any single byte operator or punctuator       */
        !          1415:         unget_ch();
        !          1416:         out--;
        !          1417:         break;
        !          1418:     default:        /* Two or more bytes operators or punctuators   */
        !          1419:         break;
        !          1420:     }
        !          1421:
        !          1422:     *out = EOS;
        !          1423:     return  out;
        !          1424: }
        !          1425:
        !          1426: int     id_operator(
        !          1427:     const char *    name
        !          1428: )
        !          1429: /*
        !          1430:  * Check whether the name is identifier-like operator in C++.
        !          1431:  * Return the operator number if matched, return 0 if not matched.
        !          1432:  * Note: these identifiers are defined as macros in <iso646.h> in C95.
        !          1433:  * This routine is never called in POST_STD mode.
        !          1434:  */
        !          1435: {
        !          1436:     typedef struct  id_op {
        !          1437:         const char *    name;
        !          1438:         int             op_num;
        !          1439:     } ID_OP;
        !          1440:
        !          1441:     ID_OP   id_ops[] = {
        !          1442:         { "and",    OP_ANA},
        !          1443:         { "and_eq", OP_2},
        !          1444:         { "bitand", OP_AND},
        !          1445:         { "bitor",  OP_OR},
        !          1446:         { "compl",  OP_COM},
        !          1447:         { "not",    OP_NOT},
        !          1448:         { "not_eq", OP_NE},
        !          1449:         { "or",     OP_ORO},
        !          1450:         { "or_eq",  OP_2},
        !          1451:         { "xor",    OP_XOR},
        !          1452:         { "xor_eq", OP_2},
        !          1453:         { NULL,     0},
        !          1454:     };
        !          1455:
        !          1456:     ID_OP *     id_p = id_ops;
        !          1457:
        !          1458:     while (id_p->name != NULL) {
        !          1459:         if (str_eq( name, id_p->name))
        !          1460:             return  id_p->op_num;
        !          1461:         id_p++;
        !          1462:     }
        !          1463:     return  0;
        !          1464: }
        !          1465:
        !          1466: void    expanding(
        !          1467:     const char *    name,       /* The name of (nested) macro just expanded. */
        !          1468:     int             to_be_freed /* The name should be freed later.  */
        !          1469: )
        !          1470: /*
        !          1471:  * Remember used macro name for diagnostic.
        !          1472:  */
        !          1473: {
        !          1474:     if (exp_mac_ind < EXP_MAC_IND_MAX - 1) {
        !          1475:         exp_mac_ind++;
        !          1476:     } else {
        !          1477:         clear_exp_mac();
        !          1478:         exp_mac_ind++;
        !          1479:     }
        !          1480:     expanding_macro[ exp_mac_ind].name = name;
        !          1481:     expanding_macro[ exp_mac_ind].to_be_freed = to_be_freed;
        !          1482: }
        !          1483:
        !          1484: void    clear_exp_mac( void)
        !          1485: /*
        !          1486:  * Initialize expanding_macro[] freeing names registered in
        !          1487:  * name_to_be_freed[].
        !          1488:  */
        !          1489: {
        !          1490:     int     i;
        !          1491:
        !          1492:     for (i = 1; i < EXP_MAC_IND_MAX; i++) {
        !          1493:         if (expanding_macro[ i].to_be_freed) {
        !          1494:             free( (void *) expanding_macro[ i].name);
        !          1495:             expanding_macro[ i].to_be_freed = FALSE;
        !          1496:         }
        !          1497:     }
        !          1498:     exp_mac_ind = 0;
        !          1499: }
        !          1500:
        !          1501: int     get_ch( void)
        !          1502: /*
        !          1503:  * Return the next character from a macro or the current file.
        !          1504:  * Always return the value representable by unsigned char.
        !          1505:  */
        !          1506: {
        !          1507:     int             len;
        !          1508:     int             c;
        !          1509:     FILEINFO *      file;
        !          1510:
        !          1511:     /*
        !          1512:      * 'in_token' is set to TRUE while scan_token() is executed (and
        !          1513:      * scan_id(), scan_quote(), scan_number(), scan_ucn() and scan_op()
        !          1514:      * via scan_token()) in Standard mode to simplify tokenization.
        !          1515:      * Any token cannot cross "file"s.
        !          1516:      */
        !          1517:     if (in_token)
        !          1518:         return (*infile->bptr++ & UCHARMAX);
        !          1519:
        !          1520:     if ((file = infile) == NULL)
        !          1521:         return  CHAR_EOF;                   /* End of all input     */
        !          1522:
        !          1523:     if (mcpp_mode == POST_STD && file->fp) {        /* In a source file     */
        !          1524:         switch (insert_sep) {
        !          1525:         case NO_SEP:
        !          1526:             break;
        !          1527:         case INSERT_SEP:                /* Insert a token separator */
        !          1528:             insert_sep = INSERTED_SEP;      /* Remember this fact   */
        !          1529:             return  ' ';                    /*   for unget_ch().    */
        !          1530:         case INSERTED_SEP:                  /* Has just inserted    */
        !          1531:             insert_sep = NO_SEP;            /* Clear the flag       */
        !          1532:             break;
        !          1533:         }
        !          1534:     }
        !          1535:     if (! standard && squeezews) {
        !          1536:         if (*file->bptr == ' ')
        !          1537:             file->bptr++;                   /* Squeeze white spaces */
        !          1538:         squeezews = FALSE;
        !          1539:     }
        !          1540:
        !          1541:     if (mcpp_debug & GETC) {
        !          1542:         mcpp_fprintf( DBG, "get_ch(%s) '%c' line %ld, bptr = %d, buffer"
        !          1543:             , file->fp ? cur_fullname : file->real_fname ? file->real_fname
        !          1544:             : file->filename ? file->filename : "NULL"
        !          1545:             , *file->bptr & UCHARMAX
        !          1546:             , src_line, (int) (file->bptr - file->buffer));
        !          1547:         dump_string( NULL, file->buffer);
        !          1548:         dump_unget( "get entrance");
        !          1549:     }
        !          1550:
        !          1551:     /*
        !          1552:      * Read a character from the current input logical line or macro.
        !          1553:      * At EOS, either finish the current macro (freeing temporary storage)
        !          1554:      * or get another logical line by parse_line().
        !          1555:      * At EOF, exit the current file (#included) or, at EOF from the MCPP input
        !          1556:      * file, return CHAR_EOF to finish processing.
        !          1557:      * The character is converted to int with no sign-extension.
        !          1558:      */
        !          1559:     if ((c = (*file->bptr++ & UCHARMAX)) != EOS) {
        !          1560:         if (standard)
        !          1561:             return  c;                      /* Just a character     */
        !          1562:         if (! in_string && c == '\\' && *file->bptr == '\n'
        !          1563:                 && in_define        /* '\\''\n' is deleted in #define line, */
        !          1564:                     /*   provided the '\\' is not the 2nd byte of mbchar.   */
        !          1565:                 && ! last_is_mbchar( file->buffer, strlen( file->buffer) - 2
        !          1566:                 && ! keep_spaces)
        !          1567:             ) {
        !          1568:             if (*(file->bptr - 2) == ' ')
        !          1569:                 squeezews = TRUE;
        !          1570:         } else {
        !          1571:             return  c;
        !          1572:         }
        !          1573:     }
        !          1574:
        !          1575:     /*
        !          1576:      * Nothing in current line or macro.  Get next line (if input from a
        !          1577:      * file), or do end of file/macro processing, and reenter get_ch() to
        !          1578:      * restart from the top.
        !          1579:      */
        !          1580:     if (file->fp &&                         /* In source file       */
        !          1581:             parse_line() != NULL)           /* Get line from file   */
        !          1582:         return  get_ch();
        !          1583:     /*
        !          1584:      * Free up space used by the (finished) file or macro and restart
        !          1585:      * input from the parent file/macro, if any.
        !          1586:      */
        !          1587:     infile = file->parent;                  /* Unwind file chain    */
        !          1588:     free( file->buffer);                    /* Free buffer          */
        !          1589:     if (infile == NULL) {                   /* If at end of input   */
        !          1590:         free( file->filename);
        !          1591:         free( file->src_dir);
        !          1592:         free( file);    /* full_fname is the same with filename for main file*/
        !          1593:         return  CHAR_EOF;                   /* Return end of file   */
        !          1594:     }
        !          1595:     if (file->fp) {                         /* Source file included */
        !          1596:         free( file->filename);              /* Free filename        */
        !          1597:         free( file->src_dir);               /* Free src_dir         */
        !          1598:         fclose( file->fp);                  /* Close finished file  */
        !          1599:         /* Do not free file->real_fname and file->full_fname        */
        !          1600:         cur_fullname = infile->full_fname;
        !          1601:         cur_fname = infile->real_fname;     /* Restore current fname*/
        !          1602:         if (infile->pos != 0L) {            /* Includer was closed  */
        !          1603:             infile->fp = fopen( cur_fullname, "r");
        !          1604:             fseek( infile->fp, infile->pos, SEEK_SET);
        !          1605:         }   /* Re-open the includer and restore the file-position   */
        !          1606:         len = (int) (infile->bptr - infile->buffer);
        !          1607:         infile->buffer = xrealloc( infile->buffer, NBUFF);
        !          1608:             /* Restore full size buffer to get the next line        */
        !          1609:         infile->bptr = infile->buffer + len;
        !          1610:         src_line = infile->line;            /* Reset line number    */
        !          1611:         inc_dirp = infile->dirp;            /* Includer's directory */
        !          1612: #if MCPP_LIB
        !          1613:         mcpp_set_out_func( infile->last_fputc, infile->last_fputs,
        !          1614:                            infile->last_fprintf);
        !          1615: #endif
        !          1616:         include_nest--;
        !          1617:         src_line++;                         /* Next line to #include*/
        !          1618:         sharp( NULL, infile->include_opt ? 1 : (file->include_opt ? 0 : 2));
        !          1619:             /* Need a #line now.  Marker depends on include_opt.    */
        !          1620:             /* The file of include_opt should be marked as 1.       */
        !          1621:             /* Else if returned from include_opt file, it is the    */
        !          1622:             /* main input file, and should not be marked.           */
        !          1623:             /* Else, it is normal includer file, and marked as 2.   */
        !          1624:         src_line--;
        !          1625:         newlines = 0;                       /* Clear the blank lines*/
        !          1626:         if (mcpp_debug & MACRO_CALL)    /* Should be re-initialized */
        !          1627:             com_cat_line.last_line = bsl_cat_line.last_line = 0L;
        !          1628:     } else if (file->filename) {            /* Expanding macro      */
        !          1629:         if (macro_name)     /* file->filename should be freed later */
        !          1630:             expanding( file->filename, TRUE);
        !          1631:         else
        !          1632:             free( file->filename);
        !          1633:     }
        !          1634:     free( file);                            /* Free file space      */
        !          1635:     return  get_ch();                       /* Get from the parent  */
        !          1636: }
        !          1637:
        !          1638: static char *   parse_line( void)
        !          1639: /*
        !          1640:  * ANSI (ISO) C: translation phase 3.
        !          1641:  * Parse a logical line.
        !          1642:  * Check illegal control characters.
        !          1643:  * Check unterminated string literal, character constant or comment.
        !          1644:  * Convert each comment to one space (or spaces of the comment length on
        !          1645:  * 'keep_spaces' mode)..
        !          1646:  * Squeeze succeding white spaces other than <newline> (including comments) to
        !          1647:  * one space (unless keep_spaces == TRUE).
        !          1648:  * The lines might be spliced by comments which cross the lines.
        !          1649:  */
        !          1650: {
        !          1651:     char *      temp;                       /* Temporary buffer     */
        !          1652:     char *      limit;                      /* Buffer end           */
        !          1653:     char *      tp;     /* Current pointer into temporary buffer    */
        !          1654:     char *      sp;                 /* Pointer into input buffer    */
        !          1655:     size_t      com_size;
        !          1656:     int         c;
        !          1657:
        !          1658:     if ((sp = get_line( FALSE)) == NULL)    /* Next logical line    */
        !          1659:         return  NULL;                       /* End of a file        */
        !          1660:     if (in_asm) {                           /* In #asm block        */
        !          1661:         while (char_type[ *sp++ & UCHARMAX] & SPA)
        !          1662:             ;
        !          1663:         if (*--sp == '#')                   /* Directive line       */
        !          1664:             infile->bptr = sp;
        !          1665:         return  infile->bptr;               /* Don't tokenize       */
        !          1666:     }
        !          1667:     tp = temp = xmalloc( (size_t) NBUFF);
        !          1668:     limit = temp + NBUFF - 2;
        !          1669:
        !          1670:     while (char_type[ c = *sp++ & UCHARMAX] & HSP) {
        !          1671:         if (mcpp_mode != POST_STD)
        !          1672:             /* Preserve line top horizontal white spaces    */
        !          1673:             /*      as they are for human-readability       */
        !          1674:             *tp++ = c;
        !          1675:         /* Else skip the line top spaces    */
        !          1676:     }
        !          1677:     sp--;
        !          1678:
        !          1679:     while ((c = *sp++ & UCHARMAX) != '\n') {
        !          1680:
        !          1681:         switch (c) {
        !          1682:         case '/':
        !          1683:             switch (*sp++) {
        !          1684:             case '*':                       /* Start of a comment   */
        !          1685: com_start:
        !          1686:                 if ((sp = read_a_comment( sp, &com_size)) == NULL) {
        !          1687:                     free( temp);            /* End of file with un- */
        !          1688:                     return  NULL;           /*   terminated comment */
        !          1689:                 }
        !          1690:                 if (keep_spaces && mcpp_mode != OLD_PREP) {
        !          1691:                     if (tp + com_size >= limit - 1)     /* Too long comment */
        !          1692:                         com_size = limit - tp - 1;      /* Truncate */
        !          1693:                     while (com_size--)
        !          1694:                         *tp++ = ' ';        /* Spaces of the comment length */
        !          1695:                     break;
        !          1696:                 }
        !          1697:                 switch (mcpp_mode) {
        !          1698:                 case POST_STD:
        !          1699:                     if (temp < tp && *(tp - 1) != ' ')
        !          1700:                         *tp++ = ' ';        /* Squeeze white spaces */
        !          1701:                     break;
        !          1702:                 case OLD_PREP:
        !          1703:                     if (temp == tp
        !          1704:                             || ! (char_type[ *(tp - 1) & UCHARMAX] & HSP))
        !          1705:                         *tp++ = COM_SEP;    /* Convert to magic character   */
        !          1706:                     break;
        !          1707:                 default:
        !          1708:                     if (temp == tp ||
        !          1709:                             ! (char_type[ *(tp - 1) & UCHARMAX] & HSP))
        !          1710:                         *tp++ = ' ';        /* Squeeze white spaces */
        !          1711:                     break;
        !          1712:                 }
        !          1713:                 break;
        !          1714:             case '/':                                       /* //   */
        !          1715:                 if (! standard)
        !          1716:                     goto  not_comment;
        !          1717:                 /* Comment when C++ or __STDC_VERSION__ >= 199901L      */
        !          1718:                 /* Need not to convert to a space because '\n' follows  */
        !          1719:                 if (! stdc2 && (warn_level & 2))
        !          1720:                     cwarn( "Parsed \"//\" as comment"       /* _W2_ */
        !          1721:                             , NULL, 0L, NULL);
        !          1722:                 if (keep_comments) {
        !          1723:                     sp -= 2;
        !          1724:                     while (*sp != '\n')     /* Until end of line    */
        !          1725:                         mcpp_fputc( *sp++, OUT);
        !          1726:                 }
        !          1727:                 goto  end_line;
        !          1728:             default:                        /* Not a comment        */
        !          1729: not_comment:
        !          1730:                 *tp++ = '/';
        !          1731:                 sp--;                       /* To re-read           */
        !          1732:                 break;
        !          1733:             }
        !          1734:             break;
        !          1735:         case '\r':                          /* Vertical white spaces*/
        !          1736:                 /* Note that [CR+LF] is already converted to [LF].  */
        !          1737:         case '\f':
        !          1738:         case '\v':
        !          1739:             if (warn_level & 4)
        !          1740:                 cwarn( "Converted %.0s0x%02lx to a space"   /* _W4_ */
        !          1741:                     , NULL, (long) c, NULL);
        !          1742:         case '\t':                          /* Horizontal space     */
        !          1743:         case ' ':
        !          1744:             if (keep_spaces) {
        !          1745:                 if (c == '\t')
        !          1746:                     *tp++ = '\t';
        !          1747:                 else
        !          1748:                     *tp++ = ' ';            /* Convert to ' '       */
        !          1749:             } else if (! (char_type[ *(tp - 1) & UCHARMAX] & HSP)) {
        !          1750:                 *tp++ = ' ';                /* Squeeze white spaces */
        !          1751:             } else if (mcpp_mode == OLD_PREP && *(tp - 1) == COM_SEP) {
        !          1752:                 *(tp - 1) = ' ';    /* Replace COM_SEP with ' '     */
        !          1753:             }
        !          1754:             break;
        !          1755:         case '"':                           /* String literal       */
        !          1756:         case '\'':                          /* Character constant   */
        !          1757:             infile->bptr = sp;
        !          1758:             if (standard) {
        !          1759:                 tp = scan_quote( c, tp, limit, TRUE);
        !          1760:             } else {
        !          1761:                 in_string = TRUE;   /* Enable line splicing by scan_quote() */
        !          1762:                 tp = scan_quote( c, tp, limit, TRUE);   /* (not by get_ch())*/
        !          1763:                 in_string = FALSE;
        !          1764:             }
        !          1765:             if (tp == NULL) {
        !          1766:                 free( temp);                /* Unbalanced quotation */
        !          1767:                 return  parse_line();       /* Skip the line        */
        !          1768:             }
        !          1769:             sp = infile->bptr;
        !          1770:             break;
        !          1771:         default:
        !          1772:             if (iscntrl( c)) {
        !          1773:                 cerror(             /* Skip the control character   */
        !          1774:     "Illegal control character %.0s0x%lx, skipped the character"    /* _E_  */
        !          1775:                         , NULL, (long) c, NULL);
        !          1776:             } else {                        /* Any valid character  */
        !          1777:                 *tp++ = c;
        !          1778:             }
        !          1779:             break;
        !          1780:         }
        !          1781:
        !          1782:         if (limit < tp) {
        !          1783:             *tp = EOS;
        !          1784:             cfatal( "Too long line spliced by comments"     /* _F_  */
        !          1785:                     , NULL, 0L, NULL);
        !          1786:         }
        !          1787:     }
        !          1788:
        !          1789: end_line:
        !          1790:     if (temp < tp && (char_type[ *(tp - 1) & UCHARMAX] & HSP))
        !          1791:         tp--;                       /* Remove trailing white space  */
        !          1792:     *tp++ = '\n';
        !          1793:     *tp = EOS;
        !          1794:     infile->bptr = strcpy( infile->buffer, temp);   /* Write back to buffer */
        !          1795:     free( temp);
        !          1796:     if (macro_line != 0 && macro_line != MACRO_ERROR) { /* Expanding macro  */
        !          1797:         temp = infile->buffer;
        !          1798:         while (char_type[ *temp & UCHARMAX] & HSP)
        !          1799:             temp++;
        !          1800:         if (*temp == '#'        /* This line starts with # token    */
        !          1801:                 || (mcpp_mode == STD && *temp == '%' && *(temp + 1) == ':'))
        !          1802:             if (warn_level & 1)
        !          1803:                 cwarn(
        !          1804:     "Macro started at line %.0s%ld swallowed directive-like line"   /* _W1_ */
        !          1805:                     , NULL, macro_line, NULL);
        !          1806:     }
        !          1807:     return  infile->buffer;
        !          1808: }
        !          1809:
        !          1810: static char *   read_a_comment(
        !          1811:     char *      sp,                         /* Source               */
        !          1812:     size_t *    sizp                        /* Size of the comment  */
        !          1813: )
        !          1814: /*
        !          1815:  * Read over a comment (which may cross the lines).
        !          1816:  */
        !          1817: {
        !          1818:     int         c;
        !          1819:     char *      saved_sp;
        !          1820:     int         cat_line = 0;       /* Number of catenated lines    */
        !          1821:
        !          1822:     if (keep_spaces) {
        !          1823:         saved_sp = sp - 2;          /* '-2' for beginning / and *   */
        !          1824:         *sizp = 0;
        !          1825:     }
        !          1826:     if (keep_comments)                      /* If writing comments  */
        !          1827:         mcpp_fputs( "/*", OUT);             /* Write the initializer*/
        !          1828:     c = *sp++;
        !          1829:
        !          1830:     while (1) {                             /* Eat a comment        */
        !          1831:         if (keep_comments)
        !          1832:             mcpp_fputc( c, OUT);
        !          1833:
        !          1834:         switch (c) {
        !          1835:         case '/':
        !          1836:             if ((c = *sp++) != '*')         /* Don't let comments   */
        !          1837:                 continue;                   /*   nest.              */
        !          1838:             if (warn_level & 1)
        !          1839:                 cwarn( "\"/*\" within comment", NULL, 0L, NULL);    /* _W1_ */
        !          1840:             if (keep_comments)
        !          1841:                 mcpp_fputc( c, OUT);
        !          1842:                                             /* Fall into * stuff    */
        !          1843:         case '*':
        !          1844:             if ((c = *sp++) != '/')         /* If comment doesn't   */
        !          1845:                 continue;                   /*   end, look at next. */
        !          1846:             if (keep_comments) {            /* Put out comment      */
        !          1847:                 mcpp_fputc( c, OUT);        /*   terminator, too.   */
        !          1848:                 mcpp_fputc( '\n', OUT);     /* Append '\n' to avoid */
        !          1849:                     /*  trouble on some other tools such as rpcgen. */
        !          1850:                 wrong_line = TRUE;
        !          1851:             }
        !          1852:             if (keep_spaces)                /* Save the length      */
        !          1853:                 *sizp = *sizp + (sp - saved_sp);
        !          1854:             if ((mcpp_debug & MACRO_CALL) && compiling) {
        !          1855:                 if (cat_line) {
        !          1856:                     cat_line++;
        !          1857:                     com_cat_line.len[ cat_line]         /* Catenated length */
        !          1858:                             = com_cat_line.len[ cat_line - 1]
        !          1859:                                 + strlen( infile->buffer) - 1;
        !          1860:                                             /* '-1' for '\n'        */
        !          1861:                     com_cat_line.last_line = src_line;
        !          1862:                 }
        !          1863:             }
        !          1864:             return  sp;                     /* End of comment       */
        !          1865:         case '\n':                          /* Line-crossing comment*/
        !          1866:             if (keep_spaces)                /* Save the length      */
        !          1867:                 *sizp = *sizp + (sp - saved_sp) - 1;    /* '-1' for '\n'    */
        !          1868:             if ((mcpp_debug & MACRO_CALL) && compiling) {
        !          1869:                                     /* Save location informations   */
        !          1870:                 if (cat_line == 0)  /* First line of catenation     */
        !          1871:                     com_cat_line.start_line = src_line;
        !          1872:                 if (cat_line >= MAX_CAT_LINE - 1) {
        !          1873:                     *sizp = 0;      /* Discard the too long comment */
        !          1874:                     cat_line = 0;
        !          1875:                     if (warn_level & 4)
        !          1876:                         cwarn(
        !          1877:                         "Too long comment, discarded up to here"    /* _W4_ */
        !          1878:                                 , NULL, 0L, NULL);
        !          1879:                 }
        !          1880:                 cat_line++;
        !          1881:                 com_cat_line.len[ cat_line]
        !          1882:                         = com_cat_line.len[ cat_line - 1]
        !          1883:                             + strlen( infile->buffer) - 1;
        !          1884:             }
        !          1885:             if ((saved_sp = sp = get_line( TRUE)) == NULL)
        !          1886:                 return  NULL;       /* End of file within comment   */
        !          1887:                 /* Never happen, because at_eof() supplement closing*/
        !          1888:             wrong_line = TRUE;      /* We'll need a #line later     */
        !          1889:             break;
        !          1890:         default:                            /* Anything else is     */
        !          1891:             break;                          /*   just a character   */
        !          1892:         }                                   /* End switch           */
        !          1893:
        !          1894:         c = *sp++;
        !          1895:     }                                       /* End comment loop     */
        !          1896:
        !          1897:     return  sp;                             /* Never reach here     */
        !          1898: }
        !          1899:
        !          1900: static char *   mcpp_fgets(
        !          1901:     char *  s,
        !          1902:     int     size,
        !          1903:     FILE *  stream
        !          1904: )
        !          1905: {
        !          1906:     return fgets( s, size, stream);
        !          1907: }
        !          1908:
        !          1909: static char *   get_line(
        !          1910:     int     in_comment
        !          1911: )
        !          1912: /*
        !          1913:  * ANSI (ISO) C: translation phase 1, 2.
        !          1914:  * Get the next logical line from source file.
        !          1915:  * Convert [CR+LF] to [LF].
        !          1916:  */
        !          1917: {
        !          1918: #if COMPILER == INDEPENDENT
        !          1919: #define cr_warn_level 1
        !          1920: #else
        !          1921: #define cr_warn_level 2
        !          1922: #endif
        !          1923:     static int  cr_converted;
        !          1924:     int     converted = FALSE;
        !          1925:     int     len;                            /* Line length - alpha  */
        !          1926:     char *  ptr;
        !          1927:     int     cat_line = 0;           /* Number of catenated lines    */
        !          1928:
        !          1929:     if (infile == NULL)                     /* End of a source file */
        !          1930:         return  NULL;
        !          1931:     ptr = infile->bptr = infile->buffer;
        !          1932:     if ((mcpp_debug & MACRO_CALL) && src_line == 0) /* Initialize   */
        !          1933:         com_cat_line.last_line = bsl_cat_line.last_line = 0L;
        !          1934:
        !          1935:     while (mcpp_fgets( ptr, (int) (infile->buffer + NBUFF - ptr), infile->fp)
        !          1936:             != NULL) {
        !          1937:         /* Translation phase 1  */
        !          1938:         src_line++;                 /* Gotten next physical line    */
        !          1939:         if (standard && src_line == std_limits.line_num + 1
        !          1940:                 && (warn_level & 1))
        !          1941:             cwarn( "Line number %.0s\"%ld\" got beyond range"       /* _W1_ */
        !          1942:                     , NULL, src_line, NULL);
        !          1943:         if (mcpp_debug & (TOKEN | GETC)) {  /* Dump it to DBG       */
        !          1944:             mcpp_fprintf( DBG, "\n#line %ld (%s)", src_line, cur_fullname);
        !          1945:             dump_string( NULL, ptr);
        !          1946:         }
        !          1947:         len = strlen( ptr);
        !          1948:         if (NBUFF - 1 <= ptr - infile->buffer + len
        !          1949:                 && *(ptr + len - 1) != '\n') {
        !          1950:                 /* The line does not yet end, though the buffer is full.    */
        !          1951:             if (NBUFF - 1 <= len)
        !          1952:                 cfatal( "Too long source line"              /* _F_  */
        !          1953:                         , NULL, 0L, NULL);
        !          1954:             else
        !          1955:                 cfatal( "Too long logical line"             /* _F_  */
        !          1956:                         , NULL, 0L, NULL);
        !          1957:         }
        !          1958:         if (*(ptr + len - 1) != '\n')   /* Unterminated source line */
        !          1959:             break;
        !          1960:         if (len >= 2 && *(ptr + len - 2) == '\r') {         /* [CR+LF]      */
        !          1961:             *(ptr + len - 2) = '\n';
        !          1962:             *(ptr + --len) = EOS;
        !          1963:             if (! cr_converted && (warn_level & cr_warn_level)) {
        !          1964:                 cwarn( "Converted [CR+LF] to [LF]"  /* _W1_ _W2_    */
        !          1965:                         , NULL, 0L, NULL);
        !          1966:                 cr_converted = TRUE;
        !          1967:             }
        !          1968:         }
        !          1969:         if (standard) {
        !          1970:             if (option_flags.trig)
        !          1971:                 converted = cnv_trigraph( ptr);
        !          1972:             if (mcpp_mode == POST_STD && option_flags.dig)
        !          1973:                 converted += cnv_digraph( ptr);
        !          1974:             if (converted)
        !          1975:                 len = strlen( ptr);
        !          1976:             /* Translation phase 2  */
        !          1977:             len -= 2;
        !          1978:             if (len >= 0) {
        !          1979:                 if ((*(ptr + len) == '\\') && ! last_is_mbchar( ptr, len)) {
        !          1980:                             /* <backslash><newline> (not MBCHAR)    */
        !          1981:                     ptr = infile->bptr += len;  /* Splice the lines */
        !          1982:                     wrong_line = TRUE;
        !          1983:                     if ((mcpp_debug & MACRO_CALL) && compiling) {
        !          1984:                                     /* Save location informations   */
        !          1985:                         if (cat_line == 0)      /* First line of catenation */
        !          1986:                             bsl_cat_line.start_line = src_line;
        !          1987:                         if (cat_line < MAX_CAT_LINE)
        !          1988:                                     /* Record the catenated length  */
        !          1989:                             bsl_cat_line.len[ ++cat_line]
        !          1990:                                     = strlen( infile->buffer) - 2;
        !          1991:                         /* Else ignore  */
        !          1992:                     }
        !          1993:                     continue;
        !          1994:                 }
        !          1995:             }
        !          1996: #if NBUFF-2 > SLEN90MIN
        !          1997:             if (ptr - infile->buffer + len + 2 > std_limits.str_len + 1
        !          1998:                     && (warn_level & 4))    /* +1 for '\n'          */
        !          1999:             cwarn( "Logical source line longer than %.0s%ld bytes"  /* _W4_ */
        !          2000:                         , NULL, std_limits.str_len, NULL);
        !          2001: #endif
        !          2002:         }
        !          2003:         if ((mcpp_debug & MACRO_CALL) && compiling) {
        !          2004:             if (cat_line && cat_line < MAX_CAT_LINE) {
        !          2005:                 bsl_cat_line.len[ ++cat_line] = strlen( infile->buffer) - 1;
        !          2006:                                 /* Catenated length: '-1' for '\n'  */
        !          2007:                 bsl_cat_line.last_line = src_line;
        !          2008:             }
        !          2009:         }
        !          2010:         return  infile->bptr = infile->buffer;      /* Logical line */
        !          2011:     }
        !          2012:
        !          2013:     /* End of a (possibly included) source file */
        !          2014:     if (ferror( infile->fp))
        !          2015:         cfatal( "File read error", NULL, 0L, NULL);         /* _F_  */
        !          2016:     if ((ptr = at_eof( in_comment)) != NULL)        /* Check at end of file */
        !          2017:         return  ptr;                        /* Partial line supplemented    */
        !          2018:     if (option_flags.z) {
        !          2019:         no_output--;                        /* End of included file */
        !          2020:         keep_comments = option_flags.c && compiling && !no_output;
        !          2021:     }
        !          2022:     return  NULL;
        !          2023: }
        !          2024:
        !          2025: #define TRIOFFSET       10
        !          2026:
        !          2027: int     cnv_trigraph(
        !          2028:     char *      in
        !          2029: )
        !          2030: /*
        !          2031:  * Perform in-place trigraph replacement on a physical line.  This was added
        !          2032:  * to the C90.  In an input text line, the sequence ??[something] is
        !          2033:  * transformed to a character (which might not appear on the input keyboard).
        !          2034:  */
        !          2035: {
        !          2036:     const char * const  tritext = "=(/)'<!>-\0#[\\]^{|}~";
        !          2037:     /*                             ^          ^
        !          2038:      *                             +----------+
        !          2039:      *                             this becomes this
        !          2040:      */
        !          2041:     int     count = 0;
        !          2042:     const char *    tp;
        !          2043:
        !          2044:     while ((in = strchr( in, '?')) != NULL) {
        !          2045:         if (*++in != '?')
        !          2046:             continue;
        !          2047:         while (*++in == '?')
        !          2048:             ;
        !          2049:         if ((tp = strchr( tritext, *in)) == NULL)
        !          2050:             continue;
        !          2051:         *(in - 2) = *(tp + TRIOFFSET);
        !          2052:         in--;
        !          2053:         memmove( in, in + 2, strlen( in + 1));
        !          2054:         count++;
        !          2055:     }
        !          2056:
        !          2057:     if (count && (warn_level & 16))
        !          2058:         cwarn( "%.0s%ld trigraph(s) converted"          /* _W16_    */
        !          2059:                 , NULL, (long) count, NULL);
        !          2060:     return  count;
        !          2061: }
        !          2062:
        !          2063: int     cnv_digraph(
        !          2064:     char *      in
        !          2065: )
        !          2066: /*
        !          2067:  * Perform in-place digraph replacement on a physical line.
        !          2068:  * Called only in POST_STD mode.
        !          2069:  */
        !          2070: {
        !          2071:     int     count = 0;
        !          2072:     int     i;
        !          2073:     int     c1, c2;
        !          2074:
        !          2075:     while ((i = strcspn( in, "%:<")), (c1 = *(in + i)) != '\0') {
        !          2076:         in += i + 1;
        !          2077:         c2 = *in;
        !          2078:         switch (c1) {
        !          2079:         case '%'    :
        !          2080:             switch (c2) {
        !          2081:             case ':'    :   *(in - 1) = '#';    break;
        !          2082:             case '>'    :   *(in - 1) = '}';    break;
        !          2083:             default     :   continue;
        !          2084:             }
        !          2085:             break;
        !          2086:         case ':'    :
        !          2087:             switch (c2) {
        !          2088:             case '>'    :   *(in - 1) = ']';    break;
        !          2089:             default     :   continue;
        !          2090:             }
        !          2091:             break;
        !          2092:         case '<'    :
        !          2093:             switch (c2) {
        !          2094:             case '%'    :   *(in - 1) = '{';    break;
        !          2095:             case ':'    :   *(in - 1) = '[';    break;
        !          2096:             default     :   continue;
        !          2097:             }
        !          2098:             break;
        !          2099:         }
        !          2100:         memmove( in, in + 1, strlen( in));
        !          2101:         count++;
        !          2102:     }
        !          2103:
        !          2104:     if (count && (warn_level & 16))
        !          2105:         cwarn( "%.0s%ld digraph(s) converted"           /* _W16_    */
        !          2106:                 , NULL, (long) count, NULL);
        !          2107:     return  count;
        !          2108: }
        !          2109:
        !          2110: static char *   at_eof(
        !          2111:     int     in_comment
        !          2112: )
        !          2113: /*
        !          2114:  * Check the partial line, unterminated comment, unbalanced #if block,
        !          2115:  * uncompleted macro call at end of a file or at end of input.
        !          2116:  * Supplement the line terminator, if possible.
        !          2117:  * Return the supplemented line or NULL on unrecoverable error.
        !          2118:  */
        !          2119: {
        !          2120:     const char * const  format
        !          2121:             = "End of %s with %.0ld%s";                 /* _E_ _W1_ */
        !          2122:     const char * const  unterm_if_format
        !          2123: = "End of %s within #if (#ifdef) section started at line %ld";  /* _E_ _W1_ */
        !          2124:     const char * const  unterm_macro_format
        !          2125:             = "End of %s within macro call started at line %ld";/* _E_ _W1_ */
        !          2126:     const char * const  input
        !          2127:             = infile->parent ? "file" : "input";        /* _E_ _W1_ */
        !          2128:     const char * const  no_newline
        !          2129:             = "no newline, supplemented newline";       /* _W1_     */
        !          2130:     const char * const  unterm_com
        !          2131:             = "unterminated comment, terminated the comment";   /* _W1_     */
        !          2132:     const char * const  backsl = "\\, deleted the \\";  /* _W1_     */
        !          2133:     const char * const  unterm_asm_format
        !          2134: = "End of %s with unterminated #asm block started at line %ld"; /* _E_ _W1_ */
        !          2135:     size_t  len;
        !          2136:     char *  cp;
        !          2137:
        !          2138:     cp = infile->buffer;
        !          2139:     len = strlen( cp);
        !          2140:     if (len && *(cp += (len - 1)) != '\n') {
        !          2141:         *++cp = '\n';                       /* Supplement <newline> */
        !          2142:         *++cp = EOS;
        !          2143:         if (mcpp_mode != OLD_PREP && (warn_level & 1))
        !          2144:             cwarn( format, input, 0L, no_newline);
        !          2145:         return  infile->bptr = infile->buffer;
        !          2146:     }
        !          2147:     if (standard && infile->buffer < infile->bptr) {
        !          2148:                             /* No line after <backslash><newline>   */
        !          2149:         cp = infile->bptr;
        !          2150:         *cp++ = '\n';                       /* Delete the \\        */
        !          2151:         *cp = EOS;
        !          2152:         if (warn_level & 1)
        !          2153:             cwarn( format, input, 0L, backsl);
        !          2154:         return  infile->bptr = infile->buffer;
        !          2155:     }
        !          2156:     if (in_comment) {               /* End of file within a comment */
        !          2157:         if (mcpp_mode != OLD_PREP && (warn_level & 1))
        !          2158:             cwarn( format, input, 0L, unterm_com);
        !          2159:         /* The partial comment line has been already read by        */
        !          2160:         /* read_a_comment(), so supplement the  next line.          */
        !          2161:         strcpy( infile->buffer, "*/\n");
        !          2162:         return  infile->bptr = infile->buffer;
        !          2163:     }
        !          2164:
        !          2165:     if (infile->initif < ifptr) {
        !          2166:         IFINFO *    ifp = infile->initif + 1;
        !          2167:         if (standard) {
        !          2168:             cerror( unterm_if_format, input, ifp->ifline, NULL);
        !          2169:             ifptr = infile->initif;         /* Clear information of */
        !          2170:             compiling = ifptr->stat;        /*   erroneous grouping */
        !          2171:         } else if (mcpp_mode == KR && (warn_level & 1)) {
        !          2172:             cwarn( unterm_if_format, input, ifp->ifline, NULL);
        !          2173:         }
        !          2174:     }
        !          2175:
        !          2176:     if (macro_line != 0 && macro_line != MACRO_ERROR
        !          2177:             && ((mcpp_mode == STD && in_getarg) || ! standard)) {
        !          2178:         if (standard) {
        !          2179:             cerror( unterm_macro_format, input, macro_line, NULL);
        !          2180:             macro_line = MACRO_ERROR;
        !          2181:         } else if (warn_level & 1) {
        !          2182:             cwarn( unterm_macro_format, input, macro_line, NULL);
        !          2183:         }
        !          2184:     }
        !          2185:
        !          2186:     if (in_asm && mcpp_mode == KR && (warn_level & 1))
        !          2187:         cwarn( unterm_asm_format, input, in_asm, NULL);
        !          2188:
        !          2189:     return  NULL;
        !          2190: }
        !          2191:
        !          2192: void    unget_ch( void)
        !          2193: /*
        !          2194:  * Back the pointer to reread the last character.  Fatal error (code bug)
        !          2195:  * if we back too far.  unget_ch() may be called, without problems, at end of
        !          2196:  * file.  Only one character may be ungotten.  If you need to unget more,
        !          2197:  * call unget_string().
        !          2198:  */
        !          2199: {
        !          2200:     if (in_token) {
        !          2201:         infile->bptr--;
        !          2202:         return;
        !          2203:     }
        !          2204:
        !          2205:     if (infile != NULL) {
        !          2206:         if (mcpp_mode == POST_STD && infile->fp) {
        !          2207:             switch (insert_sep) {
        !          2208:             case INSERTED_SEP:  /* Have just read an inserted separator */
        !          2209:                 insert_sep = INSERT_SEP;
        !          2210:                 return;
        !          2211:             case INSERT_SEP:
        !          2212:                 cfatal( "Bug: unget_ch() just after scan_token()"   /* _F_  */
        !          2213:                         , NULL, 0L, NULL);
        !          2214:                 break;
        !          2215:             default:
        !          2216:                 break;
        !          2217:             }
        !          2218:         }
        !          2219:         --infile->bptr;
        !          2220:         if (infile->bptr < infile->buffer)      /* Shouldn't happen */
        !          2221:             cfatal( "Bug: Too much pushback", NULL, 0L, NULL);      /* _F_  */
        !          2222:     }
        !          2223:
        !          2224:     if (mcpp_debug & GETC)
        !          2225:         dump_unget( "after unget");
        !          2226: }
        !          2227:
        !          2228: FILEINFO *  unget_string(
        !          2229:     const char *    text,               /* Text to unget            */
        !          2230:     const char *    name                /* Name of the macro, if any*/
        !          2231: )
        !          2232: /*
        !          2233:  * Push a string back on the input stream.  This is done by treating
        !          2234:  * the text as if it were a macro or a file.
        !          2235:  */
        !          2236: {
        !          2237:     FILEINFO *      file;
        !          2238:     size_t          size;
        !          2239:
        !          2240:     if (text)
        !          2241:         size = strlen( text) + 1;
        !          2242:     else
        !          2243:         size = 1;
        !          2244:     file = get_file( name, NULL, NULL, size, FALSE);
        !          2245:     if (text)
        !          2246:         memcpy( file->buffer, text, size);
        !          2247:     else
        !          2248:         *file->buffer = EOS;
        !          2249:     return  file;
        !          2250: }
        !          2251:
        !          2252: char *  save_string(
        !          2253:     const char *      text
        !          2254: )
        !          2255: /*
        !          2256:  * Store a string into free memory.
        !          2257:  */
        !          2258: {
        !          2259:     char *      result;
        !          2260:     size_t      size;
        !          2261:
        !          2262:     size = strlen( text) + 1;
        !          2263:     result = xmalloc( size);
        !          2264:     memcpy( result, text, size);
        !          2265:     return  result;
        !          2266: }
        !          2267:
        !          2268: FILEINFO *  get_file(
        !          2269:     const char *    name,                   /* File or macro name   */
        !          2270:     const char *    src_dir,                /* Source file directory*/
        !          2271:     const char *    fullname,               /* Full path list       */
        !          2272:     size_t      bufsize,                    /* Line buffer size     */
        !          2273:     int         include_opt         /* Specified by -include opt (for GCC)  */
        !          2274: )
        !          2275: /*
        !          2276:  * Common FILEINFO buffer initialization for a new file or macro.
        !          2277:  */
        !          2278: {
        !          2279:     FILEINFO *  file;
        !          2280:
        !          2281:     file = (FILEINFO *) xmalloc( sizeof (FILEINFO));
        !          2282:     file->buffer = xmalloc( bufsize);
        !          2283:     file->bptr = file->buffer;              /* Initialize line ptr  */
        !          2284:     file->buffer[ 0] = EOS;                 /* Force first read     */
        !          2285:     file->line = 0L;                        /* (Not used just yet)  */
        !          2286:     file->fp = NULL;                        /* No file yet          */
        !          2287:     file->pos = 0L;                         /* No pos to remember   */
        !          2288:     file->parent = infile;                  /* Chain files together */
        !          2289:     file->initif = ifptr;                   /* Initial ifstack      */
        !          2290:     file->include_opt = include_opt;        /* Specified by -include*/
        !          2291:     file->dirp = NULL;                      /* No include dir yet   */
        !          2292:     file->real_fname = name;                /* Save file/macro name */
        !          2293:     file->full_fname = fullname;            /* Full path list       */
        !          2294:     if (name) {
        !          2295:         file->filename = xmalloc( strlen( name) + 1);
        !          2296:         strcpy( file->filename, name);      /* Copy for #line       */
        !          2297:     } else {
        !          2298:         file->filename = NULL;
        !          2299:     }
        !          2300:     if (src_dir) {
        !          2301:         file->src_dir = xmalloc( strlen( src_dir) + 1);
        !          2302:         strcpy( file->src_dir, src_dir);
        !          2303:     } else {
        !          2304:         file->src_dir = NULL;
        !          2305:     }
        !          2306: #if MCPP_LIB
        !          2307:     file->last_fputc = mcpp_lib_fputc;
        !          2308:     file->last_fputs = mcpp_lib_fputs;
        !          2309:     file->last_fprintf = mcpp_lib_fprintf;
        !          2310: #endif
        !          2311:     if (infile != NULL) {                   /* If #include file     */
        !          2312:         infile->line = src_line;            /* Save current line    */
        !          2313: #if MCPP_LIB
        !          2314:         infile->last_fputc = mcpp_fputc;
        !          2315:         infile->last_fputs = mcpp_fputs;
        !          2316:         infile->last_fprintf = mcpp_fprintf;
        !          2317: #endif
        !          2318:     }
        !          2319:     infile = file;                          /* New current file     */
        !          2320:
        !          2321:     return  file;                           /* All done.            */
        !          2322: }
        !          2323:
        !          2324: static const char * const   out_of_memory
        !          2325:     = "Out of memory (required size is %.0s0x%lx bytes)";   /* _F_  */
        !          2326:
        !          2327: char *
        !          2328: (xmalloc)(
        !          2329:     size_t      size
        !          2330: )
        !          2331: /*
        !          2332:  * Get a block of free memory.
        !          2333:  */
        !          2334: {
        !          2335:     char *      result;
        !          2336:
        !          2337:     if ((result = (char *) malloc( size)) == NULL) {
        !          2338:         if (mcpp_debug & MEMORY)
        !          2339:             print_heap();
        !          2340:        cfatal( out_of_memory, NULL, (long) size, NULL);
        !          2341:     }
        !          2342:     return  result;
        !          2343: }
        !          2344:
        !          2345: char *  (xrealloc)(
        !          2346:     char *      ptr,
        !          2347:     size_t      size
        !          2348: )
        !          2349: /*
        !          2350:  * Reallocate malloc()ed memory.
        !          2351:  */
        !          2352: {
        !          2353:     char *      result;
        !          2354:
        !          2355:     if ((result = (char *) realloc( ptr, size)) == NULL && size != 0) {
        !          2356:         /* 'size != 0' is necessary to cope with some               */
        !          2357:         /*   implementation of realloc( ptr, 0) which returns NULL. */
        !          2358:         if (mcpp_debug & MEMORY)
        !          2359:             print_heap();
        !          2360:         cfatal( out_of_memory, NULL, (long) size, NULL);
        !          2361:     }
        !          2362:     return  result;
        !          2363: }
        !          2364:
        !          2365: LINE_COL *  get_src_location(
        !          2366:     LINE_COL *  p_line_col          /* Line and column on phase 4   */
        !          2367: )
        !          2368: /*
        !          2369:  * Convert line-column datum of just after translation phase 3 into that of
        !          2370:  * phase 2, tracing back line splicing by a comment and <backslash><newline>.
        !          2371:  * Note: This conversion does not give correct datum on a line catenated by
        !          2372:  * both of <backslash><newline> and line-crossing-comment at the same time.
        !          2373:  *
        !          2374:  * com_cat_line and bsl_cat_line have data only on last catenated line.
        !          2375:  * com_cat_line.len[] and bsl_cat_line.len[] have the length of catenated
        !          2376:  * line, and len[ 0] is always 0, followed by len[ 1], len[ 2], ..., as
        !          2377:  * accumulated length of successively catenated lines.
        !          2378:  */
        !          2379: {
        !          2380:     long        line;
        !          2381:     size_t      col;
        !          2382:     size_t *    cols;
        !          2383:     CAT_LINE *  l_col_p;
        !          2384:     int         i;
        !          2385:
        !          2386:     line = p_line_col->line;
        !          2387:     col = p_line_col->col;
        !          2388:
        !          2389:     for (i = 0; i <= 1; i++) {
        !          2390:         l_col_p = i ? & bsl_cat_line : & com_cat_line;
        !          2391:         if (l_col_p->last_line != line)
        !          2392:             continue;
        !          2393:         /* Else just catenated line */
        !          2394:         cols = l_col_p->len + 1;
        !          2395:         while (*cols < col)
        !          2396:             cols++;
        !          2397:         if (col <= *cols) {
        !          2398:             cols--;
        !          2399:             col -= *cols;
        !          2400:         }
        !          2401:         line = l_col_p->start_line + (cols - l_col_p->len);
        !          2402:     }
        !          2403:
        !          2404:     p_line_col->line = line;
        !          2405:     p_line_col->col = col + 1;
        !          2406:                     /* col internally start at 0, output start at 1 */
        !          2407:
        !          2408:     return  p_line_col;
        !          2409: }
        !          2410:
        !          2411: static void put_line(
        !          2412:     char *  out,
        !          2413:     FILE *  fp
        !          2414: )
        !          2415: /*
        !          2416:  * Put out a logical source line.
        !          2417:  * This routine is called only in OLD_PREP mode.
        !          2418:  */
        !          2419: {
        !          2420:     int     c;
        !          2421:
        !          2422:     while ((c = *out++) != EOS) {
        !          2423:         if (c != COM_SEP)           /* Skip 0-length comment        */
        !          2424:             mcpp_fputc( c, FP2DEST( fp));
        !          2425:     }
        !          2426: }
        !          2427:
        !          2428: static void do_msg(
        !          2429:     const char *    severity,       /* "fatal", "error", "warning"  */
        !          2430:     const char *    format,         /* Format for the error message */
        !          2431:     const char *    arg1,           /* String arg. for the message  */
        !          2432:     long            arg2,           /* Integer argument             */
        !          2433:     const char *    arg3            /* Second string argument       */
        !          2434: )
        !          2435: /*
        !          2436:  * Print filenames, macro names, line numbers and error messages.
        !          2437:  * Also print macro definitions on macro expansion problems.
        !          2438:  */
        !          2439: {
        !          2440:     FILEINFO *  file;
        !          2441:     DEFBUF *    defp;
        !          2442:     int         i;
        !          2443:     size_t      slen;
        !          2444:     const char *    arg_s[ 2];
        !          2445:     char *      arg_t[ 2];
        !          2446:     char *      tp;
        !          2447:     const char *    sp;
        !          2448:     int         c;
        !          2449:     int         ind;
        !          2450:
        !          2451:     fflush( fp_out);                /* Synchronize output and diagnostics   */
        !          2452:     arg_s[ 0] = arg1;  arg_s[ 1] = arg3;
        !          2453:
        !          2454:     for (i = 0; i < 2; i++) {   /* Convert special characters to visible    */
        !          2455:         sp = arg_s[ i];
        !          2456:         if (sp != NULL)
        !          2457:             slen = strlen( sp) + 1;
        !          2458:         else
        !          2459:             slen = 1;
        !          2460:         tp = arg_t[ i] = (char *) malloc( slen);
        !          2461:             /* Don't use xmalloc() so as not to cause infinite recursion    */
        !          2462:         if (sp == NULL || *sp == EOS) {
        !          2463:             *tp = EOS;
        !          2464:             continue;
        !          2465:         }
        !          2466:
        !          2467:         while ((c = *sp++) != EOS) {
        !          2468:             switch (c) {
        !          2469:             case TOK_SEP:
        !          2470:                 if (mcpp_mode == OLD_PREP)      /* COM_SEP          */
        !          2471:                     break;              /* Skip magic characters    */
        !          2472:                 /* Else fall through    */
        !          2473:             case RT_END:
        !          2474:             case CAT:
        !          2475:             case ST_QUOTE:
        !          2476:             case DEF_MAGIC:
        !          2477:                 if (! standard)
        !          2478:                     *tp++ = ' ';
        !          2479:                 break;                  /* Skip the magic characters*/
        !          2480:             case IN_SRC:
        !          2481:                 if (! standard)
        !          2482:                     *tp++ = ' ';
        !          2483:                 if ((mcpp_debug & MACRO_CALL) && ! in_directive)
        !          2484:                     sp += 2;            /* Skip two more bytes      */
        !          2485:                 break;
        !          2486:             case MAC_INF:
        !          2487:                 if (mcpp_mode != STD) {
        !          2488:                     *tp++ = ' ';
        !          2489:                     /* Illegal control character, convert to a space*/
        !          2490:                 } else {
        !          2491:                     switch (*sp++) {    /* Skip the magic characters*/
        !          2492:                     case MAC_ARG_START  :
        !          2493:                         sp++;
        !          2494:                         /* Fall through */
        !          2495:                     case MAC_CALL_START :
        !          2496:                         sp += 2;
        !          2497:                         break;
        !          2498:                     case MAC_ARG_END    :
        !          2499:                         if (! option_flags.v)
        !          2500:                             break;
        !          2501:                         else
        !          2502:                             sp++;
        !          2503:                             /* Fall through */
        !          2504:                     case MAC_CALL_END   :
        !          2505:                         if (option_flags.v)
        !          2506:                             sp += 2;
        !          2507:                         break;
        !          2508:                     }
        !          2509:                 }
        !          2510:                 break;
        !          2511:             case '\n':
        !          2512:                 *tp++ = ' ';            /* Convert '\n' to a space  */
        !          2513:                 break;
        !          2514:             default:
        !          2515:                 *tp++ = c;
        !          2516:                 break;
        !          2517:             }
        !          2518:         }
        !          2519:
        !          2520:         if (*(sp - 2) == '\n')
        !          2521:             tp--;
        !          2522:         *tp = EOS;
        !          2523:     }
        !          2524:
        !          2525:     /* Print source location and diagnostic */
        !          2526:     file = infile;
        !          2527:     while (file != NULL && (file->fp == NULL || file->fp == (FILE *)-1))
        !          2528:         file = file->parent;                        /* Skip macro   */
        !          2529:     if (file != NULL) {
        !          2530:         file->line = src_line;
        !          2531:         mcpp_fprintf( ERR, "%s:%ld: %s: ", cur_fullname, src_line, severity);
        !          2532:     }
        !          2533:     mcpp_fprintf( ERR, format, arg_t[ 0], arg2, arg_t[ 1]);
        !          2534:     mcpp_fputc( '\n', ERR);
        !          2535:     if (option_flags.no_source_line)
        !          2536:         goto  free_arg;
        !          2537:
        !          2538:     /* Print source line, includers and expanding macros    */
        !          2539:     file = infile;
        !          2540:     if (file != NULL && file->fp != NULL) {
        !          2541:         if (mcpp_mode == OLD_PREP) {
        !          2542:             mcpp_fputs( "    ", ERR);
        !          2543:             put_line( file->buffer, fp_err);
        !          2544:         } else {
        !          2545:             mcpp_fprintf( ERR, "    %s", file->buffer);
        !          2546:                                             /* Current source line  */
        !          2547:         }
        !          2548:         file = file->parent;
        !          2549:     }
        !          2550:     while (file != NULL) {                  /* Print #includes, too */
        !          2551:         if (file->fp == NULL) {             /* Macro                */
        !          2552:             if (file->filename) {
        !          2553:                 defp = look_id( file->filename);
        !          2554:                 if ((defp->nargs > DEF_NOARGS_STANDARD)
        !          2555:                     && ! (file->parent && file->parent->filename
        !          2556:                         && str_eq( file->filename, file->parent->filename)))
        !          2557:                         /* If the name is not duplicate of parent   */
        !          2558:                     dump_a_def( "    macro", defp, FALSE, TRUE, fp_err);
        !          2559:             }
        !          2560:         } else {                            /* Source file          */
        !          2561:             if (file->buffer[ 0] == '\0')
        !          2562:                 strcpy( file->buffer, "\n");
        !          2563:             if (mcpp_mode != OLD_PREP) {
        !          2564:                 mcpp_fprintf( ERR, "    from %s: %ld:    %s",
        !          2565:                     file->line ? file->full_fname       /* Full-path-list   */
        !          2566:                         : "<stdin>",        /* Included by -include */
        !          2567:                     file->line,             /* Current line number  */
        !          2568:                     file->buffer);          /* The source line      */
        !          2569:             } else {
        !          2570:                 mcpp_fprintf( ERR, "    from %s: %ld:    ", file->full_fname
        !          2571:                         , file->line);
        !          2572:                 put_line( file->buffer, fp_err);
        !          2573:             }
        !          2574:         }
        !          2575:         file = file->parent;
        !          2576:     }
        !          2577:
        !          2578:     if (! macro_name)
        !          2579:         goto  free_arg;
        !          2580:     /* Additional information of macro definitions  */
        !          2581:     expanding_macro[ 0].name = macro_name;
        !          2582:     for (ind = 0; ind <= exp_mac_ind; ind++) {
        !          2583:         int         ind_done;
        !          2584:
        !          2585:         for (ind_done = 0; ind_done < ind; ind_done++)
        !          2586:             if (str_eq( expanding_macro[ ind].name
        !          2587:                     , expanding_macro[ ind_done].name))
        !          2588:                 break;                      /* Already reported     */
        !          2589:         if (ind_done < ind)
        !          2590:             continue;
        !          2591:         for (file = infile; file; file = file->parent)
        !          2592:             if (file->fp == NULL && file->filename
        !          2593:                     && str_eq( expanding_macro[ ind].name, file->filename))
        !          2594:                 break;                      /* Already reported     */
        !          2595:         if (file)
        !          2596:             continue;
        !          2597:         if ((defp = look_id( expanding_macro[ ind].name)) != NULL) {
        !          2598:             if (defp->nargs <= DEF_NOARGS_STANDARD)
        !          2599:                 continue;                   /* Standard predefined  */
        !          2600:             dump_a_def( "    macro", defp, FALSE, TRUE, fp_err);
        !          2601:             /* Macro already read over  */
        !          2602:         }
        !          2603:     }
        !          2604:
        !          2605: free_arg:
        !          2606:     for (i = 0; i < 2; i++)
        !          2607:         free( arg_t[ i]);
        !          2608: }
        !          2609:
        !          2610: void    cfatal(
        !          2611:     const char *    format,
        !          2612:     const char *    arg1,
        !          2613:     long    arg2,
        !          2614:     const char *    arg3
        !          2615: )
        !          2616: /*
        !          2617:  * A real disaster.
        !          2618:  */
        !          2619: {
        !          2620:     do_msg( "fatal error", format, arg1, arg2, arg3);
        !          2621:     longjmp( error_exit, -1);
        !          2622: }
        !          2623:
        !          2624: void    cerror(
        !          2625:     const char *    format,
        !          2626:     const char *    arg1,
        !          2627:     long    arg2,
        !          2628:     const char *    arg3
        !          2629: )
        !          2630: /*
        !          2631:  * Print a error message.
        !          2632:  */
        !          2633: {
        !          2634:     do_msg( "error", format, arg1, arg2, arg3);
        !          2635:     errors++;
        !          2636: }
        !          2637:
        !          2638: void    cwarn(
        !          2639:     const char *    format,
        !          2640:     const char *    arg1,
        !          2641:     long    arg2,
        !          2642:     const char *    arg3
        !          2643: )
        !          2644: /*
        !          2645:  * Maybe an error.
        !          2646:  */
        !          2647: {
        !          2648:     do_msg( "warning", format, arg1, arg2, arg3);
        !          2649: }
        !          2650:
        !          2651: void    dump_string(
        !          2652:     const char *    why,
        !          2653:     const char *    text
        !          2654: )
        !          2655: /*
        !          2656:  * Dump text readably.
        !          2657:  * Bug: macro argument number may be putout as a control character or any
        !          2658:  * other character, just after MAC_PARM has been read away.
        !          2659:  */
        !          2660: {
        !          2661:     const char *    cp;
        !          2662:     const char *    chr;
        !          2663:     int     c, c1, c2;
        !          2664:
        !          2665:     if (why != NULL)
        !          2666:         mcpp_fprintf( DBG, " (%s)", why);
        !          2667:     mcpp_fputs( " => ", DBG);
        !          2668:
        !          2669:     if (text == NULL) {
        !          2670:         mcpp_fputs( "NULL", DBG);
        !          2671:         return;
        !          2672:     }
        !          2673:
        !          2674:     for (cp = text; (c = *cp++ & UCHARMAX) != EOS; ) {
        !          2675:         chr = NULL;
        !          2676:
        !          2677:         switch (c) {
        !          2678:         case MAC_PARM:
        !          2679:             c = *cp++ & UCHARMAX;       /* Macro parameter number   */
        !          2680:             mcpp_fprintf( DBG, "<%d>", c);
        !          2681:             break;
        !          2682:         case MAC_INF:
        !          2683:             if (! (mcpp_mode == STD && (mcpp_debug & MACRO_CALL)))
        !          2684:                 goto  no_magic;
        !          2685:             /* Macro informations inserted by -K option */
        !          2686:             c2 = *cp++ & UCHARMAX;
        !          2687:             if (option_flags.v || c2 == MAC_CALL_START
        !          2688:                     || c2 == MAC_ARG_START) {
        !          2689:                 c = ((*cp++ & UCHARMAX) - 1) * UCHARMAX;
        !          2690:                 c += (*cp++ & UCHARMAX) - 1;
        !          2691:             }
        !          2692:             switch (c2) {
        !          2693:             case MAC_CALL_START:
        !          2694:                 mcpp_fprintf( DBG, "<MAC%d>", c);
        !          2695:                 break;
        !          2696:             case MAC_CALL_END:
        !          2697:                 if (option_flags.v)
        !          2698:                     mcpp_fprintf( DBG, "<MAC_END%d>", c);
        !          2699:                 else
        !          2700:                     chr = "<MAC_END>";
        !          2701:                 break;
        !          2702:             case MAC_ARG_START:
        !          2703:                 c1 = *cp++ & UCHARMAX;
        !          2704:                 mcpp_fprintf( DBG, "<MAC%d:ARG%d>", c, c1 - 1);
        !          2705:                 break;
        !          2706:             case MAC_ARG_END:
        !          2707:                 if (option_flags.v) {
        !          2708:                     c1 = *cp++ & UCHARMAX;
        !          2709:                     mcpp_fprintf( DBG, "<ARG_END%d-%d>", c, c1 - 1);
        !          2710:                 } else {
        !          2711:                     chr = "<ARG_END>";
        !          2712:                 }
        !          2713:                 break;
        !          2714:             }
        !          2715:             break;
        !          2716:         case DEF_MAGIC:
        !          2717:             if (standard) {
        !          2718:                 chr = "<MAGIC>";
        !          2719:                 break;
        !          2720:             }       /* Else fall through    */
        !          2721:         case CAT:
        !          2722:             if (standard) {
        !          2723:                 chr = "##";
        !          2724:                 break;
        !          2725:             }       /* Else fall through    */
        !          2726:         case ST_QUOTE:
        !          2727:             if (standard) {
        !          2728:                 chr = "#";
        !          2729:                 break;
        !          2730:             }       /* Else fall through    */
        !          2731:         case RT_END:
        !          2732:             if (standard) {
        !          2733:                 chr = "<RT_END>";
        !          2734:                 break;
        !          2735:             }       /* Else fall through    */
        !          2736:         case IN_SRC:
        !          2737:             if (standard) {
        !          2738:                 if ((mcpp_debug & MACRO_CALL) && ! in_directive) {
        !          2739:                     int     num;
        !          2740:                     num = ((*cp++ & UCHARMAX) - 1) * UCHARMAX;
        !          2741:                     num += (*cp++ & UCHARMAX) - 1;
        !          2742:                     mcpp_fprintf( DBG, "<SRC%d>", num);
        !          2743:                 } else {
        !          2744:                     chr = "<SRC>";
        !          2745:                 }
        !          2746:             } else {                        /* Control character    */
        !          2747:                 mcpp_fprintf( DBG, "<^%c>", c + '@');
        !          2748:             }
        !          2749:             break;
        !          2750:         case TOK_SEP:
        !          2751:             if (mcpp_mode == STD) {
        !          2752:                 chr = "<TSEP>";
        !          2753:                 break;
        !          2754:             } else if (mcpp_mode == OLD_PREP) {     /* COM_SEP      */
        !          2755:                 chr = "<CSEP>";
        !          2756:                 break;
        !          2757:             }       /* Else fall through    */
        !          2758:         default:
        !          2759: no_magic:
        !          2760:             if (c < ' ')
        !          2761:                 mcpp_fprintf( DBG, "<^%c>", c + '@');
        !          2762:             else
        !          2763:                 mcpp_fputc( c, DBG);
        !          2764:             break;
        !          2765:         }
        !          2766:
        !          2767:         if (chr)
        !          2768:             mcpp_fputs( chr, DBG);
        !          2769:     }
        !          2770:
        !          2771:     mcpp_fputc( '\n', DBG);
        !          2772: }
        !          2773:
        !          2774: void    dump_unget(
        !          2775:     const char *    why
        !          2776: )
        !          2777: /*
        !          2778:  * Dump all ungotten junk (pending macros and current input lines).
        !          2779:  */
        !          2780: {
        !          2781:     const FILEINFO *    file;
        !          2782:
        !          2783:     mcpp_fputs( "dump of pending input text", DBG);
        !          2784:     if (why != NULL) {
        !          2785:         mcpp_fputs( "-- ", DBG);
        !          2786:         mcpp_fputs( why, DBG);
        !          2787:     }
        !          2788:     mcpp_fputc( '\n', DBG);
        !          2789:
        !          2790:     for (file = infile; file != NULL; file = file->parent)
        !          2791:         dump_string( file->real_fname ? file->real_fname
        !          2792:                 : file->filename ? file->filename : "NULL", file->bptr);
        !          2793: }
        !          2794:
        !          2795: static void dump_token(
        !          2796:     int     token_type,
        !          2797:     const char *    cp                              /* Token        */
        !          2798: )
        !          2799: /*
        !          2800:  * Dump a token.
        !          2801:  */
        !          2802: {
        !          2803:     static const char * const   t_type[]
        !          2804:             = { "NAM", "NUM", "STR", "WSTR", "CHR", "WCHR", "OPE", "SPE"
        !          2805:             , "SEP", };
        !          2806:
        !          2807:     mcpp_fputs( "token", DBG);
        !          2808:     dump_string( t_type[ token_type - NAM], cp);
        !          2809: }
        !          2810:

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