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.
This commit is contained in:
David Given 2019-06-15 13:07:10 +02:00
parent 3798673afe
commit 9109d7af7f
37 changed files with 273 additions and 186 deletions

View file

@ -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

View file

@ -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

View file

@ -10,30 +10,14 @@
#define _STDIO_H
#include <stddef.h>
#include <stdarg.h>
#include <ack/config.h>
/*
* 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 <ack/emufile.h>
#else
#include <ack/file.h>
#endif
#endif /* _STDIO_H */

View file

@ -5,19 +5,19 @@
#include <stdio.h>
#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,
};

View file

@ -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;
}

View file

@ -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

View file

@ -8,7 +8,7 @@
#include <unistd.h>
#include "loc_incl.h"
#if ACKCONF_WANT_STDIO
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
int fclose(FILE* fp)
{

View file

@ -7,7 +7,7 @@
#include <stdlib.h>
#include "../stdio/loc_incl.h"
#if ACKCONF_WANT_STDIO
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
FILE* fdopen(int fd, const char* mode)
{

View file

@ -8,7 +8,7 @@
#include <unistd.h>
#include "loc_incl.h"
#if ACKCONF_WANT_STDIO
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
int fflush(FILE* stream)
{

View file

@ -5,7 +5,7 @@
#include <stdio.h>
#if ACKCONF_WANT_STDIO
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
int(fileno)(FILE* stream)
{

View file

@ -8,7 +8,7 @@
#include <unistd.h>
#include "loc_incl.h"
#if ACKCONF_WANT_STDIO
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
int __fillbuf(register FILE* stream)
{

View file

@ -8,7 +8,7 @@
#include <unistd.h>
#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)

View file

@ -10,7 +10,7 @@
#include <unistd.h>
#include "loc_incl.h"
#if ACKCONF_WANT_STDIO
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
#define PMODE 0666

View file

@ -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;

View file

@ -9,7 +9,7 @@
#include <unistd.h>
#include "loc_incl.h"
#if ACKCONF_WANT_STDIO
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
#define PMODE 0666

View file

@ -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;

View file

@ -8,7 +8,7 @@
#include <unistd.h>
#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)
{

View file

@ -8,7 +8,7 @@
#include <unistd.h>
#include "loc_incl.h"
#if ACKCONF_WANT_STDIO
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
long ftell(FILE* stream)
{

View file

@ -10,8 +10,8 @@
#define io_testflag(p,x) ((p)->_flags & (x))
#include <stdarg.h>
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);

View file

@ -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;

View file

@ -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;

View file

@ -6,7 +6,7 @@
#include <stdio.h>
#include "loc_incl.h"
#if ACKCONF_WANT_STDIO
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
void setbuf(register FILE* stream, char* buf)
{

View file

@ -7,7 +7,7 @@
#include <stdlib.h>
#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)
{

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -6,7 +6,7 @@
#include <stdio.h>
#include "loc_incl.h"
#if ACKCONF_WANT_STDIO
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
int ungetc(int ch, FILE* stream)
{

View file

@ -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

View file

@ -0,0 +1,30 @@
/*
* vfscanf.c - read formatted input from stream
*/
/* $Id$ */
#include <stdio.h>
#include <stdarg.h>
#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

View file

@ -11,7 +11,7 @@
int vprintf(const char* format, va_list arg)
{
return _doprnt(format, arg, stdout);
return vfprintf(stdout, format, arg);
}
#endif

View file

@ -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;
}

View file

@ -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

View file

@ -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 <cpm.h>
struct FILE
{
uint8_t user;
FCB fcb;
char buffer[128];
};
#define FOPEN_MAX 8
extern FILE* __files[FOPEN_MAX];
#endif

View file

@ -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

View file

@ -9,6 +9,7 @@ local function addheader(h)
end
addheader("ack/plat.h")
addheader("ack/file.h")
addheader("sys/types.h")
addheader("cpm.h")