mirror of https://git.sr.ht/~rabbits/uxn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
2.8 KiB
195 lines
2.8 KiB
#include <stdio.h> |
|
|
|
/* |
|
Copyright (c) 2021 Devine Lu Linvega |
|
|
|
Permission to use, copy, modify, and distribute this software for any |
|
purpose with or without fee is hereby granted, provided that the above |
|
copyright notice and this permission notice appear in all copies. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
WITH REGARD TO THIS SOFTWARE. |
|
*/ |
|
|
|
#define PRGLEN 256 |
|
|
|
typedef unsigned char Uint8; |
|
|
|
typedef struct { |
|
int len; |
|
Uint8 data[PRGLEN]; |
|
} Program; |
|
|
|
char labels[256][16]; |
|
|
|
char opcodes[][4] = { |
|
"BRK", |
|
"LIT", |
|
"---", |
|
"POP", |
|
"DUP", |
|
"SWP", |
|
"OVR", |
|
"ROT", |
|
/* */ |
|
"JMP", |
|
"JSR", |
|
"JEQ", |
|
"RTS", |
|
"EQU", |
|
"NEQ", |
|
"LTH", |
|
"GTH", |
|
/* */}; |
|
|
|
Program p; |
|
|
|
#pragma mark - Helpers |
|
|
|
int |
|
scmp(char *a, char *b) /* string compare */ |
|
{ |
|
int i = 0; |
|
while(a[i] == b[i]) |
|
if(!a[i++]) |
|
return 1; |
|
return 0; |
|
} |
|
|
|
char * |
|
suca(char *s) /* string to uppercase */ |
|
{ |
|
int i = 0; |
|
char c; |
|
while((c = s[i])) |
|
s[i++] = c >= 'a' && c <= 'z' ? c - ('a' - 'A') : c; |
|
return s; |
|
} |
|
|
|
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 1; |
|
} |
|
|
|
int |
|
shex(char *s) /* string to num */ |
|
{ |
|
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; |
|
} |
|
|
|
#pragma mark - Parser |
|
|
|
void |
|
addprg(Uint8 hex) |
|
{ |
|
p.data[p.len++] = hex; |
|
} |
|
|
|
void |
|
addlabel(char *id, Uint8 addr) |
|
{ |
|
printf("new label: %s=%02x\n", id, addr); |
|
} |
|
|
|
void |
|
addconst(char *id, Uint8 value) |
|
{ |
|
printf("new const: %s=%02x\n", id, value); |
|
} |
|
|
|
Uint8 |
|
findop(char *s) |
|
{ |
|
int i; |
|
for(i = 0; i < 16; ++i) |
|
if(scmp(opcodes[i], s)) |
|
return i; |
|
return 0; |
|
} |
|
|
|
int |
|
comment(char *w, int *skip) |
|
{ |
|
if(w[0] == '>') { |
|
*skip = 0; |
|
return 1; |
|
} |
|
if(w[0] == '<') *skip = 1; |
|
if(*skip) return 1; |
|
return 0; |
|
} |
|
|
|
void |
|
pass1(FILE *f) |
|
{ |
|
int skip = 0; |
|
char word[64]; |
|
while(fscanf(f, "%s", word) == 1) { |
|
if(comment(word, &skip)) |
|
continue; |
|
} |
|
rewind(f); |
|
} |
|
|
|
void |
|
pass2(FILE *f) |
|
{ |
|
int skip = 0; |
|
char word[64]; |
|
while(fscanf(f, "%s", word) == 1) { |
|
Uint8 op; |
|
suca(word); |
|
if(comment(word, &skip)) continue; |
|
if(word[0] == ']') continue; |
|
if(word[0] == '+') { |
|
addprg(0x01); |
|
addprg(1); |
|
addprg(shex(word + 1)); |
|
} else if(word[0] == '[') { |
|
addprg(0x01); |
|
addprg(shex(word + 1)); |
|
} else if((op = findop(word))) |
|
addprg(op); |
|
else if(sihx(word)) |
|
addprg(shex(word)); |
|
else if(scmp(word, "BRK")) |
|
addprg(0x00); |
|
else |
|
printf("unknown: %s\n", word); |
|
} |
|
} |
|
|
|
int |
|
error(char *name) |
|
{ |
|
printf("Error: %s\n", name); |
|
return 0; |
|
} |
|
|
|
int |
|
main(int argc, char *argv[]) |
|
{ |
|
FILE *f; |
|
if(argc < 3) |
|
return error("No input."); |
|
if(!(f = fopen(argv[1], "r"))) |
|
return error("Missing input."); |
|
pass1(f); |
|
pass2(f); |
|
fwrite(p.data, sizeof(p.data), 1, fopen(argv[2], "wb")); |
|
fclose(f); |
|
return 0; |
|
}
|
|
|