Last active
August 15, 2020 09:46
-
-
Save xyzshantaram/8e3bc932daf08cac632d9a1f111ade28 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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