global cell shops

This commit is contained in:
2025-12-08 13:01:44 -06:00
parent 1bcdab64ff
commit 401f69b503
18 changed files with 849 additions and 301 deletions

View File

@@ -11,103 +11,100 @@
#include "cell.h"
#include "cell_internal.h"
#define QOP_IMPLEMENTATION
#include "qop.h"
#define ENGINE "engine.cm"
#define ENGINE "scripts/engine.cm"
#define CELL_SHOP_DIR ".cell"
#define CELL_CORE_DIR "core"
#include <signal.h>
#include <unistd.h>
#include <sys/stat.h>
static qop_desc qop_core;
static qop_file *qop_hashmap = NULL;
cell_rt *root_cell = NULL;
static char *core_path = NULL;
int get_executable_path(char *buffer, unsigned int buffer_size) {
#if defined(__linux__)
ssize_t len = readlink("/proc/self/exe", buffer, buffer_size - 1);
if (len == -1) {
return 0;
// Get the home directory
static const char* get_home_dir(void) {
const char *home = getenv("HOME");
if (!home) {
home = getenv("USERPROFILE"); // Windows fallback
}
buffer[len] = '\0';
return len;
#elif defined(__APPLE__)
if (_NSGetExecutablePath(buffer, &buffer_size) == 0) {
return buffer_size;
}
#elif defined(_WIN32)
return GetModuleFileName(NULL, buffer, buffer_size);
#endif
return 0;
return home;
}
int prosperon_mount_core(void)
// Find and verify the cell shop at ~/.cell
int find_cell_shop(void)
{
char exe_path[PATH_MAX];
int exe_path_len = get_executable_path(exe_path, sizeof(exe_path));
if (exe_path_len == 0) {
printf("ERROR: Could not get executable path\n");
const char *home = get_home_dir();
if (!home) {
printf("ERROR: Could not determine home directory. Set HOME environment variable.\n");
return 0;
}
// Load the entire executable into memory
FILE *fh = fopen(exe_path, "rb");
if (!fh) {
printf("ERROR: Could not open executable\n");
// Build path to ~/.cell/core
size_t path_len = strlen(home) + strlen("/" CELL_SHOP_DIR "/" CELL_CORE_DIR) + 1;
core_path = malloc(path_len);
if (!core_path) {
printf("ERROR: Could not allocate memory for core path\n");
return 0;
}
snprintf(core_path, path_len, "%s/" CELL_SHOP_DIR "/" CELL_CORE_DIR, home);
fseek(fh, 0, SEEK_END);
long file_size = ftell(fh);
fseek(fh, 0, SEEK_SET);
unsigned char *buf = malloc(file_size);
if (!buf) {
printf("ERROR: Could not allocate memory for executable\n");
fclose(fh);
return 0;
}
if (fread(buf, 1, file_size, fh) != (size_t)file_size) {
printf("ERROR: Could not read executable\n");
free(buf);
fclose(fh);
return 0;
}
fclose(fh);
// Open the QOP archive from the in-memory data
int archive_size = qop_open_data(buf, file_size, &qop_core);
if (archive_size == 0) {
printf("ERROR: Could not open QOP archive\n");
free(buf);
return 0;
}
// Read the archive index
qop_hashmap = malloc(qop_core.hashmap_size);
if (!qop_hashmap) {
printf("ERROR: Could not allocate memory for QOP hashmap\n");
qop_close(&qop_core);
free(buf);
return 0;
}
int index_len = qop_read_index(&qop_core, qop_hashmap);
if (index_len == 0) {
printf("ERROR: Could not read QOP index\n");
free(qop_hashmap);
qop_hashmap = NULL;
qop_close(&qop_core);
free(buf);
// Check if the core directory exists
struct stat st;
if (stat(core_path, &st) != 0 || !S_ISDIR(st.st_mode)) {
printf("ERROR: Cell shop not found at %s/" CELL_SHOP_DIR "\n", home);
printf("Run 'cell install' to set up the cell environment.\n");
free(core_path);
core_path = NULL;
return 0;
}
return 1;
}
// Load a file from the core directory
static char* load_core_file(const char *filename, size_t *out_size) {
if (!core_path) return NULL;
size_t path_len = strlen(core_path) + 1 + strlen(filename) + 1;
char *full_path = malloc(path_len);
if (!full_path) return NULL;
snprintf(full_path, path_len, "%s/%s", core_path, filename);
FILE *fh = fopen(full_path, "rb");
free(full_path);
if (!fh) return NULL;
fseek(fh, 0, SEEK_END);
long file_size = ftell(fh);
fseek(fh, 0, SEEK_SET);
char *data = malloc(file_size + 1);
if (!data) {
fclose(fh);
return NULL;
}
if (fread(data, 1, file_size, fh) != (size_t)file_size) {
free(data);
fclose(fh);
return NULL;
}
fclose(fh);
data[file_size] = 0;
if (out_size) *out_size = file_size;
return data;
}
// Get the core path for use by scripts
const char* cell_get_core_path(void) {
return core_path;
}
void actor_disrupt(cell_rt *crt)
{
crt->disrupt = 1;
@@ -163,39 +160,28 @@ void script_startup(cell_rt *prt)
crt->init_wota = NULL;
}
// Store the core path for scripts to use
JSValue js_cell = JS_GetPropertyStr(js, globalThis, "cell");
JSValue hidden = JS_GetPropertyStr(js, js_cell, "hidden");
size_t archive_size = qop_core.data_size - qop_core.files_offset;
JSValue blob = js_new_blob_stoned_copy(js, qop_core.data + qop_core.files_offset, archive_size);
JS_SetPropertyStr(js, hidden, "core_qop_blob", blob);
if (core_path) {
JS_SetPropertyStr(js, hidden, "core_path", JS_NewString(js, core_path));
}
JS_FreeValue(js, hidden);
JS_FreeValue(js, js_cell);
JS_FreeValue(js, globalThis);
// Find and load engine.cm from QOP archive
qop_file *engine_file = qop_find(&qop_core, ENGINE);
if (!engine_file) {
printf("ERROR: Could not find file %s in QOP archive!\n", ENGINE);
return;
}
char *data = malloc(engine_file->size + 1);
// Load engine.cm from the core directory
size_t engine_size;
char *data = load_core_file(ENGINE, &engine_size);
if (!data) {
printf("ERROR: Could not allocate memory for %s!\n", ENGINE);
printf("ERROR: Could not load %s from %s!\n", ENGINE, core_path);
return;
}
int bytes_read = qop_read(&qop_core, engine_file, (unsigned char *)data);
if (bytes_read != (int)engine_file->size) {
printf("ERROR: Could not read file %s from QOP archive!\n", ENGINE);
free(data);
return;
}
data[engine_file->size] = 0;
crt->state = ACTOR_RUNNING;
JSValue v = JS_Eval(js, data, (size_t)engine_file->size, ENGINE, 0);
JSValue v = JS_Eval(js, data, engine_size, ENGINE, 0);
free(data);
uncaught_exception(js, v);
crt->state = ACTOR_IDLE;
set_actor_state(crt);
@@ -223,10 +209,9 @@ int cell_init(int argc, char **argv)
{
int script_start = 1;
/* Load QOP package attached to executable - this is now mandatory! */
int mounted = prosperon_mount_core();
if (!mounted) {
printf("ERROR: Could not load core QOP package.\n");
/* Find the cell shop at ~/.cell */
int found = find_cell_shop();
if (!found) {
return 1;
}