⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmac1.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Macro processing, part one.
*
****************************************************************************/


#include "cvars.h"
#include "scan.h"


#define T_UNEXPANDABLE_ID       T_LAST_TOKEN

struct  tokens {
        struct  tokens  *next;
        int     length;
        char    buf[1];
};

typedef struct macro_token {
        struct macro_token *next;
        byte    token;
        char    data[1];
} MACRO_TOKEN;

typedef struct macro_arg {
        char    *arg;
} MACRO_ARG;

typedef struct nested_macros {
        struct nested_macros *next;
        MEPTR   mentry;
        MACRO_ARG *macro_parms;
        char    rescanning;
        char    substituting_parms;
} NESTED_MACRO;

static NESTED_MACRO *NestedMacros;
static MACRO_TOKEN  *TokenList;
static MACRO_TOKEN  *MacroExpansion();
static MACRO_TOKEN  *NestedMacroExpansion( int );

static int MacroBeingExpanded ( MEPTR mentry );

local void SaveParm( MEPTR      mentry,
                     int        i,
                     int        parm_cnt,
                     MACRO_ARG  *macro_parms,
                     struct tokens *token_list,
                     int        total );

struct special_macro_names {
        char    *name;
        int     value;
 };
static struct special_macro_names  SpcMacros[] = {
        {"__LINE__",     MACRO_LINE},
        {"__FILE__",     MACRO_FILE},
        {"__DATE__",     MACRO_DATE},
        {"__TIME__",     MACRO_TIME},
        {"__STDC__",     MACRO_STDC},
        {NULL,       0}
 };


static MEPTR  MKSpcMacEntry( struct special_macro_names *mac )
{
    int         macro_len;
    MEPTR       mentry;

    macro_len = sizeof( MEDEFN ) + strlen( mac->name );
    mentry = (MEPTR)  CMemAlloc( macro_len );
    mentry->macro_defn = 0; /* indicate special macro */
    mentry->macro_len = macro_len;
    mentry->parm_count = mac->value;
    strcpy( mentry->macro_name, mac->name );
    return( mentry );
}

void MacroInit(void)
{
    int         i;
    struct special_macro_names *mac;
    MEPTR       mentry;

    MTokenLen = 0;
    MacroCount = 0;
    MacroPtr = NULL;
    CppStackInit();
    NestedMacros = NULL;
    TokenList = NULL;
    UndefMacroList = NULL;                              /* 26-may-94 */
    InitialMacroFlag = MACRO_DEFINED_BEFORE_FIRST_INCLUDE;
    AllocMacroSegment( 0x1000 );
    MacHash = (MEPTR *)MacroSegment;
    MacroOffset = MacroSegment + MACRO_HASH_SIZE * sizeof(MEPTR);
    for( i=0; i < MACRO_HASH_SIZE; ++i ) {
        MacHash[i] = NULL;
    }
    for( mac = SpcMacros; mac->name; ++mac ) {
        mentry = MKSpcMacEntry( mac );
        MacroAdd( mentry, NULL, 0, 0 );
    }
    TimeInit(); /* grab time and date for __TIME__ and __DATE__ */
}

static struct special_macro_names  SpcMacroCompOnly[] = {
        {"__FUNCTION__", MACRO_FUNC},
        {"__func__", MACRO_FUNC},
        {NULL,       0}
 };

void MacroAddComp(void)
{
    struct special_macro_names *mac;
    MEPTR       mentry;

    for( mac = SpcMacroCompOnly; mac->name; ++mac ) {
        mentry = MKSpcMacEntry( mac );
        MacroAdd( mentry, NULL, 0, 0 );
    }
}

void MacroFini(void)
{

    CppStackFini();
    MacroPurge();
}


void MacroPurge(void)
{
#if 0
    int         i;
    MEPTR       mentry;

    for( i = 0; i < MACRO_HASH_SIZE; ++i ) {
        for( ; mentry = MacHash[i]; ) {
            MacHash[i] = mentry->next_macro;
            CMemFree( mentry );
        }
    }
#endif
}

static void DeleteNestedMacro(void)
{
    MEPTR       mentry;
    NESTED_MACRO *nested;
    MACRO_ARG   *macro_parms;
    int         i;

    nested = NestedMacros;
    if( nested != NULL ) {
        NestedMacros = nested->next;
        macro_parms =  nested->macro_parms;
        mentry = nested->mentry;
        CMemFree( nested );
        i = mentry->parm_count - 1;
        if( i > 0  &&  macro_parms != NULL ) {
            do {
                --i;
                CMemFree( macro_parms[i].arg );
            } while( i != 0 );
            CMemFree( macro_parms );
        }
    }
}

void GetMacroToken(void)
{
    MACRO_TOKEN *mtok;
    unsigned    i;
    char        *buf;
    struct {
        unsigned keep_token : 1;
        unsigned next_token : 1;
    } flag;

    buf = Buffer;
    CurToken = T_NULL;
    for(;;) {
        flag.keep_token = FALSE;
        flag.next_token = FALSE;
        mtok = TokenList;
        if( mtok == NULL ) {
            MacroPtr = NULL;
            break;
        }
        CurToken = mtok->token;
        i = 0;
        while( (buf[i] = mtok->data[i]) )i++;
        switch( CurToken ) {
        case T_UNEXPANDABLE_ID:
            if( ! CompFlags.doing_macro_expansion ) {
                CalcHash( buf, i );
                CurToken = KwLookup( buf );
            }
            break;
        case T_ID:
        case T_SAVED_ID:
            CalcHash( buf, i );
            if( CompFlags.doing_macro_expansion ) {     /* 04-nov-94 */
                CurToken = T_ID;
            } else {
                CurToken = KwLookup( buf );
            }
            break;
        case T_CONSTANT:
            ReScanInit( mtok->data );
            ReScanToken();
            break;
        case T_PPNUMBER:
            ReScanInit( mtok->data );
            if( ReScanToken() ){  // didn't finish string bad boy
                char *tcur;
                char *tbeg;

                tbeg = mtok->data;
                tcur = ReScanPos();
                // ppnumber is quite general so it may absorb multiple tokens
                // overlapping src & dst so do our own copy;
                for(;;){
                    *tbeg = *tcur;
                    if( *tcur == '\0' )break;
                    ++tcur;
                    ++tbeg;
                }
                flag.keep_token = TRUE;
            }
            break;
        case T_LSTRING:
            CurToken = T_STRING;
            CompFlags.wide_char_string = 1;
            CLitLength = i + 1;
            break;
        case T_STRING:
            CompFlags.wide_char_string = 0;
            CLitLength = i + 1;
            break;
        case T_BAD_CHAR:
            break;
        case T_NULL:
            if( mtok->data[0] == 'Z' ) {    // if end of macro
                DeleteNestedMacro();
            }
            flag.next_token = TRUE;
            break;
        default:
            break;
        }
        if( ! flag.keep_token ) {
            TokenList = mtok->next;
            CMemFree( mtok );
        }
        if( ! flag.next_token ) {
            break;
        }
    }
}

/* returns Dynamically allocated buffer with expanded macro */
local char *ExpandMacroToken( void )
{
    size_t       i, len;
    char        *p;
    char        *buf;

    len = 0;
    switch( *MacroPtr ) {
    case T_CONSTANT:
    case T_PPNUMBER:
    case T_ID:
    case T_UNEXPANDABLE_ID:
    case T_SAVED_ID:
    case T_BAD_TOKEN:                                   /* 07-apr-91 */
        p = ++MacroPtr;
        len = strlen( p );
        MacroPtr += len;
        break;
    case T_LSTRING:                                     /* 15-may-92 */
        len = 1;
    case T_STRING:                                      /* 15-dec-91 */
        ++MacroPtr;
        len += strlen( MacroPtr ) + 3;
        buf = CMemAlloc( len );
        i = 0;
        if ( MacroPtr[-1] == T_LSTRING )
            buf[i++] = 'L';
        buf[i++] = '"';
        while( (buf[i] = *MacroPtr++) )  ++i;
        buf[i++] = '"';
        buf[i] = '\0';
        return( buf );
    default:                                            /* 28-mar-90 */
        p = Tokens[ *MacroPtr++ ];
        len = strlen( p );
        break;
    }
    buf = NULL;
    if( len > 0 ) {
        len++;
        buf = CMemAlloc( len );
        memcpy( buf, p, len );
    }
    return( buf );
}


int SpecialMacro( MEPTR mentry )
{
    char        *p;
    char        *bufp;

    CompFlags.wide_char_string = 0;                     /* 16-dec-91 */
    switch( mentry->parm_count ) {
    case MACRO_LINE:
        utoa( TokenLine, Buffer, 10 );
        Constant = TokenLine;
        ConstType = TYPE_INT;
        return( T_CONSTANT );
    case MACRO_FILE:
        if( SrcFile == NULL ) {                 /* 26-sep-94 */
            // SrcFile can be NULL if user is missing a closing ')' on
            // a macro to contains a reference to __FILE__.
            // We end up scanning all the way to the end of the file
            // causing SrcFile to become NULL.
            p = "";
        } else {
            p = SrcFile->src_name;
        }
        bufp = Buffer;
        for(;;) {
            *bufp++ = *p;
            if( *p == '\0' ) break;
            if( *p == '\\' ) *bufp++ = '\\';
            ++p;
        }
        CLitLength = bufp - Buffer;
        return( T_STRING );
    case MACRO_DATE:
        CLitLength = 12;
        strcpy( Buffer, __Date );
        return( T_STRING );
    case MACRO_TIME:
        CLitLength = 9;
        strcpy( Buffer, __Time );
        return( T_STRING );
    case MACRO_STDC:
        Buffer[0] = '1';
        Buffer[1] = '\0';
        Constant = 1;
        ConstType = TYPE_INT;
        return( T_CONSTANT );
    case MACRO_FUNC:
        p = "";
        if( CurFunc != NULL ){
            if( CurFunc->name != NULL ){
                p = CurFunc->name;
            }
        }
        CLitLength = strlen( p ) +1;
        strcpy( Buffer, p );
        return( T_STRING );
    default:
        return( 0 ); // shut up the compiler
    }
}


local int NextMToken()
{
    CompFlags.doing_macro_expansion = 1;
    GetMacroToken();
    if( CurToken == T_NULL ) {
        CurToken = ScanToken();
    }
    CompFlags.doing_macro_expansion = 0;
    return( CurToken );
}

void EnlargeBuffer( size_t size )
{
    char       *newBuffer;

    newBuffer = CMemAlloc( size );
    memcpy( newBuffer, Buffer, BufSize );
    CMemFree( Buffer );
    Buffer = newBuffer;
    newBuffer = CMemAlloc( size );
    memcpy( newBuffer, TokenBuf, BufSize );
    CMemFree( TokenBuf );
    TokenBuf = newBuffer;
    BufSize = size;
}

static MACRO_ARG *CollectParms(void)
{
    MEPTR       mentry;
    int         j;
    int         bracket;
    TOKEN       tok;
    TOKEN       prev_tok;
    int         parm_cnt;
    int         total;  /* total # of bytes in token sequence */
    int         ppscan_mode;
    MACRO_ARG   *macro_parms;
    struct tokens **token_tail;
    auto        struct tokens *token_head;

    macro_parms = NULL;
    mentry = NextMacro;
    if( mentry->parm_count != 0 ) { /* if () expected */
        ppscan_mode = InitPPScan();             // enable T_PPNUMBER tokens
        if( mentry->parm_count > 1 ) {
            macro_parms = (MACRO_ARG *)CMemAlloc( (mentry->parm_count - 1) *
                                    sizeof( MACRO_ARG ) );
        }
        parm_cnt = 0;
        do {
            tok = NextMToken();
        } while( tok == T_WHITE_SPACE );
        /* tok will now be a '(' */
        bracket = 0;
        token_tail = &token_head;
        token_head = NULL;
        total = 0;
        MTokenLen = 0;
        for( ;; ) {
            prev_tok = tok;
            do {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -