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

📄 pass2.c

📁 < 虚拟机设计与实现> 的source code, linux版本
💻 C
📖 第 1 页 / 共 4 页
字号:
#include "pass2.h"

#include "cmdline.h"
#include "linetok.h"
#include "globvar.h"
#include "error.h"

#include "hashtbl.h"
#include "strtbl.h"
#include "symtbl.h"

#include "iset.h"

FILE * lfptr;			/*pointer to list file*/
FILE * tfptr;			/*pointer to temporary bytecode file*/

char * lfile;			/*pointer to list file name*/
char * tfile;			/*pointer to temporary bytecode file name*/

char lfBuffer[BUFFER_SIZE];   /*output buffer for list file*/
char tfBuffer[BUFFER_SIZE];	  /*output buffer for temp file*/

int iLFChar;	/*index into lfBuffer*/
int iTFChar;	/*index into tfBuffer*/

char listingfile_line[LINE_SIZE];	/*line of text file to place in listing file*/	
char lineNumber[32];		/*line number to place in listing file*/
U1 encoded[11];				/*holds bytes to write to temp file*/

void putByteTempBuff(U1 byte);
void flushTempBuff();

void putStrLstBuff(char * str);
void putByteLstBuff(U1 byte);
void flushLstBuff();

void processDirective(struct Token *tptr, struct Line *line);
void processGDirective(struct Token *tptr, struct Line *line);
void processPDirective(struct Token *tptr, struct Line *line);

void processInstruction(struct Token *tptr);

/*print symbol table, called by generateSymbolSummary()*/
void printGlobVarToLst(struct GlobalVariable * ptr); 
void printProcToLst(struct Procedure * ptr);
void printTreeToLst(struct HashTbl* link, int level);

/*
    Instruction handling
		I = instruction opcode
		B = byte constant
		R, F, D = registers ( int, float, double )
		C = constant, varies in size
		A = identifier -> resolved to 'A'ddress
*/

void I(U1 opcode, struct Token *tptr);
	
void IB(U1 opcode, struct Token *tptr);
void IRC(U1 opcode, U1 bytes, struct Token *tptr);
void IRA(struct Token *tptr);
void I2RA(struct Token *tptr);

void IR(U1 opcode, struct Token *tptr);
void I2R(U1 opcode,struct Token *tptr);
void I3R(U1 opcode, struct Token *tptr);
void I4R(U1 opcode, struct Token *tptr);

void IRF(U1 opcode, struct Token *tptr);
void IRD(U1 opcode, struct Token *tptr);

void IFC(U1 opcode, struct Token *tptr);
void IF(U1 opcode, struct Token *tptr);
void I2F(U1 opcode, struct Token *tptr);
void I3F(U1 opcode, struct Token *tptr);
void IFR(U1 opcode, struct Token *tptr);
void IFD(U1 opcode, struct Token *tptr);

void IDC(U1 opcode, struct Token *tptr);
void ID(U1 opcode, struct Token *tptr);
void I2D(U1 opcode, struct Token *tptr);
void I3D(U1 opcode, struct Token *tptr);
void IDR(U1 opcode, struct Token *tptr);
void IDF(U1 opcode, struct Token *tptr);

void commitToFiles(U1 len);

int pass2_init()
{ 
	lfile = listFile;
	tfile = tempFile;

	if (listing == TRUE)
	{
		if (lfile == NULL)
		{
			ERROR0("pass2_init(): listing file name has not been specified\n");
			return FALSE;
		}
		lfptr = fopen(lfile, "wb");
		if (lfptr == NULL)
		{
			ERROR0("pass2_init(): could not open listing file\n");
			return FALSE;
		}
	}

	if (tfile == NULL)
	{
		ERROR0("pass2_init(): temporary file's name is NULL\n");
		return FALSE;
	}
	tfptr = fopen(tfile, "wb");
	if (tfptr == NULL)
	{
		ERROR0("pass2_init(): could not open temporary file\n");
		return FALSE;
	}
	bytePosPass2 = 0;
	iLFChar = 0;
	iTFChar = 0;
	return TRUE;

} /*end constructor*/

/*-----------------------------------------------------------------*/

void pass2_free()
{
	if (listing == TRUE)
	{
		if (lfptr != NULL)
		{
			flushLstBuff();
		    if (fclose(lfptr))
			{ 
			    ERROR1("pass2_free(): problem closing listing file %s\n", lfile); 
			}
			lfptr = NULL;
		}
	}
	
	if (tfptr != NULL)
	{
		flushTempBuff();
	    if (fclose(tfptr))
		{ 
		    ERROR1("pass2_free(): problem closing temp file %s\n", tfile); 
		}
		tfptr = NULL;
	}
	return;

}

void putByteTempBuff(U1 byte)
{
	int nbytes;
	
	nbytes = 0;

	tfBuffer[iTFChar] = byte;
	iTFChar++;

	if (iTFChar == BUFFER_SIZE)
	{
		nbytes = fwrite(tfBuffer, sizeof(U1), BUFFER_SIZE, tfptr);
		if (nbytes != BUFFER_SIZE)
		{
			ERROR1("pass2::putByteTempBuff(): error during fwrite to %s\n", tfile);
			return;
		}
		iTFChar = 0;
	}
	return;

}

void flushTempBuff()
{
	int nbytes;
	
	nbytes = 0;

	if (iTFChar > 0)
	{
		PASS2_DEBUG1("Pass2::flushTempBuff(): trying to flush %lu bytes\n", iTFChar);
		nbytes = fwrite(tfBuffer, sizeof(U1), iTFChar, tfptr);
		if(nbytes != iTFChar)
		{
			ERROR2("Pass2::flushTempBuff(): error during flush to %s ,only flushed %lu bytes\n", tfile, nbytes);
			return;
		}
		iTFChar = 0;	
	}
	return;

}

void putStrLstBuff(char * str)
{
	U4 i;
	U4 j;
	U4 size;

	size = strlen(str);
	j = 0;
	
	while ((str[j] == ' ') || (str[j] == '\t'))
		j++; 

	for (i = j; i < size; i++)
		putByteLstBuff(str[i]);
	return;

}

void putByteLstBuff(U1 byte)
{
	int nbytes;

	nbytes = 0;

	lfBuffer[iLFChar] = byte;
	iLFChar++;

	if (iLFChar == BUFFER_SIZE)
	{
		nbytes = fwrite(lfBuffer, sizeof(U1), BUFFER_SIZE, lfptr);
		if (nbytes != BUFFER_SIZE)
		{
			ERROR2("Pass2::putByteLstBuff(): error during fwrite to %s, only flushed %lu bytes\n", lfile, nbytes);
			return;
		}
		iLFChar = 0;
	}
	return;

}

void flushLstBuff()
{
	int nbytes;

	nbytes = 0;

	if (iLFChar > 0)
	{
		PASS2_DEBUG1("Pass2::flushLstBuff(): trying to flush %lu bytes\n", iLFChar);
		nbytes = fwrite(lfBuffer, sizeof(U1), iLFChar, lfptr);
		if (nbytes != iLFChar)
		{
			ERROR2("Pass2::flushLstBuff(): error during fwrite to %s, only flushed %lu bytes\n", lfile, nbytes);
			return;
		}
		iLFChar = 0;	
	}
	return;

}

void pass2_parseLine(struct Line * line)
{
	struct Token token;

	PASS2_DEBUG2("pass2_parseLine(): line->(%d)\t text->(%s)\n", (*line).line, (*line).src);

	/*
	line can be
		i) a directive ( starts with a period, i.e.  .IP )
		ii) an instruction ( opcode operand(s) )
		iii) a comment ( starts with # )
	*/
	LineTokenizer_init(line);
	token = getNextLineToken();

	if (token.type == TOK_NO_MORE)
		return;

	switch (token.text[0])
	{
	case '.':
		if (listing == TRUE) 
			processDirective(&token, line); 
		break;
		
	case '#':
		/*ignore comment line*/ 
		break;
		
	default:
		processInstruction(&token);
	}
	return;

}

/*
	Directives:
	.IP identifier							import procedure
	.IG identifier							import global variable
	.GB identifier  [ integer ] [ EXPORT ]	define global variable
	( same for .GW, .GD, .GQ )
	.PB	identifier [ EXPORT ]				procedure begin
		.PR identifier +n					procedure return value
		.PA identifier +n					procedure argument
		.PV identifier -n					procedure local variable
		.PL identifier						procedure label
	.PE
*/

void processDirective(struct Token *tptr, struct Line * line)
{
	if ((*tptr).type == TOK_IDENTIFIER)
	{
		switch ((*tptr).text[1])
		{
		case 'G':
			processGDirective(tptr,line);
			break;
			
		case 'P':
			processPDirective(tptr,line); 
			break;
			
		default:
			ERROR1("processDirective(): %s not a directive\n", (*tptr).text);
		}
	}
	else
	{
		ERROR1("processDirective(): %s not a directive\n", (*tptr).text);
	}
	return;

}

/*
.GB identifier  [ integer ] [ EXPORT ]	define global variable
	( same for .GW, .GD, .GQ )
*/

void  processGDirective(struct Token * tptr, struct Line *line)
{
	sprintf(lineNumber, "%lu", (*tptr).line);
	putStrLstBuff(lineNumber);
	putByteLstBuff(')');

	putStrLstBuff((*line).src);
	putByteLstBuff('\n');

	return;

}

/*
	.PB	identifier [ EXPORT ]				procedure begin
		.PR identifier +n					procedure return value
		.PA identifier +n					procedure argument
		.PV identifier -n					procedure local variable
		.PL identifier						procedure label
	.PE
*/

void processPDirective(struct Token * tptr, struct Line * line)
{
	if (strcmp((*tptr).text, ".PB") == 0)
	{
		/*.PB	identifier [ EXPORT ]*/
		putStrLstBuff("#++++++++++++++++++++++++++++++++++++++++\n");

		sprintf(lineNumber, "%lu", (*tptr).line);
		putStrLstBuff(lineNumber);
		putByteLstBuff(')');

		putStrLstBuff((*line).src);
		putByteLstBuff('\n');
	}    /*end .PB*/
	else 
	{
		sprintf(lineNumber, "%lu", (*tptr).line);
		putStrLstBuff(lineNumber);
		putByteLstBuff(')');
		putByteLstBuff('\t');

		putStrLstBuff((*line).src);
		putByteLstBuff('\n');	
	}
	return;

}

/*
Do not generate bytecode in first pass, but we need to know
	-offset of label directives
	-size of functions
Thus, we need to do minimal instruction processing to keep
track of bytesize via ->bytePos<- variable

use switch to help cut down on calls to strcmp()

can probably recycle basic skeleton and extend on this code for Pass2

Note: have 68 instructions total

Basic goal in each case is to populate 1/2 arrays and write them to file
	char listingfiel_line[LINE_SIZE]; -> to listing file	
	U1 encoded[11];		-> to bytecode temp file
*/

void  processInstruction(struct Token * tptr)
{
	if ((*tptr).type == TOK_IDENTIFIER)
	{
		switch((*tptr).text[0])
		{
		case 'A':
			if (strcmp((*tptr).text, "ADD") == 0)
			{ 
				I3R(ADD, tptr); 
			}
			else if (strcmp((*tptr).text, "AND") == 0)
			{ 
				I3R(AND, tptr); 
			}
			else
			{
				ERROR2("processInstruction(): line %d, invalid opcode (%s)\n", (*tptr).line, (*tptr).text);
				return;
			}
            break;
		
		case 'B':
			if (strcmp((*tptr).text, "BS") == 0)
			{ 
				I2R(BS, tptr); 
			}
			else if (strcmp((*tptr).text, "BT") == 0)
			{ 
				I3R(BT, tptr); 
			}
			else
			{
				ERROR2("processInstructionPass2(): line %d, invalid opcode (%s)\n", (*tptr).line, (*tptr).text);
				return;
			}
            break;
			
		case 'C':
			if (strcmp((*tptr).text, "CAST_IF") == 0)
			{ 
				IRF(CAST_IF, tptr);
			}
			else if (strcmp((*tptr).text, "CAST_ID") == 0)
			{ 
				IRD(CAST_ID, tptr);
			}
			else if (strcmp((*tptr).text, "CAST_FI") == 0)
			{ 
				IFR(CAST_FI, tptr);
			}
			else if (strcmp((*tptr).text, "CAST_FD") == 0)
			{ 
				IFD(CAST_FD, tptr);
			}
			else if (strcmp((*tptr).text, "CAST_DI") == 0)
			{ 
				IDR(CAST_DI, tptr);
			}
			else if (strcmp((*tptr).text, "CAST_DF") == 0)
			{ 
				IDF(CAST_DF, tptr);
			}
			else
			{
				ERROR2("processInstructionPass2(): line %d, invalid opcode (%s)\n", (*tptr).line, (*tptr).text);
				return;
			}
            break;
			
		case 'D':
			if (strcmp((*tptr).text, "DIV") == 0)
			{ 
				I4R(DIV, tptr);
			}
			else if (strcmp((*tptr).text, "DI") == 0)
			{ 
				I(DI, tptr);
			}
			else if (strcmp((*tptr).text, "DADD") == 0)
			{ 
				I3D(DADD, tptr);
			}
			else if (strcmp((*tptr).text, "DSUB") == 0)
			{ 
				I3D(DSUB, tptr);
			}
			else if (strcmp((*tptr).text, "DMULT") == 0)
			{ 
				I3D(DMULT, tptr);
			}
			else if (strcmp((*tptr).text, "DDIV") == 0)
			{ 
				I3D(DDIV, tptr);
			}
			else if (strcmp((*tptr).text, "DSLT") == 0)
			{ 
				I3D(DSLT, tptr);
			}
			else
			{
				ERROR2("processInstructionPass2(): line %d, invalid opcode (%s)\n", (*tptr).line, (*tptr).text);
				return;
			}
            break;
			
		case 'E':
			if (strcmp((*tptr).text, "EI") == 0)
			{ 
				I(EI, tptr);
			}
			else
			{
				ERROR2("processInstructionPass1(): line %d, invalid opcode (%s)\n", (*tptr).line, (*tptr).text);
				return;
			}
            break;
			
		case 'F':
			if (strcmp((*tptr).text, "FADD") == 0)
			{ 
				I3F(FADD, tptr);
			}
			else if (strcmp((*tptr).text, "FSUB") == 0)
			{ 
				I3F(FSUB, tptr);
			}
			else if (strcmp((*tptr).text, "FMULT") == 0)
			{ 
				I3F(FMULT, tptr);
			}
			else if (strcmp((*tptr).text, "FDIV") == 0)
			{ 
				I3F(FDIV, tptr);
			}
			else if (strcmp((*tptr).text, "FSLT") == 0)
			{ 
				I3F(FSLT, tptr);
			}
			else
			{
				ERROR2("processInstructionPass2(): line %d, invalid opcode (%s)\n", (*tptr).line, (*tptr).text);
				return;
			}
            break;
			
		case 'H':
			if (strcmp((*tptr).text, "HALT") == 0)
			{ 
				I(HALT, tptr);
			}
			else
			{
				ERROR2("processInstructionPass2(): line %d, invalid opcode (%s)\n", (*tptr).line, (*tptr).text);
				return;
			}
            break;
			
		case 'I':
			if (strcmp((*tptr).text, "INT") == 0)
			{ 
				IB(INT, tptr);
			}
			else
			{
				ERROR2("processInstructionPass2(): line %d, invalid opcode (%s)\n", (*tptr).line, (*tptr).text);
				return;
			}
            break;
			
		case 'J':
			if (strcmp((*tptr).text, "JMP") == 0)
			{ 
				IR(JMP, tptr);
			}
			else if (strcmp((*tptr).text, "JE") == 0)
			{ 
				I3R(JE, tptr);
			}
			else if (strcmp((*tptr).text, "JNE") == 0)
			{ 
				I3R(JNE, tptr);
			}
			else
			{
				ERROR2("processInstructionPass2(): line %d, invalid opcode (%s)\n", (*tptr).line, (*tptr).text);
				return;
			}
            break;
			
		case 'L':
			if (strcmp((*tptr).text, "LBI") == 0)
			{ 
				IRC(LBI, 1, tptr);
			}
			else if (strcmp((*tptr).text, "LWI") == 0)
			{ 
				IRC(LWI, 2, tptr);
			}
			else if (strcmp((*tptr).text, "LDI") == 0)
			{ 
				IRC(LDI, 4, tptr);
			}
			else if (strcmp((*tptr).text, "LQI") == 0)
			{ 
				IRC(LQI, 8, tptr);
			}
			else if (strcmp((*tptr).text, "LF1I") == 0)
			{ 
				IFC(LF1I, tptr);
			}
			else if (strcmp((*tptr).text, "LF2I") == 0)
			{ 
				IDC(LF2I, tptr);
			}
			else if (strcmp((*tptr).text, "LB") == 0)
			{ 
				I2R(LB, tptr);
			}
			else if (strcmp((*tptr).text, "LW") == 0)
			{ 
				I2R(LW,tptr);
			}
			else if (strcmp((*tptr).text, "LD") == 0)
			{ 
				I2R(LD, tptr);
			}
			else if (strcmp((*tptr).text, "LQ") == 0)
			{ 
				I2R(LQ, tptr);
			}
			else if (strcmp((*tptr).text, "LF1") == 0)
			{ 
				IFR(LF1, tptr);
			}
			else if (strcmp((*tptr).text, "LF2") == 0)
			{ 
				IDR(LF2, tptr);
			}
			else if (strcmp((*tptr).text, "LAD") == 0)
			{ 
				IRA(tptr);
			}
			else if (strcmp((*tptr).text, "LAI") == 0)
			{ 
				I2RA(tptr);
			}
			else
			{
				ERROR2("processInstructionPass2(): line %d, invalid opcode (%s)\n", (*tptr).line, (*tptr).text);
				return;
			}
            break;
			
		case 'M':
			if (strcmp((*tptr).text, "MOV") == 0)
			{ 
				I2R(MOV, tptr); 
			}
			else if (strcmp((*tptr).text, "MOVF") == 0)
			{ 
				I2F(MOVF, tptr); 
			}
			else if (strcmp((*tptr).text, "MOVD") == 0)
			{ 
				I2D(MOVD, tptr); 
			}
			else if (strcmp((*tptr).text, "MULT") == 0)
			{ 
				I3R(MULT, tptr);

⌨️ 快捷键说明

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