Skip to content

Instantly share code, notes, and snippets.

@xyzshantaram
Last active August 15, 2020 09:46
Show Gist options
  • Save xyzshantaram/8e3bc932daf08cac632d9a1f111ade28 to your computer and use it in GitHub Desktop.
Save xyzshantaram/8e3bc932daf08cac632d9a1f111ade28 to your computer and use it in GitHub Desktop.
#include <stdlib.h>
#include "lmc.h"
#include "string_utils.h"
Instruction parse_input(char* str) {
const char* opcodes[] = {
"ADD", "SUB", "STA", "LDA", "BRA", "BRZ", "BRP", "INP", "OUT", "HLT"
};
const int opcode_count = 10;
char** instr;
Instruction i;
int pos = -1;
if ((pos = str_array_fuzzy_contains(opcodes, opcode_count, str)) != -1) {
size_t index = 0;
instr = split_on_delim(str, &index," ");
i.op = pos;
i.val = atoi(instr[1]);
}
free(instr);
return i;
}
void add(lmc_state* state, byte address) {
byte address_bounded = address % LMC_MEMORY_SIZE;
(*state).accumulator += (*state).mem[address_bounded];
}
void sub(lmc_state* state, byte address) {
byte address_bounded = address % LMC_MEMORY_SIZE;
(*state).accumulator -= (*state).mem[address_bounded];
}
void sta(lmc_state* state, byte address) {
byte address_bounded = address % LMC_MEMORY_SIZE;
(*state).mem[address_bounded] = (*state).accumulator;
}
void lda(lmc_state* state, byte address) {
byte address_bounded = address % LMC_MEMORY_SIZE;
(*state).accumulator = (*state).mem[address_bounded];
}
void bra(lmc_state* state, byte address) {
byte address_bounded = address % LMC_MEMORY_SIZE;
(*state).program_counter = (*state).mem[address_bounded];
}
void brz(lmc_state* state, byte address) {
byte address_bounded = address % LMC_MEMORY_SIZE;
if ((*state).accumulator == 0) (*state).program_counter = (*state).mem[address_bounded];
}
void brp(lmc_state* state, byte address) {
byte address_bounded = address % LMC_MEMORY_SIZE;
if ((*state).accumulator > 0) (*state).program_counter = (*state).mem[address_bounded];
}
void inp(lmc_state* state, byte address) {
(*state).accumulator = get_input();
}
void out(lmc_state* state, byte address) {
printf('OUT: %i', (*state).accumulator);
}
void* functions[] = {
&add, &sub, &sta, &lda, &bra, &brz, &brp, &inp, &out
};
int get_input() {
printf("\nINP> ");
char* str = read_string("\n");
return atoi(str);
}
#include <stdint.h>
#include <stdbool.h>
#define LMC_MEMORY_SIZE 100
typedef struct mstate {
unsigned int mem[100];
unsigned int program_counter;
unsigned int accumulator;
} lmc_state;
typedef enum op {
ADD, SUB, STA, LDA, BRA, BRZ, BRP, INP, OUT, HLT
} Opcode;
typedef struct instruction {
int val;
Opcode op;
} Instruction;
typedef uint8_t byte;
extern void* functions[];
Instruction parse_input (char* str);
int get_input();
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include "string_utils.h"
#include "lmc.h"
int main (int argc, char* argv[]) {
char* str;
lmc_state state = {
.mem = {0},
.program_counter = 0,
.accumulator = 0
};
if (argc < 2) {
printf("Please provide a filename containing LMC assembly.");
}
else {
char* file = file_into_str(argv[1]);
size_t index;
char** file_lines = split_on_delim(file, &index, "\n");
printf("%zu", index);
/* while (true) {
state.program_counter++;
Instruction i = parse_input(str);
if (i.op >= 9 || i.op < 0) {
printf("incorrect opcode.");
}
else {
if(i.op == 9) {
printf("HLT");
break;
}
else {
}
}
} */
}
return 0;
}
NAME = main
CC ?= gcc # don't override CC if one is already set, or if the user has already set one
CFLAGS := -Wall -Wextra -Wunreachable-code
OBJ = main.o string_utils.o lmc.o
HEADER = string_utils.h lmc.h
OUTPUT_NAME = a.out
$(NAME): $(OBJ)
$(CC) -o $(OUTPUT_NAME) $(CFLAGS) $(OBJ)
debug: CFLAGS += -g -ggdb
debug: $(NAME)
main.c: $(HEADERS)
string_utils.c: $(HEADERS)
run: $(NAME)
./$(OUTPUT_NAME)
clean:
rm $(OBJ)
rm $(OUTPUT_NAME)
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "string_utils.h"
String lazy_append_to_string(char* dest, const char* input) {
size_t input_len = strlen(input);
size_t cur_size = strlen(dest);
size_t realloc_size = cur_size + input_len;
char* realloc_ret = realloc(dest, realloc_size);
if (realloc_ret) {
strcat(realloc_ret, input);
}
else {
free(dest);
}
String ret = { .len = realloc_size, .ptr = realloc_ret, .old_len = cur_size };
return ret;
}
String append_to_string(char* dest, const char* input, size_t dest_size, size_t input_len) {
size_t realloc_size = dest_size + input_len;
char* realloc_ret = realloc(dest, realloc_size);
if (realloc_ret) {
strcat(realloc_ret, input);
}
else {
free(dest);
}
String ret = { .len = realloc_size, .ptr = realloc_ret, .old_len = dest_size };
return ret;
}
char* read_string(char stop_char) {
char* final = strdup("");
String new_str;
char buffer[READ_CHUNK_SIZE];
while (fgets(buffer, sizeof(buffer), stdin) != 0) {
new_str = lazy_append_to_string(final, buffer);
if (new_str.ptr) {
final = new_str.ptr;
}
else {
free(new_str.ptr);
free(final);
return NULL;
}
if (new_str.ptr[new_str.len - 1] == stop_char) break;
}
final[new_str.len - 1] = '\0';
return final;
}
char* tokenize_string(char* str, char* delim, size_t* index) {
size_t str_len = strlen(str);
size_t i = *index;
if (i >= str_len) {
return NULL;
}
char* ret = strdup("");
// i already has a value; no need to reassign.
for (; i < str_len; i += 1) {
if(str[i] == *delim) {
break;
}
char* new_ret = realloc(ret, strlen(ret) + sizeof(char));
if (new_ret) {
ret = new_ret;
}
else {
free(ret);
return NULL;
}
strncat(ret, &str[i], 1);
}
*index = i + 1; // +1 because we break at the delimiter, and we need to move to the next index after that
return ret;
}
char** split_on_delim(char* str, size_t* index, const char* DELIM) {
size_t arr_size = 0;
size_t split_index = 0; // index for reentry into the string for consecutive splits
char* token = tokenize_string(str, DELIM, &split_index);
char** arr = malloc(sizeof(char*));
while(token) {
arr_size += sizeof(char*);
char** new_arr = realloc(arr, arr_size);
if (new_arr) {
arr = new_arr;
arr[*index] = token;
}
else {
free(arr);
return NULL;
}
*index += 1;
token = tokenize_string(str, DELIM, &split_index);
}
free(token);
return arr;
}
int str_array_contains(const char* arr[], int arr_len, char* str) {
for (size_t i = 0; i < arr_len; i++) {
if (strcmp(arr[i], str) == 0) return i;
}
return -1;
}
int str_array_fuzzy_contains(const char* arr[], int arr_len, char* str) {
for (int i = 0; i < arr_len; i++) {
if (strstr(str, arr[i])) return i;
}
return -1;
}
char* file_into_str(const char* filename) {
int retval;
FILE* file_ptr;
char* file_contents = strdup("");
file_ptr = fopen(filename, "r");
if(file_ptr == NULL) {
return NULL;
}
char* temp = malloc(READ_CHUNK_SIZE);
while (!feof(file_ptr)) {
temp = fgets(temp, READ_CHUNK_SIZE, file_ptr);
if (temp != NULL) {
file_contents = lazy_append_to_string(file_contents, (const char*) temp).ptr;
}
else {
if (errno != 0) {
//TODO: implement specific error handling
retval = errno;
goto cleanup;
}
}
}
cleanup:
fclose(file_ptr);
free(temp);
return file_contents;
}
struct StrInfo {
size_t len;
size_t old_len;
char* ptr;
};
#undef String
typedef struct StrInfo String;
#undef READ_CHUNK_SIZE
#define READ_CHUNK_SIZE 32
String lazy_append_to_string(char* dest, const char* input);
String append_to_string(char* dest, const char* input, size_t dest_size, size_t input_len);
char* read_string(char stop_char);
char** split_on_delim(char* str, size_t* index, const char* DELIM);
char* tokenize_string(char* str, char* delim, size_t* index);
int str_array_contains(const char* arr[], int arr_len, char* str);
int str_array_fuzzy_contains(const char* arr[], int arr_len, char* str);
char* file_into_str(const char* filename);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment