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