cmac1.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,383 行 · 第 1/3 页

C
1,383
字号
/****************************************************************************
*
*                            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 "plusplus.h"
#include "preproc.h"
#include "tokenbuf.h"
#include "errdefns.h"
#include "memmgr.h"
#include "macro.h"
#include "ring.h"
#include "dbg.h"
#include "fmtsym.h"
#include "initdefs.h"
#include "yydriver.h"
#include "carve.h"

#define T_UNEXPANDABLE_ID       T_LAST_TOKEN

typedef struct _tokens TOKEN_LIST;
struct _tokens {
    TOKEN_LIST  *next;
    unsigned    length;
    char        buf[1];
};

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

typedef struct macro_arg {
    char        *arg;
} MACRO_ARG;

typedef struct nested_macros NESTED_MACRO;
struct nested_macros {
    NESTED_MACRO    *next;
    MEPTR           fmentry;
    MACRO_ARG       *macro_parms;
    unsigned        rescanning : 1;
    unsigned        substituting_parms : 1;
};

static carve_t carveNESTED_MACRO;
static NESTED_MACRO *nestedMacros;
static MACRO_TOKEN *scannerTokenList;
static MACRO_TOKEN *internalTokenList;
static unsigned macroDepth;

static MACRO_TOKEN  *macroExpansion( MEPTR, int );
static MACRO_TOKEN  *nestedMacroExpansion( MEPTR, boolean );

#ifdef pick
#undef pick
#endif

#define pick( s, i, f )    { s, i, f },
typedef struct special_macro_name SPECIAL_MACRO_NAME;
static struct special_macro_name {
    char        *name;
    int         value;
    unsigned    flags;
} SpcMacros[] = {
#include "specmac.h"
    { NULL, 0, 0 }
};


static void macroDiagNesting(   // DIAGNOSE NESTING
    void )
{
    NESTED_MACRO* curr;         // - current entry

    for( curr = nestedMacros ; NULL != curr ; curr = curr->next ) {
        MEPTR mdef = curr->fmentry;
        CErr( INF_MACRO_EXPANSION, mdef->macro_name, &mdef->defn );
    }
}


static void macroInit(          // MACRO PROCESSING -- INITIALIZATION
    INITFINI* defn )            // - definition
{
    SPECIAL_MACRO_NAME *mac;

    defn = defn;
    DirectiveInit();
    nestedMacros = NULL;
    scannerTokenList = NULL;
    InitialMacroFlag = MACRO_DEFINED_BEFORE_FIRST_INCLUDE;
    MacroStorageInit();
    for( mac = SpcMacros; mac->name != NULL; ++mac ) {
        MacroSpecialAdd( mac->name, mac->value, mac->flags );
    }
    TimeInit();     /* grab time and date for __TIME__ and __DATE__ */
    carveNESTED_MACRO = CarveCreate( sizeof( NESTED_MACRO ), 16 );
}


static void macroFini(          // MACRO PROCESSING -- COMPLETION
    INITFINI* defn )            // - definition
{
    defn = defn;
    DirectiveFini();
    MacroStorageFini();
#ifndef NDEBUG
    CarveVerifyAllGone( carveNESTED_MACRO, "NESTED_MACRO" );
#endif
    CarveDestroy( carveNESTED_MACRO );
}


INITDEFN( macros, macroInit, macroFini )


static void deleteNestedMacro( void )
{
    MEPTR fmentry;
    NESTED_MACRO *nested;
    MACRO_ARG *macro_parms;
    int i;

    nested = nestedMacros;
    if( nested != NULL ) {
        nestedMacros = nested->next;
        macro_parms =  nested->macro_parms;
        fmentry = nested->fmentry;
        CarveFree( carveNESTED_MACRO, nested );
        i = fmentry->parm_count - 1;
        if( i > 0  &&  macro_parms != NULL ) {
            do {
                --i;
                CMemFree( macro_parms[i].arg );
            } while( i != 0 );
            CMemFree( macro_parms );
        }
    }
}

static unsigned copyMTokToBuffer( MACRO_TOKEN *mtok )
{
    char *s;
    unsigned len;

    s = mtok->data;
    len = strlen( s );
    memcpy( Buffer, s, len + 1 );
    return( len );
}


static MACRO_TOKEN *doGetMacroToken(    // GET NEXT TOKEN
    MACRO_TOKEN *list,          // - list of tokens
    boolean doing_macro_expansion ) // - TRUE ==> doing an expansion
{
    char *token_end;
    MACRO_TOKEN *mtok;
    unsigned i;
    struct {
        unsigned keep_token : 1;
        unsigned next_token : 1;
    } flag;

    CurToken = T_NULL;
    for(;;) {
        flag.keep_token = FALSE;
        flag.next_token = FALSE;
        mtok = list;
        if( mtok == NULL ) {
            CompFlags.use_macro_tokens = FALSE;
            break;
        }
        CurToken = mtok->token;
        i = copyMTokToBuffer( mtok );
        switch( CurToken ) {
        case T_UNEXPANDABLE_ID:
            if( ! doing_macro_expansion ) {
                CurToken = KwLookup( i );
                TokenLen = i;
            }
            break;
        case T_ID:
        case T_SAVED_ID:
            if( doing_macro_expansion ) {
                CurToken = T_ID;
            } else {
                CurToken = KwLookup( i );
            }
            TokenLen = i;
            break;
        case T_BAD_TOKEN:
        case T_CONSTANT:
            ReScanInit( Buffer );
            ReScanToken();
            DbgAssert( mtok->data[ TokenLen ] == '\0' || CurToken == T_BAD_TOKEN );
            break;
        case T_PPNUMBER:
            ReScanInit( Buffer );
            ReScanToken();
            DbgAssert( CurToken != T_STRING && CurToken != T_LSTRING );
            token_end = &(mtok->data[ TokenLen ]);
            if( *token_end != '\0' ) {
                // ppnumber is quite general so it may absorb multiple tokens
                strcpy( mtok->data, token_end );
                flag.keep_token = TRUE;
            }
            break;
        case T_STRING:
        case T_LSTRING:
            TokenLen = i + 1;
            break;
        case T_BAD_CHAR:
            break;
        case T_NULL:
            if( Buffer[0] == 'Z' ) {    // if end of macro
                deleteNestedMacro();
            }
            flag.next_token = TRUE;
            break;
        }
        if( ! flag.keep_token ) {
            list = mtok->next;
            CMemFree( mtok );
        }
        if( ! flag.next_token ) {
            break;
        }
    }
    DumpMacToken();
    return( list );
}

void GetMacroToken(             // GET NEXT TOKEN
    boolean doing_macro_expansion ) // - TRUE ==> doing an expansion
{
    scannerTokenList = doGetMacroToken( scannerTokenList, doing_macro_expansion );
}

static unsigned copySafe( unsigned i, char *m )
{
    for(;;) {
        if( i >= (BUF_SIZE-4) ) {
            CErr1( ERR_TOKEN_TRUNCATED );
            macroDiagNesting();
            Buffer[i] = '\0';
            break;
        }
        if(( Buffer[i] = *m++ ) == 0 ) break;
        ++i;
        if(( Buffer[i] = *m++ ) == 0 ) break;
        ++i;
        if(( Buffer[i] = *m++ ) == 0 ) break;
        ++i;
        if(( Buffer[i] = *m++ ) == 0 ) break;
        ++i;
    }
    return( i );
}

static unsigned expandMacroToken( unsigned i, char *m )
{
    char *p;

    switch( *m ) {
    case T_CONSTANT:
    case T_PPNUMBER:
    case T_ID:
    case T_UNEXPANDABLE_ID:
    case T_SAVED_ID:
    case T_BAD_TOKEN:
        ++m;
        i = copySafe( i, m );
        break;
    case T_LSTRING:
        Buffer[i++] = 'L';
    case T_STRING:
        Buffer[i++] = '"';
        ++m;
        i = copySafe( i, m );
        Buffer[i++] = '"';
        Buffer[i] = '\0';
        break;
    default:
        p = Tokens[ *m ];
        ++m;
        i = copySafe( i, p );
    }
    return( i );
}


static int file_name_copy(       // COPY STRING, ESCAPING ANY BACKSLASHES
    char *dst,                  // - destination
    char const *src )           // - source
{
    char *org = dst;
    while( *src ) {
        if( *src == '\\' ) {
            *dst++ = '\\';
        }
        *dst++ = *src++;
    }
    *dst++ = *src++;
    return( dst - org );
}

#define _FUNCTION_expandable    (CompFlags.cpp_output == 0)

static int genFUNCTION(
    int spec_macro )
{
    SYMBOL sym;
    size_t len;
    VBUF buff;
    char *name;

    DbgAssert( ( spec_macro == MACRO_FUNCTION )
            || ( spec_macro == MACRO_FUNC ) );

    if( ! _FUNCTION_expandable ) {
        name = SpcMacros[ spec_macro ].name;
        len = strlen( name );
        memcpy( Buffer, name, len + 1 );
        TokenLen = len;
        return( T_ID );
    }
    sym = ParseCurrFunction();
    if( sym != NULL ) {
        FormatSymWithTypedefs( sym, &buff );
        len = VStrLen( &buff );
        if( len >= BUF_SIZE ) {
            len = BUF_SIZE;
        }
        memcpy( Buffer, buff.buf, len );
        VbufFree( &buff );
    } else {
        Buffer[0] = '?';
        len = 1;
    }
    Buffer[len] = '\0';
    TokenLen = len + 1;
    return( T_STRING );
}

int SpecialMacro(               // EXECUTE A SPECIAL MACRO
    MEPTR fmentry )             // - macro entry
{
    switch( fmentry->parm_count ) {
    case MACRO_LINE:
        ultoa( TokenLine, Buffer, 10 );
        U32ToU64( TokenLine, &Constant64 );
        ConstType = TYP_SINT;
        return( T_CONSTANT );
    case MACRO_FILE:
        TokenLen = file_name_copy( Buffer, SrcFileNameCurrent() );
        return( T_STRING );
    case MACRO_DATE:
        TokenLen = stpcpy( Buffer, __Date ) - Buffer + 1;
        return( T_STRING );
    case MACRO_TIME:
        TokenLen = stpcpy( Buffer, __Time ) - Buffer + 1;
        return( T_STRING );
    case MACRO_FUNCTION:
    case MACRO_FUNC:
        return( genFUNCTION( fmentry->parm_count ) );
    case MACRO_CPLUSPLUS:
        Buffer[0] = '1';
        Buffer[1] = '\0';
        U32ToU64( 1, &Constant64 );
        ConstType = TYP_SINT;
        return( T_CONSTANT );
    case MACRO_ALT_AND:
        return( T_ALT_AND_AND );
    case MACRO_ALT_BITAND:
        return( T_ALT_AND );
    case MACRO_ALT_AND_EQ:
        return( T_ALT_AND_EQUAL );
    case MACRO_ALT_OR:
        return( T_ALT_OR_OR );
    case MACRO_ALT_BITOR:
        return( T_ALT_OR );
    case MACRO_ALT_OR_EQ:
        return( T_ALT_OR_EQUAL );
    case MACRO_ALT_XOR:
        return( T_ALT_XOR );
    case MACRO_ALT_XOR_EQ:
        return( T_ALT_XOR_EQUAL );
    case MACRO_ALT_NOT:
        return( T_ALT_EXCLAMATION );
    case MACRO_ALT_NOT_EQ:
        return( T_ALT_NE );
    case MACRO_ALT_COMPL:
        return( T_ALT_TILDE );
    }
    return( T_EOF );
}


static int nextMToken( unsigned prev_token )
{
    ppstate_t save_ppstate;

    internalTokenList = doGetMacroToken( internalTokenList, TRUE );
    if( CurToken == T_NULL ) {
        if( ScanOptionalComment() ) {
            CurToken = T_WHITE_SPACE;
        } else {
            if( prev_token != T_WHITE_SPACE ) {
                // at EOL, ChkControl skips white-space for you which
                // is not appropriate at this point (this white-space
                // may be significant)
                // [the prev_token check is req'd because the scanner
                //  will not advance past T_NULL]
                save_ppstate = PPState;
                PPState |= PPS_EOL;
                CurToken = ScanToken( 1 );
                PPState = save_ppstate;
                if( CurToken == T_NULL ) {
                    CurToken = T_WHITE_SPACE;
                }
            } else {
                CurToken = ScanToken( 1 );
            }
        }
    }
    return( CurToken );
}

static void saveParm(
    MEPTR               fmentry,
    int                 parm_cnt,

⌨️ 快捷键说明

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