📄 pass1.c
字号:
#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 + -