How to save this program in C from "freezing"?

I am trying to read lines from a SIC / XE program using the C program I wrote (it should act like passing one of the SICASM assembler). However, the program will “freeze” (will not finish execution) if the last line of SIC / XE code does not have an operand after mneumonic. I just wanted to get rid of the hanging, the assembly will follow from there.

Here is the part of my program that gets 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 use to check 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 cut the original program, compiled and tested it, and it freezes.

+4
source share
3 answers

I don’t see how the code you posted can hang, either waiting for input from a file, or by looping, so it seems that the actual problem is located elsewhere in your program. Perhaps in combination with a published 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 get to the end of the file. Use return values ​​from various input calls instead.

EDIT:

I really tried your code, adding the minimum code needed to create a complete compiled program, and tried it on your input example. It did not hang. You should always try to publish a minimal work program that still detects the problem. Now you have removed the parts that seemed to be relevant.

+1
source

Your input / output code is fantastically complex (for such a few lines of code).

It is much better to read entire lines in a buffer and then parse that buffer (in memory), rather than trying to decide on the fly how to structure your reading.

Just use fgets() to load the lines or getline() if you have any.

In response to the comment, you still need to decide how to parse the line, but you do not run the risk of “hanging” a program that expects input that does not exist.

Your lines appear to consist of three tokens, separated by spaces, optionally followed by a comment that spans the end of the line. It should not be too difficult to understand how to divide it into parts.

+4
source

Use fgets, and then mark the line using tokenizer as a space. strtok in a simple loop will be much simpler.

+1
source

Source: https://habr.com/ru/post/1402271/


All Articles