From 9109d7af7f62add6467099dd5c7979d16ccd15db Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 15 Jun 2019 13:07:10 +0200 Subject: [PATCH] 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")