Ejemplo n.º 1
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;
    }
}
Ejemplo n.º 2
0
void CInclude( void )
{
    char        in_macro;
    auto char   buf[ 82 ];

    if( PCH_FileName != NULL && CompFlags.make_precompiled_header == 0 ) {
        if( CompFlags.ok_to_use_precompiled_hdr ) {     /* 27-jun-94 */
            CompFlags.use_precompiled_header = 1;
        }
    }
    if( CompFlags.use_precompiled_header ) {
        InitBuildPreCompiledHeader();
    }
    InitialMacroFlag = MFLAG_NONE;
    in_macro = 0;
    if( MacroPtr != NULL )
        in_macro = 1;
    PPCTL_ENABLE_MACROS();
    PPNextToken();
    PPCTL_DISABLE_MACROS();
    if( CurToken == T_STRING ) {
        OpenSrcFile( Buffer, FALSE );
#if _CPU == 370
        if( !CompFlags.use_precompiled_header ) {
            SrcFile->colum = Column;    /* do trunc and col on  */
            SrcFile->trunc = Trunc;     /* on user source files */
        }
#endif
    } else if( CurToken == T_LT ) {
        if( in_macro ) {
            PPCTL_ENABLE_MACROS();
        }
        buf[ 0 ] = '\0';
        for( ;; ) {
            PPNextToken();
            if( CurToken == T_GT ) {
                OpenSrcFile( buf, TRUE );
                break;
            }
            strncat( buf, Buffer, sizeof( buf ) - 2 );
            if( in_macro != 0 && MacroPtr == NULL || CurToken == T_NULL || CurToken == T_EOF ) {
                CErr1( ERR_INVALID_INCLUDE );
                break;
            }
        }
        if( in_macro ) {
            PPCTL_DISABLE_MACROS();
        }
    } else {
        CErr1( ERR_INVALID_INCLUDE );
    }
    if( CurToken != T_EOF ) {
        PPNextToken();
    }
    CompFlags.use_precompiled_header = 0;
}
Ejemplo n.º 3
0
local void CUndef( void )
{

    PPNextToken();
    if( ExpectingToken( T_ID ) ) {
        MacroDel( Buffer );
        PPNextToken();
        ChkEOL();
    }
}
Ejemplo n.º 4
0
local void CElif( void )
{
    int value;

    PPCTL_ENABLE_MACROS();
    PPNextToken();
    if( ( NestLevel == 0 ) || ( CppStack->cpp_type == PRE_ELSE ) ) {
        CErr1( ERR_MISPLACED_ELIF );
    } else {
        if( NestLevel == SkipLevel ) {
            --SkipLevel;                /* start skipping else part */
            CppStack->processing = 0;
            CppStack->cpp_type = PRE_ELIF;
        } else if( NestLevel == SkipLevel + 1 ) {
            /* only evaluate the expression when required */
            if( CppStack->cpp_type == PRE_IF ) {
                value = GetConstExpr();
                ChkEOL();
                if( value ) {
                    SkipLevel = NestLevel; /* start including else part */
                    CppStack->processing = 1;
                    CppStack->cpp_type = PRE_ELIF;
                }
            }
        }
    }
    PPCTL_DISABLE_MACROS();
}
Ejemplo n.º 5
0
TOKEN ChkControl( void )
{
    int         lines_skipped;
    ppctl_t     old_ppctl;

    if( !CompFlags.doing_macro_expansion ) {
        if( CompFlags.cpp_output ) {
            PrintWhiteSpace = FALSE;
        }
    }
    while( CurrChar == '\n' ) {
        if( TBreak() ) {
            CErr1( ERR_BREAK_KEY_HIT );
            CSuicide();
        }
        lines_skipped = 0;
        old_ppctl = CompFlags.pre_processing;
        for( ; CurrChar != EOF_CHAR; ) {
            if( CompFlags.cpp_output ) {
                CppPrtChar( '\n' );
            }
            NextChar();
            if( CurrChar != PreProcChar ) {
                SkipAhead();
            }
            if( CurrChar == EOF_CHAR )
                break;
            if( CurrChar == PreProcChar ) { /* start of comp control line */
                PPCTL_ENABLE_EOL();
                PPCTL_DISABLE_MACROS();
                PreProcStmt();
                PPFlush2EOL();
                CompFlags.pre_processing = old_ppctl;
            } else if( NestLevel != SkipLevel ) {
                PPCTL_ENABLE_EOL();
                PPCTL_DISABLE_MACROS();
                PPNextToken();              /* get into token mode */
                PPFlush2EOL();
                CompFlags.pre_processing = old_ppctl;
            }
            if( NestLevel == SkipLevel )
                break;
            if( CurrChar == '\n' ) {
                lines_skipped = 1;
            }
        }
        if( CompFlags.cpp_output ) {
            if( lines_skipped ) {
                if( SrcFile != NULL ) {                 /* 14-may-92 */
                    EmitLine( SrcFile->src_loc.line, SrcFile->src_name );
                }
            }
        }
    }
    // we have already skipped past all white space at the start of the line
    CurToken = T_WHITE_SPACE;
//  CurToken = ScanToken();
    return( T_WHITE_SPACE );
}
Ejemplo n.º 6
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();
}
Ejemplo n.º 7
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();
}
Ejemplo n.º 8
0
local void CIf( void )
{
    int value;

    PPCTL_ENABLE_MACROS();
    PPNextToken();
    value = GetConstExpr();
    IncLevel( value );
    ChkEOL();
    PPCTL_DISABLE_MACROS();
}
Ejemplo n.º 9
0
local void CIfDef( void )
{
    MEPTR       mentry;

    PPNextToken();
    if( CurToken != T_ID ) {
        ExpectIdentifier();
        IncLevel( 0 );
        return;
    }
    mentry = MacroLookup( Buffer );
    if( mentry != NULL ) {
        mentry->macro_flags |= MFLAG_REFERENCED;
        IncLevel( 1 );
    } else {
        IncLevel( 0 );
    }
    PPNextToken();
    ChkEOL();
}
Ejemplo n.º 10
0
local void CElse( void )
{
    if( ( NestLevel == 0 ) || ( CppStack->cpp_type == PRE_ELSE ) ) {
        CErr1( ERR_MISPLACED_ELSE );
    } else {
        if( NestLevel == SkipLevel ) {
            --SkipLevel;                /* start skipping else part */
            CppStack->processing = 0;
        } else if( NestLevel == SkipLevel + 1 ) {
            /* cpp_type will be PRE_ELIF if an elif was true */
            if( CppStack->cpp_type == PRE_IF ) {        /* 19-sep-88 */
                SkipLevel = NestLevel;  /* start including else part */
                CppStack->processing = 1;
            }
        }
        CppStack->cpp_type = PRE_ELSE;
    }
    PPNextToken();
    WantEOL();
}
Ejemplo n.º 11
0
local void CEndif( void )
{
    if( NestLevel == 0 ) {
        CErr1( ERR_MISPLACED_ENDIF );
    } else {
        struct cpp_info *cpp;

        --NestLevel;
        cpp = CppStack;
        if( cpp->flist != SrcFile->src_flist ) {
             CWarn2p( WARN_LEVEL_1, ERR_WEIRD_ENDIF_ENCOUNTER, FileIndexToCorrectName( cpp->src_loc.fno ) );
        }
        CppStack = cpp->prev_cpp;
        CMemFree( cpp );
    }
    if( NestLevel < SkipLevel ) {
        SkipLevel = NestLevel;
    }
    PPNextToken();
    WantEOL();
}
Ejemplo n.º 12
0
static void PreProcStmt( void )
{
    struct preproc      *pp;
    int                 hash;

    NextChar();                 /* skip over '#' */
    PPNextToken();
    if( CurToken == T_ID ) {
        hash = (TokenLen + PreProcWeights[ Buffer[ 0 ] - 'a' ]
                 + PreProcWeights[ Buffer[ TokenLen - 1 ] - 'a' ]) & 15;
        pp = &PreProcTable[ hash ];
        if( strcmp( pp->directive, Buffer ) == 0 ) {
            if( NestLevel == SkipLevel ) {
                pp->samelevel();
            } else {
                pp->skipfunc();
            }
        } else {
            CUnknown();
        }
    } else if( CurToken != T_NULL ) {
        CUnknown();
    }
}
Ejemplo n.º 13
0
local void GrabTokens( int parm_cnt, struct macro_parm *formal_parms, const char *mac_name, source_loc *loc )
{
    MEPTR       mentry;
    int         i;
    int         j;
    TOKEN       prev_token;
    int         prev_non_ws_token;
    unsigned    mlen;
    macro_flags mflags;
    TOKEN       *p_token;

    mentry = CreateMEntry( mac_name );
    mflags = MFLAG_USER_DEFINED;
    if( parm_cnt < 0 ) {
        mflags |= MFLAG_VAR_ARGS;
        parm_cnt = -parm_cnt;
    }
    mentry->parm_count = parm_cnt;
    mentry->src_loc.fno = loc->fno;
    mentry->src_loc.line = loc->line;
    mlen = mentry->macro_len;
    mentry->macro_defn = mlen;
    MacroOverflow( mlen, 0 );
    MacroCopy( mentry, MacroOffset, mlen );
    prev_token = T_NULL;
    prev_non_ws_token = T_NULL;
    if( CurToken != T_NULL ) {
        do {
            CurToken = ScanToken();
        } while( CurToken == T_WHITE_SPACE );
        if( CurToken == T_SHARP_SHARP ) {
            CErr1( ERR_MISPLACED_SHARP_SHARP );
            PPNextToken();
        }
    }
    for( ;; ) {
        i = 0;
        if( ( CurToken == T_STRING ) && CompFlags.wide_char_string ) {
            CurToken = T_LSTRING;                   /* 15-may-92 */
        }
        p_token = (TOKEN *)&TokenBuf[ i ];
        *p_token = CurToken;
        i += sizeof( TOKEN );
        if( CurToken == T_NULL )
            break;
        if( CurToken == T_EOF )
            break;
        switch( CurToken ) {
        case T_SHARP:
            /* if it is a function-like macro definition */
            if( parm_cnt != 0 ) {
                *p_token = T_MACRO_SHARP;
                CurToken = T_MACRO_SHARP;           /* 26-mar-91 */
            }
            break;
        case T_SHARP_SHARP:
            *p_token = T_MACRO_SHARP_SHARP;
            break;
        case T_WHITE_SPACE:
            if( prev_token == T_WHITE_SPACE )
                i -= sizeof( TOKEN );
            break;
        case T_ID:
            j = FormalParm( formal_parms );
            if( j != 0 ) {
                if( (mflags & MFLAG_VAR_ARGS) && (j == parm_cnt - 1) )
                    CurToken = T_MACRO_VAR_PARM;
                else
                    CurToken = T_MACRO_PARM;
                *p_token = CurToken;
                TokenBuf[ i ] = j - 1;
                ++i;
            } else {
                j = 0;
                while( (TokenBuf[ i++ ] = Buffer[ j++ ]) != '\0' )
                    ;   /*empty*/
            }
            break;
        case T_BAD_CHAR:
            TokenBuf[ i++ ] = Buffer[ 0 ];
            if( Buffer[ 1 ] != '\0' ) {
                *(TOKEN *)&TokenBuf[ i ] = T_WHITE_SPACE;
                i += sizeof( TOKEN );
            }
            break;
        case T_CONSTANT:
        case T_STRING:
        case T_LSTRING:
        case T_BAD_TOKEN:
        case T_PPNUMBER:
            j = 0;
            while( (TokenBuf[ i++ ] = Buffer[ j++ ]) != '\0' )
                ;   /* empty */
            break;
        default:
            break;
        }
        if( CurToken != T_WHITE_SPACE ) {
            if( prev_non_ws_token == T_MACRO_SHARP &&       /* 26-mar-91 */
                CurToken != T_MACRO_PARM &&
                CurToken != T_MACRO_VAR_PARM ) {
                CErr1( ERR_MUST_BE_MACRO_PARM );
                prev_token = *(TOKEN *)TokenBuf;
                *(TOKEN *)TokenBuf = T_SHARP;               /* 17-jul-92 */
                MacroCopy( TokenBuf, MacroOffset + mlen - sizeof( TOKEN ), sizeof( TOKEN ) );
                *(TOKEN *)TokenBuf = prev_token;
            }
            prev_non_ws_token = CurToken;
        }
        prev_token = CurToken;
        CurToken = ScanToken();
        MacroOverflow( mlen + i, mlen );
        MacroCopy( TokenBuf, MacroOffset + mlen, i );
        mlen += i;
    }
    if( prev_non_ws_token == T_MACRO_SHARP ) {
        CErr1( ERR_MUST_BE_MACRO_PARM );
    }
    if( prev_token == T_WHITE_SPACE ) {
        mlen -= sizeof( TOKEN );
    }
    MacroOverflow( mlen + sizeof( TOKEN ), mlen );
    *(TOKEN *)(MacroOffset + mlen) = T_NULL;
    mlen += sizeof( TOKEN );
    if( prev_non_ws_token == T_SHARP_SHARP ) {
        CErr1( ERR_MISPLACED_SHARP_SHARP );
    }
    mentry->macro_len = mlen;
    MacLkAdd( mentry, mlen, mflags );
    FreeMEntry( mentry );
    MacroSize += mlen;
}
Ejemplo n.º 14
0
static void GrabTokens( mac_parm_count parm_count, macro_flags mflags, MPPTR formal_parms, const char *mac_name, source_loc *loc )
{
    MEPTR           mentry;
    size_t          len;
    TOKEN           prev_token;
    TOKEN           prev_non_ws_token;
    size_t          mlen;
    mac_parm_count  parmno;

    mentry = CreateMEntry( mac_name, strlen( mac_name ) );
    mentry->parm_count = parm_count;
    mentry->src_loc.fno = loc->fno;
    mentry->src_loc.line = loc->line;
    mlen = mentry->macro_len;
    mentry->macro_defn = mlen;
    MacroOverflow( mlen, 0 );
    MacroCopy( mentry, MacroOffset, mlen );
    prev_token = T_NULL;
    prev_non_ws_token = T_NULL;
    if( CurToken != T_NULL ) {
        do {
            CurToken = ScanToken();
        } while( CurToken == T_WHITE_SPACE );
        if( CurToken == T_SHARP_SHARP ) {
            CErr1( ERR_MISPLACED_SHARP_SHARP );
            PPNextToken();
        }
    }
    for( ; CurToken != T_NULL && CurToken != T_EOF ; ) {
        MTOK( TokenBuf ) = CurToken;
        len = sizeof( TOKEN );
        switch( CurToken ) {
        case T_SHARP:
            /* if it is a function-like macro definition */
            if( parm_count != 0 ) {
                CurToken = T_MACRO_SHARP;
                MTOK( TokenBuf ) = CurToken;
            }
            break;
        case T_SHARP_SHARP:
            MTOK( TokenBuf ) = T_MACRO_SHARP_SHARP;
            break;
        case T_WHITE_SPACE:
            if( prev_token == T_WHITE_SPACE )
                MTOKDEC( len );
            break;
        case T_ID:
            parmno = FormalParm( formal_parms );
            if( parmno != 0 ) {
                if( (mflags & MFLAG_VAR_ARGS) && (parmno == parm_count - 1) ) {
                    CurToken = T_MACRO_VAR_PARM;
                } else {
                    CurToken = T_MACRO_PARM;
                }
                MTOK( TokenBuf ) = CurToken;
                MTOKPARM( TokenBuf + len ) = parmno - 1;
                MTOKPARMINC( len );
            } else {
                memcpy( TokenBuf + len, Buffer, TokenLen + 1 );
                len += TokenLen + 1;
            }
            break;
        case T_BAD_CHAR:
            TokenBuf[len++] = Buffer[0];
            if( Buffer[1] != '\0' ) {
                MTOK( TokenBuf + len ) = T_WHITE_SPACE;
                MTOKINC( len );
            }
            break;
        case T_STRING:
            if( CompFlags.wide_char_string ) {
                CurToken = T_LSTRING;
                MTOK( TokenBuf ) = CurToken;
            }
            /* fall through */
        case T_CONSTANT:
        case T_LSTRING:
        case T_BAD_TOKEN:
        case T_PPNUMBER:
            memcpy( TokenBuf + len, Buffer, TokenLen + 1 );
            len += TokenLen + 1;
            break;
        default:
            break;
        }
        if( CurToken != T_WHITE_SPACE ) {
            if( prev_non_ws_token == T_MACRO_SHARP
              && CurToken != T_MACRO_PARM && CurToken != T_MACRO_VAR_PARM ) {
                CErr1( ERR_MUST_BE_MACRO_PARM );
                MTOK( MacroOffset + mlen - sizeof( TOKEN ) ) = T_SHARP;
            }
            prev_non_ws_token = CurToken;
        }
        prev_token = CurToken;
        CurToken = ScanToken();
        MacroOverflow( mlen + len, mlen );
        MacroCopy( TokenBuf, MacroOffset + mlen, len );
        mlen += len;
    }
    if( prev_non_ws_token == T_MACRO_SHARP ) {
        CErr1( ERR_MUST_BE_MACRO_PARM );
    }
    if( prev_token == T_WHITE_SPACE ) {
        MTOKDEC( mlen );
    }
    MacroOverflow( mlen + sizeof( TOKEN ), mlen );
    MTOK( MacroOffset + mlen ) = T_NULL;
    MTOKINC( mlen );
    if( prev_non_ws_token == T_SHARP_SHARP ) {
        CErr1( ERR_MISPLACED_SHARP_SHARP );
    }
    mentry->macro_len = mlen;
    MacLkAdd( mentry, mlen, mflags );
    FreeMEntry( mentry );
    MacroSize += mlen;
}
Ejemplo n.º 15
0
static void PPFlush2EOL( void )
{
    while( CurToken != T_NULL && CurToken != T_EOF ) {
        PPNextToken();
    }
}
Ejemplo n.º 16
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 );
}
Ejemplo n.º 17
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 );
}