add: dynamic Windows APIs, blank IAT fix: misc & linux build
This commit is contained in:
97
src/api.c
97
src/api.c
@@ -6,6 +6,7 @@
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "libc.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
extern int dprintf(int stream, const char *format, ...);
|
||||
@@ -17,8 +18,8 @@ void api_put() {
|
||||
|
||||
int f = fstream;
|
||||
#ifdef _WIN32
|
||||
if (f == _fileno(stderr))
|
||||
f = _fileno(stdout);
|
||||
if (f == 2) //stderr (could use _fileno(stderr) but it uses the stdlib)
|
||||
f = 1; //stdout
|
||||
#else
|
||||
if (f == fileno(stderr))
|
||||
f = fileno(stdout);
|
||||
@@ -31,46 +32,68 @@ void api_put() {
|
||||
dprintf(f, "%c", c); //using printf and not write because of the buffer
|
||||
}
|
||||
else {
|
||||
dprintf(f, "%lld", state->STACK[state->STACK_IDX--]);
|
||||
#ifdef _WIN32
|
||||
dprintf(f, "%ld", state->STACK[state->STACK_IDX--]);
|
||||
#else
|
||||
dprintf(f, "%lld", state->STACK[state->STACK_IDX--]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void api_getasynckeystate() {
|
||||
#ifdef _WIN32
|
||||
state->registers->eax = GetAsyncKeyState((int)state->STACK[state->STACK_IDX--]);
|
||||
#else
|
||||
state->STACK_IDX--;
|
||||
state->registers->eax = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void api_virtualalloc() {
|
||||
#ifdef _WIN32
|
||||
long long address = state->STACK[state->STACK_IDX--];
|
||||
long long size = state->STACK[state->STACK_IDX--];
|
||||
long long alloctype = state->STACK[state->STACK_IDX--];
|
||||
long long flprotect = state->STACK[state->STACK_IDX--];
|
||||
state->registers->eax = (long long)VirtualAlloc((LPVOID)address, (SIZE_T)size, (DWORD)alloctype, (DWORD)flprotect);
|
||||
#else
|
||||
state->STACK_IDX -= 4;
|
||||
state->registers->eax = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void api_virtualfree() {
|
||||
#ifdef _WIN32
|
||||
long long address = state->STACK[state->STACK_IDX--];
|
||||
long long size = state->STACK[state->STACK_IDX--];
|
||||
long long freetype = state->STACK[state->STACK_IDX--];
|
||||
state->registers->eax = VirtualFree((LPVOID)address, (SIZE_T)size, (DWORD)freetype);
|
||||
#else
|
||||
state->STACK_IDX -= 3;
|
||||
state->registers->eax = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void api_callrawaddr() {
|
||||
long long address = state->STACK[state->STACK_IDX--];
|
||||
|
||||
((void (*)())address)();
|
||||
}
|
||||
|
||||
// generated APIs here
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef LPVOID(WINAPI *fVirtualAlloc)(LPVOID, DWORD, DWORD, DWORD);
|
||||
#endif
|
||||
void api_VirtualAlloc(void) {
|
||||
#ifdef _WIN32
|
||||
fVirtualAlloc pVirtualAlloc = GetApi(L"kernel32.dll", "VirtualAlloc");
|
||||
long long arg0 = state->STACK[state->STACK_IDX--];
|
||||
long long arg1 = state->STACK[state->STACK_IDX--];
|
||||
long long arg2 = state->STACK[state->STACK_IDX--];
|
||||
long long arg3 = state->STACK[state->STACK_IDX--];
|
||||
state->registers->eax = (long long)pVirtualAlloc((LPVOID)arg0, (DWORD)arg1, (DWORD)arg2, (DWORD)arg3);
|
||||
#else
|
||||
state->STACK_IDX -= 4;
|
||||
state->registers->eax = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef BOOL(WINAPI *fVirtualFree)(LPVOID, DWORD, DWORD);
|
||||
#endif
|
||||
void api_VirtualFree(void) {
|
||||
#ifdef _WIN32
|
||||
fVirtualFree pVirtualFree = GetApi(L"kernel32.dll", "VirtualFree");
|
||||
long long arg0 = state->STACK[state->STACK_IDX--];
|
||||
long long arg1 = state->STACK[state->STACK_IDX--];
|
||||
long long arg2 = state->STACK[state->STACK_IDX--];
|
||||
state->registers->eax = (long long)pVirtualFree((LPVOID)arg0, (DWORD)arg1, (DWORD)arg2);
|
||||
#else
|
||||
state->STACK_IDX -= 3;
|
||||
state->registers->eax = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef SHORT(WINAPI *fGetAsyncKeyState)(int);
|
||||
#endif
|
||||
void api_GetAsyncKeyState(void) {
|
||||
#ifdef _WIN32
|
||||
fGetAsyncKeyState pGetAsyncKeyState = GetApi(L"user32.dll", "GetAsyncKeyState");
|
||||
long long arg0 = state->STACK[state->STACK_IDX--];
|
||||
state->registers->eax = (long long)pGetAsyncKeyState((int)arg0);
|
||||
#else
|
||||
state->STACK_IDX -= 1;
|
||||
state->registers->eax = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
20
src/api.h
20
src/api.h
@@ -2,17 +2,25 @@
|
||||
#include "instructions.h"
|
||||
|
||||
void api_put();
|
||||
void api_getasynckeystate();
|
||||
void api_virtualalloc();
|
||||
void api_virtualfree();
|
||||
void api_callrawaddr();
|
||||
|
||||
// generated APIs here
|
||||
void api_VirtualAlloc();
|
||||
void api_VirtualFree();
|
||||
void api_GetAsyncKeyState();
|
||||
|
||||
//end
|
||||
|
||||
static const command_t api_map[] = {
|
||||
{.command = "put", .fptr = api_put},
|
||||
{.command = "GetAsyncKeyState", .fptr = api_getasynckeystate},
|
||||
{.command = "VirtualAlloc", .fptr = api_virtualalloc},
|
||||
{.command = "VirtualFree", .fptr = api_virtualfree},
|
||||
{.command = "CallRawAddress", .fptr = api_callrawaddr},
|
||||
|
||||
// generated APIs here
|
||||
{.command = "VirtualAlloc", .fptr = api_VirtualAlloc},
|
||||
{.command = "VirtualFree", .fptr = api_VirtualFree},
|
||||
{.command = "GetAsyncKeyState", .fptr = api_GetAsyncKeyState},
|
||||
|
||||
//end
|
||||
|
||||
{.command = NULL, .fptr = NULL}
|
||||
};
|
||||
|
||||
23
src/debug.c
23
src/debug.c
@@ -2,9 +2,11 @@
|
||||
#include "interpreter_states.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "libc.h"
|
||||
#include "debug.h"
|
||||
|
||||
void show_registers() {
|
||||
#ifndef LAIKA
|
||||
printf("--Registers--\n");
|
||||
printf("a1: %-3lld | ", state->registers->a1);
|
||||
printf("a2: %-3lld | ", state->registers->a2);
|
||||
@@ -16,25 +18,31 @@ void show_registers() {
|
||||
printf("a8: %-3lld | ", state->registers->a8);
|
||||
printf("a9: %-3lld\n", state->registers->a9);
|
||||
printf("eax: %-3lld\n\n", state->registers->eax);
|
||||
#endif
|
||||
}
|
||||
|
||||
void show_stack() {
|
||||
#ifndef LAIKA
|
||||
printf("--STACK--\n");
|
||||
printf("Elements: %d\n\n", state->STACK_IDX);
|
||||
for (int i = 0; i < state->STACK_IDX; i++)
|
||||
printf("[%d]: %lld\n", i, state->STACK[state->STACK_IDX]);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void show_labels() {
|
||||
#ifndef LAIKA
|
||||
printf("\n\n-----LABELS-----\n");
|
||||
printf("format:\tlabel|line\n");
|
||||
for (int i = 0; i < state->num_labels; i++)
|
||||
printf("%s|%d\n", state->labels[i], state->labels_values[i]);
|
||||
printf("\n\n-----LABELS-----\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void show_arrays() {
|
||||
#ifndef LAIKA
|
||||
printf("\n\n-----ARRAYS-----\n");
|
||||
for (int i = 0; i < state->num_arrays; i++) {
|
||||
printf("%s: ", state->ARRAYS_NAME[i]);
|
||||
@@ -43,42 +51,52 @@ void show_arrays() {
|
||||
printf("...\n");
|
||||
}
|
||||
printf("\n\n-----ARRAYS-----\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void show_breakpoints(int *bp) {
|
||||
#ifndef LAIKA
|
||||
printf("---Breakpoints---\n");
|
||||
for (int i = 0; bp[i] != 0 && i < 255; i++) {
|
||||
if (bp[i] + 1 == -1) continue; //deleted bp
|
||||
printf("bp line %d\n", bp[i] + 1);
|
||||
}
|
||||
printf("---Breakpoints---\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void show_states() {
|
||||
#ifndef LAIKA
|
||||
printf("\n\n--------PASM STATE--------\n");
|
||||
show_registers();
|
||||
show_labels();
|
||||
show_stack();
|
||||
show_arrays();
|
||||
printf("\n\n--------PASM STATE--------\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void bp_add(int *bp, int line) {
|
||||
#ifndef LAIKA
|
||||
int i = 0;
|
||||
for (i = 0; bp[i] != 0 && bp[i] != -1 && i < 255; i++);
|
||||
bp[i] = line;
|
||||
#endif
|
||||
}
|
||||
|
||||
void bp_rem(int *bp, int line) {
|
||||
#ifndef LAIKA
|
||||
int i = 0;
|
||||
for (i = 0; bp[i] != 0 && i < 255; i++) {
|
||||
if (bp[i] == line)
|
||||
bp[i] = -2;
|
||||
}
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
int add_breakpoint(char *in, int *bp) {
|
||||
#ifndef LAIKA
|
||||
for (int i = 0; i < state->num_labels; i++) {
|
||||
if (strncmp(state->labels[i], in, strlen(in) - 1) == 0) {
|
||||
bp_add(bp, state->labels_values[i] + 1);
|
||||
@@ -92,9 +110,11 @@ int add_breakpoint(char *in, int *bp) {
|
||||
bp_add(bp, line - 1);
|
||||
printf("breakpoint added at line %d.\n", line);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int rem_breakpoint(char *in, int *bp) {
|
||||
#ifndef LAIKA
|
||||
for (int i = 0; i < state->num_labels; i++) {
|
||||
if (strncmp(state->labels[i], in, strlen(in) - 1) == 0) {
|
||||
bp_rem(bp, state->labels_values[i] + 1);
|
||||
@@ -108,9 +128,11 @@ int rem_breakpoint(char *in, int *bp) {
|
||||
bp_rem(bp, line - 1);
|
||||
printf("breakpoint at line %d deleted.\n", line);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void debug_input(char *line) {
|
||||
#ifndef LAIKA
|
||||
static int should_continue = 0;
|
||||
static int breakpoints[256] = {0};
|
||||
|
||||
@@ -179,4 +201,5 @@ void debug_input(char *line) {
|
||||
printf("d [line/label]: deletes a breakpoint on line line/label]\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "libc.h"
|
||||
|
||||
void debug_input(char *line);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "interpreter_states.h"
|
||||
#include "libc.h"
|
||||
|
||||
#define MAX_LINE 2048
|
||||
|
||||
@@ -12,6 +13,7 @@ extern int dprintf(int stream, const char *format, ...);
|
||||
|
||||
size_t line_count = 0;
|
||||
int read_script(const char *filename, char ***buf, size_t *lines) {
|
||||
#ifndef LAIKA
|
||||
FILE *script = fopen(filename, "r");
|
||||
if (script == NULL) {
|
||||
dprintf(fstream, "Could not open %s.\n", filename);
|
||||
@@ -25,11 +27,11 @@ int read_script(const char *filename, char ***buf, size_t *lines) {
|
||||
line[length - 1] = '\0';
|
||||
}
|
||||
#ifdef _WIN32
|
||||
char *line_copy = _strdup(line);
|
||||
char *line_copy = strdup_(line);
|
||||
#else
|
||||
char *line_copy = strdup(line);
|
||||
#endif
|
||||
char **temp = realloc(*buf, (line_count + 1) * sizeof(char*));
|
||||
char **temp = realloc_(*buf, (line_count + 1) * sizeof(char*));
|
||||
if (temp == NULL) {
|
||||
dprintf(fstream, "Error allocating memory.\n");
|
||||
return 1;
|
||||
@@ -44,15 +46,16 @@ int read_script(const char *filename, char ***buf, size_t *lines) {
|
||||
|
||||
*lines = line_count;
|
||||
fclose(script);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_script(char **buf) {
|
||||
void free__script(char **buf) {
|
||||
if (!buf)
|
||||
return;
|
||||
for (size_t i = 0; i < line_count; ++i)
|
||||
if (buf[i])
|
||||
free(buf[i]);
|
||||
free(buf);
|
||||
free_state();
|
||||
free_(buf[i]);
|
||||
free_(buf);
|
||||
free__state();
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
int read_script(const char *filename, char ***buf, size_t *lines);
|
||||
void free_script(char **buf);
|
||||
void free__script(char **buf);
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#include "instructions.h"
|
||||
#include "interpreter_states.h"
|
||||
#include "api.h"
|
||||
#include "libc.h"
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
bool is_array(char* arg) {
|
||||
for (int i = 0; i < state->num_arrays; i++)
|
||||
if (strcmp(state->ARRAYS_NAME[i], arg) == 0)
|
||||
if (strcmp__(state->ARRAYS_NAME[i], arg) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -17,17 +18,17 @@ bool is_reg(char* arg) {
|
||||
++arg;
|
||||
if (is_array(arg))
|
||||
return true;
|
||||
return (strcmp(arg, "eax") == 0) || (((arg[0] == 'a' &&
|
||||
return (strcmp__(arg, "eax") == 0) || (((arg[0] == 'a' &&
|
||||
('1' <= arg[1] && arg[1] <= '9'))) && strlen(arg) == 2);
|
||||
}
|
||||
|
||||
bool is_num(char* arg) {
|
||||
return (atoi(arg) != 0 || (arg[0] == '0' && strlen(arg) == 1));
|
||||
return (strtol_(arg, NULL, 10) != 0 || (arg[0] == '0' && strlen(arg) == 1));
|
||||
}
|
||||
|
||||
bool check_args(s_arguments *args, int num_in_first, int num_args) {
|
||||
int arg_num = strcmp(args->arg2, "") != 0;
|
||||
arg_num += strcmp(args->arg1, "") != 0;
|
||||
int arg_num = strcmp__(args->arg2, "") != 0;
|
||||
arg_num += strcmp__(args->arg1, "") != 0;
|
||||
if (arg_num != num_args) {
|
||||
state->last_check_args_code = WRONG_NUMBER;
|
||||
return false;
|
||||
@@ -50,7 +51,7 @@ long long* get_reg(char* reg_char) {
|
||||
if (reg_char[0] == '&' || reg_char[0] == '*')
|
||||
++reg_char;
|
||||
for (int i = 0; i < state->num_arrays; i++)
|
||||
if (strcmp(state->ARRAYS_NAME[i], reg_char) == 0)
|
||||
if (strcmp__(state->ARRAYS_NAME[i], reg_char) == 0)
|
||||
return (long long *)&state->ARRAYS_VALUES[i];
|
||||
switch (reg_char[1]) {
|
||||
case '1' :
|
||||
@@ -91,9 +92,9 @@ long long get_value(char* arg) {
|
||||
}
|
||||
else {
|
||||
if (strlen(arg) > 2 && arg[0] == '0' && arg[1] == 'x') {
|
||||
ret = strtol(arg, NULL, 16);
|
||||
ret = strtol_(arg, NULL, 16);
|
||||
}
|
||||
ret = atoi(arg);
|
||||
ret = strtol_(arg, NULL, 10);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -103,7 +104,7 @@ const command_t *find_command(const command_t *commands, char *func)
|
||||
if (func == NULL)
|
||||
return NULL;
|
||||
for (int index = 0; commands[index].fptr != NULL; index += 1) {
|
||||
if (strcmp(func, commands[index].command) == 0) {
|
||||
if (strcmp__(func, commands[index].command) == 0) {
|
||||
return &commands[index];
|
||||
}
|
||||
}
|
||||
@@ -151,7 +152,7 @@ void ret() {
|
||||
void jmp() {
|
||||
if (state->RET_STACK_IDX != -1 && !check_ret_stack()) return;
|
||||
|
||||
if (strcmp(state->args->arg1, "return") == 0) {
|
||||
if (strcmp__(state->args->arg1, "return") == 0) {
|
||||
ret();
|
||||
return;
|
||||
}
|
||||
@@ -161,13 +162,13 @@ void jmp() {
|
||||
if (state->labels[i] == NULL) break;
|
||||
if (strlen(state->labels[i]) - 1 != strlen(state->args->arg1))
|
||||
continue;
|
||||
if (strncmp(state->args->arg1, state->labels[i], strlen(state->labels[i]) - 1) == 0) {
|
||||
if (strncmp__(state->args->arg1, state->labels[i], strlen(state->labels[i]) - 1) == 0) {
|
||||
state->RET_STACK[++state->RET_STACK_IDX] = state->curr_line;
|
||||
state->curr_line = state->labels_values[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
int line_off = atoi(state->args->arg1);
|
||||
int line_off = strtol_(state->args->arg1, NULL, 10);
|
||||
if (line_off) {
|
||||
state->curr_line += line_off;
|
||||
return;
|
||||
@@ -222,7 +223,9 @@ void _sqrt() {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef LAIKA //Realistically Laika won't ever need sqrt, + that creates linker errors with the CRT
|
||||
*get_reg(state->args->arg1) = (long long)sqrt(get_value(state->args->arg1));
|
||||
#endif
|
||||
}
|
||||
|
||||
void neg() {
|
||||
@@ -238,7 +241,30 @@ void mul() {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef LAIKA
|
||||
//MSVC wants to link __allmul, but a mul is just a lot of add, isn't it ?
|
||||
|
||||
long long v1 = *get_reg(state->args->arg1);
|
||||
long long v2 = get_value(state->args->arg2);
|
||||
long long result = 0;
|
||||
int isNegative = 0;
|
||||
|
||||
if (v1 < 0) {
|
||||
v1 = -v1;
|
||||
isNegative = !isNegative;
|
||||
}
|
||||
if (v2 < 0) {
|
||||
v2 = -v2;
|
||||
isNegative = !isNegative;
|
||||
}
|
||||
while (v2 > 0) {
|
||||
result += v1;
|
||||
v2--;
|
||||
}
|
||||
v1 = isNegative ? -result : result;
|
||||
#else
|
||||
*get_reg(state->args->arg1) *= get_value(state->args->arg2);
|
||||
#endif
|
||||
}
|
||||
|
||||
void _div() {
|
||||
@@ -246,7 +272,32 @@ void _div() {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef LAIKA
|
||||
//MSVC wants to link __alldiv, but a div is just a lot of sub, isn't it ?
|
||||
|
||||
long long dividend = *get_reg(state->args->arg1);
|
||||
long long divisor = get_value(state->args->arg2);
|
||||
|
||||
long long quotient = 0;
|
||||
long long sign = 1;
|
||||
|
||||
if (dividend < 0) {
|
||||
dividend = -dividend;
|
||||
sign = -sign;
|
||||
}
|
||||
if (divisor < 0) {
|
||||
divisor = -divisor;
|
||||
sign = -sign;
|
||||
}
|
||||
while (dividend >= divisor) {
|
||||
dividend -= divisor;
|
||||
quotient++;
|
||||
}
|
||||
|
||||
dividend = sign * quotient;
|
||||
#else
|
||||
*get_reg(state->args->arg1) /= get_value(state->args->arg2);
|
||||
#endif
|
||||
}
|
||||
|
||||
void mov() {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "interpreter_states.h"
|
||||
#include "libc.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -9,42 +10,42 @@ extern int dprintf(int stream, const char *format, ...);
|
||||
|
||||
s_state *state = NULL;
|
||||
int init_state() {
|
||||
state = malloc(sizeof(s_state));
|
||||
state = malloc_(sizeof(s_state));
|
||||
if (state == NULL)
|
||||
return 1;
|
||||
memset(state, 0, sizeof(s_state));
|
||||
state->registers = malloc(sizeof(s_registers));
|
||||
memset__(state, 0, sizeof(s_state));
|
||||
state->registers = malloc_(sizeof(s_registers));
|
||||
if (state->registers == NULL) {
|
||||
free(state);
|
||||
free_(state);
|
||||
return 1;
|
||||
}
|
||||
memset(state->registers, 0, sizeof(s_registers));
|
||||
state->args = malloc(sizeof(s_arguments));
|
||||
memset__(state->registers, 0, sizeof(s_registers));
|
||||
state->args = malloc_(sizeof(s_arguments));
|
||||
if (state->args == NULL) {
|
||||
free(state->registers);
|
||||
free(state);
|
||||
free_(state->registers);
|
||||
free_(state);
|
||||
return 1;
|
||||
}
|
||||
state->args->arg1 = malloc(sizeof(char) * MAX_ARG_SIZE);
|
||||
state->args->arg2 = malloc(sizeof(char) * MAX_ARG_SIZE);
|
||||
state->args->arg1 = malloc_(sizeof(char) * MAX_ARG_SIZE);
|
||||
state->args->arg2 = malloc_(sizeof(char) * MAX_ARG_SIZE);
|
||||
if (state->args->arg1 == NULL || state->args->arg2 == NULL) {
|
||||
free(state->registers);
|
||||
free(state);
|
||||
free_(state->registers);
|
||||
free_(state);
|
||||
return 1;
|
||||
}
|
||||
memset(state->args->arg1, 0, sizeof(char) * MAX_ARG_SIZE);
|
||||
memset(state->args->arg2, 0, sizeof(char) * MAX_ARG_SIZE);
|
||||
state->labels_values = malloc(sizeof(int) * MAX_LABELS);
|
||||
memset__(state->args->arg1, 0, sizeof(char) * MAX_ARG_SIZE);
|
||||
memset__(state->args->arg2, 0, sizeof(char) * MAX_ARG_SIZE);
|
||||
state->labels_values = malloc_(sizeof(int) * MAX_LABELS);
|
||||
if (state->labels_values == NULL) {
|
||||
free(state->registers);
|
||||
free(state->args->arg1);
|
||||
free(state->args->arg2);
|
||||
free(state);
|
||||
free_(state->registers);
|
||||
free_(state->args->arg1);
|
||||
free_(state->args->arg2);
|
||||
free_(state);
|
||||
return 1;
|
||||
}
|
||||
memset(state->labels_values, 0, sizeof(int) * MAX_LABELS);
|
||||
memset(state->RET_STACK, -1, sizeof(int) * STACK_SIZE);
|
||||
memset(state->STACK, 0, sizeof(long long) * STACK_SIZE);
|
||||
memset__(state->labels_values, 0, sizeof(int) * MAX_LABELS);
|
||||
memset__(state->RET_STACK, -1, sizeof(int) * STACK_SIZE);
|
||||
memset__(state->STACK, 0, sizeof(long long) * STACK_SIZE);
|
||||
state->num_arrays = 0;
|
||||
state->RET_STACK_IDX = -1;
|
||||
state->STACK_IDX = -1;
|
||||
@@ -54,28 +55,28 @@ int init_state() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void free_state() {
|
||||
void free__state() {
|
||||
for (int i = 0; i < state->num_labels; i++) {
|
||||
if (state->labels[i])
|
||||
free(state->labels[i]);
|
||||
free_(state->labels[i]);
|
||||
}
|
||||
free(state->labels);
|
||||
free(state->labels_values);
|
||||
free_(state->labels);
|
||||
free_(state->labels_values);
|
||||
|
||||
for (int j = 0; j < state->num_arrays; j++) {
|
||||
if (state->ARRAYS_NAME[j])
|
||||
free(state->ARRAYS_NAME[j]);
|
||||
free_(state->ARRAYS_NAME[j]);
|
||||
if (state->ARRAYS_VALUES[j])
|
||||
free(state->ARRAYS_VALUES[j]);
|
||||
free_(state->ARRAYS_VALUES[j]);
|
||||
}
|
||||
free(state->ARRAYS_NAME);
|
||||
free(state->ARRAYS_VALUES);
|
||||
free(state->registers);
|
||||
free(state->args->arg1);
|
||||
free(state->args->arg2);
|
||||
free(state->args);
|
||||
free_(state->ARRAYS_NAME);
|
||||
free_(state->ARRAYS_VALUES);
|
||||
free_(state->registers);
|
||||
free_(state->args->arg1);
|
||||
free_(state->args->arg2);
|
||||
free_(state->args);
|
||||
|
||||
free(state);
|
||||
free_(state);
|
||||
}
|
||||
|
||||
void set_exit_state(int exit_state) {
|
||||
@@ -93,11 +94,11 @@ LABEL_ERR add_label(char *label, int line) {
|
||||
return LABEL_MAX;
|
||||
|
||||
for (int i = 0; i < state->num_labels; i++)
|
||||
if (strcmp(label, state->labels[i]) == 0)
|
||||
if (strcmp__(label, state->labels[i]) == 0)
|
||||
return LABEL_ALREADY_EXISTS;
|
||||
|
||||
#ifdef _WIN32
|
||||
char *line_copy = _strdup(label);
|
||||
char *line_copy = strdup_(label);
|
||||
#else
|
||||
char *line_copy = strdup(label);
|
||||
#endif
|
||||
@@ -105,7 +106,7 @@ LABEL_ERR add_label(char *label, int line) {
|
||||
dprintf(fstream, "Error allocating memory.\n");
|
||||
return LABEL_ERROR;
|
||||
}
|
||||
char **temp = realloc(state->labels, (state->num_labels + 1) * sizeof(char*));
|
||||
char **temp = realloc_(state->labels, (state->num_labels + 1) * sizeof(char*));
|
||||
if (temp == NULL) {
|
||||
dprintf(fstream, "Error allocating memory.\n");
|
||||
return LABEL_ERROR;
|
||||
@@ -118,35 +119,35 @@ LABEL_ERR add_label(char *label, int line) {
|
||||
|
||||
ARRAY_ERR add_array(char* line) {
|
||||
#ifdef _WIN32
|
||||
char *line_copy = _strdup(line);
|
||||
char *line_copy = strdup_(line);
|
||||
#else
|
||||
char *line_copy = strdup(line);
|
||||
#endif
|
||||
if (strncmp(line, "set", 3) != 0) {
|
||||
free(line_copy);
|
||||
if (strncmp__(line, "set", 3) != 0) {
|
||||
free_(line_copy);
|
||||
return ARRAY_NOT_AN_ARRAY;
|
||||
}
|
||||
char *ptr = strtok(line_copy, " "); //set
|
||||
ptr = strtok(NULL, " "); //array name
|
||||
char *ptr = strtok_(line_copy, " "); //set
|
||||
ptr = strtok_(NULL, " "); //array name
|
||||
if (ptr == NULL || strlen(line) <= (4 + strlen(ptr))) {
|
||||
free(line_copy);
|
||||
free_(line_copy);
|
||||
return ARRAY_ERROR;
|
||||
}
|
||||
|
||||
char **temp = realloc(state->ARRAYS_NAME, (state->num_arrays + 1) * sizeof(char*));
|
||||
char **temp = realloc_(state->ARRAYS_NAME, (state->num_arrays + 1) * sizeof(char*));
|
||||
if (temp == NULL) {
|
||||
dprintf(fstream, "Error allocating memory.\n");
|
||||
return ARRAY_ERROR;
|
||||
}
|
||||
state->ARRAYS_NAME = temp;
|
||||
#ifdef _WIN32
|
||||
state->ARRAYS_NAME[state->num_arrays] = _strdup(ptr);
|
||||
state->ARRAYS_NAME[state->num_arrays] = strdup_(ptr);
|
||||
#else
|
||||
state->ARRAYS_NAME[state->num_arrays] = strdup(ptr);
|
||||
#endif
|
||||
ptr += strlen(ptr) + 1; //getting the data in the array, data is data after all
|
||||
if (ptr == NULL || ptr[0] == ' ' || ptr[0] == '\0') {
|
||||
free(line_copy);
|
||||
free_(line_copy);
|
||||
return ARRAY_ERROR;
|
||||
}
|
||||
|
||||
@@ -157,19 +158,19 @@ ARRAY_ERR add_array(char* line) {
|
||||
++ptr;
|
||||
while (*ptr++ != '"') {
|
||||
if (*ptr == '\0') {
|
||||
free(line_copy);
|
||||
free_(line_copy);
|
||||
return ARRAY_ERROR; //" is never closed
|
||||
}
|
||||
++array_size;
|
||||
}
|
||||
long long *tmp = realloc(arr, array_size * sizeof(long long));
|
||||
long long *tmp = realloc_(arr, array_size * sizeof(long long));
|
||||
if (tmp == NULL || array_size == 0) {
|
||||
dprintf(fstream, "Error allocating memory.\n");
|
||||
return ARRAY_ERROR;
|
||||
}
|
||||
arr = tmp;
|
||||
memset(arr, 0, array_size);
|
||||
long long **temp = realloc(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*));
|
||||
memset__(arr, 0, array_size);
|
||||
long long **temp = realloc_(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*));
|
||||
if (temp == NULL) {
|
||||
dprintf(fstream, "Error allocating memory.\n");
|
||||
return ARRAY_ERROR;
|
||||
@@ -180,10 +181,10 @@ ARRAY_ERR add_array(char* line) {
|
||||
++ptr;
|
||||
while (*ptr != '"') {
|
||||
if (*ptr == '\0' || i >= array_size) {
|
||||
free(line_copy);
|
||||
free_(line_copy);
|
||||
return ARRAY_ERROR; //" is never closed
|
||||
}
|
||||
if (strncmp(ptr, "\\0", 2) == 0) {
|
||||
if (strncmp__(ptr, "\\0", 2) == 0) {
|
||||
arr[i++] = 0;
|
||||
break;
|
||||
}
|
||||
@@ -192,58 +193,58 @@ ARRAY_ERR add_array(char* line) {
|
||||
state->ARRAYS_VALUES[state->num_arrays++] = arr;
|
||||
return ARRAY_OK;
|
||||
}
|
||||
ptr = strtok(ptr, ",");
|
||||
ptr = strtok_(ptr, ",");
|
||||
while (ptr != NULL) {
|
||||
array_size++;
|
||||
ptr = strtok(NULL, ",");
|
||||
ptr = strtok_(NULL, ",");
|
||||
}
|
||||
long long *tmp2 = realloc(arr, array_size * sizeof(long long));
|
||||
long long *tmp2 = realloc_(arr, array_size * sizeof(long long));
|
||||
if (tmp2 == NULL || array_size == 0) {
|
||||
dprintf(fstream, "Error allocating memory.\n");
|
||||
return ARRAY_ERROR;
|
||||
}
|
||||
arr = tmp2;
|
||||
memset(arr, 0, array_size);
|
||||
long long **temp2 = realloc(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*));
|
||||
memset__(arr, 0, array_size);
|
||||
long long **temp2 = realloc_(state->ARRAYS_VALUES, (state->num_arrays + 1) * sizeof(long long*));
|
||||
if (temp2 == NULL) {
|
||||
dprintf(fstream, "Error allocating memory.\n");
|
||||
return ARRAY_ERROR;
|
||||
}
|
||||
state->ARRAYS_VALUES = temp2;
|
||||
ptr = line + 4 + strlen(state->ARRAYS_NAME[state->num_arrays]) + 1; //leave me alone i'm tired
|
||||
ptr = strtok(ptr, ",");
|
||||
ptr = strtok_(ptr, ",");
|
||||
int j = 0;
|
||||
while (ptr != NULL && j < array_size) {
|
||||
if (ptr[0] == ' ')
|
||||
++ptr;
|
||||
if (strlen(ptr) > 2 && ptr[0] == '0' && ptr[1] == 'x') {
|
||||
arr[j++] = strtol(ptr, NULL, 16);
|
||||
arr[j++] = strtol_(ptr, NULL, 16);
|
||||
}
|
||||
else {
|
||||
arr[j++] = atoi(ptr);
|
||||
arr[j++] = strtol_(ptr, NULL, 10);
|
||||
}
|
||||
ptr = strtok(NULL, ",");
|
||||
ptr = strtok_(NULL, ",");
|
||||
}
|
||||
state->ARRAYS_VALUES[state->num_arrays++] = arr;
|
||||
free(line_copy);
|
||||
free_(line_copy);
|
||||
return ARRAY_OK;
|
||||
}
|
||||
|
||||
char *extract_arg(char *ptr, int a) {
|
||||
char *arg = 0;
|
||||
char *ptr2 = strstr(ptr, ";");
|
||||
char *ptr2 = strstr__(ptr, ";");
|
||||
if (ptr2)
|
||||
ptr2[0] = '\0';
|
||||
if (a == 0) {
|
||||
arg = strtok(ptr, ",");
|
||||
arg = strtok_(ptr, ",");
|
||||
} else {
|
||||
arg = strtok(NULL, ",");
|
||||
arg = strtok_(NULL, ",");
|
||||
}
|
||||
if (arg == NULL)
|
||||
return NULL;
|
||||
if (arg[0] == ' ')
|
||||
arg++;
|
||||
ptr2 = strstr(arg, " ");
|
||||
ptr2 = strstr__(arg, " ");
|
||||
if (ptr2)
|
||||
ptr2[0] = '\0';
|
||||
return arg;
|
||||
@@ -267,26 +268,26 @@ int parse_arguments(char *line) {
|
||||
strcpy(state->args->arg2, "");
|
||||
|
||||
#ifdef _WIN32
|
||||
char *line_cpy = _strdup(line);
|
||||
char *line_cpy = strdup_(line);
|
||||
#else
|
||||
char *line_cpy = strdup(line);
|
||||
#endif
|
||||
char *ptr = strstr(line_cpy, " ");
|
||||
char *ptr = strstr__(line_cpy, " ");
|
||||
char *arg = 0;
|
||||
if (!ptr) {
|
||||
free(line_cpy);
|
||||
free_(line_cpy);
|
||||
return 0;
|
||||
}
|
||||
if ((arg = extract_arg(ptr, 0)) == NULL) {
|
||||
free(line_cpy);
|
||||
free_(line_cpy);
|
||||
return 0;
|
||||
}
|
||||
strcpy(state->args->arg1, arg);
|
||||
if ((arg = extract_arg(ptr, 1)) == NULL) {
|
||||
free(line_cpy);
|
||||
free_(line_cpy);
|
||||
return 0;
|
||||
}
|
||||
strcpy(state->args->arg2, arg);
|
||||
free(line_cpy);
|
||||
free_(line_cpy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ typedef enum E_ARRAY_ERR {
|
||||
} ARRAY_ERR;
|
||||
|
||||
int init_state();
|
||||
void free_state();
|
||||
void free__state();
|
||||
void set_exit_state(int exit_state);
|
||||
int get_exit_state();
|
||||
LABEL_ERR add_label(char *label, int line);
|
||||
|
||||
437
src/libc.c
Normal file
437
src/libc.c
Normal file
@@ -0,0 +1,437 @@
|
||||
#include "libc.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE _crt_heap_ = 0;
|
||||
|
||||
#include <winternl.h>
|
||||
#ifdef _M_X64
|
||||
#define GetTEB() ((PTEB)__readgsqword(FIELD_OFFSET(NT_TIB, Self)))
|
||||
#else
|
||||
#define GetTEB() ((PTEB)__readfsdword(FIELD_OFFSET(NT_TIB, Self)))
|
||||
#endif
|
||||
|
||||
typedef LPVOID(WINAPI* fHeapAlloc)(HANDLE, DWORD, SIZE_T);
|
||||
typedef BOOL(WINAPI* fHeapFree)(HANDLE, DWORD, LPVOID);
|
||||
typedef HANDLE(WINAPI* fHeapCreate)(DWORD, SIZE_T, SIZE_T);
|
||||
typedef LPVOID(WINAPI* fHeapReAlloc)(HANDLE, DWORD, LPVOID, SIZE_T);
|
||||
typedef NTSTATUS(NTAPI* fRtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString);
|
||||
typedef NTSTATUS(NTAPI* fLdrLoadDll)(PWCHAR, ULONG, PUNICODE_STRING, PHANDLE);
|
||||
typedef HMODULE(WINAPI* fLoadLibraryW)(LPCWSTR);
|
||||
typedef FARPROC(WINAPI* fGetProcAddress)(HMODULE, LPCSTR);
|
||||
|
||||
fGetProcAddress pGetProcAddress = NULL;
|
||||
fLoadLibraryW pLoadLibraryW = NULL;
|
||||
|
||||
fHeapAlloc pHeapAlloc = NULL;
|
||||
fHeapFree pHeapFree = NULL;
|
||||
fHeapCreate pHeapCreate = NULL;
|
||||
fHeapReAlloc pHeapReAlloc = NULL;
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#define IS_LOW(c) ((c >= 'a' && c <= 'z') ? (1) : (0))
|
||||
#define IS_UP(c) ((c >= 'A' && c <= 'Z') ? (1) : (0))
|
||||
#define IS_ALPHA(c) ((IS_LOW(c) || IS_UP(c)) ? (1) : (0))
|
||||
#define IS_NUM(c) ((c >= '0' && c <= '9') ? (1) : (0))
|
||||
#define IS_SPACE(c) (c == ' ')
|
||||
|
||||
void* malloc_(size_t _Size) {
|
||||
#ifndef _WIN32
|
||||
return malloc(_Size);
|
||||
#else
|
||||
if (_crt_heap_ == 0) {
|
||||
if (pHeapCreate == NULL) {
|
||||
pHeapCreate = GetApi(L"KERNEL32.DLL", "HeapCreate");
|
||||
}
|
||||
_crt_heap_ = pHeapCreate(0, 0, 0);
|
||||
}
|
||||
|
||||
if (pHeapAlloc == NULL) {
|
||||
pHeapAlloc = GetApi(L"KERNEL32.DLL", "HeapAlloc");
|
||||
}
|
||||
return pHeapAlloc(_crt_heap_, HEAP_ZERO_MEMORY, _Size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void free_(void* _Block) {
|
||||
#ifndef _WIN32
|
||||
free(_Block);
|
||||
return;
|
||||
#else
|
||||
if (pHeapFree == NULL) {
|
||||
pHeapFree = GetApi(L"KERNEL32.DLL", "HeapFree");
|
||||
}
|
||||
pHeapFree(_crt_heap_, 0, _Block);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
void* realloc_(void* _Block, size_t _Size) {
|
||||
#ifndef _WIN32
|
||||
return realloc(_Block, _Size);
|
||||
#else
|
||||
if (_crt_heap_ == 0) {
|
||||
if (pHeapCreate == NULL) {
|
||||
pHeapCreate = GetApi(L"KERNEL32.DLL", "HeapCreate");
|
||||
}
|
||||
_crt_heap_ = pHeapCreate(0, 0, 0);
|
||||
}
|
||||
if (_Block == NULL) {
|
||||
if (pHeapAlloc == NULL) {
|
||||
pHeapAlloc = GetApi(L"KERNEL32.DLL", "HeapAlloc");
|
||||
}
|
||||
return pHeapAlloc(_crt_heap_, HEAP_ZERO_MEMORY, _Size);
|
||||
}
|
||||
if (pHeapReAlloc == NULL) {
|
||||
pHeapReAlloc = GetApi(L"KERNEL32.DLL", "HeapReAlloc");
|
||||
}
|
||||
return pHeapReAlloc(_crt_heap_, HEAP_ZERO_MEMORY, _Block, _Size);
|
||||
#endif
|
||||
}
|
||||
|
||||
int strlen__(char const* str)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if (!str)
|
||||
return 1;
|
||||
for (int i = 0; str[i] != '\0'; i += 1) {
|
||||
len += 1;
|
||||
}
|
||||
return (len);
|
||||
}
|
||||
|
||||
char* strcpy__(char* dest, char const* src)
|
||||
{
|
||||
int len = strlen__(src);
|
||||
|
||||
for (int i = 0; src[i] != '\0'; i += 1) {
|
||||
dest[i] = src[i];
|
||||
}
|
||||
dest[len] = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
char* strdup_(char const* src)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return strdup(src);
|
||||
#endif
|
||||
char* dup;
|
||||
int src_len;
|
||||
|
||||
if (src == NULL)
|
||||
return NULL;
|
||||
src_len = strlen__(src);
|
||||
dup = malloc_(sizeof(char) * (src_len + 1));
|
||||
strcpy__(dup, src);
|
||||
return (dup);
|
||||
}
|
||||
|
||||
int strncmp__(char const* s1, char const* s2, int n)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return strncmp(s1, s2, n);
|
||||
#endif
|
||||
for (int i = 0; i < n; i += 1) {
|
||||
if (s1[i] == '\0' || s2[i] == '\0') {
|
||||
return (s1[i] - s2[i]);
|
||||
}
|
||||
if (s1[i] == s2[i]) {
|
||||
continue;
|
||||
}
|
||||
return (s1[i] - s2[i]);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int strcmp__(char const* s1, char const* s2)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return strcmp(s1, s2);
|
||||
#endif
|
||||
int max_len;
|
||||
|
||||
if (strlen__(s1) > strlen__(s2)) {
|
||||
max_len = strlen__(s1);
|
||||
}
|
||||
else {
|
||||
max_len = strlen__(s2);
|
||||
}
|
||||
for (int i = 0; i < max_len; i += 1) {
|
||||
if (s1[i] == s2[i]) {
|
||||
continue;
|
||||
}
|
||||
return (s1[i] - s2[i]);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
char* strstr__(char* str, char const* to_find)
|
||||
{
|
||||
#ifndef WIN32
|
||||
return strstr(str, to_find);
|
||||
#endif
|
||||
int len_str = strlen__(str);
|
||||
int len_str_to_find = strlen__(to_find);
|
||||
|
||||
if (strlen__(to_find) == 0) {
|
||||
return (str);
|
||||
}
|
||||
for (int i = 0; i < len_str - len_str_to_find + 1; i += 1) {
|
||||
if (strncmp__(&str[i], to_find, strlen__(to_find)) == 0) {
|
||||
return (&str[i]);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
//https://github.com/gcc-mirror/gcc/blob/master/libiberty/strtol.c
|
||||
long strtol_(const char* nptr, char** endptr, register int base)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return strtol(nptr, endptr, base);
|
||||
#endif
|
||||
register const char* s = nptr;
|
||||
register unsigned long acc;
|
||||
register int c;
|
||||
register unsigned long cutoff;
|
||||
register int neg = 0, any, cutlim;
|
||||
|
||||
/*
|
||||
* Skip white space and pick up leading +/- sign if any.
|
||||
* If base is 0, allow 0x for hex and 0 for octal, else
|
||||
* assume decimal; if base is already 16, allow 0x.
|
||||
*/
|
||||
do {
|
||||
c = *s++;
|
||||
} while (IS_SPACE(c));
|
||||
if (c == '-') {
|
||||
neg = 1;
|
||||
c = *s++;
|
||||
}
|
||||
else if (c == '+')
|
||||
c = *s++;
|
||||
if ((base == 0 || base == 16) &&
|
||||
c == '0' && (*s == 'x' || *s == 'X')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
|
||||
/*
|
||||
* Compute the cutoff value between legal numbers and illegal
|
||||
* numbers. That is the largest legal value, divided by the
|
||||
* base. An input number that is greater than this value, if
|
||||
* followed by a legal input character, is too big. One that
|
||||
* is equal to this value may be valid or not; the limit
|
||||
* between valid and invalid numbers is then based on the last
|
||||
* digit. For instance, if the range for longs is
|
||||
* [-2147483648..2147483647] and the input base is 10,
|
||||
* cutoff will be set to 214748364 and cutlim to either
|
||||
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
|
||||
* a value > 214748364, or equal but the next digit is > 7 (or 8),
|
||||
* the number is too big, and we will return a range error.
|
||||
*
|
||||
* Set any if any `digits' consumed; make it negative to indicate
|
||||
* overflow.
|
||||
*/
|
||||
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
|
||||
cutlim = cutoff % (unsigned long)base;
|
||||
cutoff /= (unsigned long)base;
|
||||
for (acc = 0, any = 0;; c = *s++) {
|
||||
if (IS_NUM(c))
|
||||
c -= '0';
|
||||
else if (IS_ALPHA(c))
|
||||
c -= IS_UP(c) ? 'A' - 10 : 'a' - 10;
|
||||
else
|
||||
break;
|
||||
if (c >= base)
|
||||
break;
|
||||
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
|
||||
any = -1;
|
||||
else {
|
||||
any = 1;
|
||||
acc *= base;
|
||||
acc += c;
|
||||
}
|
||||
}
|
||||
if (any < 0) {
|
||||
acc = neg ? LONG_MIN : LONG_MAX;
|
||||
}
|
||||
else if (neg)
|
||||
acc = -acc;
|
||||
if (endptr != 0)
|
||||
*endptr = (char*)(any ? s - 1 : nptr);
|
||||
return (acc);
|
||||
}
|
||||
|
||||
//https://opensource.apple.com/source/Libc/Libc-167/string.subproj/strtok.c.auto.html
|
||||
char* strtok_(register char *s, register const char* delim)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
return strtok(s, delim);
|
||||
#endif
|
||||
register char* spanp;
|
||||
register int c, sc;
|
||||
char* tok;
|
||||
static char* last;
|
||||
|
||||
|
||||
if (s == NULL && (s = last) == NULL)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Skip (span) leading delimiters (s += strspn(s, delim), sort of).
|
||||
*/
|
||||
cont:
|
||||
c = *s++;
|
||||
for (spanp = (char*)delim; (sc = *spanp++) != 0;) {
|
||||
if (c == sc)
|
||||
goto cont;
|
||||
}
|
||||
|
||||
if (c == 0) { /* no non-delimiter characters */
|
||||
last = NULL;
|
||||
return (NULL);
|
||||
}
|
||||
tok = s - 1;
|
||||
|
||||
/*
|
||||
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
|
||||
* Note that delim must have one NUL; we stop if we see that, too.
|
||||
*/
|
||||
for (;;) {
|
||||
c = *s++;
|
||||
spanp = (char*)delim;
|
||||
do {
|
||||
if ((sc = *spanp++) == c) {
|
||||
if (c == 0)
|
||||
s = NULL;
|
||||
else
|
||||
s[-1] = 0;
|
||||
last = s;
|
||||
return (tok);
|
||||
}
|
||||
} while (sc != 0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma optimize("", off)
|
||||
#endif
|
||||
void* memset__(void* a, int val, size_t size) {
|
||||
#ifndef _WIN32
|
||||
return memset(a, val, size);
|
||||
#endif
|
||||
if (a == NULL)
|
||||
return NULL;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
((char*)a)[i] = (char)val;
|
||||
return a;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
#pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
wchar_t tolower_wchar(wchar_t wc) {
|
||||
if (wc >= L'A' && wc <= L'Z') {
|
||||
return wc + (L'a' - L'A');
|
||||
}
|
||||
return wc;
|
||||
}
|
||||
|
||||
wchar_t* wcsstr__(const wchar_t* haystack, const wchar_t* needle) {
|
||||
if (!*needle)
|
||||
return (wchar_t*)haystack;
|
||||
while (*haystack) {
|
||||
const wchar_t* h = haystack;
|
||||
const wchar_t* n = needle;
|
||||
|
||||
while (*h && *n && (tolower_wchar(*h) == tolower_wchar(*n))) {
|
||||
h++;
|
||||
n++;
|
||||
}
|
||||
if (!*n)
|
||||
return (wchar_t*)haystack;
|
||||
haystack++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HMODULE get_module(const wchar_t* mod) {
|
||||
PTEB tebPtr = GetTEB();
|
||||
|
||||
PPEB_LDR_DATA ldrData = tebPtr->ProcessEnvironmentBlock->Ldr;
|
||||
PLIST_ENTRY moduleList = &(ldrData->InMemoryOrderModuleList);
|
||||
for (PLIST_ENTRY entry = moduleList->Flink; entry != moduleList; entry = entry->Flink) {
|
||||
LDR_DATA_TABLE_ENTRY* module = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
|
||||
if (wcsstr__(module->FullDllName.Buffer, mod) != NULL) {
|
||||
return (HMODULE)(module->DllBase);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* GetProcAddress_(HMODULE hModule, LPCSTR lpProcName) {
|
||||
if (hModule == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)hModule;
|
||||
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)((BYTE*)hModule + dosHeader->e_lfanew);
|
||||
if (ntHeader->Signature != IMAGE_NT_SIGNATURE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)((BYTE*)hModule + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
DWORD* nameRVAs = (DWORD*)((BYTE*)hModule + exportDir->AddressOfNames);
|
||||
DWORD* addrRVAs = (DWORD*)((BYTE*)hModule + exportDir->AddressOfFunctions);
|
||||
WORD* ordinals = (WORD*)((BYTE*)hModule + exportDir->AddressOfNameOrdinals);
|
||||
|
||||
for (DWORD i = 0; i < exportDir->NumberOfNames; i++) {
|
||||
const char* functionName = (const char*)((BYTE*)hModule + nameRVAs[i]);
|
||||
if (strcmp(functionName, lpProcName) == 0) {
|
||||
DWORD funcRVA = addrRVAs[ordinals[i]];
|
||||
void* funcPtr = (void*)((BYTE*)hModule + funcRVA);
|
||||
return funcPtr;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* GetApi(const wchar_t* module, LPCSTR function) {
|
||||
if (pGetProcAddress == NULL) {
|
||||
HMODULE hKernel32 = NULL;
|
||||
if (pLoadLibraryW == NULL) { //should not happen as Laika loads the required modules at startup
|
||||
HMODULE ntdll = get_module(L"ntdll.dll");
|
||||
fLdrLoadDll ldr = (fLdrLoadDll)GetProcAddress_(ntdll, "LdrLoadDll");
|
||||
fRtlInitUnicodeString r = (fRtlInitUnicodeString)GetProcAddress_(ntdll, "RtlInitUnicodeString");
|
||||
wchar_t* wide = L"kernel32.dll";
|
||||
UNICODE_STRING dll;
|
||||
|
||||
r(&dll, wide);
|
||||
ldr(0, 0, &dll, (PVOID*)&hKernel32);
|
||||
pLoadLibraryW = GetProcAddress_(hKernel32, "LoadLibraryW");
|
||||
}
|
||||
pGetProcAddress = GetProcAddress_(hKernel32, "GetProcAddress");
|
||||
}
|
||||
HMODULE mod = get_module(module);
|
||||
if (mod == NULL) {
|
||||
mod = pLoadLibraryW(module);
|
||||
}
|
||||
return pGetProcAddress(mod, function);
|
||||
}
|
||||
#endif
|
||||
22
src/libc.h
Normal file
22
src/libc.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
extern HANDLE _crt_heap_;
|
||||
|
||||
#endif
|
||||
|
||||
void* malloc_(size_t _Size);
|
||||
void free_(void* _Block);
|
||||
void* realloc_(void* _Block, size_t _Size);
|
||||
char* strdup_(char const* src);
|
||||
int strncmp__(char const* s1, char const* s2, int n);
|
||||
int strcmp__(char const* s1, char const* s2);
|
||||
char* strstr__(char* str, char const* to_find);
|
||||
long strtol_(const char* nptr, char** endptr, register int base);
|
||||
char* strtok_(register char* s, register const char* delim);
|
||||
void* memset__(void* a, int val, size_t size);
|
||||
#ifdef _WIN32
|
||||
void* GetApi(const wchar_t* module, LPCSTR function);
|
||||
#endif
|
||||
103
src/pasm.c
103
src/pasm.c
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "file_utils.h"
|
||||
#include "debug.h"
|
||||
#include "libc.h"
|
||||
#include "interpreter_states.h"
|
||||
#include "instructions.h"
|
||||
|
||||
@@ -10,27 +11,61 @@ int fstream = 0;
|
||||
int pasm_debug_mode = 0;
|
||||
|
||||
#ifdef _WIN32 // i swear i hate windows at this point
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <io.h>
|
||||
#include <winsock.h>
|
||||
|
||||
typedef HANDLE(WINAPI* fGetStdHandle)(DWORD);
|
||||
typedef int(WINAPI* fwvsprintfA)(LPSTR, LPCSTR, va_list);
|
||||
typedef BOOL(WINAPI* fWriteFile)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
|
||||
|
||||
fGetStdHandle pGetStdHandle = NULL;
|
||||
fwvsprintfA pwvsprintfA = NULL;
|
||||
fWriteFile pWriteFile = NULL;
|
||||
|
||||
int dprintf(int stream, const char * format, ...) {
|
||||
char buf[256] = {0}; //might overflow but whatever, fuck Windows
|
||||
char buffer[1024]; //might overflow but whatever, fuck Windows
|
||||
va_list args;
|
||||
DWORD written;
|
||||
int length;
|
||||
va_start(args, format);
|
||||
int wrote = vsprintf(buf, format, args);
|
||||
struct sockaddr name = {0};
|
||||
int len = 0;
|
||||
if (getsockname(stream, &name, &len) != 0) {
|
||||
_write(stream, buf, sizeof(buf));
|
||||
HANDLE h;
|
||||
|
||||
if (pGetStdHandle == NULL)
|
||||
pGetStdHandle = (fGetStdHandle)GetApi(L"KERNEL32.DLL", "GetStdHandle");
|
||||
if (pwvsprintfA == NULL)
|
||||
pwvsprintfA = (fwvsprintfA)GetApi(L"USER32.dll", "wvsprintfA");
|
||||
if (pWriteFile == NULL)
|
||||
pWriteFile = (fWriteFile)GetApi(L"KERNEL32.DLL", "WriteFile");
|
||||
|
||||
switch (stream) {
|
||||
case 1: // stdout
|
||||
h = pGetStdHandle(STD_OUTPUT_HANDLE);
|
||||
break;
|
||||
case 2: // stderr
|
||||
h = pGetStdHandle(STD_ERROR_HANDLE);
|
||||
break;
|
||||
default: // Assume stream is a socket
|
||||
h = (HANDLE)stream;
|
||||
break;
|
||||
}
|
||||
|
||||
length = pwvsprintfA(buffer, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (stream == 1 || stream == 2) {
|
||||
if (!pWriteFile(h, buffer, length, &written, NULL)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
send(stream, buf, sizeof(buf), 0);
|
||||
OVERLAPPED ov = {0};
|
||||
if (!pWriteFile(h, buffer, length, &written, &ov)) {
|
||||
state->should_exit = 1; //broken socket -> host disconnected
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
return wrote;
|
||||
|
||||
return length;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -41,10 +76,21 @@ void show_error(size_t line, char *line_) {
|
||||
int wrote = dprintf(fstream, "%ld| ", line + 1);
|
||||
#endif
|
||||
dprintf(fstream, "%s\n", line_);
|
||||
#ifdef _WIN32
|
||||
// I hate you Windows
|
||||
|
||||
for (int j = 0; j < wrote; j++)
|
||||
dprintf(fstream, " ");
|
||||
dprintf(fstream, "^\n");
|
||||
for (int k = 0; k < wrote; k++)
|
||||
dprintf(fstream, " ");
|
||||
dprintf(fstream, "|\n");
|
||||
#else
|
||||
dprintf(fstream, "%*s\n", wrote + 1, "^");
|
||||
dprintf(fstream, "%*s\n", wrote + 1, "|");
|
||||
#endif
|
||||
for (int i = 0; i < wrote; i++)
|
||||
dprintf(fstream, " ");
|
||||
dprintf(fstream, " ");
|
||||
}
|
||||
|
||||
int check_errors(char *line) {
|
||||
@@ -92,7 +138,7 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea
|
||||
return 1;
|
||||
if (init_state() == 1) {
|
||||
dprintf(fstream, "Failed to initialize the interpreter.\n");
|
||||
free_script(file);
|
||||
free__script(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -101,39 +147,44 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea
|
||||
if (pasm_debug_mode && found_main)
|
||||
debug_input(file[state->curr_line]);
|
||||
#ifdef _WIN32
|
||||
char* line = _strdup(file[state->curr_line]);
|
||||
char* line = strdup_(file[state->curr_line]);
|
||||
#else
|
||||
char *line = strdup(file[state->curr_line]);
|
||||
#endif
|
||||
if (line[0] == ';' || line[0] == '\0' || line[0] == '\t') {
|
||||
free(line);
|
||||
if (line[0] == ';' || line[0] == '\0' || line[0] == '\t' || line[0] == '\r' || line[0] == '\n') {
|
||||
free_(line);
|
||||
continue;
|
||||
}
|
||||
const command_t *com = find_command(command_map, strtok(line, " "));
|
||||
while (file[state->curr_line][strlen(line) - 1] == '\r' || file[state->curr_line][strlen(line) - 1] == '\n') {
|
||||
file[state->curr_line][strlen(line) - 1] = '\0';
|
||||
line[strlen(line) - 1] = '\0';
|
||||
}
|
||||
|
||||
const command_t *com = find_command(command_map, strtok_(line, " "));
|
||||
if (com == NULL || com->fptr == NULL) {
|
||||
ARRAY_ERR err = add_array(file[state->curr_line]);
|
||||
if (err == ARRAY_OK) {
|
||||
free(line);
|
||||
free_(line);
|
||||
continue;
|
||||
}
|
||||
if (err == ARRAY_ERROR) {
|
||||
show_error(state->curr_line, file[state->curr_line]);
|
||||
dprintf(fstream, "%s\n", "bad syntax in array definition");
|
||||
set_exit_state(-1);
|
||||
free(line);
|
||||
free_(line);
|
||||
break;
|
||||
}
|
||||
if (file[state->curr_line][strlen(line) - 1] != ':') {
|
||||
show_error(state->curr_line, file[state->curr_line]);
|
||||
dprintf(fstream, "%s \"%s\"\n", "unknown expression", strtok(file[state->curr_line], " "));
|
||||
dprintf(fstream, "%s \"%s\"\n", "unknown expression", strtok_(file[state->curr_line], " "));
|
||||
set_exit_state(-1);
|
||||
free(line);
|
||||
free_(line);
|
||||
break;
|
||||
}
|
||||
add_label(line, state->curr_line);
|
||||
if (!found_main && strcmp(line, "main:") == 0)
|
||||
if (!found_main && strcmp__(line, "main:") == 0)
|
||||
found_main = 1;
|
||||
free(line);
|
||||
free_(line);
|
||||
continue;
|
||||
}
|
||||
parse_arguments(file[state->curr_line]);
|
||||
@@ -144,10 +195,10 @@ int pasm_run_script(const char *filename, char **file, size_t lines, int _fstrea
|
||||
set_exit_state(-1);
|
||||
break;
|
||||
}
|
||||
free(line);
|
||||
free_(line);
|
||||
}
|
||||
|
||||
int ret_code = get_exit_state();
|
||||
free_script(file);
|
||||
//free__script(file);
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user