From 078b4ccf0b65d655d81e9f4fc6e1284773e1dda4 Mon Sep 17 00:00:00 2001 From: Pixel Date: Sat, 5 Feb 2011 13:05:37 -0800 Subject: Re-structured the *scanf and *printf functions. --- libc/LIB.status | 7 ++-- libc/Makefile | 1 + libc/include/stdio.h | 50 +++++++++++++++++++++++----- libc/src/xprintf.c | 94 +++------------------------------------------------- libc/src/xscanf.c | 4 +-- libc/src/yscanf.c | 55 ++++++++++++++++++++++++++++++ 6 files changed, 106 insertions(+), 105 deletions(-) create mode 100644 libc/src/yscanf.c diff --git a/libc/LIB.status b/libc/LIB.status index b2b573a..7ef0748 100644 --- a/libc/LIB.status +++ b/libc/LIB.status @@ -78,10 +78,9 @@ fdopen - missing setbuf - missing setvbuf - missing -*printf - ok (f, s, vf, v, vs, sn, vsn, vas, as) -*dprintf - missing -*scanf - missing (f, s, vf, v, vs) -*getc - missing +*printf - ok, v-versions inlined (f, s, d, sn, as + x) +*scanf - ok, v-versions inlined (f, s, d + x) +*getc - ok, inlined (f, .) getchar - missing *putc - missing putchar - missing diff --git a/libc/Makefile b/libc/Makefile index 18f3d54..15b75a6 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -33,6 +33,7 @@ src/malloc.c \ \ src/xprintf.c \ src/xscanf.c \ +src/yscanf.c \ include $(ROOTDIR)/target-rules.mk diff --git a/libc/include/stdio.h b/libc/include/stdio.h index ee6226f..a99fd42 100644 --- a/libc/include/stdio.h +++ b/libc/include/stdio.h @@ -14,18 +14,37 @@ struct _FILE { }; typedef struct _FILE FILE; +extern FILE * stdin, * stdout, * stderr; -int printf(const char * format, ...); -int fprintf(FILE *stream, const char * format, ...); -int sprintf(char * str, const char * format, ...); -int snprintf(char * str, size_t size, const char * format, ...); -int asprintf(char ** strp, const char * format, ...); - -int vprintf(const char * format, va_list ap); -int vfprintf(FILE *stream, const char * format, va_list ap); +int vdprintf(int fd, const char * format, va_list ap); int vsprintf(char * str, const char * format, va_list ap); int vsnprintf(char * str, size_t size, const char * format, va_list ap); int vasprintf(char ** strp, const char * format, va_list ap); +int vxprintf(void (*func)(const char *, int, void *), void * arg, const char * format, va_list ap); +static inline int vfprintf(FILE * stream, const char * format, va_list ap) { return vdprintf(stream->fd, format, ap); } +static inline int vprintf(const char * format, va_list ap) { return vfprintf(stdout, format, ap); } + +static inline int dprintf(int fd, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vdprintf(fd, format, ap); va_end(ap); return r; } +static inline int sprintf(char * str, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vsprintf(str, format, ap); va_end(ap); return r; } +static inline int snprintf(char * str, size_t size, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vsnprintf(str, size, format, ap); va_end(ap); return r; } +static inline int asprintf(char ** strp, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vasprintf(strp, format, ap); va_end(ap); return r; } +static inline int xprintf(void (*func)(const char *, int, void *), void * arg, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vxprintf(func, arg, format, ap); va_end(ap); return r; } +static inline int fprintf(FILE * stream, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vfprintf(stream, format, ap); va_end(ap); return r; } +static inline int printf(const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vprintf(format, ap); va_end(ap); return r; } + +int vdscanf(int fd, const char * format, va_list ap); +int vsscanf(const char * str, const char * format, va_list ap); +int vxscanf(int (*xgetc)(void *), void (*xungetc)(void *, int), void * opaque, const char * format, va_list args); +static inline int vfscanf(FILE * stream, const char * format, va_list ap) { return vdscanf(stream->fd, format, ap); } +static inline int vscanf(const char * format, va_list ap) { return vfscanf(stdin, format, ap); } + +static inline int dscanf(int fd, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vdscanf(fd, format, ap); va_end(ap); return r; } +static inline int sscanf(const char * str, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vsscanf(str, format, ap); va_end(ap); return r; } +static inline int xscanf(int (*xgetc)(void *), void (*xungetc)(void *, int), void * opaque, const char *format, ...) { va_list ap; int r; va_start(ap, format); r = vxscanf(xgetc, xungetc, opaque, format, ap); va_end(ap); return r; } +static inline int fscanf(FILE * stream, const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vfscanf(stream, format, ap); va_end(ap); return r; } +static inline int scanf(const char * format, ...) { va_list ap; int r; va_start(ap, format); r = vscanf(format, ap); va_end(ap); return r; } + + void __sinit(struct _reent *); @@ -150,6 +169,19 @@ static inline size_t fwrite(const void * _ptr, size_t size, size_t nmemb, FILE * return nmemb; } -extern FILE * stdin, * stdout, * stderr; +static inline int fgetc(FILE * stream) { + uint8_t v; + + if (!stream) { + _impure_ptr->_errno = EINVAL; + return -1; + } + + if (read(stream->fd, &v, 1) != 1) + return EOF; + return v; +} + +static inline int getc() { return fgetc(stdin); } #endif diff --git a/libc/src/xprintf.c b/libc/src/xprintf.c index 30659f7..269d77c 100644 --- a/libc/src/xprintf.c +++ b/libc/src/xprintf.c @@ -213,7 +213,7 @@ static int getdigit(long double *val, int *cnt){ ** seems to make a big difference in determining how fast this beast ** will run. */ -static int vxprintf(func,arg,format,ap) +int vxprintf(func,arg,format,ap) void (*func)(const char*,int,void*); void *arg; const char *format; @@ -664,20 +664,6 @@ static int vxprintf(func,arg,format,ap) return errorflag ? -1 : count; } /* End of function */ -/* -** This non-standard function is still occasionally useful.... -*/ -int xprintf( - void (*func)(char*,int,void*), - void *arg, - const char *format, - ... -){ - va_list ap; - va_start(ap,format); - return vxprintf(func,arg,format,ap); -} - /* ** Now for string-print, also as found in any standard library. ** Add to this the snprint function which stops added characters @@ -713,19 +699,6 @@ static void sout(txt,amt,arg) ((struct s_strargument*)arg)->next = head; } -int sprintf(char *buf, const char *fmt, ...){ - int rc; - va_list ap; - struct s_strargument arg; - - va_start(ap,fmt); - arg.next = buf; - arg.last = 0; - *arg.next = 0; - rc = vxprintf(sout,&arg,fmt,ap); - va_end(ap); - return rc; -} int vsprintf(char *buf,const char *fmt,va_list ap){ struct s_strargument arg; arg.next = buf; @@ -733,19 +706,6 @@ int vsprintf(char *buf,const char *fmt,va_list ap){ *buf = 0; return vxprintf(sout,&arg,fmt,ap); } -int snprintf(char *buf, size_t n, const char *fmt, ...){ - int rc; - va_list ap; - struct s_strargument arg; - - va_start(ap,fmt); - arg.next = buf; - arg.last = &arg.next[n-1]; - *arg.next = 0; - rc = vxprintf(sout,&arg,fmt,ap); - va_end(ap); - return rc; -} int vsnprintf(char *buf, size_t n, const char *fmt, va_list ap){ struct s_strargument arg; arg.next = buf; @@ -799,31 +759,6 @@ static void mout(zNewText,nNewChar,arg) ** We changed the name to TclMPrint() to conform with the Tcl private ** routine naming conventions. */ -int asprintf(char ** out, const char *zFormat, ...){ - va_list ap; - struct sgMprintf sMprintf; - char *zNew; - char zBuf[200]; - int r; - - va_start(ap,zFormat); - sMprintf.nChar = 0; - sMprintf.nAlloc = sizeof(zBuf); - sMprintf.zText = zBuf; - sMprintf.zBase = zBuf; - r = vxprintf(mout,&sMprintf,zFormat,ap); - va_end(ap); - if( sMprintf.zText==sMprintf.zBase ){ - zNew = malloc( sMprintf.nChar+1 ); - if( zNew ) strcpy(zNew,zBuf); - }else{ - zNew = realloc(sMprintf.zText,sMprintf.nChar+1); - } - - *out = zNew; - - return r; -} /* This is the varargs version of mprintf. ** @@ -860,31 +795,10 @@ static void fout(zNewText,nNewChar,arg) int nNewChar; void *arg; { - fwrite(zNewText,1,nNewChar,(FILE*)arg); + write(*(int*)arg,zNewText,nNewChar); } /* The public interface routines */ -int fprintf(FILE *pOut, const char *zFormat, ...){ - va_list ap; - int retc; - - va_start(ap,zFormat); - retc = vxprintf(fout,pOut,zFormat,ap); - va_end(ap); - return retc; -} -int vfprintf(FILE *pOut, const char *zFormat, va_list ap){ - return vxprintf(fout,pOut,zFormat,ap); -} -int printf(const char *zFormat, ...){ - va_list ap; - int retc; - - va_start(ap,zFormat); - retc = vxprintf(fout,stdout,zFormat,ap); - va_end(ap); - return retc; -} -int vprintf(const char *zFormat, va_list ap){ - return vxprintf(fout,stdout,zFormat,ap); +int vdprintf(int fd, const char *zFormat, va_list ap){ + return vxprintf(fout,&fd,zFormat,ap); } diff --git a/libc/src/xscanf.c b/libc/src/xscanf.c index ad6f190..d121722 100755 --- a/libc/src/xscanf.c +++ b/libc/src/xscanf.c @@ -11,7 +11,7 @@ * VAL(a) leads to 1 if a is true and valid */ #define NEXT(c) ((c)=xgetc(opaque),size++,incount++) -#define PREV(c) do{if((c)!=EOF)xungetc((c),opaque);size--;incount--;}while(0) +#define PREV(c) do{if((c)!=EOF)xungetc(opaque,(c));size--;incount--;}while(0) #define VAL(a) ((a)&&size<=width) #ifdef NOFLOATINGPOINT @@ -30,7 +30,7 @@ static const unsigned char undef[3][sizeof(double)]= /* Undefined numeric values }; #endif -int vxscanf(int (*xgetc)(void *),void (*xungetc)(int,void*),void *opaque,const char *format,va_list args) +int vxscanf(int (*xgetc)(void *),void (*xungetc)(void*,int),void *opaque,const char *format,va_list args) { size_t blocks=0,incount=0; int c=0; diff --git a/libc/src/yscanf.c b/libc/src/yscanf.c new file mode 100644 index 0000000..3d2a488 --- /dev/null +++ b/libc/src/yscanf.c @@ -0,0 +1,55 @@ +#include "stdio.h" + +struct opaque_t { + union { + const char * p; + int fd; + }; + uint8_t bsize; + char backbuffer[3]; +}; + +static int str_getc(void * _opaque) { + struct opaque_t * opaque = (struct opaque_t *) _opaque; + int r; + + if (opaque->bsize) + return opaque->backbuffer[--(opaque->bsize)]; + + r = *(opaque->p++); + + return r ? r : EOF; +} + +static int file_getc(void * _opaque) { + struct opaque_t * opaque = (struct opaque_t *) _opaque; + uint8_t v; + + if (opaque->bsize) + return opaque->backbuffer[--(opaque->bsize)]; + + if (read(opaque->fd, &v, 1) != 1) + return EOF; + return v; +} + +static void scanf_ungetc(void * _opaque, int c) { + struct opaque_t * opaque = (struct opaque_t *) _opaque; + + if (opaque->bsize < sizeof(opaque->backbuffer)) + opaque->backbuffer[opaque->bsize++] = c; +} + +int vsscanf(const char * str, const char * format, va_list ap) { + struct opaque_t opaque; + opaque.p = str; + opaque.bsize = 0; + return vxscanf(str_getc, scanf_ungetc, &opaque, format, ap); +} + +int vdscanf(int fd, const char * format, va_list ap) { + struct opaque_t opaque; + opaque.fd = fd; + opaque.bsize = 0; + return vxscanf(file_getc, scanf_ungetc, &opaque, format, ap); +} -- cgit v1.2.3