Example #1
0
match(int t)
{
  if (lookahead==t)
    lookahead = lexan();
  else
    error("syntax error");
}
Example #2
0
void parse()  /*  parses and translates expression list  */
{
  lookahead = lexan();
  while (lookahead != DONE) {
    expr (); match (';');
  }
}
Example #3
0
void match(int t) {
	if(lookahead == t) {
		//printf("old lookahead = %s\n", lexbuf);
		lookahead = lexan();
		//printf("new lookahead = %s  %d\n", lexbuf, lookahead);
	} else
		error();
}
Example #4
0
match(int t)
{
	if (lookahead == t) {
		lookahead = lexan();
	} else {
		error("Syntax error");
	}
}
Example #5
0
void parse()
{
  lookahead = lexan();
  while (lookahead != DONE)
    {
    expr();
    match(';');
    }
}
Example #6
0
int match(token_id token)
{
    if (token == curr_lex.token) {
        if (lexan()) {
            /* error */
            return 0;
        }
        return 1;
    }
    /* not match */
    return 0;
}
Example #7
0
int
main(
    int argc,
    char* argv[]
    )
{
    FILE* fp;

    if( argc < 2 )
    {
        fprintf( stderr, "Usage: %s <source.p> [...]\n", *argv );
        return EXIT_FAILURE;
    }

    for( int i = 1; i < argc; ++i )
    {
        printf( "Parsing `%s'\n", argv[i] );

        if( !(fp = fopen( argv[i], "r" )) )
        {
            perror( "fopen" );
            continue;
        }

        LexAnalyzer lexan( fp );
        Parser parser( lexan );

        AstNode* ast;
        if( !parser.parse( ast ) )
        {
            printf( "Failed to parse file `%s'\n", argv[i] );
            continue;
        }

        printf( "File `%s' parsed successfully\n", argv[i] );
#ifdef DEBUG_AST
        ast->print( 1, stdout );
#endif /* DEBUG_AST */

        if( !ast->translate() )
        {
            printf( "Failed to translate file `%s'\n", argv[i] );
            delete ast;
            continue;
        }

        printf( "File `%s' translated successfully\n", argv[i] );
        delete ast;
    }
}
Example #8
0
parse()		/* Parses and translates expression list */
{
	lookahead = lexan();				//we should probably name this function stmt
	while (lookahead != DONE) {			//then wrap it in a new parse function
		if (lookahead == IF_SYM) {		
			printf("\nIF (\n");			//emit code somehow...
			match(lookahead);			//match if
			expr();						//evaluate expr1
			printf("\n) then (\n\n");	//emit code somehow...
			match(lookahead);   		//match then
			expr();						//eval expr2
			printf("\n)\n");			//end the stmt
			match(';');
		}
		expr();
		printf(";\n");	//this is a shim that makes the output look cleaner to me
		match(';');
	}
}
Example #9
0
int main(void){

	lookahead = lexan();
	//printf("lookahead = %d\n", lookahead);
	//int x = 0;
	
	while(lookahead != FILEND){
	//while(x < 10){
		//if(lookahead != -1){
		//printf("%d\n",lookahead);
		globaldeclaration();
		//expression();
		//}
	//	x++;
		
	//	lookahead = lexan();
	}
	free (lexbuf);
	return 0;
}
Example #10
0
process	shell (
		did32	dev		/* ID of tty device from which	*/
	)				/*   to accept commands		*/
{
	char	buf[SHELL_BUFLEN];	/* Input line (large enough for	*/
					/*   one line from a tty device	*/
	int32	len;			/* Length of line read		*/
	char	tokbuf[SHELL_BUFLEN +	/* Buffer to hold a set of	*/
			SHELL_MAXTOK];  /* Contiguous null-terminated	*/
					/* Strings of tokens		*/
	int32	tlen;			/* Current length of all data	*/
					/*   in array tokbuf		*/
	int32	tok[SHELL_MAXTOK];	/* Index of each token in	*/
					/*   array tokbuf		*/
	int32	toktyp[SHELL_MAXTOK];	/* Type of each token in tokbuf	*/
	int32	ntok;			/* Number of tokens on line	*/
	pid32	child;			/* Process ID of spawned child	*/
	bool8	backgnd;		/* Run command in background?	*/
	char	*outname, *inname;	/* Pointers to strings for file	*/
					/*   names that follow > and <	*/
	did32	stdinput, stdoutput;	/* Descriptors for redirected	*/
					/*   input and output		*/
	int32	i;			/* Index into array of tokens	*/
	int32	j;			/* Index into array of commands	*/
	int32	msg;			/* Message from receive() for	*/
					/*   child termination		*/
	int32	tmparg;			/* Address of this var is used	*/
					/*   when first creating child	*/
					/*   process, but is replaced	*/
	char	*src, *cmp;		/* Pointers used during name	*/
					/*   comparison			*/
	bool8	diff;			/* Was difference found during	*/
					/*   comparison			*/
	char	*args[SHELL_MAXTOK];	/* Argument vector passed to	*/
					/*   builtin commands		*/

	/* Print shell banner and startup message */

	fprintf(dev, "\n\n%s%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
		SHELL_BAN0,SHELL_BAN1,SHELL_BAN2,SHELL_BAN3,SHELL_BAN4,
		SHELL_BAN5,SHELL_BAN6,SHELL_BAN7,SHELL_BAN8,SHELL_BAN9);

	fprintf(dev, "%s\n\n", SHELL_STRTMSG);

	/* Continually prompt the user, read input, and execute command	*/

	while (TRUE) {

		/* Display prompt */

		fprintf(dev, SHELL_PROMPT);

		/* Read a command */

		len = read(dev, buf, sizeof(buf));

		/* Exit gracefully on end-of-file */

		if (len == EOF) {
			break;
		}

		/* If line contains only NEWLINE, go to next line */

		if (len <= 1) {
			continue;
		}

		buf[len] = SH_NEWLINE;	/* terminate line */

		/* Parse input line and divide into tokens */

		ntok = lexan(buf, len, tokbuf, &tlen, tok, toktyp);

		/* Handle parsing error */

		if (ntok == SYSERR) {
			fprintf(dev,"%s\n", SHELL_SYNERRMSG);
			continue;
		}

		/* If line is empty, go to next input line */

		if (ntok == 0) {
			fprintf(dev, "\n");
			continue;
		}

		/* If last token is '&', set background */

		if (toktyp[ntok-1] == SH_TOK_AMPER) {
			ntok-- ;
			tlen-= 2;
			backgnd = TRUE;
		} else {
			backgnd = FALSE;
		}


		/* Check for input/output redirection (default is none) */

		outname = inname = NULL;
		if ( (ntok >=3) && ( (toktyp[ntok-2] == SH_TOK_LESS)
				   ||(toktyp[ntok-2] == SH_TOK_GREATER))){
			if (toktyp[ntok-1] != SH_TOK_OTHER) {
				fprintf(dev,"%s\n", SHELL_SYNERRMSG);
				continue;
			}
			if (toktyp[ntok-2] == SH_TOK_LESS) {
				inname =  &tokbuf[tok[ntok-1]];
			} else {
				outname = &tokbuf[tok[ntok-1]];
			}
			ntok -= 2;
			tlen = tok[ntok];
		}


		if ( (ntok >=3) && ( (toktyp[ntok-2] == SH_TOK_LESS)
				   ||(toktyp[ntok-2] == SH_TOK_GREATER))){
			if (toktyp[ntok-1] != SH_TOK_OTHER) {
				fprintf(dev,"%s\n", SHELL_SYNERRMSG);
				continue;
			}
			if (toktyp[ntok-2] == SH_TOK_LESS) {
				if (inname != NULL) {
				    fprintf(dev,"%s\n", SHELL_SYNERRMSG);
				    continue;
				}
				inname = &tokbuf[tok[ntok-1]];
			} else {
				if (outname != NULL) {
				    fprintf(dev,"%s\n", SHELL_SYNERRMSG);
				    continue;
				}
				outname = &tokbuf[tok[ntok-1]];
			}
			ntok -= 2;
			tlen = tok[ntok];
		}

		/* Verify remaining tokens are type "other" */

		for (i=0; i<ntok; i++) {
			if (toktyp[i] != SH_TOK_OTHER) {
				break;
			}
		}
		if ((ntok == 0) || (i < ntok)) {
			fprintf(dev, SHELL_SYNERRMSG);
			continue;
		}

		stdinput = stdoutput = dev;

		/* Lookup first token in the command table */

		for (j = 0; j < ncmd; j++) {
			src = cmdtab[j].cname;
			cmp = tokbuf;
			diff = FALSE;
			while (*src != NULLCH) {
				if (*cmp != *src) {
					diff = TRUE;
					break;
				}
				src++;
				cmp++;
			}
			if (diff || (*cmp != NULLCH)) {
				continue;
			} else {
				break;
			}
		}

		/* Handle command not found */

		if (j >= ncmd) {
			fprintf(dev, "command %s not found\n", tokbuf);
			continue;
		}

		/* Handle built-in command */

		if (cmdtab[j].cbuiltin) { /* No background or redirect. */
			if (inname != NULL || outname != NULL || backgnd){
				fprintf(dev, SHELL_BGERRMSG);
				continue;
			} else {
				/* Set up arg vector for call */

				for (i=0; i<ntok; i++) {
					args[i] = &tokbuf[tok[i]];
				}

				/* Call builtin shell function */

				if ((*cmdtab[j].cfunc)(ntok, args)
							== SHELL_EXIT) {
					break;
				}
			}
			continue;
		}

		/* Open files and redirect I/O if specified */

		if (inname != NULL) {
			stdinput = open(NAMESPACE,inname,"ro");
			if (stdinput == SYSERR) {
				fprintf(dev, SHELL_INERRMSG, inname);
				continue;
			}
		}
		if (outname != NULL) {
			stdoutput = open(NAMESPACE,outname,"w");
			if (stdoutput == SYSERR) {
				fprintf(dev, SHELL_OUTERRMSG, outname);
				continue;
			} else {
				control(stdoutput, F_CTL_TRUNC, 0, 0);
			}
		}

		/* Spawn child thread for non-built-in commands */

		child = create(cmdtab[j].cfunc,
			SHELL_CMDSTK, SHELL_CMDPRIO,
			cmdtab[j].cname, 2, ntok, &tmparg);

		/* If creation or argument copy fails, report error */

		if ((child == SYSERR) ||
		    (addargs(child, ntok, tok, tlen, tokbuf, &tmparg)
							== SYSERR) ) {
			fprintf(dev, SHELL_CREATMSG);
			continue;
		}

		/* Set stdinput and stdoutput in child to redirect I/O */

		proctab[child].prdesc[0] = stdinput;
		proctab[child].prdesc[1] = stdoutput;

		msg = recvclr();
		resume(child);
		if (! backgnd) {
			msg = receive();
			while (msg != child) {
				msg = receive();
			}
		}
    }

    /* Terminate the shell process by returning from the top level */

    fprintf(dev,SHELL_EXITMSG);
    return OK;
}
Example #11
0
int yylex(void)
{
	int lex = lexan();
	yylval = tokenval;
	return lex;
}
Example #12
0
File: shell.c Project: osa1/osdev
/**
 * @ingroup shell
 *
 * The Xinu shell.  Provides an interface to execute commands.
 * @param descrp descriptor of device on which the shell is open
 * @return OK for successful exit, SYSERR for unrecoverable error
 */
thread shell(int indescrp, int outdescrp, int errdescrp)
{
    char buf[SHELL_BUFLEN];     /* line input buffer        */
    short buflen;               /* length of line input     */
    char tokbuf[SHELL_BUFLEN + SHELL_MAXTOK];   /* token value buffer       */
    short ntok;                 /* number of tokens         */
    char *tok[SHELL_MAXTOK];    /* pointers to token values */
    char *outname;              /* name of output file      */
    char *inname;               /* name of input file       */
    bool background;            /* is background proccess?  */
    syscall child;              /* pid of child thread      */
    ushort i, j;                /* temp variables           */
    irqmask im;                 /* interrupt mask state     */
    char *hostptr = NULL;       /* pointer to hostname      */

    /* Setup buffer for string for nvramGet call for hostname */
#if defined(ETH0) && NVRAM
    char hostnm[NET_HOSTNM_MAXLEN + 1]; /* hostname of backend      */
    if (!isbaddev(ETH0))
    {
        size_t hostname_strsz;          /* nvram hostname name size */

        bzero(hostnm, NET_HOSTNM_MAXLEN + 1);

        /* Determine the hostname of the main network device */
        hostname_strsz = strlen(NET_HOSTNAME);
        hostname_strsz += 1;
        hostname_strsz += DEVMAXNAME;
        hostname_strsz += 1;
        char nvramget_hostname_str[hostname_strsz];
        sprintf(nvramget_hostname_str, "%s_%s", devtab[ETH0].name,
                NET_HOSTNAME);

        /* Acquire the backend's hostname */
        hostptr = nvramGet(nvramget_hostname_str);
        if (hostptr != NULL)
        {
            strncpy(hostnm, hostptr, NET_HOSTNM_MAXLEN);
            hostptr = hostnm;
        }
    }
#endif

    /* Set command devices for input, output, and error */
    stdin = indescrp;
    stdout = outdescrp;
    stderr = errdescrp;

    /* Print shell banner to framebuffer, if exists */
#if defined(FRAMEBUF)
    if (indescrp == FRAMEBUF)
    {
        foreground = RASPBERRY;
        printf(SHELL_BANNER_NONVT100);
        foreground = LEAFGREEN;
        printf(SHELL_START);
        foreground = GREEN;
    }
    else
#endif
    {
        printf(SHELL_BANNER);
        printf(SHELL_START);
    }

    /* Continually receive and handle commands */
    while (TRUE)
    {
        /* Display prompt */
        printf(SHELL_PROMPT);

        if (NULL != hostptr)
        {
            printf("@%s$ ", hostptr);
        }
        else
        {
            printf("$ ");
        }

        /* Setup proper tty modes for input and output */
        control(stdin, TTY_CTRL_CLR_IFLAG, TTY_IRAW, NULL);
        control(stdin, TTY_CTRL_SET_IFLAG, TTY_ECHO, NULL);

        /* Read command */
        buflen = read(stdin, buf, SHELL_BUFLEN - 1);

        /* Check for EOF and exit gracefully if seen */
        if (EOF == buflen)
        {
            break;
        }

        /* Parse line input into tokens */
        if (SYSERR == (ntok = lexan(buf, buflen, &tokbuf[0], &tok[0])))
        {
            fprintf(stderr, SHELL_SYNTAXERR);
            continue;
        }

        /* Ensure parse generated tokens */
        if (0 == ntok)
        {
            continue;
        }

        /* Initialize command options */
        inname = NULL;
        outname = NULL;
        background = FALSE;

        /* Mark as background thread, if last token is '&' */
        if ('&' == *tok[ntok - 1])
        {
            ntok--;
            background = TRUE;
        }

        /* Check each token and perform special handling of '>' and '<' */
        for (i = 0; i < ntok; i++)
        {
            /* Background '&' should have already been handled; Syntax error */
            if ('&' == *tok[i])
            {
                ntok = -1;
                break;
            }

            /* Setup for output redirection if token is '>'  */
            if ('>' == *tok[i])
            {
                /* Syntax error */
                if (outname != NULL || i >= ntok - 1)
                {
                    ntok = -1;
                    break;
                }

                outname = tok[i + 1];
                ntok -= 2;

                /* shift tokens (not to be passed to command */
                for (j = i; j < ntok; j++)
                {
                    tok[j] = tok[j + 2];
                }
                continue;
            }

            /* Setup for input redirection if token is '<' */
            if ('<' == *tok[i])
            {
                /* Syntax error */
                if (inname != NULL || i >= ntok - 1)
                {
                    ntok = -1;
                    break;
                }
                inname = tok[i + 1];
                ntok -= 2;

                /* shift tokens (not to be passed to command */
                for (j = i; j < ntok; j++)
                {
                    tok[j] = tok[j + 2];
                }

                continue;
            }
        }

        /* Handle syntax error */
        if (ntok <= 0)
        {
            fprintf(stderr, SHELL_SYNTAXERR);
            continue;
        }

        /* Lookup first token in the command table */
        for (i = 0; i < ncommand; i++)
        {
            if (0 == strcmp(commandtab[i].name, tok[0]))
            {
                break;
            }
        }

        /* Handle command not found */
        if (i >= ncommand)
        {
            fprintf(stderr, "%s: command not found\n", tok[0]);
            continue;
        }

        /* Handle command if it is built-in */
        if (commandtab[i].builtin)
        {
            if (inname != NULL || outname != NULL || background)
            {
                fprintf(stderr, SHELL_SYNTAXERR);
            }
            else
            {
                (*commandtab[i].procedure) (ntok, tok);
            }
            continue;
        }

        /* Spawn child thread for non-built-in commands */
        child =
            create(commandtab[i].procedure,
                   SHELL_CMDSTK, SHELL_CMDPRIO,
                   commandtab[i].name, 2, ntok, tok);

        /* Ensure child command thread was created successfully */
        if (SYSERR == child)
        {
            fprintf(stderr, SHELL_CHILDERR);
            continue;
        }

        /* Set file descriptors for newly created thread */
        if (NULL == inname)
        {
            thrtab[child].fdesc[0] = stdin;
        }
        else
        {
            thrtab[child].fdesc[0] = getdev(inname);
        }
        if (NULL == outname)
        {
            thrtab[child].fdesc[1] = stdout;
        }
        else
        {
            thrtab[child].fdesc[1] = getdev(outname);
        }
        thrtab[child].fdesc[2] = stderr;

        if (background)
        {
            /* Make background thread ready, but don't reschedule */
            im = disable();
            ready(child, RESCHED_NO);
            restore(im);
        }
        else
        {
            /* Clear waiting message; Reschedule; */
            while (recvclr() != NOMSG);
            im = disable();
            ready(child, RESCHED_YES);
            restore(im);

            /* Wait for command thread to finish */
            while (receive() != child);
            sleep(10);
        }
    }

    /* Close shell */
    fprintf(stdout, SHELL_EXIT);
    sleep(10);
    return OK;
}
Example #13
0
int parse(void)
{
    big_int *a = NULL;
    big_int_str *str = NULL;
    int result = 0;
    unsigned int out_base = 10;

    a = big_int_create(1);
    str = big_int_str_create(1);
    if (a == NULL || str == NULL) {
        printf("error when creating [a] or [str]\n");
        result = 1;
        goto done;
    }

    while (1) {
        if (read_line(CALC_PROMPT)) {
            break;
        }
        if (line_next_char() == '\\') {
            /* command */
            switch (line_next_char()) {
                case 'q' : /* quit */
                    printf("quit\n");
                    goto done;
                case '?' : case 'h' : /* help */
                    help();
                    continue;
                case 'b' : /* change output base. Default is 10 */
                    if (sscanf(line.s, "%u", &out_base) != 1) {
                        printf("cannot recogize new base\n");
                    }
                    if (out_base < 2 || out_base > 36) {
                        printf("wrong value of base. Acceptible value is [2 - 36]\n");
                        out_base = 10;
                    } else {
                        printf("new base is %u\n", out_base);
                    }
                    continue;
                case 'm' : /* switch to modular arithmetic */
                    /* calculate module */
                    if (lexan()) {
                        continue;
                    }
                    is_mod = 0; /* disable module arithmetic */
                    if (expr(a)) {
                        /* error when calculating module */
                        continue;
                    }
                    if (big_int_copy(a, module)) {
                        printf("error when copying number [a] to [module]\n");
                        continue;
                    }
                    module->sign = PLUS;
                    if (module->len == 1 && module->num[0] < 2) {
                        printf("module must be greater than 1\n");
                        continue;
                    }
                    is_mod = 1; /* enable module arithmetic */
                    if (big_int_to_str(module, out_base, str)) {
                        printf("error during converting number to string\n");
                        continue;
                    }
                    printf("Switching to modular arithmetic. Module is %s\n", str->str);
                    continue;
                case 'i' : /* switch to integer arithmetic */
                    is_mod = 0;
                    printf("Switching to integer arithmetic\n");
                    continue;
                case 's' : /* show current settings */
                    puts("Current settings:");
                    printf("Base: %u\n", out_base);
                    printf("Mode: %s arithmetic\n", is_mod ? "modular (\\m)" : "integer (\\i)");
                    continue;
                default :
                    /* unknown command */
                    printf("unknown command\n");
                    continue;
            }
        }
        line_prev_char();
        /* parse line */
        if (lexan() || curr_lex.token == DONE) {
            continue;
        }
        while (!expr(a)) {
            if (curr_lex.token != ',' && curr_lex.token != DONE) {
                printf("wrong lexeme [%s]. Token id=%d. Expected ',' or \\n\n",
                    curr_lex.str, curr_lex.token);
                break;
            }
            match(','); /* go to the next expression */
            if (is_mod) {
                if (big_int_absmod(a, module, a)) {
                    printf("error in big_int_absmod()\n");
                    continue;
                }
            }
            if (big_int_to_str(a, out_base, str)) {
                printf("error during converting number to string\n");
                continue;
            }
            /* save result to the history */
            if (big_int_copy(a, history[history_pos])) {
                printf("error when copying number [a] to the history\n");
                continue;
            }
            /* print result to the display */
            history_pos++;
            printf("$%d = %s\n", history_pos, str->str);
            if (history_pos >= HISTORY_SIZE) {
                history_pos = 0;
            }
            if (curr_lex.token == DONE) {
                break;
            }
        }
    }

done:
    big_int_str_destroy(str);
    big_int_destroy(a);
    return result;
}
Example #14
0
/**
 * The Xinu shell.  Provides an interface to execute commands.
 * @param descrp descriptor of device on which the shell is open
 * @return OK for successful exit, SYSERR for unrecoverable error
 */
thread shell(int indescrp, int outdescrp, int errdescrp)
{
  char buf[SHELL_BUFLEN];     /* line input buffer        */
  short buflen;               /* length of line input     */
  char tokbuf[SHELL_BUFLEN + SHELL_MAXTOK];   /* token value buffer       */
  short ntok;                 /* number of tokens         */
  char *tok[SHELL_MAXTOK];    /* pointers to token values */
  char *outname;              /* name of output file      */
  char *inname;               /* name of input file       */
  bool background;            /* is background proccess?  */
  syscall child;              /* pid of child thread      */
  ushort i, j;                /* temp variables           */
  irqmask im;                 /* interrupt mask state     */

  /* hostname variables */
  char hostnm[NET_HOSTNM_MAXLEN + 1]; /* hostname of backend      */
  char *hostptr;              /* pointer to hostname      */
  int hostname_strsz;         /* nvram hostname name size */
  device *devptr;             /* device pointer           */

  printf( "Welcome to the shell!\n" );

  /* Enable interrupts */
  enable();

  hostptr = NULL;
  devptr = NULL;
  hostname_strsz = 0;
  bzero(hostnm, NET_HOSTNM_MAXLEN + 1);

  /* Setup buffer for string for nvramGet call for hostname */
#ifdef ETH0
  if (!isbaddev(ETH0))
  {
    /* Determine the hostname of the main network device */
    devptr = (device *)&devtab[ETH0];
    hostname_strsz = strnlen(NET_HOSTNAME, NVRAM_STRMAX) + 1;
    hostname_strsz += DEVMAXNAME;
    char nvramget_hostname_str[hostname_strsz];
    sprintf(nvramget_hostname_str, "%s_%s", devptr->name,
        NET_HOSTNAME);

    /* Acquire the backend's hostname */
#if NVRAM
    hostptr = nvramGet(nvramget_hostname_str);
#endif                          /* NVRAM */
    if (hostptr != NULL)
    {
      memcpy(hostnm, hostptr, NET_HOSTNM_MAXLEN);
      hostptr = hostnm;
    }
  }
#endif

  /* Set command devices for input, output, and error */
  stdin = indescrp;
  stdout = outdescrp;
  stderr = errdescrp;

  /* Print shell banner */
  printf(SHELL_BANNER);
  /* Print shell welcome message */
  printf(SHELL_START);

  /* Continually receive and handle commands */
  while (TRUE)
  {
    /* Display prompt */
    printf(SHELL_PROMPT);

    if (NULL != hostptr)
    {
      printf("@%s$ ", hostptr);
    }
    else
    {
      printf("$ ");
    }

    /* Setup proper tty modes for input and output */
    control(stdin, TTY_CTRL_CLR_IFLAG, TTY_IRAW, NULL);
    control(stdin, TTY_CTRL_SET_IFLAG, TTY_ECHO, NULL);

    /* Null out the buf and read command */
    memset(buf, '\0', SHELL_BUFLEN);
    buflen = shellRead(stdin, buf, SHELL_BUFLEN);

    if(buf[0] != '!') {
      addHistoryItem(buf, buflen);
    }

    /* Check for EOF and exit gracefully if seen */
    if (EOF == buflen)
    {
      break;
    }

    // Check for indicator of history command
    if (buf[0] == '!')
    {
      int index;

      // handler for !! (just execute most recent command)
      if(buf[1] == '!') {
        index = 0;
      } else {
        // extract the number string
        char indexString[buflen];
        strncpy(indexString, &buf[1], buflen - 1);
        indexString[buflen] = '\0';

        // convert number string into a valid index
        // calculation is done because the index numbers
        // are reverse of their numbers printed using 'history'
        index = numHistoryItems - atoi(indexString);
      }

      //replace buf and buflen with the last command
      strncpy(buf, history[index].command, SHELL_BUFLEN);
      buflen = history[index].commandLength + 1;
    }

    /* Parse line input into tokens */
    if (SYSERR == (ntok = lexan(buf, buflen, &tokbuf[0], &tok[0])))
    {
      fprintf(stderr, SHELL_SYNTAXERR);
      continue;
    }

    /* Ensure parse generated tokens */
    if (0 == ntok)
    {
      continue;
    }

    /* Initialize command options */
    inname = NULL;
    outname = NULL;
    background = FALSE;

    /* Mark as background thread, if last token is '&' */
    if ('&' == *tok[ntok - 1])
    {
      ntok--;
      background = TRUE;
    }

    /* Check each token and perform special handling of '>' and '<' */
    for (i = 0; i < ntok; i++)
    {
      /* Background '&' should have already been handled; Syntax error */
      if ('&' == *tok[i])
      {
        ntok = -1;
        break;
      }

      /* Setup for output redirection if token is '>'  */
      if ('>' == *tok[i])
      {
        /* Syntax error */
        if (outname != NULL || i >= ntok - 1)
        {
          ntok = -1;
          break;
        }

        outname = tok[i + 1];
        ntok -= 2;

        /* shift tokens (not to be passed to command */
        for (j = i; j < ntok; j++)
        {
          tok[j] = tok[j + 2];
        }
        continue;
      }

      /* Setup for input redirection if token is '<' */
      if ('<' == *tok[i])
      {
        /* Syntax error */
        if (inname != NULL || i >= ntok - 1)
        {
          ntok = -1;
          break;
        }
        inname = tok[i + 1];
        ntok -= 2;

        /* shift tokens (not to be passed to command */
        for (j = i; j < ntok; j++)
        {
          tok[j] = tok[j + 2];
        }

        continue;
      }
    }

    /* Handle syntax error */
    if (ntok <= 0)
    {
      fprintf(stderr, SHELL_SYNTAXERR);
      continue;
    }

    /* Lookup first token in the command table */
    for (i = 0; i < ncommand; i++)
    {
      if (0 == strncmp(commandtab[i].name, tok[0], SHELL_BUFLEN))
      {
        break;
      }
    }

    /* Handle command not found */
    if (i >= ncommand)
    {
      fprintf(stderr, "%s: command not found\n", tok[0]);
      continue;
    }

    /* Handle command if it is built-in */
    if (commandtab[i].builtin)
    {
      if (inname != NULL || outname != NULL || background)
      {
        fprintf(stderr, SHELL_SYNTAXERR);
      }
      else
      {
        (*commandtab[i].procedure) (ntok, tok);
      }
      continue;
    }

    /* Spawn child thread for non-built-in commands */
    child =
      create(commandtab[i].procedure,
          SHELL_CMDSTK, SHELL_CMDPRIO,
          commandtab[i].name, 2, ntok, tok);



    /* Ensure child command thread was created successfully */
    if (SYSERR == child)
    {
      fprintf(stderr, SHELL_CHILDERR);
      continue;
    }

    /* Set file descriptors for newly created thread */
    if (NULL == inname)
    {
      thrtab[child].fdesc[0] = stdin;
    }
    else
    {
      thrtab[child].fdesc[0] = getdev(inname);
    }
    if (NULL == outname)
    {
      thrtab[child].fdesc[1] = stdout;
    }
    else
    {
      thrtab[child].fdesc[1] = getdev(outname);
    }
    thrtab[child].fdesc[2] = stderr;

    if (background)
    {
      /* Make background thread ready, but don't reschedule */
      im = disable();
      ready(child, RESCHED_NO);
      restore(im);
    }
    else
    {
      /* Clear waiting message; Reschedule; */
      while (recvclr() != NOMSG);
      im = disable();
      ready(child, RESCHED_YES);
      restore(im);

      /* Wait for command thread to finish */
      while (receive() != child);
      sleep(10);
    }
  }

  /* Close shell */
  fprintf(stdout, SHELL_EXIT);
  sleep(10);
  return OK;
}