Skip to content

Commit

Permalink
[Breaking] Add context pointer to character conversion
Browse files Browse the repository at this point in the history
This allows passing general read and write lambdas that require a
pointer to some context. The context should usually fold away, since
character conversion is always_inline.
  • Loading branch information
mysterymath committed May 12, 2024
1 parent aacd8d6 commit 8ef9c08
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 74 deletions.
25 changes: 13 additions & 12 deletions mos-platform/atari8-common/getchar.c
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
#include <atari.h>
#include <stdio.h>

__attribute__((always_inline, weak)) int __to_ascii(int (*read)(void)) {
int c = read();
__attribute__((always_inline, weak)) int __to_ascii(void *ctx,
int (*read)(void *ctx)) {
int c = read(ctx);
switch (c) {
case 0x1e:
return '\b';
case 0x7f:
return '\t';
case 0x9b:
return '\n';
case 0xfd:
return '\a';
default:
return c;
case 0x1e:
return '\b';
case 0x7f:
return '\t';
case 0x9b:
return '\n';
case 0xfd:
return '\a';
default:
return c;
}
}

Expand Down
14 changes: 7 additions & 7 deletions mos-platform/atari8-common/putchar.c
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#include <stdio.h>

__attribute__((always_inline, weak)) void __from_ascii(char c,
void (*write)(char c)) {
__attribute__((always_inline, weak)) void
__from_ascii(char c, void *ctx, void (*write)(char c, void *ctx)) {
if (__builtin_expect(c == '\n', 0))
write(0x9b);
write(0x9b, ctx);
else if (__builtin_expect(c == '\t', 0))
write(0x7f);
write(0x7f, ctx);
else if (__builtin_expect(c == '\a', 0))
write(0xfd);
write(0xfd, ctx);
else if (__builtin_expect(c == '\b', 0))
write(0x1e);
write(0x1e, ctx);
else
write(c);
write(c, ctx);
}

// Send character output via HATABS/IOCB0 which the OS opens to "E:"
Expand Down
19 changes: 10 additions & 9 deletions mos-platform/commodore/char-conv.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,23 @@ asm(".section .init.250,\"axR\",@progbits\n"
" lda #0x0e\n"
" jsr __CHROUT\n");

__attribute__((always_inline, weak)) void __from_ascii(char c,
void (*write)(char c)) {
__attribute__((always_inline, weak)) void
__from_ascii(char c, void *ctx, void (*write)(char c, void *ctx)) {
if (__builtin_expect(c == '\n', 0))
write('\r');
write('\r', ctx);
else if (__builtin_expect(c == '\b', 0))
write('\x9d'); // CURSOR LEFT
write('\x9d', ctx); // CURSOR LEFT
else if ('a' <= c && c <= 'z')
write(c & ~0x20);
write(c & ~0x20, ctx);
else if ('A' <= c && c <= 'Z')
write(c | 0x80);
write(c | 0x80, ctx);
else
write(c);
write(c, ctx);
}

__attribute__((always_inline, weak)) int __to_ascii(int (*read)(void)) {
int c = read();
__attribute__((always_inline, weak)) int __to_ascii(void *ctx,
int (*read)(void *ctx)) {
int c = read(ctx);
if (__builtin_expect(c == '\r', 0))
return '\n';
else if (__builtin_expect(c == '\x9d', 0)) // CURSOR LEFT
Expand Down
11 changes: 6 additions & 5 deletions mos-platform/commodore/translate-filename.cc
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#include <stdio.h>

static char buf[36];
static char* bptr;

extern "C" const char *_translate_filename(const char *filename) {
bptr = buf;
static char buf[36];
char *bptr = buf;
for (const char *s = filename; *s; ++s)
__from_ascii(*s, [](char c) { *bptr++ = c; });
__from_ascii(*s, &bptr, [](char c, void *ctx) {
char *&bptr = *(char **)ctx;
*bptr++ = c;
});
*bptr = '\0';
return buf;
}
11 changes: 6 additions & 5 deletions mos-platform/common/c/char-conv.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
__attribute__((always_inline, weak)) void __from_ascii(char c,
void (*write)(char c)) {
write(c);
__attribute__((always_inline, weak)) void
__from_ascii(char c, void *ctx, void (*write)(char c, void *ctx)) {
write(c, ctx);
}

__attribute__((always_inline, weak)) int __to_ascii(int (*read)(void)) {
return read();
__attribute__((always_inline, weak)) int __to_ascii(void *ctx,
int (*read)(void *ctx)) {
return read(ctx);
}
8 changes: 6 additions & 2 deletions mos-platform/common/c/stdio-minimal.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,16 @@ __attribute__((weak)) int fputs(const char *__restrict__ s,

__attribute__((weak)) int getc(FILE *stream) { return fgetc(stream); }

__attribute__((weak)) int getchar(void) { return __to_ascii(__getchar); }
static int getchar_wrapper(void *ctx) { return __getchar(); }
__attribute__((weak)) int getchar(void) {
return __to_ascii(NULL, getchar_wrapper);
}

__attribute__((weak)) int putc(int c, FILE *stream) { return fputc(c, stream); }

static void putchar_wrapper(char c, void *ctx) { __putchar(c); }
__attribute__((weak)) int putchar(int c) {
__from_ascii(c, __putchar);
__from_ascii(c, NULL, putchar_wrapper);
return c;
}

Expand Down
4 changes: 2 additions & 2 deletions mos-platform/common/c/ungetc.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ int ungetc(int c, FILE *stream) {
return c;
}

static int ungetc_getchar(void) {
static int ungetc_getchar(void* ctx) {
if (full) {
full = false;
return ungetc_buffer;
Expand All @@ -22,4 +22,4 @@ static int ungetc_getchar(void) {
}
}

int getchar(void) { return __to_ascii(ungetc_getchar); }
int getchar(void) { return __to_ascii(NULL, ungetc_getchar); }
12 changes: 7 additions & 5 deletions mos-platform/common/include/stdio.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ typedef struct _FILE FILE;
#define FOPEN_MAX 8

/* See setvbuf(), third argument */
#define _IOFBF (1u<<0)
#define _IOLBF (1u<<1)
#define _IONBF (1u<<2)
#define _IOFBF (1u << 0)
#define _IOLBF (1u << 1)
#define _IONBF (1u << 2)

typedef uint64_t fpos_t;

Expand Down Expand Up @@ -115,11 +115,13 @@ void perror(const char *s);

// Write a sequence of characters in the target's character set that
// correspond to the given ASCII character.
__attribute__((always_inline)) void __from_ascii(char c, void (*write)(char c));
__attribute__((always_inline)) void
__from_ascii(char c, void *ctx, void (*write)(char c, void *ctx));

// Read a sequence of characters in the target's character set and return the
// corrsponding ASCII character.
__attribute__((always_inline)) int __to_ascii(int (*read)(void));
__attribute__((always_inline)) int __to_ascii(void *ctx,
int (*read)(void *ctx));

// Put a character in the target's character set out to the target's
// equivalent of file descriptor 1 (stdout).
Expand Down
8 changes: 4 additions & 4 deletions mos-platform/cpm65/putchar.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
#include <cpm.h>
#include <stdio.h>

__attribute__((always_inline, weak)) void __from_ascii(char c,
void (*emit)(char c)) {
__attribute__((always_inline, weak)) void
__from_ascii(char c, void *ctx, void (*emit)(char c, void *ctx)) {
if (__builtin_expect(c == '\n', 0))
emit('\r');
emit(c);
emit('\r', ctx);
emit(c, ctx);
}

void __putchar(char c) { cpm_conout(c); }
15 changes: 8 additions & 7 deletions mos-platform/cx16/char-conv.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@ asm(".section .init.250,\"axR\",@progbits\n"
" lda #0x0f\n"
" jsr __CHROUT\n");

__attribute__((always_inline, weak)) void __from_ascii(char c,
void (*write)(char c)) {
__attribute__((always_inline, weak)) void
__from_ascii(char c, void *ctx, void (*write)(char c, void *ctx)) {
if (__builtin_expect(c == '\n', 0))
write('\r');
write('\r', ctx);
else if (__builtin_expect(c == '\b', 0))
write('\x9d'); // CURSOR LEFT
write('\x9d', ctx); // CURSOR LEFT
else
write(c);
write(c, ctx);
}

__attribute__((always_inline, weak)) int __to_ascii(int (*read)(void)) {
int c = read();
__attribute__((always_inline, weak)) int __to_ascii(void *ctx,
int (*read)(void *ctx)) {
int c = read(ctx);
switch (c) {
case '\r':
return '\n';
Expand Down
5 changes: 3 additions & 2 deletions mos-platform/eater/getchar.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#include <chrin.h>
#include <stdio.h>

__attribute__((always_inline, weak)) int __to_ascii(int (*read)(void)) {
int c = read();
__attribute__((always_inline, weak)) int __to_ascii(void *ctx,
int (*read)(void *ctx)) {
int c = read(ctx);
return c == '\r' ? '\n' : c;
}

Expand Down
8 changes: 4 additions & 4 deletions mos-platform/eater/putchar.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include <stdio.h>

__attribute__((always_inline, weak)) void __from_ascii(char c,
void (*write)(char c)) {
__attribute__((always_inline, weak)) void
__from_ascii(char c, void *ctx, void (*write)(char c, void *ctx)) {
if (__builtin_expect(c == '\n', 0))
write('\r');
write(c);
write('\r', ctx);
write(c, ctx);
}

// Implemented in assembly.
Expand Down
13 changes: 7 additions & 6 deletions mos-platform/neo6502/char-conv.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@

// Neo6502 uses CR line endings instead of LF.

__attribute__((always_inline, weak)) void __from_ascii(char c,
void (*write)(char c)) {
__attribute__((always_inline, weak)) void
__from_ascii(char c, void *ctx, void (*write)(char c, void *ctx)) {
if (__builtin_expect(c == '\n', 0))
write('\r');
write('\r', ctx);
else
write(c);
write(c, ctx);
}

__attribute__((always_inline, weak)) int __to_ascii(int (*read)(void)) {
int c = read();
__attribute__((always_inline, weak)) int __to_ascii(void *ctx,
int (*read)(void *ctx)) {
int c = read(ctx);
if (__builtin_expect(c == '\r', 0))
return '\n';
return c;
Expand Down
8 changes: 4 additions & 4 deletions mos-platform/osi-c1p/putchar.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ using __osic1p_screen = __osi_screen<>;

extern "C" {

__attribute__((always_inline, weak)) void __from_ascii(char c,
void (*write)(char c)) {
__attribute__((always_inline, weak)) void
__from_ascii(char c, void *ctx, void (*write)(char c, void *ctx)) {
/*
* The low-level character output function implements LF as line feed
* without CR, e.g. the active position stays in the same column. Here we
* implement the C standard semantics where \n moves the active position
* to the initial position of the next line.
*/
if (c == '\n')
write('\r');
write(c);
write('\r', ctx);
write(c, ctx);
}

/**
Expand Down

0 comments on commit 8ef9c08

Please sign in to comment.