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

📄 pass1.c

📁 < 虚拟机设计与实现>>的 windows版本
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "pass1.h"

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

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

static U4 currentProcPass1;	/*index into symTbl of current procedure*/
static U8 bytePosPass1;		/*current index of bytecode being generated*/
static U8 globalTotal;			/*current total size of globals*/

void  pass1_processDirective(struct Token *tptr);
void  pass1_processGDirective(struct Token *tptr);
void  pass1_processPDirective(struct Token *tptr);

void  pass1_processInstruction(struct Token *tptr);

void pass1_init()
{
	currentProcPass1 = OUTSIDE_PROC_PASS1;
	bytePosPass1 = 0;
	globalTotal = 0;
	return;

}

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

	PASS1_DEBUG2("pass1_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 '.' :
		pass1_processDirective(&token);
		break;
		
	case '#' :
		/*comment, ignore line*/
		break;
		
	default:
		pass1_processInstruction(&token);
	}
	return;

}

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

void  pass1_processDirective(struct Token *tptr)
{
	if ((*tptr).type == TOK_IDENTIFIER)
	{
		switch((*tptr).text[1])
		{
		case 'G':
			pass1_processGDirective(tptr); 
			break;
			
		case 'P':
			pass1_processPDirective(tptr); 
			break;
			
		default:
			ERROR2("pass1_processDirective(): %s not directive, line %lu\n",
				       (*tptr).text,
					   (*tptr).line);		
		}
	}
	else
	{
		ERROR2("pass1_processDirective(): %s not directive, line %lu\n",
			           (*tptr).text,
					   (*tptr).line);
	}
	return;

}

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

void pass1_processGDirective(struct Token *tptr)
{
	struct GlobalVariable gv;
	struct Token t;
	struct HashTbl * hptr; /*returned from hash table*/
	U1 bret;

	/*global variable metadata*/
	char id[ID_SIZE];
	U1 dtype;
	U8 length;
	U8 size;
	U8 offset;
	U4 line;

	switch ((*tptr).text[2]) /*.GB identifier  [ integer ]*/
	{
	/*third char, text[2], gives datatype*/
	case 'B':
		dtype = SZ_BYTE; 
		break;
		
	case 'W':
		dtype = SZ_WORD; 
		break;
		
	case 'D':
		dtype = SZ_DWORD; 
		break;
		
	case 'Q':
		dtype = SZ_QWORD; 
		break;
		
	default:
		ERROR2("pass1_processGDirective(): line %d, invalid global data type (%s)\n",
			           (*tptr).line,
					   (*tptr).text);
		return;
		
	}

	/*set some defaults*/
	length = 1;
	size = dtype * length; 
	offset = 0;
	line = (*tptr).line;

	bret = match(&t, TOK_IDENTIFIER);
	if (bret != TRUE)
	{ 
		ERROR1("pass1_processGDirective(): line %d, global missing identifier\n",
			            (*tptr).line);
		return; 
	}

	strcpy(id, t.text);
	PASS1_DEBUG2("pass1_processGDirective(): .GX %s=%s\n", TokStr[t.type], t.text);
		
	/*
	the [integer] modifiers is optional
	so we cannot use match() because there are 2 correct ways
	
	i)	 .GX identifier integer EOL
	ii)  .GX identifier EOL
	*/

	t = getNextLineToken();

	if (t.type == TOK_INT_CONST)
	{
		/* .GX identifier integer EOL */
		PASS1_DEBUG2("pass1_processGDirective(): nElements %s = %lu\n", 
			          TokStr[t.type], t.val);
			
		length = (U8)t.val;
		size = dtype * length;

		globalTotal = globalTotal + size;
		offset = globalTotal;

		bret = match(&t, TOK_NO_MORE);
		if (bret == FALSE)
		{ 
			ERROR1("pass1_processGDirective(): line %d, bad global declaration\n", 
				    (*tptr).line);
			return; 
		}
	}
	else if (t.type == TOK_NO_MORE)
	{
		/*.GX identifier EOL*/
		size = dtype;
		globalTotal = globalTotal + size;
		offset = globalTotal;
	}
	else 
	{
		/*.GX identifer XXXX */
		ERROR1("pass1_processGDirective(): line %d, bad global declaration\n", 
			     (*tptr).line);
		return; 
	}
	
	/*if evade all errors, add .GB entry*/

	PASS1_DEBUG0("pass1_processGDirective(): adding .GX to symbol table\n");
	hptr =  queryHashTbl(id);
	if (hptr != NULL)
	{
		ERROR2("Pass1_processGDirective(): line %d, %s re-defined\n", line, id);
		return;
	}
	else if (currentProcPass1 != OUTSIDE_PROC_PASS1)
	{
		ERROR1("Pass1_processGDirective(): line %d, .GX declaration inside proc.\n", line);
		return;
	}
	else
	{		
		gv.text = strtbl_iStr;
		gv.dType = dtype;
		gv.len = length;
		gv.size = size;
		gv.offset = offset;
		gv.line= line;
		addStrTbl(id);
		addGlobVar(&gv);
		addHashTblEntry(id, gv.text, GLOBAL_VAR, iGlobVar - 1, 0, line);
	}
	return;

}

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

void  pass1_processPDirective(struct Token * tptr)
{
	struct Token t;
	U1 bRet;
	char name[ID_SIZE];
	struct Procedure p;
	struct StackFrame sf;
	struct Label lb;
	U8 address;
	U4 line;
	S4 offset;
	struct HashTbl * hptr;

    /*set some defaults*/
	address = 0;
	line  = (*tptr).line;
	offset = 0;

	if (strcmp((*tptr).text, ".PB") == 0)  
	{
		/*.PB	identifier EOL*/

		bRet = match(&t, TOK_IDENTIFIER);
		if (bRet != TRUE)
		{
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return; 
		}
		
		strcpy(name, t.text);
		address = bytePosPass1;

		PASS1_DEBUG2("pass1_processPDirective(): .PB identifier %s=%s\n", TokStr[t.type], t.text);

		bRet = match(&t, TOK_NO_MORE);
		if (bRet == FALSE)
		{ 
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return; 
		}	
		
		PASS1_DEBUG0("pass1_processPDirective(): adding .PB to symbol table\n");

		hptr =  queryHashTbl(name);
		if (hptr != NULL)
		{
			ERROR2("pass1_processPDirective(): line %d, %s re-definition\n", line, name);
			return;
		}
		else if (currentProcPass1 != OUTSIDE_PROC_PASS1)
		{
			ERROR2("pass1_processPDirective(): line %d, %s, cannot nest procedures\n", line, name);
			return;
		}
		else
		{
			p.text = strtbl_iStr;
			p.address = address;
			p.line = line;
			addStrTbl(name);
			addProc(&p);
			addHashTblEntry(name, p.text, PROC, iProc - 1, 0, line);
			currentProcPass1 = iProc - 1;
		}
	}  /*end .PB*/
	else if (strcmp((*tptr).text, ".PR") == 0)	
	{
		/*.PR identifier +n	*/
		bRet = match(&t, TOK_IDENTIFIER);
		if (bRet != TRUE)
		{
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return;
		}
		strcpy(name, t.text);

		bRet = match(&t, TOK_INT_CONST);
		if (bRet != TRUE)
		{
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return;
		}
		offset = (S4)t.val;

		bRet = match(&t, TOK_NO_MORE);
		if (bRet != TRUE)
		{ 
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return; 
		}
			
		PASS1_DEBUG0("pass1_processPDirective(): adding .PR to symbol table\n");

		hptr =  queryHashTbl(name);
		if (hptr != NULL)
		{
			ERROR2("pass1_processPDirective(): line %d, %s re-defined\n", line, name);
			return;
		}
		else if (currentProcPass1 == OUTSIDE_PROC_PASS1)
		{
			ERROR2("pass1_processPDirective(): line %d, .PR %s declaration not in a proc\n", line, name);
			return;
		}
		else
		{
			sf.text = strtbl_iStr;
			sf.fpOffset = offset;
			sf.line = line;
			addStrTbl(name);
			bRet = setProcRetHL(&sf);
			if (bRet == FALSE)
				return;
			addHashTblEntry(name, sf.text, PROC_RET, iProc - 1, 0, line);
		}
	} /*end .PR*/
	else if (strcmp((*tptr).text, ".PA") == 0)	
	{
		/*.PA identifier +n*/

		bRet = match(&t, TOK_IDENTIFIER);
		if (bRet != TRUE)
		{
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return;
		}
		strcpy(name, t.text);

		bRet = match(&t, TOK_INT_CONST);
		if (bRet != TRUE)
		{
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return;
		}
		offset = (S4)t.val;

		bRet = match(&t, TOK_NO_MORE);
		if (bRet != TRUE)
		{ 
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return; 
		}
				
		PASS1_DEBUG0("pass1_processPDirective(): adding .PA to symbol table\n");

		hptr = queryHashTbl(name);
		if (hptr != NULL)
		{
			ERROR2("pass1_processPDirective(): line %d, %s re-defined\n", line, name);
			return;
		}
		else if (currentProcPass1 == OUTSIDE_PROC_PASS1)
		{
			ERROR2("pass1_processPDirective(): line %d, .PR %s declaration not in a proc\n", line, name);
			return;
		}
		else
		{
			sf.text = strtbl_iStr;
		    sf.fpOffset = offset;
		    sf.line = line;
		    addStrTbl(name);
		    addProcArgHL(&sf);
		    addHashTblEntry(name, sf.text, PROC_ARG, iProc - 1,(proc[iProc - 1].iArg - 1), line);
		}
	} /*end .PA*/
	else if (strcmp((*tptr).text, ".PV") == 0)	
	{
		/*.PV identifier -n*/

		bRet = match(&t, TOK_IDENTIFIER);
		if (bRet != TRUE)
		{
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return;
		}
		strcpy(name, t.text);

		bRet = match(&t, TOK_INT_CONST);
		if (bRet != TRUE)
		{
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return;
		}
		offset = (S4)t.val;

		bRet = match(&t, TOK_NO_MORE);
		if (bRet != TRUE)
		{
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return;
		}
		
		PASS1_DEBUG0("pass1_processPDirective(): adding .PV to symbol table\n");

		hptr =  queryHashTbl(name);
		if (hptr != NULL)
		{
			ERROR2("pass1_processPDirective(): line %d, %s re-defined\n", line, name);
			return;
		}
		else if (currentProcPass1 == OUTSIDE_PROC_PASS1)
		{
			ERROR2("pass1_processPDirective(): line %d, .PV %s declaration not in a proc\n", line, name);
			return;
		}
		else
		{
			sf.text = strtbl_iStr;
		    sf.fpOffset = (S4)offset;
		    sf.line = line;
		    addStrTbl(name);
		    addProcLocHL(&sf);
		    addHashTblEntry(name, sf.text, PROC_LOC, iProc - 1, (proc[iProc - 1].iLocal - 1), line);
		}
	}   /*end .PV*/
	else if (strcmp((*tptr).text, ".PL") == 0)
	{
		/*.PL identifier*/
		
		bRet = match(&t, TOK_IDENTIFIER);
		if (bRet != TRUE)
		{
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return;
		}
		strcpy(name, t.text);
		address = bytePosPass1;

		bRet = match(&t, TOK_NO_MORE);
		if (bRet != TRUE)
		{
			ERROR1("pass1_processPDirective(): line %lu, bad directive\n", line);
			return;
		}
	
		PASS1_DEBUG0("pass1_processPDirective(): adding .PL to symbol table\n");

		hptr = queryHashTbl(name);
		if (hptr != NULL)
		{
			ERROR2("pass1_processPDirective(): line %d, %s re-defined\n", line, name);
			return;
		}
		else if (currentProcPass1 == OUTSIDE_PROC_PASS1)
		{
			ERROR2("pass1_processPDirective(): line %d, .PR %s declaration not in a proc\n", line, name);
			return;
		}
		else

⌨️ 快捷键说明

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