CS-PROJECTS / c02_assembler / DATAParser.c
DATAParser.c
Raw
#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;
}