ack/lang/b/lib/main.c

190 lines
2.7 KiB
C

#include "b.h"
#include <stdarg.h>
#include <string.h>
#include <limits.h>
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)
{
const char* p = (const char*)(s<<SHIFT);
return p[n];
}
static intptr_t i_lchar(intptr_t s, intptr_t n, intptr_t c)
{
char* p = (char*)(s<<SHIFT);
p[n] = c;
return c;
}
static intptr_t i_getchar(void)
{
return fgetc(input_unit);
}
static intptr_t i_putchar(intptr_t c)
{
fputc(c, output_unit);
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* bmodule_stdlib[] =
{
&b_char,
&b_lchar,
&b_getchar,
&b_putchar,
&b_putstr,
&b_getstr,
&b_flush,
&b_printf,
0
};
void patch_addresses(uintptr_t** p)
{
while (*p)
{
uintptr_t* q = *p++;
if (*q & MASK)
abort();
*q >>= SHIFT;
}
}
int main(int argc, const char* argv[])
{
patch_addresses(bmodule_stdlib);
binit();
input_unit = stdin;
output_unit = stdout;
return i_main(argc, NULL);
}