From 3131dc99153565a36a043af55876aa94b1b3baaf Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 15 Jun 2019 22:22:01 +0200 Subject: [PATCH] Partially working port of stdio to CP/M. I'm not sure this will work; it's getting way too complicated (stdio is horribly subtle). I think I need to rethink things. --- lang/cem/libcc.ansi/build.lua | 1 + .../libcc.ansi/{sys => core}/stdio/clearerr.c | 0 .../cem/libcc.ansi/{sys => core}/stdio/feof.c | 0 .../libcc.ansi/{sys => core}/stdio/ferror.c | 0 .../libcc.ansi/{sys => core}/stdio/fgetc.c | 0 .../libcc.ansi/{sys => core}/stdio/fgets.c | 0 .../libcc.ansi/{sys => core}/stdio/fputc.c | 0 .../libcc.ansi/{sys => core}/stdio/fputs.c | 0 .../libcc.ansi/{sys => core}/stdio/fread.c | 0 .../libcc.ansi/{sys => core}/stdio/fwrite.c | 0 .../cem/libcc.ansi/{sys => core}/stdio/getc.c | 0 .../libcc.ansi/{sys => core}/stdio/getchar.c | 0 .../cem/libcc.ansi/{sys => core}/stdio/putc.c | 0 .../libcc.ansi/{sys => core}/stdio/putchar.c | 0 .../cem/libcc.ansi/{sys => core}/stdio/puts.c | 0 lang/cem/libcc.ansi/headers/ack/emufile.h | 7 ++-- lang/cem/libcc.ansi/headers/stdio.h | 11 +++--- plat/cpm/descr | 1 + plat/cpm/include/ack/file.h | 28 +++++++++++++-- plat/cpm/include/cpm.h | 8 +++++ plat/cpm/libsys/fcb.c | 3 ++ plat/cpm/libsys/fclose.c | 20 +++++++++++ plat/cpm/libsys/feof.c | 9 +++++ plat/cpm/libsys/ferror.c | 8 +++++ plat/cpm/libsys/fflush.c | 12 +++++++ plat/cpm/libsys/getc.c | 36 +++++++++++++++++++ plat/cpm/libsys/putc.c | 17 +++++++++ plat/cpm/libsys/read.c | 31 ++-------------- 28 files changed, 153 insertions(+), 39 deletions(-) rename lang/cem/libcc.ansi/{sys => core}/stdio/clearerr.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/feof.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/ferror.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/fgetc.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/fgets.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/fputc.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/fputs.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/fread.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/fwrite.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/getc.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/getchar.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/putc.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/putchar.c (100%) rename lang/cem/libcc.ansi/{sys => core}/stdio/puts.c (100%) create mode 100644 plat/cpm/libsys/fcb.c create mode 100644 plat/cpm/libsys/fclose.c create mode 100644 plat/cpm/libsys/feof.c create mode 100644 plat/cpm/libsys/ferror.c create mode 100644 plat/cpm/libsys/fflush.c create mode 100644 plat/cpm/libsys/getc.c create mode 100644 plat/cpm/libsys/putc.c diff --git a/lang/cem/libcc.ansi/build.lua b/lang/cem/libcc.ansi/build.lua index 4cb90e05b..29c85b351 100644 --- a/lang/cem/libcc.ansi/build.lua +++ b/lang/cem/libcc.ansi/build.lua @@ -44,6 +44,7 @@ for _, plat in ipairs(vars.plats) do "./core/setjmp/*.c", "./core/setjmp/*.e", "./core/stdlib/*.c", + "./core/stdio/*.c", "./core/string/*.c", "./core/time/*.c", "./sys/exit/*.c", diff --git a/lang/cem/libcc.ansi/sys/stdio/clearerr.c b/lang/cem/libcc.ansi/core/stdio/clearerr.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/clearerr.c rename to lang/cem/libcc.ansi/core/stdio/clearerr.c diff --git a/lang/cem/libcc.ansi/sys/stdio/feof.c b/lang/cem/libcc.ansi/core/stdio/feof.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/feof.c rename to lang/cem/libcc.ansi/core/stdio/feof.c diff --git a/lang/cem/libcc.ansi/sys/stdio/ferror.c b/lang/cem/libcc.ansi/core/stdio/ferror.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/ferror.c rename to lang/cem/libcc.ansi/core/stdio/ferror.c diff --git a/lang/cem/libcc.ansi/sys/stdio/fgetc.c b/lang/cem/libcc.ansi/core/stdio/fgetc.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/fgetc.c rename to lang/cem/libcc.ansi/core/stdio/fgetc.c diff --git a/lang/cem/libcc.ansi/sys/stdio/fgets.c b/lang/cem/libcc.ansi/core/stdio/fgets.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/fgets.c rename to lang/cem/libcc.ansi/core/stdio/fgets.c diff --git a/lang/cem/libcc.ansi/sys/stdio/fputc.c b/lang/cem/libcc.ansi/core/stdio/fputc.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/fputc.c rename to lang/cem/libcc.ansi/core/stdio/fputc.c diff --git a/lang/cem/libcc.ansi/sys/stdio/fputs.c b/lang/cem/libcc.ansi/core/stdio/fputs.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/fputs.c rename to lang/cem/libcc.ansi/core/stdio/fputs.c diff --git a/lang/cem/libcc.ansi/sys/stdio/fread.c b/lang/cem/libcc.ansi/core/stdio/fread.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/fread.c rename to lang/cem/libcc.ansi/core/stdio/fread.c diff --git a/lang/cem/libcc.ansi/sys/stdio/fwrite.c b/lang/cem/libcc.ansi/core/stdio/fwrite.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/fwrite.c rename to lang/cem/libcc.ansi/core/stdio/fwrite.c diff --git a/lang/cem/libcc.ansi/sys/stdio/getc.c b/lang/cem/libcc.ansi/core/stdio/getc.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/getc.c rename to lang/cem/libcc.ansi/core/stdio/getc.c diff --git a/lang/cem/libcc.ansi/sys/stdio/getchar.c b/lang/cem/libcc.ansi/core/stdio/getchar.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/getchar.c rename to lang/cem/libcc.ansi/core/stdio/getchar.c diff --git a/lang/cem/libcc.ansi/sys/stdio/putc.c b/lang/cem/libcc.ansi/core/stdio/putc.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/putc.c rename to lang/cem/libcc.ansi/core/stdio/putc.c diff --git a/lang/cem/libcc.ansi/sys/stdio/putchar.c b/lang/cem/libcc.ansi/core/stdio/putchar.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/putchar.c rename to lang/cem/libcc.ansi/core/stdio/putchar.c diff --git a/lang/cem/libcc.ansi/sys/stdio/puts.c b/lang/cem/libcc.ansi/core/stdio/puts.c similarity index 100% rename from lang/cem/libcc.ansi/sys/stdio/puts.c rename to lang/cem/libcc.ansi/core/stdio/puts.c diff --git a/lang/cem/libcc.ansi/headers/ack/emufile.h b/lang/cem/libcc.ansi/headers/ack/emufile.h index 3eeae2eae..186630e56 100644 --- a/lang/cem/libcc.ansi/headers/ack/emufile.h +++ b/lang/cem/libcc.ansi/headers/ack/emufile.h @@ -30,6 +30,11 @@ struct FILE { #define FOPEN_MAX 20 extern FILE *__iotab[FOPEN_MAX]; +#define stdin (&__stdin) +#define stdout (&__stdout) +#define stderr (&__stderr) +extern FILE __stdin, __stdout, __stderr; + #define FILENAME_MAX 255 #define TMP_MAX 999 #define L_tmpnam (sizeof("/tmp/") + 15) @@ -38,8 +43,6 @@ extern FILE *__iotab[FOPEN_MAX]; extern int __fillbuf(FILE *_stream); extern int __flushbuf(int _c, FILE *_stream); -#define getchar() getc(stdin) -#define putchar(c) putc(c,stdout) #define getc(p) (--(p)->_count >= 0 ? (int) (*(p)->_ptr++) : \ __fillbuf(p)) #define putc(c, p) (--(p)->_count >= 0 ? \ diff --git a/lang/cem/libcc.ansi/headers/stdio.h b/lang/cem/libcc.ansi/headers/stdio.h index 093258fe6..c6ddb8808 100644 --- a/lang/cem/libcc.ansi/headers/stdio.h +++ b/lang/cem/libcc.ansi/headers/stdio.h @@ -23,14 +23,8 @@ typedef struct FILE FILE; #define SEEK_CUR 1 #define SEEK_END 2 -#define stdin (&__stdin) -#define stdout (&__stdout) -#define stderr (&__stderr) - typedef long int fpos_t; -extern FILE __stdin, __stdout, __stderr; - extern int remove(const char *_filename); extern int rename(const char *_old, const char *_new); extern FILE *tmpfile(void); @@ -76,7 +70,10 @@ extern int feof(FILE *_stream); extern int ferror(FILE *_stream); extern void perror(const char *_s); -/* Internal function used by several places which is approximately itoa(). */ +#define getchar() getc(stdin) +#define putchar(c) putc(c, stdout) + +/* Internal function used in several places which is approximately itoa(). */ extern char *_i_compute(unsigned long val, int base, char *s, int nrdigits); #if ACKCONF_WANT_EMULATED_FILE diff --git a/plat/cpm/descr b/plat/cpm/descr index 2dea09e10..e01f2c389 100644 --- a/plat/cpm/descr +++ b/plat/cpm/descr @@ -76,6 +76,7 @@ name led {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ + {PLATFORMDIR}/libc.a \ {PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libend.a) linker diff --git a/plat/cpm/include/ack/file.h b/plat/cpm/include/ack/file.h index 8e7393cdc..b60da6870 100644 --- a/plat/cpm/include/ack/file.h +++ b/plat/cpm/include/ack/file.h @@ -9,6 +9,11 @@ #include +#define CPM_FAKE_FILE ((FILE*)1) +#define stdin CPM_FAKE_FILE +#define stdout CPM_FAKE_FILE +#define stderr CPM_FAKE_FILE + struct FILE { uint8_t user; @@ -16,7 +21,26 @@ struct FILE char buffer[128]; }; -#define FOPEN_MAX 8 -extern FILE* __files[FOPEN_MAX]; +#define getc(p) cpm_getc(p) +#define putc(c, p) cpm_putc(c, p) +#define feof(p) cpm_feof(p) +#define ferror(p) cpm_ferror(p) +#define clearerr(p) cpm_clearerr(p) + +extern int cpm_putc(int c, FILE* stream); +extern int cpm_getc(FILE* stream); + +#if 0 +#define getc(p) (--(p)->_count >= 0 ? (int) (*(p)->_ptr++) : \ + __fillbuf(p)) +#define putc(c, p) (--(p)->_count >= 0 ? \ + (int) (*(p)->_ptr++ = (c)) : \ + __flushbuf((c),(p))) + +#define feof(p) (((p)->_flags & _IOEOF) != 0) +#define ferror(p) (((p)->_flags & _IOERR) != 0) +#define clearerr(p) ((p)->_flags &= ~(_IOERR|_IOEOF)) +#endif + #endif diff --git a/plat/cpm/include/cpm.h b/plat/cpm/include/cpm.h index 3ea9f6e09..c7288856b 100644 --- a/plat/cpm/include/cpm.h +++ b/plat/cpm/include/cpm.h @@ -114,4 +114,12 @@ extern void cpm_overwrite_ccp(void); /* 37 */ extern uint8_t cpm_reset_drives(uint16_t drive_bitmap); /* 40 */ extern uint8_t cpm_write_random_filled(FCB* fcb); +/* File descriptor emulation */ + +struct FCBE +{ + FCB fcb; /* drive 0 means the console */ + uint8_t user; +}; + #endif diff --git a/plat/cpm/libsys/fcb.c b/plat/cpm/libsys/fcb.c new file mode 100644 index 000000000..e8059de3e --- /dev/null +++ b/plat/cpm/libsys/fcb.c @@ -0,0 +1,3 @@ +#include +#include + diff --git a/plat/cpm/libsys/fclose.c b/plat/cpm/libsys/fclose.c new file mode 100644 index 000000000..abae8a6c0 --- /dev/null +++ b/plat/cpm/libsys/fclose.c @@ -0,0 +1,20 @@ +#include +#include +#include + +int fclose(FILE* stream) +{ + if (stream == CPM_FAKE_FILE) + return 0; + + if (fflush(stream)) + return; + + cpm_get_set_user(stream->user); + if (cpm_close_file(&stream->fcb) == 0xff) + { + errno = EIO; + return -1; + } + return 0; +} diff --git a/plat/cpm/libsys/feof.c b/plat/cpm/libsys/feof.c new file mode 100644 index 000000000..a04a76a78 --- /dev/null +++ b/plat/cpm/libsys/feof.c @@ -0,0 +1,9 @@ +#include +#include +#include + +int cpm_feof(FILE* stream) +{ + return 0; +} + diff --git a/plat/cpm/libsys/ferror.c b/plat/cpm/libsys/ferror.c new file mode 100644 index 000000000..b279c8cec --- /dev/null +++ b/plat/cpm/libsys/ferror.c @@ -0,0 +1,8 @@ +#include +#include +#include + +int cpm_ferror(FILE* stream) +{ + return 0; +} diff --git a/plat/cpm/libsys/fflush.c b/plat/cpm/libsys/fflush.c new file mode 100644 index 000000000..664488467 --- /dev/null +++ b/plat/cpm/libsys/fflush.c @@ -0,0 +1,12 @@ +#include +#include +#include + +int fflush(FILE* stream) +{ + if (stream == CPM_FAKE_FILE) + return 0; + + errno = EBADF; + return -1; +} \ No newline at end of file diff --git a/plat/cpm/libsys/getc.c b/plat/cpm/libsys/getc.c new file mode 100644 index 000000000..bb322fc04 --- /dev/null +++ b/plat/cpm/libsys/getc.c @@ -0,0 +1,36 @@ +#include +#include +#include + +struct buffer +{ + uint8_t mx; + uint8_t nc; + uint8_t c[128]; +}; + +static struct buffer buffer; +static uint8_t pos; + +int read_from_console(void) +{ + while (pos == buffer.nc) + { + /* Refill buffer. */ + buffer.mx = sizeof(buffer.c); + buffer.nc = 0; + cpm_readline((uint8_t*) &buffer); + pos = 0; + } + + return buffer.c[pos++]; +} + +int cpm_getc(FILE* stream) +{ + if (stream == CPM_FAKE_FILE) + return read_from_console(); + + errno = EBADF; + return -1; +} diff --git a/plat/cpm/libsys/putc.c b/plat/cpm/libsys/putc.c new file mode 100644 index 000000000..f78027d97 --- /dev/null +++ b/plat/cpm/libsys/putc.c @@ -0,0 +1,17 @@ +#include +#include +#include + +int cpm_putc(int c, FILE* stream) +{ + if (stream == CPM_FAKE_FILE) + { + cpm_conout(c); + if (c == '\n') + cpm_conout(c); + return 0; + } + + errno = EBADF; + return -1; +} diff --git a/plat/cpm/libsys/read.c b/plat/cpm/libsys/read.c index b04a13ee5..952995af8 100644 --- a/plat/cpm/libsys/read.c +++ b/plat/cpm/libsys/read.c @@ -3,6 +3,7 @@ * $Revision$ */ +#include #include #include #include @@ -13,37 +14,11 @@ ssize_t read(int fd, void* buffer, size_t count) short save; unsigned char before_n; - /* We're only allowed to read from fd 0, 1 or 2. */ - if ((fd < 0) || (fd > 2)) + if (fd != 0) { errno = EBADF; return -1; } - /* We need room for at least 1 char plus '\n'. */ - if (count < 2) - { - errno = EINVAL; - return -1; - } - - /* Make room to append '\n' later. */ - before_n = count > 255 ? 255 : count - 1; - - /* Borrow 2 bytes of RAM before the buffer. */ - /* This might overwrite count!!! */ - save = ((short*)buffer)[-1]; - - /* Read one line from the console. */ - ((unsigned char*)buffer)[-2] = before_n; - cpm_readline((uint8_t*)buffer - 2); - before_n = ((unsigned char*)buffer)[-1]; - - ((char*)buffer)[before_n] = '\n'; /* Append '\n'. */ - ((short*)buffer)[-1] = save; /* Give back borrowed bytes. */ - - /* Echo '\n' to console. */ - cpm_printstring("\r\n$"); - - return (int)before_n + 1; + return fread(buffer, 1, count, stdin); }