Reputation: 43
I'm trying to read lines from a SIC/XE program using a C program that I wrote (it's supposed to act like pass one of the SICASM assembler). However, the program will "hang" (won't finish executing) if the last line of SIC/XE code doesn't have an operand after the mneumonic. I would just like to get rid of the hanging, the assembly will follow from there.
Here is the piece of my program that gets the input:
#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;
}
And here is the file that I'm using to test it:
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
EDIT: There is a lot of new code. I trimmed down the original program, compiled and tested it and it hangs.
Upvotes: 4
Views: 678
Reputation: 27652
I don't see how the code that you posted could hang, either by waiting for input from a file or by looping, so it seems that the actual problem is elsewhere in your program. Perhaps in a combination with the posted snippet.
But I see that you use feof, which is almost always wrong in a C program, since it will return true only after you have hit the end of the file. Use the return values from the various input calls instead.
EDIT:
I actually tried your code, by adding the minimal code needed to make it a complete, compilable program, and tried it on your example input. It didn't hang. You should always try to post a minimal, working program that still exhibits the problem. Now you removed parts that seem to have been relevant.
Upvotes: 1
Reputation: 400019
Your I/O code is fantastically complex (for such few lines of code).
It's much better to read whole lines into a buffer, and then analyze that buffer (in memory), instead of trying to decide on the fly how to structure your reading.
Just use fgets()
to load lines, or getline()
if you have it.
In response to the comment, sure you still need to decide how to parse the line, but you won't risk "hanging" the program waiting for input that isn't there.
Your lines seem to consist of up to three tokens, separated by whitespace, optionally followed by a comment that spans to the end of the line. It shouldn't be too hard to figure out how to pick it apart into those pieces.
Upvotes: 4