📄 code_emit.cpp
字号:
/*
Project.
XSC - The XtremeScript Compiler Version 0.8
Abstract.
Code emission module
Date Created.
9.2.2002
Author.
Alex Varanese
*/
// ---- Include Files -------------------------------------------------------------------------
#include "code_emit.h"
// ---- Globals -------------------------------------------------------------------------------
FILE * g_pOutputFile = NULL; // Pointer to the output file
// ---- Instruction Mnemonics -------------------------------------------------------------
// These mnemonics are mapped to each I-code instruction, allowing the emitter to
// easily translate I-code to XVM assembly
char ppstrMnemonics [][ 12 ] =
{
"Mov",
"Add", "Sub", "Mul", "Div", "Mod", "Exp", "Neg", "Inc", "Dec",
"And", "Or", "XOr", "Not", "ShL", "ShR",
"Concat", "GetChar", "SetChar",
"Jmp", "JE", "JNE", "JG", "JL", "JGE", "JLE",
"Push", "Pop",
"Call", "Ret", "CallHost",
"Pause", "Exit"
};
// ---- Functions -----------------------------------------------------------------------------
/******************************************************************************************
*
* EmitHeader ()
*
* Emits the script's header comments.
*/
void EmitHeader ()
{
// Get the current time
time_t CurrTimeMs;
struct tm * pCurrTime;
CurrTimeMs = time ( NULL );
pCurrTime = localtime ( & CurrTimeMs );
// Emit the filename
fprintf ( g_pOutputFile, "; %s\n\n", g_pstrOutputFilename );
// Emit the rest of the header
fprintf ( g_pOutputFile, "; Source File: %s\n", g_pstrSourceFilename );
fprintf ( g_pOutputFile, "; XSC Version: %d.%d\n", VERSION_MAJOR, VERSION_MINOR );
fprintf ( g_pOutputFile, "; Timestamp: %s\n", asctime ( pCurrTime ) );
}
/******************************************************************************************
*
* EmitDirectives ()
*
* Emits the script's directives.
*/
void EmitDirectives ()
{
// If directives were emitted, this is set to TRUE so we remember to insert extra line
// breaks after them
int iAddNewline = FALSE;
// If the stack size has been set, emit a SetStackSize directive
if ( g_ScriptHeader.iStackSize )
{
fprintf ( g_pOutputFile, "\tSetStackSize %d\n", g_ScriptHeader.iStackSize );
iAddNewline = TRUE;
}
// If the priority has been set, emit a SetPriority directive
if ( g_ScriptHeader.iPriorityType != PRIORITY_NONE )
{
fprintf ( g_pOutputFile, "\tSetPriority " );
switch ( g_ScriptHeader.iPriorityType )
{
// Low rank
case PRIORITY_LOW:
fprintf ( g_pOutputFile, PRIORITY_LOW_KEYWORD );
break;
// Medium rank
case PRIORITY_MED:
fprintf ( g_pOutputFile, PRIORITY_MED_KEYWORD );
break;
// High rank
case PRIORITY_HIGH:
fprintf ( g_pOutputFile, PRIORITY_HIGH_KEYWORD );
break;
// User-defined timeslice
case PRIORITY_USER:
fprintf ( g_pOutputFile, "%d", g_ScriptHeader.iUserPriority );
break;
}
fprintf ( g_pOutputFile, "\n" );
iAddNewline = TRUE;
}
// If necessary, insert an extra line break
if ( iAddNewline )
fprintf ( g_pOutputFile, "\n" );
}
/******************************************************************************************
*
* EmitScopeSymbols ()
*
* Emits the symbol declarations of the specified scope
*/
void EmitScopeSymbols ( int iScope, int iType )
{
// If declarations were emitted, this is set to TRUE so we remember to insert extra
// line breaks after them
int iAddNewline = FALSE;
// Local symbol node pointer
SymbolNode * pCurrSymbol;
// Loop through each symbol in the table to find the match
for ( int iCurrSymbolIndex = 0; iCurrSymbolIndex < g_SymbolTable.iNodeCount; ++ iCurrSymbolIndex )
{
// Get the current symbol structure
pCurrSymbol = GetSymbolByIndex ( iCurrSymbolIndex );
// If the scopes and parameter flags match, emit the declaration
if ( pCurrSymbol->iScope == iScope && pCurrSymbol->iType == iType )
{
// Print one tab stop for global declarations, and two for locals
fprintf ( g_pOutputFile, "\t" );
if ( iScope != SCOPE_GLOBAL )
fprintf ( g_pOutputFile, "\t" );
// Is the symbol a parameter?
if ( pCurrSymbol->iType == SYMBOL_TYPE_PARAM )
fprintf ( g_pOutputFile, "Param %s", pCurrSymbol->pstrIdent );
// Is the symbol a variable?
if ( pCurrSymbol->iType == SYMBOL_TYPE_VAR )
{
fprintf ( g_pOutputFile, "Var %s", pCurrSymbol->pstrIdent );
// If the variable is an array, add the size declaration
if ( pCurrSymbol->iSize > 1 )
fprintf ( g_pOutputFile, " [ %d ]", pCurrSymbol->iSize );
}
fprintf ( g_pOutputFile, "\n" );
iAddNewline = TRUE;
}
}
// If necessary, insert an extra line break
if ( iAddNewline )
fprintf ( g_pOutputFile, "\n" );
}
/******************************************************************************************
*
* EmitFunc ()
*
* Emits a function, its local declarations, and its code.
*/
void EmitFunc ( FuncNode * pFunc )
{
// Emit the function declaration name and opening brace
fprintf ( g_pOutputFile, "\tFunc %s\n", pFunc->pstrName );
fprintf ( g_pOutputFile, "\t{\n" );
// Emit parameter declarations
EmitScopeSymbols ( pFunc->iIndex, SYMBOL_TYPE_PARAM );
// Emit local variable declarations
EmitScopeSymbols ( pFunc->iIndex, SYMBOL_TYPE_VAR );
// Does the function have an I-code block?
if ( pFunc->ICodeStream.iNodeCount > 0 )
{
// Used to determine if the current line is the first
int iIsFirstSourceLine = TRUE;
// Yes, so loop through each I-code node to emit the code
for ( int iCurrInstrIndex = 0; iCurrInstrIndex < pFunc->ICodeStream.iNodeCount; ++ iCurrInstrIndex )
{
// Get the I-code instruction structure at the current node
ICodeNode * pCurrNode = GetICodeNodeByImpIndex ( pFunc->iIndex, iCurrInstrIndex );
// Determine the node type
switch ( pCurrNode->iType)
{
// Source code annotation
case ICODE_NODE_SOURCE_LINE:
{
// Make a local copy of the source line
char * pstrSourceLine = pCurrNode->pstrSourceLine;
// If the last character of the line is a line break, clip it
int iLastCharIndex = strlen ( pstrSourceLine ) - 1;
if ( pstrSourceLine [ iLastCharIndex ] == '\n' )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -