CS-PROJECTS / c02_assembler / test / grading.tar
grading.tar
Raw
ASMParser.c0000600006173000234230000004075414237033174013013 0ustar  jordanha23Others#include "ASMParser.h"
#include "SymbolTable.h"

// On my honor:
//
// - I have not discussed the C language code in my program with
// anyone other than my instructor or the teaching assistants
// assigned to this course.
//
// - I have not used C language code obtained from another student,
// the Internet, or any other unauthorized source, either modified
// or unmodified.
//
// - If any C language code or documentation used in my program
// was obtained from an authorized source, such as a text book or
// course notes, that has been clearly noted with a proper citation
// in the comments of my program.
//
// - I have not designed this program in such a way as to defeat or
// interfere with the normal operation of the grading code.
//
// <Jordan Harrington>
// <jordanha23>

/***  Add include directives for here as needed.  ***/
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

static struct
{
   char *mnem;
   char *address;
} registers[] = {
    {"$at", "00001"},
    {"$a0", "00100"},
    {"$a1", "00101"},
    {"$a2", "00110"},
    {"$a3", "00111"},
    {"$t0", "01000"},
    {"$t1", "01001"},
    {"$t2", "01010"},
    {"$t3", "01011"},
    {"$t4", "01100"},
    {"$t5", "01101"},
    {"$t6", "01110"},
    {"$t7", "01111"},
    {"$t8", "11000"},
    {"$t9", "11001"},
    {"$s0", "10000"},
    {"$s1", "10001"},
    {"$s2", "10010"},
    {"$s3", "10011"},
    {"$s4", "10100"},
    {"$s5", "10101"},
    {"$s6", "10110"},
    {"$s7", "10111"},
    {"$v0", "00010"},
    {"$v1", "00011"},
    {"$zero", "00000"},
    {"$k0", "11010"},
    {"$k1", "11011"},
    {NULL, 0}};

static struct
{
   char *mnem;
   char *opCode;
} op[] = {
    {"lw", "100011"},
    {"sub", "000000"},
    {"add", "000000"},
    {"nor", "000000"},
    {"mult", "000000"},
    {"syscall", "000000"},
    {"mul", "011100"},
    {"slti", "001010"},
    {"lui", "001111"},
    {"addi", "001000"},
    {"la", "001000"},
    {"beq", "000100"},
    {"bne", "000101"},
    {"sw", "101011"},
    {"nop", "000000"},
    {"sll", "000000"},
    {"sra", "000000"},
    {"srav", "000000"},
    {"slt", "000000"},
    {"blt", "101010"},
    {"j", "000010"},
    {"addu", "000000"},
    {"move", "000000"},
    {"addiu", "001001"},
    {"li", "001001"},
    {"blez", "000110"},
    {"bgtz", "000111"},
    {NULL, 0}};

static struct
{
   char *mnem;
   char *funcCode;
} func[] = {
    {"sub", "100010"},
    {"slt", "101010"},
    {"addu", "100001"},
    {"move", "100001"},
    {"sra", "000011"},
    {"srav", "000111"},
    {"add", "100000"},
    {"mult", "011000"},
    {"nor", "100111"},
    {"mul", "000010"},
    {"syscall", "001100"},
    {"sll", "000000"},
    {"nop", "000000"},
    {NULL, 0}};

static struct
{
   char *mnem;
   char *mType;
} type[] = {
    {"sub", "r"},
    {"nor", "r"},
    {"add", "r"},
    {"syscall", "r"},
    {"mul", "r"},
    {"mult", "s"},
    {"lw", "i"},
    {"lui", "i"},
    {"addi", "i"},
    {"slti", "i"},
    {"la", "i"},
    {"beq", "i"},
    {"bne", "i"},
    {"sw", "i"},
    {"nop", "r"},
    {"sll", "r"},
    {"sra", "r"},
    {"srav", "r"},
    {"slt", "r"},
    {"blt", "r"},
    {"j", "ju"},
    {"addu", "r"},
    {"move", "r"},
    {"addiu", "i"},
    {"li", "i"},
    {"blez", "i"},
    {"bgtz", "i"},
    {NULL, 0}};

#define REG_LENGTH 4
#define OP_FUNC_CODE_LENGTH 7
#define REG_ADD_LENGTH 6
#define TARGET_LENGTH 27

static bool blt = false;

char *findReg(char *inp);
char *findFunc(char *inp);
char *findOp(char *inp);
char *findType(char *inp);
uint8_t binaryToDec(char *addy);
uint16_t findInstructionNum(char *word);
uint16_t findImm(char *word);
char *unDecToBinary(char *word);

ParseResult *parseASM(const char *const pASM, uint16_t instructionNumber)
{
   // Create ParseResult
   ParseResult *res = calloc(1, sizeof(ParseResult));
   res->ASMInstruction = calloc(strlen(pASM) + 1, sizeof(char));
   strcpy(res->ASMInstruction, pASM);

   res->rd = 0;
   res->rs = 0;
   res->rt = 0;

   char *line = calloc(strlen(pASM) + 1, sizeof(char)),
        *str[4];
   strcpy(line, pASM);

   // Grabs arguments
   int i = 0;
   str[i] = strtok(line, " ,\t");
   while (str[i++])
      str[i] = strtok(NULL, " ,\t");

   // Sets mnemonic for type checking
   res->Mnemonic = calloc(strlen(str[0]) + 1, sizeof(char));
   strcpy(res->Mnemonic, (blt) ? "bne" : str[0]);


   // Allocates fields of ParseResult based on instruction type
   if (!strcmp(findType(res->Mnemonic), "ju"))
      res->Opcode = calloc(OP_FUNC_CODE_LENGTH, sizeof(char));
   else if (!strcmp(findType(res->Mnemonic), "i"))
   {
      res->RT = calloc(REG_ADD_LENGTH, sizeof(char));
      res->RS = calloc(REG_ADD_LENGTH, sizeof(char));
      res->Opcode = calloc(OP_FUNC_CODE_LENGTH, sizeof(char));
      res->rtName = calloc(REG_LENGTH, sizeof(char));
      res->rsName = calloc(REG_LENGTH, sizeof(char));
      res->IMM = calloc(IMM_LENGTH, sizeof(char));
   }
   else if (!strcmp(findType(res->Mnemonic), "r"))
   {
      res->rtName = calloc(REG_LENGTH, sizeof(char));
      res->rsName = calloc(REG_LENGTH, sizeof(char));
      res->rdName = calloc(REG_LENGTH, sizeof(char));
      res->Funct = calloc(OP_FUNC_CODE_LENGTH, sizeof(char));
      res->Opcode = calloc(OP_FUNC_CODE_LENGTH, sizeof(char));
      res->RT = calloc(REG_ADD_LENGTH, sizeof(char));
      res->RS = calloc(REG_ADD_LENGTH, sizeof(char));
      res->RD = calloc(REG_ADD_LENGTH, sizeof(char));
      res->shamt = calloc(REG_ADD_LENGTH, sizeof(char));
   }
   else if (!strcmp(findType(res->Mnemonic), "s"))
   {
      res->rtName = calloc(REG_LENGTH, sizeof(char));
      res->rsName = calloc(REG_LENGTH, sizeof(char));
      res->RT = calloc(REG_ADD_LENGTH, sizeof(char));
      res->RS = calloc(REG_ADD_LENGTH, sizeof(char));
      res->RD = calloc(REG_ADD_LENGTH, sizeof(char));
      res->Funct = calloc(OP_FUNC_CODE_LENGTH, sizeof(char));
      res->Opcode = calloc(OP_FUNC_CODE_LENGTH, sizeof(char));
   }

   // R-type

   if (!strcmp(res->Mnemonic, "mul") || !strcmp(str[0], "sub") ||
       !strcmp(str[0], "add") || !strcmp(str[0], "nor") ||
       !strcmp(str[0], "slt") || !strcmp(str[0], "addu"))
   {
      strcpy(res->rdName, str[1]);
      strcpy(res->rsName, str[2]);
      strcpy(res->rtName, str[3]);
      strcpy(res->shamt, "00000");

      strcpy(res->RD, findReg(str[1]));
      strcpy(res->RS, findReg(str[2]));
      strcpy(res->RT, findReg(str[3]));

      strcpy(res->Funct, findFunc(str[0]));
      strcpy(res->Opcode, findOp(str[0]));

      res->rd = binaryToDec(res->RD);
      res->rs = binaryToDec(res->RS);
      res->rt = binaryToDec(res->RT);
   }

   else if (!strcmp(res->Mnemonic, "sll") || !strcmp(res->Mnemonic, "sra"))
   {
      strcpy(res->rdName, str[1]);
      strcpy(res->rtName, str[2]);

      strncpy(res->shamt, &decToBinary(str[3])[11], 6);

      strcpy(res->RD, findReg(str[1]));
      strcpy(res->RT, findReg(str[2]));
      strcpy(res->RS, "00000");

      strcpy(res->Funct, findFunc(str[0]));
      strcpy(res->Opcode, findOp(str[0]));

      res->rd = binaryToDec(res->RD);
      res->rt = binaryToDec(res->RT);
   }

   else if (!strcmp(res->Mnemonic, "move"))
   {
      strcpy(res->rdName, str[1]);
      strcpy(res->rtName, str[2]);
      strcpy(res->shamt, "00000");

      strcpy(res->RD, findReg(str[1]));
      strcpy(res->RT, findReg(str[2]));
      strcpy(res->RS, findReg("$zero"));

      strcpy(res->Funct, findFunc(str[0]));
      strcpy(res->Opcode, findOp(str[0]));

      res->rd = binaryToDec(res->RD);
      res->rs = binaryToDec(res->RS);
      res->rt = binaryToDec(res->RT);
   }

   else if (!strcmp(res->Mnemonic, "srav"))
   {
      strcpy(res->rdName, str[1]);
      strcpy(res->rsName, str[3]);
      strcpy(res->rtName, str[2]);
      strcpy(res->shamt, "00000");

      strcpy(res->RD, findReg(str[1]));
      strcpy(res->RS, findReg(str[3]));
      strcpy(res->RT, findReg(str[2]));

      strcpy(res->Funct, findFunc(str[0]));
      strcpy(res->Opcode, findOp(str[0]));

      res->rd = binaryToDec(res->RD);
      res->rs = binaryToDec(res->RS);
      res->rt = binaryToDec(res->RT);
   }

   else if (!strcmp(res->Mnemonic, "syscall"))
   {
      strcpy(res->RD, "00000");
      strcpy(res->RS, "00000");
      strcpy(res->RT, "00000");
      strcpy(res->shamt, "00000");
      strcpy(res->Funct, findFunc(str[0]));
      strcpy(res->Opcode, findOp(str[0]));
   }

   else if (!strcmp(res->Mnemonic, "nop"))
   {
      strcpy(res->shamt, "00000");

      strcpy(res->RD, findReg("$zero"));
      strcpy(res->RT, findReg("$zero"));
      strcpy(res->RS, "00000");

      strcpy(res->Funct, findFunc(str[0]));
      strcpy(res->Opcode, findOp(str[0]));

      res->rd = binaryToDec(res->RD);
      res->rt = binaryToDec(res->RT);
   }

   else if (!strcmp(res->Mnemonic, "blt"))
   {
      strcpy(res->rdName, "$at");
      strcpy(res->rsName, str[1]);
      strcpy(res->rtName, str[2]);
      strcpy(res->shamt, "00000");
      strcpy(res->RD, findReg("$at"));
      strcpy(res->RS, findReg(str[1]));
      strcpy(res->RT, findReg(str[2]));
      strcpy(res->Funct, findFunc("slt"));
      strcpy(res->Opcode, findOp("slt"));

      res->rd = binaryToDec(res->RD);
      res->rs = binaryToDec(res->RS);
      res->rt = binaryToDec(res->RT);

      blt = true;
   }

   // I-type

   else if (!strcmp(res->Mnemonic, "blez") || !strcmp(res->Mnemonic, "bgtz"))
   {
      strcpy(res->rsName, str[1]);
      strcpy(res->RS, findReg(str[1]));
      strcpy(res->RT, findReg("$zero"));
      strcpy(res->Opcode, findOp(str[0]));

      res->rs = binaryToDec(res->RS);
      res->rt = binaryToDec(res->RT);

      int16_t symbolInstructNum = findInstructionNum(str[2]);
      int16_t i = (symbolInstructNum - instructionNumber) - 1;

      char *imm = calloc(TARGET_LENGTH, sizeof(char));
      snprintf(imm, sizeof(char *), "%d", i);
      char *bin = decToBinary(imm);
      strcpy(res->IMM, bin);

      free(bin);
      free(imm);

      res->Imm = i;
   }

   else if (!strcmp(res->Mnemonic, "bne") || !strcmp(res->Mnemonic, "beq"))
   {

      if (blt)
      {
         strcpy(res->rsName, "$at");
         strcpy(res->RS, findReg("$at"));
         strcpy(res->RT, findReg("$zero"));
         strcpy(res->Opcode, findOp("bne"));

         res->rs = binaryToDec(res->RS);
         res->rt = binaryToDec(res->RT);

         int16_t symbolInstructNum = findInstructionNum(str[3]);
         int16_t i = (symbolInstructNum - instructionNumber);

         if (i < 0)
            i--;

         char *imm = calloc(TARGET_LENGTH, sizeof(char));
         snprintf(imm, sizeof(char *), "%d", i);
         char *bin = decToBinary(imm);
         strcpy(res->IMM, bin);

         free(bin);
         free(imm);

         res->Imm = i;

         blt = false;
      }
      else
      {
         strcpy(res->rsName, str[1]);
         strcpy(res->rtName, str[2]);
         strcpy(res->RS, findReg(str[1]));
         strcpy(res->RT, findReg(str[2]));
         strcpy(res->Opcode, findOp(str[0]));

         res->rs = binaryToDec(res->RS);
         res->rt = binaryToDec(res->RT);

         int16_t symbolInstructNum = findInstructionNum(str[3]);
         int16_t i = (symbolInstructNum - instructionNumber) - 1;

         char *imm = calloc(TARGET_LENGTH, sizeof(char));
         snprintf(imm, sizeof(char *), "%d", i);

         char *bin = decToBinary(imm);
         strcpy(res->IMM, bin);

         free(bin);
         free(imm);

         res->Imm = i;
      }
   }

   else if (!strcmp(res->Mnemonic, "li"))
   {
      strcpy(res->rtName, str[1]);
      strcpy(res->RT, findReg(str[1]));
      strcpy(res->RS, findReg("$zero"));
      strcpy(res->Opcode, findOp(str[0]));

      res->rs = binaryToDec(res->RS);
      res->rt = binaryToDec(res->RT);

      char *bin = unDecToBinary(str[2]);

      strcpy(res->IMM, bin);
      free(bin);

      res->Imm = strtoul(str[2], NULL, 10);

      res->rs = binaryToDec(res->RS);
      res->rt = binaryToDec(res->RT);
   }

   else if (!strcmp(res->Mnemonic, "la"))
   {
      strcpy(res->rtName, str[1]);
      strcpy(res->RT, findReg(str[1]));
      strcpy(res->RS, findReg("$zero"));
      strcpy(res->Opcode, findOp(str[0]));

      res->rs = binaryToDec(res->RS);
      res->rt = binaryToDec(res->RT);

      uint16_t i = findImm(str[2]);

      char *imm = calloc(TARGET_LENGTH, sizeof(char));
      snprintf(imm, sizeof(char *), "%d", i);

      char *bin = decToBinary(imm);
      strcpy(res->IMM, bin);

      free(bin);
      free(imm);

      res->Imm = i;
   }

   else if (!strcmp(res->Mnemonic, "addi") || !strcmp(res->Mnemonic, "slti") ||
            !strcmp(res->Mnemonic, "addiu"))
   {
      strcpy(res->rtName, str[1]);
      strcpy(res->rsName, str[2]);
      strcpy(res->RT, findReg(str[1]));
      strcpy(res->RS, findReg(str[2]));
      strcpy(res->Opcode, findOp(str[0]));

      char *bin;
      if (!strcmp(res->Mnemonic, "addiu"))
         bin = unDecToBinary(str[3]);
      else
         bin = decToBinary(str[3]);

      strcpy(res->IMM, bin);
      free(bin);

      if (!strcmp(res->Mnemonic, "addiu"))
         res->Imm = strtoul(str[3], NULL, 10);
      else
         res->Imm = atol(str[3]);

      res->rs = binaryToDec(res->RS);
      res->rt = binaryToDec(res->RT);
   }

   else if (!strcmp(res->Mnemonic, "lw") || !strcmp(res->Mnemonic, "sw"))
   {
      uint16_t x = 0;
      bool lwLabel = false;
      char *trash = calloc(1, sizeof(char)),
           offset[50], regi[4];

      if (!strcmp(res->Mnemonic, "lw"))
         if ((x = findImm(str[2])) != 0)
            lwLabel = true;

      if (!lwLabel)
      {
         sscanf(str[2], " %[^(]%c %[^)]", offset, trash, regi);

         strcpy(res->rtName, str[1]);
         strcpy(res->rsName, regi);
         strcpy(res->RT, findReg(str[1]));
         strcpy(res->RS, findReg(regi));
         strcpy(res->Opcode, findOp(str[0]));

         char *bin = decToBinary(offset);
         strcpy(res->IMM, bin);
         free(bin);

         res->Imm = atol(offset);
         res->rs = binaryToDec(res->RS);
         res->rt = binaryToDec(res->RT);

         free(trash);
      }
      else
      {
         strcpy(res->rtName, str[1]);
         strcpy(res->RT, findReg(str[1]));
         strcpy(res->Opcode, findOp(str[0]));
         strcpy(res->RS, findReg("$zero"));

         char *imm = calloc(TARGET_LENGTH, sizeof(char));
         snprintf(imm, sizeof(char *), "%d", x);
         char *bin = decToBinary(imm);
         strcpy(res->IMM, bin);

         free(bin);
         free(imm);

         res->Imm = x;
      }
   }

   else if (!strcmp(res->Mnemonic, "lui"))
   {
      strcpy(res->rtName, str[1]);
      strcpy(res->RT, findReg(str[1]));
      strcpy(res->Opcode, findOp(str[0]));
      strcpy(res->RS, "00000");

      free(res->rsName);
      res->rsName = NULL;

      char *bin = decToBinary(str[2]);
      strcpy(res->IMM, bin);
      free(bin);

      res->Imm = atol(str[2]);
      res->rt = binaryToDec(res->RT);
   }

   // S-type

   else if (!strcmp(res->Mnemonic, "mult"))
   {
      strcpy(res->rsName, str[1]);
      strcpy(res->rtName, str[2]);
      strcpy(res->RS, findReg(str[1]));
      strcpy(res->RT, findReg(str[2]));
      strcpy(res->Funct, findFunc(str[0]));
      strcpy(res->Opcode, findOp(str[0]));
      strcpy(res->RD, "00000");

      res->rs = binaryToDec(res->RS);
      res->rt = binaryToDec(res->RT);
   }

   // J-type

   else if (!strcmp(res->Mnemonic, "j"))
   {
      strcpy(res->Opcode, findOp(str[0]));

      int16_t symbolInstructNum = findInstructionNum(str[1]);
      if (symbolInstructNum)
         symbolInstructNum--;

      char *imm = calloc(1, sizeof(char));
      snprintf(imm, sizeof(char *), "%d", symbolInstructNum);
      char *bin = decToBinary26(imm);
      res->Target = bin;

      free(imm);
   }

   free(line);

   return res;
}

uint8_t binaryToDec(char *addy)
{
   int dec = 0;
   while (*addy)
   {
      dec *= 2;
      if (*addy == '1')
         dec++;
      addy++;
   }
   return dec;
}

char *findReg(char *inp)
{
   int i = -1;
   while (registers[++i].mnem)
      if (!strcmp(inp, registers[i].mnem))
         return registers[i].address;
   return NULL;
}

char *findFunc(char *inp)
{
   int i = -1;
   while (func[++i].mnem)
      if (!strcmp(inp, func[i].mnem))
         return func[i].funcCode;
   return NULL;
}

char *findType(char *inp)
{
   int i = -1;
   while (type[++i].mnem)
      if (!strcmp(inp, type[i].mnem))
         return type[i].mType;
   return NULL;
}

char *findOp(char *inp)
{
   int i = -1;
   while (op[++i].mnem)
      if (!strcmp(inp, op[i].mnem))
         return op[i].opCode;
   return NULL;
}

uint16_t findInstructionNum(char *word)
{
   int i = -1;
   while (textSymbols[++i].key)
      if (!strcmp(word, textSymbols[i].key))
         return textSymbols[i].instructionNum;
   return 0;
}
DATAParser.c0000600006173000234230000000577214237031432013100 0ustar  jordanha23Others#include "DATAParser.h"
#include "SymbolTable.h"

#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#define MAX_LINE_LENGTH 257
#define LINE_LENGTH 34
#define IMM_LENGTH 17

char *stringToBinary(char *text);
char *decToBinary32(char *dec);

/**  Breaks up given MIPS32 assembly instruction and creates a proper
 *   char* storing the machine code for data output.
 *
 *   Pre:  pASM points to an array holding the bits (as chars) of variables
 *         defined within the program
 *
 *   Returns:
 *         A pointer to a proper char* representation of binary machine code
 */
void parseDATA(char pDATA[], int count)
{

  char *binary = calloc((MAX_LINE_LENGTH * 2), sizeof(char)),
       *name = calloc(MAX_LINE_LENGTH, sizeof(char)),
       value[MAX_LINE_LENGTH],
       type[8];

  sscanf(pDATA, "%s %s %s", name, type, value);
  free(name);

  dataSymbols[count].type = calloc(MAX_LINE_LENGTH, sizeof(char));
  strcpy(dataSymbols[count].type, type);

  if (!strcmp(type, ".asciiz"))
  {
    char *text = strchr(pDATA, '"'),
         *bin = stringToBinary(text);
    strcpy(binary, bin);
    free(bin);
  }

  if (!strcmp(type, ".word"))
  {
    char *colon = strstr(value, ":"),
         *comma = strstr(value, ",");

    if (colon)
    {
      char *v = strtok(value, ":"),
           *s = strtok(NULL, ":"),
           *bin = decToBinary32(v);
      v[strcspn(v, "\n")] = 0;

      int size = atoi(s) - 1, i = 0;

      strcpy(binary, decToBinary32(value));
      strcat(binary, "\n");

      while (i++ < size)
        strcat(binary, bin),
            strcat(binary, "\n");

      free(bin);
    }
    else if (comma)
    {
      char *tok = strtok(pDATA, " ,\t");
      int ignore = 0;

      while (tok != NULL)
      {
        if (ignore++ < 2)
          tok = strtok(NULL, " ,\t");
        else
        {
          tok[strcspn(tok, ",")] = 0;
          tok[strcspn(tok, "\n")] = 0;

          char *bin = decToBinary32(tok);
          strcat(binary, bin);
          strcat(binary, "\n");
          free(bin);

          tok = strtok(NULL, " ,\t");
        }
      }

      free(tok);
    }
    else
    {
      char *bin = decToBinary32(value);
      strcpy(binary, bin);
      strcat(binary, "\n");
      free(bin);
    }
  }

  dataSymbols[count].binary = binary;
}

char *stringToBinary(char *text)
{
  if (!text)
    return NULL;

  char *binary = calloc(MAX_LINE_LENGTH * 8, sizeof(char));
  binary[0] = '\0';

  int count = 0;

  for (size_t i = 0; i < strlen(text) + 1; i++)
  {
    if (text[i] == '"' || text[i] == '\n')
      continue;

    for (int j = 7; j >= 0; --j)
      strcat(binary, (text[i] & (1 << j)) ? "1" : "0");
      
    if (!(count = !((count + 1) % 4) ? 0 : count + 1))
      strcat(binary, "\n");
  }

  return binary;
}

char *decToBinary32(char *dec)
{
  int32_t n = atoi(dec), i = 0, s = 31;
  char *binaryNum = calloc(33, sizeof(char));
  while (s >= 0)
    binaryNum[i++] = ((n >> s--) & 1) ? '1' : '0';
  return binaryNum;
}
Parser.c0000600006173000234230000002073014237034155012442 0ustar  jordanha23Others#include "ASMParser.h"
#include "ParseResult.h"
#include "DATAParser.h"
#include "SymbolTable.h"

#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#define MAX_LINE_LENGTH 257

void getTextSymbols(FILE *readF, uint16_t currOffset);
void getDataSymbols(FILE *readF, uint16_t currOffset);

int main(int args, char *files[])
{
    if (args > 2)
    {
        // Reads in input file and create output file
        FILE *readF = fopen(files[1], "r");
        FILE *outF = fopen(files[2], "w");

        // Checks for input file
        if (!readF)
            printf("Error:  unable to create %s\n", files[1]);
        else
        {
            char *line = calloc(MAX_LINE_LENGTH, sizeof(char)),
                 *dataSection = NULL;

            bool data = false,
                 text = false,
                 table = false;

            int instructionNum = 0;

            while (fgets(line, MAX_LINE_LENGTH - 1, readF))
            {
                char lineCopy[MAX_LINE_LENGTH + 1];
                strcpy(lineCopy, line);

                char instruction[MAX_LINE_LENGTH + 1];
                strcpy(instruction, strtok(lineCopy, " ,\t"));
                instruction[strcspn(instruction, "\n")] = 0;

                char *type = findType(instruction);

                if (strcmp(instruction, "#") != 0 && strcmp(instruction, " ") != 0)
                {
                    if (table)
                    {
                        free(type);
                        free(line);
                        fclose(outF);
                        fclose(readF);
                        return 0;
                    }

                    if (!strcmp(instruction, ".data"))
                    {
                        data = true;
                        getDataSymbols(readF, ftell(readF));
                        continue;
                    }

                    if (!strcmp(instruction, ".text"))
                    {
                        text = true;
                        getTextSymbols(readF, ftell(readF));
                        if ((table = (args == 4)))
                            makeTable(outF);
                        continue;
                    }

                    if (data)
                    {
                        int i = 0, x = 0, length = 0;

                        while (dataSymbols[x].binary)
                            length += strlen(dataSymbols[x++].binary) + 1;

                        dataSection = calloc(length * 2, sizeof(char));
                        strcpy(dataSection, dataSymbols[0].binary);

                        while (dataSymbols[++i].binary)
                        {
                            int prevLength = strlen(dataSymbols[i - 1].binary);
                            char *prevType = dataSymbols[i - 1].type,
                                 *currType = dataSymbols[i].type;

                            if (!strcmp(prevType, ".asciiz") && !strcmp(currType, ".word"))
                            {
                                int length = (prevLength < 33) ? prevLength : prevLength % 33,
                                    num_zero = 32 - length, x = 0;
                                if (prevLength != 33)
                                {
                                    while (x++ < num_zero)
                                        strcat(dataSection, "0");
                                    strcat(dataSection, "\n");
                                }
                            }

                            strcat(dataSection, dataSymbols[i].binary);

                            if ((prevLength + strlen(dataSymbols[i].binary)) % 33 == 32)
                                strcat(dataSection, "\n");
                        }

                        int dataLen = strlen(dataSection), remainder, j = 0;
                        
                        if ((remainder = (dataLen % 33)) != 0)
                        {
                            while (j++ < (32 - (dataLen % 33)))
                                strcat(dataSection, "0");
                            strcat(dataSection, "\n");
                        }

                        data = false;
                        continue;
                    }

                    if (text)
                    {
                        if (type)
                        {
                            line[strcspn(line, "\n")] = 0;
                            char *bltCopy;

                            if (!strcmp(instruction, "blt"))
                            {
                                bltCopy = calloc(MAX_LINE_LENGTH + 1, sizeof(char));
                                strcpy(bltCopy, line);
                            }

                            ParseResult *asmI = parseASM(line, ++instructionNum);

                            if (!strcmp(type, "r"))
                                fprintf(outF, "%s%s%s%s%s%s\n", asmI->Opcode, asmI->RS, asmI->RT,
                                        asmI->RD, asmI->shamt, asmI->Funct);

                            if (!strcmp(type, "i"))
                                fprintf(outF, "%s%s%s%s\n", asmI->Opcode, asmI->RS, asmI->RT, asmI->IMM);

                            if (!strcmp(type, "s"))
                                fprintf(outF, "%s%s%s%s%s%s\n", asmI->Opcode, asmI->RS, asmI->RT, asmI->RD,
                                        asmI->RD, asmI->Funct);

                            if (!strcmp(type, "ju"))
                                fprintf(outF, "%s%s\n", asmI->Opcode, asmI->Target);

                            if (!strcmp(asmI->Mnemonic, "blt"))
                            {
                                ParseResult *bltAsmi = parseASM(bltCopy, ++instructionNum);
                                fprintf(outF, "%s%s%s%s\n", bltAsmi->Opcode, bltAsmi->RS, bltAsmi->RT, bltAsmi->IMM);

                                free(bltAsmi);
                                free(bltCopy);
                            }

                            clearResult(asmI);
                            free(asmI);
                        }

                        continue;
                    }
                }
            }

            fprintf(outF, "\n%s", dataSection);

            free(line);
            free(dataSection);

            fclose(outF);
            fclose(readF);
        }

        cleanTable();
    }

    return 0;
}

void getDataSymbols(FILE *readF, uint16_t currOffset)
{
    fseek(readF, currOffset, SEEK_SET);
    char *line = calloc(MAX_LINE_LENGTH, sizeof(char));
    int count = 0, address = 8192;

    while (fgets(line, MAX_LINE_LENGTH - 1, readF))
    {
        char lineCopyData[MAX_LINE_LENGTH + 1];
        strcpy(lineCopyData, line);

        strcpy(dataSymbols[count].key, strtok(line, " ,\t"));
        dataSymbols[count].key[strcspn(dataSymbols[count].key, "\n")] = 0;

        if (!strcmp(dataSymbols[count].key, ".text"))
            break;

        if (!findType(dataSymbols[count].key) && strlen(dataSymbols[count].key) > 0)
        {
            dataSymbols[count].key[strcspn(dataSymbols[count].key, ":")] = 0;
            parseDATA(lineCopyData, count);
            dataSymbols[count].address = address;

            int binLength = strlen(dataSymbols[count++].binary);
            address += (binLength % 33 == 0) ? (4 * (binLength / 33)) : (4 * ((binLength / 33) + 1));
        }
    }

    dataSymbols[count].binary = NULL;
    fseek(readF, currOffset, SEEK_SET);

    free(line);
}

void getTextSymbols(FILE *readF, uint16_t currOffset)
{
    fseek(readF, currOffset, SEEK_SET);
    char *line = calloc(MAX_LINE_LENGTH, sizeof(char));
    int count = 0, address = 0, instructionCount = 0;

    while (fgets(line, MAX_LINE_LENGTH, readF))
    {
        char tSymbol[MAX_LINE_LENGTH + 1];
        strcpy(tSymbol, strtok(line, " ,\t"));
        tSymbol[strcspn(tSymbol, "\n")] = 0;

        if (!findType(tSymbol) && strcmp(tSymbol, "") != 0 && strcmp(tSymbol, "#") != 0)
        {
            tSymbol[strcspn(tSymbol, ":")] = 0;
            textSymbols[count].key = calloc(MAX_LINE_LENGTH, sizeof(char));
            strcpy(textSymbols[count].key, tSymbol);
            textSymbols[count].instructionNum = (strcmp(tSymbol, "main") == 0) ? instructionCount : (instructionCount + 1);

            address = (4 * instructionCount);
            textSymbols[count++].address = address;
        }

        if (findType(tSymbol))
            instructionCount++;
    }

    textSymbols[count].key = NULL;
    textSymbols[count].instructionNum = 0;
    fseek(readF, currOffset, SEEK_SET);

    free(line);
}
ParseResult.c0000600006173000234230000000655114236772524013474 0ustar  jordanha23Others#include "ParseResult.h"
#include <stdlib.h>
#include <string.h>

static struct {
	char* mnem;
	char* mType;
} type[] = {
		{ "sub", "r" },
		{ "nor", "r" },
		{ "add", "r" },
		{ "syscall", "r" },
		{ "mul", "r" },
		{ "mult", "s" },
		{ "lw",   "i" },
		{ "lui",  "i" },
		{ "addi", "i" },
		{ "slti", "i" },
		{ "la", "i" },
		{ "beq", "i" },
		{ "bne", "i" },
		{ "sw",   "i" },
		{ "nop", "r" },
		{ "sll", "r" },
		{ "sra", "r" },
		{ "srav", "r" },
		{ "slt", "r" },
		{ "blt", "r" },
		{ "j", "ju" },
		{ "addu", "r" },
		{ "move", "r" },
		{ "addiu", "i" },
		{ "li", "i" },
		{ "blez", "i" },
		{ "bgtz", "i" }, 
    	{ NULL, 0 } 
   };

/***  Add include directives for here as needed.  ***/
char* clearType(char* inp);

/**  Frees the dynamic content of a ParseResult object.
 * 
 *   Pre:  pPR points to a proper ParseResult object.
 *   Post: All of the dynamically-allocated arrays in *pPR have been
 *         deallocated; pointers are NULL, static fields are reset to
 *         default values.
 * 
 *   Comments:
 *     -  The function has no information about whether *pPR has been
 *        allocated dynamically, so it cannot risk attempting to 
 *        deallocate *pPR.
 *     -  The function is intended to provide the user with a simple
 *        way to free memory; the user may or may not reuse *pPR.  So,
 *        the function does set the pointers in *pPR to NULL.
 */
void clearResult(ParseResult* const pPR) {

	if(pPR){

		pPR->Imm = 0;
		pPR->rd = 0;
		pPR->rs = 0;
		pPR->rt = 0;

		if(!strcmp(clearType(pPR->Mnemonic), "ju")){
			free(pPR->Opcode);
			free(pPR->Target);
		}

		if(!strcmp(clearType(pPR->Mnemonic), "i")){
			free(pPR->RS);
			free(pPR->RT);
			free(pPR->rsName);
			free(pPR->rtName);
			free(pPR->Opcode);
			free(pPR->IMM);
		}

		if(!strcmp(clearType(pPR->Mnemonic), "r")){
			free(pPR->rdName);
   			free(pPR->rsName);
			free(pPR->rtName);
			free(pPR->Opcode);
			free(pPR->Funct);
			free(pPR->RD);
			free(pPR->RS);
			free(pPR->RT);
			free(pPR->shamt);

		}

		if(!strcmp(clearType(pPR->Mnemonic), "s")){
			free(pPR->RS);
			free(pPR->RT);
			free(pPR->RD);
			free(pPR->rsName);
			free(pPR->rtName);
			free(pPR->Opcode);
			free(pPR->Funct);
		}
	}

	free(pPR->Mnemonic);
	free(pPR->ASMInstruction);
}

/**  Prints the contents of a ParseResult object.
 * 
 *   Pre:  Log is open on an output file.
 *         pPR points to a proper ParseResult object.
 */
void printResult(FILE* Log, const ParseResult* const pPR) {
   
      fprintf(Log, "%s\n", pPR->ASMInstruction);
      fprintf(Log, "   %s   %s\n", pPR->Opcode, pPR->Mnemonic);
      fprintf(Log, "   %2"PRIu8"   %s", pPR->rd, pPR->rdName);
      if ( pPR->RD != NULL ) {
			fprintf(Log, "   %s", pPR->RD);
		}
		fprintf(Log, "\n");
      fprintf(Log, "   %2"PRIu8"   %s", pPR->rs, pPR->rsName);
      if ( pPR->RS != NULL ) {
			fprintf(Log, "   %s", pPR->RS);
		}
		fprintf(Log, "\n");
      fprintf(Log, "   %2"PRIu8"   %s", pPR->rt, pPR->rtName);
      if ( pPR->RT != NULL ) {
			fprintf(Log, "   %s", pPR->RT);
		}
		fprintf(Log, "\n");
      fprintf(Log, "   %s\n", pPR->Funct);
      fprintf(Log, "   %"PRId16"\n", pPR->Imm);
      if ( pPR->IMM != NULL ) {
			fprintf(Log, "   %s", pPR->IMM);
		}
		fprintf(Log, "\n");
		fprintf(Log, "\n");
}

char* clearType(char* inp){
   int i = -1;
   while(type[++i].mnem) 
      if(!strcmp(inp, type[i].mnem))
         return type[i].mType;
   return NULL;
}
SymbolTable.c0000600006173000234230000000332314237027136013423 0ustar  jordanha23Others#include "SymbolTable.h"

#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

DataSymbol dataSymbols[NUM_SYMBOLS] = {0};
TextSymbol textSymbols[NUM_SYMBOLS] = {0};

void makeTable(FILE *outF)
{
   int x = -1, j = -1, i = 0;

   while (dataSymbols[i].binary)
   {
      char key[sizeof(dataSymbols[i].key) + 1];

      j = -1;
      while (dataSymbols[i].key[++j] != 0)
         key[j] = dataSymbols[i].key[j];

      fprintf(outF, "0x%08X\t%s\n", dataSymbols[i++].address, key);
   }

   while (textSymbols[++x].key != NULL)
      fprintf(outF, "0x%08X\t%s\n", textSymbols[x].address, textSymbols[x].key);
}

void cleanTable()
{
   int i = -1, x = -1;
   while (dataSymbols[++i].binary)
      free(dataSymbols[i].binary),
          free(dataSymbols[i].type);
   while (textSymbols[++x].key)
      free(textSymbols[x].key);
}

char *decToBinary(char *dec)
{
   int16_t n = atol(dec);
   int i = 0, s = 15;
   char *binaryNum = calloc(IMM_LENGTH, sizeof(char));
   while (s >= 0)
      binaryNum[i++] = ((n >> s--) & 1) ? '1' : '0';
   return binaryNum;
}

char *decToBinary26(char *dec)
{
   int n = atoi(dec), i = 0, s = 25;
   char *binaryNum = calloc(27, sizeof(char));
   while (s >= 0)
      binaryNum[i++] = ((n >> s--) & 1) ? '1' : '0';
   return binaryNum;
}

char *unDecToBinary(char *dec)
{
   uint16_t n;
   sscanf(dec, "%hd", &n);
   int i = 0, s = 15;
   char *binaryNum = calloc(IMM_LENGTH, sizeof(char));
   while (s >= 0)
      binaryNum[i++] = ((n >> s--) & 1) ? '1' : '0';
   return binaryNum;
}

uint16_t findImm(char *word)
{
   int i = -1;
   while (dataSymbols[++i].binary)
      if (!strcmp(word, dataSymbols[i].key))
         return dataSymbols[i].address;
   return 0;
}
ASMParser.h0000600006173000234230000000150714236755613013021 0ustar  jordanha23Others#ifndef ASMPARSER_H
#define ASMPARSER_H
#include "ParseResult.h"

char* findReg(char* inp);
char* findFunc(char* inp);
char* findOp(char* inp);
char* findType(char* inp);
uint8_t binaryToDec(char* addy);
char* decToBinary(char* dec);


/**  Breaks up given MIPS32 assembly instruction and creates a proper 
 *   ParseResult object storing information about that instruction.
 * 
 *   Pre:  pASM points to an array holding the bits (as chars) of a
 *         syntactically valid assembly instruction, whose mnemonic is
 *         one of the following:
 * 
 *             addi  mul  mult  lui  lw  sub
 * 
 *   Returns:
 *         A pointer to a proper ParseResult object whose fields have been
 *         correctly initialized to correspond to the target of pASM.
 */
ParseResult* parseASM(const char* const pASM, uint16_t offset);

#endif
DATAParser.h0000600006173000234230000000066014236755613013111 0ustar  jordanha23Others#ifndef DATAPARSER_H
#define DATAPARSER_H

/**  Breaks up given MIPS32 assembly instruction and creates a proper 
 *   char* storing the machine code for data output.
 * 
 *   Pre:  pASM points to an array holding the bits (as chars) of variables
 *         defined within the program
 * 
 *   Returns:
 *         A pointer to a proper char* representation of binary machine code
 */
void parseDATA(char pDATA[], int count);

#endifParseResult.h0000600006173000234230000000646014236755613013500 0ustar  jordanha23Others#ifndef PARSERESULT_H
#define PARSERESULT_H
#include <inttypes.h>
#include <stdio.h>

char* clearType(char* inp);

/**  Represents the possible field values for a MIPS32 machine instruction.
 * 
 *   A ParseResult object is said to be proper iff:
 * 
 *     - Each of the char* members is either NULL or points to a zero-
 *       terminated C-string.
 *     - If ASMInstruction is not NULL, the contents of the array represent
 *       a MIPS32 assembly instruction.
 *     - If ASMInstruction is not NULL, the other fields are set to properly
 *       represent the corresponding fields of the MIPS32 assembly instruction
 *       stored in ASMInstruction.
 *     - Each field that is not relevant to the MIPS32 assembly instruction
 *       is set as described in the comments below.
 */
struct _ParseResult {
   // Each char* member will be NULL or point to dynamically-allocated char array
   // holding a zero-terminated C string.

   // The assembly code portion
   char* ASMInstruction;    // the assembly instruction, as a C-string
   char* Mnemonic;          // the symbolic name of the instruction
   char* rdName;            // the symbolic names of the registers, as C-strings;
   char* rsName;            //    NULL if the register field is not specified
   char* rtName;            //    in the assembly instruction
   
   //   The following are integer values
   int16_t  Imm;            // the immediate field, as a signed integer;
                            //   0 if not relevant for the assembly instruction
   uint8_t  rd;             // the three register fields, as small unsigned integers;
   uint8_t  rs;             //   255 if not relevant for the assembly instruction
   uint8_t  rt;

   char* shamt;             // shift amount
   char* Target;            // target for jump instructions

   // The computed machine code portion
   //   These are malloc'd zero-terminated C-strings
   char* Opcode;            // the opcode field bits
   char* Funct;             // the funct field bits
                            //   NULL if not relevant for the assembly instruction
   char* RD;                // the bit representations of the register numbers; 
   char* RS;                //   NULL if not relevant for the assembly instruction
   char* RT;
   char* IMM;               // 2's complement bit representation of the immediate;
                            //   NULL if not relevant for the assembly instruction

};

typedef struct _ParseResult ParseResult;

/**  Frees the dynamic content of a ParseResult object.
 * 
 *   Pre:  pPR points to a proper ParseResult object.
 *   Post: All of the dynamically-allocated arrays in *pPR have been
 *         deallocated.
 *         *pPR is proper.
 * 
 *   Comments:
 *     -  The function has no information about whether *pPR has been
 *        allocated dynamically, so it cannot risk attempting to 
 *        deallocate *pPR.
 *     -  The function is intended to provide the user with a simple
 *        way to free memory; the user may or may not reuse *pPR.  So,
 *        the function does set the pointers in *pPR to NULL.
 */
void clearResult(ParseResult* const pPR);

/**  Prints the contents of a ParseResult object.
 * 
 *   Pre:  Log is open on an output file.
 *         pPR points to a proper ParseResult object.
 */
void printResult(FILE* Log, const ParseResult* const pPR);

#endif
SymbolTable.h0000600006173000234230000000123514236755613013437 0ustar  jordanha23Others#ifndef SYMBOLTABLE_H
#define SYMBOLTABLE_H

#include <stdio.h>

#define NUM_SYMBOLS 1000
#define IMM_LENGTH 17

struct _DataSymbol {
    char key[100];
	char* binary;
    int address;
    char* type;
};
typedef struct _DataSymbol DataSymbol;

extern DataSymbol dataSymbols[NUM_SYMBOLS];

struct _TextSymbol {
    char* key;
	int instructionNum;
    int address;
};
typedef struct _TextSymbol TextSymbol;

extern TextSymbol textSymbols[NUM_SYMBOLS];

/**  Writes the symbol table out o the given file
 * 
 *   Pre:  outF is a valid output file
 * 
 */
void makeTable(FILE* outF);

void cleanTable();
char* decToBinary(char* dec);
char* decToBinary26(char* dec);

#endifpledge.txt0000600006173000234230000000126414236755613013054 0ustar  jordanha23OthersOn my honor:

 - I have not discussed the C language code in my program with
 anyone other than my instructor or the teaching assistants
 assigned to this course.

 - I have not used C language code obtained from another student,
 the Internet, or any other unauthorized source, either modified
 or unmodified.

 - If any C language code or documentation used in my program
 was obtained from an authorized source, such as a text book or
 course notes, that has been clearly noted with a proper citation
 in the comments of my program.

- I have not designed this program in such a way as to defeat or
interfere with the normal operation of the grading code.

<Jordan Harrington>
<jordanha23>makefile0000600006173000234230000000026414236757607012557 0ustar  jordanha23Othersassembler: Parser.c
	gcc -o assemble -std=c11 -Wall -W -ggdb3 Parser.c ASMParser.c ParseResult.c DATAParser.c SymbolTable.c

tar:
	tar -cvf grading.tar *.c *.h pledge.txt makefile