duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit eef899c1eee677950b7d34143cc2fef157beb789
parent f7428b37836cb89392527bf1d28303e33a3be72b
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Thu,  8 Dec 2022 09:11:19 -0500

New concept: C "header" files

See doc/cc/usage.

Also, begin using the arena allocator in asm/uxntal, along with linked lists,
so that it reserves less space in memory.

Diffstat:
Mfs/asm/uxntal.c | 49+++++++++++++++++++++++++++++--------------------
Mfs/asm/uxntal.fs | 1+
Mfs/comp/c/lib.fs | 3+++
Mfs/doc/cc/usage.txt | 16++++++++++++++++
Afs/lib/alloc.h | 8++++++++
Afs/lib/arena.h | 12++++++++++++
6 files changed, 69 insertions(+), 20 deletions(-)

diff --git a/fs/asm/uxntal.c b/fs/asm/uxntal.c @@ -1,9 +1,6 @@ /* Source: https://git.sr.ht/~rabbits/uxn * License: /license/dll-uxn.txt */ -// TODO: Compiles, doesn't crash when ran, but doesn't output the right thing. -// Almost there! -// (oh, actually it crashes on i386...) #define TRIM $100 #define LENGTH $10000 @@ -12,6 +9,8 @@ typedef unsigned char Uint8; typedef char Sint8; typedef unsigned short Uint16; +static int _arena = NULL; + struct Macro { // TODO: allow multiple decls per line char name[$40]; @@ -20,6 +19,7 @@ struct Macro { }; struct Label { + Label *next; char name[$40]; Uint16 addr; Uint16 refs; @@ -36,10 +36,9 @@ struct Program { Uint8 data[LENGTH]; unsigned int ptr; unsigned int length; - Uint16 llen; Uint16 mlen; Uint16 rlen; - Label labels[$400]; + Label *labels; Macro macros[$100]; Reference refs[$800]; char scope[$40]; @@ -90,10 +89,12 @@ findmacro(char *name) static Label * findlabel(char *name) { - int i; - for(i = 0; i < p.llen; i++) - if(scmp(p.labels[i].name, name, $40)) - return &p.labels[i]; + Label *l = p.labels; + while (l) { + if(scmp(l->name, name, $40)) + return l; + l = l->next; + } return NULL; } @@ -177,9 +178,10 @@ makelabel(char *name) return error("Label name is hex number", name); if(findopcode(name) || scmp(name, "BRK"0, 4) || !slen(name)) return error("Label name is invalid", name); - if(p.llen == $400) - return error("Labels limit exceeded", name); - l = &p.labels[p.llen++]; + // TODO: add sizeof() + l = alloc_allot($48, _arena); + llappend(l, &p.labels); + l->next = NULL; l->addr = p.ptr; l->refs = 0; scpy(name, l->name, $40); @@ -451,21 +453,28 @@ assemble(int hdl) static void review() { - int i; - for(i = 0; i < p.llen; i++) - if(p.labels[i].name[0] >= 'A' && p.labels[i].name[0] <= 'Z') - continue; /* Ignore capitalized labels(devices) */ - else if(!p.labels[i].refs) - fprintf(p.labels[i].name, "-- Unused label: %z\n", ConsoleOut()); + Label *l = p.labels; + while (l) { + if (!l->refs) { + if(l->name[0] < 'A' || l->name[0] > 'Z') + fprintf(l->name, "-- Unused label: %z\n", ConsoleOut()); + } + l = l->next; + } fprintf( - p.mlen, p.llen, p.length-TRIM, + p.mlen, llcnt(p.labels), p.length-TRIM, "Assembled %d bytes, %d labels, %d macros.\n", ConsoleOut()); } int uxntal(int srchdl) { - p.llen = (p.mlen = (p.rlen = (p.length = (p.ptr = 0)))); + if (_arena == NULL) { + _arena = arena_new(); + } + arena_reset(_arena); + p.mlen = (p.rlen = (p.length = (p.ptr = 0))); + p.labels = NULL; if(!assemble(srchdl)) return !error("Assembly", "Failed to assemble rom."0); if(p.length <= TRIM) diff --git a/fs/asm/uxntal.fs b/fs/asm/uxntal.fs @@ -1,2 +1,3 @@ ?f<< /comp/c/lib.fs +?f<< /lib/arena.h cc<< /asm/uxntal.c diff --git a/fs/comp/c/lib.fs b/fs/comp/c/lib.fs @@ -20,6 +20,9 @@ :c int ConsoleOut(); :c unsigned char stdin(); :c void stdout(unsigned char c); +:c int llend(int ll); +:c void llappend(int elem, int ll); +:c int llcnt(int ll); : strlen c@ ; :c unsigned int strlen(char *str); diff --git a/fs/doc/cc/usage.txt b/fs/doc/cc/usage.txt @@ -170,3 +170,19 @@ just like the signature. Macros are not exposed to Forth as words and are cleared at the beginning of the "cc<<" call. + +## Header files + +Dusk OS has some ".h" files littered around which have the same name as a +corresponding Forth source file. These files are not C source files, they're +Forth source files, but they serve the purpose of a traditional ".h" file in the +outside world, that is, to provide C with an interface. + +These files can't be simple C source files because providing a C interface to a +Forth library often involves more than simple function prototypes or structure +definitions. It often involves mangling of the arguments, which have to be done +in wrapper words written in Forth. + +Therefore, if you want to use a Forth library in C that has a corresponding ".h" +file, you'll want to load that ".h" file with "?f<<" before you compile your C +code. diff --git a/fs/lib/alloc.h b/fs/lib/alloc.h @@ -0,0 +1,8 @@ +\ Allocator + +?f<< /lib/alloc.fs +?f<< /comp/c/cc.fs + +\ We don't expose the Allocator struct. We don't need to. +: alloc_allot Allocator :allot ; +:c int alloc_allot(unsigned int n, int self); diff --git a/fs/lib/arena.h b/fs/lib/arena.h @@ -0,0 +1,12 @@ +\ Arena + +?f<< /lib/arena.fs +?f<< /lib/alloc.h + +\ We don't expose the Arena struct. We don't need to. +: arena_new Arena :new ; +:c int arena_new(); +: arena_reset Arena :reset ; +:c void arena_reset(int self); +: arena_reserve Arena :reserve ; +:c void arena_reserve(int self);