aboutsummaryrefslogtreecommitdiffstats
path: root/prototypes
diff options
context:
space:
mode:
Diffstat (limited to 'prototypes')
-rw-r--r--prototypes/connections/Makefile11
-rw-r--r--prototypes/connections/edit-tui.c58
-rw-r--r--prototypes/connections/source-tui-budget.json8
-rw-r--r--prototypes/connections/store-keys.c41
-rw-r--r--prototypes/connections/store.h6
-rw-r--r--prototypes/connections/tui-budget.json6
6 files changed, 90 insertions, 40 deletions
diff --git a/prototypes/connections/Makefile b/prototypes/connections/Makefile
index 4d4e5a2..47a6530 100644
--- a/prototypes/connections/Makefile
+++ b/prototypes/connections/Makefile
@@ -8,6 +8,9 @@ CORE = runtime.c
STORE ?= store.c
FIXED_PROGRAM ?= examples/editor.pure
HOST = $(STORE) store-port.c evaluate.c
+# Document browsers list keys through the store. The tree store keeps its own
+# catalog; per-object file stores share a directory listing.
+KEYS = $(if $(filter store-tree.c,$(STORE)),,store-keys.c)
HEADERS = runtime.h program.h store.h store-port.h flow.h result.h
all: core fixed-editor
core: $(BUILD)/libpure-execution.a
@@ -58,11 +61,11 @@ $(BUILD)/storage-plan.h: FORCE examples/storage.pure $(BUILD)/pure-compile
$(BUILD)/pure-mirror: mirror.c $(HOST) $(CORE) $(HEADERS) $(BUILD)/storage-plan.h | $(BUILD)
$(CC) $(CPPFLAGS) $(CFLAGS) -I$(BUILD) mirror.c $(HOST) $(CORE) $(LDFLAGS) $(LDLIBS) -o $@
-$(BUILD)/pure-edit-tui-fixed: edit-tui.c $(HOST) $(CORE) $(HEADERS) $(BUILD)/embedded-plan.h | $(BUILD)
- $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_EMBEDDED_PROGRAM -I$(BUILD) edit-tui.c $(HOST) $(CORE) $(LDFLAGS) $(LDLIBS) -o $@
+$(BUILD)/pure-edit-tui-fixed: edit-tui.c $(HOST) $(KEYS) $(CORE) $(HEADERS) $(BUILD)/embedded-plan.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_EMBEDDED_PROGRAM -I$(BUILD) edit-tui.c $(HOST) $(KEYS) $(CORE) $(LDFLAGS) $(LDLIBS) -o $@
-$(BUILD)/pure-edit-tui: edit-tui.c $(HOST) $(CORE) program.c $(HEADERS) | $(BUILD)
- $(CC) $(CPPFLAGS) $(CFLAGS) edit-tui.c $(HOST) $(CORE) program.c $(LDFLAGS) $(LDLIBS) -o $@
+$(BUILD)/pure-edit-tui: edit-tui.c $(HOST) $(KEYS) $(CORE) program.c $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) edit-tui.c $(HOST) $(KEYS) $(CORE) program.c $(LDFLAGS) $(LDLIBS) -o $@
# TLS/socket code is linked only when a document peer is explicitly selected.
$(BUILD)/pure-document-peer: document-peer.c ../common/tls-link.c ../common/tls-link.h $(HOST) program.c $(CORE) $(HEADERS) | $(BUILD)
diff --git a/prototypes/connections/edit-tui.c b/prototypes/connections/edit-tui.c
index fbd73c1..d7b1442 100644
--- a/prototypes/connections/edit-tui.c
+++ b/prototypes/connections/edit-tui.c
@@ -11,7 +11,6 @@
#ifdef PURE_EMBEDDED_PROGRAM
#include "embedded-plan.h"
#endif
-#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -100,41 +99,38 @@ static bool find_list_prefix(Editor *editor) {
return true;
}
+typedef struct {
+ DocumentKey *items;
+ size_t count, capacity;
+ bool complete;
+} KeyList;
+
+/* Bound the optional browser to 8,192 names (520 KiB of key storage). */
+static bool collect_key(void *context, const char *key) {
+ KeyList *list = context;
+ if (list->count == 8192) { list->complete = false; return false; }
+ if (list->count == list->capacity) {
+ size_t next = list->capacity ? list->capacity * 2 : 32;
+ DocumentKey *grown = realloc(list->items, next * sizeof(*grown));
+ if (!grown) { list->complete = false; return false; }
+ list->items = grown;
+ list->capacity = next;
+ }
+ memcpy(list->items[list->count++].name, key, strlen(key) + 1);
+ return true;
+}
+
/* List names from the selected byte store, not from the execution core.
- * Opening a name still goes through the store's checked READ path. Bound the
- * optional browser to 8,192 names (520 KiB of key storage). */
+ * Opening a name still goes through the store's checked READ path. */
static bool open_list(Editor *editor) {
- int descriptor = open(editor->store, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
- DIR *directory = descriptor >= 0 ? fdopendir(descriptor) : NULL;
- if (!directory) {
- if (descriptor >= 0) close(descriptor);
- snprintf(editor->message, sizeof(editor->message), "Could not read document directory");
- return false;
- }
- DocumentKey *items = NULL;
- size_t count = 0, capacity = 0;
- bool complete = true;
- for (;;) {
- errno = 0;
- struct dirent *entry = readdir(directory);
- if (!entry) { if (errno) complete = false; break; }
- if (strncmp(entry->d_name, "obj-", 4) || !valid_key(entry->d_name + 4)) continue;
- if (count == 8192) { complete = false; break; }
- if (count == capacity) {
- size_t next = capacity ? capacity * 2 : 32;
- DocumentKey *grown = realloc(items, next * sizeof(*grown));
- if (!grown) { complete = false; break; }
- items = grown;
- capacity = next;
- }
- memcpy(items[count++].name, entry->d_name + 4, strlen(entry->d_name + 4) + 1);
- }
- if (closedir(directory)) complete = false;
- if (!complete) {
- free(items);
+ KeyList list = {.complete = true};
+ if (pure_store_keys(editor->store, collect_key, &list) != PURE_OK || !list.complete) {
+ free(list.items);
snprintf(editor->message, sizeof(editor->message), "Document list exceeds 8,192 keys or cannot be read");
return false;
}
+ DocumentKey *items = list.items;
+ size_t count = list.count;
if (count > 1) qsort(items, count, sizeof(*items), compare_document_key);
close_list(editor);
editor->documents = items;
diff --git a/prototypes/connections/source-tui-budget.json b/prototypes/connections/source-tui-budget.json
index 31716a4..640630f 100644
--- a/prototypes/connections/source-tui-budget.json
+++ b/prototypes/connections/source-tui-budget.json
@@ -2,11 +2,13 @@
"profile": "linux-aarch64-gcc14-source-document-terminal-editor",
"binaries": {
"pure-edit-tui": {
- "max_text_bytes": 49152,
+ "max_text_bytes": 49664,
"max_data_bytes": 1152,
"max_bss_bytes": 64,
- "needed": ["libc.so.6"]
+ "needed": [
+ "libc.so.6"
+ ]
}
},
- "scope": "Optional source-loaded POSIX terminal editor for the same document app. Includes the runtime .pure parser and bounded document browser. Default core, fixed CLI and fixed TUI do not link the parser. These are Linux AArch64/GCC 14 section regression ceilings, not whole-process RAM; check_tui.py measures the selected whole process separately."
+ "scope": "Optional source-loaded POSIX terminal editor for the same document app. Includes the runtime .pure parser and bounded document browser. Default core, fixed CLI and fixed TUI do not link the parser. These are Linux AArch64/GCC 14 section regression ceilings, not whole-process RAM; check_tui.py measures the selected whole process separately. The 2026-09-25 ceiling reviews a measured 368-byte addition for listing keys through the selected store (pure_store_keys) instead of reading the flat store's obj- file names in the host."
}
diff --git a/prototypes/connections/store-keys.c b/prototypes/connections/store-keys.c
new file mode 100644
index 0000000..d5aeb69
--- /dev/null
+++ b/prototypes/connections/store-keys.c
@@ -0,0 +1,41 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Key listing for the stores that publish each object as obj-KEY (the flat
+ * and paged formats). Linked only by hosts that browse documents, so the
+ * default CLI and HTTP hosts do not carry it. */
+static bool valid_key(const char *key) {
+ size_t length = strlen(key);
+ if (!length || length > 64) return false;
+ for (size_t i = 0; i < length; ++i) {
+ unsigned char c = (unsigned char)key[i];
+ if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') || c == '_' || c == '-')) return false;
+ }
+ return true;
+}
+
+PureResult pure_store_keys(const char *path, bool (*visit)(void *, const char *key),
+ void *context) {
+ int descriptor = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ DIR *directory = descriptor >= 0 ? fdopendir(descriptor) : NULL;
+ if (!directory) {
+ if (descriptor >= 0) close(descriptor);
+ return PURE_STORE_ERROR;
+ }
+ PureResult result = PURE_OK;
+ for (;;) {
+ errno = 0;
+ struct dirent *entry = readdir(directory);
+ if (!entry) { if (errno) result = PURE_STORE_ERROR; break; }
+ if (strncmp(entry->d_name, "obj-", 4) || !valid_key(entry->d_name + 4)) continue;
+ if (!visit(context, entry->d_name + 4)) break;
+ }
+ if (closedir(directory)) result = PURE_STORE_ERROR;
+ return result;
+}
diff --git a/prototypes/connections/store.h b/prototypes/connections/store.h
index 6896360..dbfa8f8 100644
--- a/prototypes/connections/store.h
+++ b/prototypes/connections/store.h
@@ -37,6 +37,12 @@ PureResult pure_store_splice(const char *path, const char *key, int64_t expected
size_t offset, size_t remove, PureSpan insert,
size_t max_size, int64_t *revision);
+/* Visit each stored key once; the order is store-defined. Returning false
+ * from visit stops early. key is valid only during the call. Hosts that
+ * browse documents use this instead of reading a store's file layout. */
+PureResult pure_store_keys(const char *path, bool (*visit)(void *, const char *key),
+ void *context);
+
/* Fault hooks exist only in the separately built unit-test binary. */
typedef enum {
PURE_AFTER_HEADER, PURE_BEFORE_FILE_SYNC, PURE_BEFORE_RENAME, PURE_BEFORE_DIR_SYNC,
diff --git a/prototypes/connections/tui-budget.json b/prototypes/connections/tui-budget.json
index 1ca06b0..645ddc5 100644
--- a/prototypes/connections/tui-budget.json
+++ b/prototypes/connections/tui-budget.json
@@ -5,8 +5,10 @@
"max_text_bytes": 32768,
"max_data_bytes": 1152,
"max_bss_bytes": 64,
- "needed": ["libc.so.6"]
+ "needed": [
+ "libc.so.6"
+ ]
}
},
- "scope": "Release-linked optional POSIX terminal editor for one build-time prepared document app, including the bounded document browser. The raised text ceiling reviews its measured 2,541-byte addition; default CLI and core ceilings are unchanged. Excludes libc, terminal emulator, kernel TTY buffers, heap and stack. Whole-process RSS, including 1,024-key browsing, is checked by check_tui.py on the recorded Linux AArch64 host."
+ "scope": "Release-linked optional POSIX terminal editor for one build-time prepared document app, including the bounded document browser. The raised text ceiling reviews its measured 2,541-byte addition; default CLI and core ceilings are unchanged. Excludes libc, terminal emulator, kernel TTY buffers, heap and stack. Whole-process RSS, including 1,024-key browsing, is checked by check_tui.py on the recorded Linux AArch64 host. Key listing through the selected store added a measured 352 bytes within this ceiling (2026-09-25)."
}