IdeaSpy
IdeaSpy

Reputation: 43

How do I keep this C program from "hanging"?

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

Answers (3)

Thomas Padron-McCarthy
Thomas Padron-McCarthy

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

unwind
unwind

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

P.P
P.P

Reputation: 121407

Use fgets and then tokening the string using with tokenizer as 'space'. strtok in a simple for loop will make it a lot easier.

Upvotes: 1

Related Questions