From 9109d7af7f62add6467099dd5c7979d16ccd15db Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 15 Jun 2019 13:07:10 +0200 Subject: [PATCH 1/9] First stage in modularising FILE*. Refactor so that printf/scanf don't rely on FILE* innards; allow plats to replace the entire emulated FILE* system. --- lang/cem/libcc.ansi/headers/ack/config.h | 5 ++ lang/cem/libcc.ansi/headers/ack/emufile.h | 59 +++++++++++++++++++ lang/cem/libcc.ansi/headers/stdio.h | 68 +++++----------------- lang/cem/libcc.ansi/sys/stdio/data.c | 8 +-- lang/cem/libcc.ansi/sys/stdio/doprnt.c | 18 +++--- lang/cem/libcc.ansi/sys/stdio/doscan.c | 71 +++++++++++------------ lang/cem/libcc.ansi/sys/stdio/fclose.c | 2 +- lang/cem/libcc.ansi/sys/stdio/fdopen.c | 2 +- lang/cem/libcc.ansi/sys/stdio/fflush.c | 2 +- lang/cem/libcc.ansi/sys/stdio/fileno.c | 2 +- lang/cem/libcc.ansi/sys/stdio/fillbuf.c | 2 +- lang/cem/libcc.ansi/sys/stdio/flushbuf.c | 2 +- lang/cem/libcc.ansi/sys/stdio/fopen.c | 2 +- lang/cem/libcc.ansi/sys/stdio/fprintf.c | 4 +- lang/cem/libcc.ansi/sys/stdio/freopen.c | 2 +- lang/cem/libcc.ansi/sys/stdio/fscanf.c | 4 +- lang/cem/libcc.ansi/sys/stdio/fseek.c | 2 +- lang/cem/libcc.ansi/sys/stdio/ftell.c | 2 +- lang/cem/libcc.ansi/sys/stdio/loc_incl.h | 4 +- lang/cem/libcc.ansi/sys/stdio/printf.c | 4 +- lang/cem/libcc.ansi/sys/stdio/scanf.c | 4 +- lang/cem/libcc.ansi/sys/stdio/setbuf.c | 2 +- lang/cem/libcc.ansi/sys/stdio/setvbuf.c | 2 +- lang/cem/libcc.ansi/sys/stdio/snprintf.c | 25 +++++--- lang/cem/libcc.ansi/sys/stdio/sprintf.c | 12 +--- lang/cem/libcc.ansi/sys/stdio/sscanf.c | 27 ++++++--- lang/cem/libcc.ansi/sys/stdio/tmpfile.c | 2 +- lang/cem/libcc.ansi/sys/stdio/tmpnam.c | 2 +- lang/cem/libcc.ansi/sys/stdio/ungetc.c | 2 +- lang/cem/libcc.ansi/sys/stdio/vfprintf.c | 10 +++- lang/cem/libcc.ansi/sys/stdio/vfscanf.c | 30 ++++++++++ lang/cem/libcc.ansi/sys/stdio/vprintf.c | 2 +- lang/cem/libcc.ansi/sys/stdio/vsnprintf.c | 27 +++++---- lang/cem/libcc.ansi/sys/stdio/vsprintf.c | 16 +---- plat/cpm/include/ack/file.h | 22 +++++++ plat/cpm/include/ack/plat.h | 8 +++ plat/cpm/include/build.lua | 1 + 37 files changed, 273 insertions(+), 186 deletions(-) create mode 100644 lang/cem/libcc.ansi/headers/ack/emufile.h create mode 100644 lang/cem/libcc.ansi/sys/stdio/vfscanf.c create mode 100644 plat/cpm/include/ack/file.h diff --git a/lang/cem/libcc.ansi/headers/ack/config.h b/lang/cem/libcc.ansi/headers/ack/config.h index 2ee784213..41e9bc3b6 100644 --- a/lang/cem/libcc.ansi/headers/ack/config.h +++ b/lang/cem/libcc.ansi/headers/ack/config.h @@ -63,4 +63,9 @@ #define ACKCONF_WANT_STDIO 1 #endif +#ifndef ACKCONF_WANT_EMULATED_FILE +/* Implement FILE* on top of read()/write() file descriptors. */ +#define ACKCONF_WANT_EMULATED_FILE 1 +#endif + #endif diff --git a/lang/cem/libcc.ansi/headers/ack/emufile.h b/lang/cem/libcc.ansi/headers/ack/emufile.h new file mode 100644 index 000000000..6e799b47b --- /dev/null +++ b/lang/cem/libcc.ansi/headers/ack/emufile.h @@ -0,0 +1,59 @@ +#ifndef ACK_EMUFILE_H +#define ACK_EMUFILE_H + +/* + * Focus point of all stdio activity. + */ +struct FILE { + int _count; + int _fd; + int _flags; + int _bufsiz; + unsigned char *_buf; + unsigned char *_ptr; +}; + +#define _IOFBF 0x000 +#define _IOREAD 0x001 +#define _IOWRITE 0x002 +#define _IONBF 0x004 +#define _IOMYBUF 0x008 +#define _IOEOF 0x010 +#define _IOERR 0x020 +#define _IOLBF 0x040 +#define _IOREADING 0x080 +#define _IOWRITING 0x100 +#define _IOAPPEND 0x200 + +#define BUFSIZ 1024 + +#define FOPEN_MAX 20 +extern FILE *__iotab[FOPEN_MAX]; + +#define FILENAME_MAX 255 +#define TMP_MAX 999 +#define L_tmpnam (sizeof("/tmp/") + 15) +#define ACK_TMP_PREFIX "/tmp/tmp." + +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 ? \ + (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)) + +/* Non-standard extensions */ + +extern int fileno(FILE *_stream); +extern FILE* fdopen(int fildes, const char *type); +#define fileno(stream) ((stream)->_fd) + +#endif diff --git a/lang/cem/libcc.ansi/headers/stdio.h b/lang/cem/libcc.ansi/headers/stdio.h index 52f286f20..7988c397d 100644 --- a/lang/cem/libcc.ansi/headers/stdio.h +++ b/lang/cem/libcc.ansi/headers/stdio.h @@ -10,30 +10,14 @@ #define _STDIO_H #include +#include +#include -/* - * Focus point of all stdio activity. - */ -typedef struct __iobuf { - int _count; - int _fd; - int _flags; - int _bufsiz; - unsigned char *_buf; - unsigned char *_ptr; -} FILE; +/* Public stdio entry points. */ -#define _IOFBF 0x000 -#define _IOREAD 0x001 -#define _IOWRITE 0x002 -#define _IONBF 0x004 -#define _IOMYBUF 0x008 -#define _IOEOF 0x010 -#define _IOERR 0x020 -#define _IOLBF 0x040 -#define _IOREADING 0x080 -#define _IOWRITING 0x100 -#define _IOAPPEND 0x200 +typedef struct FILE FILE; + +#define EOF (-1) #define SEEK_SET 0 #define SEEK_CUR 1 @@ -43,18 +27,8 @@ typedef struct __iobuf { #define stdout (&__stdout) #define stderr (&__stderr) -#define BUFSIZ 1024 -#define EOF (-1) - -#define FOPEN_MAX 20 - -#define FILENAME_MAX 255 -#define TMP_MAX 999 -#define L_tmpnam (sizeof("/tmp/") + 15) - typedef long int fpos_t; -extern FILE *__iotab[FOPEN_MAX]; extern FILE __stdin, __stdout, __stderr; extern int remove(const char *_filename); @@ -69,6 +43,7 @@ extern void setbuf(FILE *_stream, char *_buf); extern int setvbuf(FILE *_stream, char *_buf, int _mode, size_t _size); extern int fprintf(FILE *_stream, const char *_format, ...); extern int fscanf(FILE *_stream, const char *_format, ...); +extern int vfscanf(FILE *_stream, const char *_format, va_list ap); extern int printf(const char *_format, ...); extern int scanf(const char *_format, ...); extern int sprintf(char *_s, const char *_format, ...); @@ -76,8 +51,8 @@ extern int snprintf(char *_s, size_t _len, const char *_format, ...); extern int sscanf(const char *_s, const char *_format, ...); extern int vfprintf(FILE *_stream, const char *_format, char *_arg); extern int vprintf(const char *_format, char *_arg); -extern int vsprintf(char *_s, const char *_format, char *_arg); -extern int vsnprintf(char *_s, size_t _len, const char *_format, char *_arg); +extern int vsprintf(char *_s, const char *_format, va_list ap); +extern int vsnprintf(char *_s, size_t _len, const char *_format, va_list ap); extern int fgetc(FILE *_stream); extern char *fgets(char *_s, int _n, FILE *_stream); extern int fputc(int _c, FILE *_stream); @@ -101,25 +76,10 @@ extern int feof(FILE *_stream); extern int ferror(FILE *_stream); extern void perror(const char *_s); -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 ? \ - (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)) - -/* Non-standard extensions */ - -extern int fileno(FILE *_stream); -extern FILE* fdopen(int fildes, const char *type); -#define fileno(stream) ((stream)->_fd) +#if ACKCONF_WANT_EMULATED_FILE +#include +#else +#include +#endif #endif /* _STDIO_H */ diff --git a/lang/cem/libcc.ansi/sys/stdio/data.c b/lang/cem/libcc.ansi/sys/stdio/data.c index ccf1664ce..aba91557a 100644 --- a/lang/cem/libcc.ansi/sys/stdio/data.c +++ b/lang/cem/libcc.ansi/sys/stdio/data.c @@ -5,19 +5,19 @@ #include -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE -struct __iobuf __stdin = { +struct FILE __stdin = { 0, 0, _IOREAD, 0, (unsigned char*)NULL, (unsigned char*)NULL, }; -struct __iobuf __stdout = { +struct FILE __stdout = { 0, 1, _IOWRITE, 0, (unsigned char*)NULL, (unsigned char*)NULL, }; -struct __iobuf __stderr = { +struct FILE __stderr = { 0, 2, _IOWRITE | _IOLBF, 0, (unsigned char*)NULL, (unsigned char*)NULL, }; diff --git a/lang/cem/libcc.ansi/sys/stdio/doprnt.c b/lang/cem/libcc.ansi/sys/stdio/doprnt.c index 9f74c7659..8c97fb5a4 100644 --- a/lang/cem/libcc.ansi/sys/stdio/doprnt.c +++ b/lang/cem/libcc.ansi/sys/stdio/doprnt.c @@ -157,7 +157,7 @@ o_print(va_list* ap, int flags, char* s, char c, int precision, int is_signed) return s; } -int _doprnt(register const char* fmt, va_list ap, FILE* stream) +int _doprnt(register const char* fmt, va_list ap, void (*put)(int)) { register char* s; register int j; @@ -176,7 +176,7 @@ int _doprnt(register const char* fmt, va_list ap, FILE* stream) PUTC('\r'); } #endif - PUTC(c); + put(c); nrchars++; continue; } @@ -263,7 +263,7 @@ int _doprnt(register const char* fmt, va_list ap, FILE* stream) nrchars++; } #endif - PUTC(c); + put(c); nrchars++; continue; case 'n': @@ -366,32 +366,32 @@ int _doprnt(register const char* fmt, va_list ap, FILE* stream) { j--; nrchars++; - PUTC(*s1++); + put(*s1++); } else { j -= 2; nrchars += 2; - PUTC(*s1++); - PUTC(*s1++); + put(*s1++); + put(*s1++); } } do { - PUTC(zfill); + put(zfill); } while (--i); } nrchars += j; while (--j >= 0) { - PUTC(*s1++); + put(*s1++); } if (i > 0) nrchars += i; while (--i >= 0) - PUTC(zfill); + put(zfill); } return nrchars; } diff --git a/lang/cem/libcc.ansi/sys/stdio/doscan.c b/lang/cem/libcc.ansi/sys/stdio/doscan.c index 3a1076bad..45748427e 100644 --- a/lang/cem/libcc.ansi/sys/stdio/doscan.c +++ b/lang/cem/libcc.ansi/sys/stdio/doscan.c @@ -33,8 +33,7 @@ static char inp_buf[NUMLEN]; * is then set to 0, so strtol() will get the right argument. */ static char* -o_collect(register int c, register FILE* stream, char type, - int width, int* basep) +o_collect(register int c, char type, int width, int* basep, int (*get)(void), void (*unget)(int c)) { register char* bufp = inp_buf; register int base; @@ -63,14 +62,14 @@ o_collect(register int c, register FILE* stream, char type, { *bufp++ = c; if (--width) - c = getc(stream); + c = get(); } if (width && c == '0' && base == 16) { *bufp++ = c; if (--width) - c = getc(stream); + c = get(); if (c != 'x' && c != 'X') { if (type == 'i') @@ -80,7 +79,7 @@ o_collect(register int c, register FILE* stream, char type, { *bufp++ = c; if (--width) - c = getc(stream); + c = get(); } } else if (type == 'i') @@ -95,14 +94,14 @@ o_collect(register int c, register FILE* stream, char type, { *bufp++ = c; if (--width) - c = getc(stream); + c = get(); } else break; } if (width && c != EOF) - ungetc(c, stream); + unget(c); if (type == 'i') base = 0; *basep = base; @@ -120,7 +119,7 @@ o_collect(register int c, register FILE* stream, char type, * numbers to be passed to strtod(). (e.g. 1.3e+) */ static char* -f_collect(register int c, register FILE* stream, register int width) +f_collect(register int c, register int width, int (*get)(void), void (*unget)(int c)) { register char* bufp = inp_buf; int digit_seen = 0; @@ -129,7 +128,7 @@ f_collect(register int c, register FILE* stream, register int width) { *bufp++ = c; if (--width) - c = getc(stream); + c = get(); } while (width && isdigit(c)) @@ -137,26 +136,26 @@ f_collect(register int c, register FILE* stream, register int width) digit_seen++; *bufp++ = c; if (--width) - c = getc(stream); + c = get(); } if (width && c == '.') { *bufp++ = c; if (--width) - c = getc(stream); + c = get(); while (width && isdigit(c)) { digit_seen++; *bufp++ = c; if (--width) - c = getc(stream); + c = get(); } } if (!digit_seen) { if (width && c != EOF) - ungetc(c, stream); + unget(c); return inp_buf - 1; } else @@ -166,30 +165,30 @@ f_collect(register int c, register FILE* stream, register int width) { *bufp++ = c; if (--width) - c = getc(stream); + c = get(); if (width && (c == '+' || c == '-')) { *bufp++ = c; if (--width) - c = getc(stream); + c = get(); } while (width && isdigit(c)) { digit_seen++; *bufp++ = c; if (--width) - c = getc(stream); + c = get(); } if (!digit_seen) { if (width && c != EOF) - ungetc(c, stream); + unget(c); return inp_buf - 1; } } if (width && c != EOF) - ungetc(c, stream); + unget(c); *bufp = '\0'; return bufp - 1; } @@ -199,7 +198,7 @@ f_collect(register int c, register FILE* stream, register int width) * the routine that does the scanning */ -int _doscan(register FILE* stream, const char* format, va_list ap) +int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int c)) { int done = 0; /* number of items done */ int nrchars = 0; /* number of characters read */ @@ -226,15 +225,15 @@ int _doscan(register FILE* stream, const char* format, va_list ap) { while (isspace(*format)) format++; /* skip whitespace */ - ic = getc(stream); + ic = get(); nrchars++; while (isspace(ic)) { - ic = getc(stream); + ic = get(); nrchars++; } if (ic != EOF) - ungetc(ic, stream); + unget(ic); nrchars--; } if (!*format) @@ -242,12 +241,12 @@ int _doscan(register FILE* stream, const char* format, va_list ap) if (*format != '%') { - ic = getc(stream); + ic = get(); nrchars++; if (ic != *format++) { if (ic != EOF) - ungetc(ic, stream); + unget(ic); nrchars--; break; /* error */ } @@ -256,7 +255,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) format++; if (*format == '%') { - ic = getc(stream); + ic = get(); nrchars++; if (ic == '%') { @@ -299,7 +298,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) { do { - ic = getc(stream); + ic = get(); nrchars++; } while (isspace(ic)); if (ic == EOF) @@ -307,7 +306,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) } else if (kind != 'n') { /* %c or %[ */ - ic = getc(stream); + ic = get(); if (ic == EOF) break; /* outer while */ nrchars++; @@ -344,7 +343,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) if (!width) return done; - str = o_collect(ic, stream, kind, width, &base); + str = o_collect(ic, kind, width, &base, get, unget); if (str < inp_buf || (str == inp_buf && (*str == '-' @@ -385,7 +384,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) *str++ = (char)ic; if (--width) { - ic = getc(stream); + ic = get(); nrchars++; } } @@ -393,7 +392,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) if (width) { if (ic != EOF) - ungetc(ic, stream); + unget(ic); nrchars--; } break; @@ -411,7 +410,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) *str++ = (char)ic; if (--width) { - ic = getc(stream); + ic = get(); nrchars++; } } @@ -421,7 +420,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) if (width) { if (ic != EOF) - ungetc(ic, stream); + unget(ic); nrchars--; } break; @@ -468,7 +467,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) if (!*format || !(Xtable[ic] ^ reverse)) { if (ic != EOF) - ungetc(ic, stream); + unget(ic); return done; } @@ -481,7 +480,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) *str++ = (char)ic; if (--width) { - ic = getc(stream); + ic = get(); nrchars++; } } while (width && ic != EOF && (Xtable[ic] ^ reverse)); @@ -489,7 +488,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) if (width) { if (ic != EOF) - ungetc(ic, stream); + unget(ic); nrchars--; } if (!(flags & FL_NOASSIGN)) @@ -508,7 +507,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) if (!width) return done; - str = f_collect(ic, stream, width); + str = f_collect(ic, width, get, unget); if (str < inp_buf || (str == inp_buf diff --git a/lang/cem/libcc.ansi/sys/stdio/fclose.c b/lang/cem/libcc.ansi/sys/stdio/fclose.c index 9a56b4cfe..2410220be 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fclose.c +++ b/lang/cem/libcc.ansi/sys/stdio/fclose.c @@ -8,7 +8,7 @@ #include #include "loc_incl.h" -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE int fclose(FILE* fp) { diff --git a/lang/cem/libcc.ansi/sys/stdio/fdopen.c b/lang/cem/libcc.ansi/sys/stdio/fdopen.c index 084d39c14..20fabd5fb 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fdopen.c +++ b/lang/cem/libcc.ansi/sys/stdio/fdopen.c @@ -7,7 +7,7 @@ #include #include "../stdio/loc_incl.h" -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE FILE* fdopen(int fd, const char* mode) { diff --git a/lang/cem/libcc.ansi/sys/stdio/fflush.c b/lang/cem/libcc.ansi/sys/stdio/fflush.c index f0f53bb25..f38be1bd1 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fflush.c +++ b/lang/cem/libcc.ansi/sys/stdio/fflush.c @@ -8,7 +8,7 @@ #include #include "loc_incl.h" -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE int fflush(FILE* stream) { diff --git a/lang/cem/libcc.ansi/sys/stdio/fileno.c b/lang/cem/libcc.ansi/sys/stdio/fileno.c index e42608845..36e2b8bb9 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fileno.c +++ b/lang/cem/libcc.ansi/sys/stdio/fileno.c @@ -5,7 +5,7 @@ #include -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE int(fileno)(FILE* stream) { diff --git a/lang/cem/libcc.ansi/sys/stdio/fillbuf.c b/lang/cem/libcc.ansi/sys/stdio/fillbuf.c index 75187edac..019d138fc 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fillbuf.c +++ b/lang/cem/libcc.ansi/sys/stdio/fillbuf.c @@ -8,7 +8,7 @@ #include #include "loc_incl.h" -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE int __fillbuf(register FILE* stream) { diff --git a/lang/cem/libcc.ansi/sys/stdio/flushbuf.c b/lang/cem/libcc.ansi/sys/stdio/flushbuf.c index 81325d3a6..aba0a7c4c 100644 --- a/lang/cem/libcc.ansi/sys/stdio/flushbuf.c +++ b/lang/cem/libcc.ansi/sys/stdio/flushbuf.c @@ -8,7 +8,7 @@ #include #include "loc_incl.h" -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE static int do_write(int d, char* buf, int nbytes) diff --git a/lang/cem/libcc.ansi/sys/stdio/fopen.c b/lang/cem/libcc.ansi/sys/stdio/fopen.c index ce8c5634e..24e1537b9 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fopen.c +++ b/lang/cem/libcc.ansi/sys/stdio/fopen.c @@ -10,7 +10,7 @@ #include #include "loc_incl.h" -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE #define PMODE 0666 diff --git a/lang/cem/libcc.ansi/sys/stdio/fprintf.c b/lang/cem/libcc.ansi/sys/stdio/fprintf.c index 3085bf96a..9db8b74ee 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fprintf.c +++ b/lang/cem/libcc.ansi/sys/stdio/fprintf.c @@ -15,9 +15,7 @@ int fprintf(FILE* stream, const char* format, ...) int retval; va_start(ap, format); - - retval = _doprnt(format, ap, stream); - + retval = vfprintf(stream, format, ap); va_end(ap); return retval; diff --git a/lang/cem/libcc.ansi/sys/stdio/freopen.c b/lang/cem/libcc.ansi/sys/stdio/freopen.c index 255e04cb6..d4bb4abf8 100644 --- a/lang/cem/libcc.ansi/sys/stdio/freopen.c +++ b/lang/cem/libcc.ansi/sys/stdio/freopen.c @@ -9,7 +9,7 @@ #include #include "loc_incl.h" -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE #define PMODE 0666 diff --git a/lang/cem/libcc.ansi/sys/stdio/fscanf.c b/lang/cem/libcc.ansi/sys/stdio/fscanf.c index b06d47253..8c006c85c 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fscanf.c +++ b/lang/cem/libcc.ansi/sys/stdio/fscanf.c @@ -15,9 +15,7 @@ int fscanf(FILE* stream, const char* format, ...) int retval; va_start(ap, format); - - retval = _doscan(stream, format, ap); - + retval = vfscanf(stream, format, ap); va_end(ap); return retval; diff --git a/lang/cem/libcc.ansi/sys/stdio/fseek.c b/lang/cem/libcc.ansi/sys/stdio/fseek.c index c1ecd5650..5b87a9b30 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fseek.c +++ b/lang/cem/libcc.ansi/sys/stdio/fseek.c @@ -8,7 +8,7 @@ #include #include "loc_incl.h" -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE int fseek(FILE* stream, long int offset, int whence) { diff --git a/lang/cem/libcc.ansi/sys/stdio/ftell.c b/lang/cem/libcc.ansi/sys/stdio/ftell.c index 8053a1de2..4728b201b 100644 --- a/lang/cem/libcc.ansi/sys/stdio/ftell.c +++ b/lang/cem/libcc.ansi/sys/stdio/ftell.c @@ -8,7 +8,7 @@ #include #include "loc_incl.h" -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE long ftell(FILE* stream) { diff --git a/lang/cem/libcc.ansi/sys/stdio/loc_incl.h b/lang/cem/libcc.ansi/sys/stdio/loc_incl.h index b30d3272a..4d21923a2 100644 --- a/lang/cem/libcc.ansi/sys/stdio/loc_incl.h +++ b/lang/cem/libcc.ansi/sys/stdio/loc_incl.h @@ -10,8 +10,8 @@ #define io_testflag(p,x) ((p)->_flags & (x)) #include -int _doprnt(const char *format, va_list ap, FILE *stream); -int _doscan(FILE * stream, const char *format, va_list ap); +int _doprnt(const char *format, va_list ap, void (*put)(int c)); +int _doscan(const char *format, va_list ap, int (*get)(void), void (*unget)(int c)); char *_i_compute(unsigned long val, int base, char *s, int nrdigits); char *_f_print(va_list *ap, int flags, char *s, char c, int precision); diff --git a/lang/cem/libcc.ansi/sys/stdio/printf.c b/lang/cem/libcc.ansi/sys/stdio/printf.c index 6b118c859..2042983e7 100644 --- a/lang/cem/libcc.ansi/sys/stdio/printf.c +++ b/lang/cem/libcc.ansi/sys/stdio/printf.c @@ -15,9 +15,7 @@ int printf(const char* format, ...) int retval; va_start(ap, format); - - retval = _doprnt(format, ap, stdout); - + retval = vfprintf(stdout, format, ap); va_end(ap); return retval; diff --git a/lang/cem/libcc.ansi/sys/stdio/scanf.c b/lang/cem/libcc.ansi/sys/stdio/scanf.c index d52788084..3fb9875fc 100644 --- a/lang/cem/libcc.ansi/sys/stdio/scanf.c +++ b/lang/cem/libcc.ansi/sys/stdio/scanf.c @@ -15,9 +15,7 @@ int scanf(const char* format, ...) int retval; va_start(ap, format); - - retval = _doscan(stdin, format, ap); - + retval = vfscanf(stdin, format, ap); va_end(ap); return retval; diff --git a/lang/cem/libcc.ansi/sys/stdio/setbuf.c b/lang/cem/libcc.ansi/sys/stdio/setbuf.c index 5ac3e8ece..866b2516d 100644 --- a/lang/cem/libcc.ansi/sys/stdio/setbuf.c +++ b/lang/cem/libcc.ansi/sys/stdio/setbuf.c @@ -6,7 +6,7 @@ #include #include "loc_incl.h" -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE void setbuf(register FILE* stream, char* buf) { diff --git a/lang/cem/libcc.ansi/sys/stdio/setvbuf.c b/lang/cem/libcc.ansi/sys/stdio/setvbuf.c index 1dfc6a0be..af203ef51 100644 --- a/lang/cem/libcc.ansi/sys/stdio/setvbuf.c +++ b/lang/cem/libcc.ansi/sys/stdio/setvbuf.c @@ -7,7 +7,7 @@ #include #include "loc_incl.h" -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE int setvbuf(register FILE* stream, char* buf, int mode, size_t size) { diff --git a/lang/cem/libcc.ansi/sys/stdio/snprintf.c b/lang/cem/libcc.ansi/sys/stdio/snprintf.c index 4ee372faa..99128e3d7 100644 --- a/lang/cem/libcc.ansi/sys/stdio/snprintf.c +++ b/lang/cem/libcc.ansi/sys/stdio/snprintf.c @@ -9,22 +9,29 @@ #if ACKCONF_WANT_STDIO +static char* output_buffer; +static size_t output_buffer_len; + +static void snprintf_putc(int c) +{ + if (output_buffer_len) + { + *output_buffer++ = c; + output_buffer_len--; + } +} + int snprintf(char* s, size_t len, const char* format, ...) { va_list ap; int retval; - FILE tmp_stream; va_start(ap, format); - tmp_stream._fd = -1; - tmp_stream._flags = _IOWRITE + _IONBF + _IOWRITING; - tmp_stream._buf = (unsigned char*)s; - tmp_stream._ptr = (unsigned char*)s; - tmp_stream._count = len; - - retval = _doprnt(format, ap, &tmp_stream); - putc('\0', &tmp_stream); + output_buffer = s; + output_buffer_len = len; + retval = _doprnt(format, ap, snprintf_putc); + snprintf_putc('\0'); va_end(ap); diff --git a/lang/cem/libcc.ansi/sys/stdio/sprintf.c b/lang/cem/libcc.ansi/sys/stdio/sprintf.c index 3a116c0f4..e57d63ac1 100644 --- a/lang/cem/libcc.ansi/sys/stdio/sprintf.c +++ b/lang/cem/libcc.ansi/sys/stdio/sprintf.c @@ -13,19 +13,9 @@ int sprintf(char* s, const char* format, ...) { va_list ap; int retval; - FILE tmp_stream; va_start(ap, format); - - tmp_stream._fd = -1; - tmp_stream._flags = _IOWRITE + _IONBF + _IOWRITING; - tmp_stream._buf = (unsigned char*)s; - tmp_stream._ptr = (unsigned char*)s; - tmp_stream._count = 32767; - - retval = _doprnt(format, ap, &tmp_stream); - putc('\0', &tmp_stream); - + retval = vsnprintf(s, 32767, format, ap); va_end(ap); return retval; diff --git a/lang/cem/libcc.ansi/sys/stdio/sscanf.c b/lang/cem/libcc.ansi/sys/stdio/sscanf.c index bd39100bd..76e96aa7b 100644 --- a/lang/cem/libcc.ansi/sys/stdio/sscanf.c +++ b/lang/cem/libcc.ansi/sys/stdio/sscanf.c @@ -10,21 +10,32 @@ #if ACKCONF_WANT_STDIO +static const char* input_buffer; + +static int sscanf_getc(void) +{ + char c = *input_buffer; + if (c == 0) + return EOF; + input_buffer++; + return c; +} + +static void sscanf_ungetc(int c) +{ + /* sscanf always ungets the last character read. */ + input_buffer--; +} + int sscanf(const char* s, const char* format, ...) { va_list ap; int retval; - FILE tmp_stream; va_start(ap, format); - tmp_stream._fd = -1; - tmp_stream._flags = _IOREAD + _IONBF + _IOREADING; - tmp_stream._buf = (unsigned char*)s; - tmp_stream._ptr = (unsigned char*)s; - tmp_stream._count = strlen(s); - - retval = _doscan(&tmp_stream, format, ap); + input_buffer = s; + retval = _doscan(format, ap, sscanf_getc, sscanf_ungetc); va_end(ap); diff --git a/lang/cem/libcc.ansi/sys/stdio/tmpfile.c b/lang/cem/libcc.ansi/sys/stdio/tmpfile.c index e50fd0d35..384007aaa 100644 --- a/lang/cem/libcc.ansi/sys/stdio/tmpfile.c +++ b/lang/cem/libcc.ansi/sys/stdio/tmpfile.c @@ -13,7 +13,7 @@ FILE* tmpfile(void) { - static char name_buffer[L_tmpnam] = "/tmp/tmp."; + static char name_buffer[L_tmpnam] = ACK_TMP_PREFIX; static char* name = NULL; FILE* file; diff --git a/lang/cem/libcc.ansi/sys/stdio/tmpnam.c b/lang/cem/libcc.ansi/sys/stdio/tmpnam.c index 89fb9a4e3..e67276545 100644 --- a/lang/cem/libcc.ansi/sys/stdio/tmpnam.c +++ b/lang/cem/libcc.ansi/sys/stdio/tmpnam.c @@ -13,7 +13,7 @@ char* tmpnam(char* s) { - static char name_buffer[L_tmpnam] = "/tmp/tmp."; + static char name_buffer[L_tmpnam] = ACK_TMP_PREFIX; static unsigned long count = 0; static char* name = NULL; diff --git a/lang/cem/libcc.ansi/sys/stdio/ungetc.c b/lang/cem/libcc.ansi/sys/stdio/ungetc.c index a53cc1cf9..6097e5104 100644 --- a/lang/cem/libcc.ansi/sys/stdio/ungetc.c +++ b/lang/cem/libcc.ansi/sys/stdio/ungetc.c @@ -6,7 +6,7 @@ #include #include "loc_incl.h" -#if ACKCONF_WANT_STDIO +#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE int ungetc(int ch, FILE* stream) { diff --git a/lang/cem/libcc.ansi/sys/stdio/vfprintf.c b/lang/cem/libcc.ansi/sys/stdio/vfprintf.c index 02b473dd6..8f7008aae 100644 --- a/lang/cem/libcc.ansi/sys/stdio/vfprintf.c +++ b/lang/cem/libcc.ansi/sys/stdio/vfprintf.c @@ -9,9 +9,17 @@ #if ACKCONF_WANT_STDIO +static FILE* vfprintf_stream; + +static void vfprintf_putc(int c) +{ + putc(c, vfprintf_stream); +} + int vfprintf(FILE* stream, const char* format, va_list arg) { - return _doprnt(format, arg, stream); + vfprintf_stream = stream; + return _doprnt(format, arg, vfprintf_putc); } #endif diff --git a/lang/cem/libcc.ansi/sys/stdio/vfscanf.c b/lang/cem/libcc.ansi/sys/stdio/vfscanf.c new file mode 100644 index 000000000..9411b65c6 --- /dev/null +++ b/lang/cem/libcc.ansi/sys/stdio/vfscanf.c @@ -0,0 +1,30 @@ +/* + * vfscanf.c - read formatted input from stream + */ +/* $Id$ */ + +#include +#include +#include "loc_incl.h" + +#if ACKCONF_WANT_STDIO + +static FILE* vfscanf_stream; + +static int vfscanf_getc(void) +{ + return getc(vfscanf_stream); +} + +static void vfscanf_ungetc(int c) +{ + ungetc(c, vfscanf_stream); +} + +int vfscanf(FILE* stream, const char* format, va_list ap) +{ + vfscanf_stream = stream; + return _doscan(format, ap, vfscanf_getc, vfscanf_ungetc); +} + +#endif diff --git a/lang/cem/libcc.ansi/sys/stdio/vprintf.c b/lang/cem/libcc.ansi/sys/stdio/vprintf.c index 5cc6b837f..192601cc8 100644 --- a/lang/cem/libcc.ansi/sys/stdio/vprintf.c +++ b/lang/cem/libcc.ansi/sys/stdio/vprintf.c @@ -11,7 +11,7 @@ int vprintf(const char* format, va_list arg) { - return _doprnt(format, arg, stdout); + return vfprintf(stdout, format, arg); } #endif diff --git a/lang/cem/libcc.ansi/sys/stdio/vsnprintf.c b/lang/cem/libcc.ansi/sys/stdio/vsnprintf.c index d973b8066..94348d70c 100644 --- a/lang/cem/libcc.ansi/sys/stdio/vsnprintf.c +++ b/lang/cem/libcc.ansi/sys/stdio/vsnprintf.c @@ -9,19 +9,26 @@ #if ACKCONF_WANT_STDIO -int vsnprintf(char* s, size_t len, const char* format, va_list arg) +static char* output_buffer; +static size_t output_buffer_len; + +static void snprintf_putc(int c) +{ + if (output_buffer_len) + { + *output_buffer++ = c; + output_buffer_len--; + } +} + +int vsnprintf(char* s, size_t len, const char* format, va_list ap) { int retval; - FILE tmp_stream; - tmp_stream._fd = -1; - tmp_stream._flags = _IOWRITE + _IONBF + _IOWRITING; - tmp_stream._buf = (unsigned char*)s; - tmp_stream._ptr = (unsigned char*)s; - tmp_stream._count = len; - - retval = _doprnt(format, arg, &tmp_stream); - putc('\0', &tmp_stream); + output_buffer = s; + output_buffer_len = len; + retval = _doprnt(format, ap, snprintf_putc); + snprintf_putc('\0'); return retval; } diff --git a/lang/cem/libcc.ansi/sys/stdio/vsprintf.c b/lang/cem/libcc.ansi/sys/stdio/vsprintf.c index 00065bec0..81147591f 100644 --- a/lang/cem/libcc.ansi/sys/stdio/vsprintf.c +++ b/lang/cem/libcc.ansi/sys/stdio/vsprintf.c @@ -9,21 +9,9 @@ #if ACKCONF_WANT_STDIO -int vsprintf(char* s, const char* format, va_list arg) +int vsprintf(char* s, const char* format, va_list ap) { - int retval; - FILE tmp_stream; - - tmp_stream._fd = -1; - tmp_stream._flags = _IOWRITE + _IONBF + _IOWRITING; - tmp_stream._buf = (unsigned char*)s; - tmp_stream._ptr = (unsigned char*)s; - tmp_stream._count = 32767; - - retval = _doprnt(format, arg, &tmp_stream); - putc('\0', &tmp_stream); - - return retval; + return vsnprintf(s, 32767, format, ap); } #endif diff --git a/plat/cpm/include/ack/file.h b/plat/cpm/include/ack/file.h new file mode 100644 index 000000000..8e7393cdc --- /dev/null +++ b/plat/cpm/include/ack/file.h @@ -0,0 +1,22 @@ +#ifndef ACK_FILE_H +#define ACK_FILE_H + +/* CP/M custom FILE* implementation. */ + +#define L_tmpnam 16 /* 0a:12345678.abc */ +#define ACK_TMP_PREFIX "0a:tmp" +#define TMP_MAX 999 + +#include + +struct FILE +{ + uint8_t user; + FCB fcb; + char buffer[128]; +}; + +#define FOPEN_MAX 8 +extern FILE* __files[FOPEN_MAX]; + +#endif diff --git a/plat/cpm/include/ack/plat.h b/plat/cpm/include/ack/plat.h index 321dadf18..6e1bac6ae 100644 --- a/plat/cpm/include/ack/plat.h +++ b/plat/cpm/include/ack/plat.h @@ -11,4 +11,12 @@ #define ACKCONF_WANT_EMULATED_TIME 0 +/* CP/M's underlying file abstraction is weird and doesn't map well onto + * file descriptors. Disable the standard FILE* mechanism in favour of our + * own. + */ + +#define ACKCONF_WANT_EMULATED_FILE 0 +#define ACKCONF_WANT_EMULATED_POPEN 0 + #endif diff --git a/plat/cpm/include/build.lua b/plat/cpm/include/build.lua index 9820e3e09..ea35db386 100644 --- a/plat/cpm/include/build.lua +++ b/plat/cpm/include/build.lua @@ -9,6 +9,7 @@ local function addheader(h) end addheader("ack/plat.h") +addheader("ack/file.h") addheader("sys/types.h") addheader("cpm.h") From 1387c8713bc85333d4a30fe63a1078e78d9d02e5 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 15 Jun 2019 13:53:20 +0200 Subject: [PATCH 2/9] Now that printf and scanf contain no FILE*-specific code, we can move them into core (and split them up). --- lang/cem/libcc.ansi/build.lua | 3 +- .../{sys/stdio => core/printf}/doprnt.c | 30 ++++---- .../stdio/loc_incl.h => core/printf/doprnt.h} | 40 ++++------ .../{sys/stdio => core/printf}/fltpr.c | 2 +- .../{sys/stdio => core/printf}/fprintf.c | 1 - .../{sys/stdio => core/printf}/icompute.c | 2 +- .../{sys/stdio => core/printf}/printf.c | 1 - lang/cem/libcc.ansi/core/printf/snprintf.c | 23 ++++++ .../{sys/stdio => core/printf}/sprintf.c | 1 - .../{sys/stdio => core/printf}/vfprintf.c | 8 +- .../{sys/stdio => core/printf}/vprintf.c | 1 - .../{sys/stdio => core/printf}/vsnprintf.c | 8 +- .../{sys/stdio => core/printf}/vsprintf.c | 1 - .../{sys/stdio => core/scanf}/doscan.c | 77 ++++++++++--------- lang/cem/libcc.ansi/core/scanf/doscan.h | 23 ++++++ .../{sys/stdio => core/scanf}/fscanf.c | 1 - .../{sys/stdio => core/scanf}/scanf.c | 1 - .../{sys/stdio => core/scanf}/sscanf.c | 6 +- .../{sys/stdio => core/scanf}/vfscanf.c | 6 +- lang/cem/libcc.ansi/headers/ack/emufile.h | 3 + lang/cem/libcc.ansi/headers/stdio.h | 3 + lang/cem/libcc.ansi/sys/stdio/fclose.c | 1 - lang/cem/libcc.ansi/sys/stdio/fdopen.c | 1 - lang/cem/libcc.ansi/sys/stdio/fflush.c | 1 - lang/cem/libcc.ansi/sys/stdio/fillbuf.c | 1 - lang/cem/libcc.ansi/sys/stdio/flushbuf.c | 1 - lang/cem/libcc.ansi/sys/stdio/fopen.c | 1 - lang/cem/libcc.ansi/sys/stdio/freopen.c | 1 - lang/cem/libcc.ansi/sys/stdio/fseek.c | 1 - lang/cem/libcc.ansi/sys/stdio/ftell.c | 1 - lang/cem/libcc.ansi/sys/stdio/setbuf.c | 1 - lang/cem/libcc.ansi/sys/stdio/setvbuf.c | 1 - lang/cem/libcc.ansi/sys/stdio/snprintf.c | 41 ---------- lang/cem/libcc.ansi/sys/stdio/tmpfile.c | 1 - lang/cem/libcc.ansi/sys/stdio/tmpnam.c | 1 - lang/cem/libcc.ansi/sys/stdio/ungetc.c | 1 - 36 files changed, 141 insertions(+), 155 deletions(-) rename lang/cem/libcc.ansi/{sys/stdio => core/printf}/doprnt.c (94%) rename lang/cem/libcc.ansi/{sys/stdio/loc_incl.h => core/printf/doprnt.h} (57%) rename lang/cem/libcc.ansi/{sys/stdio => core/printf}/fltpr.c (99%) rename lang/cem/libcc.ansi/{sys/stdio => core/printf}/fprintf.c (93%) rename lang/cem/libcc.ansi/{sys/stdio => core/printf}/icompute.c (94%) rename lang/cem/libcc.ansi/{sys/stdio => core/printf}/printf.c (93%) create mode 100644 lang/cem/libcc.ansi/core/printf/snprintf.c rename lang/cem/libcc.ansi/{sys/stdio => core/printf}/sprintf.c (93%) rename lang/cem/libcc.ansi/{sys/stdio => core/printf}/vfprintf.c (66%) rename lang/cem/libcc.ansi/{sys/stdio => core/printf}/vprintf.c (92%) rename lang/cem/libcc.ansi/{sys/stdio => core/printf}/vsnprintf.c (79%) rename lang/cem/libcc.ansi/{sys/stdio => core/printf}/vsprintf.c (92%) rename lang/cem/libcc.ansi/{sys/stdio => core/scanf}/doscan.c (90%) create mode 100644 lang/cem/libcc.ansi/core/scanf/doscan.h rename lang/cem/libcc.ansi/{sys/stdio => core/scanf}/fscanf.c (93%) rename lang/cem/libcc.ansi/{sys/stdio => core/scanf}/scanf.c (93%) rename lang/cem/libcc.ansi/{sys/stdio => core/scanf}/sscanf.c (83%) rename lang/cem/libcc.ansi/{sys/stdio => core/scanf}/vfscanf.c (77%) delete mode 100644 lang/cem/libcc.ansi/sys/stdio/snprintf.c diff --git a/lang/cem/libcc.ansi/build.lua b/lang/cem/libcc.ansi/build.lua index ee1049d66..4cb90e05b 100644 --- a/lang/cem/libcc.ansi/build.lua +++ b/lang/cem/libcc.ansi/build.lua @@ -39,6 +39,8 @@ for _, plat in ipairs(vars.plats) do "./core/math/*.c", "./core/math/*.e", "./core/misc/*.c", + "./core/printf/*.c", + "./core/scanf/*.c", "./core/setjmp/*.c", "./core/setjmp/*.e", "./core/stdlib/*.c", @@ -57,7 +59,6 @@ for _, plat in ipairs(vars.plats) do "./core/stdlib/ext_fmt.h", "./core/time/loc_time.h", "./sys/malloc/malloc.h", - "./sys/stdio/loc_incl.h", }, vars = { plat = plat } } diff --git a/lang/cem/libcc.ansi/sys/stdio/doprnt.c b/lang/cem/libcc.ansi/core/printf/doprnt.c similarity index 94% rename from lang/cem/libcc.ansi/sys/stdio/doprnt.c rename to lang/cem/libcc.ansi/core/printf/doprnt.c index 8c97fb5a4..3eae73f0c 100644 --- a/lang/cem/libcc.ansi/sys/stdio/doprnt.c +++ b/lang/cem/libcc.ansi/core/printf/doprnt.c @@ -7,7 +7,7 @@ #include #include #include -#include "loc_incl.h" +#include "doprnt.h" #if ACKCONF_WANT_STDIO @@ -44,15 +44,13 @@ gnum(register const char* f, int* ip, va_list* app) #define set_pointer(flags) /* compilation might continue */ #endif +int (*_doprnt_put)(int c); + #define PUTC(c) \ do \ { \ - int i = putc(c, stream); \ - if (i == EOF) \ - { \ - if (ferror(stream)) \ - return -1; \ - } \ + if (_doprnt_put(c)) \ + return -1; \ } while (0) /* print an ordinal number */ @@ -157,7 +155,7 @@ o_print(va_list* ap, int flags, char* s, char c, int precision, int is_signed) return s; } -int _doprnt(register const char* fmt, va_list ap, void (*put)(int)) +int _doprnt(register const char* fmt, va_list ap) { register char* s; register int j; @@ -176,7 +174,7 @@ int _doprnt(register const char* fmt, va_list ap, void (*put)(int)) PUTC('\r'); } #endif - put(c); + PUTC(c); nrchars++; continue; } @@ -263,7 +261,7 @@ int _doprnt(register const char* fmt, va_list ap, void (*put)(int)) nrchars++; } #endif - put(c); + PUTC(c); nrchars++; continue; case 'n': @@ -366,32 +364,32 @@ int _doprnt(register const char* fmt, va_list ap, void (*put)(int)) { j--; nrchars++; - put(*s1++); + PUTC(*s1++); } else { j -= 2; nrchars += 2; - put(*s1++); - put(*s1++); + PUTC(*s1++); + PUTC(*s1++); } } do { - put(zfill); + PUTC(zfill); } while (--i); } nrchars += j; while (--j >= 0) { - put(*s1++); + PUTC(*s1++); } if (i > 0) nrchars += i; while (--i >= 0) - put(zfill); + PUTC(zfill); } return nrchars; } diff --git a/lang/cem/libcc.ansi/sys/stdio/loc_incl.h b/lang/cem/libcc.ansi/core/printf/doprnt.h similarity index 57% rename from lang/cem/libcc.ansi/sys/stdio/loc_incl.h rename to lang/cem/libcc.ansi/core/printf/doprnt.h index 4d21923a2..efb056d86 100644 --- a/lang/cem/libcc.ansi/sys/stdio/loc_incl.h +++ b/lang/cem/libcc.ansi/core/printf/doprnt.h @@ -1,29 +1,5 @@ -/* - * loc_incl.h - local include file for stdio library - */ -/* $Id$ */ - -#include -#include - -#define fileno(p) ((p)->_fd) -#define io_testflag(p,x) ((p)->_flags & (x)) - -#include -int _doprnt(const char *format, va_list ap, void (*put)(int c)); -int _doscan(const char *format, va_list ap, int (*get)(void), void (*unget)(int c)); -char *_i_compute(unsigned long val, int base, char *s, int nrdigits); -char *_f_print(va_list *ap, int flags, char *s, char c, int precision); - -extern void __register_stdio_cleanup(void); - -FILE *popen(const char *command, const char *type); -FILE *fdopen(int fd, const char *mode); - -#if ACKCONF_WANT_STDIO_FLOAT -char *_ecvt(long double value, int ndigit, int *decpt, int *sign); -char *_fcvt(long double value, int ndigit, int *decpt, int *sign); -#endif +#ifndef DOPRNT_H +#define DOPRNT_H #define FL_LJUST 0x0001 /* left-justify field */ #define FL_SIGN 0x0002 /* sign in signed conversions */ @@ -38,3 +14,15 @@ char *_fcvt(long double value, int ndigit, int *decpt, int *sign); #define FL_SIGNEDCONV 0x0400 /* may contain a sign */ #define FL_NOASSIGN 0x0800 /* do not assign (in scanf) */ #define FL_NOMORE 0x1000 /* all flags collected */ + +extern int (*_doprnt_put)(int c); + +extern int _doprnt(register const char* fmt, va_list ap); +extern char* _f_print(va_list* ap, int flags, char* s, char c, int precision); + +#if ACKCONF_WANT_STDIO_FLOAT +char *_ecvt(long double value, int ndigit, int *decpt, int *sign); +char *_fcvt(long double value, int ndigit, int *decpt, int *sign); +#endif + +#endif diff --git a/lang/cem/libcc.ansi/sys/stdio/fltpr.c b/lang/cem/libcc.ansi/core/printf/fltpr.c similarity index 99% rename from lang/cem/libcc.ansi/sys/stdio/fltpr.c rename to lang/cem/libcc.ansi/core/printf/fltpr.c index 3fdc80852..7b9f28a69 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fltpr.c +++ b/lang/cem/libcc.ansi/core/printf/fltpr.c @@ -5,7 +5,7 @@ #include #include -#include "loc_incl.h" +#include "doprnt.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_STDIO_FLOAT diff --git a/lang/cem/libcc.ansi/sys/stdio/fprintf.c b/lang/cem/libcc.ansi/core/printf/fprintf.c similarity index 93% rename from lang/cem/libcc.ansi/sys/stdio/fprintf.c rename to lang/cem/libcc.ansi/core/printf/fprintf.c index 9db8b74ee..3be0ea66b 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fprintf.c +++ b/lang/cem/libcc.ansi/core/printf/fprintf.c @@ -5,7 +5,6 @@ #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO diff --git a/lang/cem/libcc.ansi/sys/stdio/icompute.c b/lang/cem/libcc.ansi/core/printf/icompute.c similarity index 94% rename from lang/cem/libcc.ansi/sys/stdio/icompute.c rename to lang/cem/libcc.ansi/core/printf/icompute.c index 9b48d51a4..7f497d107 100644 --- a/lang/cem/libcc.ansi/sys/stdio/icompute.c +++ b/lang/cem/libcc.ansi/core/printf/icompute.c @@ -3,7 +3,7 @@ */ /* $Id$ */ -#include "loc_incl.h" +#include #if ACKCONF_WANT_STDIO diff --git a/lang/cem/libcc.ansi/sys/stdio/printf.c b/lang/cem/libcc.ansi/core/printf/printf.c similarity index 93% rename from lang/cem/libcc.ansi/sys/stdio/printf.c rename to lang/cem/libcc.ansi/core/printf/printf.c index 2042983e7..7f282456a 100644 --- a/lang/cem/libcc.ansi/sys/stdio/printf.c +++ b/lang/cem/libcc.ansi/core/printf/printf.c @@ -5,7 +5,6 @@ #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO diff --git a/lang/cem/libcc.ansi/core/printf/snprintf.c b/lang/cem/libcc.ansi/core/printf/snprintf.c new file mode 100644 index 000000000..5342785ab --- /dev/null +++ b/lang/cem/libcc.ansi/core/printf/snprintf.c @@ -0,0 +1,23 @@ +/* + * sprintf - print formatted output on an array + */ +/* $Id$ */ + +#include +#include + +#if ACKCONF_WANT_STDIO + +int snprintf(char* s, size_t len, const char* format, ...) +{ + va_list ap; + int retval; + + va_start(ap, format); + retval = vsnprintf(s, len, format, ap); + va_end(ap); + + return retval; +} + +#endif diff --git a/lang/cem/libcc.ansi/sys/stdio/sprintf.c b/lang/cem/libcc.ansi/core/printf/sprintf.c similarity index 93% rename from lang/cem/libcc.ansi/sys/stdio/sprintf.c rename to lang/cem/libcc.ansi/core/printf/sprintf.c index e57d63ac1..86e81e4a4 100644 --- a/lang/cem/libcc.ansi/sys/stdio/sprintf.c +++ b/lang/cem/libcc.ansi/core/printf/sprintf.c @@ -5,7 +5,6 @@ #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO diff --git a/lang/cem/libcc.ansi/sys/stdio/vfprintf.c b/lang/cem/libcc.ansi/core/printf/vfprintf.c similarity index 66% rename from lang/cem/libcc.ansi/sys/stdio/vfprintf.c rename to lang/cem/libcc.ansi/core/printf/vfprintf.c index 8f7008aae..7e665a22f 100644 --- a/lang/cem/libcc.ansi/sys/stdio/vfprintf.c +++ b/lang/cem/libcc.ansi/core/printf/vfprintf.c @@ -5,21 +5,23 @@ #include #include -#include "loc_incl.h" +#include "doprnt.h" #if ACKCONF_WANT_STDIO static FILE* vfprintf_stream; -static void vfprintf_putc(int c) +static int vfprintf_putc(int c) { putc(c, vfprintf_stream); + return ferror(vfprintf_stream); } int vfprintf(FILE* stream, const char* format, va_list arg) { vfprintf_stream = stream; - return _doprnt(format, arg, vfprintf_putc); + _doprnt_put = vfprintf_putc; + return _doprnt(format, arg); } #endif diff --git a/lang/cem/libcc.ansi/sys/stdio/vprintf.c b/lang/cem/libcc.ansi/core/printf/vprintf.c similarity index 92% rename from lang/cem/libcc.ansi/sys/stdio/vprintf.c rename to lang/cem/libcc.ansi/core/printf/vprintf.c index 192601cc8..999fdaa4d 100644 --- a/lang/cem/libcc.ansi/sys/stdio/vprintf.c +++ b/lang/cem/libcc.ansi/core/printf/vprintf.c @@ -5,7 +5,6 @@ #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO diff --git a/lang/cem/libcc.ansi/sys/stdio/vsnprintf.c b/lang/cem/libcc.ansi/core/printf/vsnprintf.c similarity index 79% rename from lang/cem/libcc.ansi/sys/stdio/vsnprintf.c rename to lang/cem/libcc.ansi/core/printf/vsnprintf.c index 94348d70c..af97b5351 100644 --- a/lang/cem/libcc.ansi/sys/stdio/vsnprintf.c +++ b/lang/cem/libcc.ansi/core/printf/vsnprintf.c @@ -5,20 +5,21 @@ #include #include -#include "loc_incl.h" +#include "doprnt.h" #if ACKCONF_WANT_STDIO static char* output_buffer; static size_t output_buffer_len; -static void snprintf_putc(int c) +static int snprintf_putc(int c) { if (output_buffer_len) { *output_buffer++ = c; output_buffer_len--; } + return 0; } int vsnprintf(char* s, size_t len, const char* format, va_list ap) @@ -27,7 +28,8 @@ int vsnprintf(char* s, size_t len, const char* format, va_list ap) output_buffer = s; output_buffer_len = len; - retval = _doprnt(format, ap, snprintf_putc); + _doprnt_put = snprintf_putc; + retval = _doprnt(format, ap); snprintf_putc('\0'); return retval; diff --git a/lang/cem/libcc.ansi/sys/stdio/vsprintf.c b/lang/cem/libcc.ansi/core/printf/vsprintf.c similarity index 92% rename from lang/cem/libcc.ansi/sys/stdio/vsprintf.c rename to lang/cem/libcc.ansi/core/printf/vsprintf.c index 81147591f..c8da509ab 100644 --- a/lang/cem/libcc.ansi/sys/stdio/vsprintf.c +++ b/lang/cem/libcc.ansi/core/printf/vsprintf.c @@ -5,7 +5,6 @@ #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO diff --git a/lang/cem/libcc.ansi/sys/stdio/doscan.c b/lang/cem/libcc.ansi/core/scanf/doscan.c similarity index 90% rename from lang/cem/libcc.ansi/sys/stdio/doscan.c rename to lang/cem/libcc.ansi/core/scanf/doscan.c index 45748427e..97cf777a2 100644 --- a/lang/cem/libcc.ansi/sys/stdio/doscan.c +++ b/lang/cem/libcc.ansi/core/scanf/doscan.c @@ -7,7 +7,7 @@ #include #include #include -#include "loc_incl.h" +#include "doscan.h" #if ACKCONF_WANT_STDIO @@ -26,14 +26,16 @@ static char Xtable[NR_CHARS]; static char inp_buf[NUMLEN]; +int (*_doscan_get)(void); +void (*_doscan_unget)(int c); + /* Collect a number of characters which constitite an ordinal number. * When the type is 'i', the base can be 8, 10, or 16, depending on the * first 1 or 2 characters. This means that the base must be adjusted * according to the format of the number. At the end of the function, base * is then set to 0, so strtol() will get the right argument. */ -static char* -o_collect(register int c, char type, int width, int* basep, int (*get)(void), void (*unget)(int c)) +static char* o_collect(register int c, char type, int width, int* basep) { register char* bufp = inp_buf; register int base; @@ -62,14 +64,14 @@ o_collect(register int c, char type, int width, int* basep, int (*get)(void), vo { *bufp++ = c; if (--width) - c = get(); + c = _doscan_get(); } if (width && c == '0' && base == 16) { *bufp++ = c; if (--width) - c = get(); + c = _doscan_get(); if (c != 'x' && c != 'X') { if (type == 'i') @@ -79,7 +81,7 @@ o_collect(register int c, char type, int width, int* basep, int (*get)(void), vo { *bufp++ = c; if (--width) - c = get(); + c = _doscan_get(); } } else if (type == 'i') @@ -94,14 +96,14 @@ o_collect(register int c, char type, int width, int* basep, int (*get)(void), vo { *bufp++ = c; if (--width) - c = get(); + c = _doscan_get(); } else break; } if (width && c != EOF) - unget(c); + _doscan_unget(c); if (type == 'i') base = 0; *basep = base; @@ -118,8 +120,7 @@ o_collect(register int c, char type, int width, int* basep, int (*get)(void), vo * not necessary, although the use of the width field can cause incomplete * numbers to be passed to strtod(). (e.g. 1.3e+) */ -static char* -f_collect(register int c, register int width, int (*get)(void), void (*unget)(int c)) +static char* f_collect(register int c, register int width) { register char* bufp = inp_buf; int digit_seen = 0; @@ -128,7 +129,7 @@ f_collect(register int c, register int width, int (*get)(void), void (*unget)(in { *bufp++ = c; if (--width) - c = get(); + c = _doscan_get(); } while (width && isdigit(c)) @@ -136,26 +137,26 @@ f_collect(register int c, register int width, int (*get)(void), void (*unget)(in digit_seen++; *bufp++ = c; if (--width) - c = get(); + c = _doscan_get(); } if (width && c == '.') { *bufp++ = c; if (--width) - c = get(); + c = _doscan_get(); while (width && isdigit(c)) { digit_seen++; *bufp++ = c; if (--width) - c = get(); + c = _doscan_get(); } } if (!digit_seen) { if (width && c != EOF) - unget(c); + _doscan_unget(c); return inp_buf - 1; } else @@ -165,30 +166,30 @@ f_collect(register int c, register int width, int (*get)(void), void (*unget)(in { *bufp++ = c; if (--width) - c = get(); + c = _doscan_get(); if (width && (c == '+' || c == '-')) { *bufp++ = c; if (--width) - c = get(); + c = _doscan_get(); } while (width && isdigit(c)) { digit_seen++; *bufp++ = c; if (--width) - c = get(); + c = _doscan_get(); } if (!digit_seen) { if (width && c != EOF) - unget(c); + _doscan_unget(c); return inp_buf - 1; } } if (width && c != EOF) - unget(c); + _doscan_unget(c); *bufp = '\0'; return bufp - 1; } @@ -198,7 +199,7 @@ f_collect(register int c, register int width, int (*get)(void), void (*unget)(in * the routine that does the scanning */ -int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int c)) +int _doscan(const char* format, va_list ap) { int done = 0; /* number of items done */ int nrchars = 0; /* number of characters read */ @@ -225,15 +226,15 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int { while (isspace(*format)) format++; /* skip whitespace */ - ic = get(); + ic = _doscan_get(); nrchars++; while (isspace(ic)) { - ic = get(); + ic = _doscan_get(); nrchars++; } if (ic != EOF) - unget(ic); + _doscan_unget(ic); nrchars--; } if (!*format) @@ -241,12 +242,12 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int if (*format != '%') { - ic = get(); + ic = _doscan_get(); nrchars++; if (ic != *format++) { if (ic != EOF) - unget(ic); + _doscan_unget(ic); nrchars--; break; /* error */ } @@ -255,7 +256,7 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int format++; if (*format == '%') { - ic = get(); + ic = _doscan_get(); nrchars++; if (ic == '%') { @@ -298,7 +299,7 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int { do { - ic = get(); + ic = _doscan_get(); nrchars++; } while (isspace(ic)); if (ic == EOF) @@ -306,7 +307,7 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int } else if (kind != 'n') { /* %c or %[ */ - ic = get(); + ic = _doscan_get(); if (ic == EOF) break; /* outer while */ nrchars++; @@ -343,7 +344,7 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int if (!width) return done; - str = o_collect(ic, kind, width, &base, get, unget); + str = o_collect(ic, kind, width, &base); if (str < inp_buf || (str == inp_buf && (*str == '-' @@ -384,7 +385,7 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int *str++ = (char)ic; if (--width) { - ic = get(); + ic = _doscan_get(); nrchars++; } } @@ -392,7 +393,7 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int if (width) { if (ic != EOF) - unget(ic); + _doscan_unget(ic); nrchars--; } break; @@ -410,7 +411,7 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int *str++ = (char)ic; if (--width) { - ic = get(); + ic = _doscan_get(); nrchars++; } } @@ -420,7 +421,7 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int if (width) { if (ic != EOF) - unget(ic); + _doscan_unget(ic); nrchars--; } break; @@ -467,7 +468,7 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int if (!*format || !(Xtable[ic] ^ reverse)) { if (ic != EOF) - unget(ic); + _doscan_unget(ic); return done; } @@ -480,7 +481,7 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int *str++ = (char)ic; if (--width) { - ic = get(); + ic = _doscan_get(); nrchars++; } } while (width && ic != EOF && (Xtable[ic] ^ reverse)); @@ -488,7 +489,7 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int if (width) { if (ic != EOF) - unget(ic); + _doscan_unget(ic); nrchars--; } if (!(flags & FL_NOASSIGN)) @@ -507,7 +508,7 @@ int _doscan(const char* format, va_list ap, int (*get)(void), void (*unget)(int if (!width) return done; - str = f_collect(ic, width, get, unget); + str = f_collect(ic, width); if (str < inp_buf || (str == inp_buf diff --git a/lang/cem/libcc.ansi/core/scanf/doscan.h b/lang/cem/libcc.ansi/core/scanf/doscan.h new file mode 100644 index 000000000..2502ea8e8 --- /dev/null +++ b/lang/cem/libcc.ansi/core/scanf/doscan.h @@ -0,0 +1,23 @@ +#ifndef DOSCAN_H +#define DOSCAN_H + +#define FL_LJUST 0x0001 /* left-justify field */ +#define FL_SIGN 0x0002 /* sign in signed conversions */ +#define FL_SPACE 0x0004 /* space in signed conversions */ +#define FL_ALT 0x0008 /* alternate form */ +#define FL_ZEROFILL 0x0010 /* fill with zero's */ +#define FL_SHORT 0x0020 /* optional h */ +#define FL_LONG 0x0040 /* optional l */ +#define FL_LONGDOUBLE 0x0080 /* optional L */ +#define FL_WIDTHSPEC 0x0100 /* field width is specified */ +#define FL_PRECSPEC 0x0200 /* precision is specified */ +#define FL_SIGNEDCONV 0x0400 /* may contain a sign */ +#define FL_NOASSIGN 0x0800 /* do not assign (in scanf) */ +#define FL_NOMORE 0x1000 /* all flags collected */ + +extern int (*_doscan_get)(void); +extern void (*_doscan_unget)(int c); + +extern int _doscan(const char* format, va_list ap); + +#endif diff --git a/lang/cem/libcc.ansi/sys/stdio/fscanf.c b/lang/cem/libcc.ansi/core/scanf/fscanf.c similarity index 93% rename from lang/cem/libcc.ansi/sys/stdio/fscanf.c rename to lang/cem/libcc.ansi/core/scanf/fscanf.c index 8c006c85c..21fd6c8ee 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fscanf.c +++ b/lang/cem/libcc.ansi/core/scanf/fscanf.c @@ -5,7 +5,6 @@ #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO diff --git a/lang/cem/libcc.ansi/sys/stdio/scanf.c b/lang/cem/libcc.ansi/core/scanf/scanf.c similarity index 93% rename from lang/cem/libcc.ansi/sys/stdio/scanf.c rename to lang/cem/libcc.ansi/core/scanf/scanf.c index 3fb9875fc..6796013cf 100644 --- a/lang/cem/libcc.ansi/sys/stdio/scanf.c +++ b/lang/cem/libcc.ansi/core/scanf/scanf.c @@ -5,7 +5,6 @@ #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO diff --git a/lang/cem/libcc.ansi/sys/stdio/sscanf.c b/lang/cem/libcc.ansi/core/scanf/sscanf.c similarity index 83% rename from lang/cem/libcc.ansi/sys/stdio/sscanf.c rename to lang/cem/libcc.ansi/core/scanf/sscanf.c index 76e96aa7b..eb972eeb2 100644 --- a/lang/cem/libcc.ansi/sys/stdio/sscanf.c +++ b/lang/cem/libcc.ansi/core/scanf/sscanf.c @@ -6,7 +6,7 @@ #include #include #include -#include "loc_incl.h" +#include "doscan.h" #if ACKCONF_WANT_STDIO @@ -35,7 +35,9 @@ int sscanf(const char* s, const char* format, ...) va_start(ap, format); input_buffer = s; - retval = _doscan(format, ap, sscanf_getc, sscanf_ungetc); + _doscan_get = sscanf_getc; + _doscan_unget = sscanf_ungetc; + retval = _doscan(format, ap); va_end(ap); diff --git a/lang/cem/libcc.ansi/sys/stdio/vfscanf.c b/lang/cem/libcc.ansi/core/scanf/vfscanf.c similarity index 77% rename from lang/cem/libcc.ansi/sys/stdio/vfscanf.c rename to lang/cem/libcc.ansi/core/scanf/vfscanf.c index 9411b65c6..c5a562049 100644 --- a/lang/cem/libcc.ansi/sys/stdio/vfscanf.c +++ b/lang/cem/libcc.ansi/core/scanf/vfscanf.c @@ -5,7 +5,7 @@ #include #include -#include "loc_incl.h" +#include "doscan.h" #if ACKCONF_WANT_STDIO @@ -24,7 +24,9 @@ static void vfscanf_ungetc(int c) int vfscanf(FILE* stream, const char* format, va_list ap) { vfscanf_stream = stream; - return _doscan(format, ap, vfscanf_getc, vfscanf_ungetc); + _doscan_get = vfscanf_getc; + _doscan_unget = vfscanf_ungetc; + return _doscan(format, ap); } #endif diff --git a/lang/cem/libcc.ansi/headers/ack/emufile.h b/lang/cem/libcc.ansi/headers/ack/emufile.h index 6e799b47b..3eeae2eae 100644 --- a/lang/cem/libcc.ansi/headers/ack/emufile.h +++ b/lang/cem/libcc.ansi/headers/ack/emufile.h @@ -56,4 +56,7 @@ extern int fileno(FILE *_stream); extern FILE* fdopen(int fildes, const char *type); #define fileno(stream) ((stream)->_fd) +#define io_testflag(p,x) ((p)->_flags & (x)) +extern void __register_stdio_cleanup(void); + #endif diff --git a/lang/cem/libcc.ansi/headers/stdio.h b/lang/cem/libcc.ansi/headers/stdio.h index 7988c397d..093258fe6 100644 --- a/lang/cem/libcc.ansi/headers/stdio.h +++ b/lang/cem/libcc.ansi/headers/stdio.h @@ -76,6 +76,9 @@ 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(). */ +extern char *_i_compute(unsigned long val, int base, char *s, int nrdigits); + #if ACKCONF_WANT_EMULATED_FILE #include #else diff --git a/lang/cem/libcc.ansi/sys/stdio/fclose.c b/lang/cem/libcc.ansi/sys/stdio/fclose.c index 2410220be..a805a6e84 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fclose.c +++ b/lang/cem/libcc.ansi/sys/stdio/fclose.c @@ -6,7 +6,6 @@ #include #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE diff --git a/lang/cem/libcc.ansi/sys/stdio/fdopen.c b/lang/cem/libcc.ansi/sys/stdio/fdopen.c index 20fabd5fb..aff7d248e 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fdopen.c +++ b/lang/cem/libcc.ansi/sys/stdio/fdopen.c @@ -5,7 +5,6 @@ #include #include -#include "../stdio/loc_incl.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE diff --git a/lang/cem/libcc.ansi/sys/stdio/fflush.c b/lang/cem/libcc.ansi/sys/stdio/fflush.c index f38be1bd1..7746ef0fb 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fflush.c +++ b/lang/cem/libcc.ansi/sys/stdio/fflush.c @@ -6,7 +6,6 @@ #include #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE diff --git a/lang/cem/libcc.ansi/sys/stdio/fillbuf.c b/lang/cem/libcc.ansi/sys/stdio/fillbuf.c index 019d138fc..09cc5cfc6 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fillbuf.c +++ b/lang/cem/libcc.ansi/sys/stdio/fillbuf.c @@ -6,7 +6,6 @@ #include #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE diff --git a/lang/cem/libcc.ansi/sys/stdio/flushbuf.c b/lang/cem/libcc.ansi/sys/stdio/flushbuf.c index aba0a7c4c..0cf271704 100644 --- a/lang/cem/libcc.ansi/sys/stdio/flushbuf.c +++ b/lang/cem/libcc.ansi/sys/stdio/flushbuf.c @@ -6,7 +6,6 @@ #include #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE diff --git a/lang/cem/libcc.ansi/sys/stdio/fopen.c b/lang/cem/libcc.ansi/sys/stdio/fopen.c index 24e1537b9..f2189ee8f 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fopen.c +++ b/lang/cem/libcc.ansi/sys/stdio/fopen.c @@ -8,7 +8,6 @@ #include #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE diff --git a/lang/cem/libcc.ansi/sys/stdio/freopen.c b/lang/cem/libcc.ansi/sys/stdio/freopen.c index d4bb4abf8..846208420 100644 --- a/lang/cem/libcc.ansi/sys/stdio/freopen.c +++ b/lang/cem/libcc.ansi/sys/stdio/freopen.c @@ -7,7 +7,6 @@ #include #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE diff --git a/lang/cem/libcc.ansi/sys/stdio/fseek.c b/lang/cem/libcc.ansi/sys/stdio/fseek.c index 5b87a9b30..4ab5c10e3 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fseek.c +++ b/lang/cem/libcc.ansi/sys/stdio/fseek.c @@ -6,7 +6,6 @@ #include #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE diff --git a/lang/cem/libcc.ansi/sys/stdio/ftell.c b/lang/cem/libcc.ansi/sys/stdio/ftell.c index 4728b201b..d69202bd3 100644 --- a/lang/cem/libcc.ansi/sys/stdio/ftell.c +++ b/lang/cem/libcc.ansi/sys/stdio/ftell.c @@ -6,7 +6,6 @@ #include #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE diff --git a/lang/cem/libcc.ansi/sys/stdio/setbuf.c b/lang/cem/libcc.ansi/sys/stdio/setbuf.c index 866b2516d..58a99ecad 100644 --- a/lang/cem/libcc.ansi/sys/stdio/setbuf.c +++ b/lang/cem/libcc.ansi/sys/stdio/setbuf.c @@ -4,7 +4,6 @@ /* $Id$ */ #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE diff --git a/lang/cem/libcc.ansi/sys/stdio/setvbuf.c b/lang/cem/libcc.ansi/sys/stdio/setvbuf.c index af203ef51..439d12dd4 100644 --- a/lang/cem/libcc.ansi/sys/stdio/setvbuf.c +++ b/lang/cem/libcc.ansi/sys/stdio/setvbuf.c @@ -5,7 +5,6 @@ #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE diff --git a/lang/cem/libcc.ansi/sys/stdio/snprintf.c b/lang/cem/libcc.ansi/sys/stdio/snprintf.c deleted file mode 100644 index 99128e3d7..000000000 --- a/lang/cem/libcc.ansi/sys/stdio/snprintf.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * sprintf - print formatted output on an array - */ -/* $Id$ */ - -#include -#include -#include "loc_incl.h" - -#if ACKCONF_WANT_STDIO - -static char* output_buffer; -static size_t output_buffer_len; - -static void snprintf_putc(int c) -{ - if (output_buffer_len) - { - *output_buffer++ = c; - output_buffer_len--; - } -} - -int snprintf(char* s, size_t len, const char* format, ...) -{ - va_list ap; - int retval; - - va_start(ap, format); - - output_buffer = s; - output_buffer_len = len; - retval = _doprnt(format, ap, snprintf_putc); - snprintf_putc('\0'); - - va_end(ap); - - return retval; -} - -#endif diff --git a/lang/cem/libcc.ansi/sys/stdio/tmpfile.c b/lang/cem/libcc.ansi/sys/stdio/tmpfile.c index 384007aaa..d6aa31825 100644 --- a/lang/cem/libcc.ansi/sys/stdio/tmpfile.c +++ b/lang/cem/libcc.ansi/sys/stdio/tmpfile.c @@ -7,7 +7,6 @@ #include #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO diff --git a/lang/cem/libcc.ansi/sys/stdio/tmpnam.c b/lang/cem/libcc.ansi/sys/stdio/tmpnam.c index e67276545..2f40ce716 100644 --- a/lang/cem/libcc.ansi/sys/stdio/tmpnam.c +++ b/lang/cem/libcc.ansi/sys/stdio/tmpnam.c @@ -7,7 +7,6 @@ #include #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO diff --git a/lang/cem/libcc.ansi/sys/stdio/ungetc.c b/lang/cem/libcc.ansi/sys/stdio/ungetc.c index 6097e5104..f00447e27 100644 --- a/lang/cem/libcc.ansi/sys/stdio/ungetc.c +++ b/lang/cem/libcc.ansi/sys/stdio/ungetc.c @@ -4,7 +4,6 @@ /* $Id$ */ #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE From 3131dc99153565a36a043af55876aa94b1b3baaf Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 15 Jun 2019 22:22:01 +0200 Subject: [PATCH 3/9] 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); } From 50dca8b954c623b100e62f62cad0a2ab9b70e608 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 16 Jun 2019 19:04:17 +0200 Subject: [PATCH 4/9] First at-least-slightly working version of the CP/M read/write stuff. Not as bad as I expected, but far too big. --- build.lua | 32 +++--- lang/cem/libcc.ansi/headers/ack/emufile.h | 2 + plat/cpm/descr | 1 + plat/cpm/include/ack/plat.h | 14 ++- plat/cpm/include/cpm.h | 18 ++-- plat/cpm/libsys/build.lua | 38 +++---- plat/cpm/libsys/close.c | 31 ++++-- plat/cpm/libsys/cpm_read_random_safe.c | 10 ++ plat/cpm/libsys/cpmsys.h | 22 ++++ plat/cpm/libsys/fcb.c | 70 +++++++++++++ plat/cpm/libsys/fclose.c | 20 ---- plat/cpm/libsys/fd.c | 19 ++++ 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/lseek.c | 28 ++++-- plat/cpm/libsys/open.c | 59 +++++++++-- plat/cpm/libsys/putc.c | 17 ---- plat/cpm/libsys/read.c | 94 +++++++++++++++-- plat/cpm/libsys/write.c | 117 ++++++++++++++++++---- 21 files changed, 464 insertions(+), 193 deletions(-) create mode 100644 plat/cpm/libsys/cpm_read_random_safe.c create mode 100644 plat/cpm/libsys/cpmsys.h delete mode 100644 plat/cpm/libsys/fclose.c create mode 100644 plat/cpm/libsys/fd.c delete mode 100644 plat/cpm/libsys/feof.c delete mode 100644 plat/cpm/libsys/ferror.c delete mode 100644 plat/cpm/libsys/fflush.c delete mode 100644 plat/cpm/libsys/getc.c delete mode 100644 plat/cpm/libsys/putc.c diff --git a/build.lua b/build.lua index ccd113f1a..14110e4f5 100644 --- a/build.lua +++ b/build.lua @@ -7,24 +7,24 @@ vars.ackcflags = { vars.ackldflags = {} vars.plats = { "cpm", - "linux386", - "linux68k", - "linuxppc", - "linuxmips", - "osx386", - "osxppc", - "pc86", - "rpi", - "pdpv7", - "em22", +-- "linux386", +-- "linux68k", +-- "linuxppc", +-- "linuxmips", +-- "osx386", +-- "osxppc", +-- "pc86", +-- "rpi", +-- "pdpv7", +-- "em22", } vars.plats_with_tests = { - "cpm", - "linux68k", - "linux386", - "linuxppc", - "linuxmips", - "pc86", +-- "cpm", +-- "linux68k", +-- "linux386", +-- "linuxppc", +-- "linuxmips", +-- "pc86", } installable { diff --git a/lang/cem/libcc.ansi/headers/ack/emufile.h b/lang/cem/libcc.ansi/headers/ack/emufile.h index 186630e56..06a1ffcec 100644 --- a/lang/cem/libcc.ansi/headers/ack/emufile.h +++ b/lang/cem/libcc.ansi/headers/ack/emufile.h @@ -25,7 +25,9 @@ struct FILE { #define _IOWRITING 0x100 #define _IOAPPEND 0x200 +#if !defined BUFSIZ #define BUFSIZ 1024 +#endif #define FOPEN_MAX 20 extern FILE *__iotab[FOPEN_MAX]; diff --git a/plat/cpm/descr b/plat/cpm/descr index e01f2c389..c023fc45c 100644 --- a/plat/cpm/descr +++ b/plat/cpm/descr @@ -77,6 +77,7 @@ name led (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ {PLATFORMDIR}/libc.a \ + {PLATFORMDIR}/libsys.a \ {PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libend.a) linker diff --git a/plat/cpm/include/ack/plat.h b/plat/cpm/include/ack/plat.h index 6e1bac6ae..d6270fe5c 100644 --- a/plat/cpm/include/ack/plat.h +++ b/plat/cpm/include/ack/plat.h @@ -6,17 +6,21 @@ #ifndef _ACK_PLAT_H #define _ACK_PLAT_H +/* The 8080 code generator doesn't do floating point. */ + +#define ACKCONF_WANT_STDIO_FLOAT 0 + /* We're providing a time() system call rather than wanting a wrapper around * gettimeofday() in the libc. */ #define ACKCONF_WANT_EMULATED_TIME 0 -/* CP/M's underlying file abstraction is weird and doesn't map well onto - * file descriptors. Disable the standard FILE* mechanism in favour of our - * own. - */ +/* Processes? CP/M? Hahahaha... */ -#define ACKCONF_WANT_EMULATED_FILE 0 #define ACKCONF_WANT_EMULATED_POPEN 0 +/* We have a very small address space, so override the default buffer size. */ + +#define BUFSIZ 256 + #endif diff --git a/plat/cpm/include/cpm.h b/plat/cpm/include/cpm.h index c7288856b..3ad97b183 100644 --- a/plat/cpm/include/cpm.h +++ b/plat/cpm/include/cpm.h @@ -67,10 +67,19 @@ extern uint8_t* cpm_ramtop; extern uint8_t cpm_cmdlinelen; extern char cpm_cmdline[0x7f]; +/* Special: parses a filename into an FCB. Returns the user code (if any). + * Warning: cannot fail (because CP/M filespecs are incredibly lax). */ + +extern uint8_t cpm_parse_filename(FCB* fcb, const char* filename); + /* Special: if the CCP hasn't been overwritten, returns to it; otherwise does * a warmboot. */ extern void cpm_exit(void); +/* Special: equivalent to cpm_read_random() except if you read unwritten data + * 0 is returned (and the buffer contains garbage). */ +extern uint8_t cpm_read_random_safe(FCB* fcb); + /* Extends cpm_ramtop over the CCP, for a little extra space. */ extern void cpm_overwrite_ccp(void); @@ -114,12 +123,7 @@ 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; -}; +#define cpm_get_user() cpm_get_set_user(0xff) +#define cpm_set_user(u) cpm_get_set_user(u) #endif diff --git a/plat/cpm/libsys/build.lua b/plat/cpm/libsys/build.lua index 9091a6917..070290326 100644 --- a/plat/cpm/libsys/build.lua +++ b/plat/cpm/libsys/build.lua @@ -47,28 +47,28 @@ local bdos_calls = { local trap_calls = { "EARRAY", + "EBADGTO", + "EBADLAE", + "EBADLIN", + "EBADMON", + "EBADPC", + "EBADPTR", + "ECASE", + "ECONV", + "EFDIVZ", + "EFOVFL", + "EFUND", + "EFUNFL", + "EHEAP", + "EIDIVZ", + "EILLINS", + "EIOVFL", + "EIUND", + "EMEMFLT", + "EODDZ", "ERANGE", "ESET", - "EIOVFL", - "EFOVFL", - "EFUNFL", - "EIDIVZ", - "EFDIVZ", - "EIUND", - "EFUND", - "ECONV", "ESTACK", - "EHEAP", - "EILLINS", - "EODDZ", - "ECASE", - "EMEMFLT", - "EBADPTR", - "EBADPC", - "EBADLAE", - "EBADMON", - "EBADLIN", - "EBADGTO", "EUNIMPL", } diff --git a/plat/cpm/libsys/close.c b/plat/cpm/libsys/close.c index 1c570029b..be5ae0ec4 100644 --- a/plat/cpm/libsys/close.c +++ b/plat/cpm/libsys/close.c @@ -1,14 +1,31 @@ -/* $Source$ - * $State$ - * $Revision$ - */ - #include #include #include +#include +#include "cpmsys.h" int close(int fd) { - errno = EBADF; - return -1; + struct FCBE* fcbe = &__fd[fd]; + int result = 0; + uint8_t olduser; + + __init_file_descriptors(); + if (fcbe->fcb.f[0]) + { + /* There's an actual filename here, so assume it's an open file. */ + + olduser = cpm_get_user(); + cpm_set_user(fcbe->user); + if (cpm_close_file(&fcbe->fcb) == 0xff) + { + errno = EIO; + result = -1; + } + cpm_set_user(olduser); + } + + memset(fcbe, 0, sizeof(struct FCBE)); + return result; } + diff --git a/plat/cpm/libsys/cpm_read_random_safe.c b/plat/cpm/libsys/cpm_read_random_safe.c new file mode 100644 index 000000000..1c5838bd6 --- /dev/null +++ b/plat/cpm/libsys/cpm_read_random_safe.c @@ -0,0 +1,10 @@ +#include +#include + +uint8_t cpm_read_random_safe(FCB* fcb) +{ + uint8_t r = cpm_read_random(fcb); + if ((r == 1) || (r == 4)) + r = 0; + return r; +} diff --git a/plat/cpm/libsys/cpmsys.h b/plat/cpm/libsys/cpmsys.h new file mode 100644 index 000000000..d659f9e9f --- /dev/null +++ b/plat/cpm/libsys/cpmsys.h @@ -0,0 +1,22 @@ +#ifndef CPMSYS_H +#define CPMSYS_H + +/* File descriptor emulation */ + +struct FCBE +{ + uint16_t length; /* number of records */ + FCB fcb; /* drive 0 means the console, f[0] == 0 means unallocated */ + uint8_t user; + uint8_t offset; /* into current sector */ +}; + +#define NUM_FILE_DESCRIPTORS 8 +extern struct FCBE __fd[NUM_FILE_DESCRIPTORS]; +extern uint8_t __transfer_buffer[128]; + +extern void __init_file_descriptors(void); + +#define SECTOR_ALIGNED(s) (((s) & 0x7f) == 0) + +#endif diff --git a/plat/cpm/libsys/fcb.c b/plat/cpm/libsys/fcb.c index e8059de3e..0f98b5a4f 100644 --- a/plat/cpm/libsys/fcb.c +++ b/plat/cpm/libsys/fcb.c @@ -1,3 +1,73 @@ #include #include +#include +#include +#include "cpmsys.h" + +uint8_t cpm_parse_filename(FCB* fcb, const char* filename) +{ + uint8_t user = cpm_get_user(); + + memset(fcb, 0, sizeof(FCB)); + memset(fcb->f, ' ', sizeof(fcb->f)); + + if (strchr(filename, ':')) + { + char c = *filename++; + if (isdigit(c)) + { + user = c - '0'; + c = *filename++; + if (isdigit(c)) + { + user = (user*10) + (c - '0'); + c = *filename++; + } + } + c = toupper(c); + if (isalpha(c)) + { + fcb->dr = c - '@'; + c = *filename++; + } + + while (c != ':') + c = *filename++; + } + + /* Read filename part. */ + + { + uint8_t i = 8; + uint8_t* p = &fcb->f[0]; + while (i--) + { + char c = toupper(*filename++); + if (c == '.') + break; + if (!c) + goto exit; + *p++ = c; + } + } + + /* Read extension part. */ + + { + uint8_t i = 3; + uint8_t* p = &fcb->f[8]; + while (i--) + { + char c = toupper(*filename++); + if (!c) + goto exit; + *p++ = c; + } + } + +exit: + if (fcb->dr == 0) + fcb->dr = cpm_get_current_drive() + 1; + return user; +} diff --git a/plat/cpm/libsys/fclose.c b/plat/cpm/libsys/fclose.c deleted file mode 100644 index abae8a6c0..000000000 --- a/plat/cpm/libsys/fclose.c +++ /dev/null @@ -1,20 +0,0 @@ -#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/fd.c b/plat/cpm/libsys/fd.c new file mode 100644 index 000000000..e98c9d7b2 --- /dev/null +++ b/plat/cpm/libsys/fd.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include "cpmsys.h" + +struct FCBE __fd[NUM_FILE_DESCRIPTORS]; +uint8_t __transfer_buffer[128]; + +void __init_file_descriptors(void) +{ + static uint8_t initialised = 0; + if (!initialised) + { + /* Mark stdin, stdout, stderr as being open files. */ + __fd[0].fcb.f[0] = __fd[1].fcb.f[0] = __fd[2].fcb.f[0] = ' '; + initialised = 1; + } +} diff --git a/plat/cpm/libsys/feof.c b/plat/cpm/libsys/feof.c deleted file mode 100644 index a04a76a78..000000000 --- a/plat/cpm/libsys/feof.c +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include -#include - -int cpm_feof(FILE* stream) -{ - return 0; -} - diff --git a/plat/cpm/libsys/ferror.c b/plat/cpm/libsys/ferror.c deleted file mode 100644 index b279c8cec..000000000 --- a/plat/cpm/libsys/ferror.c +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include -#include - -int cpm_ferror(FILE* stream) -{ - return 0; -} diff --git a/plat/cpm/libsys/fflush.c b/plat/cpm/libsys/fflush.c deleted file mode 100644 index 664488467..000000000 --- a/plat/cpm/libsys/fflush.c +++ /dev/null @@ -1,12 +0,0 @@ -#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 deleted file mode 100644 index bb322fc04..000000000 --- a/plat/cpm/libsys/getc.c +++ /dev/null @@ -1,36 +0,0 @@ -#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/lseek.c b/plat/cpm/libsys/lseek.c index ecbc4b520..ddc38df03 100644 --- a/plat/cpm/libsys/lseek.c +++ b/plat/cpm/libsys/lseek.c @@ -1,14 +1,28 @@ -/* $Source$ - * $State$ - * $Revision$ - */ - +#include #include #include +#include #include +#include +#include "cpmsys.h" off_t lseek(int fd, off_t offset, int whence) { - errno = EINVAL; - return -1; + struct FCBE* fcbe = &__fd[fd]; + + __init_file_descriptors(); + if (fcbe->fcb.dr == 0) + { + /* Can't seek the console. */ + return 0; + } + + if (whence == SEEK_END) + offset += fcbe->length<<7; + if (whence == SEEK_CUR) + offset += (U16(fcbe->fcb.r)<<7) | fcbe->offset; + + U16(fcbe->fcb.r) = offset>>7; + fcbe->offset = offset & 0x7f; + return 0; } diff --git a/plat/cpm/libsys/open.c b/plat/cpm/libsys/open.c index f3522eae5..82345fb55 100644 --- a/plat/cpm/libsys/open.c +++ b/plat/cpm/libsys/open.c @@ -1,14 +1,61 @@ -/* $Source$ - * $State$ - * $Revision$ - */ - +#include #include #include #include +#include +#include "cpmsys.h" int open(const char* path, int access, ...) { - errno = EACCES; + uint8_t fd = 0; + struct FCBE* fcbe = &__fd[0]; + uint8_t olduser; + + __init_file_descriptors(); + while (fd != NUM_FILE_DESCRIPTORS) + { + if (fcbe->fcb.f[0] == 0) + break; + fd++; + fcbe++; + } + if (fd == NUM_FILE_DESCRIPTORS) + { + errno = EMFILE; + return -1; + } + + fcbe->user = cpm_parse_filename(&fcbe->fcb, path); + + olduser = cpm_get_user(); + cpm_set_user(fcbe->user); + + if (access & O_TRUNC) + { + cpm_delete_file(&fcbe->fcb); + access |= O_CREAT; + } + if (access & O_CREAT) + { + if (cpm_make_file(&fcbe->fcb) == 0xff) + goto eio; + } + else + { + if (cpm_open_file(&fcbe->fcb) == 0xff) + goto eio; + } + + cpm_seek_to_end(&fcbe->fcb); + fcbe->length = U16(fcbe->fcb.r); + if (!(access & O_APPEND)) + U16(fcbe->fcb.r) = 0; + return fd; + +eio: + fcbe->fcb.f[0] = 0; + errno = EIO; return -1; } + + diff --git a/plat/cpm/libsys/putc.c b/plat/cpm/libsys/putc.c deleted file mode 100644 index f78027d97..000000000 --- a/plat/cpm/libsys/putc.c +++ /dev/null @@ -1,17 +0,0 @@ -#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 952995af8..1d64faaf6 100644 --- a/plat/cpm/libsys/read.c +++ b/plat/cpm/libsys/read.c @@ -7,18 +7,100 @@ #include #include #include +#include #include +#include "cpmsys.h" ssize_t read(int fd, void* buffer, size_t count) { - short save; - unsigned char before_n; + uint8_t* bbuffer = buffer; + struct FCBE* fcbe = &__fd[fd]; + uint8_t olduser; + ssize_t result; - if (fd != 0) + __init_file_descriptors(); + if (fcbe->fcb.dr == 0) { - errno = EBADF; - return -1; + /* Read from the console. */ + + if (count == 0) + return 0; + *(uint8_t*)buffer = cpm_conin(); + return 1; } - return fread(buffer, 1, count, stdin); + olduser = cpm_get_user(); + cpm_set_user(fcbe->user); + + if (U16(fcbe->fcb.r) >= fcbe->length) + goto done; + if (fcbe->offset || !SECTOR_ALIGNED(count)) + { + uint8_t delta; + + /* We need to read bytes until we're at a sector boundary. */ + + cpm_set_dma(__transfer_buffer); + if (cpm_read_random_safe(&fcbe->fcb) != 0) + goto eio; + + /* Copy enough bytes to reach the end of the sector. */ + + delta = 128 - fcbe->offset; + if (delta > count) + delta = count; + memcpy(bbuffer, __transfer_buffer+fcbe->offset, delta); + fcbe->offset += delta; + count -= delta; + bbuffer += delta; + + /* If we've read enough bytes, advance to the next sector. */ + + if (fcbe->offset == 128) + { + U16(fcbe->fcb.r)++; + fcbe->offset = 0; + } + } + + while (count >= 128) + { + if (U16(fcbe->fcb.r) >= fcbe->length) + goto done; + + /* Read entire sectors directly into the destination buffer. */ + + cpm_set_dma(bbuffer); + if (cpm_read_random_safe(&fcbe->fcb) != 0) + goto eio; + count -= 128; + bbuffer += 128; + U16(fcbe->fcb.r)++; + } + + if (count != 0) + { + if (U16(fcbe->fcb.r) >= fcbe->length) + goto done; + + /* There's some trailing data to read. */ + + cpm_set_dma(__transfer_buffer); + if (cpm_read_random_safe(&fcbe->fcb) != 0) + goto eio; + + memcpy(bbuffer, __transfer_buffer, count); + fcbe->offset = count; + } + +done: + result = bbuffer - (uint8_t*)buffer; +exit: + cpm_set_user(olduser); + return result; + +eio: + errno = EIO; + result = -1; + goto exit; } diff --git a/plat/cpm/libsys/write.c b/plat/cpm/libsys/write.c index 768e9b2eb..384425c08 100644 --- a/plat/cpm/libsys/write.c +++ b/plat/cpm/libsys/write.c @@ -6,7 +6,9 @@ #include #include #include +#include #include +#include "cpmsys.h" void _sys_write_tty(char c) { @@ -17,24 +19,103 @@ void _sys_write_tty(char c) ssize_t write(int fd, void* buffer, size_t count) { - int i; - char* p = buffer; - - /* We're only allowed to write to fd 0, 1 or 2. */ - - if ((fd < 0) || (fd > 2)) + uint8_t* bbuffer = buffer; + struct FCBE* fcbe = &__fd[fd]; + uint8_t olduser; + uint16_t result; + + __init_file_descriptors(); + if (fcbe->fcb.dr == 0) { - errno = EBADF; - return -1; + /* Write to the console. */ + + size_t i = count; + while (i--) + _sys_write_tty(*bbuffer++); + return count; } - - /* Write all data. */ - - i = count; - while (i--) - _sys_write_tty(*p++); - - /* No failures. */ - - return count; + + olduser = cpm_get_user(); + cpm_set_user(fcbe->user); + + if (fcbe->offset || !SECTOR_ALIGNED(count)) + { + uint8_t delta; + + /* We're not at a sector boundary, so we need to do a + * read/modify/write of the initial fragment. */ + + cpm_set_dma(__transfer_buffer); + if (cpm_read_random_safe(&fcbe->fcb) != 0) + goto eio; + + /* Copy enough bytes to reach the end of the sector. */ + + delta = 128 - fcbe->offset; + if (delta > count) + delta = count; + memcpy(__transfer_buffer+fcbe->offset, bbuffer, delta); + fcbe->offset += delta; + count -= delta; + bbuffer += delta; + + /* Write back. */ + + if (cpm_write_random(&fcbe->fcb) != 0) + goto eio; + + /* If we've written enough bytes, advance to the next sector. */ + + if (fcbe->offset == 128) + { + U16(fcbe->fcb.r)++; + fcbe->offset = 0; + } + } + + while (count >= 128) + { + /* Write entire sectors directly from the source buffer. */ + + cpm_set_dma(bbuffer); + if (cpm_write_random(&fcbe->fcb) != 0) + goto eio; + count -= 128; + bbuffer += 128; + U16(fcbe->fcb.r)++; + } + + if (count != 0) + { + /* There's some trailing data to write. We need another + * read/modify/write cycle. */ + + cpm_set_dma(__transfer_buffer); + if (cpm_read_random_safe(&fcbe->fcb) != 0) + goto eio; + + memcpy(__transfer_buffer, bbuffer, count); + + if (cpm_write_random(&fcbe->fcb) != 0) + goto eio; + + fcbe->offset = count; + } + + if (U16(fcbe->fcb.r) >= fcbe->length) + { + fcbe->length = U16(fcbe->fcb.r); + if (fcbe->offset != 0) + fcbe->length++; + } + + result = bbuffer - (uint8_t*)buffer; +exit: + cpm_set_user(olduser); + return result; + +eio: + errno = EIO; + result = -1; + goto exit; } From 2b013c34dc8ae65c2411fab32d476ab54d2372b7 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 16 Jun 2019 20:04:07 +0200 Subject: [PATCH 5/9] Some byte shaving; lseek returns the offset. --- plat/cpm/libsys/lseek.c | 2 +- plat/cpm/libsys/read.c | 25 +++++++++++++++---------- plat/cpm/libsys/write.c | 26 +++++++++++++++----------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/plat/cpm/libsys/lseek.c b/plat/cpm/libsys/lseek.c index ddc38df03..9b8648b52 100644 --- a/plat/cpm/libsys/lseek.c +++ b/plat/cpm/libsys/lseek.c @@ -24,5 +24,5 @@ off_t lseek(int fd, off_t offset, int whence) U16(fcbe->fcb.r) = offset>>7; fcbe->offset = offset & 0x7f; - return 0; + return offset; } diff --git a/plat/cpm/libsys/read.c b/plat/cpm/libsys/read.c index 1d64faaf6..c2a1abd61 100644 --- a/plat/cpm/libsys/read.c +++ b/plat/cpm/libsys/read.c @@ -17,6 +17,7 @@ ssize_t read(int fd, void* buffer, size_t count) struct FCBE* fcbe = &__fd[fd]; uint8_t olduser; ssize_t result; + uint8_t* src; __init_file_descriptors(); if (fcbe->fcb.dr == 0) @@ -36,8 +37,6 @@ ssize_t read(int fd, void* buffer, size_t count) goto done; if (fcbe->offset || !SECTOR_ALIGNED(count)) { - uint8_t delta; - /* We need to read bytes until we're at a sector boundary. */ cpm_set_dma(__transfer_buffer); @@ -46,13 +45,13 @@ ssize_t read(int fd, void* buffer, size_t count) /* Copy enough bytes to reach the end of the sector. */ - delta = 128 - fcbe->offset; - if (delta > count) - delta = count; - memcpy(bbuffer, __transfer_buffer+fcbe->offset, delta); - fcbe->offset += delta; - count -= delta; - bbuffer += delta; + src = __transfer_buffer + fcbe->offset; + while ((count != 0) && (fcbe->offset != 128)) + { + *bbuffer++ = *src++; + fcbe->offset++; + count--; + } /* If we've read enough bytes, advance to the next sector. */ @@ -89,7 +88,13 @@ ssize_t read(int fd, void* buffer, size_t count) if (cpm_read_random_safe(&fcbe->fcb) != 0) goto eio; - memcpy(bbuffer, __transfer_buffer, count); + src = __transfer_buffer; + while (count != 0) + { + *bbuffer++ = *src++; + count--; + } + fcbe->offset = count; } diff --git a/plat/cpm/libsys/write.c b/plat/cpm/libsys/write.c index 384425c08..eb2c89a0a 100644 --- a/plat/cpm/libsys/write.c +++ b/plat/cpm/libsys/write.c @@ -19,10 +19,11 @@ void _sys_write_tty(char c) ssize_t write(int fd, void* buffer, size_t count) { - uint8_t* bbuffer = buffer; + const uint8_t* bbuffer = buffer; struct FCBE* fcbe = &__fd[fd]; uint8_t olduser; uint16_t result; + uint8_t* dest; __init_file_descriptors(); if (fcbe->fcb.dr == 0) @@ -40,8 +41,6 @@ ssize_t write(int fd, void* buffer, size_t count) if (fcbe->offset || !SECTOR_ALIGNED(count)) { - uint8_t delta; - /* We're not at a sector boundary, so we need to do a * read/modify/write of the initial fragment. */ @@ -51,13 +50,13 @@ ssize_t write(int fd, void* buffer, size_t count) /* Copy enough bytes to reach the end of the sector. */ - delta = 128 - fcbe->offset; - if (delta > count) - delta = count; - memcpy(__transfer_buffer+fcbe->offset, bbuffer, delta); - fcbe->offset += delta; - count -= delta; - bbuffer += delta; + dest = __transfer_buffer + fcbe->offset; + while ((count != 0) && (fcbe->offset != 128)) + { + *dest++ = *bbuffer++; + fcbe->offset++; + count--; + } /* Write back. */ @@ -94,7 +93,12 @@ ssize_t write(int fd, void* buffer, size_t count) if (cpm_read_random_safe(&fcbe->fcb) != 0) goto eio; - memcpy(__transfer_buffer, bbuffer, count); + dest = __transfer_buffer; + while (count != 0) + { + *dest++ = *bbuffer++; + count--; + } if (cpm_write_random(&fcbe->fcb) != 0) goto eio; From 97e6d8f66aa4589d40e4a449d5b2753080534387 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 16 Jun 2019 20:10:13 +0200 Subject: [PATCH 6/9] Update README. --- plat/cpm/README | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/plat/cpm/README b/plat/cpm/README index c7d7b1ac4..a774d0d50 100644 --- a/plat/cpm/README +++ b/plat/cpm/README @@ -1,26 +1,22 @@ -# $Source$ -# $State$ -# $Revision$ - - The cpm platform ================= cpm is an i80-based BSP that generates CP/M executables that can be run on any CP/M-compliant machine. -This port only implements a very limited set of syscalls --- and most of those -are stubs required to make the demo apps link. File descriptors 0, 1 and 2 -represent the console. Each read() blocks and reads an entire line (it can't -read part of a line) from the CP/M line editor, then appends \n. Each write() -converts \n to \r\n. The line editor and \n conversion can't be turned off. +CP/M has special needs in many ways, the main one being that it doesn't +support byte-accessible files --- only complete 128-byte sectors can be read +or written. The port's read/write/open/close/lseek etc should handle this +transparently, but trying to write a fragment of a sector will involve a +read/modify/write cycle. No buffering is done (that's stdio's job). -There's a special, if rather minimilist, interface to give applications access +File descriptors 0, 1 and 2 represent the console, as usual. + +In addition, there's a special interface to give applications direct access to CP/M. See include/cpm.h for details. -Link with `ack -fp` to enable software floating point. Otherwise, attempts to -use floating-point numbers will cause the program to terminate. - +Floating point is not supported and attempts to use floating-point numbers +will cause the program to terminate. Example command line ==================== From 6531850462d2bf0f1acaa5fd53e36f750bb2c7d8 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Jun 2019 00:40:01 +0200 Subject: [PATCH 7/9] Oops, forgot to turn the other plats on before checking in. --- build.lua | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/build.lua b/build.lua index 14110e4f5..ccd113f1a 100644 --- a/build.lua +++ b/build.lua @@ -7,24 +7,24 @@ vars.ackcflags = { vars.ackldflags = {} vars.plats = { "cpm", --- "linux386", --- "linux68k", --- "linuxppc", --- "linuxmips", --- "osx386", --- "osxppc", --- "pc86", --- "rpi", --- "pdpv7", --- "em22", + "linux386", + "linux68k", + "linuxppc", + "linuxmips", + "osx386", + "osxppc", + "pc86", + "rpi", + "pdpv7", + "em22", } vars.plats_with_tests = { --- "cpm", --- "linux68k", --- "linux386", --- "linuxppc", --- "linuxmips", --- "pc86", + "cpm", + "linux68k", + "linux386", + "linuxppc", + "linuxmips", + "pc86", } installable { From 402468f6fd79bcce8ad1ce7b77214887ac0c5e36 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 17 Jun 2019 00:41:49 +0200 Subject: [PATCH 8/9] Bugfix the CP/M FCB parser, and add a test for it. --- plat/cpm/libsys/fcb.c | 76 +++++++++++++++++-------------------- plat/cpm/tests/build.lua | 3 +- plat/cpm/tests/parsefcb_c.c | 66 ++++++++++++++++++++++++++++++++ tests/plat/build.lua | 5 ++- 4 files changed, 105 insertions(+), 45 deletions(-) create mode 100644 plat/cpm/tests/parsefcb_c.c diff --git a/plat/cpm/libsys/fcb.c b/plat/cpm/libsys/fcb.c index 0f98b5a4f..96705c467 100644 --- a/plat/cpm/libsys/fcb.c +++ b/plat/cpm/libsys/fcb.c @@ -1,71 +1,63 @@ #include +#include #include #include #include #include "cpmsys.h" +static const char* fill(uint8_t* dest, const char* src, int len) +{ + do + { + char c = toupper(*src); + if (!c || (c == '.')) + c = ' '; + else if (c == '*') + c = '?'; + else + src++; + *dest++ = c; + } + while (--len); + return src; +} + uint8_t cpm_parse_filename(FCB* fcb, const char* filename) { uint8_t user = cpm_get_user(); + char c; memset(fcb, 0, sizeof(FCB)); memset(fcb->f, ' ', sizeof(fcb->f)); - if (strchr(filename, ':')) { - char c = *filename++; - if (isdigit(c)) + const char* colon = strchr(filename, ':'); + if (colon) { - user = c - '0'; c = *filename++; if (isdigit(c)) { - user = (user*10) + (c - '0'); + user = strtol(filename-1, &filename, 10); + c = *filename++; + } + c = toupper(c); + if (isalpha(c)) + { + fcb->dr = c - '@'; c = *filename++; } - } - c = toupper(c); - if (isalpha(c)) - { - fcb->dr = c - '@'; - c = *filename++; - } - while (c != ':') - c = *filename++; + filename = colon + 1; + } } /* Read filename part. */ - { - uint8_t i = 8; - uint8_t* p = &fcb->f[0]; - while (i--) - { - char c = toupper(*filename++); - if (c == '.') - break; - if (!c) - goto exit; - *p++ = c; - } - } + filename = fill(&fcb->f[0], filename, 8); + filename = strchr(filename, '.'); + if (filename) + fill(&fcb->f[8], filename+1, 3); - /* Read extension part. */ - - { - uint8_t i = 3; - uint8_t* p = &fcb->f[8]; - while (i--) - { - char c = toupper(*filename++); - if (!c) - goto exit; - *p++ = c; - } - } - -exit: if (fcb->dr == 0) fcb->dr = cpm_get_current_drive() + 1; return user; diff --git a/plat/cpm/tests/build.lua b/plat/cpm/tests/build.lua index 6518c6849..1a8488136 100644 --- a/plat/cpm/tests/build.lua +++ b/plat/cpm/tests/build.lua @@ -4,5 +4,6 @@ plat_testsuite { name = "tests", plat = "cpm", method = "plat/cpm/emu+emu", - skipsets = {"floats"}, + skipsets = {"floats"}, + tests = { "./*.c" }, } diff --git a/plat/cpm/tests/parsefcb_c.c b/plat/cpm/tests/parsefcb_c.c new file mode 100644 index 000000000..53605e2a4 --- /dev/null +++ b/plat/cpm/tests/parsefcb_c.c @@ -0,0 +1,66 @@ +#include +#include +#include "test.h" + +struct testcase +{ + const char* input; + uint8_t drive; + uint8_t user; + const char filename[11]; +}; + +struct testcase tests[] = +{ + { "12345678.ABC", 'A', 0, "12345678ABC" }, + { "12345678.A", 'A', 0, "12345678A " }, + { "12345678", 'A', 0, "12345678 " }, + { "1", 'A', 0, "1 " }, + { ".X", 'A', 0, " X " }, + + { "B:FOO", 'B', 0, "FOO " }, + { "Z:FOO", 'Z', 0, "FOO " }, + { "1Z:FOO", 'Z', 1, "FOO " }, + { "23Z:FOO", 'Z', 23, "FOO " }, + + { "*.*", 'A', 0, "???????????" }, + { "FOO*.*", 'A', 0, "FOO????????" }, + { "FOO*", 'A', 0, "FOO????? " }, + { "FOO.*", 'A', 0, "FOO ???" }, +}; + +static int failed = 0; + +static void do_test(int i, struct testcase* test) +{ + static FCB fcb; + uint8_t got_user = cpm_parse_filename(&fcb, test->input); + + if ((got_user == test->user) + && (fcb.dr == (test->drive - '@')) + && (memcmp(fcb.f, test->filename, 11) == 0)) + return; + + printf("Want: %s -> %d%c:'%.11s' but got %d%c:'%.11s'\n", + test->input, + test->user, test->drive, test->filename, + got_user, fcb.dr+'@', fcb.f); + + failed = 1; +} + +int main(int argc, const char* argv[]) +{ + int i; + + failed = 0; + cpm_select_drive(0); /* A: */ + cpm_set_user(0); + + for (i=0; i Date: Mon, 17 Jun 2019 00:52:09 +0200 Subject: [PATCH 9/9] I managed to break the test system... somehow. Fix. --- tests/plat/build.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/plat/build.lua b/tests/plat/build.lua index 6bc5ef9b7..f7eecc0dd 100644 --- a/tests/plat/build.lua +++ b/tests/plat/build.lua @@ -11,7 +11,7 @@ definerule("plat_testsuite", function(e) -- Remember this is executed from the caller's directory; local -- target names will resolve there. - local testfiles = e.tests + local testfiles = filenamesof(e.tests) local skipsets = {} for _, set in ipairs(e.skipsets) do skipsets[set] = true @@ -40,7 +40,7 @@ definerule("plat_testsuite", local tests = {} for _, f in ipairs(testfiles) do - local fs = replace(basename(filenamesof(f)[1]), "%.[^.]+$", "") + local fs = replace(basename(f), "%.[^.]+$", "") local _, _, lang = fs:find("_([^_]+)$") if not lang then lang = "e"