asdrectv.c

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

C
1,060
字号
/****************************************************************************
*
*                            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:  Assembler directive processing.
*
****************************************************************************/


#include "as.h"

#define MAX_ALIGNMENT   6       // 64 byte alignment

dir_set_flags       AsDirSetOptions;

static bool         autoAlignment;
static bool         getDirOpLine = FALSE; // decides if we'll grab the line
static directive_t  *lastDirective = NULL;


static bool dirHasOperand( directive_t *dir )
//*******************************************
{
    return( dir->num_operands > 0 );
}


static bool dirNumOperandsVerify( dir_opcount actual, dir_opcount wanted )
//************************************************************************
{
    if( actual < wanted ) {
        Error( DIROP_ERR_MISSING, actual );
        return( FALSE );
    }
    if( actual > wanted ) {
        Error( DIROP_ERR_TOO_MANY );
        return( FALSE );
    }
    return( TRUE );
}


#if 0
static bool dirFuncNYI( directive_t *dir, dir_table_enum parm )
//*************************************************************
{
    printf( "Directive '%s' is not yet implemented.\n", dir->dir_sym->name );
    return( TRUE );
}
#endif


static bool dirFuncAlign ( directive_t *dir, dir_table_enum parm )
//****************************************************************
{
    int_32      val;

    parm = parm;
    if( !dirNumOperandsVerify( dir->num_operands, 1 ) ) {
        return( TRUE );
    }
    assert( dir->operand_list->type == DIROP_INTEGER );
    val = NUMBER_INTEGER( dir->operand_list );
    if( val < 0 || val > MAX_ALIGNMENT ) {
        Error( OP_OUT_OF_RANGE, 0 );
        return( TRUE );
    }
    autoAlignment = FALSE;
    CurrAlignment = val;
    return( TRUE );
}


#ifdef _STANDALONE_
static bool dirFuncBSS( directive_t *dir, dir_table_enum parm )
//*************************************************************
{
    static bool dirFuncSwitchSection( directive_t *, dir_table_enum );
    static bool dirFuncStorageAlloc( directive_t *, dir_table_enum );

    if( !dirHasOperand( dir ) ) return( dirFuncSwitchSection( dir, parm ) );
    return( dirFuncStorageAlloc( dir, parm ) ); // ".bss tag, bytes"
}


static bool dirFuncErr( directive_t *dir, dir_table_enum parm )
//*************************************************************
{
    char    *str;

    if( dirHasOperand( dir ) ) {
        assert( dir->num_operands == 1 );
        assert( dir->operand_list->type == DIROP_LINE );
        str = STRING_CONTENT( dir->operand_list );
        if( *str ) Error( GET_STRING, str );
    }
    return( FALSE );    // so that yyparse will terminate
}
#endif


static bool dirFuncIgnore( directive_t *dir, dir_table_enum parm )
//****************************************************************
// Silently ignore this directive...
{
    dir = dir;
    parm = parm;
    return( TRUE );
}


static bool dirFuncNop( directive_t *dir, dir_table_enum parm )
//*************************************************************
{
    uint_32     opcode = INS_NOP;

    dir = dir;
    if( parm == DT_NOP_NOP ) {
#ifdef _STANDALONE_
        ObjEmitData( CurrentSection, (char *)&opcode, sizeof( opcode ), TRUE );
#else
        ObjEmitData( (char *)&opcode, sizeof( opcode ), TRUE );
#endif
        return( TRUE );
    }
#ifdef AS_ALPHA
    assert( parm == DT_NOP_FNOP );
    opcode = INS_FNOP;
#ifdef _STANDALONE_
    ObjEmitData( CurrentSection, (char *)&opcode, sizeof( opcode ), TRUE );
#else
    ObjEmitData( (char *)&opcode, sizeof( opcode ), TRUE );
#endif
    return( TRUE );
#else
    assert( FALSE );
    return( TRUE );
#endif
}


#ifdef _STANDALONE_
static bool dirFuncSetLinkage( directive_t *dir, dir_table_enum parm )
//********************************************************************
{
    sym_handle  sym;

    if( !dirNumOperandsVerify( dir->num_operands, 1 ) ) {
        return( TRUE );
    }
    sym = SYMBOL_HANDLE( dir->operand_list );
    assert( sym != NULL );
    assert( SymClass( sym ) == SYM_LABEL );
    switch( parm ) {
    case DT_LNK_GLOBAL:
        if( SymGetLinkage( sym ) == SL_STATIC ) {
            // Too bad the label is already emitted as static :(
            Warning( GLOBL_DECL_OUT_OF_ORDER );
        } else {
            SymSetLinkage( sym, SL_GLOBAL );
        }
        break;
    default:
        assert( FALSE );
    }
    return( TRUE );
}
#endif


static bool optionString( const char *str, const char *option )
//*************************************************************
{
    const char  *s;
    size_t      n;
    char        c;

    if( strncmp( str, option, n = strlen( option ) ) != 0 ) {
        return( FALSE );
    }
    s = str + n;
    while( c = *s ) {
        // ignore trailing blanks only
        if( c != '\t' && c != ' ' ) return( FALSE );
        ++s;
    }
    return( TRUE );
}


static bool dirFuncSetOption( directive_t *dir, dir_table_enum parm )
//*******************************************************************
{
    char    *str;

    parm = parm;
    if( dirHasOperand( dir ) ) {
        assert( dir->num_operands == 1 );
        assert( dir->operand_list->type == DIROP_LINE );
        str = STRING_CONTENT( dir->operand_list );
        if( optionString( str, "at" ) ) {
            _DirSet( AT );
        } else if( optionString( str, "noat" ) ) {
            _DirUnSet( AT );
        } else if( optionString( str, "macro" ) ) {
            _DirSet( MACRO );
        } else if( optionString( str, "nomacro" ) ) {
            _DirUnSet( MACRO );
        } else if( optionString( str, "reorder" ) ) {
            _DirSet( REORDER );
        } else if( optionString( str, "noreorder" ) ) {
            _DirUnSet( REORDER );
        } else if( optionString( str, "volatile" ) ) {
            // ignore this for now
            // _DirSet( VOLATILE );
        } else if( optionString( str, "novolatile" ) ) {
            // ignore this for now
            // _DirUnSet( VOLATILE );
        } else if( optionString( str, "move" ) ) {
            // ignore this for now
            // _DirSet( MOVE );
        } else if( optionString( str, "nomove" ) ) {
            // ignore this for now
            // _DirUnSet( MOVE );
        } else {
            Error( IMPROPER_SET_DIRECTIVE, str );
        }
    }
    return( TRUE );
}


static bool dirFuncSpace( directive_t *dir, dir_table_enum parm )
//***************************************************************
{
    dir_operand                 *dirop;
    int_32                      count;

    parm = parm;
    if( !dirNumOperandsVerify( dir->num_operands, 1 ) ) {
        return( TRUE );
    }
    dirop = dir->operand_list;
    assert( dirop->type == DIROP_INTEGER );
    count = NUMBER_INTEGER( dirop );
    if( count < 0 ) {
        Error( OP_OUT_OF_RANGE, 0 );
        return( TRUE );
    }
#ifdef _STANDALONE_
    ObjNullPad( CurrentSection, (uint_8)count );
#else
    ObjNullPad( (uint_8)count );
#endif
    return( TRUE );
}


#ifdef _STANDALONE_
static bool dirFuncStorageAlloc( directive_t *dir, dir_table_enum parm )
//**********************************************************************
// e.g.) .comm name, expr
// Emit a label name, then emit expr bytes of data
{
    dir_operand                 *dirop;
    sym_handle                  sym;
    int_32                      expr;
    char                        *buffer;
    owl_section_handle          curr_section;
    reserved_section            as_section;

    if( !dirNumOperandsVerify( dir->num_operands, 2 ) ) {
        return( TRUE );
    }
    dirop = dir->operand_list;
    if( dirop->type != DIROP_SYMBOL ) {
        Error( IMPROPER_DIROP, 0 );
        return( TRUE );
    }
    sym = SYMBOL_HANDLE( dirop );
    dirop = dirop->next;
    if( dirop->type != DIROP_INTEGER ) {
        Error( IMPROPER_DIROP, 1 );
        return( TRUE );
    }
    expr = NUMBER_INTEGER( dirop );
    if( expr <= 0 ) {
        Error( OP_OUT_OF_RANGE, 1 );
        return( TRUE );
    }
    if( ObjLabelDefined( sym ) ) {
        // then such label has already been emitted
        Error( SYM_ALREADY_DEFINED, SymName( sym ) );
        return( TRUE );
    }
    curr_section = CurrentSection;
    switch( parm ) {
    case DT_SEC_DATA:   // .comm => globl
        as_section = AS_SECTION_DATA;
        SymSetLinkage( sym, SL_GLOBAL );
        break;
    case DT_SEC_BSS:    // .lcomm, .bss
        as_section = AS_SECTION_BSS;
        break;
    default:
        assert( FALSE );
    }
    ObjSwitchSection( as_section );     // Have to switch to the right
    ObjEmitLabel( sym );                // section before emitting label.
    buffer = MemAlloc( expr );
    memset( buffer, 0, expr );
    ObjEmitData( CurrentSection, buffer, expr, TRUE ); // Align the data also.
    MemFree( buffer );
    CurrentSection = curr_section;      // Switch back to where you were.
    return( TRUE );
}
#endif

#define ESCAPE_CHAR     '\\'
#define ESCAPE_A        0x07
#define ESCAPE_B        0x08
#define ESCAPE_F        0x0C
#define ESCAPE_N        0x0A
#define ESCAPE_R        0x0D
#define ESCAPE_T        0x09
#define ESCAPE_V        0x0B

static char *getESCChar( char * const byte, char *ptr )
//*****************************************************
// Interpret the escape sequence, store the value in *byte,
// returns the pointer to the last character in the sequence.
{

⌨️ 快捷键说明

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