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