int brklab = -1;
int wordsize = 4;
+const char* modulename = "b_module_main";
int bsymb_part;
int code_part;
int string_part;
{
for (;;) {
- int opt = getopt(argc, argv, "-w:i:o:");
+ int opt = getopt(argc, argv, "-w:B:i:o:");
if (opt == -1)
break;
wordsize = atoi(optarg);
break;
+ case 'B':
+ modulename = aprintf("b_module_%s", optarg);
+ break;
+
case 'i':
if (freopen(optarg, "r", stdin) == NULL) {
error("Can't find %s", optarg);
break;
derfault:
- error("Usage: em_b [-w wordsize] [-i inputfile] [-o outputfile]");
+ error("Usage: em_b [-w wordsize] [-B modulename] [-i inputfile] [-o outputfile]");
exit(1);
}
}
if (string_part)
C_insertpart(string_part);
- C_exa_dnam("bsymb_patch_table");
- C_df_dnam("bsymb_patch_table");
+ C_exa_dnam((char*) modulename);
+ C_df_dnam((char*) modulename);
if (bsymb_part)
C_insertpart(bsymb_part);
C_rom_cst(0);
case NEWLN:
line++;
-
+ /* fall through */
case SPACE:
c = getchar();
goto loop;
+ case HASH:
+ /* # is invalid in B; but we handle it out of convenience so that we can read
+ * in input files that have been run through the C preprocessor. Ideally we
+ * should only recognise it when it's the first character in a line, but as
+ * it's not used anywhere else we can get away with recognising it anywhere.
+ */
+
+ while ((c = getchar()) == ' ')
+ ;
+
+ peekc = c;
+ getnum();
+ line = cval;
+
+ while ((c = getchar()) != '\n')
+ ;
+
+ goto loop;
+
case PLUS:
return subseq(c,PLUS,INCBEF);
LETTER, SPACE, NEWLN, SPACE, SPACE, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
- SPACE, EXCLA, DQUOTE, UNKN, UNKN, MOD, AND, SQUOTE,
+ SPACE, EXCLA, DQUOTE, HASH, UNKN, MOD, AND, SQUOTE,
LPARN, RPARN, TIMES, PLUS, COMMA, MINUS, UNKN, DIVIDE,
DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
DIGIT, DIGIT, COLON, SEMI, LESS, ASSIGN, GREAT, QUEST,
#include "b.h"
+#include <stdarg.h>
+#include <string.h>
+#include <limits.h>
-extern uintptr_t* bsymb_patch_table[];
+extern uintptr_t* b_module_main[];
extern intptr_t i_main(intptr_t argc, const char* argv[]);
+FILE* input_unit;
FILE* output_unit;
static intptr_t i_char(intptr_t s, intptr_t n)
static intptr_t i_getchar(void)
{
- return fgetc(output_unit);
+ return fgetc(input_unit);
}
static intptr_t i_putchar(intptr_t c)
return c;
}
+static intptr_t i_putstr(intptr_t s)
+{
+ char* p = (char*)(s<<SHIFT);
+ char c;
+
+ while ((c = *p++) != END)
+ fputc(c, output_unit);
+
+ return s;
+}
+
+static intptr_t i_getstr(intptr_t s)
+{
+ char* p = (char*)(s<<SHIFT);
+
+ for (;;)
+ {
+ int c = fgetc(input_unit);
+ if ((c == -1) || (c == '\n'))
+ break;
+ *p++ = c;
+ }
+
+ *p++ = END;
+ return s;
+}
+
+static void i_flush(void)
+{
+ fflush(output_unit);
+}
+
+static int tochar(int n)
+{
+ if (n <= 9)
+ return n + '0';
+ return n - 10 + 'a';
+}
+
+static void putnum(intptr_t value, int base)
+{
+ int i;
+ char s[32];
+
+ if (value < 0)
+ {
+ fputc('-', output_unit);
+ value = -value;
+ }
+
+ i = 0;
+ do
+ s[i++] = tochar(value % base);
+ while ((value /= base) > 0);
+
+ do
+ fputc(s[--i], output_unit);
+ while (i > 0);
+}
+
+static void i_printf(intptr_t s, ...)
+{
+ char* p = (char*)(s<<SHIFT);
+ char c;
+
+ va_list ap;
+ va_start(ap, s);
+
+ while ((c = *p++) != END)
+ {
+ switch (c)
+ {
+ case '%':
+ {
+ intptr_t ss = va_arg(ap, intptr_t);
+
+ switch ((c = *p++))
+ {
+ case 's':
+ i_putstr(ss);
+ break;
+
+ case 'd':
+ putnum(ss, 10);
+ break;
+
+ case 'o':
+ putnum(ss, 8);
+ break;
+
+ case 'x':
+ putnum(ss, 16);
+ break;
+
+ case 'c':
+ fputc(ss, output_unit);
+ break;
+
+ default:
+ fputc('?', output_unit);
+ break;
+ }
+ break;
+ }
+
+ default:
+ fputc(c, output_unit);
+ break;
+ }
+ }
+
+ va_end(ap);
+}
+
uintptr_t b_char = (uintptr_t)i_char;
uintptr_t b_lchar = (uintptr_t)i_lchar;
uintptr_t b_getchar = (uintptr_t)i_getchar;
uintptr_t b_putchar = (uintptr_t)i_putchar;
+uintptr_t b_putstr = (uintptr_t)i_putstr;
+uintptr_t b_getstr = (uintptr_t)i_getstr;
+uintptr_t b_flush = (uintptr_t)i_flush;
+uintptr_t b_printf = (uintptr_t)i_printf;
-static uintptr_t* lib_patch_table[] =
+static uintptr_t* b_module_stdlib[] =
{
&b_char,
&b_lchar,
&b_getchar,
&b_putchar,
+ &b_putstr,
+ &b_getstr,
+ &b_flush,
+ &b_printf,
0
};
int main(int argc, const char* argv[])
{
- patch_addresses(bsymb_patch_table);
- patch_addresses(lib_patch_table);
+ patch_addresses(b_module_main);
+ patch_addresses(b_module_stdlib);
+ input_unit = stdin;
output_unit = stdout;
return i_main(argc, NULL);
-}
\ No newline at end of file
+}