diff --git a/lang/cem/libcc.ansi/build.lua b/lang/cem/libcc.ansi/build.lua index ee1049d66..29c85b351 100644 --- a/lang/cem/libcc.ansi/build.lua +++ b/lang/cem/libcc.ansi/build.lua @@ -39,9 +39,12 @@ 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", + "./core/stdio/*.c", "./core/string/*.c", "./core/time/*.c", "./sys/exit/*.c", @@ -57,7 +60,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 96% rename from lang/cem/libcc.ansi/sys/stdio/doprnt.c rename to lang/cem/libcc.ansi/core/printf/doprnt.c index 9f74c7659..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, FILE* stream) +int _doprnt(register const char* fmt, va_list ap) { register char* s; register int j; diff --git a/lang/cem/libcc.ansi/sys/stdio/loc_incl.h b/lang/cem/libcc.ansi/core/printf/doprnt.h similarity index 58% rename from lang/cem/libcc.ansi/sys/stdio/loc_incl.h rename to lang/cem/libcc.ansi/core/printf/doprnt.h index b30d3272a..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, FILE *stream); -int _doscan(FILE * stream, const char *format, va_list ap); -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 80% rename from lang/cem/libcc.ansi/sys/stdio/fprintf.c rename to lang/cem/libcc.ansi/core/printf/fprintf.c index 3085bf96a..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 @@ -15,9 +14,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/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 80% rename from lang/cem/libcc.ansi/sys/stdio/printf.c rename to lang/cem/libcc.ansi/core/printf/printf.c index 6b118c859..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 @@ -15,9 +14,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/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/core/printf/sprintf.c b/lang/cem/libcc.ansi/core/printf/sprintf.c new file mode 100644 index 000000000..86e81e4a4 --- /dev/null +++ b/lang/cem/libcc.ansi/core/printf/sprintf.c @@ -0,0 +1,23 @@ +/* + * sprintf - print formatted output on an array + */ +/* $Id$ */ + +#include +#include + +#if ACKCONF_WANT_STDIO + +int sprintf(char* s, const char* format, ...) +{ + va_list ap; + int retval; + + va_start(ap, format); + retval = vsnprintf(s, 32767, format, ap); + va_end(ap); + + return retval; +} + +#endif diff --git a/lang/cem/libcc.ansi/core/printf/vfprintf.c b/lang/cem/libcc.ansi/core/printf/vfprintf.c new file mode 100644 index 000000000..7e665a22f --- /dev/null +++ b/lang/cem/libcc.ansi/core/printf/vfprintf.c @@ -0,0 +1,27 @@ +/* + * vfprintf - formatted output without ellipsis + */ +/* $Id$ */ + +#include +#include +#include "doprnt.h" + +#if ACKCONF_WANT_STDIO + +static FILE* vfprintf_stream; + +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; + _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 78% rename from lang/cem/libcc.ansi/sys/stdio/vprintf.c rename to lang/cem/libcc.ansi/core/printf/vprintf.c index 5cc6b837f..999fdaa4d 100644 --- a/lang/cem/libcc.ansi/sys/stdio/vprintf.c +++ b/lang/cem/libcc.ansi/core/printf/vprintf.c @@ -5,13 +5,12 @@ #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO 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/core/printf/vsnprintf.c b/lang/cem/libcc.ansi/core/printf/vsnprintf.c new file mode 100644 index 000000000..af97b5351 --- /dev/null +++ b/lang/cem/libcc.ansi/core/printf/vsnprintf.c @@ -0,0 +1,38 @@ +/* + * vsprintf - print formatted output without ellipsis on an array + */ +/* $Id$ */ + +#include +#include +#include "doprnt.h" + +#if ACKCONF_WANT_STDIO + +static char* output_buffer; +static size_t output_buffer_len; + +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) +{ + int retval; + + output_buffer = s; + output_buffer_len = len; + _doprnt_put = snprintf_putc; + retval = _doprnt(format, ap); + snprintf_putc('\0'); + + return retval; +} + +#endif diff --git a/lang/cem/libcc.ansi/core/printf/vsprintf.c b/lang/cem/libcc.ansi/core/printf/vsprintf.c new file mode 100644 index 000000000..c8da509ab --- /dev/null +++ b/lang/cem/libcc.ansi/core/printf/vsprintf.c @@ -0,0 +1,16 @@ +/* + * vsprintf - print formatted output without ellipsis on an array + */ +/* $Id$ */ + +#include +#include + +#if ACKCONF_WANT_STDIO + +int vsprintf(char* s, const char* format, va_list ap) +{ + return vsnprintf(s, 32767, format, ap); +} + +#endif 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 3a1076bad..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,15 +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, register FILE* stream, char type, - int width, int* basep) +static char* o_collect(register int c, char type, int width, int* basep) { register char* bufp = inp_buf; register int base; @@ -63,14 +64,14 @@ o_collect(register int c, register FILE* stream, char type, { *bufp++ = c; if (--width) - c = getc(stream); + c = _doscan_get(); } if (width && c == '0' && base == 16) { *bufp++ = c; if (--width) - c = getc(stream); + c = _doscan_get(); if (c != 'x' && c != 'X') { if (type == 'i') @@ -80,7 +81,7 @@ o_collect(register int c, register FILE* stream, char type, { *bufp++ = c; if (--width) - c = getc(stream); + c = _doscan_get(); } } else if (type == 'i') @@ -95,14 +96,14 @@ o_collect(register int c, register FILE* stream, char type, { *bufp++ = c; if (--width) - c = getc(stream); + c = _doscan_get(); } else break; } if (width && c != EOF) - ungetc(c, stream); + _doscan_unget(c); if (type == 'i') base = 0; *basep = base; @@ -119,8 +120,7 @@ o_collect(register int c, register FILE* stream, char type, * 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 FILE* stream, register int width) +static char* f_collect(register int c, register int width) { register char* bufp = inp_buf; int digit_seen = 0; @@ -129,7 +129,7 @@ f_collect(register int c, register FILE* stream, register int width) { *bufp++ = c; if (--width) - c = getc(stream); + c = _doscan_get(); } while (width && isdigit(c)) @@ -137,26 +137,26 @@ f_collect(register int c, register FILE* stream, register int width) digit_seen++; *bufp++ = c; if (--width) - c = getc(stream); + c = _doscan_get(); } if (width && c == '.') { *bufp++ = c; if (--width) - c = getc(stream); + c = _doscan_get(); while (width && isdigit(c)) { digit_seen++; *bufp++ = c; if (--width) - c = getc(stream); + c = _doscan_get(); } } if (!digit_seen) { if (width && c != EOF) - ungetc(c, stream); + _doscan_unget(c); return inp_buf - 1; } else @@ -166,30 +166,30 @@ f_collect(register int c, register FILE* stream, register int width) { *bufp++ = c; if (--width) - c = getc(stream); + c = _doscan_get(); if (width && (c == '+' || c == '-')) { *bufp++ = c; if (--width) - c = getc(stream); + c = _doscan_get(); } while (width && isdigit(c)) { digit_seen++; *bufp++ = c; if (--width) - c = getc(stream); + c = _doscan_get(); } if (!digit_seen) { if (width && c != EOF) - ungetc(c, stream); + _doscan_unget(c); return inp_buf - 1; } } if (width && c != EOF) - ungetc(c, stream); + _doscan_unget(c); *bufp = '\0'; return bufp - 1; } @@ -199,7 +199,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 done = 0; /* number of items done */ int nrchars = 0; /* number of characters read */ @@ -226,15 +226,15 @@ int _doscan(register FILE* stream, const char* format, va_list ap) { while (isspace(*format)) format++; /* skip whitespace */ - ic = getc(stream); + ic = _doscan_get(); nrchars++; while (isspace(ic)) { - ic = getc(stream); + ic = _doscan_get(); nrchars++; } if (ic != EOF) - ungetc(ic, stream); + _doscan_unget(ic); nrchars--; } if (!*format) @@ -242,12 +242,12 @@ int _doscan(register FILE* stream, const char* format, va_list ap) if (*format != '%') { - ic = getc(stream); + ic = _doscan_get(); nrchars++; if (ic != *format++) { if (ic != EOF) - ungetc(ic, stream); + _doscan_unget(ic); nrchars--; break; /* error */ } @@ -256,7 +256,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) format++; if (*format == '%') { - ic = getc(stream); + ic = _doscan_get(); nrchars++; if (ic == '%') { @@ -299,7 +299,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) { do { - ic = getc(stream); + ic = _doscan_get(); nrchars++; } while (isspace(ic)); if (ic == EOF) @@ -307,7 +307,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) } else if (kind != 'n') { /* %c or %[ */ - ic = getc(stream); + ic = _doscan_get(); if (ic == EOF) break; /* outer while */ nrchars++; @@ -344,7 +344,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); if (str < inp_buf || (str == inp_buf && (*str == '-' @@ -385,7 +385,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) *str++ = (char)ic; if (--width) { - ic = getc(stream); + ic = _doscan_get(); nrchars++; } } @@ -393,7 +393,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) if (width) { if (ic != EOF) - ungetc(ic, stream); + _doscan_unget(ic); nrchars--; } break; @@ -411,7 +411,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) *str++ = (char)ic; if (--width) { - ic = getc(stream); + ic = _doscan_get(); nrchars++; } } @@ -421,7 +421,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) if (width) { if (ic != EOF) - ungetc(ic, stream); + _doscan_unget(ic); nrchars--; } break; @@ -468,7 +468,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) if (!*format || !(Xtable[ic] ^ reverse)) { if (ic != EOF) - ungetc(ic, stream); + _doscan_unget(ic); return done; } @@ -481,7 +481,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) *str++ = (char)ic; if (--width) { - ic = getc(stream); + ic = _doscan_get(); nrchars++; } } while (width && ic != EOF && (Xtable[ic] ^ reverse)); @@ -489,7 +489,7 @@ int _doscan(register FILE* stream, const char* format, va_list ap) if (width) { if (ic != EOF) - ungetc(ic, stream); + _doscan_unget(ic); nrchars--; } if (!(flags & FL_NOASSIGN)) @@ -508,7 +508,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); 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 81% rename from lang/cem/libcc.ansi/sys/stdio/fscanf.c rename to lang/cem/libcc.ansi/core/scanf/fscanf.c index b06d47253..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 @@ -15,9 +14,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/scanf.c b/lang/cem/libcc.ansi/core/scanf/scanf.c similarity index 81% rename from lang/cem/libcc.ansi/sys/stdio/scanf.c rename to lang/cem/libcc.ansi/core/scanf/scanf.c index d52788084..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 @@ -15,9 +14,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/core/scanf/sscanf.c b/lang/cem/libcc.ansi/core/scanf/sscanf.c new file mode 100644 index 000000000..eb972eeb2 --- /dev/null +++ b/lang/cem/libcc.ansi/core/scanf/sscanf.c @@ -0,0 +1,47 @@ +/* + * sscanf - read formatted output from a string + */ +/* $Id$ */ + +#include +#include +#include +#include "doscan.h" + +#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; + + va_start(ap, format); + + input_buffer = s; + _doscan_get = sscanf_getc; + _doscan_unget = sscanf_ungetc; + retval = _doscan(format, ap); + + va_end(ap); + + return retval; +} + +#endif diff --git a/lang/cem/libcc.ansi/core/scanf/vfscanf.c b/lang/cem/libcc.ansi/core/scanf/vfscanf.c new file mode 100644 index 000000000..c5a562049 --- /dev/null +++ b/lang/cem/libcc.ansi/core/scanf/vfscanf.c @@ -0,0 +1,32 @@ +/* + * vfscanf.c - read formatted input from stream + */ +/* $Id$ */ + +#include +#include +#include "doscan.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; + _doscan_get = vfscanf_getc; + _doscan_unget = vfscanf_ungetc; + return _doscan(format, ap); +} + +#endif 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/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..06a1ffcec --- /dev/null +++ b/lang/cem/libcc.ansi/headers/ack/emufile.h @@ -0,0 +1,67 @@ +#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 + +#if !defined BUFSIZ +#define BUFSIZ 1024 +#endif + +#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) +#define ACK_TMP_PREFIX "/tmp/tmp." + +extern int __fillbuf(FILE *_stream); +extern int __flushbuf(int _c, FILE *_stream); + +#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) + +#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 52f286f20..c6ddb8808 100644 --- a/lang/cem/libcc.ansi/headers/stdio.h +++ b/lang/cem/libcc.ansi/headers/stdio.h @@ -10,53 +10,21 @@ #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 #define SEEK_END 2 -#define stdin (&__stdin) -#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); extern int rename(const char *_old, const char *_new); extern FILE *tmpfile(void); @@ -69,6 +37,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 +45,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 +70,16 @@ 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 putchar(c) putc(c, stdout) -#define feof(p) (((p)->_flags & _IOEOF) != 0) -#define ferror(p) (((p)->_flags & _IOERR) != 0) -#define clearerr(p) ((p)->_flags &= ~(_IOERR|_IOEOF)) +/* Internal function used in several places which is approximately itoa(). */ +extern char *_i_compute(unsigned long val, int base, char *s, int nrdigits); -/* 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/fclose.c b/lang/cem/libcc.ansi/sys/stdio/fclose.c index 9a56b4cfe..a805a6e84 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fclose.c +++ b/lang/cem/libcc.ansi/sys/stdio/fclose.c @@ -6,9 +6,8 @@ #include #include #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..aff7d248e 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fdopen.c +++ b/lang/cem/libcc.ansi/sys/stdio/fdopen.c @@ -5,9 +5,8 @@ #include #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..7746ef0fb 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fflush.c +++ b/lang/cem/libcc.ansi/sys/stdio/fflush.c @@ -6,9 +6,8 @@ #include #include #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..09cc5cfc6 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fillbuf.c +++ b/lang/cem/libcc.ansi/sys/stdio/fillbuf.c @@ -6,9 +6,8 @@ #include #include #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..0cf271704 100644 --- a/lang/cem/libcc.ansi/sys/stdio/flushbuf.c +++ b/lang/cem/libcc.ansi/sys/stdio/flushbuf.c @@ -6,9 +6,8 @@ #include #include #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..f2189ee8f 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fopen.c +++ b/lang/cem/libcc.ansi/sys/stdio/fopen.c @@ -8,9 +8,8 @@ #include #include #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/freopen.c b/lang/cem/libcc.ansi/sys/stdio/freopen.c index 255e04cb6..846208420 100644 --- a/lang/cem/libcc.ansi/sys/stdio/freopen.c +++ b/lang/cem/libcc.ansi/sys/stdio/freopen.c @@ -7,9 +7,8 @@ #include #include #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/fseek.c b/lang/cem/libcc.ansi/sys/stdio/fseek.c index c1ecd5650..4ab5c10e3 100644 --- a/lang/cem/libcc.ansi/sys/stdio/fseek.c +++ b/lang/cem/libcc.ansi/sys/stdio/fseek.c @@ -6,9 +6,8 @@ #include #include #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..d69202bd3 100644 --- a/lang/cem/libcc.ansi/sys/stdio/ftell.c +++ b/lang/cem/libcc.ansi/sys/stdio/ftell.c @@ -6,9 +6,8 @@ #include #include #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/setbuf.c b/lang/cem/libcc.ansi/sys/stdio/setbuf.c index 5ac3e8ece..58a99ecad 100644 --- a/lang/cem/libcc.ansi/sys/stdio/setbuf.c +++ b/lang/cem/libcc.ansi/sys/stdio/setbuf.c @@ -4,9 +4,8 @@ /* $Id$ */ #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..439d12dd4 100644 --- a/lang/cem/libcc.ansi/sys/stdio/setvbuf.c +++ b/lang/cem/libcc.ansi/sys/stdio/setvbuf.c @@ -5,9 +5,8 @@ #include #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 deleted file mode 100644 index 4ee372faa..000000000 --- a/lang/cem/libcc.ansi/sys/stdio/snprintf.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * sprintf - print formatted output on an array - */ -/* $Id$ */ - -#include -#include -#include "loc_incl.h" - -#if ACKCONF_WANT_STDIO - -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); - - va_end(ap); - - return retval; -} - -#endif diff --git a/lang/cem/libcc.ansi/sys/stdio/sprintf.c b/lang/cem/libcc.ansi/sys/stdio/sprintf.c deleted file mode 100644 index 3a116c0f4..000000000 --- a/lang/cem/libcc.ansi/sys/stdio/sprintf.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * sprintf - print formatted output on an array - */ -/* $Id$ */ - -#include -#include -#include "loc_incl.h" - -#if ACKCONF_WANT_STDIO - -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); - - va_end(ap); - - return retval; -} - -#endif diff --git a/lang/cem/libcc.ansi/sys/stdio/sscanf.c b/lang/cem/libcc.ansi/sys/stdio/sscanf.c deleted file mode 100644 index bd39100bd..000000000 --- a/lang/cem/libcc.ansi/sys/stdio/sscanf.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * sscanf - read formatted output from a string - */ -/* $Id$ */ - -#include -#include -#include -#include "loc_incl.h" - -#if ACKCONF_WANT_STDIO - -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); - - 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 e50fd0d35..d6aa31825 100644 --- a/lang/cem/libcc.ansi/sys/stdio/tmpfile.c +++ b/lang/cem/libcc.ansi/sys/stdio/tmpfile.c @@ -7,13 +7,12 @@ #include #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO 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..2f40ce716 100644 --- a/lang/cem/libcc.ansi/sys/stdio/tmpnam.c +++ b/lang/cem/libcc.ansi/sys/stdio/tmpnam.c @@ -7,13 +7,12 @@ #include #include #include -#include "loc_incl.h" #if ACKCONF_WANT_STDIO 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..f00447e27 100644 --- a/lang/cem/libcc.ansi/sys/stdio/ungetc.c +++ b/lang/cem/libcc.ansi/sys/stdio/ungetc.c @@ -4,9 +4,8 @@ /* $Id$ */ #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 deleted file mode 100644 index 02b473dd6..000000000 --- a/lang/cem/libcc.ansi/sys/stdio/vfprintf.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * vfprintf - formatted output without ellipsis - */ -/* $Id$ */ - -#include -#include -#include "loc_incl.h" - -#if ACKCONF_WANT_STDIO - -int vfprintf(FILE* stream, const char* format, va_list arg) -{ - return _doprnt(format, arg, stream); -} - -#endif diff --git a/lang/cem/libcc.ansi/sys/stdio/vsnprintf.c b/lang/cem/libcc.ansi/sys/stdio/vsnprintf.c deleted file mode 100644 index d973b8066..000000000 --- a/lang/cem/libcc.ansi/sys/stdio/vsnprintf.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * vsprintf - print formatted output without ellipsis on an array - */ -/* $Id$ */ - -#include -#include -#include "loc_incl.h" - -#if ACKCONF_WANT_STDIO - -int vsnprintf(char* s, size_t len, const char* format, va_list arg) -{ - 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); - - return retval; -} - -#endif diff --git a/lang/cem/libcc.ansi/sys/stdio/vsprintf.c b/lang/cem/libcc.ansi/sys/stdio/vsprintf.c deleted file mode 100644 index 00065bec0..000000000 --- a/lang/cem/libcc.ansi/sys/stdio/vsprintf.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * vsprintf - print formatted output without ellipsis on an array - */ -/* $Id$ */ - -#include -#include -#include "loc_incl.h" - -#if ACKCONF_WANT_STDIO - -int vsprintf(char* s, const char* format, va_list arg) -{ - 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; -} - -#endif 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 ==================== diff --git a/plat/cpm/descr b/plat/cpm/descr index 2dea09e10..c023fc45c 100644 --- a/plat/cpm/descr +++ b/plat/cpm/descr @@ -75,6 +75,8 @@ name led (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ + {PLATFORMDIR}/libsys.a \ + {PLATFORMDIR}/libc.a \ {PLATFORMDIR}/libsys.a \ {PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libend.a) diff --git a/plat/cpm/include/ack/file.h b/plat/cpm/include/ack/file.h new file mode 100644 index 000000000..b60da6870 --- /dev/null +++ b/plat/cpm/include/ack/file.h @@ -0,0 +1,46 @@ +#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 + +#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; + FCB fcb; + char buffer[128]; +}; + +#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/ack/plat.h b/plat/cpm/include/ack/plat.h index 321dadf18..d6270fe5c 100644 --- a/plat/cpm/include/ack/plat.h +++ b/plat/cpm/include/ack/plat.h @@ -6,9 +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 +/* Processes? CP/M? Hahahaha... */ + +#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/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") diff --git a/plat/cpm/include/cpm.h b/plat/cpm/include/cpm.h index 3ea9f6e09..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,4 +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); +#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 new file mode 100644 index 000000000..96705c467 --- /dev/null +++ b/plat/cpm/libsys/fcb.c @@ -0,0 +1,65 @@ +#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)); + + { + const char* colon = strchr(filename, ':'); + if (colon) + { + c = *filename++; + if (isdigit(c)) + { + user = strtol(filename-1, &filename, 10); + c = *filename++; + } + c = toupper(c); + if (isalpha(c)) + { + fcb->dr = c - '@'; + c = *filename++; + } + + filename = colon + 1; + } + } + + /* Read filename part. */ + + filename = fill(&fcb->f[0], filename, 8); + filename = strchr(filename, '.'); + if (filename) + fill(&fcb->f[8], filename+1, 3); + + if (fcb->dr == 0) + fcb->dr = cpm_get_current_drive() + 1; + return user; +} + 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/lseek.c b/plat/cpm/libsys/lseek.c index ecbc4b520..9b8648b52 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 offset; } 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/read.c b/plat/cpm/libsys/read.c index b04a13ee5..c2a1abd61 100644 --- a/plat/cpm/libsys/read.c +++ b/plat/cpm/libsys/read.c @@ -3,47 +3,109 @@ * $Revision$ */ +#include #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; + uint8_t* src; - /* We're only allowed to read from fd 0, 1 or 2. */ - if ((fd < 0) || (fd > 2)) + __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; } - /* We need room for at least 1 char plus '\n'. */ - if (count < 2) + olduser = cpm_get_user(); + cpm_set_user(fcbe->user); + + if (U16(fcbe->fcb.r) >= fcbe->length) + goto done; + if (fcbe->offset || !SECTOR_ALIGNED(count)) { - errno = EINVAL; - return -1; + /* 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. */ + + 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. */ + + if (fcbe->offset == 128) + { + U16(fcbe->fcb.r)++; + fcbe->offset = 0; + } } - /* Make room to append '\n' later. */ - before_n = count > 255 ? 255 : count - 1; + while (count >= 128) + { + if (U16(fcbe->fcb.r) >= fcbe->length) + goto done; - /* Borrow 2 bytes of RAM before the buffer. */ - /* This might overwrite count!!! */ - save = ((short*)buffer)[-1]; + /* Read entire sectors directly into the destination buffer. */ - /* Read one line from the console. */ - ((unsigned char*)buffer)[-2] = before_n; - cpm_readline((uint8_t*)buffer - 2); - before_n = ((unsigned char*)buffer)[-1]; + cpm_set_dma(bbuffer); + if (cpm_read_random_safe(&fcbe->fcb) != 0) + goto eio; + count -= 128; + bbuffer += 128; + U16(fcbe->fcb.r)++; + } - ((char*)buffer)[before_n] = '\n'; /* Append '\n'. */ - ((short*)buffer)[-1] = save; /* Give back borrowed bytes. */ + if (count != 0) + { + if (U16(fcbe->fcb.r) >= fcbe->length) + goto done; - /* Echo '\n' to console. */ - cpm_printstring("\r\n$"); + /* There's some trailing data to read. */ - return (int)before_n + 1; + cpm_set_dma(__transfer_buffer); + if (cpm_read_random_safe(&fcbe->fcb) != 0) + goto eio; + + src = __transfer_buffer; + while (count != 0) + { + *bbuffer++ = *src++; + 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..eb2c89a0a 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,107 @@ 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)) + 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) { - 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)) + { + /* 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. */ + + dest = __transfer_buffer + fcbe->offset; + while ((count != 0) && (fcbe->offset != 128)) + { + *dest++ = *bbuffer++; + fcbe->offset++; + count--; + } + + /* 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; + + dest = __transfer_buffer; + while (count != 0) + { + *dest++ = *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; } 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