B library consisting of basic character, console and file handling was added
to `/bi.c`. This replaces the assembly-language B library, which is given for
reference in `/doc/libb`. Note that a few of the library calls (e.g. `printf`)
-are compiled from B. At the moment, just a basic `printf()` is implemented in
-`/bi.c`, and the full `printf()` will be installed later as interpreted code.
+are compiled from B. At the moment we manually assemble these sources into any
+program that needs them, but they have to be patched to avoid conflicts with
+the Lnnn labels (because we do not use a linker and assemble `*.s` together).
+To allow proper multiple-module B programs, we would have to use the linker.
This was sufficient for Papenhoff's B compiler `/bc.b` and `/ba.b` to compile
itself. I use Papenhoff's `/bc.s`, `/ba.s` for bootstrapping for now. See
SYS_LINK = (uint16_t)-80,
SYS_MAKDIR = (uint16_t)-84,
SYS_OPEN = (uint16_t)-88,
- SYS_PRINTF = (uint16_t)-92,
- SYS_PRINTN = (uint16_t)-96,
- SYS_PUTCHAR = (uint16_t)-100,
- SYS_QUIT = (uint16_t)-104,
- SYS_READ = (uint16_t)-108,
- SYS_SEEK = (uint16_t)-112,
- SYS_SETUID = (uint16_t)-116,
- SYS_SLEEP = (uint16_t)-120,
- SYS_STAT = (uint16_t)-124,
- SYS_STTY = (uint16_t)-128,
- SYS_TIME = (uint16_t)-132,
- SYS_UNLINK = (uint16_t)-136,
- SYS_WAIT = (uint16_t)-140,
- SYS_WRITE = (uint16_t)-144,
+ SYS_PUTCHAR = (uint16_t)-92,
+ SYS_QUIT = (uint16_t)-96,
+ SYS_READ = (uint16_t)-100,
+ SYS_SEEK = (uint16_t)-104,
+ SYS_SETUID = (uint16_t)-108,
+ SYS_SLEEP = (uint16_t)-112,
+ SYS_STAT = (uint16_t)-116,
+ SYS_STTY = (uint16_t)-120,
+ SYS_TIME = (uint16_t)-124,
+ SYS_UNLINK = (uint16_t)-128,
+ SYS_WAIT = (uint16_t)-132,
+ SYS_WRITE = (uint16_t)-136,
};
#define MEM_BASE 0x4000
#define MEM_LIMIT SYS_WRITE
mem[((addr + 2) >> 1) & MEM_MASK] = OP_N7;
}
mem[((SYS_LCHAR + 2) >> 1) & MEM_MASK] = OP_N11; // void return
- mem[((SYS_PRINTF + 2) >> 1) & MEM_MASK] = OP_N11; // void return
// run
- uint16_t arg0, arg1, arg2, len;
+ uint16_t arg0, arg1, arg2;
temp = malloc(temp_size);
mode_t mode;
- uint8_t ch, octal[8]; // room for "-100000"
+ uint8_t ch;
rassert(temp);
while (true) {
#endif
mem[(((r5 += 2) - 2) >> 1) & MEM_MASK] = data;
break;
- case (uint16_t)(SYS_PRINTF + 2):
- r5 = r4 + 42; // s; 42
- arg0 = mem[((r4 + 4) >> 1) & MEM_MASK];
- addr = r4 + 6; // argument pointer
-#if TRACE
- fprintf(stderr, "printf(%04x, ...)\n", arg0);
-#endif
- size = temp_strlen(arg0) + 1;
- temp_ensure(size);
- temp_set(arg0, size);
-#if TRACE
- fprintf(stderr, "\"%s\"\n", temp);
-#endif
- for (uint8_t *p = temp; (ch = *p++) != 0; ) {
- if (ch == '%') {
- data = mem[(((addr += 2) - 2) >> 1) & MEM_MASK]; // argument
- switch (ch = *p++) {
- case 'c':
- ch = data;
- write(mem[(fout >> 1) & MEM_MASK], &ch, 1);
- break;
- case 'o':
- write(
- mem[(fout >> 1) & MEM_MASK],
- octal,
- (int16_t)data < 0 ?
- sprintf((char *)octal, "-%o", -(int16_t)data) :
- sprintf((char *)octal, "%o", (int16_t)data)
- );
- break;
- case 's':
- len = temp_strlen(data);
- temp_ensure(len + 1);
- temp_set(data, len + 1);
- write(mem[(fout >> 1) & MEM_MASK], temp, len);
- temp_set(arg0, size);
- break;
- default:
- fprintf(stderr, "fprintf() %%%c not implemented\n", ch);
- exit(EXIT_FAILURE);
- }
- }
- else
- write(mem[(fout >> 1) & MEM_MASK], &ch, 1);
- }
- break;
- case (uint16_t)(SYS_PRINTN + 2):
- fprintf(stderr, "printn() not implemented\n");
- exit(EXIT_FAILURE);
case (uint16_t)(SYS_PUTCHAR + 2):
r5 = r4 + 6; // s; 6
arg0 = mem[((r4 + 4) >> 1) & MEM_MASK];