mirror of https://git.sr.ht/~rabbits/uxn
Compare commits
4 Commits
7c1492908c
...
a1a6271622
Author | SHA1 | Date |
---|---|---|
Devine Lu Linvega | a1a6271622 | |
Devine Lu Linvega | ea8f512fcd | |
Devine Lu Linvega | fe414183b0 | |
Devine Lu Linvega | c0ba862911 |
93
src/uxnasm.c
93
src/uxnasm.c
|
@ -29,7 +29,7 @@ typedef struct {
|
|||
|
||||
static int ptr, length;
|
||||
static char token[0x40], scope[0x40], sublabel[0x80], lambda[0x05];
|
||||
static char dict[0x10000], *dictnext = dict;
|
||||
static char dict[0x4000], *dictnext = dict;
|
||||
static Uint8 data[0x10000], lambda_stack[0x100], lambda_ptr, lambda_len;
|
||||
static Uint16 label_len, refs_len, macro_len;
|
||||
static Item labels[0x400], refs[0x1000], macros[0x100];
|
||||
|
@ -52,7 +52,6 @@ static int scmp(char *a, char *b, int len) { int i = 0; while(a[i] == b[i]) if
|
|||
static int slen(char *s) { int i = 0; while(s[i]) i++; return i; } /* str length */
|
||||
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; } /* str copy */
|
||||
static char *scat(char *dst, char *src) { char *o = dst + slen(dst); while(*src) *o++ = *src++; *o = '\0'; return dst; } /* str concat */
|
||||
static char *push(char *s, char c) { char *o = dictnext; while((*dictnext++ = *s++) && *s); *dictnext++ = c; return o; } /* save str */
|
||||
|
||||
#define isopcode(x) (findopcode(x) || scmp(x, "BRK", 4))
|
||||
#define isinvalid(x) (!slen(x) || sihx(x) || isopcode(x) || cndx(runes, x[0]) >= 0)
|
||||
|
@ -67,6 +66,23 @@ static char *push(char *s, char c) { char *o = dictnext; while((*dictnext++ = *s
|
|||
|
||||
static int parse(char *w, FILE *f, Context *ctx);
|
||||
|
||||
static char *
|
||||
push(char *s, char c)
|
||||
{
|
||||
char *d = dict, *o = dictnext;
|
||||
/* find */
|
||||
for(d = dict; d < dictnext; d++) {
|
||||
char *ss = s, *pp = d, a, b;
|
||||
while((a = *pp++) == (b = *ss++))
|
||||
if(!a && !b) return d;
|
||||
}
|
||||
/* save */
|
||||
while((*dictnext++ = *s++) && *s)
|
||||
;
|
||||
*dictnext++ = c;
|
||||
return o;
|
||||
}
|
||||
|
||||
static Item *
|
||||
finditem(char *name, Item *list, int len)
|
||||
{
|
||||
|
@ -269,7 +285,16 @@ writehex(char *w, Context *ctx)
|
|||
}
|
||||
|
||||
static int
|
||||
makeinclude(char *filename)
|
||||
writestring(char *w, Context *ctx)
|
||||
{
|
||||
char c;
|
||||
while((c = *(w++)))
|
||||
if(!writebyte(c, ctx)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
assemble(char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
int res = 0;
|
||||
|
@ -283,22 +308,12 @@ makeinclude(char *filename)
|
|||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
writestring(char *w, Context *ctx)
|
||||
{
|
||||
char c;
|
||||
while((c = *(w++)))
|
||||
if(!writebyte(c, ctx)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
parse(char *w, FILE *f, Context *ctx)
|
||||
{
|
||||
Item *m;
|
||||
switch(w[0]) {
|
||||
case '(': return !walkcomment(f, ctx) ? error_asm("Invalid comment") : 1;
|
||||
case '~': return !makeinclude(w + 1) ? error_asm("Invalid include") : 1;
|
||||
case '%': return !makemacro(w + 1, f, ctx) ? error_asm("Invalid macro") : 1;
|
||||
case '@': return !makelabel(w + 1, 1, ctx) ? error_asm("Invalid label") : 1;
|
||||
case '&': return !makelabel(w, 0, ctx) ? error_asm("Invalid sublabel") : 1;
|
||||
|
@ -314,6 +329,7 @@ parse(char *w, FILE *f, Context *ctx)
|
|||
case '?': return addref(w + 1, w[0], ptr + 1) && writebyte(0x20, ctx) && writeshort(0xffff);
|
||||
case '!': return addref(w + 1, w[0], ptr + 1) && writebyte(0x40, ctx) && writeshort(0xffff);
|
||||
case '"': return !writestring(w + 1, ctx) ? error_asm("Invalid string") : 1;
|
||||
case '~': return !assemble(w + 1) ? error_asm("Invalid include") : 1;
|
||||
case '$':
|
||||
case '|': return !writepad(w) ? error_asm("Invalid padding") : 1;
|
||||
case '[':
|
||||
|
@ -332,6 +348,7 @@ static int
|
|||
resolve(void)
|
||||
{
|
||||
int i, rel;
|
||||
if(!length) return error_top("Assembly", "Output rom is empty.");
|
||||
for(i = 0; i < refs_len; i++) {
|
||||
Item *r = &refs[i], *l = findlabel(r->name);
|
||||
Uint8 *rom = data + r->addr;
|
||||
|
@ -364,22 +381,6 @@ resolve(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
review(char *filename)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < label_len; i++)
|
||||
if(labels[i].name[0] - 'A' > 25 && !labels[i].refs)
|
||||
fprintf(stdout, "-- Unused label: %s\n", labels[i].name);
|
||||
fprintf(stdout,
|
||||
"Assembled %s in %d bytes(%.2f%% used), %d labels, %d macros.\n",
|
||||
filename,
|
||||
length - PAGE,
|
||||
(length - PAGE) / 652.80,
|
||||
label_len,
|
||||
macro_len);
|
||||
}
|
||||
|
||||
static void
|
||||
writesym(char *filename)
|
||||
{
|
||||
|
@ -400,20 +401,38 @@ writesym(char *filename)
|
|||
fclose(fp);
|
||||
}
|
||||
|
||||
static int
|
||||
build(char *filename)
|
||||
{
|
||||
int i;
|
||||
FILE *dst;
|
||||
if(!(dst = fopen(filename, "wb")))
|
||||
return !error_top("Invalid output file", filename);
|
||||
for(i = 0; i < label_len; i++)
|
||||
if(labels[i].name[0] - 'A' > 25 && !labels[i].refs)
|
||||
fprintf(stdout, "-- Unused label: %s\n", labels[i].name);
|
||||
fwrite(data + PAGE, length - PAGE, 1, dst);
|
||||
fprintf(stdout,
|
||||
"Assembled %s in %d bytes(%.2f%% used), %d labels, %d macros.\n",
|
||||
filename,
|
||||
length - PAGE,
|
||||
(length - PAGE) / 652.80,
|
||||
label_len,
|
||||
macro_len);
|
||||
writesym(filename);
|
||||
fclose(dst);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
FILE *dst;
|
||||
ptr = PAGE;
|
||||
scpy("on-reset", scope, 0x40);
|
||||
if(argc == 1) return error_top("usage", "uxnasm [-v] input.tal output.rom");
|
||||
if(scmp(argv[1], "-v", 2)) return !fprintf(stdout, "Uxnasm - Uxntal Assembler, 27 Mar 2024.\n");
|
||||
if(!makeinclude(argv[1])) return !error_top("Assembly", "Failed to assemble rom.");
|
||||
if(scmp(argv[1], "-v", 2)) return !fprintf(stdout, "Uxnasm - Uxntal Assembler, 28 Mar 2024.\n");
|
||||
if(!assemble(argv[1]) || !length) return !error_top("Assembly", "Failed to assemble rom.");
|
||||
if(!resolve()) return !error_top("Assembly", "Failed to resolve symbols.");
|
||||
if(!(dst = fopen(argv[2], "wb"))) return !error_top("Invalid Output", argv[2]);
|
||||
if(length <= PAGE) return !error_top("Assembly", "Output rom is empty.");
|
||||
review(argv[2]);
|
||||
fwrite(data + PAGE, length - PAGE, 1, dst);
|
||||
writesym(argv[2]);
|
||||
if(!build(argv[2])) return !error_top("Assembly", "Failed to build rom.");
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue