(uxnasm) Improved errors
This commit is contained in:
parent
f6cda36187
commit
fc6ec0b387
65
src/uxnasm.c
65
src/uxnasm.c
|
@ -97,7 +97,7 @@ findopcode(char *s)
|
||||||
else if(s[m] == 'k')
|
else if(s[m] == 'k')
|
||||||
i |= (1 << 7);
|
i |= (1 << 7);
|
||||||
else
|
else
|
||||||
return error_top("Unknown opcode mode", s);
|
return 0;
|
||||||
m++;
|
m++;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
|
@ -115,7 +115,7 @@ walkcomment(FILE *f, Context *ctx)
|
||||||
if(c == '(') depth++;
|
if(c == '(') depth++;
|
||||||
if(c == ')' && --depth < 1) return 1;
|
if(c == ')' && --depth < 1) return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return error_asm("Comment incomplete");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -177,9 +177,9 @@ makemacro(char *name, FILE *f, Context *ctx)
|
||||||
if(c == 0xa) ctx->line += 1;
|
if(c == 0xa) ctx->line += 1;
|
||||||
while(f && fread(&c, 1, 1, f) && c != '}') {
|
while(f && fread(&c, 1, 1, f) && c != '}') {
|
||||||
if(c == 0xa) ctx->line += 1;
|
if(c == 0xa) ctx->line += 1;
|
||||||
if(c == '%') return error_top("Nested macro", name);
|
if(c == '%') return error_top("Macro nested", name);
|
||||||
if(c == '(')
|
if(c == '(' && !walkcomment(f, ctx))
|
||||||
walkcomment(f, ctx);
|
return 0;
|
||||||
else
|
else
|
||||||
*dictnext++ = c;
|
*dictnext++ = c;
|
||||||
}
|
}
|
||||||
|
@ -194,8 +194,8 @@ makelabel(char *name, int setscope, Context *ctx)
|
||||||
if(name[0] == '&')
|
if(name[0] == '&')
|
||||||
name = join(scope, '/', name + 1);
|
name = join(scope, '/', name + 1);
|
||||||
if(labels_len >= 0x400) return error_asm("Labels limit exceeded");
|
if(labels_len >= 0x400) return error_asm("Labels limit exceeded");
|
||||||
if(isinvalid(name)) return error_asm("Label is invalid");
|
if(isinvalid(name)) return error_asm("Label invalid");
|
||||||
if(findlabel(name)) return error_asm("Label is duplicate");
|
if(findlabel(name)) return error_asm("Label duplicate");
|
||||||
l = &labels[labels_len++];
|
l = &labels[labels_len++];
|
||||||
l->name = push(name, 0);
|
l->name = push(name, 0);
|
||||||
l->addr = ptr;
|
l->addr = ptr;
|
||||||
|
@ -223,7 +223,7 @@ makeref(char *label, char rune, Uint16 addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
writepad(char *w)
|
writepad(char *w, Context *ctx)
|
||||||
{
|
{
|
||||||
Item *l;
|
Item *l;
|
||||||
int rel = w[0] == '$' ? ptr : 0;
|
int rel = w[0] == '$' ? ptr : 0;
|
||||||
|
@ -235,14 +235,14 @@ writepad(char *w)
|
||||||
ptr = l->addr + rel;
|
ptr = l->addr + rel;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return error_asm("Padding invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
writebyte(Uint8 b, Context *ctx)
|
writebyte(Uint8 b, Context *ctx)
|
||||||
{
|
{
|
||||||
if(ptr < PAGE)
|
if(ptr < PAGE)
|
||||||
return error_asm("Writing in zero-page");
|
return error_asm("Writing zero-page");
|
||||||
else if(ptr >= 0x10000)
|
else if(ptr >= 0x10000)
|
||||||
return error_asm("Writing outside memory");
|
return error_asm("Writing outside memory");
|
||||||
else if(ptr < length)
|
else if(ptr < length)
|
||||||
|
@ -263,7 +263,7 @@ writehex(char *w, Context *ctx)
|
||||||
else if(w[3] && !w[4])
|
else if(w[3] && !w[4])
|
||||||
return writeshort(shex(w));
|
return writeshort(shex(w));
|
||||||
else
|
else
|
||||||
return 0;
|
return error_asm("Hexadecimal invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -271,7 +271,7 @@ writestring(char *w, Context *ctx)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
while((c = *(w++)))
|
while((c = *(w++)))
|
||||||
if(!writebyte(c, ctx)) return 0;
|
if(!writebyte(c, ctx)) return error_asm("String invalid");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ assemble(char *filename)
|
||||||
ctx.line = 0;
|
ctx.line = 0;
|
||||||
ctx.path = push(filename, 0);
|
ctx.path = push(filename, 0);
|
||||||
if(!(f = fopen(filename, "r")))
|
if(!(f = fopen(filename, "r")))
|
||||||
return error_top("Invalid source", filename);
|
return error_top("Source missing", filename);
|
||||||
res = walkfile(f, &ctx);
|
res = walkfile(f, &ctx);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return res;
|
return res;
|
||||||
|
@ -295,12 +295,12 @@ parse(char *w, FILE *f, Context *ctx)
|
||||||
{
|
{
|
||||||
Item *m;
|
Item *m;
|
||||||
switch(w[0]) {
|
switch(w[0]) {
|
||||||
case '(': return !walkcomment(f, ctx) ? error_asm("Invalid comment") : 1;
|
case '(': return walkcomment(f, ctx);
|
||||||
case '%': return !makemacro(w + 1, f, ctx) ? error_asm("Invalid macro") : 1;
|
case '%': return makemacro(w + 1, f, ctx);
|
||||||
case '@': return !makelabel(w + 1, 1, ctx) ? error_asm("Invalid label") : 1;
|
case '@': return makelabel(w + 1, 1, ctx);
|
||||||
case '&': return !makelabel(w, 0, ctx) ? error_asm("Invalid sublabel") : 1;
|
case '&': return makelabel(w, 0, ctx);
|
||||||
case '}': return !makelabel(makelambda(lambda_stack[--lambda_ptr]), 0, ctx) ? error_asm("Invalid label") : 1;
|
case '}': return makelabel(makelambda(lambda_stack[--lambda_ptr]), 0, ctx);
|
||||||
case '#': return !ishex(w + 1) || !writehex(w, ctx) ? error_asm("Invalid hexadecimal") : 1;
|
case '#': return ishex(w + 1) && writehex(w, ctx);
|
||||||
case '_': return makeref(w + 1, w[0], ptr) && writebyte(0xff, ctx);
|
case '_': return makeref(w + 1, w[0], ptr) && writebyte(0xff, ctx);
|
||||||
case ',': return makeref(w + 1, w[0], ptr + 1) && writebyte(findopcode("LIT"), ctx) && writebyte(0xff, ctx);
|
case ',': return makeref(w + 1, w[0], ptr + 1) && writebyte(findopcode("LIT"), ctx) && writebyte(0xff, ctx);
|
||||||
case '-': return makeref(w + 1, w[0], ptr) && writebyte(0xff, ctx);
|
case '-': return makeref(w + 1, w[0], ptr) && writebyte(0xff, ctx);
|
||||||
|
@ -310,10 +310,10 @@ parse(char *w, FILE *f, Context *ctx)
|
||||||
case ';': return makeref(w + 1, w[0], ptr + 1) && writebyte(findopcode("LIT2"), ctx) && writeshort(0xffff);
|
case ';': return makeref(w + 1, w[0], ptr + 1) && writebyte(findopcode("LIT2"), ctx) && writeshort(0xffff);
|
||||||
case '?': return makeref(w + 1, w[0], ptr + 1) && writebyte(0x20, ctx) && writeshort(0xffff);
|
case '?': return makeref(w + 1, w[0], ptr + 1) && writebyte(0x20, ctx) && writeshort(0xffff);
|
||||||
case '!': return makeref(w + 1, w[0], ptr + 1) && writebyte(0x40, ctx) && writeshort(0xffff);
|
case '!': return makeref(w + 1, w[0], ptr + 1) && writebyte(0x40, ctx) && writeshort(0xffff);
|
||||||
case '"': return !writestring(w + 1, ctx) ? error_asm("Invalid string") : 1;
|
case '"': return writestring(w + 1, ctx);
|
||||||
case '~': return !assemble(w + 1) ? error_asm("Invalid include") : 1;
|
case '~': return !assemble(w + 1) ? error_asm("Include missing") : 1;
|
||||||
case '$':
|
case '$':
|
||||||
case '|': return !writepad(w) ? error_asm("Invalid padding") : 1;
|
case '|': return writepad(w, ctx);
|
||||||
case '[':
|
case '[':
|
||||||
case ']': return 1;
|
case ']': return 1;
|
||||||
}
|
}
|
||||||
|
@ -324,20 +324,20 @@ parse(char *w, FILE *f, Context *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
resolve(void)
|
resolve(char *filename)
|
||||||
{
|
{
|
||||||
int i, rel;
|
int i, rel;
|
||||||
if(!length) return error_top("Assembly", "Output rom is empty.");
|
if(!length) return error_top("Output empty", filename);
|
||||||
for(i = 0; i < refs_len; i++) {
|
for(i = 0; i < refs_len; i++) {
|
||||||
Item *r = &refs[i], *l = findlabel(r->name);
|
Item *r = &refs[i], *l = findlabel(r->name);
|
||||||
Uint8 *rom = data + r->addr;
|
Uint8 *rom = data + r->addr;
|
||||||
if(!l) return error_top("Unknown label", r->name);
|
if(!l) return error_top("Label unknown", r->name);
|
||||||
switch(r->rune) {
|
switch(r->rune) {
|
||||||
case '_':
|
case '_':
|
||||||
case ',':
|
case ',':
|
||||||
*rom = rel = l->addr - r->addr - 2;
|
*rom = rel = l->addr - r->addr - 2;
|
||||||
if((Sint8)data[r->addr] != rel)
|
if((Sint8)data[r->addr] != rel)
|
||||||
return error_top("Relative reference is too far", r->name);
|
return error_top("Relative reference too far", r->name);
|
||||||
break;
|
break;
|
||||||
case '-':
|
case '-':
|
||||||
case '.':
|
case '.':
|
||||||
|
@ -368,7 +368,7 @@ build(char *rompath)
|
||||||
char *sympath = join(rompath, '.', "sym");
|
char *sympath = join(rompath, '.', "sym");
|
||||||
/* rom */
|
/* rom */
|
||||||
if(!(dst = fopen(rompath, "wb")))
|
if(!(dst = fopen(rompath, "wb")))
|
||||||
return !error_top("Invalid output file", rompath);
|
return !error_top("Output file invalid", rompath);
|
||||||
for(i = 0; i < labels_len; i++)
|
for(i = 0; i < labels_len; i++)
|
||||||
if(labels[i].name[0] - 'A' > 25 && !labels[i].refs)
|
if(labels[i].name[0] - 'A' > 25 && !labels[i].refs)
|
||||||
fprintf(stdout, "-- Unused label: %s\n", labels[i].name);
|
fprintf(stdout, "-- Unused label: %s\n", labels[i].name);
|
||||||
|
@ -382,7 +382,7 @@ build(char *rompath)
|
||||||
macro_len);
|
macro_len);
|
||||||
/* sym */
|
/* sym */
|
||||||
if(!(dstsym = fopen(sympath, "w")))
|
if(!(dstsym = fopen(sympath, "w")))
|
||||||
return !error_top("Invalid symbols file", sympath);
|
return !error_top("Symbols file invalid", sympath);
|
||||||
for(i = 0; i < labels_len; i++) {
|
for(i = 0; i < labels_len; i++) {
|
||||||
Uint8 hb = labels[i].addr >> 8, lb = labels[i].addr;
|
Uint8 hb = labels[i].addr >> 8, lb = labels[i].addr;
|
||||||
char c, d = 0, *name = labels[i].name;
|
char c, d = 0, *name = labels[i].name;
|
||||||
|
@ -400,11 +400,10 @@ main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
ptr = PAGE;
|
ptr = PAGE;
|
||||||
copy("on-reset", scope, 0);
|
copy("on-reset", scope, 0);
|
||||||
if(argc == 2 && scmp(argv[1], "-v", 2)) return !fprintf(stdout, "Uxnasm - Uxntal Assembler, 29 Mar 2024.\n");
|
if(argc == 2 && scmp(argv[1], "-v", 2)) return !fprintf(stdout, "Uxnasm - Uxntal Assembler, 30 Mar 2024.\n");
|
||||||
if(argc != 3) return error_top("usage", "uxnasm [-v] input.tal output.rom");
|
if(argc != 3) return error_top("usage", "uxnasm [-v] input.tal output.rom");
|
||||||
if(!assemble(argv[1])) return !error_top("Assembly", "Failed to assemble rom.");
|
if(!assemble(argv[1])) return 1;
|
||||||
if(!length) return !error_top("Assembly", "Output rom is empty.");
|
if(!resolve(argv[2])) return 1;
|
||||||
if(!resolve()) return !error_top("Assembly", "Failed to resolve symbols.");
|
if(!build(argv[2])) return 1;
|
||||||
if(!build(argv[2])) return !error_top("Assembly", "Failed to build rom.");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue