Better library stuff #7

Merged
max merged 3 commits from unstable into master 2026-01-19 20:01:56 +11:00
5 changed files with 42 additions and 112 deletions
Showing only changes of commit 754b63fb75 - Show all commits

View File

@@ -10,7 +10,7 @@ GroundValue native_file_read(GroundScope* scope, List args) {
char* path = args.values[0].data.stringVal; char* path = args.values[0].data.stringVal;
FILE* f = fopen(path, "r"); FILE* f = fopen(path, "r");
if (!f) { if (!f) {
return groundCreateValue(NONE); ERROR("Failed to open file for reading", "FileError");
} }
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
@@ -20,7 +20,7 @@ GroundValue native_file_read(GroundScope* scope, List args) {
char* content = malloc(fsize + 1); char* content = malloc(fsize + 1);
if (!content) { if (!content) {
fclose(f); fclose(f);
return groundCreateValue(NONE); ERROR("Failed to allocate memory for file reading", "FileError");
} }
fread(content, 1, fsize, f); fread(content, 1, fsize, f);
@@ -42,7 +42,7 @@ GroundValue native_file_write(GroundScope* scope, List args) {
FILE* f = fopen(path, "w"); FILE* f = fopen(path, "w");
if (!f) { if (!f) {
return groundCreateValue(BOOL, 0); ERROR("Failed to open file for writing", "FileError");
} }
fprintf(f, "%s", content); fprintf(f, "%s", content);

View File

@@ -50,21 +50,11 @@ size_t write_callback(void* ptr, size_t size, size_t nmemb, void* userdata) {
// GET request // GET request
GroundValue get_request(GroundScope* scope, List args) { GroundValue get_request(GroundScope* scope, List args) {
if (args.size < 1) {
printf("Requires a URL argument\n");
return groundCreateValue(NONE);
}
if (args.values[0].type != STRING) {
printf("Arg 1 needs to be a string (URL)\n");
return groundCreateValue(NONE);
}
curl_setup(); curl_setup();
CURL* handle = curl_easy_init(); CURL* handle = curl_easy_init();
if (!handle) { if (!handle) {
printf("Curl failed to init\n"); ERROR("CURL failed to init", "GenericRequestError");
return groundCreateValue(NONE);
} }
ResponseBuffer buffer = {0}; ResponseBuffer buffer = {0};
@@ -81,10 +71,9 @@ GroundValue get_request(GroundScope* scope, List args) {
CURLcode result = curl_easy_perform(handle); CURLcode result = curl_easy_perform(handle);
if (result != CURLE_OK) { if (result != CURLE_OK) {
printf("Curl request failed: %s\n", curl_easy_strerror(result)); char buf[256];
free(buffer.data); snprintf(buf, sizeof(buf) - 1, "Curl request failed: %s\n", curl_easy_strerror(result));
curl_easy_cleanup(handle); ERROR(buf, "ActionRequestError");
return groundCreateValue(NONE);
} }
curl_easy_cleanup(handle); curl_easy_cleanup(handle);
@@ -95,21 +84,11 @@ GroundValue get_request(GroundScope* scope, List args) {
// POST request // POST request
GroundValue post_request(GroundScope* scope, List args) { GroundValue post_request(GroundScope* scope, List args) {
if (args.size < 2) {
printf("Requires URL and POST data arguments\n");
return groundCreateValue(NONE);
}
if (args.values[0].type != STRING || args.values[1].type != STRING) {
printf("Both arguments need to be strings (URL, POST data)\n");
return groundCreateValue(NONE);
}
curl_setup(); curl_setup();
CURL* handle = curl_easy_init(); CURL* handle = curl_easy_init();
if (!handle) { if (!handle) {
printf("Curl failed to init\n"); ERROR("CURL failed to init", "GenericRequestError");
return groundCreateValue(NONE);
} }
ResponseBuffer buffer = {0}; ResponseBuffer buffer = {0};
@@ -127,10 +106,11 @@ GroundValue post_request(GroundScope* scope, List args) {
CURLcode result = curl_easy_perform(handle); CURLcode result = curl_easy_perform(handle);
if (result != CURLE_OK) { if (result != CURLE_OK) {
printf("Curl POST request failed: %s\n", curl_easy_strerror(result));
free(buffer.data); free(buffer.data);
char buf[256];
snprintf(buf, sizeof(buf) - 1, "Curl request failed: %s\n", curl_easy_strerror(result));
curl_easy_cleanup(handle); curl_easy_cleanup(handle);
return groundCreateValue(NONE); ERROR(buf, "ActionRequestError");
} }
curl_easy_cleanup(handle); curl_easy_cleanup(handle);
@@ -153,27 +133,16 @@ int find_ws_slot() {
// WebSocket Connect - returns connection ID as INT // WebSocket Connect - returns connection ID as INT
GroundValue ws_connect(GroundScope* scope, List args) { GroundValue ws_connect(GroundScope* scope, List args) {
if (args.size < 1) {
printf("Requires a WebSocket URL argument (ws:// or wss://)\n");
return groundCreateValue(NONE);
}
if (args.values[0].type != STRING) {
printf("Arg 1 needs to be a string (WebSocket URL)\n");
return groundCreateValue(NONE);
}
curl_setup(); curl_setup();
int slot = find_ws_slot(); int slot = find_ws_slot();
if (slot == -1) { if (slot == -1) {
printf("Maximum WebSocket connections reached\n"); ERROR("Maximum WebSocket connections reached", "OverflowError");
return groundCreateValue(NONE);
} }
CURL* handle = curl_easy_init(); CURL* handle = curl_easy_init();
if (!handle) { if (!handle) {
printf("Curl failed to init\n"); ERROR("CURL failed to init", "GenericWSError");
return groundCreateValue(NONE);
} }
curl_easy_setopt(handle, CURLOPT_URL, args.values[0].data.stringVal); curl_easy_setopt(handle, CURLOPT_URL, args.values[0].data.stringVal);
@@ -183,9 +152,10 @@ GroundValue ws_connect(GroundScope* scope, List args) {
CURLcode result = curl_easy_perform(handle); CURLcode result = curl_easy_perform(handle);
if (result != CURLE_OK) { if (result != CURLE_OK) {
printf("WebSocket connection failed: %s\n", curl_easy_strerror(result)); char buf[256];
snprintf(buf, sizeof(buf) - 1, "Curl WebSocket failed: %s\n", curl_easy_strerror(result));
curl_easy_cleanup(handle); curl_easy_cleanup(handle);
return groundCreateValue(NONE); ERROR(buf, "ActionWSError");
} }
ws_connections[slot].handle = handle; ws_connections[slot].handle = handle;
@@ -197,19 +167,9 @@ GroundValue ws_connect(GroundScope* scope, List args) {
// WebSocket Send - sends a text message, returns bytes sent as INT // WebSocket Send - sends a text message, returns bytes sent as INT
GroundValue ws_send(GroundScope* scope, List args) { GroundValue ws_send(GroundScope* scope, List args) {
if (args.size < 2) {
printf("Requires connection ID and message\n");
return groundCreateValue(NONE);
}
if (args.values[0].type != INT || args.values[1].type != STRING) {
printf("Args need to be (INT connection ID, STRING message)\n");
return groundCreateValue(NONE);
}
int conn_id = (int)args.values[0].data.intVal; int conn_id = (int)args.values[0].data.intVal;
if (conn_id < 0 || conn_id >= MAX_WS_CONNECTIONS || !ws_connections[conn_id].connected) { if (conn_id < 0 || conn_id >= MAX_WS_CONNECTIONS || !ws_connections[conn_id].connected) {
printf("Invalid or closed WebSocket connection\n"); ERROR("Invalid WebSocket connection ID", "GenericWSError");
return groundCreateValue(NONE);
} }
CURL* handle = ws_connections[conn_id].handle; CURL* handle = ws_connections[conn_id].handle;
@@ -219,8 +179,9 @@ GroundValue ws_send(GroundScope* scope, List args) {
CURLcode result = curl_ws_send(handle, message, strlen(message), &sent, 0, CURLWS_TEXT); CURLcode result = curl_ws_send(handle, message, strlen(message), &sent, 0, CURLWS_TEXT);
if (result != CURLE_OK) { if (result != CURLE_OK) {
printf("WebSocket send failed: %s\n", curl_easy_strerror(result)); char buf[256];
return groundCreateValue(NONE); snprintf(buf, sizeof(buf) - 1, "WebSocket send failed: %s\n", curl_easy_strerror(result));
ERROR(buf, "ActionWSError");
} }
return groundCreateValue(INT, (int64_t)sent); return groundCreateValue(INT, (int64_t)sent);
@@ -228,19 +189,9 @@ GroundValue ws_send(GroundScope* scope, List args) {
// WebSocket Receive - receives a message (blocking) // WebSocket Receive - receives a message (blocking)
GroundValue ws_receive(GroundScope* scope, List args) { GroundValue ws_receive(GroundScope* scope, List args) {
if (args.size < 1) {
printf("Requires connection ID\n");
return groundCreateValue(NONE);
}
if (args.values[0].type != INT) {
printf("Arg 1 needs to be an INT (connection ID)\n");
return groundCreateValue(NONE);
}
int conn_id = (int)args.values[0].data.intVal; int conn_id = (int)args.values[0].data.intVal;
if (conn_id < 0 || conn_id >= MAX_WS_CONNECTIONS || !ws_connections[conn_id].connected) { if (conn_id < 0 || conn_id >= MAX_WS_CONNECTIONS || !ws_connections[conn_id].connected) {
printf("Invalid or closed WebSocket connection\n"); ERROR("Invalid WebSocket connection ID", "GenericWSError");
return groundCreateValue(NONE);
} }
CURL* handle = ws_connections[conn_id].handle; CURL* handle = ws_connections[conn_id].handle;
@@ -255,8 +206,9 @@ GroundValue ws_receive(GroundScope* scope, List args) {
// No data available right now // No data available right now
return groundCreateValue(STRING, ""); return groundCreateValue(STRING, "");
} }
printf("WebSocket receive failed: %s\n", curl_easy_strerror(result)); char buf[256];
return groundCreateValue(NONE); snprintf(buf, sizeof(buf) - 1, "WebSocket receive failed: %s\n", curl_easy_strerror(result));
ERROR(buf, "ActionWSError");
} }
buffer[received] = '\0'; buffer[received] = '\0';
@@ -283,21 +235,11 @@ GroundValue ws_receive(GroundScope* scope, List args) {
// WebSocket Receive with timeout (non-blocking version) // WebSocket Receive with timeout (non-blocking version)
GroundValue ws_receive_timeout(GroundScope* scope, List args) { GroundValue ws_receive_timeout(GroundScope* scope, List args) {
if (args.size < 2) {
printf("Requires connection ID and timeout in milliseconds\n");
return groundCreateValue(NONE);
}
if (args.values[0].type != INT || args.values[1].type != INT) {
printf("Both arguments need to be INT (connection ID, timeout_ms)\n");
return groundCreateValue(NONE);
}
int conn_id = (int)args.values[0].data.intVal; int conn_id = (int)args.values[0].data.intVal;
long timeout_ms = (long)args.values[1].data.intVal; long timeout_ms = (long)args.values[1].data.intVal;
if (conn_id < 0 || conn_id >= MAX_WS_CONNECTIONS || !ws_connections[conn_id].connected) { if (conn_id < 0 || conn_id >= MAX_WS_CONNECTIONS || !ws_connections[conn_id].connected) {
printf("Invalid or closed WebSocket connection\n"); ERROR("Invalid WebSocket connection ID", "GenericWSError");
return groundCreateValue(NONE);
} }
CURL* handle = ws_connections[conn_id].handle; CURL* handle = ws_connections[conn_id].handle;
@@ -316,8 +258,9 @@ GroundValue ws_receive_timeout(GroundScope* scope, List args) {
} }
if (result != CURLE_OK) { if (result != CURLE_OK) {
printf("WebSocket receive failed: %s\n", curl_easy_strerror(result)); char buf[256];
return groundCreateValue(NONE); snprintf(buf, sizeof(buf) - 1, "WebSocket receive failed: %s\n", curl_easy_strerror(result));
ERROR(buf, "ActionWSError");
} }
buffer[received] = '\0'; buffer[received] = '\0';
@@ -341,19 +284,9 @@ GroundValue ws_receive_timeout(GroundScope* scope, List args) {
// WebSocket Close - properly close a connection, returns BOOL success // WebSocket Close - properly close a connection, returns BOOL success
GroundValue ws_close(GroundScope* scope, List args) { GroundValue ws_close(GroundScope* scope, List args) {
if (args.size < 1) {
printf("Requires connection ID\n");
return groundCreateValue(NONE);
}
if (args.values[0].type != INT) {
printf("Arg 1 needs to be an INT (connection ID)\n");
return groundCreateValue(NONE);
}
int conn_id = (int)args.values[0].data.intVal; int conn_id = (int)args.values[0].data.intVal;
if (conn_id < 0 || conn_id >= MAX_WS_CONNECTIONS || !ws_connections[conn_id].connected) { if (conn_id < 0 || conn_id >= MAX_WS_CONNECTIONS || !ws_connections[conn_id].connected) {
printf("Invalid or already closed WebSocket connection\n"); ERROR("Invalid or already connected websocket", "GenericWSError");
return groundCreateValue(BOOL, false);
} }
CURL* handle = ws_connections[conn_id].handle; CURL* handle = ws_connections[conn_id].handle;
@@ -374,19 +307,9 @@ GroundValue ws_close(GroundScope* scope, List args) {
// WebSocket Send Binary data, returns bytes sent as INT // WebSocket Send Binary data, returns bytes sent as INT
GroundValue ws_send_binary(GroundScope* scope, List args) { GroundValue ws_send_binary(GroundScope* scope, List args) {
if (args.size < 2) {
printf("Requires connection ID and binary data\n");
return groundCreateValue(NONE);
}
if (args.values[0].type != INT || args.values[1].type != STRING) {
printf("Args need to be (INT connection ID, STRING binary data)\n");
return groundCreateValue(NONE);
}
int conn_id = (int)args.values[0].data.intVal; int conn_id = (int)args.values[0].data.intVal;
if (conn_id < 0 || conn_id >= MAX_WS_CONNECTIONS || !ws_connections[conn_id].connected) { if (conn_id < 0 || conn_id >= MAX_WS_CONNECTIONS || !ws_connections[conn_id].connected) {
printf("Invalid or closed WebSocket connection\n"); ERROR("Invalid WebSocket connection ID", "GenericWSError");
return groundCreateValue(NONE);
} }
CURL* handle = ws_connections[conn_id].handle; CURL* handle = ws_connections[conn_id].handle;
@@ -396,8 +319,9 @@ GroundValue ws_send_binary(GroundScope* scope, List args) {
CURLcode result = curl_ws_send(handle, data, strlen(data), &sent, 0, CURLWS_BINARY); CURLcode result = curl_ws_send(handle, data, strlen(data), &sent, 0, CURLWS_BINARY);
if (result != CURLE_OK) { if (result != CURLE_OK) {
printf("WebSocket binary send failed: %s\n", curl_easy_strerror(result)); char buf[256];
return groundCreateValue(NONE); snprintf(buf, sizeof(buf) - 1, "WebSocket binary send failed: %s\n", curl_easy_strerror(result));
ERROR(buf, "ActionWSError");
} }
return groundCreateValue(INT, (int64_t)sent); return groundCreateValue(INT, (int64_t)sent);

View File

@@ -90,7 +90,7 @@ bool isMainScopeGlobal = true;
printGroundInstruction(error->where); printGroundInstruction(error->where);
printf("\n"); printf("\n");
} }
if (error->line > -1) { if (error->hasLine) {
printf(" ErrorLine: %zu\n", error->line + 1); printf(" ErrorLine: %zu\n", error->line + 1);
} }
exit(1); exit(1);
@@ -1762,6 +1762,9 @@ GroundValue interpretGroundInstruction(GroundInstruction inst, GroundScope* scop
if (function->nativeFn) { if (function->nativeFn) {
GroundValue returnValue = function->nativeFn(scope, argsList); GroundValue returnValue = function->nativeFn(scope, argsList);
if (returnValue.type == ERROR) { if (returnValue.type == ERROR) {
returnValue.data.errorVal.line = currentInstruction;
returnValue.data.errorVal.hasLine = true;
returnValue.data.errorVal.where = in;
if (scope->isMainScope) { if (scope->isMainScope) {
throwError(&returnValue.data.errorVal); throwError(&returnValue.data.errorVal);
} }

View File

@@ -562,7 +562,8 @@ GroundError createGroundError(char* what, char* type, GroundInstruction* where,
ge.type = malloc(strlen(type) + 1); ge.type = malloc(strlen(type) + 1);
strcpy(ge.type, type); strcpy(ge.type, type);
} else { } else {
ge.type = "GenericError"; ge.type = malloc(strlen("GenericError") + 1);
strcpy(ge.type, "GenericError");
} }
if (where != NULL) { if (where != NULL) {
@@ -575,7 +576,8 @@ GroundError createGroundError(char* what, char* type, GroundInstruction* where,
if (line != NULL) { if (line != NULL) {
ge.line = *line; ge.line = *line;
} else { } else {
ge.line = -1; ge.line = 0;
ge.hasLine = false;
} }
return ge; return ge;

View File

@@ -51,6 +51,7 @@ typedef struct GroundError {
char* type; char* type;
struct GroundInstruction* where; struct GroundInstruction* where;
size_t line; size_t line;
bool hasLine;
} GroundError; } GroundError;
/* /*