Esempio n. 1
0
static void performCommand(char *acLine, DynArray_T oHistoryList, 
                           char *pcProgName)

/* Expand any !commandprefix in acLine. Insert acLine into 
   oHistoryList iff the expanding succeeds and acLine does not consist
   of entirely whitespace characters. Lexically and syntactically 
   analyze acLine. Execute acLine if no errors are found. It is a 
   checked runtime error for acLine, oHistory, or pcProgName to be
   NULL. */

{
   char *pcTemp;
   Command_T oCommand;
   DynArray_T oTokens;
   int iSuccessful;

   assert(acLine != NULL);
   assert(oHistoryList != NULL);
   assert(pcProgName != NULL);

   if(histHasCommandPrefix(acLine))
   {
      iSuccessful = histExpandLine(acLine, oHistoryList, pcProgName);
      if(iSuccessful)
         printf("%s\n", acLine);
      else
         return;
   }
   oTokens = DynArray_new(0);
   iSuccessful = lexLine(acLine, oTokens, pcProgName);
   if(DynArray_getLength(oTokens) > 0)
   {
      /* Allocate memory to store command in oHistoryList iff 
         command does not consist of entirely whitespace
         characters. */
      pcTemp = (char*)malloc(strlen(acLine) + 1);
      assert(pcTemp != NULL);
      strcpy(pcTemp, acLine);
      DynArray_add(oHistoryList, pcTemp);

      if(iSuccessful)
      {
         oCommand = Command_new();
         iSuccessful = parseToken(oTokens, oCommand, pcProgName);
         if(iSuccessful)
            execute(oCommand, oHistoryList, pcProgName);
         Command_free(oCommand, NULL);
      }
   }
   DynArray_map(oTokens, Token_free, NULL);
   DynArray_free(oTokens);
}
Esempio n. 2
0
static DynArray_T lexLine(const char *pcLine)
{
   /* lexLine() uses a DFA approach.  It "reads" its characters from
      pcLine. The DFA has these three states: */
   enum LexState {STATE_START, STATE_IN_NUMBER, STATE_IN_WORD};

   /* The current state of the DFA. */
   enum LexState eState = STATE_START;

   /* An index into pcLine. */
   int iLineIndex = 0;

   /* Pointer to a buffer in which the characters comprising each
      token are accumulated. */
   char *pcBuffer;

   /* An index into the buffer. */
   int iBufferIndex = 0;

   char c;
   struct Token *psToken;
   DynArray_T oTokens;
   int iSuccessful;

   assert(pcLine != NULL);

   /* Create an empty token DynArray object. */
   oTokens = DynArray_new(0);
   if (oTokens == NULL)
      {perror(pcPgmName); exit(EXIT_FAILURE);}

   /* Allocate memory for a buffer that is large enough to store the
      largest token that might appear within pcLine. */
   pcBuffer = (char*)malloc(strlen(pcLine) + 1);
   if (pcBuffer == NULL)
      {perror(pcPgmName); exit(EXIT_FAILURE);}

   for (;;)
   {
      /* "Read" the next character from pcLine. */
      c = pcLine[iLineIndex++];

      switch (eState)
      {
         /* Handle the START state. */
         case STATE_START:
            if (c == '\0')
            {
               free(pcBuffer);
               return oTokens;
            }
            else if (isdigit(c))
            {
               pcBuffer[iBufferIndex++] = c;
               eState = STATE_IN_NUMBER;
            }
            else if (isalpha(c))
            {
               pcBuffer[iBufferIndex++] = c;
               eState = STATE_IN_WORD;
            }
            else if (isspace(c))
               eState = STATE_START;
            else
            {
               fprintf(stderr, "Invalid line\n");
               free(pcBuffer);
               freeTokens(oTokens);
               DynArray_free(oTokens);
               return NULL;
            }
            break;

         /* Handle the IN_NUMBER state. */
         case STATE_IN_NUMBER:
            if (c == '\0')
            {
               /* Create a NUMBER token. */
               pcBuffer[iBufferIndex] = '\0';
               psToken = newToken(TOKEN_NUMBER, pcBuffer);
               iSuccessful = DynArray_add(oTokens, psToken);
               if (! iSuccessful)
                  {perror(pcPgmName); exit(EXIT_FAILURE);}
               iBufferIndex = 0;
               free(pcBuffer);
               return oTokens;
            }
            else if (isdigit(c))
            {
               pcBuffer[iBufferIndex++] = c;
               eState = STATE_IN_NUMBER;
            }
            else if (isspace(c))
            {
               /* Create a NUMBER token. */
               pcBuffer[iBufferIndex] = '\0';
               psToken = newToken(TOKEN_NUMBER, pcBuffer);
               iSuccessful = DynArray_add(oTokens, psToken);
               if (! iSuccessful)
                  {perror(pcPgmName); exit(EXIT_FAILURE);}
               iBufferIndex = 0;
               eState = STATE_START;
            }
            else
            {
               fprintf(stderr, "Invalid line\n");
               free(pcBuffer);
               freeTokens(oTokens);
               DynArray_free(oTokens);
               return NULL;
            }
            break;

         /* Handle the IN_WORD state. */
         case STATE_IN_WORD:
            if (c == '\0')
            {
               /* Create a WORD token. */
               pcBuffer[iBufferIndex] = '\0';
               psToken = newToken(TOKEN_WORD, pcBuffer);
               iSuccessful = DynArray_add(oTokens, psToken);
               if (! iSuccessful)
                  {perror(pcPgmName); exit(EXIT_FAILURE);}
               iBufferIndex = 0;
               free(pcBuffer);
               return oTokens;
            }
            else if (isalpha(c))
            {
               pcBuffer[iBufferIndex++] = c;
               eState = STATE_IN_WORD;
            }
            else if (isspace(c))
            {
               /* Create a WORD token. */
               pcBuffer[iBufferIndex] = '\0';
               psToken = newToken(TOKEN_WORD, pcBuffer);
               iSuccessful = DynArray_add(oTokens, psToken);
               if (! iSuccessful)
                  {perror(pcPgmName); exit(EXIT_FAILURE);}
               iBufferIndex = 0;

               eState = STATE_START;
            }
            else
            {
               fprintf(stderr, "Invalid line\n");
               free(pcBuffer);
               freeTokens(oTokens);
               DynArray_free(oTokens);
               return NULL;
            }
            break;

         default:
            assert(0);
      }
   }
}
Command_T Command_new(char *pcName, DynArray_T oArgs, 
                      char *pcStdIn, char *pcStdOut) {
    int i;
    int argsLength; /* length of oArgs array */
    char* pcArg;
    size_t pcArgLength; /* track how much memory to give pcArg */
    Command_T oCommand;

    /* a command must have a name */
    assert(pcName != NULL);
    assert(oArgs != NULL);

    oCommand = (Command_T) malloc(sizeof(struct Command));
    if (oCommand == NULL) {
        fprintf(stderr, 
        "%s: Can't allocate memory for command\n", 
        pcPgmName); 
        exit(EXIT_FAILURE);
    }

    /* allocate memory for and set the command name */
    oCommand->pcName = (char*)malloc(strlen(pcName) + 1);
    if (oCommand->pcName == NULL) {
        fprintf(stderr, 
        "%s: Can't allocate memory for command\n", 
        pcPgmName); 
        exit(EXIT_FAILURE);
    }
    strcpy(oCommand->pcName, pcName);
    
    /* allocate memory for and set the command arguments*/
    argsLength = DynArray_getLength(oArgs);
    oCommand->oArgs = DynArray_new(0);
    for (i = 0; i < argsLength; i++) {
        pcArgLength = strlen((char*) DynArray_get(oArgs, i));
        pcArg = (char*) malloc(pcArgLength + 1);
        strcpy(pcArg, DynArray_get(oArgs, i));
        if (pcArg == NULL) {
            fprintf(stderr, 
            "%s: Can't allocate memory for command args\n", 
            pcPgmName); 
            exit(EXIT_FAILURE);
        }
        DynArray_add(oCommand->oArgs, pcArg);
    }

    /* allocate memory for and set the command stdin redirect */
    if (pcStdIn == NULL) {
        oCommand->pcStdIn = NULL;
    }
    else {
        oCommand->pcStdIn = (char*)malloc(strlen(pcStdIn) + 1);
        if (oCommand->pcStdIn == NULL) {
            fprintf(stderr, 
            "%s: Can't allocate memory for command\n", 
            pcPgmName); 
            exit(EXIT_FAILURE);
        }
        strcpy(oCommand->pcStdIn, pcStdIn);
    }   

    /* allocate memory for and set the command stdout redirect*/
    if (pcStdOut == NULL) {
        oCommand->pcStdOut = NULL;
    }
    else {
        oCommand->pcStdOut = (char*)malloc(strlen(pcStdOut) + 1);
        if (oCommand->pcStdOut == NULL) {
            fprintf(stderr, 
            "%s: Can't allocate memory for command\n", 
            pcPgmName); 
            exit(EXIT_FAILURE);
        }
        strcpy(oCommand->pcStdOut, pcStdOut);
    }
    return oCommand;

}
Esempio n. 4
0
int lexLine(const char *pcLine, DynArray_T oTokens, char *pcProgName)

/* Lexically analyze string pcLine.  Populate oTokens with the 
   tokens that pcLine contains.  Return TRUE if successful, and FALSE
   if pcLine contains a lexical error.  In the latter case, oTokens
   may contain tokens that were discovered before the lexical error.
   pcProgName is used in printing error messages. It is a checked
   runtime error for pcLine, oTokens, or pcProgName to be NULL. It 
   is a checked runtime error for the size of pcLine to be greater
   than MAX_LINE_SIZE. */

/* lexLine() uses a DFA approach. It "reads" its characters from
   pcLine. */

{
   char acValue[MAX_LINE_SIZE];
   char c;
   int iLineIndex = 0;
   int iValueIndex = 0;
   enum LexState eState = STATE_START;
   struct Token *psToken;

   assert(pcLine != NULL);
   assert(strlen(pcLine) + 1 <= MAX_LINE_SIZE);
   assert(oTokens != NULL);
   assert(pcProgName != NULL);

   while ((eState != STATE_EXIT) && (eState != STATE_ERROR))
   {
      /* "Read" the next character from pcLine. */
      c = pcLine[iLineIndex++];

      switch (eState)
      {
         case STATE_START:
            if ((c == '\n') || (c == '\0'))
               eState = STATE_EXIT;
            else if (c == '<')
            {
               /* Create a STDIN token. */
               acValue[iValueIndex++] = c;
               acValue[iValueIndex] = '\0';
               psToken = makeToken(TOKEN_STDIN, acValue);
               DynArray_add(oTokens, psToken);
               iValueIndex = 0;

               eState = STATE_START;
            }
            else if (c == '>')
            {
               /* Create a STDOUT token. */
               acValue[iValueIndex++] = c;               
               acValue[iValueIndex] = '\0';
               psToken = makeToken(TOKEN_STDOUT, acValue);
               DynArray_add(oTokens, psToken);
               iValueIndex = 0;

               eState = STATE_START;
            }
            else if (c == '"')
            {
               eState = STATE_IN_QUOTE;
            }
            else if ((int)c > 0x20 && (int)c < 0x7F)
            {
               acValue[iValueIndex++] = c;
               eState = STATE_IN_WORD;
            }
            else if ((c == ' ') || (c == '\t'))
               eState = STATE_START;
            else
               eState = STATE_ERROR;
            break;

         case STATE_IN_WORD:
            if ((c == '\n') || (c == '\0'))
            {
               /* Create a WORD token. */
               acValue[iValueIndex] = '\0';
               psToken = makeToken(TOKEN_WORD, acValue);
               DynArray_add(oTokens, psToken);
               iValueIndex = 0;
               
               eState = STATE_EXIT;
            }
            else if ((c == ' ') || (c == '\t'))
            {
               /* Create a WORD token. */
               acValue[iValueIndex] = '\0';
               psToken = makeToken(TOKEN_WORD, acValue);
               DynArray_add(oTokens, psToken);
               iValueIndex = 0;
               
               eState = STATE_START;
            }
            else if (c == '<')
            {
               /* Create a WORD token. */
               acValue[iValueIndex] = '\0';
               psToken = makeToken(TOKEN_WORD, acValue);
               DynArray_add(oTokens, psToken);
               iValueIndex = 0;
               
               /* Create a STDIN token. */
               acValue[iValueIndex++] = c;
               acValue[iValueIndex] = '\0';
               psToken = makeToken(TOKEN_STDIN, acValue);
               DynArray_add(oTokens, psToken);
               iValueIndex = 0;

               eState = STATE_START;
            }
            else if (c == '>')
            {
               /* Create a WORD token. */
               acValue[iValueIndex] = '\0';
               psToken = makeToken(TOKEN_WORD, acValue);
               DynArray_add(oTokens, psToken);
               iValueIndex = 0;
               
               /* Create a STDOUT token. */
               acValue[iValueIndex++] = c;               
               acValue[iValueIndex] = '\0';
               psToken = makeToken(TOKEN_STDOUT, acValue);
               DynArray_add(oTokens, psToken);
               iValueIndex = 0;
               
               eState = STATE_START;
            }
            else if (c == '"')
            {
               eState = STATE_IN_QUOTE;
            }
            else if ((int)c > 0x20 && (int)c < 0x7F)
            {
               acValue[iValueIndex++] = c;               
               eState = STATE_IN_WORD;
            }
            else
               eState = STATE_ERROR;
            break;

         case STATE_IN_QUOTE:
            if ((c == '\n') || (c == '\0'))
            {
               /* Create a token so we know command did not consist of
                  entirely white spaces. The eType TOKEN_WORD is 
                  chosen arbitrarily. */
               acValue[iValueIndex] = '\0';
               psToken = makeToken(TOKEN_WORD, acValue);
               DynArray_add(oTokens, psToken);
               iValueIndex = 0;
               
               fprintf(stderr, "%s: Unmatched quote\n", pcProgName);
               eState = STATE_ERROR;
            }
            else if (c == '"')
            {
               eState = STATE_IN_WORD;
            }
            else if ((c == ' ') || (c == '\t') 
                                || ((int)c > 0x20 && (int)c < 0x7F))
            {
               acValue[iValueIndex++] = c;
               eState = STATE_IN_QUOTE;
            }
            else 
               eState = STATE_ERROR;
            break;

         default:
            assert(0);
      }
   }

   if (eState == STATE_ERROR)
      return FALSE;
   return TRUE;
}