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