Merge pull request #197 from davidgiven/dtrg-cpm
Overhaul the CP/M libsys.
This commit is contained in:
commit
585e035c14
|
@ -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 }
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#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;
|
|
@ -1,29 +1,5 @@
|
|||
/*
|
||||
* loc_incl.h - local include file for stdio library
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ack/config.h>
|
||||
|
||||
#define fileno(p) ((p)->_fd)
|
||||
#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);
|
||||
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
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "loc_incl.h"
|
||||
#include "doprnt.h"
|
||||
|
||||
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_STDIO_FLOAT
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#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;
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include "loc_incl.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if ACKCONF_WANT_STDIO
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#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;
|
23
lang/cem/libcc.ansi/core/printf/snprintf.c
Normal file
23
lang/cem/libcc.ansi/core/printf/snprintf.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* sprintf - print formatted output on an array
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#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
|
23
lang/cem/libcc.ansi/core/printf/sprintf.c
Normal file
23
lang/cem/libcc.ansi/core/printf/sprintf.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* sprintf - print formatted output on an array
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#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
|
27
lang/cem/libcc.ansi/core/printf/vfprintf.c
Normal file
27
lang/cem/libcc.ansi/core/printf/vfprintf.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* vfprintf - formatted output without ellipsis
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#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
|
|
@ -5,13 +5,12 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#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
|
38
lang/cem/libcc.ansi/core/printf/vsnprintf.c
Normal file
38
lang/cem/libcc.ansi/core/printf/vsnprintf.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* vsprintf - print formatted output without ellipsis on an array
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#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
|
16
lang/cem/libcc.ansi/core/printf/vsprintf.c
Normal file
16
lang/cem/libcc.ansi/core/printf/vsprintf.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* vsprintf - print formatted output without ellipsis on an array
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if ACKCONF_WANT_STDIO
|
||||
|
||||
int vsprintf(char* s, const char* format, va_list ap)
|
||||
{
|
||||
return vsnprintf(s, 32767, format, ap);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -7,7 +7,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#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
|
23
lang/cem/libcc.ansi/core/scanf/doscan.h
Normal file
23
lang/cem/libcc.ansi/core/scanf/doscan.h
Normal file
|
@ -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
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#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;
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#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;
|
47
lang/cem/libcc.ansi/core/scanf/sscanf.c
Normal file
47
lang/cem/libcc.ansi/core/scanf/sscanf.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* sscanf - read formatted output from a string
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#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
|
32
lang/cem/libcc.ansi/core/scanf/vfscanf.c
Normal file
32
lang/cem/libcc.ansi/core/scanf/vfscanf.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* vfscanf.c - read formatted input from stream
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#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
|
|
@ -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
|
||||
|
|
67
lang/cem/libcc.ansi/headers/ack/emufile.h
Normal file
67
lang/cem/libcc.ansi/headers/ack/emufile.h
Normal file
|
@ -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
|
|
@ -10,53 +10,21 @@
|
|||
#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
|
||||
#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 <ack/emufile.h>
|
||||
#else
|
||||
#include <ack/file.h>
|
||||
#endif
|
||||
|
||||
#endif /* _STDIO_H */
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -6,9 +6,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "loc_incl.h"
|
||||
|
||||
#if ACKCONF_WANT_STDIO
|
||||
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
|
||||
|
||||
int fclose(FILE* fp)
|
||||
{
|
||||
|
|
|
@ -5,9 +5,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#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)
|
||||
{
|
||||
|
|
|
@ -6,9 +6,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "loc_incl.h"
|
||||
|
||||
#if ACKCONF_WANT_STDIO
|
||||
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
|
||||
|
||||
int fflush(FILE* stream)
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#if ACKCONF_WANT_STDIO
|
||||
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
|
||||
|
||||
int(fileno)(FILE* stream)
|
||||
{
|
||||
|
|
|
@ -6,9 +6,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "loc_incl.h"
|
||||
|
||||
#if ACKCONF_WANT_STDIO
|
||||
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
|
||||
|
||||
int __fillbuf(register FILE* stream)
|
||||
{
|
||||
|
|
|
@ -6,9 +6,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#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)
|
||||
|
|
|
@ -8,9 +8,8 @@
|
|||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "loc_incl.h"
|
||||
|
||||
#if ACKCONF_WANT_STDIO
|
||||
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
|
||||
|
||||
#define PMODE 0666
|
||||
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "loc_incl.h"
|
||||
|
||||
#if ACKCONF_WANT_STDIO
|
||||
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
|
||||
|
||||
#define PMODE 0666
|
||||
|
||||
|
|
|
@ -6,9 +6,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#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)
|
||||
{
|
||||
|
|
|
@ -6,9 +6,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "loc_incl.h"
|
||||
|
||||
#if ACKCONF_WANT_STDIO
|
||||
#if ACKCONF_WANT_STDIO && ACKCONF_WANT_EMULATED_FILE
|
||||
|
||||
long ftell(FILE* stream)
|
||||
{
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
/* $Id$ */
|
||||
|
||||
#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)
|
||||
{
|
||||
|
|
|
@ -5,9 +5,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#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)
|
||||
{
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* sprintf - print formatted output on an array
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#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
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* sprintf - print formatted output on an array
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#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
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* sscanf - read formatted output from a string
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#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
|
|
@ -7,13 +7,12 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
|
||||
|
|
|
@ -7,13 +7,12 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
/* $Id$ */
|
||||
|
||||
#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)
|
||||
{
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* vfprintf - formatted output without ellipsis
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "loc_incl.h"
|
||||
|
||||
#if ACKCONF_WANT_STDIO
|
||||
|
||||
int vfprintf(FILE* stream, const char* format, va_list arg)
|
||||
{
|
||||
return _doprnt(format, arg, stream);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* vsprintf - print formatted output without ellipsis on an array
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#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
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* vsprintf - print formatted output without ellipsis on an array
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#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
|
|
@ -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
|
||||
====================
|
||||
|
|
|
@ -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)
|
||||
|
|
46
plat/cpm/include/ack/file.h
Normal file
46
plat/cpm/include/ack/file.h
Normal file
|
@ -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 <cpm.h>
|
||||
|
||||
#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
|
|
@ -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
|
||||
|
|
|
@ -9,6 +9,7 @@ local function addheader(h)
|
|||
end
|
||||
|
||||
addheader("ack/plat.h")
|
||||
addheader("ack/file.h")
|
||||
addheader("sys/types.h")
|
||||
addheader("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
|
||||
|
|
|
@ -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",
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,31 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <cpm.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
10
plat/cpm/libsys/cpm_read_random_safe.c
Normal file
10
plat/cpm/libsys/cpm_read_random_safe.c
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include <string.h>
|
||||
#include <cpm.h>
|
||||
|
||||
uint8_t cpm_read_random_safe(FCB* fcb)
|
||||
{
|
||||
uint8_t r = cpm_read_random(fcb);
|
||||
if ((r == 1) || (r == 4))
|
||||
r = 0;
|
||||
return r;
|
||||
}
|
22
plat/cpm/libsys/cpmsys.h
Normal file
22
plat/cpm/libsys/cpmsys.h
Normal file
|
@ -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
|
65
plat/cpm/libsys/fcb.c
Normal file
65
plat/cpm/libsys/fcb.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cpm.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#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;
|
||||
}
|
||||
|
19
plat/cpm/libsys/fd.c
Normal file
19
plat/cpm/libsys/fd.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <cpm.h>
|
||||
#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;
|
||||
}
|
||||
}
|
|
@ -1,14 +1,28 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <cpm.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,61 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <cpm.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,47 +3,109 @@
|
|||
* $Revision$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <cpm.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <cpm.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -4,5 +4,6 @@ plat_testsuite {
|
|||
name = "tests",
|
||||
plat = "cpm",
|
||||
method = "plat/cpm/emu+emu",
|
||||
skipsets = {"floats"},
|
||||
skipsets = {"floats"},
|
||||
tests = { "./*.c" },
|
||||
}
|
||||
|
|
66
plat/cpm/tests/parsefcb_c.c
Normal file
66
plat/cpm/tests/parsefcb_c.c
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include <stdio.h>
|
||||
#include <cpm.h>
|
||||
#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<sizeof(tests)/sizeof(*tests); i++)
|
||||
do_test(i, &tests[i]);
|
||||
|
||||
if (failed)
|
||||
fail(0);
|
||||
finished();
|
||||
}
|
|
@ -6,11 +6,12 @@ definerule("plat_testsuite",
|
|||
method = { type="string" },
|
||||
sets = { type="table", default={"core", "b", "bugs", "m2", "floats"}},
|
||||
skipsets = { type="table", default={}},
|
||||
tests = { type="targets", default={} },
|
||||
},
|
||||
function(e)
|
||||
-- Remember this is executed from the caller's directory; local
|
||||
-- target names will resolve there.
|
||||
local testfiles = {}
|
||||
local testfiles = filenamesof(e.tests)
|
||||
local skipsets = {}
|
||||
for _, set in ipairs(e.skipsets) do
|
||||
skipsets[set] = true
|
||||
|
|
Loading…
Reference in a new issue