Как мне удержать эту программу на C от "зависания"? - PullRequest
4 голосов
/ 19 марта 2012

Я пытаюсь прочитать строки из SIC / XE-программы, используя написанную мною программу на C (она должна действовать как pass один из ассемблера SICASM). Однако программа «зависнет» (не завершит выполнение), если последняя строка кода SIC / XE не имеет операнда после мнемоники. Хотелось бы просто избавиться от зависания, оттуда последует сборка.

Вот часть моей программы, которая получает ввод:

#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 

РЕДАКТИРОВАТЬ: есть много нового кода. Я урезал оригинальную программу, скомпилировал и протестировал ее, и она зависает.

Ответы [ 3 ]

4 голосов
/ 19 марта 2012

Ваш код ввода / вывода фантастически сложен (для таких нескольких строк кода).

Гораздо лучше прочитать целые строки в буфере, а затем проанализировать этот буфер (в памяти), вместо того, чтобы на лету решить, как структурировать чтение.

Просто используйте fgets() для загрузки строк или getline(), если он у вас есть.

В ответ на комментарий, конечно, вам все еще нужно решить, как анализировать строку, но вы не рискуете «повесить» программу, ожидающую ввода, которого там нет.

Кажется, что ваши строки состоят из трех токенов, разделенных пробелами, за которыми, возможно, следует комментарий, который простирается до конца строки. Не должно быть слишком сложно понять, как разбить его на части.

1 голос
/ 19 марта 2012

Я не вижу, как код, который вы разместили, мог зависнуть, либо в ожидании ввода из файла, либо в цикле, поэтому кажется, что настоящая проблема в другом месте вашей программы. Возможно в сочетании с размещенным фрагментом.

Но я вижу, что вы используете feof , что почти всегда неправильно в программе на C, поскольку оно вернет true только после , когда вы достигли конца файла. Вместо этого используйте возвращаемые значения из различных входных вызовов.

EDIT:

Я на самом деле попробовал ваш код, добавив минимальный код, необходимый для того, чтобы сделать его полноценной, компилируемой программой, и попробовал его на вашем примере ввода. Это не зависало. Вы всегда должны пытаться опубликовать минимальную рабочую программу , в которой все еще присутствует проблема . Теперь вы удалили части, которые, по-видимому, были актуальны.

1 голос
/ 19 марта 2012

Используйте fgets, а затем добавьте токен в строку, используя tokenizer в качестве «пробела». strtok в простом цикле for сделает это намного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...