now using function ptr instead of switch case
also changed get_instruction to parser
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
#include "instruction_set.h"
|
||||
|
||||
INSTRUCTION get_instruction(char* line, int* args_start_pos, int line_number);
|
||||
void get_args(char* line, int args_start_pos);
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
typedef enum INSTRUCTIONS {
|
||||
ERROR_INSTRUCTION = -2,
|
||||
LABEL = -1,
|
||||
ADD,
|
||||
SUB,
|
||||
MOV,
|
||||
CMP,
|
||||
JE,
|
||||
JNE,
|
||||
JMP,
|
||||
JB,
|
||||
JNB,
|
||||
JA,
|
||||
JNA,
|
||||
RET,
|
||||
POP,
|
||||
PUSH,
|
||||
CALL,
|
||||
AND
|
||||
} INSTRUCTION;
|
||||
@@ -64,22 +64,36 @@ int get_value(char* arg) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
cmp_return_codes cmp() {
|
||||
const command_t *find_command(char *your_var)
|
||||
{
|
||||
if (your_var == NULL)
|
||||
return NULL;
|
||||
for (int index = 0; command_map[index].fptr != NULL; index += 1) {
|
||||
if (strcmp(your_var, command_map[index].command) == 0) {
|
||||
return &command_map[index];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cmp() {
|
||||
if (!check_args(1)) {
|
||||
return CMP_ERROR;
|
||||
last_cmp_code = CMP_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
int a1_ = get_value(args->arg1);
|
||||
int a2_ = get_value(args->arg2);
|
||||
|
||||
if (a1_ == a2_) return CMP_EQUAL;
|
||||
if (a1_ > a2_) return CMP_ABOVE;
|
||||
if (a2_ > a1_) return CMP_BELOW;
|
||||
|
||||
return CMP_EQUAL; //never hit but it makes the compiler happy
|
||||
if (a1_ == a2_) last_cmp_code = CMP_EQUAL;
|
||||
else if (a1_ > a2_) last_cmp_code = CMP_ABOVE;
|
||||
else if (a2_ > a1_) last_cmp_code = CMP_BELOW;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void jmp() {
|
||||
return;
|
||||
for (int i = 0; i < MAX_LABEL; i++) {
|
||||
if (labels[i] == NULL) break;
|
||||
if (strcmp(args->arg1, labels[i]) == 0) {
|
||||
@@ -92,28 +106,28 @@ void jmp() {
|
||||
return;
|
||||
}
|
||||
|
||||
bool jna() {
|
||||
return last_cmp_code != CMP_ABOVE;
|
||||
void jna() {
|
||||
if (last_cmp_code != CMP_ABOVE) jmp();
|
||||
}
|
||||
|
||||
bool ja() {
|
||||
return last_cmp_code == CMP_ABOVE;
|
||||
void ja() {
|
||||
if (last_cmp_code == CMP_ABOVE) jmp();
|
||||
}
|
||||
|
||||
bool jnb() {
|
||||
return last_cmp_code != CMP_BELOW;
|
||||
void jnb() {
|
||||
if (last_cmp_code != CMP_BELOW) jmp();
|
||||
}
|
||||
|
||||
bool jb() {
|
||||
return last_cmp_code == CMP_BELOW;
|
||||
void jb() {
|
||||
if (last_cmp_code == CMP_BELOW) jmp();
|
||||
}
|
||||
|
||||
bool jne() {
|
||||
return last_cmp_code != CMP_EQUAL;
|
||||
void jne() {
|
||||
if (last_cmp_code != CMP_EQUAL) jmp();
|
||||
}
|
||||
|
||||
bool je() {
|
||||
return last_cmp_code == CMP_EQUAL;
|
||||
void je() {
|
||||
if (last_cmp_code == CMP_EQUAL) jmp();
|
||||
}
|
||||
|
||||
void sub() {
|
||||
@@ -138,4 +152,24 @@ void mov() {
|
||||
}
|
||||
|
||||
*get_reg(args->arg1) = get_value(args->arg2);
|
||||
}
|
||||
|
||||
void ret() {
|
||||
|
||||
}
|
||||
|
||||
void call() {
|
||||
|
||||
}
|
||||
|
||||
void push() {
|
||||
|
||||
}
|
||||
|
||||
void pop() {
|
||||
|
||||
}
|
||||
|
||||
void and() {
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "get_instruction.h"
|
||||
#include "parser.h"
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum cmp_return_codes {
|
||||
@@ -17,20 +18,50 @@ typedef enum check_args_codes {
|
||||
} check_args_codes ;
|
||||
extern check_args_codes last_check_args_code;
|
||||
|
||||
//pasted from https://github.com/Sakutaroo/Templates/blob/main/C/FunctionPointer/function_pointer.h
|
||||
typedef struct command_s {
|
||||
char *command;
|
||||
void (*fptr)();
|
||||
} command_t;
|
||||
|
||||
const command_t *find_command(char *your_var);
|
||||
|
||||
bool check_args(int num_in_first);
|
||||
|
||||
void add();
|
||||
void sub();
|
||||
void mov();
|
||||
cmp_return_codes cmp();
|
||||
bool je();
|
||||
bool jne();
|
||||
bool jb();
|
||||
bool jnb();
|
||||
bool ja();
|
||||
bool jna();
|
||||
void cmp();
|
||||
void je();
|
||||
void jne();
|
||||
void jb();
|
||||
void jnb();
|
||||
void ja();
|
||||
void jna();
|
||||
void jmp();
|
||||
void ret();
|
||||
void pop();
|
||||
void push();
|
||||
void call();
|
||||
void and();
|
||||
|
||||
static const command_t command_map[] = {
|
||||
{.command = "add", .fptr = add},
|
||||
{.command = "sub", .fptr = sub},
|
||||
{.command = "mov", .fptr = mov},
|
||||
{.command = "cmp", .fptr = cmp},
|
||||
{.command = "je", .fptr = je},
|
||||
{.command = "jne", .fptr = jne},
|
||||
{.command = "jb", .fptr = jb},
|
||||
{.command = "jnb", .fptr = jnb},
|
||||
{.command = "ja", .fptr = ja},
|
||||
{.command = "jna", .fptr = jna},
|
||||
{.command = "jmp", .fptr = jmp},
|
||||
{.command = "ret", .fptr = ret},
|
||||
{.command = "pop", .fptr = pop},
|
||||
{.command = "push", .fptr = push},
|
||||
{.command = "call", .fptr = call},
|
||||
{.command = "and", .fptr = and},
|
||||
|
||||
{.command = NULL, .fptr = NULL}
|
||||
};
|
||||
|
||||
91
src/main.c
91
src/main.c
@@ -2,7 +2,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "main.h"
|
||||
#include "get_instruction.h"
|
||||
#include "parser.h"
|
||||
#include "instructions.h"
|
||||
|
||||
void show_help() {
|
||||
@@ -43,7 +43,9 @@ int main(int argc, char** argv) {
|
||||
char line[256];
|
||||
int line_number = 1;
|
||||
size_t char_read = 0;
|
||||
const command_t* com = NULL;
|
||||
while (fgets(line, sizeof(line), fptr)) {
|
||||
com = NULL;
|
||||
char_read += strlen(line);
|
||||
|
||||
if (line[0] == ';' || line[0] == '\n') {
|
||||
@@ -52,68 +54,39 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
int args_pos;
|
||||
INSTRUCTION ins = get_instruction(line, &args_pos, (int)char_read);
|
||||
if (args_pos != -1) {
|
||||
|
||||
char* ins = calloc(MAX_INS_LENGHT, 1);
|
||||
|
||||
get_instruction(line, &args_pos, (int)char_read, &ins);
|
||||
if (args_pos == -1) {
|
||||
free(ins);
|
||||
++line_number;
|
||||
continue;
|
||||
}
|
||||
|
||||
com = find_command(ins);
|
||||
if (com != NULL) {
|
||||
get_args(line, args_pos);
|
||||
}
|
||||
|
||||
switch (ins) {
|
||||
case SUB :
|
||||
sub();
|
||||
break;
|
||||
case MOV :
|
||||
mov();
|
||||
break;
|
||||
case ADD :
|
||||
add();
|
||||
break;
|
||||
case CMP :
|
||||
last_cmp_code = cmp();
|
||||
break;
|
||||
case JE :
|
||||
if (je()) {
|
||||
jmp();
|
||||
}
|
||||
break;
|
||||
case JNE :
|
||||
if (jne()) {
|
||||
jmp();
|
||||
}
|
||||
break;
|
||||
case JB :
|
||||
if (jb()) {
|
||||
jmp();
|
||||
}
|
||||
break;
|
||||
case JNB :
|
||||
if (jnb()) {
|
||||
jmp();
|
||||
}
|
||||
break;
|
||||
case JA :
|
||||
if (ja()) {
|
||||
jmp();
|
||||
}
|
||||
break;
|
||||
case JNA :
|
||||
if (jna()) {
|
||||
jmp();
|
||||
}
|
||||
break;
|
||||
case JMP :
|
||||
jmp();
|
||||
break;
|
||||
case LABEL :
|
||||
break;
|
||||
case ERROR_INSTRUCTION:
|
||||
printf("%s ^\n |\ninvalid operand on line %d", line, line_number);
|
||||
free(args->arg1);
|
||||
free(args->arg2);
|
||||
free(args);
|
||||
fclose(fptr);
|
||||
return 1;
|
||||
free(ins);
|
||||
|
||||
if (args == NULL || args->arg1 == NULL || args->arg2 == NULL) {
|
||||
++line_number;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (com == NULL) {
|
||||
printf("%s ^\n |\ninvalid operand on line %d", line, line_number);
|
||||
free(args->arg1);
|
||||
free(args->arg2);
|
||||
free(args);
|
||||
fclose(fptr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
com->fptr();
|
||||
|
||||
if (last_check_args_code != OK) {
|
||||
printf("%s", line);
|
||||
printf("%*c ^\n", args_pos, ' ');
|
||||
|
||||
@@ -1,52 +1,45 @@
|
||||
#include "get_instruction.h"
|
||||
#include "parser.h"
|
||||
#include "main.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
const char* instructions_char[] = {"add", "sub", "mov", "cmp", "je", "jne", "jmp", "jb", "jbn", "ja", "jna", "ret", "pop", "push", "call", "and"};
|
||||
void get_instruction(char* line, int* args_start_pos, int line_number, char** ins) {
|
||||
char temp[MAX_INS_LENGHT];
|
||||
memset(temp, 0, sizeof(temp));
|
||||
|
||||
INSTRUCTION get_instruction(char* line, int* args_start_pos, int line_number) {
|
||||
char ins[20]; //20 should be enough
|
||||
memset(ins, 0, sizeof(ins));
|
||||
|
||||
for (int i = 0; i < (int)strlen(line); i++) {
|
||||
for (int i = 0; i < MAX_INS_LENGHT; i++) {
|
||||
if (line[i] == ' ' || line[i] == '\n' || line[i] == '\0') {
|
||||
ins[i] = '\0';
|
||||
temp[i] = '\0';
|
||||
*args_start_pos = i + 1;
|
||||
break;
|
||||
}
|
||||
if (line[i] == ':') {
|
||||
ins[i] = '\0';
|
||||
temp[i] = '\0';
|
||||
*args_start_pos = -1;
|
||||
strcpy_s(*ins, strlen(temp)+1,temp);
|
||||
|
||||
for (int i = 0; i < MAX_LABEL; i++) {
|
||||
if (labels[i] == NULL) break;
|
||||
if (strcmp(ins, labels[i]) == 0) {
|
||||
return LABEL;
|
||||
if (strcmp(temp, labels[i]) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
labels[num_labels] = (char*)calloc(1, strlen(ins) + 1);
|
||||
labels[num_labels] = (char*)calloc(1, strlen(temp) + 1);
|
||||
if (labels[num_labels] != NULL) {
|
||||
strcpy_s(labels[num_labels], strlen(ins) + 1, ins);
|
||||
strcpy_s(labels[num_labels], strlen(temp) + 1, temp);
|
||||
}
|
||||
labels_lines[num_labels] = line_number;
|
||||
++num_labels;
|
||||
return LABEL;
|
||||
return;
|
||||
}
|
||||
|
||||
ins[i] = line[i];
|
||||
temp[i] = line[i];
|
||||
}
|
||||
|
||||
for (int j = 0; j < sizeof(instructions_char)/sizeof(instructions_char[0]); j++) {
|
||||
if (strcmp(ins, instructions_char[j]) == 0) {
|
||||
return (INSTRUCTION)j;
|
||||
}
|
||||
}
|
||||
|
||||
*args_start_pos = -1;
|
||||
return ERROR_INSTRUCTION;
|
||||
strcpy_s(*ins, strlen(temp)+1,temp);
|
||||
return;
|
||||
}
|
||||
|
||||
void get_args(char* line, int args_start_pos) {
|
||||
5
src/parser.h
Normal file
5
src/parser.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#define MAX_INS_LENGHT 20
|
||||
|
||||
void get_instruction(char* line, int* args_start_pos, int line_number, char** ins);
|
||||
void get_args(char* line, int args_start_pos);
|
||||
@@ -149,15 +149,14 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="api.c" />
|
||||
<ClCompile Include="get_instruction.c" />
|
||||
<ClCompile Include="parser.c" />
|
||||
<ClCompile Include="instructions.c" />
|
||||
<ClCompile Include="main.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="api.h" />
|
||||
<ClInclude Include="get_instruction.h" />
|
||||
<ClInclude Include="parser.h" />
|
||||
<ClInclude Include="instructions.h" />
|
||||
<ClInclude Include="instruction_set.h" />
|
||||
<ClInclude Include="main.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<ClCompile Include="main.c">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="get_instruction.c">
|
||||
<ClCompile Include="parser.c">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="instructions.c">
|
||||
@@ -28,13 +28,10 @@
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="instruction_set.h">
|
||||
<Filter>Fichiers d%27en-tête</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="main.h">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="get_instruction.h">
|
||||
<ClInclude Include="parser.h">
|
||||
<Filter>Fichiers sources</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="instructions.h">
|
||||
|
||||
Reference in New Issue
Block a user