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

📄 xasm.cpp

📁 < Game Script Mastery>> source code
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                                    OP_FLAG_TYPE_FLOAT |
                                    OP_FLAG_TYPE_STRING |
                                    OP_FLAG_TYPE_MEM_REF |
                                    OP_FLAG_TYPE_REG );

        // Pop           Destination

        iInstrIndex = AddInstrLookup ( "Pop", INSTR_POP, 1 );
        SetOpType ( iInstrIndex, 0, OP_FLAG_TYPE_MEM_REF |
                                    OP_FLAG_TYPE_REG );

        // ---- The Function Interface

        // Call          FunctionName

        iInstrIndex = AddInstrLookup ( "Call", INSTR_CALL, 1 );
        SetOpType ( iInstrIndex, 0, OP_FLAG_TYPE_FUNC_NAME );

        // Ret

        iInstrIndex = AddInstrLookup ( "Ret", INSTR_RET, 0 );

        // CallHost      FunctionName

        iInstrIndex = AddInstrLookup ( "CallHost", INSTR_CALLHOST, 1 );
        SetOpType ( iInstrIndex, 0, OP_FLAG_TYPE_HOST_API_CALL );

        // ---- Miscellaneous

        // Pause        Duration

        iInstrIndex = AddInstrLookup ( "Pause", INSTR_PAUSE, 1 );
        SetOpType ( iInstrIndex, 0, OP_FLAG_TYPE_INT |
                                    OP_FLAG_TYPE_FLOAT |
                                    OP_FLAG_TYPE_STRING |
                                    OP_FLAG_TYPE_MEM_REF |
                                    OP_FLAG_TYPE_REG );

        // Exit         Code

        iInstrIndex = AddInstrLookup ( "Exit", INSTR_EXIT, 1 );
        SetOpType ( iInstrIndex, 0, OP_FLAG_TYPE_INT |
                                    OP_FLAG_TYPE_FLOAT |
                                    OP_FLAG_TYPE_STRING |
                                    OP_FLAG_TYPE_MEM_REF |
                                    OP_FLAG_TYPE_REG );
    }

    /******************************************************************************************
    *
    *   AddInstrLookup ()
    *
    *   Adds an instruction to the instruction lookup table.
    */

    int AddInstrLookup ( char * pstrMnemonic, int iOpcode, int iOpCount )
    {
        // Just use a simple static int to keep track of the next instruction index in the
        // table.

        static int iInstrIndex = 0;

        // Make sure we haven't run out of instruction indices

        if ( iInstrIndex >= MAX_INSTR_LOOKUP_COUNT )
            return -1;

        // Set the mnemonic, opcode and operand count fields

        strcpy ( g_InstrTable [ iInstrIndex ].pstrMnemonic, pstrMnemonic );
        strupr ( g_InstrTable [ iInstrIndex ].pstrMnemonic );
        g_InstrTable [ iInstrIndex ].iOpcode = iOpcode;
        g_InstrTable [ iInstrIndex ].iOpCount = iOpCount;

        // Allocate space for the operand list

        g_InstrTable [ iInstrIndex ].OpList = ( OpTypes * ) malloc ( iOpCount * sizeof ( OpTypes ) );

        // Copy the instruction index into another variable so it can be returned to the caller

        int iReturnInstrIndex = iInstrIndex;

        // Increment the index for the next instruction

        ++ iInstrIndex;

        // Return the used index to the caller

        return iReturnInstrIndex;
    }

	/******************************************************************************************
	*
	*	AddString ()
	*
	*	Adds a string to a linked list, blocking duplicate entries
	*/

	int AddString ( LinkedList * pList, char * pstrString )
	{
		// ---- First check to see if the string is already in the list

		// Create a node to traverse the list

		LinkedListNode * pNode = pList->pHead;

		// Loop through each node in the list

		for ( int iCurrNode = 0; iCurrNode < pList->iNodeCount; ++ iCurrNode )
		{
			// If the current node's string equals the specified string, return its index

			if ( strcmp ( ( char * ) pNode->pData, pstrString ) == 0 )
				return iCurrNode;

			// Otherwise move along to the next node

			pNode = pNode->pNext;
		}

		// ---- Add the new string, since it wasn't added

		// Create space on the heap for the specified string

		char * pstrStringNode = ( char * ) malloc ( strlen ( pstrString ) + 1 );
		strcpy ( pstrStringNode, pstrString );

		// Add the string to the list and return its index

		return AddNode ( pList, pstrStringNode );
	}

    /******************************************************************************************
    *
    *   SetOpType ()
    *
    *   Sets the operand type for the specified operand in the specified instruction.
    */

    void SetOpType ( int iInstrIndex, int iOpIndex, OpTypes iOpType )
    {
        g_InstrTable [ iInstrIndex ].OpList [ iOpIndex ] = iOpType;
    }

	/******************************************************************************************
	*
	*	Init ()
	*
	*	Initializes the assembler.
	*/

	void Init ()
	{
        // Initialize the master instruction lookup table

        InitInstrTable ();

        // Initialize tables

        InitLinkedList ( & g_SymbolTable );
        InitLinkedList ( & g_LabelTable );
        InitLinkedList ( & g_FuncTable );
		InitLinkedList ( & g_StringTable );
        InitLinkedList ( & g_HostAPICallTable );
	}

    /******************************************************************************************
    *
    *   ShutDown ()
    *
    *   Frees any dynamically allocated resources back to the system.
    */

    void ShutDown ()
    {
        // ---- Free source code array

        // Free each source line individually

        for ( int iCurrLineIndex = 0; iCurrLineIndex < g_iSourceCodeSize; ++ iCurrLineIndex )
            free ( g_ppstrSourceCode [ iCurrLineIndex ] );

        // Now free the base pointer

        free ( g_ppstrSourceCode );

        // ---- Free the assembled instruction stream

		if ( g_pInstrStream )
		{
			// Free each instruction's operand list

			for ( int iCurrInstrIndex = 0; iCurrInstrIndex < g_iInstrStreamSize; ++ iCurrInstrIndex )
				if ( g_pInstrStream [ iCurrInstrIndex ].pOpList )
					free ( g_pInstrStream [ iCurrInstrIndex ].pOpList );

			// Now free the stream itself

            free ( g_pInstrStream );
		}

		// ---- Free the tables

		FreeLinkedList ( & g_SymbolTable );
		FreeLinkedList ( & g_LabelTable );
		FreeLinkedList ( & g_FuncTable );
		FreeLinkedList ( & g_StringTable );
		FreeLinkedList ( & g_HostAPICallTable );
    }

    /******************************************************************************************
    *
    *   ResetLexer ()
    *
    *   Resets the lexer to the beginning of the source file by setting the current line and
    *   indices to zero.
    */

    void ResetLexer ()
    {
        // Set the current line to the start of the file

        g_Lexer.iCurrSourceLine = 0;

        // Set both indices to point to the start of the string

        g_Lexer.iIndex0 = 0;
        g_Lexer.iIndex1 = 0;

        // Set the token type to invalid, since a token hasn't been read yet

        g_Lexer.CurrToken = TOKEN_TYPE_INVALID;

        // Set the lexing state to no strings

        g_Lexer.iCurrLexState = LEX_STATE_NO_STRING;
    }

    /******************************************************************************************
    *
    *   GetNextToken ()
    *
    *   Extracts and returns the next token from the character stream. Also makes a copy of
    *   the current lexeme for use with GetCurrLexeme ().
    */

    Token GetNextToken ()
    {
        // ---- Lexeme Extraction

        // Move the first index (Index0) past the end of the last token, which is marked
        // by the second index (Index1).

        g_Lexer.iIndex0 = g_Lexer.iIndex1;

        // Make sure we aren't past the end of the current line. If a string is 8 characters long,
        // it's indexed from 0 to 7; therefore, indices 8 and beyond lie outside of the string and
        // require us to move to the next line. This is why I use >= for the comparison rather
        // than >. The value returned by strlen () is always one greater than the last valid
        // character index.

        if ( g_Lexer.iIndex0 >= strlen ( g_ppstrSourceCode [ g_Lexer.iCurrSourceLine ] ) )
        {
            // If so, skip to the next line but make sure we don't go past the end of the file.
            // SkipToNextLine () will return FALSE if we hit the end of the file, which is
            // the end of the token stream.

            if ( ! SkipToNextLine () )
                return END_OF_TOKEN_STREAM;
        }

        // If we just ended a string, tell the lexer to stop lexing
        // strings and return to the normal state

        if ( g_Lexer.iCurrLexState == LEX_STATE_END_STRING )
            g_Lexer.iCurrLexState = LEX_STATE_NO_STRING;

        // Scan through the potential whitespace preceding the next lexeme, but ONLY if we're
        // not currently parsing a string lexeme (since strings can contain arbitrary whitespace
        // which must be preserved).

        if ( g_Lexer.iCurrLexState != LEX_STATE_IN_STRING )
        {
            // Scan through the whitespace and check for the end of the line

            while ( TRUE )
            {
                // If the current character is not whitespace, exit the loop because the lexeme
                // is starting.

                if ( ! IsCharWhitespace ( g_ppstrSourceCode [ g_Lexer.iCurrSourceLine ][ g_Lexer.iIndex0 ] ) )
                    break;

                // It is whitespace, however, so move to the next character and continue scanning

                ++ g_Lexer.iIndex0;
            }
        }

        // Bring the second index (Index1) to the lexeme's starting character, which is marked by
        // the first index (Index0)

        g_Lexer.iIndex1 = g_Lexer.iIndex0;

        // Scan through the lexeme until a delimiter is hit, incrementing Index1 each time

        while ( TRUE )
        {
            // Are we currently scanning through a string?

            if ( g_Lexer.iCurrLexState == LEX_STATE_IN_STRING )
            {
                // If we're at the end of the line, return an invalid token since the string has no
                // ending double-quote on the line

                if ( g_Lexer.iIndex1 >= strlen ( g_ppstrSourceCode [ g_Lexer.iCurrSourceLine ] ) )
                {
                    g_Lexer.CurrToken = TOKEN_TYPE_INVALID;
                    return g_Lexer.CurrToken;
                }

                // If the current character is a backslash, move ahead two characters to skip the
                // escape sequence and jump to the next iteration of the loop

                if ( g_ppstrSourceCode [ g_Lexer.iCurrSourceLine ][ g_Lexer.iIndex1 ] == '\\' )
                {
                    g_Lexer.iIndex1 += 2;
                    continue;
                }

                // If the current character isn't a double-quote, move to the next, otherwise exit
                // the loop, because the string has ended.

                if ( g_ppstrSourceCode [ g_Lexer.iCurrSourceLine ][ g_Lexer.iIndex1 ] == '"' )
                    break;

                ++ g_Lexer.iIndex1;
            }

            // We are not currently scanning through a string

            else
            {
                // If we're at the end of the line, the lexeme has ended so exit the loop

                if ( g_Lexer.iIndex1 >= st

⌨️ 快捷键说明

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