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

Annotation of OpenXM_contrib2/windows/mcpp/directive.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:  *                          D I R E C T I V E . C
        !            33:  *              P r o c e s s   D i r e c t i v e  L i n e s
        !            34:  *
        !            35:  * The routines to handle directives other than #include and #pragma
        !            36:  * are placed here.
        !            37:  */
        !            38:
        !            39: #if PREPROCESSED
        !            40: #include    "mcpp.H"
        !            41: #else
        !            42: #include    "system.H"
        !            43: #include    "internal.H"
        !            44: #endif
        !            45:
        !            46: static int      do_if( int hash, const char * directive_name);
        !            47:                 /* #if, #elif, #ifdef, #ifndef      */
        !            48: static void     sync_linenum( void);
        !            49:                 /* Synchronize number of newlines   */
        !            50: static long     do_line( void);
        !            51:                 /* Process #line directive          */
        !            52: static int      get_parm( void);
        !            53:                 /* Get parameters of macro, its nargs, names, lengths       */
        !            54: static int      get_repl( const char * macroname);
        !            55:                 /* Get replacement text embedding parameter number  */
        !            56: static char *   is_formal( const char * name, int conv);
        !            57:                 /* If formal parameter, save the number     */
        !            58: static char *   def_stringization( char * repl_cur);
        !            59:                 /* Define stringization     */
        !            60: static char *   mgtoken_save( const char * macroname);
        !            61:                 /* Prefix DEF_MAGIC to macro name in repl-text      */
        !            62: static char *   str_parm_scan( char * string_end);
        !            63:                 /* Scan the parameter in quote      */
        !            64: static void     do_undef( void);
        !            65:                 /* Process #undef directive         */
        !            66: static void     dump_repl( const DEFBUF * dp, FILE * fp, int gcc2_va);
        !            67:                 /* Dump replacement text            */
        !            68:
        !            69: /*
        !            70:  * Generate (by hand-inspection) a set of unique values for each directive.
        !            71:  * MCPP won't compile if there are hash conflicts.
        !            72:  */
        !            73: #define L_if            ('i' ^ (EOS << 1))
        !            74: #define L_ifdef         ('i' ^ ('d' << 1))
        !            75: #define L_ifndef        ('i' ^ ('n' << 1))
        !            76: #define L_elif          ('e' ^ ('i' << 1))
        !            77: #define L_else          ('e' ^ ('s' << 1))
        !            78: #define L_endif         ('e' ^ ('d' << 1))
        !            79: #define L_define        ('d' ^ ('f' << 1))
        !            80: #define L_undef         ('u' ^ ('d' << 1))
        !            81: #define L_line          ('l' ^ ('n' << 1))
        !            82: #define L_include       ('i' ^ ('c' << 1))
        !            83: #if COMPILER == GNUC
        !            84: #define L_include_next  ('i' ^ ('c' << 1) ^ ('_' << 1))
        !            85: #endif
        !            86: #if SYSTEM == SYS_MAC
        !            87: #define L_import        ('i' ^ ('p' << 1))
        !            88: #endif
        !            89: #define L_error         ('e' ^ ('r' << 1))
        !            90: #define L_pragma        ('p' ^ ('a' << 1))
        !            91:
        !            92: static const char * const   not_ident
        !            93:             = "Not an identifier \"%s\"";               /* _E_      */
        !            94: static const char * const   no_arg = "No argument";     /* _E_      */
        !            95: static const char * const   excess
        !            96:             = "Excessive token sequence \"%s\"";        /* _E_ _W1_ */
        !            97:
        !            98: void    directive( void)
        !            99: /*
        !           100:  * Process #directive lines.  Each directive have their own subroutines.
        !           101:  */
        !           102: {
        !           103:     const char * const  many_nesting =
        !           104: "More than %.0s%ld nesting of #if (#ifdef) sections%s"; /* _F_ _W4_ _W8_    */
        !           105:     const char * const  not_in_section
        !           106:     = "Not in a #if (#ifdef) section in a source file"; /* _E_ _W1_ */
        !           107:     const char * const  illeg_dir
        !           108:             = "Illegal #directive \"%s%.0ld%s\"";       /* _E_ _W1_ _W8_    */
        !           109:     const char * const  in_skipped = " (in skipped block)"; /* _W8_ */
        !           110:     FILEINFO *  file;
        !           111:     int     token_type;
        !           112:     int     hash;
        !           113:     int     c;
        !           114:     char *  tp;
        !           115:
        !           116:     in_directive = TRUE;
        !           117:     if (keep_comments) {
        !           118:         mcpp_fputc( '\n', OUT);     /* Possibly flush out comments  */
        !           119:         newlines--;
        !           120:     }
        !           121:     c = skip_ws();
        !           122:     if (c == '\n')                              /* 'null' directive */
        !           123:         goto  ret;
        !           124:     token_type = scan_token( c, (workp = work_buf, &workp), work_end);
        !           125:     if (in_asm && (token_type != NAM
        !           126:             || (! str_eq( identifier, "asm")
        !           127:                 && ! str_eq( identifier, "endasm"))))
        !           128:         /* In #asm block, ignore #anything other than #asm or #endasm       */
        !           129:         goto  skip_line;
        !           130:     if (token_type != NAM) {
        !           131:         if (mcpp_mode == OLD_PREP && token_type == NUM) {   /* # 123 [fname]*/
        !           132:             strcpy( identifier, "line");
        !           133:         } else {
        !           134:             if (compiling) {
        !           135:                 if (option_flags.lang_asm) {
        !           136:                     if (warn_level & 1)
        !           137:                         cwarn( illeg_dir, work_buf, 0L, NULL);
        !           138:                 } else {
        !           139:                     cerror( illeg_dir, work_buf, 0L, NULL);
        !           140:                 }
        !           141:             } else if (warn_level & 8) {
        !           142:                 cwarn( illeg_dir, work_buf, 0L, in_skipped);
        !           143:             }
        !           144:             goto  skip_line;
        !           145:         }
        !           146:     }
        !           147:     hash = (identifier[ 1] == EOS) ? identifier[ 0]
        !           148:             : (identifier[ 0] ^ (identifier[ 2] << 1));
        !           149:     if (strlen( identifier) > 7)
        !           150:         hash ^= (identifier[ 7] << 1);
        !           151:
        !           152:     /* hash is set to a unique value corresponding to the directive.*/
        !           153:     switch (hash) {
        !           154:     case L_if:      tp = "if";      break;
        !           155:     case L_ifdef:   tp = "ifdef";   break;
        !           156:     case L_ifndef:  tp = "ifndef";  break;
        !           157:     case L_elif:    tp = "elif";    break;
        !           158:     case L_else:    tp = "else";    break;
        !           159:     case L_endif:   tp = "endif";   break;
        !           160:     case L_define:  tp = "define";  break;
        !           161:     case L_undef:   tp = "undef";   break;
        !           162:     case L_line:    tp = "line";    break;
        !           163:     case L_include: tp = "include"; break;
        !           164: #if COMPILER == GNUC
        !           165:     case L_include_next:    tp = "include_next";    break;
        !           166: #endif
        !           167: #if SYSTEM == SYS_MAC
        !           168:     case L_import:  tp = "import";  break;
        !           169: #endif
        !           170:     case L_error:   tp = "error";   break;
        !           171:     case L_pragma:  tp = "pragma";  break;
        !           172:     default:        tp = NULL;      break;
        !           173:     }
        !           174:
        !           175:     if (tp != NULL && ! str_eq( identifier, tp)) {  /* Hash conflict*/
        !           176:         hash = 0;                       /* Unknown directive, will  */
        !           177:         tp = NULL;                      /*   be handled by do_old() */
        !           178:     }
        !           179:
        !           180:     if (! compiling) {                      /* Not compiling now    */
        !           181:         switch (hash) {
        !           182:         case L_elif :
        !           183:             if (! standard) {
        !           184:                 if (warn_level & 8)
        !           185:                     do_old();               /* Unknown directive    */
        !           186:                 goto  skip_line;            /* Skip the line        */
        !           187:             }   /* Else fall through    */
        !           188:         case L_else :       /* Test the #if's nest, if 0, compile   */
        !           189:         case L_endif:                       /* Un-nest #if          */
        !           190:             break;
        !           191:         case L_if   :                       /* These can't turn     */
        !           192:         case L_ifdef:                       /*  compilation on, but */
        !           193:         case L_ifndef   :                   /*   we must nest #if's.*/
        !           194:             if (&ifstack[ BLK_NEST] < ++ifptr)
        !           195:                 goto  if_nest_err;
        !           196:             if (standard && (warn_level & 8)
        !           197:                     && &ifstack[ std_limits.blk_nest + 1] == ifptr)
        !           198:                 cwarn( many_nesting, NULL, (long) std_limits.blk_nest
        !           199:                         , in_skipped);
        !           200:             ifptr->stat = 0;                /* !WAS_COMPILING       */
        !           201:             ifptr->ifline = src_line;       /* Line at section start*/
        !           202:             goto  skip_line;
        !           203:         default :                           /* Other directives     */
        !           204:             if (tp == NULL && (warn_level & 8))
        !           205:                 do_old();                   /* Unknown directive ?  */
        !           206:             goto  skip_line;                /* Skip the line        */
        !           207:         }
        !           208:     }
        !           209:
        !           210:     macro_line = 0;                         /* Reset error flag     */
        !           211:     file = infile;                  /* Remember the current file    */
        !           212:
        !           213:     switch (hash) {
        !           214:
        !           215:     case L_if:
        !           216:     case L_ifdef:
        !           217:     case L_ifndef:
        !           218:         if (&ifstack[ BLK_NEST] < ++ifptr)
        !           219:             goto  if_nest_err;
        !           220:         if (standard && (warn_level & 4) &&
        !           221:                 &ifstack[ std_limits.blk_nest + 1] == ifptr)
        !           222:             cwarn( many_nesting, NULL , (long) std_limits.blk_nest, NULL);
        !           223:         ifptr->stat = WAS_COMPILING;
        !           224:         ifptr->ifline = src_line;
        !           225:         goto  ifdo;
        !           226:
        !           227:     case L_elif:
        !           228:         if (! standard) {
        !           229:             do_old();               /* Unrecognized directive       */
        !           230:             break;
        !           231:         }
        !           232:         if (ifptr == &ifstack[0])
        !           233:             goto  nest_err;
        !           234:         if (ifptr == infile->initif) {
        !           235:             goto  in_file_nest_err;
        !           236:         }
        !           237:         if (ifptr->stat & ELSE_SEEN)
        !           238:             goto  else_seen_err;
        !           239:         if ((ifptr->stat & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING) {
        !           240:             compiling = FALSE;              /* Done compiling stuff */
        !           241:             goto  skip_line;                /* Skip this group      */
        !           242:         }
        !           243:         hash = L_if;
        !           244: ifdo:
        !           245:         c = do_if( hash, tp);
        !           246:         if (mcpp_debug & IF) {
        !           247:             mcpp_fprintf( DBG
        !           248:                     , "#if (#elif, #ifdef, #ifndef) evaluate to %s.\n"
        !           249:                     , compiling ? "TRUE" : "FALSE");
        !           250:             mcpp_fprintf( DBG, "line %ld: %s", src_line, infile->buffer);
        !           251:         }
        !           252:         if (c == FALSE) {                   /* Error                */
        !           253:             compiling = FALSE;              /* Skip this group      */
        !           254:             goto  skip_line;    /* Prevent an extra error message   */
        !           255:         }
        !           256:         break;
        !           257:
        !           258:     case L_else:
        !           259:         if (ifptr == &ifstack[0])
        !           260:             goto  nest_err;
        !           261:         if (ifptr == infile->initif) {
        !           262:             if (standard)
        !           263:                 goto  in_file_nest_err;
        !           264:             else if (warn_level & 1)
        !           265:                 cwarn( not_in_section, NULL, 0L, NULL);
        !           266:         }
        !           267:         if (ifptr->stat & ELSE_SEEN)
        !           268:             goto  else_seen_err;
        !           269:         ifptr->stat |= ELSE_SEEN;
        !           270:         ifptr->elseline = src_line;
        !           271:         if (ifptr->stat & WAS_COMPILING) {
        !           272:             if (compiling || (ifptr->stat & TRUE_SEEN) != 0)
        !           273:                 compiling = FALSE;
        !           274:             else
        !           275:                 compiling = TRUE;
        !           276:         }
        !           277:         if ((mcpp_debug & MACRO_CALL) && (ifptr->stat & WAS_COMPILING)) {
        !           278:             sync_linenum();
        !           279:             mcpp_fprintf( OUT, "/*else %ld:%c*/\n", src_line
        !           280:                     , compiling ? 'T' : 'F');   /* Show that #else is seen  */
        !           281:         }
        !           282:         break;
        !           283:
        !           284:     case L_endif:
        !           285:         if (ifptr == &ifstack[0])
        !           286:             goto  nest_err;
        !           287:         if (ifptr <= infile->initif) {
        !           288:             if (standard)
        !           289:                 goto  in_file_nest_err;
        !           290:             else if (warn_level & 1)
        !           291:                 cwarn( not_in_section, NULL, 0L, NULL);
        !           292:         }
        !           293:         if (! compiling && (ifptr->stat & WAS_COMPILING))
        !           294:             wrong_line = TRUE;
        !           295:         compiling = (ifptr->stat & WAS_COMPILING);
        !           296:         if ((mcpp_debug & MACRO_CALL) && compiling) {
        !           297:             sync_linenum();
        !           298:             mcpp_fprintf( OUT, "/*endif %ld*/\n", src_line);
        !           299:             /* Show that #if block has ended    */
        !           300:         }
        !           301:         --ifptr;
        !           302:         break;
        !           303:
        !           304:     case L_define:
        !           305:         do_define( FALSE, 0);
        !           306:         break;
        !           307:
        !           308:     case L_undef:
        !           309:         do_undef();
        !           310:         break;
        !           311:
        !           312:     case L_line:
        !           313:         if ((c = do_line()) > 0) {
        !           314:             src_line = c;
        !           315:             sharp( NULL, 0);    /* Putout the new line number and file name */
        !           316:             infile->line = --src_line;  /* Next line number is 'src_line'   */
        !           317:             newlines = -1;
        !           318:         } else {            /* Error already diagnosed by do_line() */
        !           319:             skip_nl();
        !           320:         }
        !           321:         break;
        !           322:
        !           323:     case L_include:
        !           324:         in_include = TRUE;
        !           325:         if (do_include( FALSE) == TRUE && file != infile)
        !           326:             newlines = -1;  /* File has been included. Clear blank lines    */
        !           327:         in_include = FALSE;
        !           328:         break;
        !           329:
        !           330:     case L_error:
        !           331:         if (! standard) {
        !           332:             do_old();               /* Unrecognized directive       */
        !           333:             break;
        !           334:         }
        !           335:         cerror( infile->buffer, NULL, 0L, NULL);            /* _E_  */
        !           336:         break;
        !           337:
        !           338:     case L_pragma:
        !           339:         if (! standard) {
        !           340:             do_old();               /* Unrecognized directive       */
        !           341:             break;
        !           342:         }
        !           343:         do_pragma();
        !           344:         newlines = -1;              /* Do not putout excessive '\n' */
        !           345:         break;
        !           346:
        !           347:     default:                /* Non-Standard or unknown directives   */
        !           348:         do_old();
        !           349:         break;
        !           350:     }
        !           351:
        !           352:     switch (hash) {
        !           353:     case L_if       :
        !           354:     case L_elif     :
        !           355:     case L_define   :
        !           356:     case L_line     :
        !           357:         goto  skip_line;    /* To prevent duplicate error message   */
        !           358: #if COMPILER == GNUC
        !           359:     case L_include_next  :
        !           360:         if (file != infile)             /* File has been included   */
        !           361:             newlines = -1;
        !           362: #endif
        !           363: #if SYSTEM == SYS_MAC
        !           364:     case L_import   :
        !           365:         if (file != infile)             /* File has been included   */
        !           366:             newlines = -1;
        !           367: #endif
        !           368:     case L_error    :
        !           369:         if (standard)
        !           370:             goto  skip_line;
        !           371:         /* Else fall through    */
        !           372:     case L_include  :
        !           373:     case L_pragma   :
        !           374:         if (standard)
        !           375:             break;          /* Already read over the line           */
        !           376:         /* Else fall through    */
        !           377:     default :               /* L_else, L_endif, L_undef, etc.       */
        !           378:         if (mcpp_mode == OLD_PREP) {
        !           379:         /*
        !           380:          * Ignore the rest of the #directive line so you can write
        !           381:          *          #if     foo
        !           382:          *          #endif  foo
        !           383:          */
        !           384:             ;
        !           385:         } else if (skip_ws() != '\n') {
        !           386: #if COMPILER == GNUC
        !           387:             if (standard && hash != L_endif)
        !           388: #else
        !           389:             if (standard)
        !           390: #endif
        !           391:                 cerror( excess, infile->bptr-1, 0L, NULL);
        !           392:             else if (warn_level & 1)
        !           393:                 cwarn( excess, infile->bptr-1, 0L, NULL);
        !           394:         }
        !           395:         skip_nl();
        !           396:     }
        !           397:     goto  ret;
        !           398:
        !           399: in_file_nest_err:
        !           400:     cerror( not_in_section, NULL, 0L, NULL);
        !           401:     goto  skip_line;
        !           402: nest_err:
        !           403:     cerror( "Not in a #if (#ifdef) section", NULL, 0L, NULL);       /* _E_  */
        !           404:     goto  skip_line;
        !           405: else_seen_err:
        !           406:     cerror( "Already seen #else at line %.0s%ld"            /* _E_  */
        !           407:             , NULL, ifptr->elseline, NULL);
        !           408: skip_line:
        !           409:     skip_nl();                              /* Ignore rest of line  */
        !           410:     goto  ret;
        !           411:
        !           412: if_nest_err:
        !           413:     cfatal( many_nesting, NULL, (long) BLK_NEST, NULL);
        !           414:
        !           415: ret:
        !           416:     in_directive = FALSE;
        !           417:     keep_comments = option_flags.c && compiling && !no_output;
        !           418:     keep_spaces = option_flags.k && compiling;
        !           419:        /* keep_spaces is on for #define line even if no_output is TRUE  */
        !           420:     if (! wrong_line)
        !           421:         newlines++;
        !           422: }
        !           423:
        !           424: static int  do_if( int hash, const char * directive_name)
        !           425: /*
        !           426:  * Process an #if (#elif), #ifdef or #ifndef.  The latter two are straight-
        !           427:  * forward, while #if needs a subroutine to evaluate the expression.
        !           428:  * do_if() is called only if compiling is TRUE.  If false, compilation is
        !           429:  * always supressed, so we don't need to evaluate anything.  This supresses
        !           430:  * unnecessary warnings.
        !           431:  */
        !           432: {
        !           433:     int     c;
        !           434:     int     found;
        !           435:     DEFBUF *    defp;
        !           436:
        !           437:     if ((c = skip_ws()) == '\n') {
        !           438:         unget_ch();
        !           439:         cerror( no_arg, NULL, 0L, NULL);
        !           440:         return  FALSE;
        !           441:     }
        !           442:     if (mcpp_debug & MACRO_CALL) {
        !           443:         sync_linenum();
        !           444:         mcpp_fprintf( OUT, "/*%s %ld*/", directive_name, src_line);
        !           445:     }
        !           446:     if (hash == L_if) {                 /* #if or #elif             */
        !           447:         unget_ch();
        !           448:         found = (eval_if() != 0L);      /* Evaluate expression      */
        !           449:         if (mcpp_debug & MACRO_CALL)
        !           450:             in_if = FALSE;      /* 'in_if' is dynamically set in eval_lex() */
        !           451:         hash = L_ifdef;                 /* #if is now like #ifdef   */
        !           452:     } else {                            /* #ifdef or #ifndef        */
        !           453:         if (scan_token( c, (workp = work_buf, &workp), work_end) != NAM) {
        !           454:             cerror( not_ident, work_buf, 0L, NULL);
        !           455:             return  FALSE;      /* Next token is not an identifier  */
        !           456:         }
        !           457:         found = ((defp = look_id( identifier)) != NULL);    /* Look in table*/
        !           458:         if (mcpp_debug & MACRO_CALL) {
        !           459:             if (found)
        !           460:                 mcpp_fprintf( OUT, "/*%s*/", defp->name);
        !           461:         }
        !           462:     }
        !           463:     if (found == (hash == L_ifdef)) {
        !           464:         compiling = TRUE;
        !           465:         ifptr->stat |= TRUE_SEEN;
        !           466:     } else {
        !           467:         compiling = FALSE;
        !           468:     }
        !           469:     if (mcpp_debug & MACRO_CALL) {
        !           470:         mcpp_fprintf( OUT, "/*i %c*/\n", compiling ? 'T' : 'F');
        !           471:         /* Report wheather the directive is evaluated TRUE or FALSE */
        !           472:     }
        !           473:     return  TRUE;
        !           474: }
        !           475:
        !           476: static void sync_linenum( void)
        !           477: /*
        !           478:  * Put out newlines or #line line to synchronize line number with the
        !           479:  * annotations about #if, #elif, #ifdef, #ifndef, #else or #endif on -K option.
        !           480:  */
        !           481: {
        !           482:     if (wrong_line || newlines > 10) {
        !           483:         sharp( NULL, 0);
        !           484:     } else {
        !           485:         while (newlines-- > 0)
        !           486:             mcpp_fputc('\n', OUT);
        !           487:     }
        !           488:     newlines = -1;
        !           489: }
        !           490:
        !           491: static long do_line( void)
        !           492: /*
        !           493:  * Parse the line to update the line number and "filename" field for the next
        !           494:  * input line.
        !           495:  * Values returned are as follows:
        !           496:  *  -1:     syntax error or out-of-range error (diagnosed by do_line(),
        !           497:  *          eval_num()).
        !           498:  *  [1,32767]:  legal line number for C90, [1,2147483647] for C99.
        !           499:  * Line number [32768,2147483647] in C90 mode is only warned (not an error).
        !           500:  * do_line() always absorbs the line (except the <newline>).
        !           501:  */
        !           502: {
        !           503:     const char * const  not_digits
        !           504:         = "Line number \"%s\" isn't a decimal digits sequence"; /* _E_ _W1_ */
        !           505:     const char * const  out_of_range
        !           506:         = "Line number \"%s\" is out of range of [1,%ld]";      /* _E_ _W1_ */
        !           507:     int     token_type;
        !           508:     VAL_SIGN *      valp;
        !           509:     char *  save;
        !           510:     int     c;
        !           511:
        !           512:     if ((c = skip_ws()) == '\n') {
        !           513:         cerror( no_arg, NULL, 0L, NULL);
        !           514:         unget_ch();                         /* Push back <newline>  */
        !           515:         return  -1L;                /* Line number is not changed   */
        !           516:     }
        !           517:
        !           518:     if (standard) {
        !           519:         token_type = get_unexpandable( c, FALSE);
        !           520:         if (macro_line == MACRO_ERROR)      /* Unterminated macro   */
        !           521:             return  -1L;                    /*   already diagnosed. */
        !           522:         if (token_type == NO_TOKEN) /* Macro expanded to 0 token    */
        !           523:             goto  no_num;
        !           524:         if (token_type != NUM)
        !           525:             goto  illeg_num;
        !           526:     } else if (scan_token( c, (workp = work_buf, &workp), work_end) != NUM) {
        !           527:         goto  illeg_num;
        !           528:     }
        !           529:     for (workp = work_buf; *workp != EOS; workp++) {
        !           530:         if (! isdigit( *workp & UCHARMAX)) {
        !           531:             if (standard) {
        !           532:                 cerror( not_digits, work_buf, 0L, NULL);
        !           533:                 return  -1L;
        !           534:             } else if (warn_level & 1) {
        !           535:                 cwarn( not_digits, work_buf, 0L, NULL);
        !           536:             }
        !           537:         }
        !           538:     }
        !           539:     valp = eval_num( work_buf);             /* Evaluate number      */
        !           540:     if (valp->sign == VAL_ERROR) {  /* Error diagnosed by eval_num()*/
        !           541:         return  -1;
        !           542:     } else if (standard
        !           543:             && (std_limits.line_num < valp->val || valp->val <= 0L)) {
        !           544:         if (valp->val < LINE99LIMIT && valp->val > 0L) {
        !           545:             if (warn_level & 1)
        !           546:                 cwarn( out_of_range, work_buf, std_limits.line_num, NULL);
        !           547:         } else {
        !           548:             cerror( out_of_range, work_buf, std_limits.line_num, NULL);
        !           549:             return  -1L;
        !           550:         }
        !           551:     }
        !           552:
        !           553:     if (standard) {
        !           554:         token_type = get_unexpandable( skip_ws(), FALSE);
        !           555:         if (macro_line == MACRO_ERROR)
        !           556:             return  -1L;
        !           557:         if (token_type != STR) {
        !           558:             if (token_type == NO_TOKEN) {   /* Filename is absent   */
        !           559:                 return  (long) valp->val;
        !           560:             } else {    /* Expanded macro should be a quoted string */
        !           561:                 goto  not_fname;
        !           562:             }
        !           563:         }
        !           564:     } else {
        !           565:         if ((c = skip_ws()) == '\n') {
        !           566:             unget_ch();
        !           567:             return  (long) valp->val;
        !           568:         }
        !           569:         if (scan_token( c, (workp = work_buf, &workp), work_end) != STR)
        !           570:             goto  not_fname;
        !           571:     }
        !           572: #if COMPILER == GNUC
        !           573:     if (memcmp( workp - 3, "//", 2) == 0) { /* "/cur-dir//"         */
        !           574:         save = infile->filename;    /* Do not change the file name  */
        !           575:     } else
        !           576: #endif
        !           577:     {
        !           578:         *(workp - 1) = EOS;                 /* Ignore right '"'     */
        !           579:         save = save_string( &work_buf[ 1]); /* Ignore left '"'      */
        !           580:     }
        !           581:
        !           582:     if (standard) {
        !           583:         if (get_unexpandable( skip_ws(), FALSE) != NO_TOKEN) {
        !           584:             cerror( excess, work_buf, 0L, NULL);
        !           585:             free( save);
        !           586:             return  -1L;
        !           587:         }
        !           588:     } else if (mcpp_mode == OLD_PREP) {
        !           589:         skip_nl();
        !           590:         unget_ch();
        !           591:     } else if ((c = skip_ws()) == '\n') {
        !           592:         unget_ch();
        !           593:     } else {
        !           594:         if (warn_level & 1) {
        !           595:             scan_token( c, (workp = work_buf, &workp), work_end);
        !           596:             cwarn( excess, work_buf, 0, NULL);
        !           597:         }
        !           598:         skip_nl();
        !           599:         unget_ch();
        !           600:     }
        !           601:
        !           602:     if (infile->filename)
        !           603:         free( infile->filename);
        !           604:     infile->filename = save;                /* New file name        */
        !           605:             /* Note that this does not change infile->real_fname    */
        !           606:     return  (long) valp->val;               /* New line number      */
        !           607:
        !           608: no_num:
        !           609:     cerror( "No line number", NULL, 0L, NULL);              /* _E_  */
        !           610:     return  -1L;
        !           611: illeg_num:
        !           612:     cerror( "Not a line number \"%s\"", work_buf, 0L, NULL);        /* _E_  */
        !           613:     return  -1L;
        !           614: not_fname:
        !           615:     cerror( "Not a file name \"%s\"", work_buf, 0L, NULL);  /* _E_  */
        !           616:     return  -1L;
        !           617: }
        !           618:
        !           619: /*
        !           620:  *                  M a c r o  D e f i n i t i o n s
        !           621:  */
        !           622:
        !           623: /*
        !           624:  * look_id()    Looks for the name in the defined symbol table.  Returns a
        !           625:  *              pointer to the definition if found, or NULL if not present.
        !           626:  * install_macro()  Installs the definition.  Updates the symbol table.
        !           627:  * undefine()   Deletes the definition from the symbol table.
        !           628:  */
        !           629:
        !           630: /*
        !           631:  * Global work_buf[] are used to store #define parameter lists and
        !           632:  * parms[].name point to them.
        !           633:  * 'nargs' contains the actual number of parameters stored.
        !           634:  */
        !           635: typedef struct {
        !           636:     char *  name;                   /* -> Start of each parameter   */
        !           637:     size_t  len;                    /* Length of parameter name     */
        !           638: } PARM;
        !           639: static PARM     parms[ NMACPARS];
        !           640: static int      nargs;              /* Number of parameters         */
        !           641: static char *   token_p;            /* Pointer to the token scanned */
        !           642: static char *   repl_base;          /* Base of buffer for repl-text */
        !           643: static char *   repl_end;           /* End of buffer for repl-text  */
        !           644: static const char * const   no_ident = "No identifier";     /* _E_  */
        !           645: #if COMPILER == GNUC
        !           646: static int      gcc2_va_arg;        /* GCC2-spec variadic macro     */
        !           647: #endif
        !           648:
        !           649: DEFBUF *    do_define(
        !           650:     int     ignore_redef,       /* Do not redefine   */
        !           651:     int     predefine           /* Predefine compiler-specific name */
        !           652:     /*
        !           653:      * Note: The value of 'predefine' should be one of 0, DEF_NOARGS_PREDEF
        !           654:      *      or DEF_NOARGS_PREDEF_OLD, the other values cause errors.
        !           655:      */
        !           656: )
        !           657: /*
        !           658:  * Called from directive() when a #define is scanned or called from
        !           659:  *      do_options() when a -D option is scanned.  This module parses formal
        !           660:  *      parameters by get_parm() and the replacement text by get_repl().
        !           661:  *
        !           662:  * There is some special case code to distinguish
        !           663:  *      #define foo     bar     --  object-like macro
        !           664:  * from #define foo()   bar     --  function-like macro with no parameter
        !           665:  *
        !           666:  * Also, we make sure that
        !           667:  *      #define foo     foo
        !           668:  * expands to "foo" but doesn't put MCPP into an infinite loop.
        !           669:  *
        !           670:  * A warning is printed if you redefine a symbol with a non-identical
        !           671:  * text.  I.e,
        !           672:  *      #define foo     123
        !           673:  *      #define foo     123
        !           674:  * is ok, but
        !           675:  *      #define foo     123
        !           676:  *      #define foo     +123
        !           677:  * is not.
        !           678:  *
        !           679:  * The following subroutines are called from do_define():
        !           680:  * get_parm()   parsing and remembering parameter names.
        !           681:  * get_repl()   parsing and remembering replacement text.
        !           682:  *
        !           683:  * The following subroutines are called from get_repl():
        !           684:  * is_formal()  is called when an identifier is scanned.  It checks through
        !           685:  *              the array of formal parameters.  If a match is found, the
        !           686:  *              identifier is replaced by a control byte which will be used
        !           687:  *              to locate the parameter when the macro is expanded.
        !           688:  * def_stringization()  is called when '#' operator is scanned.  It surrounds
        !           689:  *              the token to stringize with magic-codes.
        !           690:  *
        !           691:  * modes other than STD ignore difference of parameter names in macro
        !           692:  * redefinition.
        !           693:  */
        !           694: {
        !           695:     const char * const  predef = "\"%s\" shouldn't be redefined";   /* _E_  */
        !           696:     char    repl_list[ NMACWORK + IDMAX];   /* Replacement text     */
        !           697:     char    macroname[ IDMAX + 1];  /* Name of the macro defining   */
        !           698:     DEFBUF *    defp;               /* -> Old definition            */
        !           699:     DEFBUF **   prevp;      /* -> Pointer to previous def in list   */
        !           700:     int     c;
        !           701:     int     redefined;                      /* TRUE if redefined    */
        !           702:     int     dnargs = 0;                     /* defp->nargs          */
        !           703:     int     cmp;                    /* Result of name comparison    */
        !           704:     size_t  def_start, def_end;     /* Column of macro definition   */
        !           705:
        !           706:     repl_base = repl_list;
        !           707:     repl_end = & repl_list[ NMACWORK];
        !           708:     c = skip_ws();
        !           709:     if ((mcpp_debug & MACRO_CALL) && src_line)      /* Start of definition  */
        !           710:         def_start = infile->bptr - infile->buffer - 1;
        !           711:     if (c == '\n') {
        !           712:         cerror( no_ident, NULL, 0L, NULL);
        !           713:         unget_ch();
        !           714:         return  NULL;
        !           715:     } else if (scan_token( c, (workp = work_buf, &workp), work_end) != NAM) {
        !           716:         cerror( not_ident, work_buf, 0L, NULL);
        !           717:         return  NULL;
        !           718:     } else {
        !           719:         prevp = look_prev( identifier, &cmp);
        !           720:                 /* Find place in the macro list to insert the definition    */
        !           721:         defp = *prevp;
        !           722:         if (standard) {
        !           723:             if (cmp || defp->push) {    /* Not known or 'pushed' macro      */
        !           724:                 if (str_eq( identifier, "defined")
        !           725:                         || ((stdc_val || cplus_val)
        !           726:                             &&  str_eq( identifier, "__VA_ARGS__"))) {
        !           727:                     cerror(
        !           728:             "\"%s\" shouldn't be defined", identifier, 0L, NULL);   /* _E_  */
        !           729:                     return  NULL;
        !           730:                 }
        !           731:                 redefined = FALSE;          /* Quite new definition */
        !           732:             } else {                        /* It's known:          */
        !           733:                 if (ignore_redef)
        !           734:                     return  defp;
        !           735:                 dnargs = (defp->nargs == DEF_NOARGS_STANDARD
        !           736:                             || defp->nargs == DEF_NOARGS_PREDEF
        !           737:                             || defp->nargs == DEF_NOARGS_PREDEF_OLD)
        !           738:                         ? DEF_NOARGS : defp->nargs;
        !           739:                 if (dnargs <= DEF_NOARGS_DYNAMIC    /* __FILE__ and such    */
        !           740:                         || dnargs == DEF_PRAGMA /* _Pragma() pseudo-macro   */
        !           741:                         ) {
        !           742:                     cerror( predef, identifier, 0L, NULL);
        !           743:                     return  NULL;
        !           744:                 } else {
        !           745:                     redefined = TRUE;       /* Remember this fact   */
        !           746:                 }
        !           747:             }
        !           748:         } else {
        !           749:             if (cmp) {
        !           750:                 redefined = FALSE;          /* Quite new definition */
        !           751:             } else {                        /* It's known:          */
        !           752:                 if (ignore_redef)
        !           753:                     return  defp;
        !           754:                 dnargs = (defp->nargs == DEF_NOARGS_STANDARD
        !           755:                             || defp->nargs == DEF_NOARGS_PREDEF
        !           756:                             || defp->nargs == DEF_NOARGS_PREDEF_OLD)
        !           757:                         ? DEF_NOARGS : defp->nargs;
        !           758:                 redefined = TRUE;
        !           759:             }
        !           760:         }
        !           761:     }
        !           762:     strcpy( macroname, identifier);         /* Remember the name    */
        !           763:
        !           764:     in_define = TRUE;                       /* Recognize '#', '##'  */
        !           765:     if (get_parm() == FALSE) {              /* Get parameter list   */
        !           766:         in_define = FALSE;
        !           767:         return  NULL;                       /* Syntax error         */
        !           768:     }
        !           769:     if (get_repl( macroname) == FALSE) {    /* Get replacement text */
        !           770:         in_define = FALSE;
        !           771:         return  NULL;                       /* Syntax error         */
        !           772:     }
        !           773:     if ((mcpp_debug & MACRO_CALL) && src_line) {
        !           774:                                     /* Remember location on source  */
        !           775:         char *  cp;
        !           776:         cp = infile->bptr - 1;              /* Before '\n'          */
        !           777:         while (char_type[ *cp & UCHARMAX] & HSP)
        !           778:             cp--;                           /* Trailing space       */
        !           779:         cp++;                       /* Just after the last token    */
        !           780:         def_end = cp - infile->buffer;      /* End of definition    */
        !           781:     }
        !           782:
        !           783:     in_define = FALSE;
        !           784:     if (redefined) {
        !           785:         if (dnargs != nargs || ! str_eq( defp->repl, repl_list)
        !           786:                 || (mcpp_mode == STD && ! str_eq( defp->parmnames, work_buf))
        !           787:                 ) {             /* Warn if differently redefined    */
        !           788:             if (warn_level & 1) {
        !           789:                 cwarn(
        !           790:             "The macro is redefined", NULL, 0L, NULL);      /* _W1_ */
        !           791:                 if (! option_flags.no_source_line)
        !           792:                     dump_a_def( "    previously macro", defp, FALSE, TRUE
        !           793:                             , fp_err);
        !           794:             }
        !           795:         } else {                        /* Identical redefinition   */
        !           796:             return  defp;
        !           797:         }
        !           798:     }                                   /* Else new or re-definition*/
        !           799:     defp = install_macro( macroname, nargs, work_buf, repl_list, prevp, cmp
        !           800:             , predefine);
        !           801:     if ((mcpp_debug & MACRO_CALL) && src_line) {
        !           802:                                     /* Get location on source file  */
        !           803:         LINE_COL    s_line_col, e_line_col;
        !           804:         s_line_col.line = src_line;
        !           805:         s_line_col.col = def_start;
        !           806:         get_src_location( & s_line_col);
        !           807:                             /* Convert to pre-line-splicing data    */
        !           808:         e_line_col.line = src_line;
        !           809:         e_line_col.col = def_end;
        !           810:         get_src_location( & e_line_col);
        !           811:         /* Putout the macro definition information embedded in comment  */
        !           812:         mcpp_fprintf( OUT, "/*m%s %ld:%d-%ld:%d*/\n", defp->name
        !           813:                 , s_line_col.line, s_line_col.col
        !           814:                 , e_line_col.line, e_line_col.col);
        !           815:         wrong_line = TRUE;                      /* Need #line later */
        !           816:     }
        !           817:     if (mcpp_mode == STD && cplus_val && id_operator( macroname)
        !           818:             && (warn_level & 1))
        !           819:         /* These are operators, not identifiers, in C++98   */
        !           820:         cwarn( "\"%s\" is defined as macro", macroname      /* _W1_ */
        !           821:                 , 0L, NULL);
        !           822:     return  defp;
        !           823: }
        !           824:
        !           825: static int  get_parm( void)
        !           826: /*
        !           827:  *   Get parameters i.e. numbers into nargs, name into work_buf[], name-length
        !           828:  * into parms[].len.  parms[].name point into work_buf.
        !           829:  *   Return TRUE if the parameters are legal, else return FALSE.
        !           830:  *   In STD mode preprocessor must remember the parameter names, only for
        !           831:  * checking the validity of macro redefinitions.  This is required by the
        !           832:  * Standard (what an overhead !).
        !           833:  */
        !           834: {
        !           835:     const char * const  many_parms
        !           836:             = "More than %.0s%ld parameters";       /* _E_ _W4_     */
        !           837:     const char * const  illeg_parm
        !           838:             = "Illegal parameter \"%s\"";           /* _E_          */
        !           839:     const char * const  misplaced_ellip
        !           840:             = "\"...\" isn't the last parameter";   /* _E_          */
        !           841:     int     token_type;
        !           842:     int     c;
        !           843:
        !           844:     parms[ 0].name = workp = work_buf;
        !           845:     work_buf[ 0] = EOS;
        !           846: #if COMPILER == GNUC
        !           847:     gcc2_va_arg = FALSE;
        !           848: #endif
        !           849:
        !           850:     /* POST_STD mode    */
        !           851:     insert_sep = NO_SEP;    /* Clear the inserted token separator   */
        !           852:     c = get_ch();
        !           853:
        !           854:     if (c == '(') {                         /* With arguments?      */
        !           855:         nargs = 0;                          /* Init parms counter   */
        !           856:         if (skip_ws() == ')')
        !           857:             return  TRUE;                   /* Macro with 0 parm    */
        !           858:         else
        !           859:             unget_ch();
        !           860:
        !           861:         do {                                /* Collect parameters   */
        !           862:             if (nargs >= NMACPARS) {
        !           863:                 cerror( many_parms, NULL, (long) NMACPARS, NULL);
        !           864:                 return  FALSE;
        !           865:             }
        !           866:             parms[ nargs].name = workp;     /* Save its start       */
        !           867:             if ((token_type = scan_token( c = skip_ws(), &workp, work_end))
        !           868:                     != NAM) {
        !           869:                 if (c == '\n') {
        !           870:                     break;
        !           871:                 } else if (c == ',' || c == ')') {
        !           872:                     cerror( "Empty parameter", NULL, 0L, NULL);     /* _E_  */
        !           873:                     return  FALSE;
        !           874:                 } else if (standard && (stdc_val || cplus_val)
        !           875:                         && token_type == OPE && openum == OP_ELL) {
        !           876:                     /*
        !           877:                      * Enable variable argument macro which is a feature of
        !           878:                      * C99.  We enable this even on C90 or C++ for GCC
        !           879:                      * compatibility.
        !           880:                      */
        !           881:                     if (skip_ws() != ')') {
        !           882:                         cerror( misplaced_ellip, NULL, 0L, NULL);
        !           883:                         return  FALSE;
        !           884:                     }
        !           885:                     parms[ nargs++].len = 3;
        !           886:                     nargs |= VA_ARGS;
        !           887:                     goto  ret;
        !           888:                 } else {
        !           889:                     cerror( illeg_parm, parms[ nargs].name, 0L, NULL);
        !           890:                     return  FALSE;          /* Bad parameter syntax */
        !           891:                 }
        !           892:             }
        !           893:             if (standard && (stdc_val || cplus_val)
        !           894:                     && str_eq( identifier, "__VA_ARGS__")) {
        !           895:                 cerror( illeg_parm, parms[ nargs].name, 0L, NULL);
        !           896:                 return  FALSE;
        !           897:                 /* __VA_ARGS__ should not be used as a parameter    */
        !           898:             }
        !           899:             if (is_formal( parms[ nargs].name, FALSE)) {
        !           900:                 cerror( "Duplicate parameter name \"%s\""   /* _E_  */
        !           901:                         , parms[ nargs].name, 0L, NULL);
        !           902:                 return  FALSE;
        !           903:             }
        !           904:             parms[ nargs].len = (size_t) (workp - parms[ nargs].name);
        !           905:                                             /* Save length of param */
        !           906:             *workp++ = ',';
        !           907:             nargs++;
        !           908:         } while ((c = skip_ws()) == ',');   /* Get another parameter*/
        !           909:
        !           910:         *--workp = EOS;                     /* Remove excessive ',' */
        !           911:         if (c != ')') {                     /* Must end at )        */
        !           912: #if COMPILER == GNUC
        !           913:             /* Handle GCC2 variadic params like par...  */
        !           914:             char *  tp = workp;
        !           915:             if (mcpp_mode == STD
        !           916:                     &&(token_type = scan_token( c, &workp, work_end)) == OPE
        !           917:                     && openum == OP_ELL) {
        !           918:                 if ((c = skip_ws()) != ')') {
        !           919:                     cerror( misplaced_ellip, NULL, 0L, NULL);
        !           920:                     return  FALSE;
        !           921:                 }
        !           922:                 *tp = EOS;                  /* Remove "..."         */
        !           923:                 nargs |= VA_ARGS;
        !           924:                 gcc2_va_arg = TRUE;
        !           925:                 goto  ret;
        !           926:             }
        !           927: #endif
        !           928:             unget_ch();                     /* Push back '\n'       */
        !           929:             cerror(
        !           930:         "Missing \",\" or \")\" in parameter list \"(%s\""  /* _E_  */
        !           931:                     , work_buf, 0L, NULL);
        !           932:             return  FALSE;
        !           933:         }
        !           934:     } else {
        !           935:         /*
        !           936:          * DEF_NOARGS is needed to distinguish between
        !           937:          * "#define foo" and "#define foo()".
        !           938:          */
        !           939:         nargs = DEF_NOARGS;                 /* Object-like macro    */
        !           940:         unget_ch();
        !           941:     }
        !           942: ret:
        !           943: #if NMACPARS > NMACPARS90MIN
        !           944:     if ((warn_level & 4) && (nargs & ~AVA_ARGS) > std_limits.n_mac_pars)
        !           945:         cwarn( many_parms, NULL , (long) std_limits.n_mac_pars, NULL);
        !           946: #endif
        !           947:     return  TRUE;
        !           948: }
        !           949:
        !           950: static int  get_repl(
        !           951:     const char * macroname
        !           952: )
        !           953: /*
        !           954:  *   Get replacement text i.e. names of formal parameters are converted to
        !           955:  * the magic numbers, and operators #, ## is converted to magic characters.
        !           956:  *   Return TRUE if replacement list is legal, else return FALSE.
        !           957:  *   Any token separator in the text is converted to a single space, no token
        !           958:  * sepatator is inserted by MCPP.  Those are required by the Standard for
        !           959:  * stringizing of an argument by # operator.
        !           960:  *   In POST_STD mode, inserts a space between any tokens in source (except a
        !           961:  * macro name and the next '(' in macro definition), hence presence or absence
        !           962:  * of token separator makes no difference.
        !           963:  */
        !           964: {
        !           965:     const char * const  mixed_ops
        !           966:     = "Macro with mixing of ## and # operators isn't portable";     /* _W4_ */
        !           967:     const char * const  multiple_cats
        !           968:     = "Macro with multiple ## operators isn't portable";    /* _W4_ */
        !           969:     char *  prev_token = NULL;              /* Preceding token      */
        !           970:     char *  prev_prev_token = NULL;         /* Pre-preceding token  */
        !           971:     int     multi_cats = FALSE;             /* Multiple ## operators*/
        !           972:     int     c;
        !           973:     int     token_type;                     /* Type of token        */
        !           974:     char *  temp;
        !           975:     char *  repl_cur = repl_base;   /* Pointer into repl-text buffer*/
        !           976:
        !           977:     *repl_cur = EOS;
        !           978:     token_p = NULL;
        !           979:     if (mcpp_mode == STD) {
        !           980:         c = get_ch();
        !           981:         unget_ch();
        !           982:         if (((char_type[ c] & SPA) == 0) && (nargs < 0) && (warn_level & 1))
        !           983:             cwarn( "No space between macro name \"%s\" and repl-text"/* _W1_ */
        !           984:                 , macroname, 0L, NULL);
        !           985:     }
        !           986:     c = skip_ws();                          /* Get to the body      */
        !           987:
        !           988:     while (c != '\n') {
        !           989:         if (standard) {
        !           990:             prev_prev_token = prev_token;
        !           991:             prev_token = token_p;
        !           992:         }
        !           993:         token_p = repl_cur;                 /* Remember the pointer */
        !           994:         token_type = scan_token( c, &repl_cur, repl_end);
        !           995:
        !           996:         switch (token_type) {
        !           997:         case OPE:                   /* Operator or punctuator       */
        !           998:             if (! standard)
        !           999:                 break;
        !          1000:             switch (openum) {
        !          1001:             case OP_CAT:                    /* ##                   */
        !          1002:                 if (prev_token == NULL) {
        !          1003:                     cerror( "No token before ##"            /* _E_  */
        !          1004:                             , NULL, 0L, NULL);
        !          1005:                     return  FALSE;
        !          1006:                 } else if (*prev_token == CAT) {
        !          1007:                     cerror( "## after ##", NULL, 0L, NULL); /* _E_  */
        !          1008:                     return  FALSE;
        !          1009:                 } else if (prev_prev_token && *prev_prev_token == CAT) {
        !          1010:                     multi_cats = TRUE;
        !          1011:                 } else if (prev_prev_token && *prev_prev_token == ST_QUOTE
        !          1012:                         && (warn_level & 4)) {      /* # parm ##    */
        !          1013:                     cwarn( mixed_ops, NULL, 0L, NULL);
        !          1014:                 }
        !          1015:                 repl_cur = token_p;
        !          1016:                 *repl_cur++ = CAT;          /* Convert to CAT       */
        !          1017:                 break;
        !          1018:             case OP_STR:                    /* #                    */
        !          1019:                 if (nargs < 0)              /* In object-like macro */
        !          1020:                     break;                  /* '#' is an usual char */
        !          1021:                 if (prev_token && *prev_token == CAT
        !          1022:                         && (warn_level & 4))        /* ## #         */
        !          1023:                     cwarn( mixed_ops, NULL, 0L, NULL);
        !          1024:                 repl_cur = token_p;         /* Overwrite on #       */
        !          1025:                 if ((temp = def_stringization( repl_cur)) == NULL) {
        !          1026:                     return  FALSE;          /* Error                */
        !          1027:                 } else {
        !          1028:                     repl_cur = temp;
        !          1029:                 }
        !          1030:                 break;
        !          1031:             default:                    /* Any operator as it is    */
        !          1032:                 break;
        !          1033:             }
        !          1034:             break;
        !          1035:         case NAM:
        !          1036:         /*
        !          1037:          * Replace this name if it's a parm.  Note that the macro name is a
        !          1038:          * possible replacement token.  We stuff DEF_MAGIC in front of the
        !          1039:          * token which is treated as a LETTER by the token scanner and eaten
        !          1040:          * by the macro expanding routine.  This prevents the macro expander
        !          1041:          * from looping if someone writes "#define foo foo".
        !          1042:          */
        !          1043:             temp = is_formal( identifier, TRUE);
        !          1044:             if (temp == NULL) {             /* Not a parameter name */
        !          1045:                 if (! standard)
        !          1046:                     break;
        !          1047:                 if ((stdc_val || cplus_val)
        !          1048:                             && str_eq( identifier, "__VA_ARGS__")) {
        !          1049: #if COMPILER == GNUC
        !          1050:                     if (gcc2_va_arg) {
        !          1051:         cerror( "\"%s\" cannot be used in GCC2-spec variadic macro" /* _E_  */
        !          1052:                             , identifier, 0L, NULL);
        !          1053:                         return  FALSE;
        !          1054:                     }
        !          1055: #endif
        !          1056:                     cerror( "\"%s\" without corresponding \"...\""  /* _E_  */
        !          1057:                             , identifier, 0L, NULL);
        !          1058:                     return  FALSE;
        !          1059:                 }
        !          1060:                 if ((temp = mgtoken_save( macroname)) != NULL)
        !          1061:                     repl_cur = temp;        /* Macro name           */
        !          1062:             } else {                        /* Parameter name       */
        !          1063:                 repl_cur = temp;
        !          1064: #if COMPILER == GNUC
        !          1065:                 if (mcpp_mode == STD && (nargs & VA_ARGS)
        !          1066:                         && *(repl_cur - 1) == (nargs & ~AVA_ARGS)) {
        !          1067:                     if (! str_eq( identifier, "__VA_ARGS__")
        !          1068:                             && (warn_level & 2))
        !          1069:                         cwarn(
        !          1070:                             "GCC2-spec variadic macro is defined"   /* _W2_ */
        !          1071:                                     , NULL, 0L, NULL);
        !          1072:                     if (prev_token && *prev_token == CAT
        !          1073:                             && prev_prev_token && *prev_prev_token == ',')
        !          1074:                         /* ", ## __VA_ARGS__" is sequence peculiar  */
        !          1075:                         /* to GCC3-spec variadic macro.             */
        !          1076:                         /* Or ", ## last_arg" is sequence peculiar  */
        !          1077:                         /* to GCC2-spec variadic macro.             */
        !          1078:                         nargs |= GVA_ARGS;
        !          1079:                         /* Mark as sequence peculiar to GCC         */
        !          1080:                         /* This will be warned at expansion time    */
        !          1081:                 }
        !          1082: #endif
        !          1083:             }
        !          1084:             break;
        !          1085:
        !          1086:         case STR:                           /* String in mac. body  */
        !          1087:         case CHR:                           /* Character constant   */
        !          1088:             if (mcpp_mode == OLD_PREP)
        !          1089:                 repl_cur = str_parm_scan( repl_cur);
        !          1090:             break;
        !          1091:         case SEP:
        !          1092:             if (mcpp_mode == OLD_PREP && c == COM_SEP)
        !          1093:                 repl_cur--;                 /* Skip comment now     */
        !          1094:             break;
        !          1095:         default:                            /* Any token as it is   */
        !          1096:             break;
        !          1097:         }
        !          1098:
        !          1099:         if ((c = get_ch()) == ' ' || c == '\t') {
        !          1100:             *repl_cur++ = ' ';              /* Space                */
        !          1101:             while ((c = get_ch()) == ' ' || c == '\t')
        !          1102:                 ;                   /* Skip excessive spaces        */
        !          1103:         }
        !          1104:     }
        !          1105:
        !          1106:     while (repl_base < repl_cur
        !          1107:             && (*(repl_cur - 1) == ' ' || *(repl_cur - 1) == '\t'))
        !          1108:         repl_cur--;                     /* Remove trailing spaces   */
        !          1109:     *repl_cur = EOS;                        /* Terminate work       */
        !          1110:
        !          1111:     unget_ch();                             /* For syntax check     */
        !          1112:     if (standard) {
        !          1113:         if (token_p && *token_p == CAT) {
        !          1114:             cerror( "No token after ##", NULL, 0L, NULL);   /* _E_  */
        !          1115:             return  FALSE;
        !          1116:         }
        !          1117:         if (multi_cats && (warn_level & 4))
        !          1118:             cwarn( multiple_cats, NULL, 0L, NULL);
        !          1119:         if ((nargs & VA_ARGS) && stdc_ver < 199901L && (warn_level & 2))
        !          1120:             /* Variable arg macro is the spec of C99, not C90 nor C++98     */
        !          1121:             cwarn( "Variable argument macro is defined",    /* _W2_ */
        !          1122:                     NULL, 0L, NULL);
        !          1123:     }
        !          1124:
        !          1125:     return  TRUE;
        !          1126: }
        !          1127:
        !          1128: static char *   is_formal(
        !          1129:     const char *    name,
        !          1130:     int         conv                    /* Convert to magic number? */
        !          1131: )
        !          1132: /*
        !          1133:  * If the identifier is a formal parameter, save the MAC_PARM and formal
        !          1134:  * offset, returning the advanced pointer into the replacement text.
        !          1135:  * Else, return NULL.
        !          1136:  */
        !          1137: {
        !          1138:     char *  repl_cur;
        !          1139:     const char *    va_arg = "__VA_ARGS__";
        !          1140:     PARM    parm;
        !          1141:     size_t  len;
        !          1142:     int     i;
        !          1143:
        !          1144:     len = strlen( name);
        !          1145:     for (i = 0; i < (nargs & ~AVA_ARGS); i++) {     /* For each parameter   */
        !          1146:         parm = parms[ i];
        !          1147:         if ((len == parm.len
        !          1148:                 /* Note: parms[].name are comma separated  */
        !          1149:                     && memcmp( name, parm.name, parm.len) == 0)
        !          1150:                 || (standard && (nargs & VA_ARGS)
        !          1151:                     && i == (nargs & ~AVA_ARGS) - 1 && conv
        !          1152:                     && str_eq( name, va_arg))) {    /* __VA_ARGS__  */
        !          1153:                                             /* If it's known        */
        !          1154: #if COMPILER == GNUC
        !          1155:             if (gcc2_va_arg && str_eq( name, va_arg))
        !          1156:                 return  NULL;               /* GCC2 variadic macro  */
        !          1157: #endif
        !          1158:             if (conv) {
        !          1159:                 repl_cur = token_p;         /* Overwrite on the name*/
        !          1160:                 *repl_cur++ = MAC_PARM;     /* Save the signal      */
        !          1161:                 *repl_cur++ = i + 1;        /* Save the parm number */
        !          1162:                 return  repl_cur;           /* Return "gotcha"      */
        !          1163:             } else {
        !          1164:                 return  parm.name;          /* Duplicate parm name  */
        !          1165:             }
        !          1166:         }
        !          1167:     }
        !          1168:
        !          1169:     return  NULL;                           /* Not a formal param   */
        !          1170: }
        !          1171:
        !          1172: static char *   def_stringization( char * repl_cur)
        !          1173: /*
        !          1174:  * Define token stringization.
        !          1175:  * We store a magic cookie (which becomes surrouding " on expansion) preceding
        !          1176:  * the parameter as an operand of # operator.
        !          1177:  * Return the current pointer into replacement text if the token following #
        !          1178:  * is a parameter name, else return NULL.
        !          1179:  */
        !          1180: {
        !          1181:     int     c;
        !          1182:     char *  temp;
        !          1183:
        !          1184:     *repl_cur++ = ST_QUOTE;                 /* Prefix               */
        !          1185:     if (char_type[ c = get_ch()] & HSP) {   /* There is a space     */
        !          1186:         *repl_cur++ = ' ';
        !          1187:         while (char_type[ c = get_ch()] & HSP)      /* Skip excessive spaces*/
        !          1188:             ;
        !          1189:     }
        !          1190:     token_p = repl_cur;                     /* Remember the pointer */
        !          1191:     if (scan_token( c, &repl_cur, repl_end) == NAM) {
        !          1192:         if ((temp = is_formal( identifier, TRUE)) != NULL) {
        !          1193:             repl_cur = temp;
        !          1194:             return  repl_cur;
        !          1195:         }
        !          1196:     }
        !          1197:     cerror( "Not a formal parameter \"%s\"", token_p, 0L, NULL);    /* _E_  */
        !          1198:     return  NULL;
        !          1199: }
        !          1200:
        !          1201: static char *   mgtoken_save( const char * macroname)
        !          1202: /*
        !          1203:  * A magic cookie is inserted if the token is identical to the macro name,
        !          1204:  * so the expansion doesn't recurse.
        !          1205:  * Return the advanced pointer into the replacement text or NULL.
        !          1206:  */
        !          1207: {
        !          1208:     char *   repl_cur;
        !          1209:
        !          1210:     if (str_eq( macroname, identifier)) {   /* Macro name in body   */
        !          1211:         repl_cur = token_p;                 /* Overwrite on token   */
        !          1212:         *repl_cur++ = DEF_MAGIC;            /* Save magic marker    */
        !          1213:         repl_cur = stpcpy( repl_cur, identifier);
        !          1214:                                             /* And save the token   */
        !          1215:         return  repl_cur;
        !          1216:     } else {
        !          1217:         return  NULL;
        !          1218:     }
        !          1219: }
        !          1220:
        !          1221: static char *   str_parm_scan( char * string_end)
        !          1222: /*
        !          1223:  * String parameter scan.
        !          1224:  * This code -- if enabled -- recognizes a formal parameter in a string
        !          1225:  * literal or in a character constant.
        !          1226:  *      #define foo(bar, v) printf("%bar\n", v)
        !          1227:  *      foo( d, i)
        !          1228:  * expands to:
        !          1229:  *      printf("%d\n", i)
        !          1230:  * str_parm_scan() return the advanced pointer into the replacement text.
        !          1231:  * This has been superceded by # stringizing and string concatenation.
        !          1232:  * This routine is called only in OLD_PREP mode.
        !          1233:  */
        !          1234: {
        !          1235:     int     delim;
        !          1236:     int     c;
        !          1237:     char *  tp;
        !          1238:     char *  wp;             /* Pointer into the quoted literal  */
        !          1239:
        !          1240:     delim = *token_p;
        !          1241:     unget_string( ++token_p, NULL);
        !          1242:     /* Pseudo-token-parsing in a string literal */
        !          1243:     wp = token_p;
        !          1244:     while ((c = get_ch()) != delim) {
        !          1245:         token_p = wp;
        !          1246:         if (scan_token( c, &wp, string_end) != NAM)
        !          1247:             continue;
        !          1248:         if ((tp = is_formal( token_p, TRUE)) != NULL)
        !          1249:             wp = tp;
        !          1250:     }
        !          1251:     *wp++ = delim;
        !          1252:     return  wp;
        !          1253: }
        !          1254:
        !          1255: static void do_undef( void)
        !          1256: /*
        !          1257:  * Remove the symbol from the defined list.
        !          1258:  * Called from directive().
        !          1259:  */
        !          1260: {
        !          1261:     DEFBUF *    defp;
        !          1262:     int     c;
        !          1263:
        !          1264:     if ((c = skip_ws()) == '\n') {
        !          1265:         cerror( no_ident, NULL, 0L, NULL);
        !          1266:         unget_ch();
        !          1267:         return;
        !          1268:     }
        !          1269:     if (scan_token( c, (workp = work_buf, &workp), work_end) != NAM) {
        !          1270:         cerror( not_ident, work_buf, 0L, NULL);
        !          1271:         skip_nl();
        !          1272:         unget_ch();
        !          1273:     } else {
        !          1274:         if ((defp = look_id( identifier)) == NULL) {
        !          1275:             if (warn_level & 8)
        !          1276:                 cwarn( "\"%s\" wasn't defined"              /* _W8_ */
        !          1277:                         , identifier, 0L, NULL);
        !          1278:         } else if (standard && (defp->nargs <= DEF_NOARGS_STANDARD
        !          1279:                                                 /* Standard predef  */
        !          1280:                     || defp->nargs == DEF_PRAGMA)) {
        !          1281:                                         /* _Pragma() pseudo-macro   */
        !          1282:             cerror( "\"%s\" shouldn't be undefined"         /* _E_  */
        !          1283:                     , identifier, 0L, NULL);
        !          1284:         } else if (standard) {
        !          1285:             c = skip_ws();
        !          1286:             unget_ch();
        !          1287:             if (c != '\n')                      /* Trailing junk    */
        !          1288:                 return;
        !          1289:             else
        !          1290:                 undefine( identifier);
        !          1291:         } else {
        !          1292:             undefine( identifier);
        !          1293:         }
        !          1294:     }
        !          1295: }
        !          1296:
        !          1297: /*
        !          1298:  *                  C P P   S y m b o l   T a b l e s
        !          1299:  *
        !          1300:  * SBSIZE defines the number of hash-table slots for the symbol table.
        !          1301:  * It must be a power of 2.
        !          1302:  */
        !          1303:
        !          1304: /* Symbol table queue headers.  */
        !          1305: static DEFBUF *     symtab[ SBSIZE];
        !          1306: static long         num_of_macro = 0;
        !          1307:
        !          1308: #if MCPP_LIB
        !          1309: void    init_directive( void)
        !          1310: /* Initialize static variables. */
        !          1311: {
        !          1312:     num_of_macro = 0;
        !          1313: }
        !          1314: #endif
        !          1315:
        !          1316: DEFBUF *    look_id( const char * name)
        !          1317: /*
        !          1318:  * Look for the identifier in the symbol table.
        !          1319:  * If found, return the table pointer;  Else return NULL.
        !          1320:  */
        !          1321: {
        !          1322:     DEFBUF **   prevp;
        !          1323:     int         cmp;
        !          1324:
        !          1325:     prevp = look_prev( name, &cmp);
        !          1326:
        !          1327:     if (standard)
        !          1328:         return ((cmp == 0 && (*prevp)->push == 0) ? *prevp : NULL);
        !          1329:     else
        !          1330:         return ((cmp == 0) ? *prevp : NULL);
        !          1331: }
        !          1332:
        !          1333: DEFBUF **   look_prev(
        !          1334:     const char *    name,                   /* Name of the macro    */
        !          1335:     int *   cmp                             /* Result of comparison */
        !          1336: )
        !          1337: /*
        !          1338:  * Look for the place to insert the macro definition.
        !          1339:  * Return a pointer to the previous member in the linked list.
        !          1340:  */
        !          1341: {
        !          1342:     const char *    np;
        !          1343:     DEFBUF **   prevp;
        !          1344:     DEFBUF *    dp;
        !          1345:     size_t      s_name;
        !          1346:     int         hash;
        !          1347:
        !          1348:     for (hash = 0, np = name; *np != EOS; )
        !          1349:         hash += *np++;
        !          1350:     hash += s_name = (size_t)(np - name);
        !          1351:     s_name++;
        !          1352:     prevp = & symtab[ hash & SBMASK];
        !          1353:     *cmp = -1;                              /* Initialize           */
        !          1354:
        !          1355:     while ((dp = *prevp) != NULL) {
        !          1356:         if ((*cmp = memcmp( dp->name, name, s_name)) >= 0)
        !          1357:             break;
        !          1358:         prevp = &dp->link;
        !          1359:     }
        !          1360:
        !          1361:     return  prevp;
        !          1362: }
        !          1363:
        !          1364: DEFBUF *    look_and_install(
        !          1365:     const char *    name,                   /* Name of the macro    */
        !          1366:     int     numargs,                        /* The numbers of parms */
        !          1367:     const char *    parmnames,  /* Names of parameters concatenated */
        !          1368:     const char *    repl                    /* Replacement text     */
        !          1369: )
        !          1370: /*
        !          1371:  * Look for the name and (re)define it.
        !          1372:  * Returns a pointer to the definition block.
        !          1373:  * Returns NULL if the symbol was Standard-predefined.
        !          1374:  */
        !          1375: {
        !          1376:     DEFBUF **   prevp;          /* Place to insert definition       */
        !          1377:     DEFBUF *    defp;                       /* New definition block */
        !          1378:     int         cmp;    /* Result of comparison of new name and old */
        !          1379:
        !          1380:     prevp = look_prev( name, &cmp);
        !          1381:     defp = install_macro( name, numargs, parmnames, repl, prevp, cmp, 0);
        !          1382:     return  defp;
        !          1383: }
        !          1384:
        !          1385: DEFBUF *    install_macro(
        !          1386:     const char *    name,                   /* Name of the macro    */
        !          1387:     int     numargs,                        /* The numbers of parms */
        !          1388:     const char *    parmnames,  /* Names of parameters concatenated */
        !          1389:     const char *    repl,                   /* Replacement text     */
        !          1390:     DEFBUF **  prevp,           /* The place to insert definition   */
        !          1391:     int     cmp,        /* Result of comparison of new name and old */
        !          1392:     int     predefine   /* Predefined macro without leading '_'     */
        !          1393: )
        !          1394: /*
        !          1395:  * Enter this name in the lookup table.
        !          1396:  * Returns a pointer to the definition block.
        !          1397:  * Returns NULL if the symbol was Standard-predefined.
        !          1398:  * Note that predefinedness can be specified by either of 'numargs' or
        !          1399:  * 'predefine'.
        !          1400:  */
        !          1401: {
        !          1402:     DEFBUF *    dp;
        !          1403:     DEFBUF *    defp;
        !          1404:     size_t      s_name, s_parmnames, s_repl;
        !          1405:
        !          1406:     defp = *prevp;                  /* Old definition, if cmp == 0  */
        !          1407:     if (cmp == 0 && defp->nargs < DEF_NOARGS - 1)
        !          1408:         return  NULL;                       /* Standard predefined  */
        !          1409:     if (parmnames == NULL || repl == NULL || (predefine && numargs > 0)
        !          1410:             || (predefine && predefine != DEF_NOARGS_PREDEF
        !          1411:                     && predefine != DEF_NOARGS_PREDEF_OLD))
        !          1412:                                                 /* Shouldn't happen */
        !          1413:         cfatal( "Bug: Illegal macro installation of \"%s\"" /* _F_  */
        !          1414:                 , name, 0L, NULL);      /* Use "" instead of NULL   */
        !          1415:     s_name = strlen( name);
        !          1416:     if (mcpp_mode == STD)
        !          1417:         s_parmnames = strlen( parmnames) + 1;
        !          1418:     else
        !          1419:         s_parmnames = 0;
        !          1420:     s_repl = strlen( repl) + 1;
        !          1421:     dp = (DEFBUF *)
        !          1422:         xmalloc( sizeof (DEFBUF) + s_name + s_parmnames + s_repl);
        !          1423:     if (cmp || (standard && (*prevp)->push)) {  /* New definition   */
        !          1424:         dp->link = defp;                /* Insert to linked list    */
        !          1425:         *prevp = dp;
        !          1426:     } else {                            /* Redefinition             */
        !          1427:         dp->link = defp->link;          /* Replace old def with new */
        !          1428:         *prevp = dp;
        !          1429:         free( defp);
        !          1430:     }
        !          1431:     dp->nargs = predefine ? predefine : numargs;
        !          1432:     if (standard) {
        !          1433:         dp->push = 0;
        !          1434:         dp->parmnames = (char *)dp + sizeof (DEFBUF) + s_name;
        !          1435:         dp->repl = dp->parmnames + s_parmnames;
        !          1436:         if (mcpp_mode == STD)
        !          1437:             memcpy( dp->parmnames, parmnames, s_parmnames);
        !          1438:     } else {
        !          1439:         dp->repl = (char *)dp + sizeof (DEFBUF) + s_name;
        !          1440:     }
        !          1441:     memcpy( dp->name, name, s_name + 1);
        !          1442:     memcpy( dp->repl, repl, s_repl);
        !          1443:     /* Remember where the macro is defined  */
        !          1444:     dp->fname = cur_fullname;   /* Full-path-list of current file   */
        !          1445:     dp->mline = src_line;
        !          1446:     if (standard && cmp && ++num_of_macro == std_limits.n_macro + 1
        !          1447:             && std_limits.n_macro && (warn_level & 4))
        !          1448:         /* '&& std_limits.n_macro' to avoid warning before initialization   */
        !          1449:         cwarn( "More than %.0s%ld macros defined"           /* _W4_ */
        !          1450:                 , NULL , std_limits.n_macro, NULL);
        !          1451:     return  dp;
        !          1452: }
        !          1453:
        !          1454: int undefine(
        !          1455:     const char *  name                      /* Name of the macro    */
        !          1456: )
        !          1457: /*
        !          1458:  * Delete the macro definition from the symbol table.
        !          1459:  * Returns TRUE, if deleted;
        !          1460:  * Else returns FALSE (when the macro was not defined or was Standard
        !          1461:  * predefined).
        !          1462:  */
        !          1463: {
        !          1464:     DEFBUF **   prevp;          /* Preceding definition in list     */
        !          1465:     DEFBUF *    dp;                     /* Definition to delete     */
        !          1466:     int         cmp;            /* 0 if defined, else not defined   */
        !          1467:
        !          1468:     prevp = look_prev( name, &cmp);
        !          1469:     dp = *prevp;                        /* Definition to delete     */
        !          1470:     if (cmp || dp->nargs <= DEF_NOARGS_STANDARD)
        !          1471:         return  FALSE;      /* Not defined or Standard predefined   */
        !          1472:     if (standard && dp->push)
        !          1473:         return  FALSE;                  /* 'Pushed' macro           */
        !          1474:     *prevp = dp->link;          /* Link the previous and the next   */
        !          1475:     if ((mcpp_debug & MACRO_CALL) && dp->mline) {
        !          1476:         /* Notice this directive unless the macro is predefined     */
        !          1477:         mcpp_fprintf( OUT, "/*undef %ld*//*%s*/\n", src_line, dp->name);
        !          1478:         wrong_line = TRUE;
        !          1479:     }
        !          1480:     free( dp);                          /* Delete the definition    */
        !          1481:     if (standard)
        !          1482:         num_of_macro--;
        !          1483:     return  TRUE;
        !          1484: }
        !          1485:
        !          1486: static void dump_repl(
        !          1487:     const DEFBUF *  dp,
        !          1488:     FILE *  fp,
        !          1489:     int     gcc2_va
        !          1490: )
        !          1491: /*
        !          1492:  * Dump replacement text.
        !          1493:  */
        !          1494: {
        !          1495:     int     numargs = dp->nargs;
        !          1496:     char *  cp1;
        !          1497:     size_t  i;
        !          1498:     int     c;
        !          1499:     const char *    cp;
        !          1500:
        !          1501:     for (cp = dp->repl; (c = *cp++ & UCHARMAX) != EOS; ) {
        !          1502:
        !          1503:         switch (c) {
        !          1504:         case MAC_PARM:                              /* Parameter    */
        !          1505:             c = (*cp++ & UCHARMAX) - 1;
        !          1506:             if (standard) {
        !          1507:                 PARM    parm = parms[ c];
        !          1508:                 if ((numargs & VA_ARGS) && c == (numargs & ~AVA_ARGS) - 1) {
        !          1509:                     mcpp_fputs( gcc2_va ? parm.name : "__VA_ARGS__"
        !          1510:                             , FP2DEST( fp));
        !          1511:                     /* gcc2_va is possible only in STD mode */
        !          1512:                 } else {
        !          1513:                     if (mcpp_mode == STD) {
        !          1514:                         for (i = 0, cp1 = parm.name; i < parm.len; i++)
        !          1515:                             mcpp_fputc( *cp1++, FP2DEST( fp));
        !          1516:                     } else {
        !          1517:                         mcpp_fputc( 'a' + c % 26, FP2DEST( fp));
        !          1518:                         if (c > 26)
        !          1519:                             mcpp_fputc( '0' + c / 26, FP2DEST( fp));
        !          1520:                     }
        !          1521:                 }
        !          1522:             } else {
        !          1523:                 mcpp_fputc( 'a' + c % 26, FP2DEST( fp));
        !          1524:                 if (c > 26)
        !          1525:                     mcpp_fputc( '0' + c / 26, FP2DEST( fp));
        !          1526:             }
        !          1527:             break;
        !          1528:         case DEF_MAGIC:
        !          1529:             if (! standard)
        !          1530:                 mcpp_fputc( c, FP2DEST( fp));
        !          1531:             /* Else skip    */
        !          1532:             break;
        !          1533:         case CAT:
        !          1534:             if (standard)
        !          1535:                 mcpp_fputs( "##", FP2DEST( fp));
        !          1536:             else
        !          1537:                 mcpp_fputc( c, FP2DEST( fp));
        !          1538:             break;
        !          1539:         case ST_QUOTE:
        !          1540:             if (standard)
        !          1541:                 mcpp_fputs( "#", FP2DEST( fp));
        !          1542:             else
        !          1543:                 mcpp_fputc( c, FP2DEST( fp));
        !          1544:             break;
        !          1545:         case COM_SEP:
        !          1546:             /*
        !          1547:              * Though TOK_SEP coincides to COM_SEP, this cannot appear in
        !          1548:              * Standard mode.
        !          1549:              */
        !          1550:             if (mcpp_mode == OLD_PREP)
        !          1551:                 mcpp_fputs( "/**/", FP2DEST( fp));
        !          1552:             break;
        !          1553:         default:
        !          1554:             mcpp_fputc( c, FP2DEST( fp));
        !          1555:             break;
        !          1556:         }
        !          1557:     }
        !          1558: }
        !          1559:
        !          1560: /*
        !          1561:  * If the compiler is so-called "one-pass" compiler, compiler-predefined
        !          1562:  * macros are commented out to avoid redefinition.
        !          1563:  */
        !          1564: #if ONE_PASS
        !          1565: #define CAN_REDEF   DEF_NOARGS
        !          1566: #else
        !          1567: #define CAN_REDEF   DEF_NOARGS_PREDEF
        !          1568: #endif
        !          1569:
        !          1570: void    dump_a_def(
        !          1571:     const char *    why,
        !          1572:     const DEFBUF *  dp,
        !          1573:     int     newdef,         /* TRUE if parmnames are currently in parms[] */
        !          1574:     int     comment,        /* Show location of the definition in comment   */
        !          1575:     FILE *  fp
        !          1576: )
        !          1577: /*
        !          1578:  * Dump a macro definition.
        !          1579:  */
        !          1580: {
        !          1581:     char *  cp, * cp1;
        !          1582:     int     numargs = dp->nargs & ~AVA_ARGS;
        !          1583:     int     commented;                      /* To be commented out  */
        !          1584:     int     gcc2_va = FALSE;                /* GCC2-spec variadic   */
        !          1585:     int     i;
        !          1586:
        !          1587:     if (standard && numargs == DEF_PRAGMA)  /* _Pragma pseudo-macro */
        !          1588:         return;
        !          1589:     if ((numargs < CAN_REDEF) || (standard && dp->push))
        !          1590:         commented = TRUE;
        !          1591:     else
        !          1592:         commented = FALSE;
        !          1593:     if (! comment && commented)             /* For -dM option       */
        !          1594:         return;
        !          1595:     if (why)
        !          1596:         mcpp_fprintf( FP2DEST( fp), "%s \"%s\" defined as: ", why, dp->name);
        !          1597:     mcpp_fprintf( FP2DEST( fp), "%s#define %s", commented ? "/* " : "",
        !          1598:             dp->name);                      /* Macro name           */
        !          1599:     if (numargs >= 0) {                     /* Parameter list       */
        !          1600:         if (mcpp_mode == STD) {
        !          1601:             const char *    appendix = null;
        !          1602:             if (! newdef) {
        !          1603:                 /* Make parms[] for dump_repl() */
        !          1604:                 for (i = 0, cp = dp->parmnames; i < numargs;
        !          1605:                         i++, cp = cp1 + 1) {
        !          1606:                     if ((cp1 = strchr( cp, ',')) == NULL)   /* The last arg */
        !          1607:                         parms[ i].len = strlen( cp);
        !          1608:                     else
        !          1609:                         parms[ i].len = (size_t) (cp1 - cp);
        !          1610:                     parms[ i].name = cp;
        !          1611:                 }
        !          1612:             }
        !          1613: #if COMPILER == GNUC
        !          1614:             if ((dp->nargs & VA_ARGS)
        !          1615:                     && memcmp( parms[ numargs - 1].name, "...", 3) != 0) {
        !          1616:                 appendix = "...";   /* Append ... so as to become 'args...' */
        !          1617:                 gcc2_va = TRUE;
        !          1618:             }
        !          1619: #endif
        !          1620:             mcpp_fprintf( FP2DEST( fp), "(%s%s)", dp->parmnames, appendix);
        !          1621:         } else {
        !          1622:             if (newdef) {
        !          1623:                 mcpp_fprintf( FP2DEST( fp), "(%s)", parms[ 0].name);
        !          1624:             } else if (numargs == 0) {
        !          1625:                 mcpp_fputs( "()", FP2DEST( fp));
        !          1626:             } else {
        !          1627:                 /* Print parameter list automatically made as:      */
        !          1628:                 /* a, b, c, ..., a0, b0, c0, ..., a1, b1, c1, ...   */
        !          1629:                 mcpp_fputc( '(', FP2DEST( fp));
        !          1630:                 for (i = 0; i < numargs; i++) {     /* Make parameter list  */
        !          1631:                     mcpp_fputc( 'a' + i % 26, FP2DEST( fp));
        !          1632:                     if (i >= 26)
        !          1633:                         mcpp_fputc( '0' + i / 26, FP2DEST( fp));
        !          1634:                     if (i + 1 < numargs)
        !          1635:                         mcpp_fputc( ',', FP2DEST( fp));
        !          1636:                 }
        !          1637:                 mcpp_fputc( ')', FP2DEST( fp));
        !          1638:             }
        !          1639:         }
        !          1640:     }
        !          1641:     if (*dp->repl) {
        !          1642:         mcpp_fputc( ' ', FP2DEST( fp));
        !          1643:         dump_repl( dp, fp, gcc2_va);        /* Replacement text     */
        !          1644:     }
        !          1645:     if (commented)
        !          1646:             /* Standard predefined or one-pass-compiler-predefined  */
        !          1647:         mcpp_fputs( " */", FP2DEST( fp));
        !          1648:     if (comment)                            /* Not -dM option       */
        !          1649:         mcpp_fprintf( FP2DEST( fp), " \t/* %s:%ld\t*/", dp->fname, dp->mline);
        !          1650:     mcpp_fputc( '\n', FP2DEST( fp));
        !          1651: }
        !          1652:
        !          1653: void    dump_def(
        !          1654:     int     comment,        /* Location of definition in comment    */
        !          1655:     int     K_opt                       /* -K option is specified   */
        !          1656: )
        !          1657: /*
        !          1658:  * Dump all the current macro definitions to output stream.
        !          1659:  */
        !          1660: {
        !          1661:     DEFBUF *    dp;
        !          1662:     DEFBUF **   symp;
        !          1663:
        !          1664:     sharp( NULL, 0);    /* Report the current source file & line    */
        !          1665:     if (comment)
        !          1666:         mcpp_fputs( "/* Currently defined macros. */\n", OUT);
        !          1667:     for (symp = symtab; symp < &symtab[ SBSIZE]; symp++) {
        !          1668:         if ((dp = *symp) != NULL) {
        !          1669:             do {
        !          1670:                 if (K_opt)
        !          1671:                     mcpp_fprintf( OUT, "/*m%s*/\n", dp->name);
        !          1672:                 else
        !          1673:                     dump_a_def( NULL, dp, FALSE, comment, fp_out);
        !          1674:             } while ((dp = dp->link) != NULL);
        !          1675:         }
        !          1676:     }
        !          1677:     wrong_line = TRUE;               /* Line number is out of sync  */
        !          1678: }
        !          1679:
        !          1680: #if MCPP_LIB
        !          1681: void    clear_symtable( void)
        !          1682: /*
        !          1683:  * Free all the macro definitions.
        !          1684:  */
        !          1685: {
        !          1686:     DEFBUF *    next;
        !          1687:     DEFBUF *    dp;
        !          1688:     DEFBUF **   symp;
        !          1689:
        !          1690:     for (symp = symtab; symp < &symtab[ SBSIZE]; symp++) {
        !          1691:         for (next = *symp; next != NULL; ) {
        !          1692:             dp = next;
        !          1693:             next = dp->link;
        !          1694:             free( dp);                      /* Free the symbol      */
        !          1695:         }
        !          1696:         *symp = NULL;
        !          1697:     }
        !          1698: }
        !          1699: #endif
        !          1700:

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