示例#1
0
// form: #pragma include_alias( "alias_name", "real_name" )
//       #pragma include_alias( <alias_name>, <real_name> )
//
// (1) causes include directives referencing alias_name to refer
//     to real_name instead
//
static void pragIncludeAlias( void )
{
    if( ExpectingToken( T_LEFT_PAREN ) ) {
        PPCTL_ENABLE_MACROS();
        NextToken();
        if( CurToken == T_STRING ) {
            char    *alias_name;

            alias_name = CMemAlloc( strlen( Buffer ) + 1 );
            strcpy( alias_name, Buffer );
            NextToken();
            if( ExpectingToken( T_COMMA ) ) {
                NextToken();
            }
            if( CurToken == T_STRING ) {
                IAliasAdd( alias_name, Buffer, false );
                NextToken();
            }
            CMemFree( alias_name );
        } else if( CurToken == T_LT ) {
            char    a_buf[82];
            char    r_buf[82];

            a_buf[0] = '\0';
            for( ;; ) {
                NextToken();
                if( CurToken == T_GT ) {
                    NextToken();
                    break;
                }
                if( CurToken == T_NULL ) {
                    break;
                }
                strncat( a_buf, Buffer, sizeof( a_buf ) - 2 );
            }
            if( ExpectingToken( T_COMMA ) ) {
                NextToken();
            }
            if( CurToken == T_LT ) {
                r_buf[0] = '\0';
                for( ;; ) {
                    NextToken();
                    if( CurToken == T_GT ) {
                        NextToken();
                        break;
                    }
                    if( CurToken == T_NULL ) {
                        break;
                    }
                    strncat( r_buf, Buffer, sizeof( r_buf ) - 2 );
                }
                IAliasAdd( a_buf, r_buf, true );
            }
        }
        PPCTL_DISABLE_MACROS();
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#2
0
local void PragComment( void )
/****************************/
{
    if( ExpectingToken( T_LEFT_PAREN ) ) {
        NextToken();
        if( PragRecog( "lib" ) ) {
            if( ExpectingToken( T_COMMA ) ) {
                NextToken();
            }
            GetLibraryNames();
        }
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#3
0
static void StmtExpr( void )
{
    ChkStmtExpr();
    if( ExpectingToken( T_SEMI_COLON ) ) {
        NextToken();
    }
}
示例#4
0
static void PragIntrinsic( int intrinsic )              /* 09-oct-92 */
/****************************************/
{
    SYM_HANDLE  sym_handle;
    SYM_ENTRY   sym;

    if( ExpectingToken( T_LEFT_PAREN ) ) {
        NextToken();
        while( IS_ID_OR_KEYWORD( CurToken ) ) {
            sym_handle = SymLook( HashValue, Buffer );
            if( sym_handle != 0 ) {
                SymGet( &sym, sym_handle );
                sym.flags &= ~ SYM_INTRINSIC;
                if( intrinsic )
                    sym.flags |= SYM_INTRINSIC;
                SymReplace( &sym, sym_handle );
            }
            NextToken();
            if( CurToken != T_COMMA )
                break;
            NextToken();
        }
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#5
0
void MustRecog(                 // REQUIRE A SPECIFIC TOKEN AND SCAN NEXT
    TOKEN token )               // - token to be recognized
{
    ExpectingToken( token );
    if( CurToken != T_EOF ) {
        NextToken();
    }
}
示例#6
0
// #pragma alias(id1/"name1", id2/"name2")
//
// Causes linker to replace references to id1/name1 with references
// to id2/name2. Both the alias and the substituted symbol may be defined
// either as a string name or an id of existing symbol.
//
static void PragAlias( void )
/***************************/
{
    SYM_HANDLE      alias_sym;
    SYM_HANDLE      subst_sym;
    const char      *alias_name;
    const char      *subst_name;
    alias_list      **alias;
    alias_list      *new_alias;

    alias_name = subst_name = NULL;
    alias_sym  = subst_sym  = NULL;

    if( ExpectingToken( T_LEFT_PAREN ) ) {
        PPCTL_ENABLE_MACROS();
        PPNextToken();
        if( CurToken == T_ID ) {
            alias_sym = SymLook( HashValue, Buffer );
            if( alias_sym == 0 ) {
                CErr2p( ERR_UNDECLARED_SYM, Buffer );
            }
        } else if( CurToken == T_STRING ) {
            alias_name = CStrSave( Buffer );
        }
        PPNextToken();
        MustRecog( T_COMMA );
        if( CurToken == T_ID ) {
            subst_sym = SymLook( HashValue, Buffer );
            if( subst_sym == 0 ) {
                CErr2p( ERR_UNDECLARED_SYM, Buffer );
            }
        } else if( CurToken == T_STRING ) {
            subst_name = CStrSave( Buffer );
        }
        PPNextToken();
        PPCTL_DISABLE_MACROS();
        MustRecog( T_RIGHT_PAREN );
    }

    /* Add a new alias record - if it's valid - to the list */
    if( ( alias_name != NULL || alias_sym != NULL ) && ( subst_name != NULL || subst_sym != NULL ) ) {
        for( alias = &AliasHead; *alias != NULL; alias = &(*alias)->next )
            ; /* nothing to do */
        new_alias = (void *)CMemAlloc( sizeof( alias_list ) );
        new_alias->next = NULL;
        if( alias_name ) {
            new_alias->name = alias_name;
        } else {
            new_alias->a_sym = alias_sym;
        }
        if( subst_name ) {
            new_alias->subst = subst_name;
        } else {
            new_alias->s_sym = subst_sym;
        }
        *alias = new_alias;
    }
}
示例#7
0
static void pragPack(           // #PRAGMA PACK
    void )
{
    if( ExpectingToken( T_LEFT_PAREN ) ) {
        PPCTL_ENABLE_MACROS();
        NextToken();
        PPCTL_DISABLE_MACROS();
        switch( CurToken ) {
        case T_ID:
            if( PragIdRecog( "pop" ) ) {
                popPrag( &HeadPacks, &PackAmount );
            } else if( PragIdRecog( "push" ) ) {
                if( CurToken == T_RIGHT_PAREN ) {
                    pushPrag( &HeadPacks, PackAmount );
                } else {
                    if( ExpectingToken( T_COMMA ) ) {
                        PPCTL_ENABLE_MACROS();
                        NextToken();
                        PPCTL_DISABLE_MACROS();
                    }
                    if( CurToken == T_CONSTANT ) {
                        pushPrag( &HeadPacks, PackAmount );
                        PackAmount = VerifyPackAmount( U32Fetch( Constant64 ) );
                        NextToken();
                    } else {
                        MustRecog( T_CONSTANT );
                    }
                }
            } else {
                CErr( ERR_EXPECTING_BUT_FOUND, "push or pop", Buffer );
            }
            break;
        case T_CONSTANT:
            PackAmount = VerifyPackAmount( U32Fetch( Constant64 ) );
            NextToken();
            break;
        case T_RIGHT_PAREN:
            PackAmount = GblPackAmount;
            break;
        default:
            break;
        }
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#8
0
static void pragComment(        // #PRAGMA COMMENT
    void )
{
    if( ExpectingToken( T_LEFT_PAREN ) ) {
        NextToken();
        if( PragRecog( "lib" ) ) {
            PPCTL_ENABLE_MACROS();
            if( ExpectingToken( T_COMMA ) ) {
                NextToken();
            }
            while( IS_ID_OR_KEYWORD( CurToken ) || CurToken == T_STRING ) {
                CgInfoAddUserLib( Buffer );
                NextToken();
            }
            PPCTL_DISABLE_MACROS();
        }
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#9
0
static void endOfPragma(
    void )
{
    if( CurToken == T_SEMI_COLON )
        NextToken();
    ExpectingToken( T_NULL );
    while( CurToken != T_NULL && CurToken != T_EOF ) {
        NextToken();
    }
}
示例#10
0
local void CUndef( void )
{

    PPNextToken();
    if( ExpectingToken( T_ID ) ) {
        MacroDel( Buffer );
        PPNextToken();
        ChkEOL();
    }
}
示例#11
0
local void EndOfPragma( void )
/*****************************/
{
    if( CurToken == T_SEMI_COLON )
        NextToken();
    ExpectingToken( T_NULL );
    while( CurToken != T_NULL && CurToken != T_EOF ) {
        NextToken();
    }
}
示例#12
0
// forms: (1) #pragma include_alias( "alias_name", "real_name" )
//        (2) #pragma include_alias( <alias_name>, <real_name> ) 
// 
// causes include directives referencing alias_name to be refer
// to real_name instead
//
static void PragIncludeAlias( void )
/**********************************/
{
    if( ExpectingToken( T_LEFT_PAREN ) ) {
        PPCTL_ENABLE_MACROS();
        NextToken();
        if( CurToken == T_STRING ) {
            char    *alias_name;

            alias_name = CStrSave( Buffer );
            NextToken();
            MustRecog( T_COMMA );
            if( CurToken == T_STRING ) {
                SrcFileIncludeAlias( alias_name, Buffer, FALSE );
                NextToken();
            }
            CMemFree( alias_name );
        } else if( CurToken == T_LT ) {
            char    a_buf[ 82 ];    /* same size as CInclude() in cmac2.c */
            char    r_buf[ 82 ];

            a_buf[ 0 ] = '\0';
            for( ;; ) {
                NextToken();
                if( CurToken == T_GT ) {
                    NextToken();
                    break;
                }
                if( CurToken == T_NULL ) {
                    break;
                }
                strncat( a_buf, Buffer, sizeof( a_buf ) - 2 );
            }
            MustRecog( T_COMMA );
            if( CurToken == T_LT ) {
                r_buf[ 0 ] = '\0';
                for( ;; ) {
                    NextToken();
                    if( CurToken == T_GT ) {
                        NextToken();
                        break;
                    }
                    if( CurToken == T_NULL ) {
                        break;
                    }
                    strncat( r_buf, Buffer, sizeof( r_buf ) - 2 );
                }
                SrcFileIncludeAlias( a_buf, r_buf, TRUE );
            }
        }
        PPCTL_DISABLE_MACROS();
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#13
0
static void pragFlag(           // SET TOGGLES
    bool set_flag )             // - true ==> set flag
{
    if( ExpectingToken( T_LEFT_PAREN ) ) {
        NextToken();
        while( IS_ID_OR_KEYWORD( CurToken ) ) {
            PragmaSetToggle( set_flag );
            NextToken();
        }
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#14
0
// form:
// #pragma message ("one or more " "long message " "strings")
// output these strings to stdout
// this output is _not_ dependent on setting
// of #pragma enable_message or disable_message.
static void PragMessage( void )
/*****************************/
{
    if( ExpectingToken( T_LEFT_PAREN ) ) {
        PPCTL_ENABLE_MACROS();
        while( NextToken() == T_STRING ) {
            printf( "%s", Buffer );
        }
        printf( "\n" );
        PPCTL_DISABLE_MACROS();
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#15
0
local void PragFlag( int value )
/******************************/
{

    if( ExpectingToken( T_LEFT_PAREN ) ) {
        NextToken();
        while( IS_ID_OR_KEYWORD( CurToken ) ) {
            SetToggleFlag( Buffer, value );
            NextToken();
        }
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#16
0
static void pragIntrinsic(      // SET FUNCTIONS TO BE (NOT TO BE) INTRINSIC
    bool intrinsic )            // - true ==> function to be intrinsic
{
    if( ExpectingToken( T_LEFT_PAREN ) ) {
        NextToken();
        while( IS_ID_OR_KEYWORD( CurToken ) ) {
            ScopeIntrinsic( intrinsic );
            NextToken();
            if( CurToken != T_COMMA )  break;
            NextToken();
        }
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#17
0
// forms:
//    #pragma enable_message( messageNo )
//    #pragma disable_message( messageNo )
//
// dis- enable display of selected message number
//
local void PragEnableDisableMessage( int enable )
/***********************************************/
{
    if( ExpectingToken( T_LEFT_PAREN ) ) {
        NextToken();
        while( CurToken == T_CONSTANT ) {
            EnableDisableMessage( enable, Constant );
            NextToken();
            if( CurToken == T_COMMA ) {
                NextToken();
            }
        }
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#18
0
static void pragMessage(        // #PRAGMA MESSAGE
    void )
{
    VBUF str;

    if( ExpectingToken( T_LEFT_PAREN ) ) {
        PPCTL_ENABLE_MACROS();
        NextToken();
        if( CurToken == T_STRING ) {
            collectStrings( &str );
            CErr2p( WARN_USER_WARNING_MSG, VbufString( &str ) );
            VbufFree( &str );
        }
        PPCTL_DISABLE_MACROS();
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#19
0
REWRITE *RewritePackageClassTemplate( REWRITE *r, TOKEN_LOCN *locn )
/******************************************************************/
{
    unsigned brace_depth;
    bool first_time;
    TOKEN_LOCN start_locn;

    SrcFileGetTokenLocn( &start_locn );
    brace_depth = 0;
    first_time = TRUE;
    for(;;) {
        if( CurToken == T_EOF ) {
            templateError( r, &start_locn );
            break;
        }
        if( ! first_time ) {
            /* already been saved by YYDRIVER */
            saveToken( r, locn );
        }
        first_time = FALSE;
        switch( CurToken ) {
        case T_RIGHT_BRACE:
        case T_ALT_RIGHT_BRACE:
            if( brace_depth == 0 ) {
                return( templateError( r, &start_locn ) );
            }
            --brace_depth;
            if( brace_depth == 0 ) {
                NextToken();
                if( !ExpectingToken( T_SEMI_COLON ) ) {
                    return( templateError( r, &start_locn ) );
                }
                return( r );
            }
            break;
        case T_LEFT_BRACE:
        case T_ALT_LEFT_BRACE:
            ++brace_depth;
            break;
        default:
            break;
        }
        NextToken();
    }
    return( NULL );
}
示例#20
0
static void PragUnroll( void )
/****************************/
{
    unsigned    unroll_count;

    if( ExpectingToken( T_LEFT_PAREN ) ) {
        unroll_count = 0;
        NextToken();
        if( CurToken == T_CONSTANT ) {
            unroll_count = Constant;
            NextToken();
        }
        if( unroll_count > 255 )
            unroll_count = 255;
        UnrollCount = unroll_count;
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#21
0
local void PragPack( void )
/*************************/
{
    if( ExpectingToken( T_LEFT_PAREN ) ) {
        PPCTL_ENABLE_MACROS();
        NextToken();
        PPCTL_DISABLE_MACROS();
        if( CurToken == T_CONSTANT ) {
            SetPackAmount();
            NextToken();
        } else if( IS_ID_OR_KEYWORD( CurToken ) ) {
            getPackArgs();
        } else if( CurToken == T_RIGHT_PAREN ) {
            PackAmount = GblPackAmount;
        }
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#22
0
local void CLine( void )
{
    FNAMEPTR        flist;
    unsigned long   src_line;

    src_line = 0;
    PPCTL_ENABLE_MACROS();
    PPNextToken();
    if( ExpectingConstant() ) {
        if( CompFlags.cpp_ignore_line == 0 ) {
            src_line = Constant; // stash in case of side effects
            SrcFile->src_loc.line = src_line - 1; /* don't count this line */
        }
        PPNextToken();
        if( CurToken == T_NULL ) {
            if( CompFlags.cpp_ignore_line == 0 ) {
                if( CompFlags.cpp_output ) {
                    EmitLine( src_line, SrcFile->src_name );
                }
            }
        } else {
            if( ExpectingToken( T_STRING ) ) {
                if( CompFlags.wide_char_string ) {
                    /* wide char string not allowed */
                    ExpectString();
                } else {
                    if( CompFlags.cpp_ignore_line == 0 ) {
                        // RemoveEscapes( Buffer );
                        flist = AddFlist( Buffer );
                        flist->rwflag = FALSE;  // not a real file so no autodep
                        SrcFile->src_name = flist->name;
                        SrcFile->src_loc.fno  = flist->index;
                        if( CompFlags.cpp_output ) {
                            EmitLine( src_line, SrcFile->src_name );
                        }
                    }
                }
            }
            PPNextToken();
            ChkEOL();
        }
    }
    PPCTL_DISABLE_MACROS();
}
示例#23
0
local void CIfNDef( void )
{
    MEPTR       mentry;

    PPNextToken();
    if( !ExpectingToken( T_ID ) ) {
        IncLevel( 0 );
        return;
    }
    mentry = MacroLookup( Buffer );
    if( mentry != NULL ) {
        mentry->macro_flags |= MFLAG_REFERENCED;
        IncLevel( 0 );
    } else {
        IncLevel( 1 );
    }
    PPNextToken();
    ChkEOL();
}
示例#24
0
// forms: #pragma init_seg({compiler|lib|user})
//
//      - compiler (16)
//      - library (32)
//      - user (64)
//
static void pragInitSeg(     // #pragma init_seg ...
    void )
{
    int priority;

    if( ExpectingToken( T_LEFT_PAREN ) ) {
        NextToken();
        if( PragRecog( "compiler" ) ) {
            priority = INIT_PRIORITY_LIBRARY - 1;
        } else if( PragRecog( "lib" ) ) {
            priority = INIT_PRIORITY_LIBRARY;
        } else {
            priority = INIT_PRIORITY_PROGRAM;
            MustRecog( T_ID );
        }
        CompInfo.init_priority = priority;
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#25
0
local void PragAllocText( void )                              /* 26-oct-91 */
/******************************/
{
    struct textsegment  *seg;
    SYM_HANDLE          sym_handle;
    auto SYM_ENTRY      sym;

    if( ExpectingToken( T_LEFT_PAREN ) ) {
        NextToken();
        /* current token can be an T_ID or a T_STRING */
        seg = LkSegName( Buffer, "" );
        NextToken();
        for( ; ; ) {
            MustRecog( T_COMMA );
            /* current token can be an T_ID or a T_STRING */
            sym_handle = Sym0Look( CalcHash( Buffer, strlen( Buffer ) ), Buffer );
            if( sym_handle == 0 ) {
                /* error */
            } else {
                SymGet( &sym, sym_handle );
                if( sym.flags & SYM_FUNCTION ) {
                    sym.seginfo = seg;
                    SymReplace( &sym, sym_handle );
                } else {
                    /* error, must be function */
                }
            }
            NextToken();
            if( CurToken == T_RIGHT_PAREN )
                break;
            if( CurToken == T_EOF )
                break;
            if( CurToken == T_NULL ) {
                break;
            }
        }
#if _CPU == 8086 || _CPU == 386
        CompFlags.multiple_code_segments = 1;
#endif
        MustRecog( T_RIGHT_PAREN );
    }
}
示例#26
0
void MustRecog( TOKEN this_token )
{
    if( ExpectingToken( this_token ) ) {
        NextToken();
    } else {
/*      if( CurToken != T_LEFT_BRACE && CurToken != T_RIGHT_BRACE */
        if( CurToken != T_EOF ) {
            if( CurToken == T_SEMI_COLON ) {    /* 13-nov-94 */
                switch( this_token ) {
                case T_RIGHT_BRACKET:
                case T_RIGHT_PAREN:
                    break;
                default:
                    NextToken();
                    break;
                }
            } else if( this_token != T_SEMI_COLON ) {   /* 14-sep-95 */
                NextToken();
            }
        }
    }
}
示例#27
0
local void CDefine( void )
{
    struct macro_parm *mp, *prev_mp, *formal_parms;
    int         parm_cnt, parm_end = 0;
    int         ppscan_mode;
    char        *token_buf;
    source_loc  macro_loc;

    PPNextToken();
    if( CurToken != T_ID ) {
        ExpectIdentifier();
        return;
    }
    if( strcmp( Buffer, "defined" ) == 0 ) {
        CErr1( ERR_CANT_DEFINE_DEFINED );
        return;
    }
    token_buf = CStrSave( Buffer );
    formal_parms = NULL;
    macro_loc = SrcFileLoc;
    parm_cnt = -1;              /* -1 ==> no () following */
    if( CurrChar == '(' ) {     /* parms present */
        PPNextToken();          /* grab the '(' */
        PPNextToken();
        parm_cnt = 0;           /* 0 ==> () following */
        parm_end = 0;
        prev_mp = NULL;
        for( ;; ) {
            if( CurToken == T_RIGHT_PAREN )
                break;
            if( parm_end ) {
                ExpectingAfter( T_RIGHT_PAREN, T_DOT_DOT_DOT );
                return;
            }
            if( CurToken != T_DOT_DOT_DOT && !ExpectingToken( T_ID ) ) {
                return;
            }
            ++parm_cnt;
            if( CurToken == T_DOT_DOT_DOT ) {
                parm_end = 1; /* can have no more parms after this. */
            }
            mp = (struct macro_parm *)CMemAlloc( sizeof( struct macro_parm ) );
            if( formal_parms == NULL ) {
                formal_parms = mp;
            } else {
                if( FormalParm( formal_parms ) ) {
                    CErr2p( ERR_DUPLICATE_MACRO_PARM, Buffer );
                }
                prev_mp->next_macro_parm = mp;
            }
            if( CurToken == T_DOT_DOT_DOT )
                mp->parm = CStrSave( "__VA_ARGS__" );
            else
                mp->parm = CStrSave( Buffer );
            prev_mp = mp;
            PPNextToken();
            if( CurToken == T_RIGHT_PAREN )
                break;
            if( CurToken == T_NULL ) {
                CErr1( ERR_INVALID_MACRO_DEFN );
                break;
            }
            if( parm_end ) {
                ExpectingAfter( T_RIGHT_PAREN, T_DOT_DOT_DOT );
                return;
            }
            MustRecog( T_COMMA );
            if( CurToken != T_DOT_DOT_DOT && !ExpectingToken( T_ID ) ) {
                return;
            }
        }
    }
    /* grab replacement tokens */
    ppscan_mode = InitPPScan();         // enable T_PPNUMBER tokens
    GrabTokens( parm_end ? -(parm_cnt + 1) : (parm_cnt + 1), formal_parms, token_buf, &macro_loc );
    FiniPPScan( ppscan_mode );          // disable T_PPNUMBER tokens
    for( ; (mp = formal_parms) != NULL; ) {
        formal_parms = mp->next_macro_parm;
        CMemFree( mp->parm );
        CMemFree( mp );
    }
    CMemFree( token_buf );
}
示例#28
0
local void ChkEOL( void )
{
    if( CurToken != T_EOF ) {
        ExpectingToken( T_NULL );
    }
}
示例#29
0
static void CDefine( void )
{
    MPPTR           mp;
    MPPTR           prev_mp;
    MPPTR           formal_parms;
    mac_parm_count  parm_count;
    macro_flags     mflags;
    bool            ppscan_mode;
    char            *token_buf;
    source_loc      macro_loc;

    PPNextToken();
    if( CurToken != T_ID ) {
        ExpectIdentifier();
        return;
    }
    if( CMPLIT( Buffer, "defined" ) == 0 ) {
        CErr1( ERR_CANT_DEFINE_DEFINED );
        return;
    }
    token_buf = CStrSave( Buffer );
    formal_parms = NULL;
    macro_loc = SrcFileLoc;
    parm_count = 0;             /* 0 ==> no () following */
    mflags = MFLAG_USER_DEFINED;
    if( CurrChar == '(' ) {     /* parms present */
        PPNextToken();          /* grab the '(' */
        PPNextToken();
        parm_count = 1;         /* 1 ==> () following */
        prev_mp = NULL;
        for( ; CurToken != T_RIGHT_PAREN; ) {
            if( mflags & MFLAG_VAR_ARGS ) {
                ExpectingAfter( T_RIGHT_PAREN, T_DOT_DOT_DOT );
                return;
            }
            if( CurToken != T_DOT_DOT_DOT && !ExpectingToken( T_ID ) ) {
                return;
            }
            ++parm_count;
            if( CurToken == T_DOT_DOT_DOT ) {
                mflags |= MFLAG_VAR_ARGS;   /* can have no more parms after this. */
            }
            mp = (MPPTR)CMemAlloc( sizeof( MPDEFN ) );
            if( formal_parms == NULL ) {
                formal_parms = mp;
            } else {
                if( FormalParm( formal_parms ) ) {
                    CErr2p( ERR_DUPLICATE_MACRO_PARM, Buffer );
                }
                prev_mp->next = mp;
            }
            if( CurToken == T_DOT_DOT_DOT ) {
                mp->parm = CStrSave( "__VA_ARGS__" );
            } else {
                mp->parm = CStrSave( Buffer );
            }
            prev_mp = mp;
            PPNextToken();
            if( CurToken == T_RIGHT_PAREN )
                break;
            if( CurToken == T_NULL ) {
                CErr1( ERR_INVALID_MACRO_DEFN );
                break;
            }
            if( mflags & MFLAG_VAR_ARGS ) {
                ExpectingAfter( T_RIGHT_PAREN, T_DOT_DOT_DOT );
                return;
            }
            MustRecog( T_COMMA );
            if( CurToken != T_DOT_DOT_DOT && !ExpectingToken( T_ID ) ) {
                return;
            }
        }
    }
    /* grab replacement tokens */
    ppscan_mode = InitPPScan();         // enable T_PPNUMBER tokens
    GrabTokens( parm_count, mflags, formal_parms, token_buf, &macro_loc );
    FiniPPScan( ppscan_mode );          // disable T_PPNUMBER tokens
    for( ; (mp = formal_parms) != NULL; ) {
        formal_parms = mp->next;
        CMemFree( mp->parm );
        CMemFree( mp );
    }
    CMemFree( token_buf );
}