187 lines
		
	
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			187 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++;
 | 
						|
        *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);
 | 
						|
}
 |