asmeval.c

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

C
2,000
字号
/****************************************************************************
*
*                            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:  WASM expression evaluator.
*
****************************************************************************/


#include "asmglob.h"

#include "asmins.h"
#include "asmeval.h"
#include "asmdefs.h"

#if defined( _STANDALONE_ )
#include "myassert.h"
#else
//  FIXME!!
#define myassert(x)
#endif

extern void             DefFlatGroup( void );

static int              TakeOut[ MAX_TOKEN ];
static int              TokCnt;

static struct asm_tok   Store[ MAX_TOKEN ];

static int              op_sq_bracket_level;
static bool             error_msg;

enum process_flag {
    PROC_BRACKET,
    PROC_OPERAND
};

static int evaluate( expr_list *, int *, int, enum process_flag, bool (*)(int) );

static void init_expr( expr_list *new )
/*************************************/
{
    new->empty    = TRUE;
    new->type     = EMPTY;
    new->label    = EMPTY;
    new->override = EMPTY;
    new->instr    = EMPTY;
    new->base_reg = EMPTY;
    new->idx_reg  = EMPTY;
    new->indirect = FALSE;
    new->explicit = FALSE;
    new->abs      = FALSE;
    new->mem_type = MT_EMPTY;
    new->value    = 0;
    new->scale    = 1;
    new->string   = NULL;
    new->sym      = NULL;
    new->mbr      = NULL;
}

static void TokenAssign( expr_list *t1, expr_list *t2 )
/*****************************************************/
{
    t1->empty    = t2->empty;
    t1->type     = t2->type;
    t1->label    = t2->label;
    t1->override = t2->override;
    t1->instr    = t2->instr;
    t1->base_reg = t2->base_reg;
    t1->idx_reg  = t2->idx_reg;
    t1->indirect = t2->indirect;
    t1->explicit = t2->explicit;
    t1->abs      = t2->abs;
    t1->mem_type = t2->mem_type;
    t1->value    = t2->value;
    t1->scale    = t2->scale;
    t1->string   = t2->string;
    t1->sym      = t2->sym;
    t1->mbr      = t2->mbr;
}

#define PLUS_PRECEDENCE 9

static int get_precedence( int i )
/********************************/
{
    /* The following table is taken verbatim from MASM 6.1 Programmer's Guide,
     * page 14, Table 1.3. Sadly, it flatly contradicts QuickHelp online
     * documentation shipped with said product and should not be taken as gospel.
     */

//    1             (), []
//    2             LENGTH, SIZE, WIDTH, MASK, LENGTHOF, SIZEOF
//    3             . (structure-field-name operator)
//    4             : (segment override operator), PTR
//    5             LROFFSET, OFFSET, SEG, THIS, TYPE
//    6             HIGH, HIGHWORD, LOW, LOWWORD
//    7             +, - (unary)
//    8             *, /, MOD, SHL, SHR
//    9             +, - (binary)
//    10            EQ, NE, LT, LE, GT, GE
//    11            NOT
//    12            AND
//    13            OR, XOR
//    14            OPATTR, SHORT, .TYPE

    /* The following table appears in QuickHelp online documentation for
     * both MASM 6.0 and 6.1. Typical Microsoft mess.
     */

//    1             LENGTH, SIZE, WIDTH, MASK
//    2             (), []
//    3             . (structure-field-name operator)
//    4             : (segment override operator), PTR
//    5             THIS, OFFSET, SEG, TYPE
//    6             HIGH, LOW
//    7             +, - (unary)
//    8             *, /, MOD, SHL, SHR
//    9             +, - (binary)
//    10            EQ, NE, LT, LE, GT, GE
//    11            NOT
//    12            AND
//    13            OR, XOR
//    14            SHORT, OPATTR, .TYPE, ADDR

    switch( AsmBuffer[i]->token ) {
    case T_UNARY_OPERATOR:
        switch( AsmBuffer[i]->value ) {
#if defined( _STANDALONE_ )
        case T_LENGTH:
        case T_SIZE:
        case T_LENGTHOF:
        case T_SIZEOF:
            return( 3 );
#endif
        case T_SEG:
        case T_OFFSET:
            return( 5 );
        }
        break;
    case T_INSTR:
        switch( AsmBuffer[i]->value ) {
        case T_MOD:
        case T_SHL:
        case T_SHR:
            return( 8 );
#if defined( _STANDALONE_ )
        case T_EQ:
        case T_NE:
        case T_LT:
        case T_LE:
        case T_GT:
        case T_GE:
            return( 10 );
#endif
        case T_NOT:
            return( 11 );
        case T_AND:
            return( 12 );
        case T_OR:
        case T_XOR:
            return( 13 );
        }
        break;
    case T_RES_ID:
        switch( AsmBuffer[i]->value ) {
        case T_SHORT:
            return( 14 );
        case T_BYTE:
        case T_WORD:
        case T_DWORD:
        case T_FWORD:
        case T_QWORD:
        case T_TBYTE:
        case T_OWORD:
        case T_NEAR:
        case T_FAR:
#if defined( _STANDALONE_ )
        case T_SBYTE:
        case T_SWORD:
        case T_SDWORD:
#endif
        case T_PTR:
            return( 5 );
        }
        break;
    case T_COLON:
        return( 4 );
    case T_POSITIVE:
    case T_NEGATIVE:
        return( 7 );
    case '*':
    case '/':
        return( 8 );
    case '+':
    case '-':
        return( 9 );
    case T_DOT:
        return( 2 );
    default:
        /**/myassert( 0 );
        break;
    }
    return( ERROR );
}

static int get_operand( expr_list *new, int *start, int end, bool (*is_expr)(int) )
/*********************************************************************************/
{
    char        *tmp;
    int         i = *start;

    init_expr( new );
    switch( AsmBuffer[i]->token ) {
    case T_NUM:
        new->empty = FALSE;
        new->type = EXPR_CONST;
        new->value = AsmBuffer[i]->value;
        break;
    case T_STRING:
        new->empty = FALSE;
        new->type = EXPR_CONST;
        new->string = AsmBuffer[i]->string_ptr;
        new->value = 0;
        for( tmp = new->string; *tmp != '\0'; tmp++ ) {
            new->value <<= 8;
            new->value |= (*tmp);
        }
        break;
    case T_REG:
        new->empty = FALSE;
        new->type = EXPR_REG;
        new->base_reg = i;
        if( op_sq_bracket_level > 0 ) {
            switch( AsmBuffer[i]->value ) {
            case T_EAX:
            case T_EBX:
            case T_ECX:
            case T_EDX:
            case T_EDI:
            case T_ESI:
            case T_EBP:
            case T_ESP:
            case T_BX:
            case T_BP:
            case T_DI:
            case T_SI:
                new->indirect = TRUE;
                break;
            case T_DS:
            case T_CS:
            case T_ES:
            case T_SS:
            case T_FS:
            case T_GS:
                if( AsmBuffer[i+1]->token != T_COLON ) {
                    if( error_msg )
                        AsmError( ILLEGAL_USE_OF_REGISTER );
                    new->type = EXPR_UNDEF;
                    return( ERROR );
                }
                break;
            default:
                if( error_msg )
                    AsmError( ILLEGAL_USE_OF_REGISTER );
                new->type = EXPR_UNDEF;
                return( ERROR );
            }
        } else if( AsmBuffer[i]->value == T_ST ) {

            expr_list   sti;

            // read st(i), put i into idx_reg
            i++;
            switch( AsmBuffer[i]->token ) {
            case T_OP_BRACKET:
            case T_OP_SQ_BRACKET:
            case T_NUM:
                *start = i;
                init_expr( &sti );
                if( evaluate( &sti, start, end, PROC_OPERAND, is_expr ) == ERROR ) {
                    new->type = EXPR_UNDEF;
                    return( ERROR );
                }
                if( sti.type != EXPR_CONST ) {
                    if( error_msg )
                        AsmError( CONSTANT_EXPECTED );
                    new->type = EXPR_UNDEF;
                    return( ERROR );
                }
                new->idx_reg = sti.value;
                return( NOT_ERROR );
            default:
                new->idx_reg = 0; // st = st(0)
                break;
            }
        }
        break;
    case T_ID:
#if defined( _STANDALONE_ )
        if( Parse_Pass == PASS_1 ) {
            new->sym = AsmLookup( AsmBuffer[i]->string_ptr );
            if( new->sym == NULL ) {
                new->type = EXPR_UNDEF;
                return( ERROR );
            }
        } else {
            new->sym = AsmGetSymbol( AsmBuffer[i]->string_ptr );
            if( new->sym == NULL ) {
                if( error_msg )
                    AsmErr( SYMBOL_NOT_DEFINED, AsmBuffer[i]->string_ptr );
                new->type = EXPR_UNDEF;
                return( ERROR );
            }
#if 0
// FIXME !!!!!
// problem with aliases and equ directive
            if( ( new->sym == NULL ) || ( new->sym->state == SYM_UNDEFINED ) ) {
                if( error_msg )
                    AsmErr( SYMBOL_NOT_DEFINED, AsmBuffer[i]->string_ptr );
                new->type = EXPR_UNDEF;
                return( ERROR );
            }
#endif
        }
        if( new->sym != NULL ) {
            if( new->sym->state == SYM_STRUCT ) {
                new->empty = FALSE;
                new->value = new->sym->offset;
                new->mbr = new->sym;
                new->sym = NULL;
                new->type = EXPR_ADDR;
                break;
            } else if( new->sym->state == SYM_STRUCT_FIELD ) {
                new->empty = FALSE;
                new->mem_type = new->sym->mem_type;
                new->value = new->sym->offset;
                new->mbr = new->sym;
                new->sym = NULL;
                new->type = EXPR_ADDR;
                break;
            }
            if( new->sym->mem_type == MT_ABS ) {
                new->abs = TRUE;
            } else {
                new->mem_type = new->sym->mem_type;
            }
        }
#else
        new->sym = AsmLookup( AsmBuffer[i]->string_ptr );
        new->mem_type = new->sym->mem_type;
#endif
        new->empty = FALSE;
        new->type = EXPR_ADDR;
        new->label = i;
        break;
    case T_RES_ID:
        new->sym = AsmLookup( AsmBuffer[i]->string_ptr );
        new->empty = FALSE;
        new->type = EXPR_ADDR;
        new->label = i;
        break;
    default:
        new->type = EXPR_UNDEF;
        return( ERROR );
    }
    (*start)++;
    return( NOT_ERROR );
}

static bool is_optr( int i )
/**************************/
/* determine if it is an operator */
{
    switch( AsmBuffer[i]->token ) {
    case T_REG:
    case T_NUM:
    case T_ID:

⌨️ 快捷键说明

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