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 + -
显示快捷键?