Anonymous Anonymous - 1 month ago
7371 0

No description

C

parser.c - Parsing program

/* This file contains the code for parser used to parse the input
 * given to shell program. You shouldn't need to modify this 
 * file */

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "parse.h"

#define PIPE  ('|')
#define BG    ('&')
#define RIN   ('<')
#define RUT   ('>')

#define ispipe(c) ((c) == PIPE)
#define isbg(c)   ((c) == BG)
#define isrin(c)  ((c) == RIN)
#define isrut(c)  ((c) == RUT)
#define isspec(c) (ispipe(c) || isbg(c) || isrin(c) || isrut(c))

static Pgm  cmdbuf[20], *cmds;
static char cbuf[256], *cp;
static char *pbuf[50], **pp;

/*
 * A quick hack to parse a commandline
 */

int
parse (char *buf, Command *c)
{
  int n;
  Pgm *cmd0;

  char *t = buf;
  char *tok;

  init();
  c->rstdin    = NULL;
  c->rstdout   = NULL;
  c->rstderr   = NULL;
  c->bakground = 0; /* false */
  c->pgm       = NULL;

newcmd:
  if ((n = acmd(t, &cmd0)) <= 0) {
    return -1;
  }

  t += n;

  cmd0->next = c->pgm;
  c->pgm = cmd0;

newtoken:
  n = nexttoken(t, &tok);
  if (n == 0) {
    return 1;
  }
  t += n;

  switch(*tok) {
  case PIPE:
    goto newcmd;
    break;
  case BG:
    n = nexttoken(t, &tok);
    if (n == 0) {
      c->bakground = 1;
      return 1;
    }
    else {
      fprintf(stderr, "illegal bakgrounding\n");
      return -1;
    }
    break;
  case RIN:
    if (c->rstdin != NULL) {
      fprintf(stderr, "duplicate redirection of stdin\n");
      return -1;
    }
    if ((n = nexttoken(t, &(c->rstdin))) < 0) {
      return -1;
    }
    if (!isidentifier(c->rstdin)) {
      fprintf(stderr, "Illegal filename: \"%s\"\n", c->rstdin);
      return -1;
    }
    t += n;
    goto newtoken;
    break;
  case RUT:
    if (c->rstdout != NULL) {
      fprintf(stderr, "duplicate redirection of stdout\n");
      return -1;
    }
    if ((n = nexttoken(t, &(c->rstdout))) < 0)  {
      return -1;
    }
    if (!isidentifier(c->rstdout)) {
      fprintf(stderr, "Illegal filename: \"%s\"\n", c->rstdout);
      return -1;
    }
    t += n;
    goto newtoken;
    break;
  default:
    return -1;
  }
  goto newcmd;
}

void init( void )
{
  int i;
  for (i=0;i<19;i++) {
    cmdbuf[i].next = &cmdbuf[i+1];
  }
  cmdbuf[19].next = NULL;
  cmds = cmdbuf;
  cp = cbuf;
  pp = pbuf;
}

int
nexttoken( char *s, char **tok)
{
  char *s0 = s;
  char c;

  *tok = cp;
  while (isspace(c = *s++) && c);
  if (c == '\0') {
    return 0;
  }
  if (isspec(c)) {
    *cp++ = c;
    *cp++ = '\0';
  }
  else {
    *cp++ = c;
    do {
        c = *cp++ = *s++;
    } while (!isspace(c) && !isspec(c) && (c != '\0'));
    --s;
    --cp;
    *cp++ = '\0';
  }
  return s - s0;
}

int
acmd (char *s, Pgm **cmd)
{
  char *tok;
  int n, cnt = 0;
  Pgm *cmd0 = cmds;
  cmds = cmds->next;
  cmd0->next = NULL;
  cmd0->pgmlist = pp;

next:
  n = nexttoken(s, &tok);
  if (n == 0 || isspec(*tok)) {
    *cmd = cmd0;
    *pp++ = NULL;
    return cnt;
  }
  else {
    *pp++ = tok;
    cnt += n;
    s += n;
    goto next;
  }
}


#define IDCHARS "_-.,/~+"

int
isidentifier (char *s)
{
    while (*s) {
      char *p = strrchr (IDCHARS,  *s);
      if (! isalnum(*s++) && (p == NULL))
        return 0;
    }
    return 1;
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download