我正在尝试使用我编写的C程序读取SIC / XE程序中的行(它应该像传递SICASM汇编程序一样)。但是,如果最后一行SIC / XE代码在mneumonic之后没有操作数,程序将“挂起”(不会完成执行)。我想摆脱悬挂,组装将从那里开始。
以下是获得输入的程序:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define SIZE 51
#define LABEL_SIZE 9
#define MNEUMONIC_SIZE 8
#define OPERAND_SIZE 10
void getData(FILE* fpIn);
int hashFunc(char label[]);
unsigned long hex2int(char *a, unsigned int len);
bool checkMneumonic(char* mneumonic, int* bytes);
int main(int argc, char* argv[])
{
FILE* fpIn = fopen(argv[1], "r");
if(fpIn != NULL)
printf("\nFile open.");
else
{
printf("\nError: Main needs an input file.\n");
exit(EXIT_FAILURE);
}
getData(fpIn);
fclose(fpIn);
printf("\nFileClosed");
printf("\n\n");
return 0;
}
void getData(FILE* fpIn)
{
//debug printf("\nIn \"getData\" ");
char label[LABEL_SIZE];
char mneumonic[MNEUMONIC_SIZE];
char operand[OPERAND_SIZE];
int startAddr, currentAddr, PC = 0;
bool gotValidMneu = true;
int bytes;
//open file for writing
FILE* fpOut = fopen("output", "w");
if(fpOut != NULL)
printf("\n Ready to write.");
fprintf(fpOut,"\n\tHash\tLabel\tAddress");
char string1[10];
char string2[10];
int size;
while( fscanf(fpIn, "%s", string1) != EOF)
{
gotValidMneu = true;
if(strcmp(string1, "LTORG") == 0)
strcpy(string2, " ");
else if(strcmp(string1, "RSUB") == 0)
strcpy(string2, " ");
else if(!feof(fpIn) && fgetc(fpIn) != '\n')
fscanf(fpIn,"%s", string2);
if(checkMneumonic(string1, &size) && !feof(fpIn))
{
strcpy(mneumonic, string1);
strcpy(operand, string2);
strcpy(label, " ");
}
else if(checkMneumonic(string2, &size) && !feof(fpIn))
{
strcpy(label, string1);
strcpy(mneumonic, string2);
fscanf(fpIn, "%s[\n]", operand);
}
else if( string1[0] == '.')
{
char junk[80];
fgets(junk, 80, fpIn);
gotValidMneu = false;
}
else
{
printf("\nError: got invalid mneumonic");
gotValidMneu = false;
}
if(gotValidMneu)
{
//adjust the current address
currentAddr = PC;
//get the starting address
if(strcmp(mneumonic, "START") == 0)
{
startAddr = hex2int(operand, strlen(operand) );
PC = startAddr;
}
//mneumonic is "BASE"
else if(strcmp(mneumonic, "BASE") == 0);
//mneumonic is "RESW"
else if(strcmp(mneumonic, "RESW") == 0)
{
PC += (3 * atoi(operand) );
}
//mneumonic is "BYTE"
else if(strcmp(mneumonic, "BYTE") == 0 )
{
PC += atoi(operand);
}
//mneumonic is "END"
else if(strcmp(mneumonic, "END") == 0);
//check if the mneumonic is valid
else if(checkMneumonic(mneumonic, &bytes) )
{
PC += bytes;
}
//got a bad mneumonic
else
{
gotValidMneu = false;
printf("\nError: \"%s\" is not a valid mneumonic.", mneumonic);
fprintf(fpOut,"\nError: \"%s\" is not a valid mneumonic.",
mneumonic);
}
if(gotValidMneu)
{
if(strcmp(label, " ") != 0 )
fprintf(fpOut,"\n\t%d\t%s\t%x", hashFunc(label), label,
currentAddr);
printf("\n%x\t%s\t%s\t%s", currentAddr, label, mneumonic, operand);
}
}
if(gotValidMneu)
//flush the comments, if any
while( '\n' != getc(fpIn) )
getc(fpIn);
} //end while
fprintf(fpOut,"\n");
fclose(fpOut);
printf("\n Symbol table sent to file: \"output\".");
}
int hashFunc(char label[])
{
int i, sum, hashVal;
sum = 0;
for(i = 0; i < strlen(label); i++)
sum += label[i];
hashVal = sum % SIZE;
// printf("\nHashed Index: %d", hashVal);
return hashVal;
}
unsigned long hex2int(char *a, unsigned int len)
{
int i;
unsigned long val = 0;
for(i=0;i<len;i++)
if(a[i] <= 57)
val += (a[i]-48)*(1<<(4*(len-1-i)));
else
val += (a[i]-55)*(1<<(4*(len-1-i)));
return val;
}
bool checkMneumonic(char mneumonic[], int* bytes)
{
bool valid = false;
char validMneumonic[MNEUMONIC_SIZE];
FILE* fpIn = fopen("sicOps", "r");
while( (fscanf(fpIn, "%s %d", validMneumonic, bytes) != EOF) )
{
if(strcmp(mneumonic, validMneumonic) == 0 )
{
valid = true;
break;
}
}
fclose(fpIn);
return valid;
}
这是我用来测试它的文件:
ADDRES START 100
. tests pc forward addressing
. tests base addressing
. tests pc backward addressing
NOW +LDB #BEGIN load base register
XXX BASE BEGIN tell assembler
YYY LDA BE A <- (m..m+2)
EN RESW 4
BE WORD 2
BEGIN RESW 1
JUNK RESW 2200
THERE RESW 1
ZZZ LDA JUNK
MMM STA THERE
END
编辑:有很多新代码。我删减了原始程序,编译并测试了它并且它挂了。
答案 0 :(得分:4)
您的I / O代码非常复杂(对于如此少的代码行)。
最好将整行读入缓冲区,然后分析缓冲区(在内存中),而不是试着动态决定如何构建阅读。
只需使用fgets()
加载行,或getline()
如果有加载行。
在回复评论时,确定你仍然需要决定如何解析这一行,但你不会冒“挂”程序等待不存在的输入。
您的行似乎由最多三个标记组成,由空格分隔,可选地后跟一个跨越行末尾的注释。要弄清楚如何把它拆分成这些碎片应该不会太难。
答案 1 :(得分:1)
使用fgets,然后使用tokenizer将字符串标记为'space'。简单的for循环中的strtok将使它变得更容易。
答案 2 :(得分:1)
我看不到你发布的代码是如何挂起的,无论是通过等待来自文件的输入还是通过循环,所以看起来实际的问题在程序的其他地方。也许与发布的片段结合使用。
但我发现你使用的是 feof ,这在C程序中几乎总是错误的,因为只有在之后才会返回true 。改为使用各种输入调用的返回值。
编辑:
我实际上尝试了你的代码,添加了使它成为一个完整的,可编译的程序所需的最少代码,并在你的示例输入上尝试了它。它没有挂起。您应该总是尝试发布一个最小的工作程序 仍然会出现问题。现在你删除了似乎相关的部分。