commit 89191859b440d20f149e51762e4f888b69116955
parent 1b5a5963a73fae9898dc2301f2cafd0a5a91d70f
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Mon, 11 May 2026 10:53:58 -0700
api: implement cfree_dep_iter_new/_next over SourceManager
Wraps the internal source_depiter_* iterator, translating file ids to
the interned resolved paths the driver writes into Make rules. The
driver's -M/-MM/-MMD/-MP path was already wired through cfree_dep_iter_*;
it now produces real output instead of failing as "out of memory".
from_system_path and bracketed currently share SourceInclude.system
until the include resolver reports which dir matched — comment in
dep.c flags the gap.
Diffstat:
3 files changed, 64 insertions(+), 17 deletions(-)
diff --git a/Makefile b/Makefile
@@ -8,9 +8,6 @@ HOST_SYSROOT_LDFLAGS = -isysroot $(SYSROOT)
CFLAGS_COMMON = -std=c11 -Wpedantic -Wall -Wextra -Werror $(HOST_SYSROOT_CFLAGS)
-# Dep-file flags. clang supports -MMD/-MP; cfree-cc doesn't yet (dep iterator
-# is a stub — emits a misleading "out of memory"). Stage 2 overrides this to
-# empty until cfree implements the API.
DEPFLAGS = -MMD -MP
# libcfree: written in C11 freestanding; sees both src/ (internal) and
diff --git a/src/api/dep.c b/src/api/dep.c
@@ -0,0 +1,63 @@
+/* Header-dependency iteration — public CfreeDepIter wraps the internal
+ * SourceManager iterator and translates file ids to the resolved path
+ * strings the driver writes into Make rules. */
+
+#include <cfree.h>
+
+#include "core/core.h"
+#include "core/heap.h"
+#include "core/pool.h"
+
+struct CfreeDepIter {
+ Compiler* c;
+ SourceDepIter* inner;
+};
+
+CfreeDepIter* cfree_dep_iter_new(CfreeCompiler* c) {
+ Heap* h;
+ CfreeDepIter* it;
+ if (!c || !c->sources) return NULL;
+ h = (Heap*)c->env->heap;
+ it = (CfreeDepIter*)h->alloc(h, sizeof(*it), _Alignof(CfreeDepIter));
+ if (!it) return NULL;
+ it->c = c;
+ it->inner = source_depiter_new(c->sources);
+ if (!it->inner) {
+ h->free(h, it, sizeof(*it));
+ return NULL;
+ }
+ return it;
+}
+
+int cfree_dep_iter_next(CfreeDepIter* it, CfreeDepEdge* out) {
+ const SourceInclude* edge;
+ const SourceFile* includer;
+ const SourceFile* included;
+ if (!it || !out) return 0;
+ edge = source_depiter_next(it->inner);
+ if (!edge) return 0;
+ includer = source_file(it->c->sources, edge->includer_file_id);
+ included = source_file(it->c->sources, edge->included_file_id);
+ out->includer_name =
+ includer ? pool_str(it->c->global, includer->name, NULL) : NULL;
+ out->included_name =
+ included ? pool_str(it->c->global, included->name, NULL) : NULL;
+ out->include_loc = edge->include_loc;
+ /* SourceInclude.system tracks the bracket form, not the resolved
+ * directory's system flag — the include resolver doesn't yet
+ * distinguish which dir matched. -MM filtering treats every <...>
+ * as a system header until the resolver feeds that back. */
+ out->from_system_path = (uint8_t)(edge->system ? 1 : 0);
+ out->bracketed = (uint8_t)(edge->system ? 1 : 0);
+ out->pad[0] = 0;
+ out->pad[1] = 0;
+ return 1;
+}
+
+void cfree_dep_iter_free(CfreeDepIter* it) {
+ Heap* h;
+ if (!it) return;
+ h = (Heap*)it->c->env->heap;
+ if (it->inner) source_depiter_free(it->inner);
+ h->free(h, it, sizeof(*it));
+}
diff --git a/src/api/stubs.c b/src/api/stubs.c
@@ -88,20 +88,7 @@ ObjBuilder* read_wasm(Compiler* c, const char* n, const u8* d, size_t l) {
* defaults and document the missing capability through the return value
* (NULL handle / nonzero error). */
-/* Header-dep iterator — drained empty until PP records edges. */
-struct CfreeDepIter {
- int _;
-};
-CfreeDepIter* cfree_dep_iter_new(CfreeCompiler* c) {
- (void)c;
- return 0;
-}
-int cfree_dep_iter_next(CfreeDepIter* it, CfreeDepEdge* o) {
- (void)it;
- (void)o;
- return 0;
-}
-void cfree_dep_iter_free(CfreeDepIter* it) { (void)it; }
+/* Header-dep iterator lives in src/api/dep.c. */
/* Disassembler is real (src/api/disasm.c, src/arch/disasm.c,
* src/arch/aa64_disasm.c). Per-arch register name lookups and the