⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scan.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*
*                            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:  Lexical scanner, Windows RC version.
*
****************************************************************************/


#include <ctype.h>
#include <string.h>
#include "varstr.h"
#include "rctypes.h"
#include "global.h"
#include "rcio.h"
#include "rcmem.h"
#include "errors.h"
#include "ytab.gh"
#include "scan.h"
#include "keyword.h"
#include "depend.h"
//#include "rcdll.h"
#include "errprt.h"

#ifdef SCANDEBUG

#define DEBUGPUTS(s) PutScanString(s);

static void PutScanString( const char *string )
{
    if( CmdLineParms.DebugScanner && string != NULL ) {
        RcFprintf( stdout, NULL, "%s\n", string );
    }
} /* PutScanString */

#else
    #define DEBUGPUTS(s)
#endif

/*** Macros to implement the parts of a finite state machine ***/
/* change_state changes states without reading a character */

static int      _next;
static int      LookAhead;
static int      longString;
static int      newLineInString = 0;

static int ScanDFA( ScanValue *value );

static void GetNextChar( void )
{
    while( 1 ) {
        LookAhead = _next;
        if( LookAhead != RC_EOF ) {
            _next = RcIoGetChar();
            if( LookAhead == '\\' && _next == '\n' ) {
                _next = RcIoGetChar();
                continue;
            }
        }
        break;
    }
} /* GetNextChar */

static void CharInit( void )
{
    _next = RcIoGetChar();
    GetNextChar();
} /* CharInit */


#define state(s) s
#define do_transition(s) GetNextChar(); goto s
#define change_state(s) goto s
#define enter_start_state CharInit()

static void AddDigitToInt( long *value, int base, int newchar )
{
    int     newdigit;

    if( isdigit(newchar) ) {
        newdigit = newchar - '0';
    } else {            /* assume it is a hex digit */
        newdigit = toupper(newchar) - 'A' + 10;
    }

    *value = *value * base + newdigit;
} /* AddDigitToInt */

static int ScanCPPDirective( ScanValue *value )
/*********************************************/
/* This function takes the correct action for the #line directive and returns */
/* the token following the preprocessor stuff. It uses Scan to do it's */
/* scanning. DON'T call this function from within Scan or the functions it */
/* calls unless you are very careful about recurtion. */
{
    int     token;
    int     linenum;

    if( StopInvoked ) {
        RcFatalError( ERR_STOP_REQUESTED );
    }
    /* get the "line" or "pragma" directive */
    token = ScanDFA( value );
    if( token != Y_NAME ) {
        RcFatalError( ERR_INVALID_CPP );
    }

    if( stricmp( value->string.string, "line" ) == 0 ) {
        RcMemFree( value->string.string );

        /* get the line number */
        token = ScanDFA( value );
        if( token != Y_INTEGER ) {
            RcFatalError( ERR_INVALID_CPP_LINE );
        }
        RcMemFree( value->intinfo.str );
        value->intinfo.str = NULL;
        linenum = value->intinfo.val;

        /* get the filename if there is one */
        token = ScanDFA( value );
        if( token == Y_STRING ) {
            RcIoSetLogicalFileInfo( linenum, value->string.string );
            if( AddDependency( value->string.string ) ) {
                ErrorHasOccured = TRUE;
            }
            RcMemFree( value->string.string );
            token = ScanDFA( value );
        } else {
            RcIoSetLogicalFileInfo( linenum, NULL );
        }
    } else if( stricmp( value->string.string, "pragma" ) == 0 ) {
        RcMemFree( value->string.string );
        token = Y_POUND_PRAGMA;
    } else if( stricmp( value->string.string, "error" ) == 0 ) {
        char            buf[80];
        unsigned        i;

        i = 0;
        while( LookAhead != '\n' && LookAhead != RC_EOF ) {
            buf[i] = LookAhead;
            i ++;
            GetNextChar();
        }
        buf[i] = '\0';
        RcFatalError( ERR_TEXT_FROM_CPP, buf );
    } else {
        RcFatalError( ERR_INVALID_CPP );
    }

    return( token );
} /* ScanCPPDirective */

extern void ScanInit( void )
/**************************/
{
    enter_start_state;
} /* ScanInit */

static int ScanDFA( ScanValue * value )
/*************************************/
{
    long                newint;     /* these are used to accumulate parts of */
    VarString           *newstring; /* a new value */
    int                 token;
#ifdef SCANDEBUG
    char                debugstring[10];
#endif
    char                *stringFromFile;

    value->intinfo.type  = SCAN_INT_TYPE_DEFAULT;
    value->string.string = NULL;
    longString = FALSE;

    state(S_START):
        if( isspace(LookAhead) ) {
            do_transition( S_START );
        } else if( isdigit(LookAhead) ) {
            newint = LookAhead - '0';
            newstring = VarStringStart();
            VarStringAddChar( newstring, LookAhead );
            if( LookAhead == '0' ) {
                do_transition( S_HEXSTART );
            } else {
                do_transition( S_DECIMAL );
            }
        } else if( isalpha(LookAhead) || LookAhead == '_' ) {
            newstring = VarStringStart();
            VarStringAddChar( newstring, LookAhead );
            if( LookAhead == 'l' || LookAhead == 'L' ) {
                do_transition( S_L_STRING );
            }
            do_transition( S_NAME );
        } else switch (LookAhead) {
            case '"':
                newstring = VarStringStart();  /* don't include the " */
                newLineInString = 0; /* reset newline in string status */
                do_transition( S_STRING );
            case '.':
                newstring = VarStringStart();
                VarStringAddChar( newstring, LookAhead );
                do_transition( S_DOS_FILENAME );
            case RC_EOF:
                DEBUGPUTS("RC_EOF")
                return( 0 );                /* yacc wants 0 on EOF */
            case '#':           do_transition( S_POUND_SIGN );
            case '(':           do_transition( S_LPAREN );
            case ')':           do_transition( S_RPAREN );
            case '[':           do_transition( S_LSQ_BRACKET );
            case ']':           do_transition( S_RSQ_BRACKET );
            case '{':           do_transition( S_LBRACE );
            case '}':           do_transition( S_RBRACE );
            case '+':           do_transition( S_PLUS );
            case '-':           do_transition( S_MINUS );
            case '~':           do_transition( S_BITNOT );
            case '!':           do_transition( S_NOT );
            case '*':           do_transition( S_TIMES );
            case '/':           do_transition( S_DIVIDE );
            case '%':           do_transition( S_MOD );
            case '>':           do_transition( S_GT );
            case '<':           do_transition( S_LT );
            case '=':           do_transition( S_EQ );
            case '&':           do_transition( S_BITAND );
            case '^':           do_transition( S_BITXOR );
            case '|':           do_transition( S_BITOR );
            case '?':           do_transition( S_QUESTION );
            case ':':           do_transition( S_COLON );
            case ',':           do_transition( S_COMMA );
            case ';':           do_transition( S_COMMENT );
            case '\\':
                newstring = VarStringStart();
                VarStringAddChar( newstring, '\\' );
                VarStringAddChar( newstring, LookAhead );
                do_transition( S_DOS_FILENAME );
            default:
                value->UnknownChar = LookAhead;
                do_transition( S_ERROR );
        }
    state(S_L_STRING):
        if( LookAhead =='"' ) {
            longString = TRUE;
            RcMemFree( VarStringEnd( newstring, NULL ) );
            change_state( S_START );
        } else {
            change_state( S_NAME );
        }
    state(S_ERROR):
        ErrorHasOccured = TRUE;
        return( Y_SCAN_ERROR );

    state(S_COMMENT):
        if( LookAhead == '\n' || LookAhead == RC_EOF ) {
            do_transition( S_START );
        } else {
            do_transition( S_COMMENT );
        }

    state(S_POUND_SIGN):
        DEBUGPUTS( "#" )
        return( Y_POUND_SIGN );

    state(S_LPAREN):
        DEBUGPUTS( "(" )
        return( Y_LPAREN );

    state(S_RPAREN):
        DEBUGPUTS( ")" )
        return( Y_RPAREN );

    state( S_LSQ_BRACKET ):
        DEBUGPUTS( "[" )
        return( Y_LSQ_BRACKET );

    state( S_RSQ_BRACKET ):
        DEBUGPUTS( "]" )
        return( Y_RSQ_BRACKET );

    state(S_LBRACE):
        DEBUGPUTS( "{" )
        return( Y_LBRACE );

    state(S_RBRACE):
        DEBUGPUTS( "}" )
        return( Y_RBRACE );

    state(S_PLUS):
        DEBUGPUTS( "+" )
        return( Y_PLUS );

    state(S_MINUS):
        DEBUGPUTS( "-" )
        return( Y_MINUS );

    state(S_BITNOT):
        DEBUGPUTS( "~" )
        return( Y_BITNOT );

    state(S_NOT):
        if( LookAhead == '=' ) {
            do_transition( S_NE );
        } else {
            DEBUGPUTS( "!" )
            return( Y_NOT );
        }

    state(S_TIMES):
        DEBUGPUTS( "*" )
        return( Y_TIMES );

    state(S_DIVIDE):
        DEBUGPUTS( "/" )
        return( Y_DIVIDE );

    state(S_MOD):
        DEBUGPUTS( "%" )
        return( Y_MOD );

    state(S_GT):
        switch (LookAhead) {
        case '>':       do_transition( S_SHIFTR );
        case '=':       do_transition( S_GE );
        default:
            DEBUGPUTS( ">" )
            return( Y_GT );
        }

    state(S_LT):
        switch (LookAhead) {
        case '<':       do_transition( S_SHIFTL );
        case '=':       do_transition( S_LE );
        default:
            DEBUGPUTS( "<" )
            return( Y_LT );
        }

    state(S_EQ):
        if( LookAhead == '=' ) {
            do_transition( S_ENDEQ );
        } else {
            DEBUGPUTS( "=" )
            return( Y_SINGLE_EQ );
        }

    state(S_BITAND):
        if( LookAhead == '&' ) {
            do_transition( S_AND );
        } else {
            DEBUGPUTS( "&" )
            return( Y_BITAND );
        }

    state(S_BITXOR):
        DEBUGPUTS( "^" )
        return( Y_BITXOR );

    state(S_BITOR):
        if( LookAhead == '|' ) {
            do_transition( S_OR );
        } else {
            DEBUGPUTS( "|" )
            return( Y_BITOR );
        }

    state(S_QUESTION):
        DEBUGPUTS( "?" )
        return( Y_QUESTION );

    state(S_COLON):
        DEBUGPUTS( ":" )
        return( Y_COLON );

    state(S_COMMA):
        DEBUGPUTS( "," )
        return( Y_COMMA );

    state(S_NE):
        DEBUGPUTS( "!=" )
        return( Y_NE );

    state(S_SHIFTR):
        DEBUGPUTS( ">>" )
        return( Y_SHIFTR );

    state(S_GE):
        DEBUGPUTS( ">=" )
        return( Y_GE );

    state(S_SHIFTL):
        DEBUGPUTS( "<<" )
        return( Y_SHIFTL );

    state(S_LE):
        DEBUGPUTS( "<=" )
        return( Y_LE );

    state(S_ENDEQ):
        DEBUGPUTS( "==" )
        return( Y_EQ );

    state(S_AND):
        DEBUGPUTS( "&&" )
        return( Y_AND );

    state(S_OR):
        DEBUGPUTS( "||" )

⌨️ 快捷键说明

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