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:
David Given 2016-12-29 17:10:21 +00:00
parent e3f8fb84dc
commit ebd424e7f1
5 changed files with 170 additions and 12 deletions

View file

@ -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

View file

@ -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,

View file

@ -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",

View file

@ -14,6 +14,9 @@
#error Unsupported EM_PSIZE
#endif
extern FILE* input_unit;
extern FILE* output_unit;
#define END 4
#endif

View file

@ -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);
}