Source

programming_languages / chap3 / wici.c

Full commit
/**
 * Main execution file for the WIC Interpreter.
 * @author Seth Hobson
 * @version 20121002
 */
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include "instruction.h"

// local function prototypes
void discardLine(FILE *file);
void readFile(FILE *file);
void execute();

/**
 * Main
 */
int main(int argc, char **argv)
{
    FILE *fileIn;
    
    if (argc != 2) {
        printf("usage: wici <filename>\n");
        exit(EXIT_FAILURE);
    }
    
    fileIn = fopen(argv[1], "r");
    if (fileIn == NULL) {
        printf("failed opening file: '%s'\n", argv[1]);
        exit(EXIT_FAILURE);
    }
    
    readFile(fileIn);
    fclose(fileIn);
    
    execute();
    printAll();
    exit(EXIT_SUCCESS);
}

/**
 * Function: reads the file input and inserts instructions into table
 * @param file the file read from stdin
 */
void readFile(FILE *file)
{
    char opcode[OPCODE_LENGTH];
    char operand[OPERAND_LENGTH];
    int pc = 0;
    
    while (fscanf(file, "%s", opcode) == 1) {
        if (opcode[0] == '%') { // WIC comments
            discardLine(file);
            continue;
        }
        
        if (hasOperand(opcode))
            fscanf(file, "%s", operand);
        else
            operand[0] = 0;
        
        insertInstruction(pc, opcode, operand);
        pc++;
    }
}

/**
 * Function: executes the REPL for the interpreter
 */
void execute()
{
    int pc = 0;
    char *opcode;
    while (pc >= 0) {
        opcode = fetchOpcode(pc);
        if (strcmp(opcode, "get") == 0)
            pc = get(pc);
        else if (strcmp(opcode, "push") == 0)
            pc = push(pc);
        else if (strcmp(opcode, "add") == 0)
            pc = add(pc);
        else if (strcmp(opcode, "pop") == 0)
            pc = pop(pc);
        else if (strcmp(opcode, "put") == 0)
            pc = put(pc);
        else if (strcmp(opcode, "halt") == 0)
            pc = halt();
        else if (strcmp(opcode, "nop") == 0)
            pc = nop(pc);
        else if (strcmp(opcode, "j") == 0)
            pc = jump(pc);
        else if (strcmp(opcode, "jf") == 0)
            pc = jf(pc);
        else if (strcmp(opcode, "and") == 0)
            pc = and(pc);
        else if (strcmp(opcode, "or") == 0)
            pc = or(pc);
        else if (strcmp(opcode, "not") == 0)
            pc = not(pc);
        else if (strcmp(opcode, "sub") == 0)
            pc = sub(pc);
        else if (strcmp(opcode, "mul") == 0)
            pc = mult(pc);
        else if (strcmp(opcode, "div") == 0)
            pc = divide(pc);
        else if (strcmp(opcode, "tstlt") == 0)
            pc = testlt(pc);
        else if (strcmp(opcode, "tstgt") == 0)
            pc = testgt(pc);
        else if (strcmp(opcode, "tsteq") == 0)
            pc = testeq(pc);
        else if (strcmp(opcode, "tstne") == 0)
            pc = testne(pc);
        else if (strcmp(opcode, "tstle") == 0)
            pc = testle(pc);
        else if (strcmp(opcode, "tstge") == 0)
            pc = testge(pc);
        else {
            printf("invalid opcode '%s'\n", opcode);
            exit(EXIT_FAILURE);
        }
    }
}

/**
 * Function: swallows the current line up to the new line character
 * @param file the file read from stdin
 */
void discardLine(FILE *file)
{
    while (fgetc(file) != '\n');
}