mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
added basic read, and an improved HAL
This commit is contained in:
@@ -10,6 +10,8 @@ typedef enum hal_file_code {
|
|||||||
HAL_ERROR_READ, // Error while reading from a file
|
HAL_ERROR_READ, // Error while reading from a file
|
||||||
HAL_ERROR_WRITE, // Error while writing to a file
|
HAL_ERROR_WRITE, // Error while writing to a file
|
||||||
HAL_ERROR_CLOSE, // Error while closing a file
|
HAL_ERROR_CLOSE, // Error while closing a file
|
||||||
|
HAL_ERROR_RENAME, // Error while renaming a file
|
||||||
|
HAL_ERROR_REMOVE, // Error while removing (deleting) a file
|
||||||
HAL_ERROR_TEARDOWN, // Error during teardown
|
HAL_ERROR_TEARDOWN, // Error during teardown
|
||||||
HAL_ERROR_MAX, // Maximum error code value (used for range checking)
|
HAL_ERROR_MAX, // Maximum error code value (used for range checking)
|
||||||
} hal_file_code;
|
} hal_file_code;
|
||||||
@@ -44,6 +46,12 @@ typedef struct hal_file_operations {
|
|||||||
// Returns: HAL_SUCCESS on successful close, or appropriate error code on failure.
|
// Returns: HAL_SUCCESS on successful close, or appropriate error code on failure.
|
||||||
hal_file_code (*close)(hal_file* file);
|
hal_file_code (*close)(hal_file* file);
|
||||||
|
|
||||||
|
|
||||||
|
hal_file_code (*rename)(const char* oldname, const char* newname);
|
||||||
|
|
||||||
|
|
||||||
|
hal_file_code (*remove)(const char* filename);
|
||||||
|
|
||||||
// Function: teardown
|
// Function: teardown
|
||||||
// Perform necessary cleanup and teardown operations for the file handling system.
|
// Perform necessary cleanup and teardown operations for the file handling system.
|
||||||
// Returns: HAL_SUCCESS on successful teardown, or appropriate error code on failure.
|
// Returns: HAL_SUCCESS on successful teardown, or appropriate error code on failure.
|
||||||
25
hal/makefile
Normal file
25
hal/makefile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -Wextra -pedantic
|
||||||
|
|
||||||
|
# Library name and source files
|
||||||
|
LIB_NAME = hal.a
|
||||||
|
SRC_FILES = ports/hal_file.c
|
||||||
|
BUILD_DIR = bin
|
||||||
|
|
||||||
|
# Object files derived from source files
|
||||||
|
OBJ_FILES = $(SRC_FILES:.c=.o)
|
||||||
|
|
||||||
|
# Target: build the library
|
||||||
|
all: $(BUILD_DIR)/$(LIB_NAME)
|
||||||
|
|
||||||
|
# Build the library from object files
|
||||||
|
$(LIB_NAME): $(OBJ_FILES)
|
||||||
|
ar rcs $@ $^
|
||||||
|
|
||||||
|
# Compile from object files
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# Clean up generated files
|
||||||
|
clean:
|
||||||
|
rm -f $(LIB_NAME) $(OBJ_FILES)
|
||||||
@@ -36,6 +36,8 @@ hal_file_code read(hal_file* file, char* buffer, const int size) {
|
|||||||
return HAL_ERROR_INPUT;
|
return HAL_ERROR_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scanf()
|
||||||
|
|
||||||
if (fgets(buffer, size, file->fp) == NULL) {
|
if (fgets(buffer, size, file->fp) == NULL) {
|
||||||
return HAL_ERROR_READ;
|
return HAL_ERROR_READ;
|
||||||
}
|
}
|
||||||
@@ -68,6 +70,31 @@ hal_file_code close(hal_file* file) {
|
|||||||
return HAL_SUCCESS;
|
return HAL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hal_file_code crename(const char* oldname, const char* newname) {
|
||||||
|
if (!oldname || !newname) {
|
||||||
|
return HAL_ERROR_INPUT;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rename(oldname, newname) != 0) {
|
||||||
|
return HAL_ERROR_RENAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HAL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
hal_file_code cremove(const char* filename) {
|
||||||
|
if (!filename) {
|
||||||
|
return HAL_ERROR_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remove(filename) != 0) {
|
||||||
|
return HAL_ERROR_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return HAL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// deletion logic, if needed
|
// deletion logic, if needed
|
||||||
hal_file_code teardown() {
|
hal_file_code teardown() {
|
||||||
return HAL_SUCCESS;
|
return HAL_SUCCESS;
|
||||||
@@ -80,6 +107,8 @@ hal_file_operations hal_file_manager = {
|
|||||||
.read = read,
|
.read = read,
|
||||||
.write = write,
|
.write = write,
|
||||||
.close = close,
|
.close = close,
|
||||||
|
.rename = crename,
|
||||||
|
.remove = cremove,
|
||||||
.teardown = teardown
|
.teardown = teardown
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
#include "lib_fileio.h"
|
#include "lib_fileio.h"
|
||||||
#include "toy_memory.h"
|
#include "toy_memory.h"
|
||||||
|
|
||||||
#include "hal_file.h"
|
#include "../hal/hal_file.h"
|
||||||
|
|
||||||
typedef struct Toy_File
|
typedef struct Toy_File
|
||||||
{
|
{
|
||||||
hal_file* fp;
|
hal_file* fp;
|
||||||
int error;
|
hal_file_code error;
|
||||||
int size;
|
int size;
|
||||||
} Toy_File;
|
} Toy_File;
|
||||||
|
|
||||||
@@ -46,19 +46,16 @@ static int nativeOpen(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
const char* filename = Toy_toCString(TOY_AS_STRING(filenameLiteral));
|
const char* filename = Toy_toCString(TOY_AS_STRING(filenameLiteral));
|
||||||
const char* mode = Toy_toCString(TOY_AS_STRING(modeLiteral));
|
const char* mode = Toy_toCString(TOY_AS_STRING(modeLiteral));
|
||||||
|
|
||||||
static int tag = 0;
|
// build file object
|
||||||
bool error = false;
|
Toy_File* file = TOY_ALLOCATE(Toy_File, 1);
|
||||||
hal_file* fp = NULL;
|
file->error = HAL_SUCCESS;
|
||||||
|
file->fp = NULL;
|
||||||
|
file->size = 0;
|
||||||
|
|
||||||
// attempt to open file
|
// attempt to open file
|
||||||
hal_file_code code = hal_file_manager.open(&fp, filename, mode);
|
file->error = hal_file_manager.open(&file->fp, filename, mode);
|
||||||
if (code != HAL_SUCCESS) {
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set size
|
// set size
|
||||||
int size = 0;
|
|
||||||
|
|
||||||
// if (!error) {
|
// if (!error) {
|
||||||
// fseek(fp, 0, SEEK_END);
|
// fseek(fp, 0, SEEK_END);
|
||||||
|
|
||||||
@@ -69,42 +66,15 @@ static int nativeOpen(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// result
|
// result
|
||||||
Toy_LiteralDictionary* result = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
|
Toy_Literal fileLiteral = TOY_TO_OPAQUE_LITERAL(file, 900);
|
||||||
Toy_initLiteralDictionary(result);
|
|
||||||
|
|
||||||
Toy_Literal fileKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("_file"));
|
Toy_pushLiteralArray(&interpreter->stack, fileLiteral);
|
||||||
Toy_Literal fileLiteral = TOY_TO_OPAQUE_LITERAL(fp, tag);
|
|
||||||
|
|
||||||
Toy_Literal errorKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("error"));
|
|
||||||
Toy_Literal errorLiteral = TOY_TO_BOOLEAN_LITERAL(error);
|
|
||||||
|
|
||||||
Toy_Literal sizeKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("size"));
|
|
||||||
Toy_Literal sizeLiteral = TOY_TO_INTEGER_LITERAL(size);
|
|
||||||
|
|
||||||
Toy_setLiteralDictionary(result, fileKeyLiteral, fileLiteral);
|
|
||||||
Toy_setLiteralDictionary(result, errorKeyLiteral, errorLiteral);
|
|
||||||
Toy_setLiteralDictionary(result, sizeKeyLiteral, sizeLiteral);
|
|
||||||
|
|
||||||
Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString("File"));
|
|
||||||
Toy_Literal resultLiteral = TOY_TO_DICTIONARY_LITERAL(result);
|
|
||||||
|
|
||||||
Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true);
|
|
||||||
Toy_Literal stringType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true);
|
|
||||||
Toy_Literal anyType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_ANY, true);
|
|
||||||
TOY_TYPE_PUSH_SUBTYPE(&type, stringType);
|
|
||||||
TOY_TYPE_PUSH_SUBTYPE(&type, anyType);
|
|
||||||
|
|
||||||
|
|
||||||
Toy_pushLiteralArray(&interpreter->stack, resultLiteral);
|
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
Toy_freeLiteral(type);
|
Toy_freeLiteral(fileLiteral);
|
||||||
Toy_freeLiteral(resultLiteral);
|
|
||||||
Toy_freeLiteral(filenameLiteral);
|
Toy_freeLiteral(filenameLiteral);
|
||||||
Toy_freeLiteral(modeLiteral);
|
Toy_freeLiteral(modeLiteral);
|
||||||
|
|
||||||
tag++;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,6 +105,61 @@ static int nativeClose(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nativeRead(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
|
if (arguments->count != 2) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to read\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Literal valueLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
|
||||||
|
|
||||||
|
// parse the value (if it's an identifier)
|
||||||
|
Toy_Literal valueLiteralIdn = valueLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(valueLiteral) && Toy_parseIdentifierToValue(interpreter, &valueLiteral)) {
|
||||||
|
Toy_freeLiteral(valueLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the value type
|
||||||
|
if (!TOY_IS_TYPE(valueLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to read\n");
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
Toy_freeLiteral(valueLiteral);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the self (if it's an identifier)
|
||||||
|
Toy_Literal selfLiteralIdn = selfLiteral;
|
||||||
|
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
|
||||||
|
Toy_freeLiteral(selfLiteralIdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check self type
|
||||||
|
if (!TOY_IS_OPAQUE(selfLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect argument type passed to read\n");
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
Toy_freeLiteral(valueLiteral);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral);
|
||||||
|
|
||||||
|
char buffer[256] = {0};
|
||||||
|
|
||||||
|
hal_file_manager.read(file->fp, buffer, 256);
|
||||||
|
|
||||||
|
Toy_RefString* result = Toy_createRefStringLength(buffer, 256);
|
||||||
|
|
||||||
|
Toy_pushLiteralArray(&interpreter->stack, TOY_TO_STRING_LITERAL(result));
|
||||||
|
|
||||||
|
Toy_freeLiteral(valueLiteral);
|
||||||
|
Toy_freeLiteral(selfLiteral);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
//call the hook
|
//call the hook
|
||||||
typedef struct Natives {
|
typedef struct Natives {
|
||||||
char* name;
|
char* name;
|
||||||
@@ -196,11 +221,24 @@ int Toy_hookFileIO(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Lit
|
|||||||
{"open", nativeOpen},
|
{"open", nativeOpen},
|
||||||
{"close", nativeClose},
|
{"close", nativeClose},
|
||||||
|
|
||||||
|
//
|
||||||
|
{"read", nativeRead},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// store the library in an aliased dictionary
|
||||||
|
if (!TOY_IS_NULL(alias)) {
|
||||||
|
// make sure the name isn't taken
|
||||||
|
if (Toy_isDeclaredScopeVariable(interpreter->scope, alias)) {
|
||||||
|
interpreter->errorOutput("Can't override an existing variable\n");
|
||||||
|
Toy_freeLiteral(alias);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
//default
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// default
|
||||||
for (int i = 0; natives[i].name; i++) {
|
for (int i = 0; natives[i].name; i++) {
|
||||||
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,17 @@ import fileio;
|
|||||||
|
|
||||||
// test open
|
// test open
|
||||||
{
|
{
|
||||||
var file = open("doesNotExist.txt", "r");
|
var file = open("does", "r");
|
||||||
|
|
||||||
assert file["error"] == true, "error failed";
|
file.read(string);
|
||||||
assert file["size"] == 0, "size failed";
|
|
||||||
|
// TODO:
|
||||||
|
// file.write(12, ",", 12);
|
||||||
|
// file.size();
|
||||||
|
// file.isOpened();
|
||||||
|
// file.error();
|
||||||
|
// file.position();
|
||||||
|
// file.mode();
|
||||||
|
|
||||||
// close(file);
|
// close(file);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user