First draft of the B module code; a module name can now be specified as a
compiler flag, which is used to set the name of the patch table. The compiler now understands C preprocessor line directives. Extend the standard library somewhat.
This commit is contained in:
parent
e3f8fb84dc
commit
ebd424e7f1
|
@ -4,6 +4,7 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <em.h>
|
||||
#include "astring.h"
|
||||
|
||||
#define NCPS 8 /* chars per symbol */
|
||||
#define HSHSIZ 400 /* hash table size */
|
||||
|
@ -40,6 +41,7 @@ struct swtab {
|
|||
};
|
||||
|
||||
extern int wordsize;
|
||||
extern const char* modulename;
|
||||
int paramsize;
|
||||
struct hshtab hshtab[HSHSIZ];
|
||||
int hshused;
|
||||
|
@ -89,6 +91,7 @@ char* manglename(char* name, char prefix);
|
|||
#define RPARN 7
|
||||
#define COLON 8
|
||||
#define COMMA 9
|
||||
#define HASH 10
|
||||
|
||||
#define MCALL 15
|
||||
#define CALL 16
|
||||
|
|
|
@ -14,6 +14,7 @@ int contlab = -1;
|
|||
int brklab = -1;
|
||||
|
||||
int wordsize = 4;
|
||||
const char* modulename = "b_module_main";
|
||||
int bsymb_part;
|
||||
int code_part;
|
||||
int string_part;
|
||||
|
@ -38,7 +39,7 @@ main(int argc, char *argv[])
|
|||
{
|
||||
|
||||
for (;;) {
|
||||
int opt = getopt(argc, argv, "-w:i:o:");
|
||||
int opt = getopt(argc, argv, "-w:B:i:o:");
|
||||
if (opt == -1)
|
||||
break;
|
||||
|
||||
|
@ -47,6 +48,10 @@ main(int argc, char *argv[])
|
|||
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);
|
||||
|
@ -62,7 +67,7 @@ main(int argc, char *argv[])
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
@ -97,8 +102,8 @@ main(int argc, char *argv[])
|
|||
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);
|
||||
|
@ -340,11 +345,30 @@ loop:
|
|||
|
||||
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);
|
||||
|
||||
|
@ -1242,7 +1266,7 @@ char ctab[128] = {
|
|||
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,
|
||||
|
|
|
@ -8,6 +8,7 @@ cprogram {
|
|||
"./*.h",
|
||||
"modules+headers",
|
||||
"modules/src/alloc+lib",
|
||||
"modules/src/data+lib",
|
||||
"modules/src/em_code+lib_k",
|
||||
"modules/src/em_data+lib",
|
||||
"modules/src/em_mes+lib",
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#error Unsupported EM_PSIZE
|
||||
#endif
|
||||
|
||||
extern FILE* input_unit;
|
||||
extern FILE* output_unit;
|
||||
|
||||
#define END 4
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
#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)
|
||||
|
@ -19,7 +23,7 @@ static void i_lchar(intptr_t s, intptr_t n, intptr_t c)
|
|||
|
||||
static intptr_t i_getchar(void)
|
||||
{
|
||||
return fgetc(output_unit);
|
||||
return fgetc(input_unit);
|
||||
}
|
||||
|
||||
static intptr_t i_putchar(intptr_t c)
|
||||
|
@ -28,17 +32,139 @@ 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
|
||||
};
|
||||
|
||||
|
@ -53,8 +179,9 @@ static void patch_addresses(uintptr_t** p)
|
|||
|
||||
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);
|
||||
}
|
Loading…
Reference in a new issue