Example #1
0
bool BoardGenerator::handleNakedPairs(int round){
    for (int position=0; position<BOARD_SIZE; position++){
        int possibilities = countPossibilities(position);
        if (possibilities == 2){
            int row = cellToRow(position);
            int column = cellToColumn(position);
            int section = cellToSectionStartCell(position);
            for (int position2=position; position2<BOARD_SIZE; position2++){
                if (position != position2){
                    int possibilities2 = countPossibilities(position2);
                    if (possibilities2 == 2 && arePossibilitiesSame(position, position2)){
                        if (row == cellToRow(position2)){
                            bool doneSomething = false;
                            for (int column2=0; column2<9; column2++){
                                int position3 = rowColumnToCell(row,column2);
                                if (position3 != position && position3 != position2 && removePossibilitiesInOneFromTwo(position, position3, round)){
                                    doneSomething = true;
                                }
                            }
                            if (doneSomething){
                                if (recordHistory) addHistoryItem(new LogItem(round, LogItem::NAKED_PAIR_ROW, 0, position));
                                return true;
                            }
                        }
                        if (column == cellToColumn(position2)){
                            bool doneSomething = false;
                            for (int row2=0; row2<9; row2++){
                                int position3 = rowColumnToCell(row2,column);
                                if (position3 != position && position3 != position2 && removePossibilitiesInOneFromTwo(position, position3, round)){
                                    doneSomething = true;
                                }
                            }
                            if (doneSomething){
                                if (recordHistory) addHistoryItem(new LogItem(round, LogItem::NAKED_PAIR_COLUMN, 0, position));
                                return true;
                            }
                        }
                        if (section == cellToSectionStartCell(position2)){
                            bool doneSomething = false;
                            int secStart = cellToSectionStartCell(position);
                            {for (int i=0; i<3; i++){
                                    for (int j=0; j<3; j++){
                                        int position3=secStart+i+(9*j);
                                        if (position3 != position && position3 != position2 && removePossibilitiesInOneFromTwo(position, position3, round)){
                                            doneSomething = true;
                                        }
                                    }
                                }}
                            if (doneSomething){
                                if (recordHistory) addHistoryItem(new LogItem(round, LogItem::NAKED_PAIR_SECTION, 0, position));
                                return true;
                            }
                        }
                    }
                }
            }
        }
    }
    return false;
}
Example #2
0
/**
 * Reset the board to its initial state with
 * only the givens.
 * This method clears any solution, resets statistics,
 * and clears any history messages.
 */
bool BoardGenerator::reset(){
    {for (int i=0; i<BOARD_SIZE; i++){
            solution[i] = 0;
        }}
    {for (int i=0; i<BOARD_SIZE; i++){
            solutionRound[i] = 0;
        }}
    {for (int i=0; i<POSSIBILITY_SIZE; i++){
            possibilities[i] = 0;
        }}

    {for (vector<LogItem*>::size_type i=0;i<solveHistory->size();i++){
            delete solveHistory->at(i);
        }}
    solveHistory->clear();
    solveInstructions->clear();

    int round = 1;
    for (int position=0; position<BOARD_SIZE; position++){
        if (puzzle[position] > 0){
            int valIndex = puzzle[position]-1;
            int valPos = getPossibilityIndex(valIndex,position);
            int value = puzzle[position];
            if (possibilities[valPos] != 0) return false;
            mark(position,round,value);
            if (recordHistory) addHistoryItem(new LogItem(round, LogItem::GIVEN, value, position));
        }
    }

    return true;
}
Example #3
0
/**
 * Mark exactly one cell which is the only possible value for some section, if
 * such a cell exists.
 * This method will look in a section for a possibility that is only listed
 * for one cell.  This type of cell is often called a "hidden single"
 */
bool BoardGenerator::onlyValueInSection(int round){
    for (int sec=0; sec<SEC_COUNT; sec++){
        int secPos = sectionToFirstCell(sec);
        for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
            int count = 0;
            int lastPosition = 0;
            {for (int i=0; i<3; i++){
                    for (int j=0; j<3; j++){
                        int position = secPos + i + 9*j;
                        int valPos = getPossibilityIndex(valIndex,position);
                        if (possibilities[valPos] == 0){
                            count++;
                            lastPosition = position;
                        }
                    }
                }}
            if (count == 1){
                int value = valIndex+1;
                if (recordHistory) addHistoryItem(new LogItem(round, LogItem::HIDDEN_SINGLE_SECTION, value, lastPosition));
                mark(lastPosition, round, value);
                return true;
            }
        }
    }
    return false;
}
Example #4
0
int main(int argc, char *argv[])
{
	int i, *a;
	historyItem *h;

	setHistoryLimit(15);

	for (i=0;i < 6; i++) {
	  a = (int *)malloc(sizeof(int));
	  *a = i;
	  h = newHistoryItem(a);
	  addHistoryItem(h);
	}

	/* Start at the beginning */
	setHistoryIndex(numHistoryItems());
	while ((h = nextHistoryItem(0)) != NULL) {
	  printf("h[%d]->a is %d\n", getHistoryIndex(), *(int *)h->data);
	}

	printf("Doing the reverse now...\n");
	setHistoryIndex(3);
	for (i=0;i<6;i++) {
	  h = prevHistoryItem(1);
	  if (h)
	    printf("h[%d]->a is %d\n", getHistoryIndex(), *(int *)h->data);
	}

	return 0;
}
Example #5
0
void HistoryManager::addHistoryEntry(const QString &url)
{
    QUrl cleanUrl(url);
    cleanUrl.setPassword(QString());
    cleanUrl.setHost(cleanUrl.host().toLower());
    HistoryItem item(cleanUrl.toString(), QDateTime::currentDateTime());
    addHistoryItem(item);
}
Example #6
0
bool BoardGenerator::rowBoxReduction(int round){
    for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
        for (int row=0; row<9; row++){
            int rowStart = rowToFirstCell(row);
            bool inOneBox = true;
            int rowBox = -1;
            {for (int i=0; i<3; i++){
                    for (int j=0; j<3; j++){
                        int column = i*3+j;
                        int position = rowColumnToCell(row, column);
                        int valPos = getPossibilityIndex(valIndex,position);
                        if(possibilities[valPos] == 0){
                            if (rowBox == -1 || rowBox == i){
                                rowBox = i;
                            } else {
                                inOneBox = false;
                            }
                        }

                    }
                }}
            if (inOneBox && rowBox != -1){
                bool doneSomething = false;
                int column = 3*rowBox;
                int secStart = cellToSectionStartCell(rowColumnToCell(row, column));
                int secStartRow = cellToRow(secStart);
                int secStartCol = cellToColumn(secStart);
                {for (int i=0; i<3; i++){
                        for (int j=0; j<3; j++){
                            int row2 = secStartRow+i;
                            int col2 = secStartCol+j;
                            int position = rowColumnToCell(row2, col2);
                            int valPos = getPossibilityIndex(valIndex,position);
                            if (row != row2 && possibilities[valPos] == 0){
                                possibilities[valPos] = round;
                                doneSomething = true;
                            }
                        }
                    }}
                if (doneSomething){
                    if (recordHistory) addHistoryItem(new LogItem(round, LogItem::ROW_BOX, valIndex+1, rowStart));
                    return true;
                }
            }
        }
    }
    return false;
}
Example #7
0
bool BoardGenerator::guess(int round, int guessNumber){
    int localGuessCount = 0;
    int position = findPositionWithFewestPossibilities();
    {for (int i=0; i<NUM_POSS; i++){
            int valIndex = randomPossibilityArray[i];
            int valPos = getPossibilityIndex(valIndex,position);
            if (possibilities[valPos] == 0){
                if (localGuessCount == guessNumber){
                    int value = valIndex+1;
                    if (recordHistory) addHistoryItem(new LogItem(round, LogItem::GUESS, value, position));
                    mark(position, round, value);
                    return true;
                }
                localGuessCount++;
            }
        }}
    return false;
}
Example #8
0
void BoardGenerator::rollbackRound(int round){
    if (recordHistory) addHistoryItem(new LogItem(round, LogItem::ROLLBACK));
    {for (int i=0; i<BOARD_SIZE; i++){
            if (solutionRound[i] == round){
                solutionRound[i] = 0;
                solution[i] = 0;
            }
        }}
    {for (int i=0; i<POSSIBILITY_SIZE; i++){
            if (possibilities[i] == round){
                possibilities[i] = 0;
            }
        }}

    while(solveInstructions->size() > 0 && solveInstructions->back()->getRound() == round){
        solveInstructions->pop_back();
    }
}
Example #9
0
bool BoardGenerator::pointingColumnReduction(int round){
    for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
        for (int section=0; section<9; section++){
            int secStart = sectionToFirstCell(section);
            bool inOneCol = true;
            int boxCol = -1;
            {for (int i=0; i<3; i++){
                    for (int j=0; j<3; j++){
                        int secVal=secStart+i+(9*j);
                        int valPos = getPossibilityIndex(valIndex,secVal);
                        if(possibilities[valPos] == 0){
                            if (boxCol == -1 || boxCol == i){
                                boxCol = i;
                            } else {
                                inOneCol = false;
                            }
                        }
                    }
                }}
            if (inOneCol && boxCol != -1){
                bool doneSomething = false;
                int col = cellToColumn(secStart) + boxCol;
                int colStart = columnToFirstCell(col);

                {for (int i=0; i<9; i++){
                        int position = colStart+(9*i);
                        int section2 = cellToSection(position);
                        int valPos = getPossibilityIndex(valIndex,position);
                        if (section != section2 && possibilities[valPos] == 0){
                            possibilities[valPos] = round;
                            doneSomething = true;
                        }
                    }}
                if (doneSomething){
                    if (recordHistory) addHistoryItem(new LogItem(round, LogItem::POINTING_PAIR_TRIPLE_COLUMN, valIndex+1, colStart));
                    return true;
                }
            }
        }
    }
    return false;
}
Example #10
0
bool BoardGenerator::pointingRowReduction(int round){
    for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
        for (int section=0; section<9; section++){
            int secStart = sectionToFirstCell(section);
            bool inOneRow = true;
            int boxRow = -1;
            for (int j=0; j<3; j++){
                {for (int i=0; i<3; i++){
                        int secVal=secStart+i+(9*j);
                        int valPos = getPossibilityIndex(valIndex,secVal);
                        if(possibilities[valPos] == 0){
                            if (boxRow == -1 || boxRow == j){
                                boxRow = j;
                            } else {
                                inOneRow = false;
                            }
                        }
                    }}
            }
            if (inOneRow && boxRow != -1){
                bool doneSomething = false;
                int row = cellToRow(secStart) + boxRow;
                int rowStart = rowToFirstCell(row);

                {for (int i=0; i<9; i++){
                        int position = rowStart+i;
                        int section2 = cellToSection(position);
                        int valPos = getPossibilityIndex(valIndex,position);
                        if (section != section2 && possibilities[valPos] == 0){
                            possibilities[valPos] = round;
                            doneSomething = true;
                        }
                    }}
                if (doneSomething){
                    if (recordHistory) addHistoryItem(new LogItem(round, LogItem::POINTING_PAIR_TRIPLE_ROW, valIndex+1, rowStart));
                    return true;
                }
            }
        }
    }
    return false;
}
Example #11
0
/**
 * Mark exactly one cell that has a single possibility, if such a cell exists.
 * This method will look for a cell that has only one possibility.  This type
 * of cell is often called a "single"
 */
bool BoardGenerator::onlyPossibilityForCell(int round){
    for (int position=0; position<BOARD_SIZE; position++){
        if (solution[position] == 0){
            int count = 0;
            int lastValue = 0;
            for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0){
                    count++;
                    lastValue=valIndex+1;
                }
            }
            if (count == 1){
                mark(position, round, lastValue);
                if (recordHistory) addHistoryItem(new LogItem(round, LogItem::SINGLE, lastValue, position));
                return true;
            }
        }
    }
    return false;
}
Example #12
0
/**
 * Mark exactly one cell which is the only possible value for some column, if
 * such a cell exists.
 * This method will look in a column for a possibility that is only listed
 * for one cell.  This type of cell is often called a "hidden single"
 */
bool BoardGenerator::onlyValueInColumn(int round){
    for (int col=0; col<COL_HEIGHT; col++){
        for (int valIndex=0; valIndex<NUM_POSS; valIndex++){
            int count = 0;
            int lastPosition = 0;
            for (int row=0; row<ROW_LENGTH; row++){
                int position = rowColumnToCell(row,col);
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0){
                    count++;
                    lastPosition = position;
                }
            }
            if (count == 1){
                int value = valIndex+1;
                if (recordHistory) addHistoryItem(new LogItem(round, LogItem::HIDDEN_SINGLE_COLUMN, value, lastPosition));
                mark(lastPosition, round, value);
                return true;
            }
        }
    }
    return false;
}
Example #13
0
bool BoardGenerator::hiddenPairInRow(int round){
    for (int row=0; row<9; row++){
        for (int valIndex=0; valIndex<9; valIndex++){
            int c1 = -1;
            int c2 = -1;
            int valCount = 0;
            for (int column=0; column<9; column++){
                int position = rowColumnToCell(row,column);
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0){
                    if (c1 == -1 || c1 == column){
                        c1 = column;
                    } else if (c2 == -1 || c2 == column){
                        c2 = column;
                    }
                    valCount++;
                }
            }
            if (valCount==2){
                for (int valIndex2=valIndex+1; valIndex2<9; valIndex2++){
                    int c3 = -1;
                    int c4 = -1;
                    int valCount2 = 0;
                    for (int column=0; column<9; column++){
                        int position = rowColumnToCell(row,column);
                        int valPos = getPossibilityIndex(valIndex2,position);
                        if (possibilities[valPos] == 0){
                            if (c3 == -1 || c3 == column){
                                c3 = column;
                            } else if (c4 == -1 || c4 == column){
                                c4 = column;
                            }
                            valCount2++;
                        }
                    }
                    if (valCount2==2 && c1==c3 && c2==c4){
                        bool doneSomething = false;
                        for (int valIndex3=0; valIndex3<9; valIndex3++){
                            if (valIndex3 != valIndex && valIndex3 != valIndex2){
                                int position1 = rowColumnToCell(row,c1);
                                int position2 = rowColumnToCell(row,c2);
                                int valPos1 = getPossibilityIndex(valIndex3,position1);
                                int valPos2 = getPossibilityIndex(valIndex3,position2);
                                if (possibilities[valPos1] == 0){
                                    possibilities[valPos1] = round;
                                    doneSomething = true;
                                }
                                if (possibilities[valPos2] == 0){
                                    possibilities[valPos2] = round;
                                    doneSomething = true;
                                }
                            }
                        }
                        if (doneSomething){
                            if (recordHistory) addHistoryItem(new LogItem(round, LogItem::HIDDEN_PAIR_ROW, valIndex+1, rowColumnToCell(row,c1)));
                            return true;
                        }
                    }
                }
            }
        }
    }
    return false;
}
Example #14
0
bool BoardGenerator::hiddenPairInSection(int round){
    for (int section=0; section<9; section++){
        for (int valIndex=0; valIndex<9; valIndex++){
            int si1 = -1;
            int si2 = -1;
            int valCount = 0;
            for (int secInd=0; secInd<9; secInd++){
                int position = sectionToCell(section,secInd);
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0){
                    if (si1 == -1 || si1 == secInd){
                        si1 = secInd;
                    } else if (si2 == -1 || si2 == secInd){
                        si2 = secInd;
                    }
                    valCount++;
                }
            }
            if (valCount==2){
                for (int valIndex2=valIndex+1; valIndex2<9; valIndex2++){
                    int si3 = -1;
                    int si4 = -1;
                    int valCount2 = 0;
                    for (int secInd=0; secInd<9; secInd++){
                        int position = sectionToCell(section,secInd);
                        int valPos = getPossibilityIndex(valIndex2,position);
                        if (possibilities[valPos] == 0){
                            if (si3 == -1 || si3 == secInd){
                                si3 = secInd;
                            } else if (si4 == -1 || si4 == secInd){
                                si4 = secInd;
                            }
                            valCount2++;
                        }
                    }
                    if (valCount2==2 && si1==si3 && si2==si4){
                        bool doneSomething = false;
                        for (int valIndex3=0; valIndex3<9; valIndex3++){
                            if (valIndex3 != valIndex && valIndex3 != valIndex2){
                                int position1 = sectionToCell(section,si1);
                                int position2 = sectionToCell(section,si2);
                                int valPos1 = getPossibilityIndex(valIndex3,position1);
                                int valPos2 = getPossibilityIndex(valIndex3,position2);
                                if (possibilities[valPos1] == 0){
                                    possibilities[valPos1] = round;
                                    doneSomething = true;
                                }
                                if (possibilities[valPos2] == 0){
                                    possibilities[valPos2] = round;
                                    doneSomething = true;
                                }
                            }
                        }
                        if (doneSomething){
                            if (recordHistory) addHistoryItem(new LogItem(round, LogItem::HIDDEN_PAIR_SECTION, valIndex+1, sectionToCell(section,si1)));
                            return true;
                        }
                    }
                }
            }
        }
    }
    return false;
}
Example #15
0
bool BoardGenerator::hiddenPairInColumn(int round){
    for (int column=0; column<9; column++){
        for (int valIndex=0; valIndex<9; valIndex++){
            int r1 = -1;
            int r2 = -1;
            int valCount = 0;
            for (int row=0; row<9; row++){
                int position = rowColumnToCell(row,column);
                int valPos = getPossibilityIndex(valIndex,position);
                if (possibilities[valPos] == 0){
                    if (r1 == -1 || r1 == row){
                        r1 = row;
                    } else if (r2 == -1 || r2 == row){
                        r2 = row;
                    }
                    valCount++;
                }
            }
            if (valCount==2){
                for (int valIndex2=valIndex+1; valIndex2<9; valIndex2++){
                    int r3 = -1;
                    int r4 = -1;
                    int valCount2 = 0;
                    for (int row=0; row<9; row++){
                        int position = rowColumnToCell(row,column);
                        int valPos = getPossibilityIndex(valIndex2,position);
                        if (possibilities[valPos] == 0){
                            if (r3 == -1 || r3 == row){
                                r3 = row;
                            } else if (r4 == -1 || r4 == row){
                                r4 = row;
                            }
                            valCount2++;
                        }
                    }
                    if (valCount2==2 && r1==r3 && r2==r4){
                        bool doneSomething = false;
                        for (int valIndex3=0; valIndex3<9; valIndex3++){
                            if (valIndex3 != valIndex && valIndex3 != valIndex2){
                                int position1 = rowColumnToCell(r1,column);
                                int position2 = rowColumnToCell(r2,column);
                                int valPos1 = getPossibilityIndex(valIndex3,position1);
                                int valPos2 = getPossibilityIndex(valIndex3,position2);
                                if (possibilities[valPos1] == 0){
                                    possibilities[valPos1] = round;
                                    doneSomething = true;
                                }
                                if (possibilities[valPos2] == 0){
                                    possibilities[valPos2] = round;
                                    doneSomething = true;
                                }
                            }
                        }
                        if (doneSomething){
                            if (recordHistory) addHistoryItem(new LogItem(round, LogItem::HIDDEN_PAIR_COLUMN, valIndex+1, rowColumnToCell(r1,column)));
                            return true;
                        }
                    }
                }
            }
        }
    }
    return false;
}
Example #16
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;
}