📄 tm.c
字号:
/* File: tm.c
* The TM ( Tiny Machine ) computer
* K. C. Louden CCPP-C
*
* Compiler Construction: Principles and Practice
* Kenneth C. Louden
* 编译原理及实践
* (美) Kenneth C. Louden 著
* 冯博琴 冯岚 等译
* 机械工业出版社 IBSN 7-111-07703-2
* 源代码:zwf编辑并修订
* Code Modify: Larry Li 2001.11
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
//#define CHINESE
/* const */
#define IADDR_SIZE 1024
#define DADDR_SIZE 1024
#define NO_REGS 8
#define PC_REG 7
#define LINESIZE 121
#define WORDSIZE 20
/* type */
typedef enum {
opclRR,
opclRM,
opclRA
} OPCLASS;
typedef enum {
opHALT,
opIN,
opOUT,
opADD,
opSUB,
opMUL,
opDIV,
opRRLim,
opLD,
opST,
opRMLim,
opLDA,
opLDC,
opJLT,
opJLE,
opJGT,
opJGE,
opJEQ,
opJNE,
opRALim
} OPCODE;
typedef enum {
srOKAY,
srHALT,
srIMEM_ERR,
srDMEM_ERR,
srZERODIVIDE
} STEPRESULT;
typedef struct {
int iop;
int iarg1;
int iarg2;
int iarg3;
} INSTRUCTION;
/* vars */
int iloc = 0;
int dloc = 0;
int traceflag = FALSE;
int icountflag = FALSE;
INSTRUCTION iMem[IADDR_SIZE];
int dMem[DADDR_SIZE];
int reg[NO_REGS];
char *opCodeTab[] = {
"HALT", "IN", "OUT", "ADD", "SUB", "MUL", "DIV", "????",
"LD", "ST", "????",
"LDA", "LDC", "JLT", "JLE", "JGT", "JGE", "JEQ", "JNE", "????"
};
#ifdef CHINESE
char *stepResultTab[] = {
"就绪", "停止", "初始化内存失败",
"数据储存失败", "零除错误"
};
#else
char *stepResultTab[] = {
"OK", "Halted", "Instruction Memory Fault",
"Data Memory Fault", "Division by 0"
};
#endif
char pgmName[20];
FILE *pgm;
char in_Line[LINESIZE];
int lineLen;
int inCol;
int num;
char word[WORDSIZE];
char ch;
int done;
/* opClass */
int opClass(int c)
{
if (c <= opRRLim)
return opclRR;
if (c <= opRMLim)
return opclRM;
return opclRA;
}
/* writeInstruction */
void writeInstruction(int loc)
{
printf("%5d: ", loc);
if ((loc >= 0) && (loc < IADDR_SIZE)) {
printf("%6s%3d,", opCodeTab[iMem[loc].iop], iMem[loc].iarg1);
switch (opClass(iMem[loc].iop)) {
case opclRR:
printf("%1d,%1d", iMem[loc].iarg2, iMem[loc].iarg3);
break;
case opclRM:
case opclRA:
printf("%3d(%1d)", iMem[loc].iarg2, iMem[loc].iarg3);
break;
}
printf("\n");
}
}
/* getCh */
void getCh(void)
{
if (++inCol < lineLen)
ch = in_Line[inCol];
else
ch = ' ';
}
/* nonBlank */
int nonBlank(void)
{
while ((inCol < lineLen) && (in_Line[inCol] == ' '))
inCol++;
if (inCol < lineLen) {
ch = in_Line[inCol];
return TRUE;
} else {
ch = ' ';
return FALSE;
}
}
/* getNum */
int getNum(void)
{
int sign;
int term;
int temp = FALSE;
num = 0;
do {
sign = 1;
while (nonBlank() && ((ch == '+') || (ch == '-'))) {
temp = FALSE;
if (ch == '-')
sign = -sign;
getCh();
}
term = 0;
nonBlank();
while (isdigit(ch)) {
temp = TRUE;
term = term * 10 + (ch - '0');
getCh();
}
num += term * sign;
} while ((nonBlank()) && ((ch == '+') || (ch == '-')));
return temp;
}
/* getWord */
int getWord(void)
{
int temp = FALSE;
int length = 0;
if (nonBlank()) {
while (isalnum(ch)) {
if (length < WORDSIZE - 1)
word[length++] = ch;
getCh();
}
word[length] = '\0';
temp = (length != 0);
}
return temp;
}
/* skipCh */
int skipCh(char c)
{
int temp = FALSE;
if (nonBlank() && (ch == c)) {
getCh();
temp = TRUE;
}
return temp;
}
/* atEOL */
int atEOL(void)
{
return (!nonBlank());
}
/* error */
int error(char *msg, int lineNo, int instNo)
{
#ifdef CHINESE
printf("第 %d 行", lineNo);
#else
printf("Line %d", lineNo);
#endif
if (instNo >= 0)
#ifdef CHINESE
printf(" (指令 %d)", instNo);
#else
printf(" (Instruction %d)", instNo);
#endif
printf(" %s\n", msg);
return FALSE;
}
/* readInstructions */
int readInstructions(void)
{
OPCODE op;
int arg1, arg2, arg3;
int loc, regNo, lineNo;
for (regNo = 0; regNo < NO_REGS; regNo++)
reg[regNo] = 0;
dMem[0] = DADDR_SIZE - 1;
for (loc = 1; loc < DADDR_SIZE; loc++)
dMem[loc] = 0;
for (loc = 0; loc < DADDR_SIZE; loc++) {
iMem[loc].iop = opHALT;
iMem[loc].iarg1 = 0;
iMem[loc].iarg2 = 0;
iMem[loc].iarg3 = 3;
}
lineNo = 0;
while (!feof(pgm)) {
fgets(in_Line, LINESIZE - 2, pgm);
inCol = 0;
lineNo++;
lineLen = strlen(in_Line) - 1;
if (in_Line[lineLen] == '\n')
in_Line[lineLen] = '\0';
else
in_Line[++lineLen] = '\0';
if ((nonBlank()) && (in_Line[inCol] != '*')) {
if (!getNum())
#ifdef CHINESE
return error("地址错误", lineNo, -1);
#else
return error("Bad location", lineNo, -1);
#endif
loc = num;
if (loc > IADDR_SIZE)
#ifdef CHINESE
return error("地址太大", lineNo, loc);
#else
return error("Location too large", lineNo, loc);
#endif
if (!skipCh(':'))
#ifdef CHINESE
return error("丢失冒号", lineNo, loc);
#else
return error("Missing colon", lineNo, loc);
#endif
if (!getWord())
#ifdef CHINESE
return error("丢失操作符", lineNo, loc);
#else
return error("Missing opcode", lineNo, loc);
#endif
op = opHALT;
while ((op < opRALim)
&& (strncmp(opCodeTab[op], word, 4) != 0))
op++;
if (strncmp(opCodeTab[op], word, 4) != 0)
#ifdef CHINESE
return error("丢失操作数", lineNo, loc);
#else
return error("Illegal opcode", lineNo, loc);
#endif
switch (opClass(op)) {
case opclRR:
if ((!getNum()) || (num < 0) || (num >= NO_REGS))
#ifdef CHINESE
return error("第一个数据错误", lineNo, loc);
#else
return error("Bad first register", lineNo, loc);
#endif
arg1 = num;
if (!skipCh(','))
#ifdef CHINESE
return error("丢失逗号", lineNo, loc);
#else
return error("Missing comma", lineNo, loc);
#endif
if ((!getNum()) || (num < 0) || (num >= NO_REGS))
#ifdef CHINESE
return error("第二个数据错误", lineNo, loc);
#else
return error("Bad second register", lineNo, loc);
#endif
arg2 = num;
if (!skipCh(','))
#ifdef CHINESE
return error("丢失逗号", lineNo, loc);
#else
return error("Missing comma", lineNo, loc);
#endif
if ((!getNum()) || (num < 0) || (num >= NO_REGS))
#ifdef CHINESE
return error("第三个数据错误", lineNo, loc);
#else
return error("Bad third register", lineNo, loc);
#endif
arg3 = num;
break;
case opclRM:
case opclRA:
if ((!getNum()) || (num < 0) || (num >= NO_REGS))
#ifdef CHINESE
return error("第一个数据错误", lineNo, loc);
#else
return error("Bad first register", lineNo, loc);
#endif
arg1 = num;
if (!skipCh(','))
#ifdef CHINESE
return error("丢失逗号", lineNo, loc);
#else
return error("Missing comma", lineNo, loc);
#endif
if (!getNum())
#ifdef CHINESE
return error("错误位移数据", lineNo, loc);
#else
return error("Bad displacement", lineNo, loc);
#endif
arg2 = num;
if (!skipCh('(') && !skipCh(','))
#ifdef CHINESE
return error("丢失左括号", lineNo, loc);
#else
return error("Missing LParen", lineNo, loc);
#endif
if ((!getNum()) || (num < 0) || (num >= NO_REGS))
#ifdef CHINESE
return error("第二个数据错误", lineNo, loc);
#else
return error("Bad second register", lineNo, loc);
#endif
arg3 = num;
break;
}
iMem[loc].iop = op;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -