asmeval.c

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

C
2,000
字号
    case T_RES_ID:
    case T_STRING:
    case T_PATH:
    case T_OP_BRACKET:
        return( FALSE );
    }
    return( TRUE );
}

static bool is_unary( int i, char sign )
/**************************************/
/* determine if it is an unary operand */
{
    switch( AsmBuffer[i]->token ) {
    case T_UNARY_OPERATOR:
        return( TRUE );
    case T_INSTR:
        if( AsmBuffer[i]->value == T_NOT )
            return( TRUE );
        break;
    case T_POSITIVE:
    case T_NEGATIVE:
        return( TRUE );
    case '+':
        if( sign ) {
            AsmBuffer[i]->token = T_POSITIVE;
            return( TRUE );
        }
        break;
    case '-':
        if( sign ) {
            AsmBuffer[i]->token = T_NEGATIVE;
            return( TRUE );
        }
        break;
    case T_RES_ID:
        switch( AsmBuffer[i]->value ) {
        case T_BYTE:
        case T_WORD:
        case T_DWORD:
        case T_FWORD:
        case T_QWORD:
        case T_TBYTE:
        case T_OWORD:
        case T_SHORT:
        case T_NEAR:
        case T_FAR:
#if defined( _STANDALONE_ )
        case T_SBYTE:
        case T_SWORD:
        case T_SDWORD:
#endif
        case T_PTR:
            return( TRUE );
        }
        break;
    default:
        break;
    }
    return( FALSE );
}

static bool cmp_token( int i, enum state tok )
/********************************************/
/* compare AsmBuffer[i] and tok */
{
    if( AsmBuffer[i]->token == tok ) {
        return( TRUE );
    } else {
        return( FALSE );
    }
}

static bool check_same( expr_list *tok_1, expr_list *tok_2, int_8 type )
/**********************************************************************/
/* Check if both tok_1 and tok_2 equal type */
{
    if( tok_1->type == type &&
        tok_2->type == type ) {
        return( TRUE );
    } else {
        return( FALSE );
    }
}

static bool check_both( expr_list *tok_1, expr_list *tok_2, int_8 type1, int_8 type2 )
/************************************************************************************/
/* Check if tok_1 == type1 and tok_2 == type2 or vice versa */
{
    if( tok_1->type == type1 &&
        tok_2->type == type2 ) {
        return( TRUE );
    } else if( tok_1->type == type2 &&
               tok_2->type == type1 ) {
        return( TRUE );
    } else {
        return( FALSE );
    }
}

static void index_connect( expr_list *tok_1, expr_list *tok_2 )
/*************************************************************/
/* Connects the register lists */
{
    if( tok_1->base_reg == EMPTY ) {
        if( tok_2->base_reg != EMPTY ) {
            tok_1->base_reg = tok_2->base_reg;
            tok_2->base_reg = EMPTY;
        } else if( ( tok_2->idx_reg != EMPTY ) && ( tok_2->scale == 1 ) ) {
            tok_1->base_reg = tok_2->idx_reg;
            tok_2->idx_reg = EMPTY;
        }
    }
    if( tok_1->idx_reg == EMPTY ) {
        if( tok_2->idx_reg != EMPTY ) {
            tok_1->idx_reg = tok_2->idx_reg;
            tok_1->scale = tok_2->scale;
        } else if( tok_2->base_reg != EMPTY ) {
            tok_1->idx_reg = tok_2->base_reg;
            tok_1->scale = 1;
        }
    }
}

static void MakeConst( expr_list *token )
/***************************************/
{
    if( token->type != EXPR_ADDR )
        return;
    if( token->sym != NULL )
        return;
    token->label = EMPTY;
    if( token->mbr != NULL ) {
#if defined( _STANDALONE_ )
        if( token->mbr->state == SYM_STRUCT_FIELD ) {
        } else if( token->mbr->state == SYM_STRUCT ) {
            token->value += token->mbr->total_size;
            token->mbr = NULL;
        } else {
            return;
        }
#else
        return;
#endif
    }
    if( token->base_reg != EMPTY )
        return;
    if( token->idx_reg != EMPTY )
        return;
    if( token->override != EMPTY )
        return;
    token->instr = EMPTY;
    token->type = EXPR_CONST;
    token->indirect = FALSE;
    token->explicit = FALSE;
    token->mem_type = MT_EMPTY;
}

static void fix_struct_value( expr_list *token )
/**********************************************/
{
#if defined( _STANDALONE_ )
    if( token->mbr != NULL ) {
        if( token->mbr->state == SYM_STRUCT ) {
            token->value += token->mbr->total_size;
            token->mbr = NULL;
        }
    }
#endif
}

static int check_direct_reg( expr_list *token_1, expr_list *token_2 )
/*******************************************************************/
{
    if( ( token_1->type == EXPR_REG ) && ( token_1->indirect == FALSE )
        || ( token_2->type == EXPR_REG ) && ( token_2->indirect == FALSE ) ) {
        return( ERROR );
    } else {
        return( NOT_ERROR );
    }
}

static int calculate( expr_list *token_1, expr_list *token_2, uint_8 index )
/**************************************************************************/
/* Perform the operation between token_1 and token_2 */
{
    struct asm_sym      *sym;
    long                value;

    token_1->string = NULL;

    switch( AsmBuffer[index]->token ) {
    case T_POSITIVE:
        /*
         * The only format allowed is:
         *        + constant
         */

        MakeConst( token_2 );
        if( token_2->type != EXPR_CONST ) {
            if( error_msg )
                AsmError( POSITIVE_SIGN_CONSTANT_EXPECTED );
            token_1->type = EXPR_UNDEF;
            return( ERROR );
        }
        token_1->type = EXPR_CONST;
        token_1->value = token_2->value;
        break;
    case T_NEGATIVE:
        /*
         * The only format allowed is:
         *        - constant
         */

        MakeConst( token_2 );
        if( token_2->type != EXPR_CONST ) {
            if( error_msg )
                AsmError( NEGATIVE_SIGN_CONSTANT_EXPECTED );
            token_1->type = EXPR_UNDEF;
            return( ERROR );
        }
        token_1->type = EXPR_CONST;
        token_1->value = -token_2->value;
        break;
    case '+':
        /*
         * The only formats allowed are:
         *        constant + constant
         *        constant + address
         *         address + register       ( only inside [] )
         *        register + register       ( only inside [] )
         *        register + constant       ( only inside [] )
         *        address  + address        ( only inside [] )
         */

        if( check_direct_reg( token_1, token_2 ) == ERROR ) {
            if( error_msg )
                AsmError( ILLEGAL_USE_OF_REGISTER );
            token_1->type = EXPR_UNDEF;
            return( ERROR );
        }
        if( check_same( token_1, token_2, EXPR_CONST ) ) {

            token_1->value += token_2->value;

        } else if( check_same( token_1, token_2, EXPR_ADDR ) ) {

            fix_struct_value( token_1 );
            fix_struct_value( token_2 );
            index_connect( token_1, token_2 );
            token_1->indirect |= token_2->indirect;
            if( token_1->sym != NULL ) {
                if( token_2->sym != NULL ) {
                    if( error_msg )
                        AsmError( SYNTAX_ERROR );
                    token_1->type = EXPR_UNDEF;
                    return( ERROR );
                }
            } else if( token_2->sym != NULL ) {
                token_1->label = token_2->label;
                token_1->sym = token_2->sym;
            }
            token_1->value += token_2->value;

        } else if( check_both( token_1, token_2, EXPR_CONST, EXPR_ADDR ) ) {

            if( token_1->type == EXPR_CONST ) {
                token_2->value += token_1->value;
                token_2->indirect |= token_1->indirect;
                if( token_1->explicit ) {
                    token_2->explicit |= token_1->explicit;
                    token_2->mem_type = token_1->mem_type;
                }
                TokenAssign( token_1, token_2 );
            } else {
                token_1->value += token_2->value;
            }
            fix_struct_value( token_1 );

        } else if( check_both( token_1, token_2, EXPR_ADDR, EXPR_REG ) ) {

            if( token_1->type == EXPR_REG ) {
                if( token_2->instr != EMPTY ) {
                    if( error_msg )
                        AsmError( LABEL_IS_EXPECTED );
                    token_1->type = EXPR_UNDEF;
                    return( ERROR );
                }
                index_connect( token_2, token_1 );
                token_2->indirect |= token_1->indirect;
                TokenAssign( token_1, token_2 );
            } else {
                index_connect( token_1, token_2 );
                token_1->indirect |= token_2->indirect;
            }
            fix_struct_value( token_1 );

        } else if( check_same( token_1, token_2, EXPR_REG ) ) {

            index_connect( token_1, token_2 );
            token_1->indirect |= token_2->indirect;
            token_1->type = EXPR_ADDR;

        } else if( check_both( token_1, token_2, EXPR_CONST, EXPR_REG ) ) {

            if( token_2->type == EXPR_REG ) {
                token_1->base_reg = token_2->base_reg;
                token_1->idx_reg = token_2->idx_reg;
                token_2->base_reg = EMPTY;
                token_2->idx_reg = EMPTY;
            }
            token_1->value += token_2->value;
            token_1->indirect |= token_2->indirect;
            token_1->type = EXPR_ADDR;
        } else {
            /* Error */
            if( error_msg )
                AsmError( ADDITION_CONSTANT_EXPECTED );
            token_1->type = EXPR_UNDEF;
            return( ERROR );
        }
        break;
    case T_DOT:
        /*
         * The only formats allowed are:
         *        register . address       ( only inside [] )
         *        address  . address
         *        address  . constant
         */

        if( check_direct_reg( token_1, token_2 ) == ERROR ) {
            if( error_msg )
                AsmError( ILLEGAL_USE_OF_REGISTER );
            token_1->type = EXPR_UNDEF;
            return( ERROR );
        }
        if( check_same( token_1, token_2, EXPR_ADDR ) ) {

            index_connect( token_1, token_2 );
            token_1->indirect |= token_2->indirect;
            if( token_1->sym != NULL ) {
                if( token_2->sym != NULL ) {
                    if( error_msg )
                        AsmError( SYNTAX_ERROR );
                    token_1->type = EXPR_UNDEF;
                    return( ERROR );
                }
            } else if( token_2->sym != NULL ) {
                token_1->label = token_2->label;
                token_1->sym = token_2->sym;
            }
            if( token_2->mbr != NULL ) {
                token_1->mbr = token_2->mbr;
            }
            token_1->value += token_2->value;
            if( token_1->explicit == FALSE ) {
                token_1->mem_type = token_2->mem_type;
            }

        } else if( check_both( token_1, token_2, EXPR_CONST, EXPR_ADDR ) ) {

            if( token_1->type == EXPR_CONST ) {
                token_2->indirect |= token_1->indirect;
                token_2->value += token_1->value;
                TokenAssign( token_1, token_2 );
            } else {
                token_1->value += token_2->value;
            }

        } else if( check_both( token_1, token_2, EXPR_ADDR, EXPR_REG ) ) {

            if( token_1->type == EXPR_REG ) {
                if( token_2->instr != EMPTY ) {
                    if( error_msg )
                        AsmError( LABEL_IS_EXPECTED );
                    token_1->type = EXPR_UNDEF;
                    return( ERROR );
                }
                index_connect( token_2, token_1 );
                token_2->indirect |= token_1->indirect;
                TokenAssign( token_1, token_2 );
            } else {
                index_connect( token_1, token_2 );
                token_1->indirect |= token_2->indirect;
            }

        } else if( check_both( token_1, token_2, EXPR_CONST, EXPR_REG ) ) {

            if( token_2->type == EXPR_REG ) {
                token_1->base_reg = token_2->base_reg;
                token_1->idx_reg = token_2->idx_reg;
                token_2->base_reg = EMPTY;
                token_2->idx_reg = EMPTY;
            }
            token_1->value += token_2->value;
            token_1->indirect |= token_2->indirect;
            token_1->type = EXPR_ADDR;
        } else {
            /* Error */
            if( error_msg )

⌨️ 快捷键说明

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