asmdata.c

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

C
896
字号
/****************************************************************************
*
*                            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:  data directive DB,DW,DD,... and structure processing
*
****************************************************************************/


#include "asmglob.h"

#include "asmdefs.h"
#include "asmsym.h"
#include "asmins.h"
#include "asmexpnd.h"
#include "tbyte.h"
#include "asmfixup.h"

#if defined( _STANDALONE_ )
  #include "directiv.h"
#endif

#ifndef min
#define min(x,y) (((x) < (y)) ? (x) : (y))
#endif

/* structure stuff from asmstruct */
extern int              InitializeStructure( asm_sym *, asm_sym *, int );
extern int              AddFieldToStruct( int );
extern int              GetStructSize( asm_sym * );

#if defined( _STANDALONE_ )

extern int              ChangeCurrentLocation( bool, int_32, bool );
extern int              SymIs32( struct asm_sym *sym );

/* static globals */
/* is this data element a field in a structure definition? */
static bool             struct_field;
/* is this the first initializer for this field? */
static bool             first;

#endif

static int dup_array( asm_sym *sym, asm_sym *struct_sym, int start_pos, unsigned no_of_bytes );

static bool             More_Array_Element = FALSE;
static unsigned         Last_Element_Size;

/* data initialization stuff */

static void little_endian( char *string, unsigned no_of_bytes )
/*************************************************************/
/* convert a string into little endian format - ( LSB 1st, LSW 1st ... etc ) */
{
    if( no_of_bytes >= 2 ) {
        strrev( string );
    }
    return;
}

static void output_float( char index, unsigned no_of_bytes, char negative )
/*************************************************************************/
{
    double              double_value;
    float               float_value;
    char                *char_ptr;
    uint_8              count;
    TB_LD               tbyte;

    if( no_of_bytes == BYTE_10 ) {
        char_ptr = (char *)strtotb( AsmBuffer[index]->string_ptr, &tbyte, negative );
    } else {
        double_value = strtod( AsmBuffer[index]->string_ptr, NULL );
        if( negative )
            double_value *= -1;
        switch( no_of_bytes ) {
        case BYTE_1:
        case BYTE_2:
#if defined( _STANDALONE_ )
            AsmWarn( 4, FLOAT_OPERAND );
#endif
            char_ptr = (char *)&AsmBuffer[index]->value;
            break;
        case BYTE_4:
            float_value = double_value;
            char_ptr = (char *)&float_value;
            break;
        case BYTE_8:
            char_ptr = (char *)&double_value;
            break;
        }
    }

    count = 0;
    while( count < no_of_bytes ) {
        AsmDataByte( *char_ptr );
        char_ptr++;
        count++;
    }
    return;
}

#if defined( _STANDALONE_ )
static void update_sizes( asm_sym *sym, bool first, unsigned no_of_bytes )
/************************************************************************/
{
    sym->total_length++;
    sym->total_size += no_of_bytes;
    if( first ) {
        sym->first_length++;
        sym->first_size += no_of_bytes;
    }
}
#endif

static int array_element( asm_sym *sym, asm_sym *struct_sym, int start_pos, unsigned no_of_bytes )
/************************************************************************************************/
/*
- parse an array and initialize the number;
- call by dup_array() only;
*/
{
    int                 cur_pos = start_pos;
    char                count;
    char                *char_ptr;
    char                negative = FALSE;

#if defined( _STANDALONE_ )
    asm_sym             *the_struct;
    int                 tmp;

    the_struct = (asm_sym*)Definition.curr_struct;

    if( sym != NULL ) {
        sym->count++;
    }
#endif

    for( cur_pos = start_pos;
        ( cur_pos < Token_Count ) && ( AsmBuffer[cur_pos]->token != T_FINAL );
        cur_pos++ ) {
#if defined( _STANDALONE_ )
        if( AsmBuffer[cur_pos]->token == T_RES_ID )
            continue;
        tmp = cur_pos;
        if( check_override( &tmp ) == ERROR )
            return( ERROR );
        cur_pos = tmp;
#endif
        if(( cur_pos == Token_Count - 1 )
            && ( AsmBuffer[cur_pos]->token == T_CL_BRACKET ))
            break;
        switch( AsmBuffer[cur_pos]->token ) {
        case T_QUESTION_MARK:
            if( cur_pos != start_pos ) {
                if( AsmBuffer[cur_pos - 1]->token != T_COMMA ) {
                    AsmError( EXPECTING_COMMA );
                    return( ERROR );
                }
            }
#if defined( _STANDALONE_ )
            if( !struct_field ) {
                ChangeCurrentLocation( TRUE, no_of_bytes,
                      ( ( CurrSeg != NULL ) && SEGISCODE( CurrSeg ) ) );
            } else {
                Definition.curr_struct->e.structinfo->size += no_of_bytes;
                the_struct->total_size += no_of_bytes;
                the_struct->total_length++;
                the_struct->first_size += no_of_bytes;
                the_struct->first_length++;
            }

            if( sym && Parse_Pass == PASS_1 ) {
                update_sizes( sym, first, no_of_bytes );
            }
#else
            count = 0;
            while( count < no_of_bytes ) {
                AsmDataByte( 0 );
                count++;
            }
#endif
            break;
        case T_MINUS:
            switch( AsmBuffer[cur_pos+1]->token ) {
            case T_NUM:
                AsmBuffer[cur_pos+1]->value *= -1;
                AsmBuffer[cur_pos]->token = T_PLUS;
                break;
            case T_FLOAT:
                negative = TRUE;
                break;
            default:
                AsmError( EXPECTING_NUMBER );
                return( ERROR );
            }
            break;
        case T_PLUS:
        case T_DOT:
            break; // go around again
        case T_NUM:
        case T_FLOAT:
            if( AsmBuffer[cur_pos+1]->token == T_RES_ID &&
                AsmBuffer[cur_pos+1]->value == T_DUP ) {
                cur_pos = dup_array( sym, struct_sym, cur_pos, no_of_bytes );
                if( cur_pos == ERROR )
                    return( ERROR );
                break;
            }

            if( cur_pos != start_pos ) {
                switch( AsmBuffer[cur_pos - 1]->token ) {
                case T_COMMA:
                    break;
                case T_PLUS:
                case T_MINUS:
                    if( AsmBuffer[cur_pos - 2]->token == T_COMMA )
                        break;
                    if( cur_pos - 1 == start_pos )
                        break;
                default:
                    AsmError( EXPECTING_COMMA );
                    return( ERROR );
                }
            }
            if( AsmBuffer[cur_pos]->token == T_FLOAT ) {
                output_float( cur_pos, no_of_bytes, negative );
                negative = FALSE;
                break;
            }
            count = 0;
            char_ptr = AsmBuffer[cur_pos]->bytes;
#if defined( _STANDALONE_ )
            if( sym && Parse_Pass == PASS_1 ) {
                update_sizes( sym, first, no_of_bytes );
            }
            if( !struct_field ) {
#endif
                while( count < no_of_bytes ) {
                    AsmDataByte( *(char_ptr++) );
                    count++;
                }
#if defined( _STANDALONE_ )
            } else {
                if( the_struct == NULL )
                    break;
                Definition.curr_struct->e.structinfo->size += no_of_bytes;
                update_sizes( the_struct, first, no_of_bytes );
            }
#endif
            break;
        case T_COMMA:
#if defined( _STANDALONE_ )
            first = FALSE;
#endif
            if( cur_pos != start_pos ) {
                if( AsmBuffer[cur_pos - 1]->token == T_COMMA ) {
                    AsmError( EXPECTING_NUMBER );
                    return( ERROR );
                    /********SHOULD WE DO IT THIS WAY?*********
                    for( count = 0; count < no_of_bytes; count++ ) {
                    AsmDataByte( 0x00 );
                    }
                    ******************************************/
                }
            } else {
                AsmError( EXPECTING_NUMBER );
                return( ERROR );
            }
            if( cur_pos == ( Token_Count - 1 ) ) {
                More_Array_Element = TRUE;
                Last_Element_Size = no_of_bytes;
            }
            break;
        case T_STRING:
#if defined( _STANDALONE_ )
            if( struct_sym != NULL ) {
                InitializeStructure( sym, struct_sym, cur_pos );
                break;
            }
#endif
            if( no_of_bytes != 1 ) {
                if( AsmBuffer[cur_pos]->value > no_of_bytes ) {
                    AsmError( INITIALIZER_OUT_OF_RANGE );
                    return( ERROR );
                }
            }
            count = 0;
            char_ptr = AsmBuffer[cur_pos]->string_ptr;

            /* anything bigger than a byte must be stored in little-endian
            * format -- LSB first */
            little_endian( char_ptr, no_of_bytes );
#if defined( _STANDALONE_ )
            if( no_of_bytes == 1 && struct_field ) {
                no_of_bytes = AsmBuffer[cur_pos]->value;
            }
            if( sym && Parse_Pass == PASS_1 ) {
                update_sizes( sym, first, no_of_bytes );
            }
            if( !struct_field ) {
#endif
                while( count < AsmBuffer[cur_pos]->value ) {
                    AsmDataByte( *char_ptr );
                    char_ptr++;
                    count++;
                }
                while( count < no_of_bytes ) {
                    AsmDataByte( 0 );
                    char_ptr++;
                    count++;
                }
#if defined( _STANDALONE_ )
            } else {
                if( the_struct == NULL )
                    break;
                Definition.curr_struct->e.structinfo->size += no_of_bytes;
                update_sizes( the_struct, first, no_of_bytes );
            }
#endif
            break;
        case T_ID: {
            int i;
            int fixup_type;
            asm_sym *init_sym;
            char *ptr;
            long data = 0;
            struct asmfixup     *fixup;
            /* temporary test .. if this works, combine code for id & resid */
#if defined( _STANDALONE_ )
            i = ++cur_pos;
            if( check_override( &i ) == ERROR ) {
                return( ERROR );
            }
            i--;
            cur_pos = i;

            switch( ExpandSymbol( i, FALSE ) ) {
            case ERROR:
                return( ERROR );
            case STRING_EXPANDED:
                continue;
            }
#endif

            init_sym = AsmLookup( AsmBuffer[cur_pos]->string_ptr );

            if( init_sym == NULL )
                return( ERROR );

#if defined( _STANDALONE_ )
            switch( init_sym->state ) {
            case SYM_STRUCT_FIELD:
                AsmBuffer[cur_pos]->token = T_NUM;
                AsmBuffer[cur_pos]->value = init_sym->offset;
                continue;
            case SYM_GRP:
            case SYM_SEG:
                fixup_type = FIX_SEG;
                break;
            default:
#endif
                switch( no_of_bytes ) {
                case 1:
                    AsmError( OFFSET_TOO_SMALL ); // fixme
                    return( ERROR );
                case 2:
                    fixup_type = FIX_OFF16;
                    break;
                case 4:
                    if( Code->use32 ) {
                        fixup_type = FIX_OFF32;
                    } else {
                        fixup_type = FIX_PTR16;
                    }
                    break;
                case 6:
                    // fixme -- this needs work .... check USE_32, etc
                    fixup_type = FIX_PTR32;
                    Code->info.opnd_type[OPND1] = OP_J48;
                    break;
                default:
                    AsmError( NOT_IMPLEMENTED );
                    return( ERROR );
                }
#if defined( _STANDALONE_ )
                /* switch( init_sym->state ) from above */
            }
            find_frame( init_sym );
#endif
            fixup = AddFixup( init_sym, fixup_type, OPTJ_NONE );
            //          if( fixup == NULL ) return( ERROR );
            // fixme
            InsFixups[OPND1] = fixup;
            data += fixup->offset;

            for( cur_pos++;
                ( cur_pos < Token_Count ) && ( AsmBuffer[cur_pos]->token != T_FINAL )
                    && ( AsmBuffer[cur_pos]->token != T_COMMA )
                    && ( AsmBuffer[cur_pos]->token != T_CL_BRACKET );
                cur_pos++ ) {
                switch( AsmBuffer[cur_pos]->token ) {
                case T_PLUS:
                case T_DOT:
                case T_OP_SQ_BRACKET:
                    break;
#if defined( _STANDALONE_ )
                case T_ID:
                    init_sym = AsmLookup( AsmBuffer[cur_pos]->string_ptr );
                    data += init_sym->offset;
                    break;
#endif
                case T_MINUS:
                    if( AsmBuffer[cur_pos+1]->token != T_NUM ) {
                        AsmError( EXPECTING_NUMBER );
                        return( ERROR );
                    }
                    AsmBuffer[cur_pos+1]->value *=-1;
                    break;
                case T_NUM:
                    data += AsmBuffer[cur_pos]->value;
                }
            }

#if defined( _STANDALONE_ )

⌨️ 快捷键说明

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