commit 919e09bf652c319197b536d09e84c6dc0999f1df
parent 93c0cca799e5e1a35fcd15d08b12d5a92177aed0
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 14 Dec 2022 16:36:32 -0500
comp/c: add uchar ushort uint typedefs
Also, move slen0 from emul/uxn/varvara to lib/str, add a C interface to it and
use it in asm/uxntal.
Diffstat:
7 files changed, 101 insertions(+), 94 deletions(-)
diff --git a/fs/asm/uxntal.c b/fs/asm/uxntal.c
@@ -1,4 +1,5 @@
/* Source: https://git.sr.ht/~rabbits/uxn
+ * Filename: src/uxnasm.c
* License: /license/dll-uxn.txt
*/
@@ -6,10 +7,6 @@
#define LENGTH $10000
#define LINESZ $40
-typedef unsigned char Uint8;
-typedef char Sint8;
-typedef unsigned short Uint16;
-
static int _arena = NULL;
struct MacroLine {
@@ -26,17 +23,17 @@ struct Macro {
struct Label {
Label *next;
char name[LINESZ];
- Uint16 addr, refs;
+ ushort addr, refs;
};
struct Reference {
Reference *next;
char name[LINESZ], rune;
- Uint16 addr;
+ ushort addr;
};
struct Program {
- Uint8 data[LENGTH];
+ uchar data[LENGTH];
unsigned int ptr, length;
Label *labels;
Macro *macros;
@@ -56,10 +53,9 @@ static char* ops[$20] = {
static int scmp(char *a, char *b, int len) { int i = 0; while(a[i] == b[i]) if(!a[i] || ++i >= len) return 1; return 0; } /* string compare */
static int sihx(char *s) { int i = 0; char c; while((c = s[i++])) if(!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f')) return 0; return i > 1; } /* string is hexadecimal */
static int shex(char *s) { int n = 0, i = 0; char c; while((c = s[i++])) if(c >= '0' && c <= '9') n = n * 16 + (c - '0'); else if(c >= 'a' && c <= 'f') n = n * 16 + 10 + (c - 'a'); return n; } /* string to num */
-static int slen(char *s) { int i = 0; while(s[i]) i++; return i; } /* string length */
-static int spos(char *s, char c) { Uint8 i = 0, j; while((j = s[i++])) if(j == c) return i; return -1; } /* character position */
+static int spos(char *s, char c) { uchar i = 0, j; while((j = s[i++])) if(j == c) return i; return -1; } /* character position */
static char *scpy(char *src, char *dst, int len) { int i = 0; while((dst[i] = src[i]) && i < len - 2) i++; dst[i + 1] = 0; return dst; } /* string copy */
-static char *scat(char *dst, char *src) { char *ptr = dst + slen(dst); while(*src) *ptr++ = *src++; *ptr = 0; return dst; } /* string cat */
+static char *scat(char *dst, char *src) { char *ptr = dst + zstrlen(dst); while(*src) *ptr++ = *src++; *ptr = 0; return dst; } /* string cat */
static int parse(char *w, int hdl);
@@ -100,7 +96,7 @@ findlabel(char *name)
return NULL;
}
-static Uint8
+static uchar
findopcode(char *s)
{
int i, m;
@@ -150,9 +146,9 @@ makemacro(char *name, int hdl)
char word[LINESZ];
if(findmacro(name))
return error("Macro duplicate", name);
- if(sihx(name) && slen(name) % 2 == 0)
+ if(sihx(name) && zstrlen(name) % 2 == 0)
return error("Macro name is hex number", name);
- if(findopcode(name) || scmp(name, "BRK"0, 4) || !slen(name))
+ if(findopcode(name) || scmp(name, "BRK"0, 4) || !zstrlen(name))
return error("Macro name is invalid", name);
m = alloc_allot(sizeof(Macro), _arena);
m->next = NULL;
@@ -178,9 +174,9 @@ makelabel(char *name)
Label *l;
if(findlabel(name))
return error("Label duplicate", name);
- if(sihx(name) && (slen(name) == 2 || slen(name) == 4))
+ if(sihx(name) && (zstrlen(name) == 2 || zstrlen(name) == 4))
return error("Label name is hex number", name);
- if(findopcode(name) || scmp(name, "BRK"0, 4) || !slen(name))
+ if(findopcode(name) || scmp(name, "BRK"0, 4) || !zstrlen(name))
return error("Label name is invalid", name);
l = alloc_allot(sizeof(Label), _arena);
l->next = NULL;
@@ -192,7 +188,7 @@ makelabel(char *name)
}
static int
-makereference(char *scope, char *label, Uint16 addr)
+makereference(char *scope, char *label, ushort addr)
{
char subw[LINESZ], parent[LINESZ];
int pos;
@@ -217,7 +213,7 @@ makereference(char *scope, char *label, Uint16 addr)
}
static int
-writebyte(Uint8 b)
+writebyte(uchar b)
{
if(p.ptr < TRIM)
return error("Writing in zero-page", ""0);
@@ -233,13 +229,13 @@ writebyte(Uint8 b)
static int
writeopcode(char *w)
{
- Uint8 res;
+ uchar res;
res = writebyte(findopcode(w));
return res;
}
static int
-writeshort(Uint16 s, int lit)
+writeshort(ushort s, int lit)
{
if(lit)
if(!writebyte(findopcode("LIT2"0))) return 0;
@@ -247,7 +243,7 @@ writeshort(Uint16 s, int lit)
}
static int
-writelitbyte(Uint8 b)
+writelitbyte(uchar b)
{
if(!writebyte(findopcode("LIT"0))) return 0;
if(!writebyte(b)) return 0;
@@ -275,14 +271,14 @@ parse(char *w, int hdl)
char word[LINESZ], subw[LINESZ], c;
Macro *m;
MacroLine *ml;
- if(slen(w) >= 63)
+ if(zstrlen(w) >= 63)
return error("Invalid token", w);
switch(w[0]) {
case '(': /* comment */
- if(slen(w) != 1) fprintf(w, "-- Malformed comment: %s\n", ConsoleOut());
+ if(zstrlen(w) != 1) fprintf(w, "-- Malformed comment: %s\n", ConsoleOut());
i = 1; /* track nested comment depth */
while(freadword(word, hdl) == 1) {
- if(slen(word) != 1)
+ if(zstrlen(word) != 1)
continue;
else if(word[0] == '(')
i++;
@@ -318,11 +314,11 @@ parse(char *w, int hdl)
return error("Invalid sublabel", w);
break;
case '#': /* literals hex */
- if(!sihx(w + 1) || (slen(w) != 3 && slen(w) != 5))
+ if(!sihx(w + 1) || (zstrlen(w) != 3 && zstrlen(w) != 5))
return error("Invalid hex literal", w);
- if(slen(w) == 3) {
+ if(zstrlen(w) == 3) {
if(!writelitbyte(shex(w + 1))) return 0;
- } else if(slen(w) == 5) {
+ } else if(zstrlen(w) == 5) {
if(!writeshort(shex(w + 1), 1)) return 0;
}
break;
@@ -358,18 +354,18 @@ parse(char *w, int hdl)
break;
case '[':
case ']':
- if(slen(w) == 1) break; /* else fallthrough */
+ if(zstrlen(w) == 1) break; /* else fallthrough */
default:
/* opcode */
if(findopcode(w) || scmp(w, "BRK"0, 4)) {
if(!writeopcode(w)) return 0;
}
/* raw byte */
- else if(sihx(w) && slen(w) == 2) {
+ else if(sihx(w) && zstrlen(w) == 2) {
if(!writebyte(shex(w))) return 0;
}
/* raw short */
- else if(sihx(w) && slen(w) == 4) {
+ else if(sihx(w) && zstrlen(w) == 4) {
if(!writeshort(shex(w), 0)) return 0;
}
/* macro */
@@ -397,16 +393,16 @@ resolve()
case '_':
if(!(l = findlabel(r->name)))
return error("Unknown relative reference", r->name);
- p.data[r->addr] = (Sint8)(l->addr - r->addr - 2);
- if(p.data[r->addr] != (Sint8)(l->addr - r->addr - 2))
+ p.data[r->addr] = (char)(l->addr - r->addr - 2);
+ if(p.data[r->addr] != (char)(l->addr - r->addr - 2))
return error("Relative reference is too far", r->name);
l->refs++;
break;
case ',':
if(!(l = findlabel(r->name)))
return error("Unknown relative reference", r->name);
- p.data[r->addr + 1] = (Sint8)(l->addr - r->addr - 3);
- if(p.data[r->addr + 1] != (Sint8)(l->addr - r->addr - 3))
+ p.data[r->addr + 1] = (char)(l->addr - r->addr - 3);
+ if(p.data[r->addr + 1] != (char)(l->addr - r->addr - 3))
return error("Relative reference is too far", r->name);
l->refs++;
break;
diff --git a/fs/comp/c/cc.fs b/fs/comp/c/cc.fs
@@ -14,3 +14,7 @@
: :c cctok$ nextt cparse ;
: cc<< ( -- ) ['] cc1, word with-stdin-file ;
+
+:c typedef unsigned char uchar ;
+:c typedef unsigned short ushort ;
+:c typedef unsigned int uint ;
diff --git a/fs/comp/c/lib.fs b/fs/comp/c/lib.fs
@@ -14,6 +14,7 @@
:c void dump(int addr);
:c void emit(char c);
:c void stype(char *str);
+:c int zstrlen(char *zstr);
:c int StdIn();
:c int StdOut();
:c int ConsoleIn();
diff --git a/fs/doc/cc/usage.txt b/fs/doc/cc/usage.txt
@@ -28,6 +28,10 @@ are a few differences:
* no long, redundant with int
* no double, float is always 32b
* char is always 8b, short is always 16b, int is always 32b
+* Extra builtin typedefs:
+ * uchar -- unsigned char
+ * ushort -- unsigned short
+ * uint -- unsigned int
* tightened parsing requirements for simplification purposes
* "unsigned" always goes first
* no "signed" (always default), no "auto"
diff --git a/fs/emul/uxn/varvara.fs b/fs/emul/uxn/varvara.fs
@@ -1,9 +1,7 @@
+\ Varvara implementation
+?f<< /lib/str.fs
?f<< /emul/uxn/vm.fs
-: slen0 ( a -- len )
- 0 swap $100 [c]? ( idx )
- dup 0< if abort" string too long" then ;
-
: short@ ( a -- n ) c@+ 8 lshift swap c@ or ;
: short! ( n a -- ) over 8 rshift swap c!+ c! ;
: devshort@ ( idx dev -- n ) Device dat + short@ ;
@@ -24,7 +22,7 @@ create _fpos 8 allot0 \ current file position
: _findfn ( dev -- path-or-0 )
8 swap devshort@ uxn_ram + ( a )
- dup slen0 dup _fnbuf c! _fnbuf 1+ swap move ( dev )
+ dup zstrlen dup _fnbuf c! _fnbuf 1+ swap move ( dev )
\ _fnbuf now holds stringified filename
_fnbuf curpath :find ( path ) ;
diff --git a/fs/emul/uxn/vm.c b/fs/emul/uxn/vm.c
@@ -7,71 +7,71 @@
*/
struct Stack {
- unsigned char ptr, dat[$ff];
+ uchar ptr, dat[$ff];
};
struct Device {
- unsigned char port, dat[$10];
- unsigned char (*dei)(Device*, unsigned char);
- void (*deo)(Device*, unsigned char);
+ uchar port, dat[$10];
+ uchar (*dei)(Device*, uchar);
+ void (*deo)(Device*, uchar);
};
typedef void (*VMOP) ();
-static unsigned char ram[$10000];
+static uchar ram[$10000];
static Stack wst, rst, *src, *dst;
static Device dev[$10];
-static unsigned short pc; // Program Counter
+static ushort pc; // Program Counter
static int bs; // byte/short 0=byte 1=short
-static unsigned char *sp; // pointer to current stack top
-static unsigned char kptr; // holding value for keep mode
+static uchar *sp; // pointer to current stack top
+static uchar kptr; // holding value for keep mode
static void error(int code) {
printf(code, "Error %d encountered\n");
abort();
}
-static unsigned short gw(unsigned char *a) { return *a<<8|*(a+1); }
-static void sw(unsigned char *a, unsigned short val) {
+static ushort gw(uchar *a) { return *a<<8|*(a+1); }
+static void sw(uchar *a, ushort val) {
*a = val>>8; *(a+1) = val; }
-static unsigned short signext(unsigned short val) {
+static ushort signext(ushort val) {
// TODO: allow sign-extending through typecasting
if (val >= $80) return val - $100; else return val;
}
-static void push8(Stack *s, unsigned char val) {
+static void push8(Stack *s, uchar val) {
if (s->ptr == $ff) { error(2); } else { s->dat[s->ptr++] = val; }
}
-static void push16(Stack *s, unsigned short val) {
+static void push16(Stack *s, ushort val) {
if (s->ptr >= $fe) { error(2); } else {
sw(&s->dat[s->ptr], val);
s->ptr += 2 ;
}
}
-static void pushs(Stack *s, unsigned short val) {
+static void pushs(Stack *s, ushort val) {
if (bs) push16(s, val); else push8(s, val); }
-static void push(unsigned short val) { pushs(src, val); }
+static void push(ushort val) { pushs(src, val); }
-static unsigned char pop8() {
+static uchar pop8() {
if (!*sp) { error(0); } else { return src->dat[--*sp]; }
}
-static unsigned short pop16() {
- unsigned short val;
+static ushort pop16() {
+ ushort val;
if (*sp <= 1) { error(0); } else {
*sp -= 2;
return gw(&src->dat[*sp]);
}
}
-static unsigned short pop() { if (bs) return pop16(); else return pop8(); }
+static ushort pop() { if (bs) return pop16(); else return pop8(); }
-static void poke(unsigned short addr, unsigned short val) {
+static void poke(ushort addr, ushort val) {
if (bs) sw(&ram[addr], val); else ram[addr] = val; }
-static unsigned short peek(unsigned short addr) {
+static ushort peek(ushort addr) {
if (bs) return gw(&ram[addr]); else return ram[addr]; }
-static void warp(unsigned short addr) {
+static void warp(ushort addr) {
if (bs) {
pc = addr;
} else {
@@ -79,53 +79,53 @@ static void warp(unsigned short addr) {
}
}
-static unsigned char nulldei(Device *d, unsigned char port) { return d->dat[port]; }
-static void nulldeo(Device *d, unsigned char port) { }
+static uchar nulldei(Device *d, uchar port) { return d->dat[port]; }
+static void nulldeo(Device *d, uchar port) { }
/* Operations */
static void LIT() { push(peek(pc++)); pc += bs; }
static void INC() { push(pop()+1); }
static void POP() { pop(); }
-static void NIP() { unsigned short x = pop(); pop(); push(x); }
+static void NIP() { ushort x = pop(); pop(); push(x); }
static void SWP() {
- unsigned short x = pop();
- unsigned short y = pop();
+ ushort x = pop();
+ ushort y = pop();
push(x); push(y); }
static void ROT() {
- unsigned short x = pop();
- unsigned short y = pop();
- unsigned short z = pop();
+ ushort x = pop();
+ ushort y = pop();
+ ushort z = pop();
push(y); push(x); push(z); }
-static void DUP() { unsigned short x = pop(); push(x); push(x); }
+static void DUP() { ushort x = pop(); push(x); push(x); }
static void OVR() {
- unsigned short x = pop();
- unsigned short y = pop();
+ ushort x = pop();
+ ushort y = pop();
push(y); push(x); push(y); }
static void EQU() { push8(src, pop() == pop()); }
static void NEQ() { push8(src, pop() != pop()); }
static void GTH() {
- unsigned short a = pop();
- unsigned short b = pop();
+ ushort a = pop();
+ ushort b = pop();
push8(src, b > a); }
static void LTH() {
- unsigned short a = pop();
- unsigned short b = pop();
+ ushort a = pop();
+ ushort b = pop();
push8(src, b < a); }
static void JMP() { warp(pop()); }
-static void JCN() { unsigned short a = pop(); if (pop8()) { warp(a); } }
+static void JCN() { ushort a = pop(); if (pop8()) { warp(a); } }
static void JSR() {
- unsigned short a = pop();
+ ushort a = pop();
push16(dst, pc); warp(a); }
static void STH() { pushs( dst, pop()); }
static void LDZ() { push(peek(pop8())); }
-static void STZ() { unsigned short a = pop8(); poke(a, pop()); }
+static void STZ() { ushort a = pop8(); poke(a, pop()); }
static void LDR() { push(peek(pc+signext(pop8()))); }
-static void STR() { unsigned short r = signext(pop8()); poke(pc+r, pop()); }
+static void STR() { ushort r = signext(pop8()); poke(pc+r, pop()); }
static void LDA() { push(peek(pop16())); }
-static void STA() { unsigned short a = pop16(); poke(a, pop()); }
+static void STA() { ushort a = pop16(); poke(a, pop()); }
static void DEI() {
- unsigned char port = pop8();
- unsigned short val;
+ uchar port = pop8();
+ ushort val;
Device *d = &dev[port>>4];
port &= $f;
if (bs) {
@@ -138,8 +138,8 @@ static void DEI() {
push(val);
}
static void DEO() {
- unsigned char port = pop8();
- unsigned short val = pop();
+ uchar port = pop8();
+ ushort val = pop();
Device *d = &dev[port>>4];
port &= $f;
if (bs) {
@@ -152,20 +152,20 @@ static void DEO() {
}
static void ADD() { push(pop() + pop()); }
static void SUB() {
- unsigned short a = pop();
- unsigned short b = pop();
+ ushort a = pop();
+ ushort b = pop();
push(b - a); }
static void MUL() { push(pop() * pop()); }
static void DIV() {
- unsigned short a = pop();
- unsigned short b = pop();
+ ushort a = pop();
+ ushort b = pop();
push(b / a); }
static void AND() { push(pop() & pop()); }
static void ORA() { push(pop() | pop()); }
static void EOR() { push(pop() ^ pop()); }
static void SFT() {
- unsigned char shift = pop8();
- unsigned short n = pop();
+ uchar shift = pop8();
+ ushort n = pop();
n >>= (shift & $0f);
n <<= (shift >> 4);
push(n);
@@ -178,7 +178,7 @@ static VMOP ops[$20] = {
ADD, SUB, MUL, DIV, AND, ORA, EOR, SFT};
void uxn_exec() {
- unsigned char op;
+ uchar op;
while (op = ram[pc++]) {
bs = (op >> 5) & 1;
if(op & $40) {
@@ -217,11 +217,11 @@ void uxn_init() {
}
}
-unsigned int* uxn_ram() { return ram; }
+uint* uxn_ram() { return ram; }
void uxn_set_dev(
int port,
- unsigned char (*dei)(Device*, unsigned char),
- void (*deo)(Device*, unsigned char)) {
+ uchar (*dei)(Device*, uchar),
+ void (*deo)(Device*, uchar)) {
dev[port].dei = dei;
dev[port].deo = deo;
}
diff --git a/fs/lib/str.fs b/fs/lib/str.fs
@@ -14,6 +14,10 @@ create NULLSTR 0 c,
: s[]= ( str a len -- f )
rot dup c@ rot = if ( a str ) c@+ []= else 2drop 0 then ;
+\ null-terminated strings (zstr) routines
+: zstrlen ( zstr -- len )
+ 0 swap $100 [c]? ( idx ) dup 0< if abort" string too long" then ;
+
\\ append character to end of string
: sappend ( c str -- ) tuck s) c! dup c@ 1+ swap c! ;