* for SM83
*/
-// define <name> r8, r8
+/* define <name> r8, r8 */
#define ULAS_INSTRSM83_R8R8(name, base_op, reg_left, reg_right) \
{ \
(name), {(reg_left), ',', (reg_right), 0}, { base_op, 0 } \
{(base_op) + 6, 0}}, \
ULAS_INSTRSM83_R8R8(name, (base_op) + 7, reg_left, ULAS_REGSM83_A)
-// <name> a, r8
+/* <name> a, r8 */
#define ULAS_INSTRSM83_ALUR8D(name, base_op) \
ULAS_INSTRSM83_R8R8D(name, base_op, ULAS_REGSM83_A)
(name), {(reg_left), ',', ULAS_E8, 0}, { (op), ULAS_E8, 0 } \
}
-// <name> r16, e16
+/* <name> r16, e16 */
#define ULAS_INSTRSM83_R16E16(name, op, reg_left) \
{ \
(name), {(reg_left), ',', ULAS_E16, 0}, { (op), ULAS_E16, 0 } \
}
-// <name> r16, a16
+/* <name> r16, a16 */
#define ULAS_INSTRSM83_R16A16(name, op, reg_left) \
{ \
(name), {(reg_left), ',', ULAS_A16, 0}, { (op), ULAS_A16, 0 } \
-// <name> reg
+/* <name> reg */
#define ULAS_INSTRSM83_REG(name, op, reg) \
{ \
(name), {(reg), 0}, { (op), 0x00 } \
}
-// prefixed <name> reg
+/* prefixed <name> reg */
#define ULAS_INSTRSM83_PRER8(name, base_op, reg_right) \
{ \
(name), {(reg_right), 0}, { 0xCB, base_op, 0 } \
{(name), {'[', ULAS_REGSM83_HL, ']', 0}, {0xCB, (base_op) + 6, 0}}, \
ULAS_INSTRSM83_PRER8(name, (base_op) + 7, ULAS_REGSM83_A)
-// prefixed <name> <bit>, reg
+/* prefixed <name> <bit>, reg */
#define ULAS_INSTRSM83_PREBITR8(name, base_op, bit, reg_right) \
{ \
(name), {(bit), ',', (reg_right), 0}, { 0xCB, base_op, 0 } \
{0xCB, (base_op) + 6, 0}}, \
ULAS_INSTRSM83_PREBITR8(name, (base_op) + 7, bit, ULAS_REGSM83_A)
-// all instructions
-// when name is NULL list ended
-// FIXME: Add ULAS_A16 and make all absolute calls/jumps A16 instead of E16
+/* all instructions
+ * when name is NULL list ended
+ * FIXME: Add ULAS_A16 and make all absolute calls/jumps A16 instead of E16
+ */
const struct ulas_instr ULASINSTRS_SM83[] = {
- // control instructions
+ /* control instructions */
{"nop", {0}, {(short)ULAS_DATZERO, 0}},
{"halt", {0}, {0x76, 0}},
{"stop", {0}, {0x10, (short)ULAS_DATZERO, 0x00}},
{"di", {0}, {0xF3, 0x00}},
{"ei", {0}, {0xFB, 0x00}},
- // misc
+ /* misc */
{"daa", {0}, {0x27, 0x00}},
{"scf", {0}, {0x37, 0x00}},
{"cpl", {0}, {0x2F, 0x00}},
{"ccf", {0}, {0x3F, 0x00}},
- // shift / bits
+ /* shift / bits */
{"rlca", {0}, {0x07, 0x00}},
{"rls", {0}, {0x17, 0x00}},
{"rrca", {0}, {0x0F, 0x00}},
{"rra", {0}, {0x1F, 0x00}},
- // ld r8, r8
+ /* ld r8, r8 */
ULAS_INSTRSM83_R8R8D("ld", 0x40, ULAS_REGSM83_B),
ULAS_INSTRSM83_R8R8D("ld", 0x48, ULAS_REGSM83_C),
ULAS_INSTRSM83_R8R8D("ld", 0x50, ULAS_REGSM83_D),
ULAS_INSTRSM83_R8R8D("ld", 0x68, ULAS_REGSM83_L),
ULAS_INSTRSM83_R8R8D("ld", 0x78, ULAS_REGSM83_A),
- // ld [r16], a
+ /* ld [r16], a */
{"ld", {'[', ULAS_REGSM83_BC, ']', ',', ULAS_REGSM83_A, 0}, {0x02, 0}},
{"ld", {'[', ULAS_REGSM83_DE, ']', ',', ULAS_REGSM83_A, 0}, {0x12, 0}},
{"ld", {'[', ULAS_REGSM83_HL, ']', ',', ULAS_REGSM83_A, 0}, {0x77, 0}},
{"ld", {'[', ULAS_REGSM83_HL, '-', ']', ',', ULAS_REGSM83_A, 0}, {0x32, 0}},
{"ld", {'[', ULAS_REGSM83_HL, ']', ',', ULAS_E8, 0}, {0x36, ULAS_E8, 0x00}},
- // ld a, [r16]
+ /* ld a, [r16] */
{"ld", {ULAS_REGSM83_A, ',', '[', ULAS_REGSM83_BC, ']', 0}, {0x0A, 0}},
{"ld", {ULAS_REGSM83_A, ',', '[', ULAS_REGSM83_DE, ']', 0}, {0x1A, 0}},
{"ld", {ULAS_REGSM83_A, ',', '[', ULAS_REGSM83_HL, '+', ']', 0}, {0x2A, 0}},
{"ldh", {'[', ULAS_A8, ']', ',', ULAS_REGSM83_A, 0}, {0xE0, ULAS_A8, 0}},
{"ldh", {ULAS_REGSM83_A, ',', '[', ULAS_A8, ']', 0}, {0xF0, ULAS_A8, 0}},
- // ld r8, e8
+ /* ld r8, e8 */
ULAS_INSTRSM83_R8_EXPR8("ld", 0x06, ULAS_REGSM83_B),
ULAS_INSTRSM83_R8_EXPR8("ld", 0x16, ULAS_REGSM83_D),
ULAS_INSTRSM83_R8_EXPR8("ld", 0x26, ULAS_REGSM83_H),
ULAS_INSTRSM83_R8_EXPR8("ld", 0x2E, ULAS_REGSM83_L),
ULAS_INSTRSM83_R8_EXPR8("ld", 0x3E, ULAS_REGSM83_A),
- // ld r16, e16
+ /* ld r16, e16 */
ULAS_INSTRSM83_R16E16("ld", 0x01, ULAS_REGSM83_BC),
ULAS_INSTRSM83_R16E16("ld", 0x11, ULAS_REGSM83_DE),
ULAS_INSTRSM83_R16E16("ld", 0x21, ULAS_REGSM83_HL),
ULAS_INSTRSM83_R16E16("ld", 0x31, ULAS_REGSM83_SP),
- // jr
+ /* jr */
ULAS_INSTRSM83_R8_EXPR8("jr", 0x20, ULAS_REGSM83_NOT_ZERO),
ULAS_INSTRSM83_R8_EXPR8("jr", 0x30, ULAS_REGSM83_NOT_CARRY),
ULAS_INSTRSM83_R8_EXPR8("jr", 0x28, ULAS_REGSM83_ZERO),
ULAS_INSTRSM83_R8_EXPR8("jr", 0x38, ULAS_REGSM83_CARRY),
{"jr", {ULAS_E8, 0}, {0x18, ULAS_E8, 0x00}},
- // ret
+ /* ret */
ULAS_INSTRSM83_REG("ret", 0xC0, ULAS_REGSM83_NOT_ZERO),
ULAS_INSTRSM83_REG("ret", 0xD0, ULAS_REGSM83_NOT_CARRY),
ULAS_INSTRSM83_REG("ret", 0xC8, ULAS_REGSM83_ZERO),
{"ret", {0}, {0xC9, 0x00}},
{"reti", {0}, {0xD9, 0x00}},
- // jp
+ /* jp */
ULAS_INSTRSM83_R16A16("jp", 0xC2, ULAS_REGSM83_NOT_ZERO),
ULAS_INSTRSM83_R16A16("jp", 0xD2, ULAS_REGSM83_NOT_CARRY),
ULAS_INSTRSM83_R16A16("jp", 0xCA, ULAS_REGSM83_ZERO),
{"jp", {ULAS_REGSM83_HL, 0}, {0xE9, 0x00}},
{"jp", {ULAS_A16, 0}, {0xC3, ULAS_A16, 0x00}},
- // call
+ /* call */
ULAS_INSTRSM83_R16A16("call", 0xC4, ULAS_REGSM83_NOT_ZERO),
ULAS_INSTRSM83_R16A16("call", 0xD4, ULAS_REGSM83_NOT_CARRY),
ULAS_INSTRSM83_R16A16("call", 0xCC, ULAS_REGSM83_ZERO),
ULAS_INSTRSM83_R16A16("call", 0xDC, ULAS_REGSM83_CARRY),
{"call", {ULAS_A16, 0}, {0xCD, ULAS_A16, 0x00}},
- // rst
+ /* rst */
ULAS_INSTRSM83_REG("rst", 0xC7, ULAS_VECSM83_00),
ULAS_INSTRSM83_REG("rst", 0xD7, ULAS_VECSM83_10),
ULAS_INSTRSM83_REG("rst", 0xE7, ULAS_VECSM83_20),
ULAS_INSTRSM83_REG("rst", 0xEF, ULAS_VECSM83_28),
ULAS_INSTRSM83_REG("rst", 0xFF, ULAS_VECSM83_38),
- // inc/dec
+ /* inc/dec */
ULAS_INSTRSM83_REG("inc", 0x03, ULAS_REGSM83_BC),
ULAS_INSTRSM83_REG("inc", 0x13, ULAS_REGSM83_DE),
ULAS_INSTRSM83_REG("inc", 0x23, ULAS_REGSM83_HL),
ULAS_INSTRSM83_REG("dec", 0x2D, ULAS_REGSM83_L),
ULAS_INSTRSM83_REG("dec", 0x3D, ULAS_REGSM83_A),
- // alu r8, r8
+ /* alu r8, r8 */
ULAS_INSTRSM83_ALUR8D("add", 0x80),
ULAS_INSTRSM83_ALUR8D("adc", 0x88),
ULAS_INSTRSM83_ALUR8D("sub", 0x90),
ULAS_INSTRSM83_R8_EXPR8("add", 0xE8, ULAS_REGSM83_SP),
- // alu r16, r16
+ /* alu r16, r16 */
ULAS_INSTRSM83_R16R16("add", 0x09, ULAS_REGSM83_HL, ULAS_REGSM83_BC),
ULAS_INSTRSM83_R16R16("add", 0x19, ULAS_REGSM83_HL, ULAS_REGSM83_DE),
ULAS_INSTRSM83_R16R16("add", 0x29, ULAS_REGSM83_HL, ULAS_REGSM83_HL),
ULAS_INSTRSM83_R16R16("add", 0x39, ULAS_REGSM83_HL, ULAS_REGSM83_SP),
- // pop
+ /* pop */
ULAS_INSTRSM83_REG("pop", 0xC1, ULAS_REGSM83_BC),
ULAS_INSTRSM83_REG("pop", 0xD1, ULAS_REGSM83_DE),
ULAS_INSTRSM83_REG("pop", 0xE1, ULAS_REGSM83_HL),
ULAS_INSTRSM83_REG("pop", 0xF1, ULAS_REGSM83_AF),
- // push
+ /* push */
ULAS_INSTRSM83_REG("push", 0xC5, ULAS_REGSM83_BC),
ULAS_INSTRSM83_REG("push", 0xD5, ULAS_REGSM83_DE),
ULAS_INSTRSM83_REG("push", 0xE5, ULAS_REGSM83_HL),
ULAS_INSTRSM83_REG("push", 0xF5, ULAS_REGSM83_AF),
- // prefixed
+ /* prefixed */
ULAS_INSTRSM83_PRER8D("swap", 0x30),
ULAS_INSTRSM83_PRER8D("rlc", 0x00),
ULAS_INSTRSM83_PRER8D("rrc", 0x08),
void ulas_arch_set(enum ulas_archs arch) {
switch (arch) {
case ULAS_ARCH_SM83:
- ulas.arch = (struct ulas_arch){arch, ULAS_SM83_REGS, ULAS_SM83_REGS_LEN,
- ULASINSTRS_SM83, ULAS_LE};
+ ulas.arch.type = arch;
+ ulas.arch.regs_names = ULAS_SM83_REGS;
+ ulas.arch.regs_len = ULAS_SM83_REGS_LEN;
+ ulas.arch.instrs = ULASINSTRS_SM83;
+ ulas.arch.endianess = ULAS_LE;
+
break;
default:
ULASPANIC("Unknown architecture\n");
#define ULAS_TEST_OPTS_ARG ""
#define ULAS_TOKMAX 64
-#define TESTBEGIN(name) printf("[test %s]\n", (name));
-#define TESTEND(name) printf("[%s ok]\n", (name));
+#define TESTBEGIN(name) { printf("[test %s]\n", (name)); }
+#define TESTEND(name) { printf("[%s ok]\n", (name)); }
-#define assert_tok(line, ...) \
+#define assert_tok(line, expect) \
{ \
- const char *expect[] = __VA_ARGS__; \
- unsigned long n = strlen(line); \
+ unsigned long expect_n, n = strlen(line); \
struct ulas_str dst = ulas_str(n); \
- memset(dst.buf, 0, n); \
int i = 0; \
const char *pline = line; \
- while (ulas_tok(&dst, &pline, n)) { \
+ memset(dst.buf, 0, n); \
+ while (ulas_tok(&dst, &pline, n)) { \
assert(expect[i]); \
assert(strcmp(dst.buf, expect[i]) == 0); \
i++; \
} \
- unsigned long expect_n = 0; \
+ expect_n = 0; \
for (expect_n = 0; expect[expect_n]; expect_n++) { \
} \
assert(i == expect_n); \
ulas_strfree(&dst); \
}
-#define assert_tokuntil(line, c, ...) \
+#define assert_tokuntil(line, c, expect) \
{ \
- const char *expect[] = __VA_ARGS__; \
- unsigned long n = strlen(line); \
+ const char *pline; \
+ unsigned long expect_n, n = strlen(line); \
struct ulas_str dst = ulas_str(n); \
- memset(dst.buf, 0, n); \
int i = 0; \
- const char *pline = line; \
+ pline = line; \
+ memset(dst.buf, 0, n); \
while (ulas_tokuntil(&dst, c, &pline, n)) { \
assert(expect[i]); \
assert(strcmp(dst.buf, expect[i]) == 0); \
i++; \
} \
- unsigned long expect_n = 0; \
+ expect_n = 0; \
for (expect_n = 0; expect[expect_n]; expect_n++) { \
} \
assert(i == expect_n); \
}
void test_tok(void) {
+ const char *expect1[] = {"test", "tokens", "with", ",", "line", "/", "*",
+ "+", "-", ",", ";", "$1", "$", "=",
+ "==", "!=", ">", "<", ">=", "<=", NULL};
+ const char *expect2[] = {"this is a", "test for tok ", "until", NULL};
TESTBEGIN("tok");
assert_tok(" test tokens with, line / * + - , ; $1 $ = == != > < >= <=",
- {"test", "tokens", "with", ",", "line", "/", "*",
- "+", "-", ",", ";", "$1", "$", "=",
- "==", "!=", ">", "<", ">=", "<=", NULL});
-
- assert_tokuntil(" this is a, test for tok , until", ',',
- {"this is a", "test for tok ", "until", NULL});
+ expect1);
+
+ assert_tokuntil(" this is a, test for tok , until", ',', expect2);
TESTEND("tok");
}
void test_strbuf(void) {
+ struct ulas_str s;
TESTBEGIN("strbuf");
-
- struct ulas_str s = ulas_str(5);
+
+ s = ulas_str(5);
assert(s.maxlen == 5);
assert(s.buf);
#define assert_preproc(expect_dst, expect_ret, input) \
{ \
+ FILE *src, *dst; \
+ char dstbuf[ULAS_LINEMAX]; \
ulas_preprocclear(&ulas.pp); \
ulas.pass = ULAS_PASS_RESOLVE; \
- char dstbuf[ULAS_LINEMAX]; \
memset(dstbuf, 0, ULAS_LINEMAX); \
- FILE *src = fmemopen((input), strlen((input)), "re"); \
- FILE *dst = fmemopen(dstbuf, ULAS_LINEMAX, "we"); \
+ src = fmemopen((input), strlen((input)), "re"); \
+ dst = fmemopen(dstbuf, ULAS_LINEMAX, "we"); \
assert(ulas_preproc(dst, src) == (expect_ret)); \
fclose(src); \
fclose(dst); \
ulascfg.preproc_only = 1;
TESTBEGIN("preproc");
- // no directive
+ /* no directive */
assert_preproc(" test line", 0, " test line");
- // define
+ /* define */
assert_preproc("123", 0, " #define test 123\ntest");
assert_preproc("this is a ", 0, " #define test\nthis is a test");
assert_preproc("", -1, " #define 1test 123\n");
assert_preproc("", -1, " #define\n");
assert_preproc("this is a 123 for defs", 0,
" #define test 123\nthis is a test for defs");
- // define used inside define
+ /* define used inside define */
assert_preproc(
"this is a 123 for defs", 0,
" #define ftest 123\n#define test ftest\nthis is a test for defs");
- // undefined
+ /* undefined */
assert_preproc("123\ntest", 0,
"#define test 123\ntest\n#undefine test\ntest");
- // macro
+ /* macro */
assert_preproc(
" line p1 1 label01,2 3\n line p2 2\n line p3 3 p1, p2, p3\n", 0,
"#macro test\n line $1 1 label$$$$,$$ $$\n line $2 2\n line $3 3 "
"#macro test\nmnested macro $1\n$1\n#macro "
"mnested\ncontent $1\n#endmacro\nafter\nmnested n1\n#endmacro\ntest t1");
- // this macro caused a heap buffer overflow in production code
+ /* this macro caused a heap buffer overflow in production code */
assert_preproc("ld a, verylongmacroinput & 0xFF\nld [hl+], a\nld a, "
"(verylongmacroinput >> 8) & 0xFF\nld [hl+], a\n",
0,
"($1 >> 8) & 0xFF\nld [hl+], a\n#endmacro\ntestlonginput "
"verylongmacroinput");
- // ifdef
+ /* ifdef */
assert_preproc(
"before\nifdeftest defined!\nafter", 0,
"before\n#define test\n#ifdef test\nifdeftest defined!\n#endif\nafter");
assert_preproc("ifdeftest defined!\n", -1,
"#define test\n#ifdef test\nifdeftest defined!\n");
- // ifndef
+ /* ifndef */
assert_preproc("before\nifndeftest defined!\nafter", 0,
"before\n#ifndef test\nifndeftest defined!\n#endif\nafter");
assert_preproc(
void test_totok(void) {
TESTBEGIN("totok");
- // regular ints
+ /* regular ints */
ASSERT_INT_TOTOK(10, 0, "10");
ASSERT_INT_TOTOK(0x1A, 0, "0x1A");
ASSERT_INT_TOTOK(5, 0, "0b101");
- // chars
+ /* chars */
ASSERT_INT_TOTOK('a', 0, "'a'");
ASSERT_INT_TOTOK('\n', 0, "'\\n'");
ASSERT_INT_TOTOK('\\', 0, "'\\\\'");
- // char - not terminated
+ /* char - not terminated */
ASSERT_INT_TOTOK('a', -1, "'a");
- // bad escape
+ /* bad escape */
ASSERT_INT_TOTOK(0, -1, "'\\z'");
- // unterminated escape
+ /* unterminated escape */
ASSERT_INT_TOTOK('\n', -1, "'\\n");
- // string token
+ /* string token */
ASSERT_STR_TOTOK("test", 0, "\"test\"");
ASSERT_STR_TOTOK("test\n", 0, "\"test\\n\"");
- // string with escape
+ /* string with escape */
ASSERT_STR_TOTOK("test\n\"123\"", 0, "\"test\\n\\\"123\\\"\"");
- // unterminated string
+ /* unterminated string */
ASSERT_STR_TOTOK("test\n\"123\"", -1, "\"test\\n\\\"123\\\"");
- // symbols
+ /* symbols */
ASSERT_SYMBOL_TOTOK("_symbol123", 0, "_symbol123");
ASSERT_SYMBOL_TOTOK("symbol123", 0, "symbol123");
ASSERT_UNEXPECTED_TOTOK(-1, "1symbol123");
- // generic tokens with no value
+ /* generic tokens with no value */
ASSERT_TOTOK(ULAS_EQ, 0, "==");
ASSERT_TOTOK(ULAS_NEQ, 0, "!=");
ASSERT_TOTOK('=', 0, "=");
#define ASSERT_INTEXPR(expected_val, expected_rc, expr) \
{ \
- int rc = 0; \
+ int val, rc = 0; \
const char *oexpr = expr; \
ulas.pass = ULAS_PASS_FINAL; \
- int val = ulas_intexpr(&oexpr, strlen((expr)), &rc); \
+ val = ulas_intexpr(&oexpr, strlen((expr)), &rc); \
assert(rc == (expected_rc)); \
assert(val == (expected_val)); \
}
#define ASSERT_STREXPR(expected_val, expected_rc, expr) \
{ \
int rc = 0; \
+ const char *val; \
const char *oexpr = expr; \
ulas.pass = ULAS_PASS_FINAL; \
- const char *val = ulas_strexpr(&oexpr, strlen((expr)), &rc); \
+ val = ulas_strexpr(&oexpr, strlen((expr)), &rc); \
assert(rc == (expected_rc)); \
assert(val); \
assert(strcmp((expected_val), val) == 0); \
TESTEND("strexpr");
}
-#define ASSERT_ASMINSTR(expect_len, line, ...) \
+#define ASSERT_ASMINSTR(expect_len, line, expect_dst) \
{ \
const char *l = line; \
- int n = strlen(l); \
+ int i, n = strlen(l); \
char dst[64]; \
- unsigned char expect_dst[] = {__VA_ARGS__}; \
int res = ulas_asminstr(dst, 64, &l, n); \
assert(res == expect_len); \
- for (int i = 0; i < res; i++) { \
+ for (i = 0; i < res; i++) { \
assert(expect_dst[i] == (unsigned char)dst[i]); \
} \
}
void test_asminstr(void) {
+ unsigned char expect_dst1[] = {0x00};
+ unsigned char expect_dst2[] = {0x76};
+ unsigned char expect_dst3[] = {0x41};
+ unsigned char expect_dst4[] = {0xF0, 0x03};
TESTBEGIN("asminstr");
- ASSERT_ASMINSTR(1, "nop", 0x00);
- ASSERT_ASMINSTR(1, "halt", 0x76);
- ASSERT_ASMINSTR(1, "ld b, c", 0x41);
- ASSERT_ASMINSTR(2, "ldh a, [1 + 2]", 0xF0, 0x03);
+ ASSERT_ASMINSTR(1, "nop", expect_dst1);
+ ASSERT_ASMINSTR(1, "halt", expect_dst2);
+ ASSERT_ASMINSTR(1, "ld b, c", expect_dst3);
+ ASSERT_ASMINSTR(2, "ldh a, [1 + 2]", expect_dst4);
TESTEND("asminstr");
}
void test_symscope(void) {
TESTBEGIN("symscope");
- // auto-scope
+ /* auto-scope */
ASSERT_SYMSCOPE(0, "t1:", -1, 1);
ASSERT_SYMSCOPE(-1, "t1:", -1, 1);
ASSERT_SYMSCOPE(0, "@t1:", -1, 1);
ASSERT_SYMSCOPE(-1, "@t1:", -1, 1);
- // manual scoping
+ /* manual scoping */
ASSERT_SYMSCOPE(0, "t2:", 5, 1);
ASSERT_SYMSCOPE(-1, "t2:", 5, 1);
ASSERT_SYMSCOPE(0, "t2:", 6, 1);
ASSERT_SYMSCOPE(-1, "t2:", 6, 1);
- // set
+ /* set */
ASSERT_SYMSCOPE(0, "t3:", -1, 0);
ASSERT_SYMSCOPE(0, "t3:", -1, 0);
#define ASSERT_FULL(expect_rc, in_path, expect_path) \
{ \
+ char dstbuf[ULAS_FULLEN]; \
+ char expect[ULAS_FULLEN]; \
+ FILE *expectf = fopen(expect_path, "re"); \
+ int i, expect_len; \
printf("[source: %s; expect: %s]\n", in_path, expect_path); \
ulaslstout = stdout; \
ulassymout = stdout; \
cfg.verbose = 1; \
- char dstbuf[ULAS_FULLEN]; \
- char expect[ULAS_FULLEN]; \
- FILE *expectf = fopen(expect_path, "re"); \
- int expect_len = fread(expect, 1, ULAS_FULLEN, expectf); \
+ expect_len = fread(expect, 1, ULAS_FULLEN, expectf); \
fclose(expectf); \
memset(dstbuf, 0, ULAS_FULLEN); \
ulasout = fmemopen(dstbuf, ULAS_FULLEN, "we"); \
ulasin = fopen(in_path, "re"); \
assert(ulas_main(cfg) == (expect_rc)); \
fclose(ulasout); \
- for (int i = 0; i < expect_len; i++) { \
- assert(expect[i] == dstbuf[i]); \
+ for (i = 0; i < expect_len; i++) { \
+ assert(expect[i] == dstbuf[i]); \
if (cfg.disas) { \
putchar(dstbuf[i]); /* for easier debugging in disas mode */ \
} \
} \
- for (int i = expect_len; i < ULAS_FULLEN; i++) { \
+ for (i = expect_len; i < ULAS_FULLEN; i++) { \
assert(dstbuf[i] == 0); \
} \
ulasin = stdin; \
ASSERT_FULL(expect_rc, in_path, expect_path) \
}
-// tests the entire stack
+/* tests the entire stack */
void test_full_asm(void) {
TESTBEGIN("testfullasm");
#define ASSERT_FULL_ASM_FAIL(expect_rc, in_path) \
{ \
+ char dstbuf[ULAS_FULLEN]; \
struct ulas_config cfg = ulas_cfg_from_env(); \
printf("[source: %s;]\n", in_path); \
ulaslstout = stdout; \
ulassymout = stdout; \
cfg.verbose = 1; \
- char dstbuf[ULAS_FULLEN]; \
memset(dstbuf, 0, ULAS_FULLEN); \
ulasout = fmemopen(dstbuf, ULAS_FULLEN, "we"); \
ulasin = fopen(in_path, "re"); \
ulas_free();
- // this will re-init everything on its own,
- // so call after free
+ /* this will re-init everything on its own,
+ so call after free */
test_full_dasm();
test_full_asm_fail();
test_full_asm();
void ulas_version(void) { printf("%s version %s\n", ULAS_NAME, ULAS_VER); }
void ulas_init(struct ulas_config cfg) {
- // init global cfg
+ int i;
+ /* init global cfg */
if (ulasin == NULL) {
ulasin = stdin;
}
ulascfg = cfg;
- // init assembly context
+ /* init assembly context */
memset(&ulas, 0, sizeof(ulas));
ulas.tok = ulas_str(8);
ulas.pp = ulas_preprocinit();
ulas.scope = 1;
- for (int i = 0; i < ULAS_CHARCODEMAPLEN; i++) {
+ for (i = 0; i < ULAS_CHARCODEMAPLEN; i++) {
ulas.charcodemap[i] = (char)i;
}
ulas_arch_set(ULAS_ARCH_SM83);
}
void ulas_nextpass(void) {
+ int i;
ulas.scope = 1;
ulas.line = 0;
ulas.icntr = 0;
ulas.address = ulascfg.org;
ulas.chksm = 0;
ulas.filename = ulas.initial_filename;
- ulas.section[0] = '\0'; // reset section
+ ulas.section[0] = '\0'; /* reset section */
ulas.section_address = 0;
- for (int i = 0; i < ULAS_CHARCODEMAPLEN; i++) {
+ for (i = 0; i < ULAS_CHARCODEMAPLEN; i++) {
ulas.charcodemap[i] = (char)i;
}
}
unsigned int ulas_strlcat(char *dst, const char *src, unsigned int max) {
unsigned int dst_len = ulas_strnlen(dst, max);
unsigned int src_len = ulas_strnlen(src, max);
+ int i;
- for (int i = 0; i < src_len; i++) {
+ for (i = 0; i < src_len; i++) {
dst[dst_len+i] = src[i];
}
FILE *ulas_incpathfopen(const char *path, const char *mode) {
char pathbuf[ULAS_PATHMAX];
- memset(pathbuf, 0, ULAS_PATHMAX);
+ FILE *f;
+ int i;
unsigned long baselen = strlen(path);
+ memset(pathbuf, 0, ULAS_PATHMAX);
- // check all include paths
- for (int i = 0; i < ulascfg.incpathslen; i++) {
- pathbuf[0] = '\0';
+ /* check all include paths */
+ for (i = 0; i < ulascfg.incpathslen; i++) {
char *ip = ulascfg.incpaths[i];
unsigned long len = strlen(ip);
+ pathbuf[0] = '\0';
if (len + baselen + 1 >= ULAS_PATHMAX) {
continue;
}
}
ulas_strlcat(pathbuf, path, ULAS_PATHMAX);
- FILE *f = fopen(pathbuf, mode);
+ f = fopen(pathbuf, mode);
if (f != NULL) {
return f;
}
}
- // check the original path last
- FILE *f = fopen(path, mode);
+ /* check the original path last */
+ f = fopen(path, mode);
if (f == NULL) {
ULASERR("%s: %s\n", path, strerror(errno));
}
}
FILE *ulas_fopen(const char *path, const char *mode, FILE *stdfile) {
+ FILE *f;
if (!path || strncmp(path, ULAS_STDFILEPATH, 1) == 0) {
return stdfile;
}
- FILE *f = fopen(path, mode);
+ f = fopen(path, mode);
if (!f) {
ULASPANIC("%s: %s\n", path, strerror(errno));
fclose(f);
}
-long long ulas_timeusec(void) {
+long ulas_timeusec(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return 1000000 * tv.tv_sec + tv.tv_usec;
}
int ulas_main(struct ulas_config cfg) {
- long long total_startusec = ulas_timeusec();
+ long total_startusec = ulas_timeusec();
+ long total_endusec;
int rc = 0;
+ FILE *preprocdst;
+
ulas_init(cfg);
if (cfg.output_path) {
ULASDBG("output: %s\n", cfg.output_path);
ULASDBG("input: %s\n", cfg.argv[0]);
ulasin = ulas_fopen(cfg.argv[0], "re", stdin);
}
- FILE *preprocdst = NULL;
+ preprocdst = NULL;
- // only do 2 pass if we have a file as input
- // because we cannot really rewind stdout
+ /* only do 2 pass if we have a file as input
+ * because we cannot really rewind stdout
+ */
if (!cfg.preproc_only && ulasin != stdin) {
ulas.pass = ULAS_PASS_RESOLVE;
}
ulas_nextpass();
- // FIXME: it would be nice if we could do the 2 pass by clearing the
- // tmpfile instead of making an entierly new one
+ /* FIXME: it would be nice if we could do the 2 pass by clearing the
+ * tmpfile instead of making an entierly new one
+ */
if (cfg.preproc_only) {
preprocdst = ulasout;
} else {
ulas_free();
- long long total_endusec = ulas_timeusec();
+ total_endusec = ulas_timeusec();
if (ulascfg.verbose) {
- fprintf(ulaserr, "[Completed in %lld ms]\n",
- (total_endusec - total_startusec) / 1000);
+ fprintf(ulaserr, "[Completed in %ld ms]\n",
+ (long int)((total_endusec - total_startusec) / 1000));
}
return rc;
}
int ulas_isname(const char *tok, unsigned long n) {
+ unsigned long i;
if (n == 0) {
return 0;
}
return 0;
}
- for (unsigned long i = 0; i < n && tok[i]; i++) {
+ for (i = 0; i < n && tok[i]; i++) {
char c = tok[i];
if (c != '_' && !isalnum(c) &&
!(i == 0 && c == ULAS_TOK_SCOPED_SYMBOL_BEGIN)) {
}
struct ulas_sym *ulas_symbolresolve(const char *name, int scope, int *rc) {
- for (int i = 0; i < ulas.syms.len; i++) {
+ int i;
+ for (i = 0; i < ulas.syms.len; i++) {
struct ulas_sym *sym = &ulas.syms.buf[i];
- // when scope is the same as the current one, or scope 0 (global)
+ /* when scope is the same as the current one, or scope 0 (global) */
if ((sym->scope == 0 || sym->scope == scope) &&
strcmp(name, sym->name) == 0) {
return sym;
int ulas_symbolset(const char *cname, int scope, struct ulas_tok tok,
int constant) {
- // remove : from name
+ struct ulas_sym *existing;
+ int rc = 0;
+ int resolve_rc = 0;
+ unsigned long len;
+
+ /* remove : from name */
char name[ULAS_SYMNAMEMAX];
memset(name, 0, ULAS_SYMNAMEMAX);
- unsigned long len = strlen(cname);
+ len = strlen(cname);
assert(len < ULAS_SYMNAMEMAX);
strncpy(name, cname, len);
if (name[len - 1] == ':') {
name[len - 1] = '\0';
}
- int rc = 0;
- int resolve_rc = 0;
- // auto-determine scope
+ /* auto-determine scope */
if (scope == -1) {
if (name[0] == ULAS_TOK_SCOPED_SYMBOL_BEGIN) {
scope = ulas.scope;
}
}
- struct ulas_sym *existing = ulas_symbolresolve(name, scope, &resolve_rc);
- // inc scope when symbol is global
+ existing = ulas_symbolresolve(name, scope, &resolve_rc);
+ /* inc scope when symbol is global */
if (name[0] != ULAS_TOK_SCOPED_SYMBOL_BEGIN && cname[len - 1] == ':') {
ulas.scope++;
}
if (!existing || (name[0] == '\0' && len == 1)) {
- // def new symbol
- struct ulas_sym new_sym = {ulas_strndup(name, len), tok, scope, ulas.pass,
- constant};
+ /* def new symbol */
+ struct ulas_sym new_sym;
+ new_sym.name = ulas_strndup(name, len);
+ new_sym.tok = tok;
+ new_sym.scope = scope;
+ new_sym.lastdefin = ulas.pass,
+ new_sym.constant = constant;
+
ulas_symbufpush(&ulas.syms, new_sym);
rc = ulas_symbolout(ulassymout, &new_sym);
} else if (existing->lastdefin != ulas.pass || !existing->constant) {
- // redefine if not defined this pass
+ /* redefine if not defined this pass */
existing->lastdefin = ulas.pass;
ulas_tokfree(&existing->tok);
existing->tok = tok;
rc = ulas_symbolout(ulassymout, existing);
} else {
- // exists.. cannot have duplicates!
+ /* exists.. cannot have duplicates! */
rc = -1;
ULASERR("Redefenition of symbol '%s' in scope %d\n", name, scope);
}
if (ulas.section[0] != '\0') {
const char *section = ulas.section;
- // statically map some ulas section names to mlb sections
+ /* statically map some ulas section names to mlb sections */
if (strncmp(ULAS_MLB_SECTION_PRGROM, ulas.section, ULAS_SECTIONMAX) == 0) {
section = "GbPrgRom";
} else if (strncmp(ULAS_MLB_SECTION_WORKRAM, ulas.section,
return 0;
}
- // fallback
- // if no previous section was declared we fall back to the
- // old default output
+ /* fallback
+ * if no previous section was declared we fall back to the
+ * old default output
+ */
switch (ulas.arch.type) {
case ULAS_ARCH_SM83:
if (addr >= 0x0000 && addr <= 0x7FFF) {
}
int ulas_symbolout(FILE *dst, struct ulas_sym *s) {
+ int rc = 0;
if (!dst || ulas.pass != ULAS_PASS_FINAL) {
return 0;
}
- int rc = 0;
-
switch (ulascfg.sym_fmt) {
case ULAS_SYM_FMT_DEFAULT:
if (!s->name || s->name[0] == '\0') {
#define ULAS_TOKISTERM write
#define ULAS_TOKCOND (i < n && write < n && line[i])
#define ULAS_QUOTED_TOKEN(quote_char) { \
- dst->buf[write++] = line[i++];\
int last_escape = 0;\
+ dst->buf[write++] = line[i++];\
while (ULAS_TOKCOND && (line[i] != (quote_char) || last_escape)) {\
last_escape = line[i] == '\\';\
dst->buf[write++] = line[i];\
int ulas_tok(struct ulas_str *dst, const char **out_line, unsigned long n) {
const char *line = *out_line;
- ulas_strensr(dst, n + 1);
-
int i = 0;
int write = 0;
- // always skip leading terminators
+ ulas_strensr(dst, n + 1);
+
+ /* always skip leading terminators */
while (ULAS_TOKCOND && isspace(line[i])) {
i++;
}
- // string token
+ /* string token */
if (line[i] == '"') {
ULAS_QUOTED_TOKEN('\"');
} else if (line[i] == '\'') {
if (ULAS_TOKISTERM) {
goto tokdone;
}
- // single char tokens
+ /* single char tokens */
dst->buf[write++] = line[i++];
goto tokdone;
case '$':
if (ULAS_TOKISTERM) {
goto tokdone;
}
- // special var for preprocessor
- // make sure we have enough space in buffer
+ /* special var for preprocessor
+ * make sure we have enough space in buffer
+ */
ulas_strensr(dst, write + 2);
- // escape char tokens
+ /* escape char tokens */
dst->buf[write++] = line[i++];
if (line[i] == '$') {
dst->buf[write++] = line[i++];
return i;
}
-// tokenize until the char c is seen
-// this will also consume c and out_line will point to the next valid char
-// this is useful if the next expected token is well defined and we want to
-// capture everything between
-// will remove leading white spaces
+/* tokenize until the char c is seen
+ * this will also consume c and out_line will point to the next valid char
+ * this is useful if the next expected token is well defined and we want to
+ * capture everything between
+ * will remove leading white spaces
+ */
int ulas_tokuntil(struct ulas_str *dst, char c, const char **out_line,
unsigned long n) {
const char *line = *out_line;
- ulas_strensr(dst, n + 1);
-
int i = 0;
int write = 0;
+ ulas_strensr(dst, n + 1);
+
while (ULAS_TOKCOND && isspace(line[i])) {
i++;
}
struct ulas_tok ulas_totok(char *buf, unsigned long n, int *rc) {
struct ulas_tok tok;
+ long i = 0;
+ unsigned char first;
memset(&tok, 0, sizeof(tok));
if (n == 0) {
goto end;
}
- unsigned char first = buf[0];
+ first = buf[0];
buf++;
if (n == 1 && !isalnum(first)) {
- // single char tokens
+ /* single char tokens */
tok.type = first;
} else {
switch (first) {
case '"':
- // string
+ /* string */
tok.type = ULAS_STR;
- // FIXME: this likely mallocs a few extra bytes
- // but honestly its probably fine
+ /* FIXME: this likely mallocs a few extra bytes
+ * but honestly its probably fine
+ */
tok.val.strv = malloc(n * sizeof(char) + 1);
memset(tok.val.strv, 0, n);
- long i = 0;
+ i = 0;
while (*buf && *buf != '\"') {
if (*buf == '\\') {
buf++;
break;
default:
if (isdigit(first)) {
- // integer
+ /* integer */
tok.type = ULAS_INT;
- // 0b prefix is not supported in strtol... so we implement it by hand
+ /* 0b prefix is not supported in strtol... so we implement it by hand */
if (*buf == 'b') {
buf++;
tok.val.intv = (int)strtol(buf, &buf, 2);
buf++;
break;
} else if (ulas_isname(buf - 1, n)) {
- // literal token
- // we resolve it later, will need to malloc here for now
+ /* literal token
+ * we resolve it later, will need to malloc here for now
+ */
tok.type = ULAS_SYMBOL;
tok.val.strv = ulas_strndup(buf - 1, n);
buf += n - 1;
}
end:
- // did we consume the entire token?
+ /* did we consume the entire token? */
if (buf[0] != '\0') {
*rc = -1;
}
#undef ULAS_TOKISTERM
struct ulas_str ulas_str(unsigned long n) {
- struct ulas_str str = {malloc(n), n};
+ struct ulas_str str;
+ str.buf = malloc(n);
+ str.maxlen = n;
return str;
}
struct ulas_ppdef *ulas_preprocgetdef(struct ulas_preproc *pp, const char *name,
unsigned long maxlen) {
- for (unsigned long i = 0; i < pp->defslen; i++) {
+ unsigned long i;
+ for (i = 0; i < pp->defslen; i++) {
struct ulas_ppdef *def = &pp->defs[i];
if (!def->undef && strncmp(def->name, name, maxlen) == 0) {
return def;
return NULL;
}
-// inserts all leading white space from praw_line into linebuf
+/* inserts all leading white space from praw_line into linebuf */
int ulas_preproclws(struct ulas_preproc *pp, const char *praw_line,
unsigned long maxlen) {
int i = 0;
if (buflen == 0) {
return;
}
- // remove trailing new line if present
+ /* remove trailing new line if present */
while (buf[buflen - 1] == '\n') {
buf[buflen - 1] = '\0';
buflen--;
char *ulas_preprocexpand2(struct ulas_preproc *pp, const char *raw_line,
unsigned long *n, int recursive);
void ulas_preprocexpand_rec(struct ulas_preproc *pp) {
- // expand macro result again to allow
- // defines to appear in the macro
+ unsigned long n;
+ /* expand macro result again to allow
+ * defines to appear in the macro
+ */
ulas_strensr(&pp->line2, strlen(pp->line.buf) + 1);
sprintf(pp->line2.buf, "%s", pp->line.buf);
- unsigned long n = strlen(pp->line.buf);
+ n = strlen(pp->line.buf);
pp->exp_depth++;
if (pp->exp_depth > ULAS_PREPROC_MAX_MACRO_DEPTH) {
ULASERR("Max macro recursion depth reached\n");
char *ulas_preprocexpand2(struct ulas_preproc *pp, const char *raw_line,
unsigned long *n, int recursive) {
+ const char *macro_argname[ULAS_MACROPARAMMAX] = {
+ "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
+ "$9", "$10", "$11", "$12", "$13", "$14", "$15"};
const char *praw_line = raw_line;
- memset(pp->line.buf, 0, pp->line.maxlen);
int read = 0;
int first_tok = 1;
int skip_next_tok = 0;
int comment_seen = 0;
+ unsigned long mi;
+ unsigned long i;
+ memset(pp->line.buf, 0, pp->line.maxlen);
- // go through all tokens, see if a define matches the token,
- // if so expand it
- // only expand macros if they match toks[0] though!
- // otherwise memcpy the read bytes 1:1 into the new string
+ /* go through all tokens, see if a define matches the token,
+ * if so expand it
+ * only expand macros if they match toks[0] though!
+ * otherwise memcpy the read bytes 1:1 into the new string
+ */
while ((read = ulas_tok(&pp->tok, &praw_line, *n))) {
- // remove comment seen if raw line
- // starts a new line
- // this fixes expnasion in macros containing comments
- // also make sure the next char is not 0
+ struct ulas_ppdef *def;
+ /* remove comment seen if raw line
+ * starts a new line
+ * this fixes expnasion in macros containing comments
+ * also make sure the next char is not 0
+ */
if (*praw_line == '\n' && praw_line[1]) {
comment_seen = 0;
}
- struct ulas_ppdef *def =
+ def =
ulas_preprocgetdef(pp, pp->tok.buf, pp->tok.maxlen);
- // if it is the first token, and it begins with a # do not process at all!
- // if the first token is a # preproc directive skip the second token at all
- // times
+ /* if it is the first token, and it begins with a # do not process at all!
+ * if the first token is a # preproc directive skip the second token at all
+ * times
+ */
if ((first_tok && pp->tok.buf[0] == ULAS_TOK_PREPROC_BEGIN) ||
skip_next_tok) {
def = NULL;
skip_next_tok = !skip_next_tok;
} else if (pp->tok.buf[0] == ULAS_TOK_COMMENT) {
- // if its a comment at the end of a preproc statement
- // just bail now
+ /* if its a comment at the end of a preproc statement
+ * just bail now
+ */
comment_seen = 1;
}
first_tok = 0;
if (def && !comment_seen) {
- // if so... expand now and leave
+ /* if so... expand now and leave */
switch (def->type) {
case ULAS_PPDEF: {
unsigned long val_len = strlen(def->value);
int wsi = ulas_preproclws(pp, praw_line - read, *n);
if (val_len) {
- // make sure to include leading white space
- // adjust total length
+ /* make sure to include leading white space
+ * adjust total length
+ */
*n -= strlen(pp->tok.buf);
*n += val_len;
ulas_strensr(&pp->line, (*n) + 1 + wsi);
- // only remove the first white space char if the lenght of value
- // is greater than 1, otherwise just leave it be...
+ /* only remove the first white space char if the lenght of value
+ * is greater than 1, otherwise just leave it be...
+ */
if (val_len > 1) {
strncat(pp->line.buf, def->value + 1, val_len - 1);
} else {
break;
}
case ULAS_PPMACRO: {
- // TODO: i am sure we can optimize the resize of line buffers here...
- // TODO: allow recursive macro calls
-
- // get 9 comma separated values.
- // $1-$9 will reference the respective arg
- // $0 will reference the entire line after the macro name
- // there can be more than 9 args, but anything after the 9th arg can
- // only be accessed via $0
+ const char *val;
+ unsigned long vallen;
+ unsigned long valread;
+ const char *tocat;
+ unsigned long tocatlen;
+ int paramc;
+
+ /* TODO: i am sure we can optimize the resize of line buffers here...
+ * TODO: allow recursive macro calls
+ */
+
+ /* get 9 comma separated values.
+ * $1-$9 will reference the respective arg
+ * $0 will reference the entire line after the macro name
+ * there can be more than 9 args, but anything after the 9th arg can
+ * only be accessed via $0
+ */
const char *line = praw_line;
unsigned long linelen = strlen(praw_line);
- // clear all params from previous attempt
- for (unsigned long i = 0; i < ULAS_MACROPARAMMAX; i++) {
+ /* clear all params from previous attempt */
+ for (i = 0; i < ULAS_MACROPARAMMAX; i++) {
pp->macroparam[i].buf[0] = '\0';
}
- // loop until 9 args are found or the line ends
- int paramc = 0;
+ /* loop until 9 args are found or the line ends */
+ paramc = 0;
while (paramc < ULAS_MACROPARAMMAX &&
- // TODO: allow escaping , with \,
+ /* TODO: allow escaping , with \, */
ulas_tokuntil(&pp->macroparam[paramc], ',', &praw_line, *n) >
0) {
- // trim new lines from the end of macro params
+ /* trim new lines from the end of macro params */
ulas_trimend('\n', pp->macroparam[paramc].buf,
strlen(pp->macroparam[paramc].buf));
paramc++;
}
ulas_strensr(&pp->line, strlen(def->value) + 2);
- const char *macro_argname[ULAS_MACROPARAMMAX] = {
- "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
- "$9", "$10", "$11", "$12", "$13", "$14", "$15"};
-
- const char *val = def->value;
- unsigned long vallen = strlen(def->value);
- unsigned long valread = 0;
+ val = def->value;
+ vallen = strlen(def->value);
+ valread = 0;
- // the pointer to tocat will be the variable's value if any
- // exists
- const char *tocat = NULL;
- unsigned long tocatlen = 0;
+ /* the pointer to tocat will be the variable's value if any
+ * exists
+ */
+ tocat = NULL;
+ tocatlen = 0;
- // always start an expanded macro with a new line
- // to ensure expansion are separated if we are in a recursive call
- // this fixes new lines in recursive macros being consumed
+ /* always start an expanded macro with a new line
+ * to ensure expansion are separated if we are in a recursive call
+ * this fixes new lines in recursive macros being consumed
+ */
if (recursive) {
int len = ulas_strnlen(pp->line.buf, pp->line.maxlen) + 1;
ulas_strensr(&pp->line,
}
- // now tokenize the macro's value and look for $0-$9
- // and replace those instances
- // eveyrthing else will just be copied as is
+ /* now tokenize the macro's value and look for $0-$9
+ * and replace those instances
+ * eveyrthing else will just be copied as is
+ */
while ((valread = ulas_tok(&pp->macrobuf, &val, vallen)) > 0) {
- tocat = NULL;
char numbuf[128];
+ tocat = NULL;
- // decide what tocat should be
- for (unsigned long mi = 0; mi < ULAS_MACROPARAMMAX; mi++) {
+ /* decide what tocat should be */
+ for (mi = 0; mi < ULAS_MACROPARAMMAX; mi++) {
const char *name = macro_argname[mi];
if (pp->macroparam[mi].buf[0] &&
strncmp((name), pp->macrobuf.buf, pp->macrobuf.maxlen) == 0) {
ulas_strnlen(pp->line.buf, pp->line.maxlen) + linelen + 1);
if (linelen > 1) {
- // this skips the separating token which is usually a space
- // all further spaces are included though!
+ /* this skips the separating token which is usually a space
+ * all further spaces are included though!
+ */
tocat = line + 1;
tocatlen = linelen - 1;
} else {
- // do not do this if the line is literally empty!
+ /* do not do this if the line is literally empty! */
tocat = line;
tocatlen = linelen;
}
ulas_strensr(&pp->line, strlen(pp->line.buf) + valread + 1);
strncat(pp->line.buf, val - valread, valread);
} else {
- // make sure to include leading white space
+ /* make sure to include leading white space */
int wsi = ulas_preproclws(pp, val - valread, vallen);
ulas_strensr(&pp->line, ulas_strnlen(pp->line.buf, pp->line.maxlen) +
tocatlen + wsi + 1);
}
} else {
- // if not found: copy everythin from prev to the current raw_line point -
- // tok lenght -> this keeps the line in-tact as is
+ /* if not found: copy everythin from prev to the current raw_line point -
+ * tok lenght -> this keeps the line in-tact as is
+ */
ulas_strensr(&pp->line, (*n) + 1);
strncat(pp->line.buf, praw_line - read, read);
}
}
int ulas_preprocdef(struct ulas_preproc *pp, struct ulas_ppdef def) {
+ void *defs;
pp->defslen++;
- void *defs = realloc(pp->defs, pp->defslen * sizeof(struct ulas_ppdef));
+ defs = realloc(pp->defs, pp->defslen * sizeof(struct ulas_ppdef));
if (!defs) {
ULASPANIC("%s\n", strerror(errno));
}
*/
char *line = ulas_preprocexpand(pp, raw_line, &n);
const char *pline = line;
+ unsigned long i;
const char *dirstrs[] = {
ULAS_PPSTR_DEF, ULAS_PPSTR_MACRO, ULAS_PPSTR_IFDEF,
enum ulas_ppdirs found_dir = ULAS_PPDIR_NONE;
- // check if the first token is any of the valid preproc directives
+ /* check if the first token is any of the valid preproc directives */
if (ulas_tok(&pp->tok, &pline, n)) {
- // not a preproc directive...
+ /* not a preproc directive... */
if (pp->tok.buf[0] != ULAS_TOK_PREPROC_BEGIN) {
goto found;
}
- for (unsigned long i = 0; dirstrs[i]; i++) {
+ for (i = 0; dirstrs[i]; i++) {
if (strncmp(dirstrs[i], pp->tok.buf, pp->tok.maxlen) == 0) {
found_dir = dirs[i];
goto found;
ulas_trimend('\n', line, strlen(line));
switch (found_dir) {
case ULAS_PPDIR_DEF: {
- // next token is a name
- // and then the entire remainder of the line is a value
+ struct ulas_ppdef def;
+ /* next token is a name
+ * and then the entire remainder of the line is a value
+ */
if (ulas_tok(&pp->tok, &pline, n) == 0) {
ULASERR("Expected name for #define\n");
return -1;
return -1;
}
- struct ulas_ppdef def = {ULAS_PPDEF, ulas_strdup(pp->tok.buf),
- ulas_strdup(pline),
- 0};
+ def.type = ULAS_PPDEF;
+ def.name = ulas_strdup(pp->tok.buf);
+ def.value = ulas_strdup(pline);
+ def.undef = 0;
ulas_preprocdef(pp, def);
- // define short-circuits the rest of the logic
- // because it just takes the entire rest of the line as a value!
+ /* define short-circuits the rest of the logic
+ * because it just takes the entire rest of the line as a value!
+ */
goto dirdone;
}
case ULAS_PPDIR_MACRO: {
- // get a name, ensure no more tokens come after
- // and then consume lines until ENDMACRO is seen
+ struct ulas_ppdef def;
+ int rc;
+ char buf[ULAS_LINEMAX];
+ char *name;
+ struct ulas_str val;
+ /* get a name, ensure no more tokens come after
+ * and then consume lines until ENDMACRO is seen
+ */
if (ulas_tok(&pp->tok, &pline, n) == 0) {
ULASERR("Expected name for #macro\n");
return -1;
ULASERR("'%s' is not a valid #macro name!\n", pp->tok.buf);
return -1;
}
- char *name = ulas_strdup(pp->tok.buf);
+ name = ulas_strdup(pp->tok.buf);
- struct ulas_str val = ulas_str(32);
+ val = ulas_str(32);
memset(val.buf, 0, 32);
- char buf[ULAS_LINEMAX];
memset(buf, 0, ULAS_LINEMAX);
- // consume lines until #endmacro is read
- // if reaching end of input without #endmacro we have an unterminated
- // macro. pass NULL as dst to consume lines that are being read instead of
- // echoing them back
- int rc = 0;
+ /* consume lines until #endmacro is read
+ * if reaching end of input without #endmacro we have an unterminated
+ * macro. pass NULL as dst to consume lines that are being read instead of
+ * echoing them back
+ */
+ rc = 0;
while ((rc = ulas_preprocnext(pp, NULL, src, buf, ULAS_LINEMAX)) > 0) {
+ unsigned long len;
if (rc == ULAS_PPDIR_ENDMACRO) {
- // we need to clear the line buffer to now echo back
- // the #endmacro directive
+ /* we need to clear the line buffer to now echo back
+ * the #endmacro directive
+ */
pp->line.buf[0] = '\0';
break;
}
- unsigned long len = ulas_strnlen(pp->line.buf, pp->line.maxlen);
+ len = ulas_strnlen(pp->line.buf, pp->line.maxlen);
ulas_strensr(&val, ulas_strnlen(val.buf, val.maxlen) + len + 1);
strncat(val.buf, pp->line.buf, val.maxlen);
}
free(name);
return -1;
}
- // we leak the str's buffer into the def now
- // this is ok because we call free for it later anyway
- struct ulas_ppdef def = {ULAS_PPMACRO, name, val.buf, 0};
+ /* we leak the str's buffer into the def now
+ * this is ok because we call free for it later anyway
+ */
+ def.type = ULAS_PPMACRO;
+ def.name = name;
+ def.value = val.buf;
+ def.undef = 0;
ulas_preprocdef(pp, def);
goto dirdone;
break;
case ULAS_PPDIR_IFDEF:
case ULAS_PPDIR_IFNDEF: {
- // get the name
- // get a name, ensure no more tokens come after
- // and then consume lines until ENDMACRO is seen
+ FILE *defdst;
+ int rc;
+ struct ulas_ppdef *def;
+ char buf[ULAS_LINEMAX];
+ /* get the name
+ * get a name, ensure no more tokens come after
+ * and then consume lines until ENDMACRO is seen
+ */
if (ulas_tok(&pp->tok, &pline, n) == 0) {
ULASERR("Expected name for #if(n)def\n");
return -1;
}
- struct ulas_ppdef *def =
+ def =
ulas_preprocgetdef(pp, pp->tok.buf, pp->tok.maxlen);
- char buf[ULAS_LINEMAX];
memset(buf, 0, ULAS_LINEMAX);
- FILE *defdst = NULL;
+ defdst = NULL;
if ((def && found_dir == ULAS_PPDIR_IFDEF) ||
(!def && found_dir == ULAS_PPDIR_IFNDEF)) {
defdst = dst;
}
- // loop until end of line or endif
- int rc = 0;
+ /* loop until end of line or endif */
+ rc = 0;
while ((rc = ulas_preprocnext(pp, defdst, src, buf, ULAS_LINEMAX)) > 0) {
if (rc == ULAS_PPDIR_ENDIF) {
- // we need to clear the line buffer to now echo back
- // the #endif directive
+ /* we need to clear the line buffer to now echo back
+ * the #endif directive
+ */
pp->line.buf[0] = '\0';
break;
}
goto dirdone;
}
case ULAS_PPDIR_UNDEF: {
+ struct ulas_ppdef *def;
if (ulas_tok(&pp->tok, &pline, n) == 0) {
ULASERR("Expected name for #undef\n");
return -1;
}
- struct ulas_ppdef *def = NULL;
+ def = NULL;
while ((def = ulas_preprocgetdef(pp, pp->tok.buf, pp->tok.maxlen))) {
def->undef = 1;
}
break;
}
case ULAS_PPDIR_INCLUDE: {
+ FILE *tmp, *f;
int rc = found_dir;
+ unsigned long prev_lines;
+ char *prev_path;
char *path = ulas_strexpr(&pline, strlen(pline), &rc);
if (rc == -1 || !path) {
return rc;
}
- FILE *f = ulas_incpathfopen(path, "re");
+ f = ulas_incpathfopen(path, "re");
if (!f) {
return -1;
}
- char *prev_path = ulas.filename;
- unsigned long prev_lines = ulas.line;
+ prev_path = ulas.filename;
+ prev_lines = ulas.line;
ulas.filename = ulas_strdup(path);
ulas.line = 0;
- FILE *tmp = tmpfile();
+ tmp = tmpfile();
rc = ulas_preproc(tmp, f);
- // only error if -1
+ /* only error if -1 */
if (rc != -1) {
rc = found_dir;
}
return rc;
}
default:
- // this should not happen!
+ /* this should not happen! */
break;
}
return ULAS_PPDIR_NONE;
}
-// checks if the last printable char in a string is '\'
-// side-effect: also replaced that what with \0 if it is found
+/* checks if the last printable char in a string is '\'
+ * side-effect: also replaced that what with \0 if it is found
+ */
int ulas_last_print_is_escape(char *buf, int n) {
int found_escape = 0;
- // check if last printable char is an escape char
+ int i;
+ /* check if last printable char is an escape char */
unsigned int buf_len = ulas_strnlen(buf, n);
if (buf_len == 0) {
return 0;
}
- for (int i = buf_len - 1; i >= 0; i--) {
+ for (i = buf_len - 1; i >= 0; i--) {
if (isprint(buf[i])) {
found_escape = buf[i] == '\\';
if (found_escape) {
return found_escape;
}
-// call fgets and concats into buf until either buf is full (fatal error)
-// or a non-escape character is *not* the last chracter of a line
-// returns number of lines read
+/* call fgets and concats into buf until either buf is full (fatal error)
+ * or a non-escape character is *not* the last chracter of a line
+ * returns number of lines read
+ */
int ulas_fgets(char *buf, int n, FILE *src) {
char internal_buf[ULAS_LINEMAX+1];
+ int lines_read;
buf[0] = '\0';
internal_buf[ULAS_LINEMAX] = '\0';
- int lines_read = 0;
+ lines_read = 0;
do {
char *res = fgets(internal_buf, ULAS_LINEMAX, src);
- // bail early
+ /* bail early */
if (res == NULL) {
break;
}
int ulas_preprocnext(struct ulas_preproc *pp, FILE *dst, FILE *src, char *buf,
int n) {
+ unsigned long buflen;
int rc = 1;
int lines_read = 0;
if ((lines_read = ulas_fgets(buf, n, src)) != 0) {
ulas.line += lines_read;
- unsigned long buflen = strlen(buf);
+ buflen = strlen(buf);
rc = ulas_preprocline(pp, dst, src, buf, buflen);
} else {
}
struct ulas_preproc ulas_preprocinit(void) {
- struct ulas_preproc pp = {NULL, 0, ulas_str(1), ulas_str(1), ulas_str(1)};
- for (unsigned long i = 0; i < ULAS_MACROPARAMMAX; i++) {
+ int i;
+ struct ulas_preproc pp;
+ pp.defs = NULL;
+ pp.defslen = 0;
+ pp.tok = ulas_str(1);
+ pp.line = ulas_str(1);
+ pp.line2 = ulas_str(1);
+
+ for (i = 0; i < ULAS_MACROPARAMMAX; i++) {
pp.macroparam[i] = ulas_str(8);
}
pp.macrobuf = ulas_str(8);
- // set up initial defs
- for (int i = 0; i < ulascfg.defslen; i++) {
-
- struct ulas_ppdef def = {ULAS_PPDEF, ulas_strdup(ulascfg.defs[i]),
- ulas_strdup(""),
- 0};
+ /* set up initial defs */
+ for (i = 0; i < ulascfg.defslen; i++) {
+ struct ulas_ppdef def;
+ def.type = ULAS_PPDEF;
+ def.name = ulas_strdup(ulascfg.defs[i]);
+ def.value = ulas_strdup("");
+ def.undef = 0;
ulas_preprocdef(&pp, def);
}
}
void ulas_preprocclear(struct ulas_preproc *pp) {
- for (unsigned long i = 0; i < pp->defslen; i++) {
+ unsigned long i;
+ for (i = 0; i < pp->defslen; i++) {
if (pp->defs[i].name) {
free(pp->defs[i].name);
}
}
void ulas_preprocfree(struct ulas_preproc *pp) {
+ unsigned long i;
ulas_strfree(&pp->line);
ulas_strfree(&pp->line2);
ulas_strfree(&pp->tok);
ulas_preprocclear(pp);
- for (unsigned long i = 0; i < ULAS_MACROPARAMMAX; i++) {
+ for (i = 0; i < ULAS_MACROPARAMMAX; i++) {
ulas_strfree(&pp->macroparam[i]);
}
ulas_strfree(&pp->macrobuf);
int ulas_preproc(FILE *dst, FILE *src) {
FILE *asmsrc = dst;
char buf[ULAS_LINEMAX];
- memset(buf, 0, ULAS_LINEMAX);
int rc = 0;
+ long prevseek;
+ memset(buf, 0, ULAS_LINEMAX);
- // init
+ /* init */
- long prevseek = ftell(asmsrc);
- // preproc
+ prevseek = ftell(asmsrc);
+ /* preproc */
while ((rc = ulas_preprocnext(&ulas.pp, dst, src, buf, ULAS_LINEMAX)) > 0) {
if (ulascfg.preproc_only) {
continue;
}
- // after each preproc line we assembly it by reading it back
- // from the temporary buffer
+ /* after each preproc line we assembly it by reading it back
+ * from the temporary buffer
+ */
fseek(asmsrc, prevseek, SEEK_SET);
if (ulas_asm(ulasout, asmsrc) == -1) {
rc = -1;
}
int ulas_tokbufpush(struct ulas_tokbuf *tb, struct ulas_tok tok) {
+ void *n;
if (tb->len >= tb->maxlen) {
tb->maxlen += 5;
- void *n = realloc(tb->buf, tb->maxlen * sizeof(struct ulas_tok));
+ n = realloc(tb->buf, tb->maxlen * sizeof(struct ulas_tok));
if (!n) {
ULASPANIC("%s\n", strerror(errno));
}
}
void ulas_tokbufclear(struct ulas_tokbuf *tb) {
- for (long i = 0; i < tb->len; i++) {
+ long i;
+ for (i = 0; i < tb->len; i++) {
struct ulas_tok *t = &tb->buf[i];
ulas_tokfree(t);
}
}
int ulas_exprbufpush(struct ulas_exprbuf *eb, struct ulas_expr expr) {
+ void *newbuf;
if (eb->len >= eb->maxlen) {
eb->maxlen *= 2;
- void *newbuf = realloc(eb->buf, eb->maxlen * sizeof(struct ulas_expr));
+ newbuf = realloc(eb->buf, eb->maxlen * sizeof(struct ulas_expr));
if (!newbuf) {
ULASPANIC("%s\n", strerror(errno));
}
}
int ulas_symbufpush(struct ulas_symbuf *sb, struct ulas_sym sym) {
+ void *newbuf;
if (sb->len >= sb->maxlen) {
sb->maxlen *= 2;
- void *newbuf = realloc(sb->buf, sb->maxlen * sizeof(struct ulas_sym));
+ newbuf = realloc(sb->buf, sb->maxlen * sizeof(struct ulas_sym));
if (!newbuf) {
ULASPANIC("%s\n", strerror(errno));
}
}
void ulas_symbufclear(struct ulas_symbuf *sb) {
- for (long i = 0; i < sb->len; i++) {
+ long i;
+ for (i = 0; i < sb->len; i++) {
struct ulas_sym *s = &sb->buf[i];
free(s->name);
}
int ulas_istokend(struct ulas_str *tok) {
long len = (int)ulas_strnlen(tok->buf, tok->maxlen);
- // skip comments though, they are not trailing tokens!
+ /* skip comments though, they are not trailing tokens! */
if (len > 0 && tok->buf[0] != ULAS_TOK_COMMENT) {
return 0;
}
return 1;
}
-// tokenize all until a terminator token or comment is reached
+/* tokenize all until a terminator token or comment is reached */
int ulas_tokexpr(const char **line, unsigned long n) {
+ struct ulas_tok tok;
+ int tokrc = 0;
ulas_tokbufclear(&ulas.toks);
- int tokrc = 0;
while ((tokrc = ulas_tok(&ulas.tok, line, n) > 0)) {
if (tokrc == -1) {
goto end;
}
- // empty tokens are going to be ignored
+ /* empty tokens are going to be ignored */
if (ulas_strnlen(ulas.tok.buf, ulas.tok.maxlen) == 0) {
continue;
}
- // interpret the token
- struct ulas_tok tok = ulas_totok(
+ /* interpret the token */
+ tok = ulas_totok(
ulas.tok.buf, ulas_strnlen(ulas.tok.buf, ulas.tok.maxlen), &tokrc);
if (tokrc == -1) {
goto end;
}
- // check for any expression terminators here
+ /* check for any expression terminators here */
if (tok.type == ',' || tok.type == ']' || tok.type == '=' ||
ulas_istokend(&ulas.tok)) {
- // on terminator we roll back line so that the terminator token
- // is not consumed now
+ /* on terminator we roll back line so that the terminator token
+ * is not consumed now
+ */
*line -= tokrc;
goto end;
}
- // now we can loop token type, add all tokens to the token buffer
+ /* now we can loop token type, add all tokens to the token buffer */
ulas_tokbufpush(&ulas.toks, tok);
}
int ulas_parseexprat(int *i);
int ulas_parseprim(int *i) {
+ struct ulas_expprim prim;
+ union ulas_expval val;
+ struct ulas_expr e;
+ struct ulas_expgrp grp;
+ int head;
+ struct ulas_tok *closing;
+
struct ulas_tok *t = ulas_tokbufget(&ulas.toks, *i);
if (!t ||
(t->type != ULAS_INT && t->type != ULAS_STR && t->type != ULAS_SYMBOL &&
if (t->type == '(') {
*i += 1;
- int head = ulas_parseexprat(i);
+ head = ulas_parseexprat(i);
- struct ulas_expgrp grp = {head};
- union ulas_expval val = {.grp = grp};
- struct ulas_expr e = {ULAS_EXPGRP, val};
+ grp.head = head;
+ val.grp = grp;
+ e.type = ULAS_EXPGRP;
+ e.val = val;
- struct ulas_tok *closing = ulas_tokbufget(&ulas.toks, *i);
+ closing = ulas_tokbufget(&ulas.toks, *i);
if (!closing || closing->type != ')') {
ULASERR("Unterminated group expression\n");
return -1;
*i += 1;
return ulas_exprbufpush(&ulas.exprs, e);
} else {
- struct ulas_expprim prim = {*i};
- union ulas_expval val = {.prim = prim};
- struct ulas_expr e = {ULAS_EXPPRIM, val};
+ prim.tok = *i;
+ val.prim = prim;
+ e.type = ULAS_EXPPRIM;
+ e.val = val;
+
*i += 1;
return ulas_exprbufpush(&ulas.exprs, e);
}
int ulas_parseun(int *i) {
struct ulas_tok *t = ulas_tokbufget(&ulas.toks, *i);
+ struct ulas_expun un;
+ union ulas_expval val;
+ struct ulas_expr e;
+ int op, right;
if (t &&
(t->type == '!' || t->type == '-' || t->type == '~' || t->type == '+')) {
- int op = *i;
+ op = *i;
*i += 1;
- int right = ulas_parseun(i);
+ right = ulas_parseun(i);
- struct ulas_expun un = {right, op};
- union ulas_expval val = {.un = un};
- struct ulas_expr e = {ULAS_EXPUN, val};
+ un.right = right;
+ un.op = op;
+ val.un = un;
+ e.type = ULAS_EXPUN;
+ e.val = val;
return ulas_exprbufpush(&ulas.exprs, e);
}
int ulas_parsefact(int *i) {
int expr = ulas_parseun(i);
struct ulas_tok *t = NULL;
+ struct ulas_expbin bin;
+ union ulas_expval val;
+ struct ulas_expr e;
+ int op, right;
while ((t = ulas_tokbufget(&ulas.toks, *i)) &&
(t->type == '*' || t->type == '/' || t->type == '%')) {
- int op = *i;
+ op = *i;
*i += 1;
- int right = ulas_parseun(i);
+ right = ulas_parseun(i);
+
+ bin.left = expr;
+ bin.right = right;
+ bin.op = op;
+
+ val.bin = bin;
+
+ e.type = ULAS_EXPBIN;
+ e.val = val;
- struct ulas_expbin bin = {expr, right, op};
- union ulas_expval val = {.bin = bin};
- struct ulas_expr e = {ULAS_EXPBIN, val};
expr = ulas_exprbufpush(&ulas.exprs, e);
}
int ulas_parseterm(int *i) {
int expr = ulas_parsefact(i);
struct ulas_tok *t = NULL;
+ struct ulas_expbin bin;
+ union ulas_expval val;
+ struct ulas_expr e;
+ int op, right;
while ((t = ulas_tokbufget(&ulas.toks, *i)) &&
(t->type == '+' || t->type == '-')) {
- int op = *i;
+ op = *i;
*i += 1;
- int right = ulas_parsefact(i);
+ right = ulas_parsefact(i);
+
+ bin.left = expr;
+ bin.right = right;
+ bin.op = op;
+
+ val.bin = bin;
+ e.type = ULAS_EXPBIN;
+ e.val = val;
- struct ulas_expbin bin = {expr, right, op};
- union ulas_expval val = {.bin = bin};
- struct ulas_expr e = {ULAS_EXPBIN, val};
expr = ulas_exprbufpush(&ulas.exprs, e);
}
int ulas_parseshift(int *i) {
int expr = ulas_parseterm(i);
struct ulas_tok *t = NULL;
+ struct ulas_expbin bin;
+ union ulas_expval val;
+ struct ulas_expr e;
+ int op, right;
while ((t = ulas_tokbufget(&ulas.toks, *i)) &&
(t->type == ULAS_RSHIFT || t->type == ULAS_LSHIFT)) {
- int op = *i;
+ op = *i;
*i += 1;
- int right = ulas_parseterm(i);
+ right = ulas_parseterm(i);
+
+ bin.left = expr;
+ bin.right = right;
+ bin.op = op;
+
+ val.bin = bin;
+ e.type = ULAS_EXPBIN;
+ e.val = val;
- struct ulas_expbin bin = {expr, right, op};
- union ulas_expval val = {.bin = bin};
- struct ulas_expr e = {ULAS_EXPBIN, val};
expr = ulas_exprbufpush(&ulas.exprs, e);
}
int ulas_parsecmp(int *i) {
int expr = ulas_parseshift(i);
struct ulas_tok *t = NULL;
+ struct ulas_expbin bin;
+ union ulas_expval val;
+ struct ulas_expr e;
+ int right, op;
while ((t = ulas_tokbufget(&ulas.toks, *i)) &&
(t->type == ULAS_LTEQ || t->type == ULAS_GTEQ || t->type == '>' ||
t->type == '<')) {
- int op = *i;
+ op = *i;
*i += 1;
- int right = ulas_parseshift(i);
+ right = ulas_parseshift(i);
+
+ bin.left = expr;
+ bin.right = right;
+ bin.op = op;
+
+ val.bin = bin;
+ e.type = ULAS_EXPBIN;
+ e.val = val;
- struct ulas_expbin bin = {expr, right, op};
- union ulas_expval val = {.bin = bin};
- struct ulas_expr e = {ULAS_EXPBIN, val};
expr = ulas_exprbufpush(&ulas.exprs, e);
}
int ulas_parseeq(int *i) {
int expr = ulas_parsecmp(i);
struct ulas_tok *t = NULL;
+ struct ulas_expbin bin;
+ union ulas_expval val;
+ struct ulas_expr e;
+ int right, op;
+
while ((t = ulas_tokbufget(&ulas.toks, *i)) &&
(t->type == ULAS_EQ || t->type == ULAS_NEQ)) {
- int op = *i;
+ op = *i;
*i += 1;
- int right = ulas_parsecmp(i);
+ right = ulas_parsecmp(i);
+
+ bin.left = expr;
+ bin.right = right;
+ bin.op = op;
+
+ val.bin = bin;
+ e.type = ULAS_EXPBIN;
+ e.val = val;
- struct ulas_expbin bin = {expr, right, op};
- union ulas_expval val = {.bin = bin};
- struct ulas_expr e = {ULAS_EXPBIN, val};
expr = ulas_exprbufpush(&ulas.exprs, e);
}
int ulas_parsebit(int *i) {
int expr = ulas_parseeq(i);
struct ulas_tok *t = NULL;
+ struct ulas_expbin bin;
+ union ulas_expval val;
+ struct ulas_expr e;
while ((t = ulas_tokbufget(&ulas.toks, *i)) &&
(t->type == '&' || t->type == '|' || t->type == '^')) {
- int op = *i;
+ int right, op = *i;
*i += 1;
- int right = ulas_parseeq(i);
+ right = ulas_parseeq(i);
+
+ bin.left = expr;
+ bin.right = right;
+ bin.op = op;
- struct ulas_expbin bin = {expr, right, op};
- union ulas_expval val = {.bin = bin};
- struct ulas_expr e = {ULAS_EXPBIN, val};
+ val.bin = bin;
+ e.type = ULAS_EXPBIN;
+ e.val = val;
expr = ulas_exprbufpush(&ulas.exprs, e);
}
int ulas_parseexprat(int *i) { return ulas_parsebit(i); }
-// parses tokens to expression tree
-// returns head expression index
+/* parses tokens to expression tree
+ * returns head expression index */
int ulas_parseexpr(void) {
+ int i, rc;
+ struct ulas_tokbuf *toks;
ulas_exprbufclear(&ulas.exprs);
- struct ulas_tokbuf *toks = &ulas.toks;
+ toks = &ulas.toks;
if (toks->len == 0) {
ULASERR("Expected expression\n");
return -1;
}
- int i = 0;
- int rc = ulas_parseexprat(&i);
+ i = 0;
+ rc = ulas_parseexprat(&i);
if (i < toks->len) {
ULASERR("Trailing token at index %d\n", i);
int ulas_intexpreval(int i, int *rc) {
struct ulas_expr *e = ulas_exprbufget(&ulas.exprs, i);
+ int right, left;
+ struct ulas_tok *op;
+ struct ulas_tok *t;
if (!e) {
ULASERR("unable to evaluate expression\n");
*rc = -1;
switch ((int)e->type) {
case ULAS_EXPBIN: {
- struct ulas_tok *op = ulas_tokbufget(&ulas.toks, (int)e->val.bin.op);
+ op = ulas_tokbufget(&ulas.toks, (int)e->val.bin.op);
if (!op) {
ULASPANIC("Binary operator was NULL\n");
}
- int left = ulas_intexpreval((int)e->val.bin.left, rc);
- int right = ulas_intexpreval((int)e->val.bin.right, rc);
+ left = ulas_intexpreval((int)e->val.bin.left, rc);
+ right = ulas_intexpreval((int)e->val.bin.right, rc);
switch ((int)op->type) {
case ULAS_EQ:
return left == right;
break;
}
case ULAS_EXPUN: {
- struct ulas_tok *op = ulas_tokbufget(&ulas.toks, (int)e->val.un.op);
+ op = ulas_tokbufget(&ulas.toks, (int)e->val.un.op);
if (!op) {
ULASPANIC("Unary operator was NULL\n");
}
- int right = ulas_intexpreval((int)e->val.un.right, rc);
+ right = ulas_intexpreval((int)e->val.un.right, rc);
switch ((int)op->type) {
case '!':
return !right;
return ulas_intexpreval((int)e->val.grp.head, rc);
}
case ULAS_EXPPRIM: {
- struct ulas_tok *t = ulas_tokbufget(&ulas.toks, (int)e->val.prim.tok);
+ t = ulas_tokbufget(&ulas.toks, (int)e->val.prim.tok);
return ulas_valint(t, rc);
}
}
}
int ulas_intexpr(const char **line, unsigned long n, int *rc) {
+ int expr;
if (ulas_tokexpr(line, n) == -1) {
*rc = -1;
return -1;
}
- int expr = ulas_parseexpr();
+ expr = ulas_parseexpr();
if (expr == -1) {
*rc = -1;
return -1;
}
- // execute the tree of expressions
+ /* execute the tree of expressions */
return ulas_intexpreval(expr, rc);
}
char *ulas_strexpr(const char **line, unsigned long n, int *rc) {
+ struct ulas_expr *e;
+ int expr;
if (ulas_tokexpr(line, n) == -1) {
*rc = -1;
return NULL;
}
- int expr = ulas_parseexpr();
+ expr = ulas_parseexpr();
if (expr == -1) {
*rc = -1;
return NULL;
}
- struct ulas_expr *e = ulas_exprbufget(&ulas.exprs, expr);
+ e = ulas_exprbufget(&ulas.exprs, expr);
if (!e) {
ULASERR("unable to evaluate expression\n");
*rc = -1;
int ulas_asminstr(char *dst, unsigned long max, const char **line,
unsigned long n) {
const char *start = *line;
+ int datread, rc = 0, i, res;
+ const short *dat;
+ char c[2];
+ const short *tok;
+ const char *regstr;
+ const struct ulas_instr *instrs;
+ int written;
+
if (max < ULAS_INSTRBUF_MIN) {
ULASPANIC("Instruction buffer is too small!");
return -1;
}
- const struct ulas_instr *instrs = ulas.arch.instrs;
+ instrs = ulas.arch.instrs;
- int written = 0;
+ written = 0;
while (instrs->name && written == 0) {
+ int exprres[ULAS_INSTRDATMAX];
+ int expridx = 0;
*line = start;
if (ulas_tok(&ulas.tok, line, n) == -1) {
ULASERR("Expected instruction\n");
return -1;
}
- // check for instruction name first
+ /* check for instruction name first */
if (strncmp(ulas.tok.buf, instrs->name, ulas.tok.maxlen) != 0) {
goto skip;
}
- // expression results in order they appear
- // TODO: this should probably become a union of sort to allow float
- // expressions
- int exprres[ULAS_INSTRDATMAX];
- int expridx = 0;
+ /* expression results in order they appear
+ * TODO: this should probably become a union of sort to allow float
+ * expressions
+ */
memset(&exprres, 0, sizeof(int) * ULAS_INSTRDATMAX);
- // then check for each single token...
- const short *tok = instrs->tokens;
- int i = 0;
+ /* then check for each single token... */
+ tok = instrs->tokens;
+ i = 0;
while (tok[i]) {
assert(i < ULAS_INSTRTOKMAX);
- const char *regstr = ulas_asmregstr(tok[i]);
+ regstr = ulas_asmregstr(tok[i]);
if (regstr) {
if (ulas_tok(&ulas.tok, line, n) == -1) {
goto skip;
} else if (tok[i] == ULAS_E8 || tok[i] == ULAS_E16 || tok[i] == ULAS_A8 ||
tok[i] == ULAS_A16) {
assert(expridx < ULAS_INSTRDATMAX);
- int rc = 0;
- int res = ulas_intexpr(line, n, &rc);
+ rc = 0;
+ res = ulas_intexpr(line, n, &rc);
exprres[expridx++] = res;
if (rc == -1) {
return -1;
goto skip;
}
- char c[2] = {(char)tok[i], '\0'};
+ c[0] = (char)tok[i];
+ c[1] = '\0';
if (strncmp(ulas.tok.buf, c, ulas.tok.maxlen) != 0) {
goto skip;
}
i++;
}
- // we are good to go!
- int datread = 0;
+ /* we are good to go! */
+ datread = 0;
expridx = 0;
- const short *dat = instrs->data;
+ dat = instrs->data;
while (dat[datread]) {
assert(datread < ULAS_INSTRDATMAX);
assert(expridx < ULAS_INSTRDATMAX);
dst[written++] = (char)(val >> 8);
dst[written] = (char)(val & 0xFF);
} else {
- // write 16-bit le values
+ /* write 16-bit le values */
dst[written++] = (char)(val & 0xFF);
dst[written] = (char)(val >> 8);
}
}
void ulas_asmlst(const char *line, const char *outbuf, unsigned long n) {
- // only write to dst on final pass
+ long i;
+ int outwrt;
+ const int pad = 10;
+ /* only write to dst on final pass */
if (ulaslstout && ulas.pass == ULAS_PASS_FINAL) {
fprintf(ulaslstout, "%08X", ulas.address);
- // always pad at least n bytes
+ /* always pad at least n bytes */
fputs(" ", ulaslstout);
- const int pad = 10;
- int outwrt = 0;
+ outwrt = 0;
- for (long i = 0; i < n; i++) {
+ for (i = 0; i < n; i++) {
outwrt += fprintf(ulaslstout, "%02x ", outbuf[i] & 0xFF);
}
- for (long i = outwrt; i < pad; i++) {
+ for (i = outwrt; i < pad; i++) {
fputs(".", ulaslstout);
}
}
void ulas_asmout(FILE *dst, const char *outbuf, unsigned long n) {
- // only write to dst on final pass
+ int i;
+ /* only write to dst on final pass */
if (ulas.pass == ULAS_PASS_FINAL) {
fwrite(outbuf, 1, n, dst);
}
if (ulas.address < 0x14C) {
- for (int i = 0; i < n; i++) {
+ for (i = 0; i < n; i++) {
ulas.chksm = (char)(ulas.chksm - outbuf[i] - 1);
}
}
}
int ulas_asmdirbyte(FILE *dst, const char **line, unsigned long n, int *rc) {
- // .db expr, expr, expr
+ /* .db expr, expr, expr */
struct ulas_tok t;
int written = 0;
memset(&t, 0, sizeof(t));
}
} while (*rc != -1 && t.type == ',');
- // go back one byte if the token was a comment
+ /* go back one byte if the token was a comment */
if (t.type == ULAS_TOK_COMMENT) {
*line = *line - strlen(ulas.tok.buf);
}
int ulas_asmdirset(const char **line, unsigned long n, enum ulas_type t) {
char name[ULAS_SYMNAMEMAX];
+ struct ulas_tok tok;
+ int rc;
ulas_tok(&ulas.tok, line, n);
if (!ulas_isname(ulas.tok.buf, ulas.tok.maxlen)) {
ULASERR("Unexpected token '%s'\n", ulas.tok.buf);
}
strncpy(name, ulas.tok.buf, ULAS_SYMNAMEMAX);
- // consume =
+ /* consume = */
ulas_tok(&ulas.tok, line, n);
if (strncmp(ulas.tok.buf, "=", ulas.tok.maxlen) != 0) {
ULASERR("Unexpected token '%s'. Expected '='\n", ulas.tok.buf);
return -1;
}
- int rc = 0;
+ rc = 0;
- union ulas_val val = {0};
switch (t) {
case ULAS_INT:
- val.intv = ulas_intexpr(line, n, &rc);
+ tok.val.intv = ulas_intexpr(line, n, &rc);
if (rc == -1) {
goto fail;
}
break;
case ULAS_STR:
- val.strv = ulas_strexpr(line, n, &rc);
+ tok.val.strv = ulas_strexpr(line, n, &rc);
if (rc == -1) {
goto fail;
}
ULASERR("Unexpected type\n");
return -1;
}
- struct ulas_tok tok = {t, val};
+ tok.type = t;
if (ulas.pass == ULAS_PASS_FINAL) {
- // only really define in final pass
+ /* only really define in final pass */
ulas_symbolset(name, -1, tok, 0);
}
fail:
}
int ulas_asmdirset_lookup(const char **line, unsigned long n) {
+ enum ulas_type t;
+ int rc;
+ struct ulas_sym *found;
+ const char *start;
+
if (ulas.pass != ULAS_PASS_FINAL) {
*line += strlen(*line);
return 0;
}
- const char *start = *line;
+ start = *line;
ulas_tok(&ulas.tok, line, n);
- int rc = 0;
- struct ulas_sym *found = ulas_symbolresolve(ulas.tok.buf, -1, &rc);
+ rc = 0;
+ found = ulas_symbolresolve(ulas.tok.buf, -1, &rc);
if (rc == -1 || !found) {
ULASERR("Unable to set symbol '%s'\n", ulas.tok.buf);
return -1;
}
- enum ulas_type t = found->tok.type;
+ t = found->tok.type;
*line = start;
}
int ulas_asmdirdef(const char **line, unsigned long n) {
- // .set <str,int> = name expr
+ /* .set <str,int> = name expr */
- ulas_tok(&ulas.tok, line, n);
enum ulas_type t = ULAS_INT;
+ ulas_tok(&ulas.tok, line, n);
if (strncmp(ulas.tok.buf, "int", ulas.tok.maxlen) == 0) {
t = ULAS_INT;
} else if (strncmp(ulas.tok.buf, "str", ulas.tok.maxlen) == 0) {
int ulas_asmdirdefenum(const char **line, unsigned long n) {
char name[ULAS_SYMNAMEMAX];
+ struct ulas_tok tok;
+ int rc;
+
ulas_tok(&ulas.tok, line, n);
if (!ulas_isname(ulas.tok.buf, ulas.tok.maxlen)) {
ULASERR("Unexpected token '%s'\n", ulas.tok.buf);
}
strncpy(name, ulas.tok.buf, ULAS_SYMNAMEMAX);
- // consume ,
+ /* consume , */
ulas_tok(&ulas.tok, line, n);
if (strncmp(ulas.tok.buf, ",", ulas.tok.maxlen) != 0) {
ULASERR("Unexpected token '%s'. Expected ','\n", ulas.tok.buf);
return -1;
}
- union ulas_val val = {0};
- val.intv = ulas.enumv;
+ tok.val.intv = ulas.enumv;
- int rc = 0;
+ rc = 0;
ULAS_EVALEXPRS(ulas.enumv += ulas_intexpr(line, n, &rc));
if (rc == -1) {
goto fail;
}
- struct ulas_tok tok = {ULAS_INT, val};
+ tok.type = ULAS_INT;
- // only really define in final pass
+ /* only really define in final pass */
ulas_symbolset(name, -1, tok, 1);
fail:
return rc;
}
int ulas_asmdirfill(FILE *dst, const char **line, unsigned long n, int *rc) {
- // fill <what>, <how many>
- int written = 0;
-
+ /* fill <what>, <how many> */
+ int written = 0, i, count;
int ival = ulas_intexpr(line, n, rc);
char val = (char)ival;
+ struct ulas_tok t;
+
if (*rc == -1) {
return 0;
}
ulas_tok(&ulas.tok, line, n);
- struct ulas_tok t =
+ t =
ulas_totok(ulas.tok.buf, ulas_strnlen(ulas.tok.buf, ulas.tok.maxlen), rc);
if (*rc == -1 || t.type != ',') {
ULASERR("Expected ,\n");
return 0;
}
- int count = 0;
+ count = 0;
ULAS_EVALEXPRS(count = ulas_intexpr(line, n, rc));
if (count < 0) {
return 0;
}
- for (int i = 0; i < count; i++) {
+ for (i = 0; i < count; i++) {
ulas_asmout(dst, &val, 1);
written++;
}
}
int ulas_asmdirstr(FILE *dst, const char **line, unsigned long n, int *rc) {
- // .str expr, expr, expr
+ /* .str expr, expr, expr */
struct ulas_tok t;
+ int i;
unsigned long written = 0;
+ unsigned long len;
memset(&t, 0, sizeof(t));
do {
*rc = -1;
return 0;
}
- unsigned long len = strlen(s);
+ len = strlen(s);
- // apply char code map
- for (int i = 0; i < len; i++) {
+ /* apply char code map */
+ for (i = 0; i < len; i++) {
s[i] = ulas.charcodemap[(int)s[i]];
}
int ulas_asmdirincbin(FILE *dst, const char **line, unsigned long n, int *rc) {
char *path = ulas_strexpr(line, n, rc);
char buf[256];
- memset(buf, 0, 256);
unsigned long written = 0;
+ unsigned long read = 0;
FILE *f = ulas_incpathfopen(path, "re");
+ memset(buf, 0, 256);
+
if (!f) {
*rc = -1;
return 0;
}
- unsigned long read = 0;
while ((read = fread(buf, 1, 256, f))) {
ulas_asmout(dst, buf, read);
written += read;
int rc = 0;
int charcode = 0;
int setto = 0;
+ struct ulas_tok t;
ULAS_EVALEXPRS(charcode = ulas_intexpr(line, n, &rc));
charcode = charcode & 0xFF;
ulas_tok(&ulas.tok, line, n);
- struct ulas_tok t =
+ t =
ulas_totok(ulas.tok.buf, ulas_strnlen(ulas.tok.buf, ulas.tok.maxlen), &rc);
if (rc == -1 || t.type != '=') {
int ulas_asmdirchr(FILE *dst, const char **line, unsigned long n, int *rc) {
unsigned char b[2] = {0, 0};
struct ulas_tok t;
- memset(&t, 0, sizeof(t));
+ int i, written;
+ unsigned long len;
int bit = 7;
+
+ memset(&t, 0, sizeof(t));
ulas_tok(&ulas.tok, line, n);
- unsigned long len = strlen(ulas.tok.buf);
+ len = strlen(ulas.tok.buf);
if (len > 8) {
*rc = -1;
ULASERR("chr input exceeds 8 pixels\n");
return 0;
}
- for (int i = 0; i < len; i++, bit--) {
+ for (i = 0; i < len; i++, bit--) {
switch (ulas.tok.buf[i]) {
case '0':
- // 0 sets no bit
+ /* 0 sets no bit */
break;
case '1':
- // 1 sets 01
+ /* 1 sets 01 */
b[1] |= (char)(1 << bit);
break;
case '2':
- // 2 sets 10
+ /* 2 sets 10 */
b[0] |= (char)(1 << bit);
break;
case '3':
- // 3 sets 11
+ /* 3 sets 11 */
b[0] |= (char)(1 << bit);
b[1] |= (char)(1 << bit);
break;
}
}
- int written = 2;
+ written = 2;
ulas_asmout(dst, (char *)b, written);
- // this always writes 2 bytes
+ /* this always writes 2 bytes */
return written;
}
int ulas_asmdirrep(FILE *dst, FILE *src, const char **line, unsigned long n) {
char name[ULAS_SYMNAMEMAX];
+ int i, step, repval, rc;
+ struct ulas_tok t;
+ unsigned long argline_len;
+ struct ulas_tok tok;
+
ulas_tok(&ulas.tok, line, n);
if (!ulas_isname(ulas.tok.buf, ulas.tok.maxlen)) {
ULASERR("Unexpected token '%s'\n", ulas.tok.buf);
}
strncpy(name, ulas.tok.buf, ULAS_SYMNAMEMAX);
- // consume ,
+ /* consume , */
ulas_tok(&ulas.tok, line, n);
if (strncmp(ulas.tok.buf, ",", ulas.tok.maxlen) != 0) {
ULASERR("Unexpected token '%s'. Expected ','\n", ulas.tok.buf);
return -1;
}
- union ulas_val val = {0};
- val.intv = 0;
- struct ulas_tok tok = {ULAS_INT, val};
+ tok.type = ULAS_INT;
+ tok.val.intv = 0;
+
ulas_symbolset(name, ulas.scope, tok, 0);
- int repval = 0;
- int rc = 0;
+ repval = 0;
+ rc = 0;
ULAS_EVALEXPRS(repval = ulas_intexpr(line, n, &rc));
ulas_tok(&ulas.tok, line, n);
- struct ulas_tok t =
+ t =
ulas_totok(ulas.tok.buf, ulas_strnlen(ulas.tok.buf, ulas.tok.maxlen), &rc);
if (rc == -1 || t.type != ',') {
ULASERR("Expected ,\n");
return 0;
}
- int step = 0;
+ step = 0;
ULAS_EVALEXPRS(step = ulas_intexpr(line, n, &rc));
ulas_tok(&ulas.tok, line, n);
t = ulas_totok(ulas.tok.buf, ulas_strnlen(ulas.tok.buf, ulas.tok.maxlen), &rc);
return 0;
}
- unsigned long argline_len = strlen(*line);
+ argline_len = strlen(*line);
- for (int i = 0; i < repval; i += step) {
+ for (i = 0; i < repval; i += step) {
tok.val.intv = i;
ulas_symbolset(name, ulas.scope, tok, 0);
rc = ulas_asmline(dst, src, *line, argline_len);
}
int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) {
- // this buffer is written both to dst and to verbose output
+ /* this buffer is written both to dst and to verbose output */
char outbuf[ULAS_OUTBUFMAX];
- memset(outbuf, 0, ULAS_OUTBUFMAX);
long towrite = 0;
long other_writes = 0;
-
+ long i;
+ int nextwrite;
+ struct ulas_tok label_tok;
const char *start = line;
const char *instr_start = start;
int rc = 0;
+
+ memset(outbuf, 0, ULAS_OUTBUFMAX);
- // read the first token and decide
+ /* read the first token and decide */
ulas_tok(&ulas.tok, &line, n);
- // we ignore empty lines or all comments lines
+ /* we ignore empty lines or all comments lines */
if (ulas_istokend(&ulas.tok)) {
ulas_asmlst(start, outbuf, towrite);
return 0;
}
- // is it a label?
+ /* is it a label? */
if (ulas_islabelname(ulas.tok.buf, strlen(ulas.tok.buf))) {
instr_start = line;
- struct ulas_tok label_tok = {ULAS_INT, {(int)ulas.address}};
+ label_tok.type = ULAS_INT;
+ label_tok.val.intv = (int)ulas.address;
+
if (ulas_symbolset(ulas.tok.buf, -1, label_tok, 1) == -1) {
return -1;
}
ulas_tok(&ulas.tok, &line, n);
- // is next token empty?
+ /* is next token empty? */
if (ulas_istokend(&ulas.tok)) {
ulas_asmlst(start, outbuf, towrite);
return 0;
enum ulas_asmdir dir = ULAS_ASMDIR_NONE;
- for (long i = 0; dirstrs[i]; i++) {
+ for (i = 0; dirstrs[i]; i++) {
if (strncmp(ulas.tok.buf, dirstrs[i], n) == 0) {
dir = dirs[i];
break;
break;
}
case ULAS_ASMDIR_DEF:
- // only do this in the final pass
+ /* only do this in the final pass */
rc = ulas_asmdirdef(&line, n);
break;
case ULAS_ASMDIR_SET:
ulas.prev_scope = 0;
break;
case ULAS_ASMDIR_PAD:
- // TODO: pad is the same as .fill n, $ - n
+ /* TODO: pad is the same as .fill n, $ - n */
case ULAS_ASMDIR_NONE:
ULASPANIC("asmdir not implemented\n");
break;
}
} else {
- // is regular line in form of [label:] instruction ; comment
- // start over for the next step...
+ /* is regular line in form of [label:] instruction ; comment
+ * start over for the next step...
+ */
line = instr_start;
- int nextwrite = ulas_asminstr(outbuf, ULAS_OUTBUFMAX, &line, n);
+ nextwrite = ulas_asminstr(outbuf, ULAS_OUTBUFMAX, &line, n);
if (nextwrite == -1) {
ULASERR("Unable to assemble instruction\n");
rc = -1;
towrite += nextwrite;
}
- // check for trailing
- // but only if its not a comment
+ /* check for trailing
+ * but only if its not a comment
+ */
if (ulas_tok(&ulas.tok, &line, n) > 0) {
if (!ulas_istokend(&ulas.tok)) {
ULASERR("Trailing token '%s'\n", ulas.tok.buf);
int ulas_asm(FILE *dst, FILE *src) {
char buf[ULAS_LINEMAX];
- memset(buf, 0, ULAS_LINEMAX);
int rc = 0;
+ memset(buf, 0, ULAS_LINEMAX);
- // preproc
+ /* preproc */
while ((rc = ulas_asmnext(dst, src, buf, ULAS_LINEMAX)) > 0) {
}
#define ULAS_NAME "ulas"
#define ULAS_VER "0.0.1"
-// args without value
+/* args without value */
#define ULAS_OPTS "hvVpdA"
-// args with value
+/* args with value */
#define ULAS_OPTS_ARG "o:l:s:I:w:a:S:D:"
#define ULAS_HELP(a, desc) printf("\t-%s\t%s\n", (a), desc);
extern char *defs[ULAS_DEFSMAX];
extern unsigned long defslen;
-// if this is used as a path use stdin or stdout instead
+/* if this is used as a path use stdin or stdout instead */
#define ULAS_STDFILEPATH "-"
#define ULAS_PATHSEP "/"
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-// Config variables
+/* Config variables */
#define ULAS_CFG_FMT_GREEN "\x1B[32m"
#define ULAS_CFG_FMT_YELLOW "\x1B[33m"
#define ULAS_CFG_FMT_RED "\x1B[31m"
#define ULAS_ASMSTR_PAD ".pad"
#define ULAS_ASMSTR_INCBIN ".incbin"
#define ULAS_ASMSTR_DEF ".def"
-// TODO: chksm should only work on sm83
+/* TODO: chksm should only work on sm83 */
#define ULAS_ASMSTR_CHKSM ".chksm"
#define ULAS_ASMSTR_ADV ".adv"
#define ULAS_ASMSTR_SET_ENUM_DEF ".se"
#define ULAS_ASMSTR_BEGIN_SCOPE ".beginscope"
#define ULAS_ASMSTR_END_SCOPE ".endscope"
-// configurable tokens
+/* configurable tokens */
#define ULAS_TOK_COMMENT ';'
-// start of as directives such as .org
+/* start of as directives such as .org */
#define ULAS_TOK_ASMDIR_BEGIN '.'
-// start of preprocessor directives such as #define or #include
+/* start of preprocessor directives such as #define or #include */
#define ULAS_TOK_PREPROC_BEGIN '#'
#define ULAS_TOK_SCOPED_SYMBOL_BEGIN '@'
#define ULAS_TOK_CURRENT_ADDR '$'
}
#define ULASWARNLEVEL(level) (ulascfg.warn_level & (level))
-// format macros
+/* format macros */
#define ULAS_FMT(f, fmt) \
if (isatty(fileno(f)) && ulascfg.color) { \
fprintf((f), "%s", (fmt)); \
}
-// this is a bit of a hack to get the int expression to evaluate anyway
-// because expressions only work in the final pass
-// Beware that this can cause unforseen writes to the file and should really
-// only be uesd to evalulate an expression that needs to be evaled during
-// all passes and nothing else!
+/* this is a bit of a hack to get the int expression to evaluate anyway
+ * because expressions only work in the final pass
+ * Beware that this can cause unforseen writes to the file and should really
+ * only be uesd to evalulate an expression that needs to be evaled during
+ * all passes and nothing else!
+ */
#define ULAS_EVALEXPRS(...) \
{ \
int pass = ulas.pass; \
* Output target files
*/
-// input file for source reader
+/* input file for source reader */
extern FILE *ulasin;
-// source code output target
+/* source code output target */
extern FILE *ulasout;
-// error output target
+/* error output target */
extern FILE *ulaserr;
-// assembly listing output
+/* assembly listing output */
extern FILE *ulaslstout;
-// symbol list output
+/* symbol list output */
extern FILE *ulassymout;
struct ulas_expr;
enum ulas_symfmt { ULAS_SYM_FMT_DEFAULT, ULAS_SYM_FMT_SYM, ULAS_SYM_FMT_MLB };
struct ulas_config {
- // argv represents file names
+ /* argv represents file names */
char **argv;
int argc;
unsigned int print_addrs;
- // all include search paths
+ /* all include search paths */
char **incpaths;
unsigned int incpathslen;
enum ulas_warm warn_level;
- // initial defs for preproc
+ /* initial defs for preproc */
char **defs;
unsigned int defslen;
};
* Tokens
*/
-// any token before 256 is just the literal char value
-// primitive data types
-// FIXME: split up types and operators
-// TODO:add float expressions
+/* any token before 256 is just the literal char value
+ * primitive data types
+ * FIXME: split up types and operators
+ * TODO:add float expressions
+ */
enum ulas_type {
ULAS_SYMBOL = 256,
ULAS_INT,
ULAS_GTEQ,
ULAS_LTEQ,
ULAS_RSHIFT,
- ULAS_LSHIFT,
+ ULAS_LSHIFT
};
-// data type value
+/* data type value */
union ulas_val {
int intv;
char *strv;
union ulas_val val;
};
-// the token buffer is a dynamically allocated token store
+/* the token buffer is a dynamically allocated token store */
struct ulas_tokbuf {
struct ulas_tok *buf;
long len;
long maxlen;
};
-// the expression buffer hold expression buffers
+/* the expression buffer hold expression buffers */
struct ulas_exprbuf {
struct ulas_expr *buf;
unsigned long len;
*/
enum ulas_pass {
ULAS_PASS_FINAL = 0,
- ULAS_PASS_RESOLVE = 1,
+ ULAS_PASS_RESOLVE = 1
};
/**
struct ulas_sym {
char *name;
struct ulas_tok tok;
- // this label's scope index
+ /* this label's scope index */
int scope;
- // last pass this was defined in...
- // a symbol may only be defined once per pass/scope
+ /* last pass this was defined in...
+ * a symbol may only be defined once per pass/scope
+ */
enum ulas_pass lastdefin;
int constant;
};
-// holds all currently defned symbols
+/* holds all currently defned symbols */
struct ulas_symbuf {
struct ulas_sym *buf;
unsigned long len;
int exp_depth;
- // macro parameter buffers
+ /* macro parameter buffers */
struct ulas_str macroparam[ULAS_MACROPARAMMAX];
- // macro expansion buffer
+ /* macro expansion buffer */
struct ulas_str macrobuf;
};
char *initial_filename;
unsigned long line;
- // count how many passes we have completed so far
+ /* count how many passes we have completed so far */
int pass;
- // holds the current token
+ /* holds the current token */
struct ulas_str tok;
- // current token stream
+ /* current token stream */
struct ulas_tokbuf toks;
struct ulas_exprbuf exprs;
struct ulas_symbuf syms;
unsigned int address;
int enumv;
- // current scope index
- // each global-label increments the scope
+ /* current scope index
+ * each global-label increments the scope
+ */
int scope;
- // temporary storage for .beginscope
- // and .endscope
+ /* temporary storage for .beginscope
+ * and .endscope
+ */
int prev_scope;
- // internal counter
- // used whenever a new unique number might be needed
+ /* internal counter
+ * used whenever a new unique number might be needed
+ */
int icntr;
char chksm;
- // character code map
- // defaults to just x=x mapping
- // but cna be set with a directive
+ /* character code map
+ * defaults to just x=x mapping
+ * but cna be set with a directive
+ */
char charcodemap[ULAS_CHARCODEMAPLEN];
char section[ULAS_SECTIONMAX];
- // where was the section defined?
+ /* where was the section defined? */
unsigned int section_address;
- // active bank
+ /* active bank */
unsigned int bank;
struct ulas_arch arch;
int ulas_icntr(void);
-// init the next pass
-// by resetting some values
+/* init the next pass
+ * by resetting some values
+ */
void ulas_nextpass(void);
/**
enum ulas_ppdirs {
ULAS_PPDIR_NONE = 1,
- // #define name value
+ /* #define name value */
ULAS_PPDIR_DEF,
- // #undefine name
+ /* #undefine name */
ULAS_PPDIR_UNDEF,
- // #macro name
- // value
- // value
+ /* #macro name
+ * value
+ * value
+ */
ULAS_PPDIR_MACRO,
- // #endmacro
+ /* #endmacro */
ULAS_PPDIR_ENDMACRO,
- // ifdef name
+ /* ifdef name */
ULAS_PPDIR_IFDEF,
- // ifndef name
+ /* ifndef name */
ULAS_PPDIR_IFNDEF,
- // endif
+ /* endif */
ULAS_PPDIR_ENDIF,
- // include "filename"
- ULAS_PPDIR_INCLUDE,
+ /* include "filename" */
+ ULAS_PPDIR_INCLUDE
};
enum ulas_ppdefs {
ULAS_PPDEF,
- ULAS_PPMACRO,
+ ULAS_PPMACRO
};
struct ulas_ppdef {
};
struct ulas_expgrp {
- // points to the first expression
- // in this group
+ /* points to the first expression
+ * in this group
+ */
long head;
};
*/
enum ulas_asmdir {
ULAS_ASMDIR_NONE = 0,
- // .org <address>
+ /* .org <address> */
ULAS_ASMDIR_ORG,
- // .set <type> name = <expr>
+ /* .set <type> name = <expr> */
ULAS_ASMDIR_SET,
- // .byte <expr>, <expr>, <expr>, ...
+ /* .byte <expr>, <expr>, <expr>, ... */
ULAS_ASMDIR_BYTE,
- // .str "String value"
+ /* .str "String value" */
ULAS_ASMDIR_STR,
- // .fill <expr>, n
+ /* .fill <expr>, n */
ULAS_ASMDIR_FILL,
- // .pad <expr>, <addr>
+ /* .pad <expr>, <addr> */
ULAS_ASMDIR_PAD,
- // .incbin <filename>
+ /* .incbin <filename> */
ULAS_ASMDIR_INCBIN,
- // .def name = value
+ /* .def name = value */
ULAS_ASMDIR_DEF,
- // inserts checksum into rom
+ /* inserts checksum into rom */
ULAS_ASMDIR_CHKSM,
- // .adv <int>
- // advance .org by n bytes without writing to rom
+ /* .adv <int>
+ * advance .org by n bytes without writing to rom
+ */
ULAS_ASMDIR_ADV,
- // .setenum <int>
- // sets the internal _ENUM counter
+ /* .setenum <int>
+ * sets the internal _ENUM counter
+ */
ULAS_ASMDIR_SET_ENUM_DEF,
- // .de <size>
- // acts like .def but sets the value to the current _ENUM counter
- // and increments it by size
+ /* .de <size>
+ * acts like .def but sets the value to the current _ENUM counter
+ * and increments it by size
+ */
ULAS_ASMDIR_DEFINE_ENUM,
- // .scc '<char>'=<value>
- // allows to set custom encoding for char codes
- // when using .str
+ /* .scc '<char>'=<value>
+ * allows to set custom encoding for char codes
+ * when using .str
+ */
ULAS_ASMDIR_SETCHRCODE,
- // .chr 01230123
- // allows defining
- // chr (tile) data from 0-3
- // for each possible color
- // it requires up to 8 integer expressions between 0 and 3
+ /* .chr 01230123
+ * allows defining
+ * chr (tile) data from 0-3
+ * for each possible color
+ * it requires up to 8 integer expressions between 0 and 3
+ */
ULAS_ASMDIR_CHR,
- // .rep <n>, <step>, <line>
- // repeats a line n times
+ /* .rep <n>, <step>, <line>
+ * repeats a line n times
+ */
ULAS_ASMDIR_REP,
- // .section <name>
- // set the current section
+ /* .section <name>
+ * set the current section
+ */
ULAS_ASMDIR_SECTION,
- // .bank <banknum>
- // sets the current bank number
+ /* .bank <banknum>
+ * sets the current bank number
+ */
ULAS_ASMDIR_BANK,
- // .beginscope
- // incements scope index by 1
+ /* .beginscope
+ * incements scope index by 1
+ */
ULAS_ASMDIR_BEGIN_SCOPE,
- // .endscope
- // decrements scope index by 1
- ULAS_ASMDIR_END_SCOPE,
+ /* .endscope
+ * decrements scope index by 1
+ */
+ ULAS_ASMDIR_END_SCOPE
};
#define ULAS_INSTRTOKMAX 16
#define ULAS_INSTRDATMAX 16
-// entry for lut instruction parser
-// in the form of: name token token token token
-// tokens can either be literal chars, or any of the special tokens like an
-// asmreg or e8, e16
-// if toks value is 0 the list ends
-// if data value is 0 the list ends
-// if toks is E8 or E16 an expression is evaluated
-// id data is E8 or E16 the previous expression is inserted
+/* entry for lut instruction parser
+ * in the form of: name token token token token
+ * tokens can either be literal chars, or any of the special tokens like an
+ * asmreg or e8, e16
+ * if toks value is 0 the list ends
+ * if data value is 0 the list ends
+ * if toks is E8 or E16 an expression is evaluated
+ * id data is E8 or E16 the previous expression is inserted
+ */
struct ulas_instr {
char *name;
short tokens[ULAS_INSTRTOKMAX];
int ulas_main(struct ulas_config cfg);
-// resolve a symbol until an actual literal token (str, int) is found
-// returns NULL if the symbol cannot be resolved
-// returns -1 if any flagged symbol was not found
-// if flagged symbols remain unresolved (e.g. global or locals) rc is set to the
-// respective flag value
+/* resolve a symbol until an actual literal token (str, int) is found
+ * returns NULL if the symbol cannot be resolved
+ * returns -1 if any flagged symbol was not found
+ * if flagged symbols remain unresolved (e.g. global or locals) rc is set to the
+ * respective flag value
+ */
struct ulas_sym *ulas_symbolresolve(const char *name, int scope, int *rc);
-// define a new symbol
-// scope 0 indicates global scope. a scope of -1 instructs
-// the function to auto-detect the scope
-// if a label starts with @ the current scope is used, otherwise 0 is used
-// if the symbol already exists -1 is returned
+/* define a new symbol
+ * scope 0 indicates global scope. a scope of -1 instructs
+ * the function to auto-detect the scope
+ * if a label starts with @ the current scope is used, otherwise 0 is used
+ * if the symbol already exists -1 is returned
+ */
int ulas_symbolset(const char *cname, int scope, struct ulas_tok tok,
int constant);
int ulas_symbolout(FILE *dst, struct ulas_sym *s);
-// tokenisze according to pre-defined rules
-// returns the amount of bytes of line that were
-// consumed or -1 on error
-// returns 0 when no more tokens can be read
-// writes the token to dst string buffer
+/* tokenisze according to pre-defined rules
+ * returns the amount of bytes of line that were
+ * consumed or -1 on error
+ * returns 0 when no more tokens can be read
+ * writes the token to dst string buffer
+ */
int ulas_tok(struct ulas_str *dst, const char **out_line, unsigned long n);
-// converts a token string to a token struct
-// this is only useful if we do not require the token literal
-// but rather can be used to store a slimmer list of token types
-// and literal values
+/* converts a token string to a token struct
+ * this is only useful if we do not require the token literal
+ * but rather can be used to store a slimmer list of token types
+ * and literal values
+ */
struct ulas_tok ulas_totok(char *buf, unsigned long n, int *rc);
-// tokenize until a terminator char is reached
+/* tokenize until a terminator char is reached */
int ulas_tokuntil(struct ulas_str *dst, char c, const char **out_line,
unsigned long n);
* str
*/
-// create a string buffer
+/* create a string buffer */
struct ulas_str ulas_str(unsigned long n);
-// ensure the string buffer is at least n bytes long, if not realloc
+/* ensure the string buffer is at least n bytes long, if not realloc */
struct ulas_str ulas_strensr(struct ulas_str *s, unsigned long maxlen);
-// require at least n bytes + the current strlen
+/* require at least n bytes + the current strlen */
struct ulas_str ulas_strreq(struct ulas_str *s, unsigned long n);
void ulas_strfree(struct ulas_str *s);
*/
int ulas_preproc(FILE *dst, FILE *src);
-// reads the next line
-// returns 0 if no more data can be read
-// > 0 if data was read (enum ulas_ppdirs id)
-// -1 on error
-// it also places the processed line into pp->line.buf
-// note that this is overwritten by every call!
+/* reads the next line
+ * returns 0 if no more data can be read
+ * > 0 if data was read (enum ulas_ppdirs id)
+ * -1 on error
+ * it also places the processed line into pp->line.buf
+ * note that this is overwritten by every call!
+ */
int ulas_preprocnext(struct ulas_preproc *pp, FILE *dst, FILE *src, char *buf,
int n);
-// process a line of preproc
-// returns: 0 when a regular line was read
-// enum ulas_ppdirs id for preprocessor directive
-// -1 on error
-// Warning: calling this recursively may clobber pp buffers and those should
-// not be used in the caller after recursvion finishes!
-// or initialize a new preproc object if the old state is important!
-// (preprocinit and preprocfree)
+/* process a line of preproc
+ * returns: 0 when a regular line was read
+ * enum ulas_ppdirs id for preprocessor directive
+ * -1 on error
+ * Warning: calling this recursively may clobber pp buffers and those should
+ * not be used in the caller after recursvion finishes!
+ * or initialize a new preproc object if the old state is important!
+ * (preprocinit and preprocfree)
+ */
int ulas_preprocline(struct ulas_preproc *pp, FILE *dst, FILE *src,
const char *raw_line, unsigned long n);
-// expand preproc into dst line
+/* expand preproc into dst line */
char *ulas_preprocexpand(struct ulas_preproc *pp, const char *raw_line,
unsigned long *n);
* Literals, tokens and expressions
*/
-// convert literal to its int value
-// retunrs -1 on error, 0 on success and 1 if there is an unresolved symbol
+/* convert literal to its int value
+ * retunrs -1 on error, 0 on success and 1 if there is an unresolved symbol
+ */
int ulas_valint(struct ulas_tok *lit, int *rc);
-// convert literal to its char value
+/* convert literal to its char value */
char *ulas_valstr(struct ulas_tok *lit, int *rc);
struct ulas_tokbuf ulas_tokbuf(void);
-// TODO: maybe we could macro all those buf functions into a single more
-// "geneirc" thing...
+/* TODO: maybe we could macro all those buf functions into a single more
+ * "geneirc" thing...
+ */
-// pushes new token, returns newly added index
+/* pushes new token, returns newly added index */
int ulas_tokbufpush(struct ulas_tokbuf *tb, struct ulas_tok tok);
struct ulas_tok *ulas_tokbufget(struct ulas_tokbuf *tb, int i);
void ulas_tokbufclear(struct ulas_tokbuf *tb);
struct ulas_exprbuf ulas_exprbuf(void);
-// pushes new expression, returns newly added index
+/* pushes new expression, returns newly added index */
int ulas_exprbufpush(struct ulas_exprbuf *eb, struct ulas_expr expr);
struct ulas_expr *ulas_exprbufget(struct ulas_exprbuf *eb, int i);
void ulas_exprbufclear(struct ulas_exprbuf *eb);
* Assembly step
*/
-// assembles an instruction, writes bytes into dst
-// returns bytes written or -1 on error
+/* assembles an instruction, writes bytes into dst
+ * returns bytes written or -1 on error
+ */
int ulas_asminstr(char *dst, unsigned long max, const char **line,
unsigned long n);
-// returns 0 if no more data can be read
-// > 0 if data was read
-// -1 on error
+/* returns 0 if no more data can be read
+ * > 0 if data was read
+ * -1 on error
+ */
int ulas_asmnext(FILE *dst, FILE *src, char *buf, int n);
int ulas_asm(FILE *dst, FILE *src);
int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n);