//------------------------------------------------------------------------------------
//Title:   BRAIN98.c      ver.3
//Authors: Jason Moreau and Doug Patnaude
//Date: 11-18-99
//Description:  This is our third version of BRAIN.  In this installment we included
//              the ability to allow for the dynamic creation and deletion of BRAIN98
//              processes that use a prespecified address space from addresses 0 up to
//              n.  To accomplish this several changes to the code were made.  First
//              of all, the first line of brain98 code now requires that n be given.
//              N is an int that specifies how much space the process needs (or in
//              this case, wants!).  
//              A new operator named "SP__" (spawn) was added.  This operator is given
//              a two character name of a brain file to open.  
//              A scheme to manage this memory is needed and this is included in our
//              function malloc.  The method we use to keep track of how memory has
//              been allocated is a bitmap.  A bit is set for each location in memory.
//              (note: this wouldn't be an optimal method in a real operating system
//              because half of memory would be taken up by bits; in our case we have
//              a seemingly endless supply of magic memory in the background so this
//              method works quite well.
//              Our method of allocating the memory can be changed in the options
//              menu.  The user has a choice between first fit and next fit.  These
//              are talked about in greater depth in our writeup.
//              Along side with these new options, a brand-new user-friendly interface
//              has been added to BRAIN.  The user now has run-time screen dump
//              options to choose from as well as messages that state what the program
//              is doing at any given moment.  A debug feature was also added that
//              has multiple functions for analyzing code.  These are also explained
//              in greater detail in the write-up.
//_____________________________________________________________________________________

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

struct word {        //This sturcture is our primary memory structure.  It
  char letter[5];    //is a five character array, primarily used as a string.
};                   //The fifth character is used for the delimiter.

struct tinny {       //This is the structure that is our virtual machine.
  char r[5];          //This is the R register
  int c;              //This is the C register
  int ic;             //This is the IC counter
  int timer;          //This is the index counter
};

struct phor{     //This structure represents a semaphore.   The hold variable
  int hold;         //is the int that states if something is holding on it
  int semq[1000];     //Semq is a ten item int array that holds the pid values of
  int qind;         //those processes waiting on it.  qind is an index to the
};                //This is a mail box structure.  The flag is 1 if there

struct mbox {         //This is a mail box structure.  The flag is 1 if there
  int flag;            //is mail in the box.  Addr holds the address of the
  struct word addr;    //the message to be sent.
};

struct process {    	//This is our struct for process tables.
  char R[5];            //This holds the R value
  int C;                //This holds the C value
  int IC;               //This holds the index counter
  int offset;           //This holds the real memory offset of a process
  int pid;              //This holds the process ID of the process
  int before;           //This tells what process is ahead of it on the list
  int after;            //and this tells which follows it on the list
  struct mbox mail[1000]; //This is the processes mailbox for receiving messages
  int blocked;          //Tells if process is blocked or not.
  int bsem;             //If blocked on a semaphore.
  int mreq;             
  FILE *cfptr;          //The file pointer associated with the process.
  int run;
  int dirty;            //Dirty bit (not yet used *put in for preparation for p4)
};

struct process process_table[1000];  //Our process table is now 1000 large (max amount of processes possible)
struct word wordlist[1000];          //1000 memory locations (0-999)
struct word share[100];              //100 shared memory locations (0-99)
struct phor  sema[100];              //100 semaphores (0-99)
struct tinny vm;                     //Our virtual "physical" machine
int bitmas[1000];                    //The bitmap(one bit for ever memory location.
int a,b,nexc;                        //Where the values for A = x1x2 and B = x1*10 are stored
int mmpid;                                                                                                        //?
char buffer[5];                      //Used in reading and storing operations
void setstr(int);
void seta(int,int);        //returns a value as an int instead of as string
void setb(int,int);        //returns b value as an int instead of as string
int inputer(FILE *,int, int);   //Loads program into memory
void lr();           //(R := [a] )
void ll();           //(R := zz[a]3[a]4[a])
void lh();           //(R := [a]1[a]2zz)
void sr();           //([a] := R)
void ce();           //(if R=[a] -> C:=T else C:=F)
void cl();           //(if R<[a] -> C:=T else C:=F)
void bt();           //(if C = T then IC := [a])
void bu();           //(IC := [a])
void gd();           //(Read ([b+i], i=0,...,9)
void pd();           //(Print ([b+i], i=0,...,9)
void sd();           //(Send Message)
void rc();           //(Receive Message)
void ad();           //(R := R + [a])
void su();           //(R := R - [a])
void mu();           //(R := R * [a])
void di();           //(R := R / [a])
void np();           //(NO OP)
void messa(int);     //Generates a without the offset
void interpreter();  //Determines which function is needed for each operator
int sched(int);      //Scheduals the next process in line
void ls();           //(load from shared memory)
void ss();           //(Store in shared memory)
void pe();           //Down Semaphore
void ve();           //Up Semaphore
void si();           //Set semaphore value
void gp();           //Get Pid
void sp();           //The SP operator (spawn)
int bmalloc(int);    //our memory allocation function (next fit)
int bmalloc2(int);   //our memory allocation function (first fit)
void bfree(int);     //frees up memory                                                                //?
void options();     //The options menu.
void BMode();       //The Main menu.
void DBug();        //The debugger.
void dhelp();       //Debugger - Displays help menu
void dmem();        //Debugger - Memory Display function
void showBM();      //Debugger - Display Bitmap function
void skipit();      //Debugger - Skip Steps function
void dispQ();       //Debugger - Display Process Queue function
int x;              //stores present pid of running process
int instruct;       //used to graph calculation of context vs. num ops                               ***
int context;        //keeps track of the number of context switches                                  ***
int tot;            //another counter for testing code                                               ***
int allo;                                                                                            //?
FILE *cfptr;        //Store file pointers
char buf[80];       //used for storing lines of brain98 files
char halter[5];     //temp storage of Brain98 ops
int blsemf, blmsgf, sendf, recf, accessf, upsemf, dnsemf, mallocf, endloop; //flags for debug options
int debugf;                                                        //flag turns on and off debug mode.
int skipcount;             //Used by debugger to specify how many steps to skip.

int main(){
  int loop;       //used for loops
  int z;          //
  int q;          //
  char path[64];     //File Name Buffer... assumes name length < 64 chars
  char bran[82];     //stores line of brain code
  buffer[0] = '\0';   //makes buffer an empty string
  strcpy(vm.r,"0000");   //Inits R to all zeros
  loop = 1;              //Initiates loop
  blsemf = 0;            //initialize all Options under the Options menu to O.
  blmsgf = 0;            //
  sendf = 0;             //
  recf = 0;              //
  accessf = 0;           //
  upsemf = 0;            //
  dnsemf = 0;            //
  mallocf = 0;           // sets default method of allocation to First Fit
  debugf = 0;            // Defaults to non-debug mode.
  skipcount = 0;         // No skips are need when the debugger starts.

  instruct = 0;          // Initializes graph counters
  context = 0;           //
  nexc = 0;              //                                                                              //?
  tot = 0;               //
  vm.timer = 0;          // Sets internal timer to 0
  for (x = 0;x < 1000; x++){              //initializes all memory words to 0000.
    strcpy(wordlist[x].letter,"0000");
  }
  for (x = 0;x < 1000;x++){               //intitializes process_table
    process_table[x].IC = -1;
    process_table[x].blocked = 1001;
    process_table[x].bsem = 100;
    process_table[x].run = 0;
    process_table[x].dirty = 1;
  }
  for (x = 0;x < 100;x++){                //initializes all our semaphores to 1;
    sema[x].hold = 1;
    strcpy(share[x].letter,"0000");
    for (q = 0;q < 1000;q++){
      sema[x].semq[q] = 1001;
    }
  }
  allo = 0;

  BMode();     //Displays the main menu.

  printf ("Open file? \n");  //After all options are set and user chooses to move on theya are
  scanf("%s", &path);        //asked to specify the brain file to run.
  if ((process_table[0].cfptr=fopen(path,"r")) == NULL){   //if the BRAIN98 file given is invalid
    exit(1);                                               //we quit out, which is a bit more
  }                                                        //elegant than crashing and core dumping.
  printf("opened\n");                                   //Otherwise, we know the file opened fine.
  fscanf(process_table[0].cfptr,"%s",bran);             //check to see if it is a valid brain file                ?
  fscanf(process_table[0].cfptr,"%d\n",&allo);          //allo is set to the number provided by the process       ?
  //printf("%s\n%d\n",bran,allo);
  if (strcmp(bran,"BRAIN98") == 0){
    z = 0;
    process_table[z].mreq = allo;
    if (mallocf == 1){                                                     //The method of memory allocation
      while (inputer(process_table[0].cfptr,z,bmalloc(allo)) == 0){        //is determined by the options menu.
	process_table[z].after = z + 1;                                    //if the bit is set to 1 we use next
	z++;                                                               //next fit
	process_table[z].before = z - 1;
      }
    }
    else{                                                                  //Otherwise we use the first fit method.
      while (inputer(process_table[0].cfptr,z,bmalloc2(allo)) == 0){       //bmalloc allocates the memory            
	process_table[z].after = z + 1;                                    //the process table is then
	z++;                                                               //updated accordingly
	process_table[z].before = z - 1;
      }
    }
    process_table[0].run = 1;
    process_table[0].dirty = 1;
    process_table[0].before = z;
    process_table[z].after = 0;
    mmpid = z;                         // keeps track of the next pid to give out                                     ?
    mmpid++;
    x = 0;
    vm.ic = x * 100;
    while (loop == 1){                                       //Until program is finished...
      sprintf(halter,"%c",wordlist[vm.ic].letter[0]);        //Check for H operator
      while((strcmp(halter,"h") != 0) && (vm.timer != 2)){   //As long as we have not reached a halt or our
	seta(vm.ic,process_table[x].offset);                  //quantum has expired, set A and B relative to
	setb(vm.ic,process_table[x].offset);                  //the processes offset.
	//if (instruct == 100){
	//  printf("Number of context switchs %d Instructions %d\n",context,tot);
	//  instruct = 0;
	//}
        if(debugf){                                           //Runs the debugger if it has been toggled on
          DBug();                                             //by the user in the options menu.
        }
	interpreter();                                        //determines what function is needed for the operator
	sprintf(halter,"%c",wordlist[vm.ic].letter[0]);       //Reads in next line and repeats.
      }
      if (vm.timer == 2){                                     //This is our timer.  When it expires, the 
	x = sched(x);                                         //schedular is called.
	vm.timer = 0;                                         //and the timer is reset.
      }
      else{
	if (process_table[x].after != x){                     //if we have reached a hault...
	  process_table[process_table[x].before].after = process_table[x].after;  //The process is removed from the
	  process_table[process_table[x].after].before = process_table[x].before; //the queue.
	  //printf("Process %d Halted\n",x);                                                       //Make option
	  process_table[x].run = 0;                                               //This is done by having the other
	  fclose(process_table[x].cfptr);                                         //processes to either side of it
	  bfree(x);                                                               //point to each other
	  x = sched(x);                                       //We then free up the memory and call the sheduler.
	}
	else{
	  //printf("freeing mem\n");
	  process_table[x].run = 0;
	  bfree(x);
	  exit(0);
	}
      }
    }
  }
  else{
    fprintf(stderr,"not a brain file");                       //If it was determined that the file specified was not
  }                                                           //a brain file, we print and error and exit.
  return 0;
}

//This function takes the memory location of the command and extracts
//the a value which if x1x2 is the operand, a = 10x1+x2.  Now this function
//must take into consideration the offset in memory
void seta(int i,int off){
  int hold;
  char *offset = wordlist[i].letter;
  offset = offset +2;
  hold = atoi(offset);
  a = hold + off;
}

//This function takes the memory location of the command and extracts
//the b value which if x1x2 is the operand, a = 10x1+0.  Now this function
//must take into consideration the offset in memory
void setb(int i,int off){ 
    int hold;
    char *offset = wordlist[i].letter;
    offset = offset +2;
    hold = atoi(offset);
    offset++;
    b = hold - atoi(offset);
    b = b + off;
}

//This function takes a file descriptor as its input and reads
//the program from the file and into memory.
int inputer(FILE *fd, int i, int o){
  char buff[82];          //where a line from the file is stored.
  int counter = o;  //Used to index memory location
  process_table[i].pid = i;   //Set the pid
  process_table[i].offset = counter;   //sets the offset depending on was pid
  fgets(buff,80,fd);   //read the line into the buffer...
  buff[4] = '\0';      //makes sure string format is preserved
  while ((strcmp(buff,"BRAI") != 0) && (strcmp(buff,"END") != 0) && (strcmp(buff,"DATA") != 0) ){  
    if (buff[0] == 'h'){                            //while we have not reached some haulting point...
      //printf("read halt\n");                      if it is a hault...
      sprintf(wordlist[counter].letter,"h   ");     //buffer in zeros in memory (make sure halt is 4 chars large)
    }
    else{
      strncpy(wordlist[counter].letter,buff,4);     //...otherwise just copy it in.
    }
    counter++;
    fgets(buff,80,fd);                              //get the next line...
    buff[4] = '\0';                                 //and chop off the crap.
  }
  if(strcmp(buff,"BRAI") != 0) {                    //lets main know if we have another brain file
    return 1;                                       //or not.
  }
  else {
    return 0;
  }
}

//This function loads the value stored in memory location [a]
//int the R register.
void lr(){
  strcpy(vm.r,wordlist[a].letter);  //Simply copies it into place directly
}                                   //from memory using our indexing method.

//This function loads the low portion of a memory word into
//the low area of the R register.
void ll(){
  vm.r[2] = wordlist[a].letter[2];  //Using our indexing we take each part of
  vm.r[3] = wordlist[a].letter[3];   //memory and store in right into R
  vm.r[4] = '\0';                   //This is just a safety feature to ensure
}                                    //our string method is not lost.

//This function loads the high portion of a memory word into
//the high area of the R register.
void lh(){
  vm.r[0] = wordlist[a].letter[0];  //Uses the same technique as LL except
  vm.r[1] = wordlist[a].letter[1];   //it deals with the high areas.
  vm.r[4] = '\0';
}

//This function loads the value in the R register into the
//memory location [a].
void sr(){
  strcpy(wordlist[a].letter,vm.r);  //Directly copies the string into
}                                    //memory using our indexing.

//This function compares the value stored in R with the value
//stored in memory location [a] and sets the C register to true
//if they are equal and to false if they are not equal.
void ce(){
  if (strcmp(vm.r,wordlist[a].letter) == 0){   //uses strcmp to check if the
    vm.c = 1;                                   //two string values are equal.
  }                                            //If they are C is set to TRUE.
  else{
    vm.c = 0;                                  //IF not C is made FALSE.
  }
}

//This function compares the value stored in R with the value
//stored in memory location [a] and sets the C register to true
//if R is less than [a].
void cl(){
  if (strcmp(vm.r,wordlist[a].letter) < 0){  //Again, we use string compare
    vm.c = 1;                                 //and if the value returned is
  }                                           //less than zero we know that R
  else{                                       //is less than [a] and C is made
    vm.c = 0;                                 //to equal TRUE.
  }                                           //Otherwise we set C to FALSE.
}

//This function sets the IC register to a if the C register
//is set to TRUE.
void bt(){
  if (vm.c == 1){    //Checks to see if the C register contains TRUE.
    vm.ic = a;       //If so, the IC register now equal a.
  }
  else{
    vm.ic++;         //If not, we increment the instruction counter and move on.
  }                  //*NOTE*  For most functions the incrementation of the
}                    //        IC register is done by the interpreter.

//This function sets the IC register equal to the value of a.
void bu(){
  vm.ic = a;   //Simply sets IC to a.
}

//This function retreaves data from the DATA section and
//loads it into the memory location [a].  It does this in
//ten word clusters.  Example: if data was to be read into
//memory location 40, locations 40 - 49 would be loaded
//with the next 10 data items in successive order.
void gd(){
  int cou = 0;   //This value keeps track of how many data items have been read.
  int sind;      //Used to store calculated actual memory location.
  char temp[5];  //Temporary location to store data item
  while(cou != 10){          //Until we've read in 10 items...
    fscanf(process_table[x].cfptr,"%s",temp);  //Read the item into temp...
    sind = b + cou;           //Calculate memory location by adding our
    							      //initial memory location with our "i" value.
    strcpy(wordlist[sind].letter,temp); //and stores data item in this location.
    cou++;                        //now move to the next memory location...
  }                               //and do it again (until 10 have been read).
}

//This function prints to standard output data from the
//memory location [a].  It does this in ten word clusters.
// Example: if data was to be printed from
//memory location 40, the data in memory locations 40 - 49
//would be outputted to the screen.
void pd(){
  int cou = 0;         //Sets "i" to zero.
  int sind;         //used to store the current memory location to be delt with.
  char temp[5];        //Temporary storage for data to be printed to output.
  while(cou != 10){    //While we have not printed 10 items to the screen...
    sind = b + cou;    //Figure out what memory location we are at...
    printf("%s ",wordlist[sind].letter);  //Print this value to output...
    cou++;                                //and move on to next mem location.
  }
  printf("\n");                           //when we are done, we move the
}                                         //cursor to the next line.

//This function adds the values stored in the R register and
//the memory location [a] and stores the sum into R.  If the
//added amount exceeds the bounds of the register, then the lower
//four places are preserved, and no error is reported.  If AD is
//given a non-number value it reports an error.
void ad(){
  int z;              //Used in a FOR loop.
  int digflg = 0;     //Flag to report if a character is not a digit.
  int rval,nval,sum;  //Temp storage for R, [a], and the sum of the two.
  char sumbuff[6];    //Temp storage for the char conversion of the sum.
  for(z = 0;z < 4;z++){        //This for loop checks the four char values
    if(isdigit(vm.r[z]) == 0){  //stored in R to see if they are digits
      digflg = 1;              //if not a digit, set the flag.
    }
    if(isdigit(wordlist[a].letter[z]) == 0){
      digflg = 1;              //Does the same check to the memory location.
    }
  }
  if (digflg == 0){           //If the flag was not se we know we that we have
    rval = atoi(vm.r);         //valid digits.  At this point each character
    nval = atoi(wordlist[a].letter);  //value is converted to its INT equivelent
    sum = rval + nval;                //using atoi (sting to int).
    sprintf(sumbuff,"%d",sum);        //sum is then converted to a string.
    if (strlen(sumbuff) > 4){         //if the number is larger than what we
      char *offset = sumbuff;       //set the pointer to point to the sumbuff.
      offset++;                     //increment to the pointer so that it
      strcpy(vm.r,offset);          //points to the 4'th digit and copy that
    }                               //string (4digit string) to R.
    else{
      if(sum < 1000){                  //This is our big cludge that fixes the
	sprintf(sumbuff,"%s%d","0",sum);    //problem of no leading zeros in our
      }                                //calulated strings.  Right now this
      if(sum < 100){                   //piece of code is messily pasted in each
	   sprintf(sumbuff,"%s%d","00",sum); //of the arithmetic operators.  In the
      }                                 //next version of BRAIN this will be
      if(sum < 10){                     //changed into a function to make things
	   sprintf(sumbuff,"%s%d","000",sum);//neater.  What this does is pack the
      }                                 //appropriate amount of zeros into the
      if(sum > 999){                    //the string if its value has less than
	sprintf(sumbuff,"%d",sum);           //four digits.
      }
      strcpy(vm.r,sumbuff);             //This fixed value is then placed in R.
    }
  }
  else{                                 //Error message for non numeric data.
    fprintf(stderr,"Cannot add non-numeric data.\n");
  }
}

//This function subtracts the value located in memory
//location [a] from R and stores difference in R. This
//function does not allow [a] to be larger than R because
//brain does not yet have a concept of negative numbers.
//If this occurs, an error message is printed and no
//subtraction takes place.
void su(){
  int z;            //Used in FOR loop.
  int digflg = 0;   //Flag that is triggered if a non-numeric value is used
  int rval,nval,sum;    //Temp storage for R, [a], and the difference.
  char sumbuff[6];      //Used to temporarily store the difference (string form)
  for(z = 0;z < 4;z++){        //This loop checks through all chars in the
    if(isdigit(vm.r[z]) == 0){ //to see if they are digits in R.
      digflg = 1;              //if they are not, then the flag is tripped.
    }
    if(isdigit(wordlist[a].letter[z]) == 0){
      digflg = 1;              //The same is done to memory.
    }
  }
  if (digflg == 0){                   //If the string is comprised of digits
    rval = atoi(vm.r);                 //then it is converted into a int value
    nval = atoi(wordlist[a].letter);   //in the same manner it was done in AD.
    sum = rval - nval;
    if (sum >= 0){          //As long as the value is not negative...
      if(sum < 1000){                       //ONCE AGAIN... the cludge...
	   sprintf(sumbuff,"%s%d","0",sum);
	}
	if(sum < 100){
	   sprintf(sumbuff,"%s%d","00",sum);
	}
	if(sum < 10){
	   sprintf(sumbuff,"%s%d","000",sum);
	}
	if(sum > 999){
	  sprintf(sumbuff,"%d",sum);
	}
      strcpy(vm.r,sumbuff);
    }
    else{
      fprintf(stderr,"negitive result in subtract.\n");
    }
  }
  else{                              //Message that is displayed if diff is neg.
    fprintf(stderr,"Cannot subtract non-numeric data.\n");
  }
}

//This function multiplies the values of R and [a] and
//stores that value in R.  If overflow occurs the lower
//four digits are preserved and no error message is displayed.
void mu(){
  int z;                    //again, our standard method of checking for
  int digflg = 0;            //numeric values.  Our next version will make
  int rval,nval,sum;         //a function out of this process for better
  char sumbuff[9];           //organization.  This time the buffer is 9
  for(z = 0;z < 4;z++){      //chars in size because the max size of the
    if(isdigit(vm.r[z]) == 0){  //multiplication is eight digits (last place
      digflg = 1;               //is for the null character.
    }
    if(isdigit(wordlist[a].letter[z]) == 0){
      digflg = 1;
    }
  }
  if (digflg == 0){
    rval = atoi(vm.r);
    nval = atoi(wordlist[a].letter);
    sum = rval * nval;
    sprintf(sumbuff,"%d",sum);
    if (strlen(sumbuff) > 4){
      char *offset = sumbuff;
      rval = strlen(sumbuff) -4;     //Sets a pointer to point at the fourth
      offset = offset + rval;         //digit so we can throw away the overflow.
      if(sum < 1000){                 //AND AGAIN... THE CLUDGE!
	sprintf(sumbuff,"%s%d","0",sum);
      }
      if(sum < 100){
	sprintf(sumbuff,"%s%d","00",sum);
      }
      if(sum < 10){
	sprintf(sumbuff,"%s%d","000",sum);
      }
      if(sum > 999){
	sprintf(sumbuff,"%d",sum);
      }
      strcpy(vm.r,offset);
    }
    else{
      if(sum < 1000){                     //BUT... must be done twice incase
	   sprintf(sumbuff,"%s%d","0",sum);    //there is no overflow.
	}
	if(sum < 100){
	   sprintf(sumbuff,"%s%d","00",sum);
	}
	if(sum < 10){
	   sprintf(sumbuff,"%s%d","000",sum);
	}
	if(sum > 999){
	  sprintf(sumbuff,"%d",sum);
	}
      strcpy(vm.r,sumbuff);
    }
  }
  else{                                  //ERROR FOR NON-NUMERIC DATA PRINTED
    fprintf(stderr,"Cannot mult non-numeric data.\n");
  }
}

//This function divides the value in R by the value in [a] and
//stores this value back in R.  Of course, division by zero causes
//an error (undefined) and the user is told of it.
void di(){
  int z;                          //Our standard check for valid numeric values.
  int digflg = 0;                  //...
  int rval,nval,sum;               //...
  char sumbuff[6];
  for(z = 0;z < 4;z++){
    if(isdigit(vm.r[z]) == 0){
      digflg = 1;
    }
    if(isdigit(wordlist[a].letter[z]) == 0){
      digflg = 1;
    }
  }
  if (digflg == 0){
    rval = atoi(vm.r);
    nval = atoi(wordlist[a].letter);
    if (nval != 0)                  //As long as we are not dividing by zero...
      {
	sum = rval / nval;
	if(sum < 1000){                        //ARGG... the CLUDGE!....
	   sprintf(sumbuff,"%s%d","0",sum);
	}
	if(sum < 100){
	   sprintf(sumbuff,"%s%d","00",sum);
	}
	if(sum < 10){
	   sprintf(sumbuff,"%s%d","000",sum);
	}
	if(sum > 999){
	  sprintf(sumbuff,"%d",sum);
	}
	strcpy(vm.r,sumbuff);
      }                           //Error printed if division by zero detected.
    else{
      fprintf(stderr,"Division by zero detected.\n");
    }
  }
  else{                           //and error if non-numeric value are used.
    fprintf(stderr,"Cannot add non-numeric data.\n");
  }
}

//This function does nothing.  It was a joy to program.
void np(){   //Like the name suggests, it does absolutely nothing... neat.
};

//This function determines what operator to used based on the line
//read from memory.  What it does is checks the first and second
//characters of the data stored in memory through a series of case
//statements.  When the operator is found the function that the
//operator represents is called and after completetion (in most cases)
//the IC register is incremented (it is not done so atomatically if the
//function involves changing the counter itself).  If the operand is
//determined not to be valid an error message is displayed, no action
//is done, and the program continues to run.
void interpreter(){
  switch(wordlist[vm.ic].letter[0]){
  case 'g':
    gp();
    vm.ic++;
    break;
  case 'G':
    gd();
    vm.ic++;
    break;
  case 'A':
    ad();
    vm.ic++;
    break;
  case 'B':
    switch(wordlist[vm.ic].letter[1]){
    case 'T':
      bt();
      break;
    case 'U':
      bu();
      break;
    default:
      fprintf(stderr,"%c%c invalid command",wordlist[vm.ic].letter[0],wordlist[vm.ic].letter[1]);
      vm.ic++;
    }
    break;
  case 'C':
    switch(wordlist[vm.ic].letter[1]){
    case 'E':
      ce();
      vm.ic++;
      break;
    case 'L':
      cl();
      vm.ic++;
      break;
    default:
      fprintf(stderr,"%c%c invalid command",wordlist[vm.ic].letter[0],wordlist[vm.ic].letter[1]);
      vm.ic++;
    }
    break;
  case 'D':
    di();
    vm.ic++;
    break;
  case 'L':
    switch(wordlist[vm.ic].letter[1]){
    case 'H':
      lh();
      vm.ic++;
      break;
    case 'L':
      ll();
      vm.ic++;
      break;
    case 'R':
      lr();
      vm.ic++;
      break;
    case 'S':
      ls();
      vm.ic++;
      break;
    default:
      fprintf(stderr,"%c%c invalid command",wordlist[vm.ic].letter[0],wordlist[vm.ic].letter[1]);
      vm.ic++;
    }
    break;
  case 'M':
    mu();
    vm.ic++;
    break;
  case 'N':
    np();
    vm.ic++;
    break;
  case 'P':
    switch(wordlist[vm.ic].letter[1]){
    case 'D':
      pd();
      vm.ic++;
      break;
    case 'E':
      pe();
      break;
    default:
      fprintf(stderr,"%c%c invalid command\n",wordlist[vm.ic].letter[0],wordlist[vm.ic].letter[1]);
      vm.ic++;
    }
    break;
  case 'R':
    rc();
    break;
  case 'S':
    switch(wordlist[vm.ic].letter[1]){
    case 'D':
      sd();
      break;
    case 'I':
      si();
      vm.ic++;
      break;
    case 'R':
      sr();
      vm.ic++;
      break;
    case 'S':
      ss();
      vm.ic++;
      break;
    case 'U':
      su();
      vm.ic++;
      break;
    case 'P':
      sp();
      break;
    default:
      fprintf(stderr,"%c%c invalid command\n",wordlist[vm.ic].letter[0],wordlist[vm.ic].letter[1]);
      vm.ic++;
    }
    break;
  case 'V':
    ve();
    vm.ic++;
    break;
  default:
    printf("No command recognized %s.\n",wordlist[vm.ic].letter);
    vm.ic++;
  }
  vm.timer++;
  instruct++;
  tot++;
  printf("ic %d\n",vm.ic);
}

//This function saves the state of the currectly running process, takes it
//off run and puts it on the ready list, and restores the next process in line
//to run.
int sched(int id){
int npid;                        //Pid of next Process to run
strcpy(process_table[id].R,vm.r);    //Saves registers of currently running
process_table[id].C = vm.c;           //process...
process_table[id].IC = vm.ic;         //
npid = process_table[id].after;   //Set to the PID of the next process to run.
//printf("Npid %d\n",npid);                                                                         ***
context++;                       //Used for graphing problem.
strcpy(vm.r,process_table[npid].R);  //Restores registers of next process
vm.c = process_table[npid].C;         //
vm.ic = process_table[npid].IC;       //
return npid;                          //Set pid of current process (x)
}

//This function send a message to a process with the PID given in x1x2.  The
//to send is stored in the address that is stored in R.  After a message is sent
//the process blocks until the process that it sent the message to receives
//the message.  After the message is receives the process is put back on the
//ready linked list.
void sd(){
  messa(vm.ic);    //Returns unoffsetted x1x2 value of a
  sprintf(process_table[a].mail[x].addr.letter,"%s", vm.r);  //Places address
  process_table[a].mail[x].flag = 1;         //in mail box and raises the flag
  // printf("%d blocked %d\n",a,process_table[a].blocked);
  if((process_table[a].blocked == x) || (process_table[a].blocked == 1000)){
    process_table[a].before = process_table[x].before;  //If process to be sent
    process_table[a].after = process_table[x].after;  //to is blocked on us or
    process_table[process_table[x].after].before = a; //it is waitig for block
    process_table[process_table[x].before].after = a; //anyone, wake it up.
    process_table[x].after = a;     //we also remove ourselves from the queue
    //printf("Send did not block\n");
  }
  else{     //otherwise we will only need to remove ourselves from the queue
    process_table[process_table[x].after].before = process_table[x].before;
    process_table[process_table[x].before].after = process_table[x].after;
    // printf("Send blocked %d\n",x);
    if(process_table[x].after ==x){   //If everything is blocking we have
      fprintf(stderr, "All Processes blocked exiting\n"); //achieved deadlock
      exit(1);                        //so brain exits displaying this error
    }                                 //message.
  }
  vm.ic++;        //we increase our index counter
  vm.timer = -1;  //reset the clock
  x = sched(x);   //and reschedual
}

//This function makes a process wait for message from a PID given in x1x2 = a.
//Also, if x1x2 is XX this process will wait for the first message it recieves
//from anyone.  While we wait to receive a message we are removed from the
//process linked list and we block until we receive a message from the desired
//source.
void rc(){
  int j;      //loop variable
  int flag;   //is set if we received the wanted message
  int cou;
  int reg;
  int off;
  char *offset = wordlist[vm.ic].letter;   //points to operation value in mem
  flag = 0;                                //init flag to zero
  offset = offset + 2;  //increments pointer twice so we are pointing x1x2 val
  messa(vm.ic);                    //gets x1x2 val as a
  if (strcmp(offset, "XX") == 0){  //checks to see if we are waiting for
    //printf("Waiting on any\n");   //any message
    process_table[x].blocked = 1000;  //11 delimates unblocked (because 0 would
    for(j = 0; j < 1000; j++){        //mean that we are blocked on 0)
      if(process_table[x].mail[j].flag == 1){  //Checks all the mail slots
        process_table[x].mail[j].flag = 0;     //if we find mail we "put down"
        a = j;                     //the mail flag (meaning we received it)
        flag = 1;                  //set our flag meaning we found mail,
        j = 1001;                    //and kill the loop
      }
    }
  }
  else{                           //If not XX variant, we simply check the mail
    process_table[x].blocked = a; //box of the specified process...
    //printf("Got to specific %d %d\n",a,process_table[x].blocked);
    if(process_table[x].mail[a].flag == 1){
      process_table[x].mail[a].flag = 0;
      flag = 1;                           //...if we find it set the flag
      //printf("Found flag\n");           //meaning we found it.
    }
  }
  if(flag == 1){                                 //If we did receive mail...
    process_table[a].after = x;                        //put message sender
    process_table[a].before = process_table[x].before; //back on the queue.
    process_table[process_table[x].before].after = a;
    if(process_table[process_table[x].after].after == process_table[x].after){
      process_table[process_table[x].after].after = a;
    }
    process_table[x].before = a;
    reg = x * 100;                 //Find offset of sender so we can copy
    reg = reg + atoi(vm.r);        //the data in his memory.
    off = a * 100;                 //
    off = off + atoi(process_table[x].mail[a].addr.letter);  //
    for(cou = 0;cou < 10;cou++){                             //
      strcpy(wordlist[reg].letter,wordlist[off].letter);  //and copy it to
      reg++;                         //the memory location we specified in R
      off++;                         //and the other nine values
    }
    process_table[x].blocked = 1001;      //remove ourselves from blocked
    //printf("%d Recieved %d\n",x,a);
    vm.ic++;                            //and finish up
    vm.timer = -1;
  }
  else{          //if we did not receive the message we block and wait
    if(strcpy(offset, "XX") != 0){
      process_table[x].blocked = a;
    }
    process_table[process_table[x].before].after = process_table[x].after;
    process_table[process_table[x].after].before = process_table[x].before;
    if(process_table[x].after == x){
      fprintf(stderr, "All Processes blocked. Now Exiting\n");
      exit(1);
    }
    x = sched(x);      //We don't inc the IC counter because we want to
  }                    //start the whole function again after we are awoken.
}

//This function calculates the value of a without adding the offset, like we
//did in the first brain project.
void messa(int i){
  int hold;
  char *offset = wordlist[i].letter;
  offset = offset +2;
  hold = atoi(offset);
  a = hold;
}

//This function allows a process to load register R with the value stored in
//a memory location in Shared Memory.  The location is calculated by x1x2 = a.
void ls(){
  messa(vm.ic);
  strcpy(vm.r,share[a].letter);
}

//This function stores the value in R to the memory location in shared memory
//denoted by x1x2 = a.
void ss(){
  //  int cou;
  //int fr;
  //int sind;
  //char temp[5];
  //cou = 0;
  messa(vm.ic);
  strcpy(share[a].letter,vm.r); 
  // for (fr = 0;fr < 10;fr++){
  //  while(cou != 10){
  //    sind = fr * 10;
  //    sind = sind + cou;
  //    printf("%s ",share[sind].letter);
  //    cou++;
  //  }
  //  cou = 0;
  //  printf("\n");
  //} 
}

//This function allows a process to do a Down on a semaphore.  What a down does
//decrement the semaphore (it is an int value, or at least the part we are
//concerned with is).  If the value of the semaphore is zero or greater than
//we may continue on without blocking.  If we get a value less than zero we are
//forced to block until someone ups the semaphore and wakes us up.
void pe(){
  messa(vm.ic);         //returns unadjucted value of A (no offset added)
  sema[a].hold--;       //Downs the semaphore.
  if(dnsemf){                                                         //option for downsem - displayed if toggled
    printf("%s%d%s%d%s%d%s%d%s", "Process ", x, " down on sem# ", a, ". Now sem# ", a, " = ", sema[a].hold, ".\n");
  }
  vm.ic++;
  if (sema[a].hold < 0){      //if the process is not permitted to pass because the semaphore was equalp to zero...
    if(blsemf){                                                                  //displayed if toggled in option menu
      printf("%s%d%s%d%s", "Process ", x, " blocked on semaphore ", a, "\n");    //option for semblock
    }
    process_table[process_table[x].before].after = process_table[x].after;   //...the process is removed from the 
    process_table[process_table[x].after].before = process_table[x].before;  //process queue...
    process_table[x].bsem = a;                                               //...we mark what we are blocked on...
    sema[a].semq[sema[a].qind] = x;                                          //...state our intent on getting through...
    sema[a].qind++;                                                          //
    if(process_table[x].after == x){                                         //if this process was the last one on the
      fprintf(stderr,"All Processes blocked exiting\n");                     //queue, we have now reached a point where
      exit(1);                                                               //all the processes have blocked and we are
    }                                                                        //stuck.
  }
  vm.timer = -1;                      //The timer is reset and we contact switch
  x = sched(x);                       //
}

//This function allows the process to preform an up on a semaphore.  What this
//does is increment the semaphore.  When this is done, the kernal checks
//to see if there are anythings waiting on the semaphore.  When a process
//blocks on a semaphore it is placed in a line (indexed array) so the first
//process in line is awoken to pass through the semaphore.
void ve(){
  int foo;
  int klu;
  messa(vm.ic);
  sema[a].hold++;        //The semaphore is up't
  if(upsemf){                                                  //option for upsem - displayed if toggled by user
    printf("%s%d%s%d%s%d%s%d%s", "Process ", x, " up on sem# ", a, ". Now sem# ", a, " = ", sema[a].hold, ".\n");
  }
  printf("upped sem %d\n",a);
  for(foo = 0;foo < 1000;foo++){                     //If there is some process waiting on a semaphore...
    if (sema[a].semq[foo]  != 1001){
      process_table[sema[a].semq[foo]].after = x;
      process_table[sema[a].semq[foo]].before = process_table[x].before;
      process_table[process_table[x].before].after = sema[a].semq[foo];
      process_table[x].before = sema[a].semq[foo];
      if(process_table[process_table[x].after].after == process_table[x].after){
	process_table[process_table[x].after].after = a;   //The case where there is one process on the queue
      }
      printf("unblocking %d\n",foo);      //...wake the first process in line up
      for(klu = 0;klu < 999;klu++){       //updates the line after the one is pulled out of it.
	sema[a].semq[klu] = sema[a].semq[klu + 1];
      }
      sema[a].semq[999] = 1001;   //These statements clean up the line
      foo = 1000;
      sema[a].qind--;
    }
  }
}

//This function allows a process to set a semaphore to a certain value.  This
//value is stored in R and the semaphore is refered to by x1x2 = a.
void si(){
  messa(vm.ic);
  sema[a].hold = atoi(vm.r);
}

//This function returns the pid of a function into its R register
void gp(){
  sprintf(vm.r,"%.4d",x);
  }

int bmalloc(int mem){
  int hold,stop,count;
  if (nexc == 0){                           //If your counter is zero we move the pointer to the end.
    nexc = 1000;                            //
    stop = 0;
  }
  else{                                     //If the counter isn't zero we want to set the index to the next one
  stop = nexc + 1;
  }
  count = 0;                                
  while((stop != nexc) && (count < mem)){   //While your index isn't equalp to your pointer and you havn't found a spot in mem
    if(stop == 999){                        //if the index is at the end of memory..
      if (bitmas[999] == 0){                  //if your bitmask for 999 is zero we increment the count
	count++;                            //used for next check
	  if(count < mem){                      //now we check to see if the last hole didn't make us fit in memory
	    count = 0;                          //if not we set our counter back to zero
	    stop = -1;                          //and start at the begining of memory
	  }
      	}
      else{                                     //if our bitmask was 1...
        count = 0;                               //we set our state back to the beginging of the array.
        stop = -1;
      }
      if ((count != mem) && (nexc == 1000)){    //if stop was 999 and the process fits into memory
	nexc = 0;                               //nexc is made to be zero (makes sure that next time we come in, we 
	stop = nexc;                            //don't check 1001, and instead check the beginging of the array.
      }
    }
    else{
      if(bitmas[stop] == 1){                    //if you find a 1 clear your counter.
	count = 0;
      }
      if(bitmas[stop] == 0){                    //if you find a zero, count on brother.
	count++;
      }
    }
    stop++;                                     //make sure that the index  goes up so that maybe someday the
  }                                             //the thing will stop.
  if ((stop == nexc) && (count < mem)){         //Same as first fit from here on out.
    fprintf(stderr,"no mem\n");
    return -1;
  }
  stop--;
  count--;
  while(count != -1){ 
    bitmas[stop] = 1;
    stop--;
    count--;
  }
  stop++;
//   for(count = 0;count < 1000;count++){
//    printf("%d",bitmas[count]);
//   }
//   printf("\n");
   nexc = stop;
  return stop;
}

int bmalloc2(int mem){                      // First fit
  int hold,hole,stop,count;
  stop = 0;
  count = 0;
  while((stop != 1000) && (count != mem)){    //While we have not checked all memory...
    if(bitmas[stop] == 1){                    //If we find a 1 clear the count
      count = 0;
    }
    if(bitmas[stop] == 0){                    //if not, continue counting...
      count++;
    }
    stop++;                                   //make sure the index goes up.
  }
  if ((stop == 1000) && (count < mem)){       //if stop hits 1000 and we still don't have enough memory
    fprintf(stderr,"no mem\n");               //print error.
    return -1;                                //return error code
  }
  stop--;                                     //index 0
  count--;
  while(count != -1){                         //start at top and go backwards to zero... (to plug in one's)
    bitmas[stop] = 1;
    stop--;
    count--;
  }
  //printf("\n");
  stop++;
  //for(count = 0;count < 1000;count++){
  //  printf("%d",bitmas[count]);
  // }
  // printf("\n");
  return stop;
}

//This function is given a pid and clears starting at offset of the requested memory size.
void bfree(int pid){
  int count,hold;
  hold = process_table[pid].offset + process_table[pid].mreq;
  count = process_table[pid].offset;
  while(count < hold){
    bitmas[count] = 0;
    count++;
  }
//   for(count = 0;count < 1000;count++){
//     printf("%d",bitmas[count]);
//   }
//   printf("\n");
}

void sp(){
  int memor,i,z,f;
  char bran[82];
  char *offset = wordlist[vm.ic].letter;
  for(f = 0;f < 1000;f++){
    if(process_table[f].run == 0){  //find first process Id that is not running
      process_table[f].run = 1;     //This helps prevent max pid's 
      mmpid = f;                    //We can reuse stopped PIDs with little problem
      f = 1000;                     //This raises a problem with Message passing
      //but anything that was going to pass to the old PID  would have blocked forever anyway
      //therefore it is attributed to poor prgramming and not to the Operating system.
      //as for not running though the entire list of pid before starting to look at the begining again
      //is to organize the PCBs so that you do not get large amounts of fragments in the
    }
  }
  printf("here %d\n",mmpid);
  offset = offset + 2;
  if (mmpid > 999){
    fprintf(stderr,"Max number of processes met cannot spawn process\n"); //In case you don't have a process halt before you hit 1000
  }
  else{
    if ((process_table[mmpid].cfptr=fopen(offset,"r")) == NULL){
      sprintf(process_table[x].R,"0000");
      vm.ic++;
      return;
    }
    fscanf(process_table[mmpid].cfptr,"%s",bran);
    fscanf(process_table[mmpid].cfptr,"%d\n",&allo);
    if(mallocf == 1){
      memor=bmalloc(allo);
    }
    else{
      memor=bmalloc2(allo);
    }
    if (memor == -1){
      sprintf(process_table[x].R,"0000");
      process_table[mmpid].run = 0;
      process_table[mmpid].dirty = 0;
      fclose(process_table[mmpid].cfptr);
      fprintf(stderr,"Memory is full. Process %d not loaded. Was owned by %d\n",mmpid,x);
    }
    else{
      process_table[mmpid].dirty = 1;
      printf("%s\n%d\n",bran,allo);
      if (strcmp(bran,"BRAIN98") == 0){
	z = mmpid;
	process_table[z].mreq = allo;
	while (inputer(process_table[mmpid].cfptr,z,memor) == 0){
	  process_table[z].after = z + 1;
	  z++;
	  process_table[z].before = z - 1;
	}
	process_table[z].before = process_table[x].before;
	process_table[z].after = x;
	process_table[process_table[x].before].after = z;
	process_table[x].before = z;
	process_table[z].IC = memor;
	mmpid = z;
	if(mmpid == 0){
	  sprintf(process_table[x].R,"1000");
	}
	else{
	  sprintf(process_table[x].R,"%.4d",mmpid);
	}
	sprintf(process_table[mmpid].R,"%.4d",x);
      }
    }
  }
  vm.ic++;
  x = sched(x);
}

//This function displays and allows the user to edit the option available to them.
void options(){
  int cval;
  endloop = 1;
  while(endloop){
    printf("%s", "Display Options              Current State\n");
    printf("%s%d%s", "  1> Semaphore Blocks:         ", blsemf, "\n");
    printf("%s%d%s", "  2> Message Blocks:           ", blmsgf, "\n");
    printf("%s%d%s", "  3> Sending Message:          ", sendf, "\n");
    printf("%s%d%s", "  4> Receiving Message:        ", recf, "\n");
    printf("%s%d%s", "  5> Writing to shared Memory: ", accessf, "\n");
    printf("%s%d%s", "  6> Sem ups & sem value:      ", upsemf, "\n");
    printf("%s%d%s", "  7> Sem downs & sem value:    ", dnsemf, "\n");
    printf("%s%d%s", "  8> FirstFit = 0 NextFit = 1: ", mallocf, "\n");
    printf("%s", "\n  9> Done\n");
    printf("%s", "Enter Choice>");
    scanf ("%d", &cval);
    switch (cval){
    case 1:
      if(blsemf == 0){
        blsemf = 1;
      }
      else{
        blsemf = 0;
      }
      break;
    case 2:
      if(blmsgf == 0){
        blmsgf = 1;
      }
      else{
        blmsgf = 0;
      }
      break;
    case 3:
      if(sendf == 0){
        sendf = 1;
      }
      else{
        sendf = 0;
      }
      break;
    case 4: 
      if(recf == 0){
        recf = 1;
      }
      else{
        recf = 0;
      }
      break;
    case 5:
      if(accessf == 0){
        accessf = 1;
      }
      else{
        accessf = 0;
      }
      break;
    case 6:
      if(upsemf == 0){
        upsemf = 1;
      }
      else{
        upsemf = 0;
      }
      break;
    case 7:
      if(dnsemf == 0){
        dnsemf = 1;
      }
      else{
        dnsemf = 0;
      }
      break;
    case 8:
      if(mallocf == 0){
        mallocf = 1;
      }
      else{
        mallocf = 0;
      }
      break;
    case 9:
      endloop = 0;
      break;
    default:
      printf("%s", "*Invalid Choice*\n");
    }
  }
}

//This is the main interface of our BRAIN98 program.  It gives the user the choice
//of running in Normal Mode (no step by step processing) or in Debugging mode.  An
//Options menu also exists that allows the user to toggle messages to appear during
//certain events as well as options on how brain runs (ex. First or Next fit).
void BMode(){
  int optmode;
  optmode = 3;
  while (optmode == 3){
    printf("%s", "Choose Mode:\n");
    printf("%s", "  1> Normal Mode\n");
    printf("%s", "  2> Debug Mode\n\n");
    printf("%s", "  3> OPTIONS\n");
    printf("%s", "  4> QUIT\n");
    printf("%s", "Enter Choice>");
    scanf("%d", &optmode);
    switch(optmode){
      case 1:
	break;
      case 2:
        debugf = 1;
	break;
      case 3:
        options();
        break;
      case 4:
        exit(1);
        break;
    }
  }
}

//This function is the main part of our debugger.  This function displays to the screen the
//state of the virtual processor's registers, what process is running, the next process to
//run, the base address of the process, and the next operation that is prepared to be done
//at that IC number.  From here the user can choose to continue on stepping through the
//program or they can choose other options.  These options include displaying memory, displaying
//the bitmap, displaying the process queue, skipping steps, quiting, and viewing the help screen.
//If the user gives an invalid command an error message is displayed and they are returned to
//the main debugger screen.
void DBug(){
  char dopt;          //stores the option character
  dopt = 'x';         //defaults it as an unused character so the while loop is not skipped
  if (skipcount == 0){
    while((dopt != 'n') && (dopt != 's')){                                 //while the user has not chosen to move on...
      printf("\nNext> %s\n", wordlist[vm.ic].letter);   //the display is printed...
      printf("%s%s%s%d%s%d", "R:", vm.r, " C:", vm.c, " IC:", vm.ic);
      printf("%s%d%s%d", "     PID:", process_table[x].pid, " NextPID:", process_table[process_table[x].after].pid);
      printf("%s%d%s%d%s", " Timer:", vm.timer, " BaseAddress:", process_table[x].offset, "\n");
      printf("%s", "n,m,p,b,s,q,h> ");
      scanf("\n%c", &dopt);                             //...and the user is promted for a command.
      switch(dopt){
        case 'n':                                       // n will proceed to the next step
          break;
        case 'h':                                       // h will display what each command does
          dhelp();
          break;
        case 'm':                                       // m will run the memory display function
          dmem(); 
          break;
        case 'p':                                       // p will run the process queue display funtion
          dispQ();
          break;
        case 'b':                                       // b will run the bitmap display program
          showBM();
          break;
        case 'q':                                       // q will cause the whole session to end
          exit(1);
          break;
        case 's':                                       // s allows the user to skip a specified number of steps
          skipit();                                     
          break;
        default:
          printf("%s", "ERROR: NOT AN OPTION\n");       // otherwise an error is displayed and the user is
      }
    }                                                 // returned to the debugger screen.
  }
  else{
    skipcount--;
  }
}

//This function is called by the debugger when the user requests to see the help screen.  It
//prints to the screen all the commands that are available to them in debug mode.
void dhelp(){
  printf("%s", "\nHelp:\n  n - Next Command\n  m - Display Memory\n  p - Display Process Queue\n");
  printf("%s", "  s - Skip Commands\n  b - Display Bitmap\n  q - Quit\n  h - hmmm... let's see...\n");
}

//This function displays a specified portion of memory to the screen.  When the user prompts the
//debugger for a memory display the function asks the user for a starting position and then a
//end postion.  The debugger than displays that portion of memory from the first number rounded
//to the nearest tens place and to the next number which is also rounded.  Ex.  If the requested
//portion of memory is 34 to 121 it will display from 30 to 129.  If the first number given is 
//less than the second value, the values are swapped.  If a value is given that is beyond the
//domain of memory, an error is displayed and nothing is displayed.
void dmem(){
  int mfrom, mto, count;          //mfrom is the starting position and mto is the end position.
  printf("%s", "FROM: ");         //Requests the start position...
  scanf("\n%d", &mfrom);           //and stores it in mfrom.
  printf("%s", "TO: ");           //Requests the end position...
  scanf("\n%d", &mto);             //and stores it in mto.
  if( (mfrom >= 0) && (mfrom <= 999) && (mto >= 0) && (mto <= 999) ){  //Checks to see if values are valid.
    if (mfrom > mto){        //if they are valid, we first check to see if the start value is
      count = mfrom;         //is larger than the end value.  If it is we reverse the values.
      mfrom = mto;           //Count is used as the temp because we havn't needed to use it yet.
      mto = count;           //This made more sense than returning an error message. 
    }
    mfrom = ((mfrom / 10) * 10);   //Next the first number is rounded to the nearest ten.
    mto = ((mto / 10) * 10) + 10;  //Next the second is rounded.
    printf("%s", "      0    1    2    3    4    5    6    7    8    9\n");  //this is the top index.
    printf("%d%s", mfrom, "   ");   //this is the start of the left index
    count = 0;
    for(mfrom; mfrom != mto; mfrom++){
      if(count == 10){                         //after ten locations are displayed, we start a
	printf("%s%d%s","\n", mfrom, "   ");   //new line and label the index of that line.
	count = 0;                             //The count is then restarted.
      }
      count++;                                 //Incrementst he count for every mem location
      printf("%s%s", wordlist[mfrom].letter, " "); //displayed.
    }
  }
  else{
    printf("INCORRECT INPUT VALUES\n");         //If the values given were invalid, an error
  }                                               //message is displayed.
}

//This function displays the bitmap used in memory allocation to the screen.  Each line
//contains 100 of the bits spaced into ten bit segments.  This function is called by the
//debug user by enter 'b' as the next command.
void showBM(){                            
  int count;                //Keeps track of what bit is being displayed
  int nl, spc, ind;         //These are used in formatting the bitmap to be displayed
  nl = 0;                   
  spc = 0;
  ind = 100;                //Each line is indexed in 100 intervals
  printf("000  ");          //prints the initial index of 000.
  for(count = 0; count < 1000; count++){    //reads every bit
    if (spc == 10){                    //if ten bits have been printed, print a space
      printf(" ");
      spc = 0;
    }
    if (nl == 100){                    //if 100 bits have been printed, print a new line
      printf("\n%d  ", ind);
      nl = 0;
      ind = ind + 100;
    }
    printf("%d",bitmas[count]);        //print the bit itself to the screen
    nl++;    //update counters
    spc++;
  }
  printf("\n");           //when we are done print a new line before going back
}                         //to the debugger.

//This function allows the debugger to skip a number of commands specified by the user.
//It does this by setting skipcount to the value specified by the user.  While skipcount
//is greater than zero, the debugger is passed over while the processes run.
void skipit(){
  printf("How Many> ");
  scanf("\n%d", &skipcount);
  skipcount--;
  printf("\n");
}

//This function displays the process queue to the screen.  It does so by moving through
//the linked list that is our process queue and prints out the pids of those processes
//waiting.
void dispQ(){
  int last;                      //Pid of the last process checked on the queue.
  last = process_table[x].after;
  printf("\nProcess Queue:\nCurrently running( %d )", x);
  while (last != x){                                      //Runs until we get back to the
    printf(" <- %d", last);                               //currently running process.
    last = process_table[last].after;
  }
  printf("\n");
}

















