asmscan.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 682 行 · 第 1/2 页
C
682 行
if( OK_NUM( DECIMAL ) )
break;
/* fall through */
case 8:
if( OK_NUM( OCTAL ) )
break;
/* fall through */
case 2:
if( OK_NUM( BINARY ) )
break;
/* fall through */
//AsmError( INVALID_NUMBER_DIGIT );
/* swallow remainder of token */
while( isalnum( *ptr )
|| *ptr == '_'
|| *ptr == '$'
|| *ptr == '@'
|| *ptr == '?' ) {
++ptr;
}
buf->token = T_BAD_NUM;
break;
}
/* copy the string, fix input & output pointers */
len = ptr - *input + extra;
strncpy( *output, *input, len );
buf->string_ptr = *output;
*output += len;
**output = '\0';
(*output)++;
*input = ptr + extra;
memset(buf->bytes, 0, sizeof(buf->bytes));
while( dig_start < ptr ) {
if( isdigit( *dig_start ) ) {
val = *dig_start - '0';
} else {
val = tolower( *dig_start ) - 'a' + 10;
}
array_mul_add( buf->bytes, base, val, sizeof( buf->bytes ) );
++dig_start;
}
return( NOT_ERROR );
} /* get_number */
static int get_id_in_backquotes( struct asm_tok *buf, char **input, char **output )
/*********************************************************************************/
{
buf->string_ptr = *output;
buf->token = T_ID;
buf->value = 0;
/* copy char from input to output & inc both */
(*input)++; // strip off the backquotes
for( ; **input != '`'; ) {
*(*output)++ = *(*input)++;
if( **input == '\0' || **input == ';' ) {
AsmError( SYNTAX_ERROR );
return( ERROR );
}
}
(*input)++; /* don't output the last '`' */
*(*output)++ = '\0';
return( NOT_ERROR );
}
static int get_id( unsigned int *buf_index, char **input, char **output )
/***********************************************************************/
/* get_id could change buf_index, if a COMMENT directive is found */
{
struct asm_tok *buf;
char cur_char;
int count;
buf = AsmBuffer[ *buf_index ];
buf->string_ptr = *output;
if( **input != '\\' ) {
buf->token = T_ID;
} else {
buf->token = T_PATH;
}
buf->value = 0;
*(*output)++ = *(*input)++;
for( ; ; ) {
cur_char = **input;
/* if character is part of a valid name, add it */
if( isalpha( cur_char )
|| isdigit( cur_char )
|| cur_char == '_'
|| cur_char == '$'
|| cur_char == '@'
|| cur_char == '?' ) {
*(*output)++ = *(*input)++;
} else if( cur_char == '\\' ) {
*(*output)++ = *(*input)++;
buf->token = T_PATH;
} else {
break;
}
}
*(*output)++ = '\0';
/* now decide what to do with it */
if( buf->token == T_PATH )
return( NOT_ERROR );
count = get_instruction_position( buf->string_ptr );
if( count == EMPTY ) {
buf->token = T_ID;
if( buf->string_ptr[1] == '\0' && buf->string_ptr[0] == '?' ) {
buf->token = T_QUESTION_MARK;
}
} else {
buf->value = AsmOpTable[count].token;
// count = AsmOpcode[count].position;
if( AsmOpTable[count].opnd_type[OPND1] == OP_SPECIAL ) {
if( AsmOpTable[count].rm_byte & OP_REGISTER ) {
buf->token = T_REG;
} else if( AsmOpTable[count].rm_byte & OP_RES_ID ) {
if( buf->value == T_PWORD ) {
buf->value = T_FWORD;
} else if( buf->value == T_DP ) {
buf->value = T_DF;
}
buf->token = T_RES_ID;
} else if( AsmOpTable[count].rm_byte & OP_UNARY_OPERATOR ) {
buf->token = T_UNARY_OPERATOR;
} else if( AsmOpTable[count].rm_byte & OP_DIRECTIVE ) {
buf->token = T_DIRECTIVE;
#if defined( _STANDALONE_ )
switch( AsmOpTable[count].token ) {
case T_COMMENT:
/* save the whole line .. we need to check
* if the delim. char shows up 2 times */
(*output)++;
*(*output) = '\0';
(*output)++;
(*buf_index)++;
buf = AsmBuffer[ *buf_index ];
buf->string_ptr = *output;
strcpy( buf->string_ptr, *input );
(*output) += strlen( *input );
*(*output) = '\0';
(*output)++;
(*input) += strlen( *input );
buf->token = T_STRING;
buf->value = 0;
break;
} /* default do nothing */
#endif
} else if( AsmOpTable[count].rm_byte & OP_DIRECT_EXPR ) {
buf->token = T_DIRECT_EXPR;
} else {
buf->token = T_INSTR;
}
} else {
buf->token = T_INSTR;
}
}
return( NOT_ERROR );
}
static int get_special_symbol( struct asm_tok *buf,
char **input, char **output )
/***********************************************************/
{
char symbol;
buf->string_ptr = *output;
symbol = **input;
switch( symbol ) {
case '.' :
case ',' :
case '+' :
case '-' :
case '*' :
case '/' :
case '[' :
case ']' :
case '(' :
case ')' :
case ':' :
case '%' :
/* all of these are themselves a token */
/* fixme
* wasm used to do a bunch of error checking dealing with use of
* registers and +,- inside and outside brackets
* I am not sure we need to do this here
* this looks more like the job of the parser
*/
buf->token = symbol;
*(*output)++ = *(*input)++;
*(*output)++ = '\0';
break;
#if defined( _STANDALONE_ )
case '=' :
buf->token = T_DIRECTIVE;
buf->value = T_EQU2;
*(*output)++ = *(*input)++;
*(*output)++ = '\0';
break;
#endif
case '\'' :
case '"' :
case '<' :
case '{' :
/* string delimiters */
/* fall through */
default:
/* anything we don't recognise we will consider a string,
* delimited by space characters, commas, newlines or nulls
*/
return( get_string( buf, input, output ) );
break;
}
return( NOT_ERROR );
}
#if defined( _STANDALONE_ )
static int get_inc_path( unsigned int *buf_index, char **input, char **output )
/*****************************************************************************/
{
char symbol;
AsmBuffer[*buf_index]->token = T_PATH;
AsmBuffer[*buf_index]->value = 0;
AsmBuffer[*buf_index]->string_ptr = *output;
while( isspace( **input ) )
(*input)++;
symbol = **input;
switch( symbol ) {
case '\'' :
case '"' :
case '<' :
case '{' :
/* string delimiters -- just get the path as a string */
if( get_special_symbol( AsmBuffer[*buf_index],input,output ) == ERROR ) {
return( ERROR );
}
return( NOT_ERROR );
default:
/* otherwise, just copy whatever is here */
while( **input && !isspace( **input ) ) {
*(*output)++ = *(*input)++;
}
return( NOT_ERROR );
}
}
#endif
int AsmScan( char *string )
/******************************************/
/*
- perform syntax checking on scan line;
- pass back tokens for later use;
- string contains the WHOLE line to scan
*/
{
char *ptr;
char *output_ptr;
unsigned int buf_index = 0;
// stringbuf - buffer in which to store strings
static char stringbuf[MAX_LINE_LEN];
CurrString = string;
output_ptr = stringbuf;
ptr = string;
/* skip initial spaces and expansion codes */
while( isspace( *ptr ) || (*ptr == '%') ) {
ptr++;
}
for( ;; ) {
AsmBuffer[buf_index]->string_ptr = output_ptr;
while( isspace( *ptr ) ) {
ptr++;
}
if( *ptr == NULLC )
break;
if( isalpha( *ptr )
|| *ptr == '_'
|| *ptr == '$'
|| *ptr == '@'
|| *ptr == '?'
|| *ptr == '\\'
|| ( *ptr == '.' && buf_index == 0 ) ) {
if( get_id( &buf_index,&ptr,&output_ptr ) == ERROR ) {
return( ERROR );
}
#if defined( _STANDALONE_ )
// this mess allows include directives with undelimited file names
if( AsmBuffer[buf_index]->token == T_DIRECTIVE &&
( AsmBuffer[buf_index]->value == T_INCLUDE ||
AsmBuffer[buf_index]->value == T_INCLUDELIB ) ) {
buf_index++;
get_inc_path( &buf_index, &ptr, &output_ptr );
}
#endif
} else if( isdigit( *ptr ) ) {
if( get_number( AsmBuffer[buf_index],&ptr,&output_ptr ) == ERROR ) {
return( ERROR );
}
/* handle negatives here - for inline assembler */
#if !defined( _STANDALONE_ )
if( buf_index > 0 && AsmBuffer[buf_index-1]->token == T_MINUS ) {
AsmBuffer[buf_index-1]->token = T_PLUS;
AsmBuffer[buf_index]->value = -AsmBuffer[buf_index]->value;
}
#endif
} else if( *ptr == '`' ) {
if( get_id_in_backquotes( AsmBuffer[buf_index],&ptr,&output_ptr ) == ERROR ) {
return( ERROR );
}
} else {
if( get_special_symbol( AsmBuffer[buf_index],&ptr,&output_ptr ) == ERROR ) {
return( ERROR );
}
}
buf_index++;
if( buf_index >= MAX_TOKEN ) {
AsmError( TOO_MANY_TOKENS );
return( ERROR );
}
}
AsmBuffer[buf_index]->token = T_FINAL;
*output_ptr='\0';
return( buf_index );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?