asmscan.c

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

C
682
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "asmglob.h"
#include <ctype.h>

#include "asmins.h"
#include "asmdefs.h"

char                    *CurrString; // Current Input Line

extern int              get_instruction_position( char *string );

#if defined( _STANDALONE_ )

extern global_options   Options;

void GetInsString( enum asm_token token, char *string, int len )
/**************************************************************/
{
    int index;

    if( len > AsmOpcode[ token ].len ) {
        len = AsmOpcode[ token ].len;
        index = AsmOpcode[ token ].index;
        if( AsmChars[index]== '.' ) {
            index++;
            len--;
        }
        strncpy( string, &(AsmChars[ index ]), len );
        string[ len ] = '\0';
    } else {
        *string='\0';
    }
    return;
}
#endif

typedef union {
        float   f;
        long    l;
} NUMBERFL;

static int get_float( struct asm_tok *buf, char **input, char **output )
/**********************************************************************/
{
    /* valid floats look like:  (int)[.(int)][e(int)] */

    char    got_decimal = FALSE;
    char    got_e = FALSE;
    char    *ptr = *input;

    for( ; *ptr != '\0'; ptr++ ) {
        if( isdigit( *ptr ) )
            continue;
        if( isspace( *ptr ) )
            break;
        switch( tolower( *ptr ) ) {
        case '.':
            got_decimal = TRUE;
            continue;
        case 'r':
            *ptr=' ';
            goto done_scanning_float;
        case 'e':
            if( !got_e ) {
                got_e = TRUE;
                /* accept e+2 / e-4 /etc. */

                switch( *(ptr+1) ) {
                case '+':
                case '-':
                    ptr++;
                    /* fall through */
                default:
                    continue;
                }
            }
            /* fall through */
        default:
            goto done_scanning_float;
//            return( get_string( buf, input, output ) );
        }
    }

done_scanning_float:

    buf->token = T_FLOAT;
    /* copy the string, fix input & output pointers */
    strncpy( *output, *input, ptr - *input );
    buf->string_ptr = *output;
    *output += ( ptr - *input );
    **output = '\0';
    (*output)++;
    *input = ptr;

    *((float *)(&buf->value)) = atof(buf->string_ptr);
    return( NOT_ERROR );
}

static void array_mul_add(char *buf, unsigned base, unsigned num, unsigned size) {

    while( size-- > 0 ) {
        num += *buf * base;
        *(buf++) = num;
        num >>= 8;
    }
}

static int get_string( struct asm_tok *buf, char **input, char **output )
/***********************************************************************/
{
    char    symbol_o;
    char    symbol_c;
    int     count;
    int     level;

    buf->string_ptr = *output;

    symbol_o = **input;

    buf->token = T_STRING;
    switch( symbol_o ) {
    case '"':
    case '\'':
        symbol_c = 0;
        break;  // end of string marker is the same
    case '<':
        symbol_c = '>';
        break;
    case '{':
        symbol_c = '}';
        break;
    default:
        /* this is an undelimited string,
         * so just copy it until we hit something that looks like the end
         */

        for( count = 0; **input != '\0' && !isspace( **input ) && **input != ','; count++ ) {
            *(*output)++ = *(*input)++; /* keep the 2nd one */
        }
        *(*output)++ = '\0';
        buf->value = count;
        return( NOT_ERROR );
    }
    (*input)++;

    count = 0;
    level = 0;
    while( count < MAX_TOK_LEN ) {
        if( **input == symbol_o ) {
            if( symbol_c ) {
                level++;
                *(*output)++ = *(*input)++;
                count++;
            } else if( *( *input + 1 ) == symbol_o ) {
                /* if we see "" in a " delimited string,
                 * treat it as a literal " */
                (*input)++; /* skip the 1st one */
                *(*output)++ = *(*input)++; /* keep the 2nd one */
                count++;
            } else {
                *(*output)++ = '\0';
                (*input)++; /* skip the closing delimiter */
                buf->value = count;
                break;
            }
        } else if( symbol_c && **input == symbol_c ) {
            if( level ) {
                level--;
                *(*output)++ = *(*input)++;
                count++;
            } else {
                *(*output)++ = '\0';
                (*input)++; /* skip the closing delimiter */
                buf->value = count;
                break;
            }
        } else if( **input == '\0' || **input == '\n' ) {
            AsmError( SYNTAX_ERROR );
            return( ERROR );
        } else {
            *(*output)++ = *(*input)++;
            count++;
        }
    }
    return( NOT_ERROR );
}

static int get_number( struct asm_tok *buf, char **input, char **output )
/***********************************************************************/
{
    char                *ptr = *input;
    char                *dig_start;
    char                first_char_0 = FALSE;
    unsigned            extra;
    unsigned            len;
    unsigned            base = 0;
    unsigned            digits_seen;
    unsigned long       val;

#define VALID_BINARY    0x0003
#define VALID_OCTAL     0x00ff
#define VALID_DECIMAL   0x03ff
#define OK_NUM( t )     ((digits_seen & ~VALID_##t) == 0)
    digits_seen = 0;

    extra = 0;
    if( *ptr == '0' ) {
        if( tolower( *(ptr+1) ) == 'x' ) {
            ptr+=2;
            base = 16;
        } else {
            ptr += 1;
            first_char_0 = TRUE;
        }
    }
    dig_start = ptr;
    for( ;; ) {
        switch( tolower( *ptr ) ) {
        case '9':
        case '8':
        case '7':
        case '6':
        case '5':
        case '4':
        case '3':
        case '2':
        case '1':
        case '0':
            digits_seen |= 1 << (*ptr - '0');
            break;
        case 'a':
            digits_seen |= 1 << 10;
            break;
        case 'b':
            if( base == 0
             && OK_NUM( BINARY )
             && !isxdigit( ptr[1] )
             && tolower( ptr[1] ) != 'h' ) {
                base = 2;
                extra = 1;
                goto done_scan;
            }
            digits_seen |= 1 << 11;
            break;
        case 'c':
            digits_seen |= 1 << 12;
            break;
        case 'd':
            if( base == 0
             && OK_NUM( DECIMAL )
             && !isxdigit( ptr[1] )
             && tolower( ptr[1] ) != 'h' ) {
                if( !isalnum( ptr[1] ) && ptr[1] != '_' ) {
                    base = 10;
                    extra = 1;
                }
                goto done_scan;
            }
            digits_seen |= 1 << 13;
            break;
        case 'e': /* note that this could NOT be part of a float */
            digits_seen |= 1 << 14;
            break;
        case 'f':
            digits_seen |= 1U << 15;
            break;
        case 'y':
            base = 2;
            extra = 1;
            goto done_scan;
        case 'h':
            base = 16;
            extra = 1;
            goto done_scan;
        case 'o':
            base = 8;
            extra = 1;
            goto done_scan;
        case '.':
        case 'r':
            /* note that a float MUST contain a dot
             * OR be ended with an "r"
             * 1234e78 is NOT a valid float */

            return( get_float( buf, input, output ) );
         default:
             goto done_scan;
        }
        ++ptr;
    }
done_scan:
    if( digits_seen == 0 ) {
        if( !first_char_0 ) {
            return( get_string( buf, input, output ) );
        }
        digits_seen |= 1;
        first_char_0 = FALSE;
        dig_start = *input;
    }
#if defined( _STANDALONE_ )
    if( !Options.allow_c_octals ) {
        first_char_0 = FALSE;
    }
#endif
    buf->token = T_NUM;
    if( base == 0 ) {
        base = first_char_0 ? 8 : 10;
    }
    switch( base ) {
    case 10:

⌨️ 快捷键说明

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