From 6d269edda0f49741484c1da6c71d24c031abc9ce Mon Sep 17 00:00:00 2001 From: Robert de Bath Date: Tue, 20 Mar 2001 18:55:18 +0100 Subject: Import Dev86src-0.15.5.tar.gz --- libc/Config.dflt | 4 +- libc/Makefile | 2 +- libc/malloc/Config | 1 + libc/malloc/Makefile | 22 ++ libc/malloc/README | 9 + libc/malloc/malloc.c | 546 ++++++++++++++++++++++++++++ libc/malloc/malloc.h | 30 ++ libc/malloc1/Config | 1 - libc/malloc1/Makefile | 22 -- libc/malloc1/README | 9 - libc/malloc1/malloc.c | 546 ---------------------------- libc/malloc1/malloc.h | 30 -- libc/malloc2/Config | 1 - libc/malloc2/Makefile | 14 - libc/malloc2/README | 19 - libc/malloc2/malloc.c | 126 ------- libc/malloc2/malloc.h | 21 -- libc/malloc2/stack.c | 10 - libc/stdio/Config | 4 + libc/stdio/Makefile | 49 +++ libc/stdio/printf.c | 380 ++++++++++++++++++++ libc/stdio/scanf.c | 536 ++++++++++++++++++++++++++++ libc/stdio/stdio.c | 866 +++++++++++++++++++++++++++++++++++++++++++++ libc/stdio/stdio.h | 129 +++++++ libc/stdio1/BUGS | 15 - libc/stdio1/Config | 3 - libc/stdio1/NOTICE | 17 - libc/stdio1/README | 8 - libc/stdio1/TODO | 33 -- libc/stdio1/__ffillbuf.c | 55 --- libc/stdio1/__stdio_init.c | 66 ---- libc/stdio1/fclose.c | 41 --- libc/stdio1/fcntl.h | 72 ---- libc/stdio1/fflush.c | 36 -- libc/stdio1/fgetc.c | 39 -- libc/stdio1/fgets.c | 50 --- libc/stdio1/fopen.c | 80 ----- libc/stdio1/fputc.c | 53 --- libc/stdio1/fputs.c | 32 -- libc/stdio1/idealgetline.c | 67 ---- libc/stdio1/makefile | 36 -- libc/stdio1/old_printf.c | 230 ------------ libc/stdio1/printf.c | 649 --------------------------------- libc/stdio1/puts.c | 26 -- libc/stdio1/scanf.c | 151 -------- libc/stdio1/stdio.h | 135 ------- libc/stdio1/test.sh | 12 - libc/stdio2/Config | 4 - libc/stdio2/Makefile | 49 --- libc/stdio2/printf.c | 380 -------------------- libc/stdio2/scanf.c | 536 ---------------------------- libc/stdio2/stdio.c | 866 --------------------------------------------- libc/stdio2/stdio.h | 129 ------- 53 files changed, 2575 insertions(+), 4672 deletions(-) create mode 100644 libc/malloc/Config create mode 100644 libc/malloc/Makefile create mode 100644 libc/malloc/README create mode 100644 libc/malloc/malloc.c create mode 100644 libc/malloc/malloc.h delete mode 100644 libc/malloc1/Config delete mode 100644 libc/malloc1/Makefile delete mode 100644 libc/malloc1/README delete mode 100644 libc/malloc1/malloc.c delete mode 100644 libc/malloc1/malloc.h delete mode 100644 libc/malloc2/Config delete mode 100644 libc/malloc2/Makefile delete mode 100644 libc/malloc2/README delete mode 100644 libc/malloc2/malloc.c delete mode 100644 libc/malloc2/malloc.h delete mode 100644 libc/malloc2/stack.c create mode 100644 libc/stdio/Config create mode 100644 libc/stdio/Makefile create mode 100644 libc/stdio/printf.c create mode 100644 libc/stdio/scanf.c create mode 100644 libc/stdio/stdio.c create mode 100644 libc/stdio/stdio.h delete mode 100644 libc/stdio1/BUGS delete mode 100644 libc/stdio1/Config delete mode 100644 libc/stdio1/NOTICE delete mode 100644 libc/stdio1/README delete mode 100644 libc/stdio1/TODO delete mode 100644 libc/stdio1/__ffillbuf.c delete mode 100644 libc/stdio1/__stdio_init.c delete mode 100644 libc/stdio1/fclose.c delete mode 100644 libc/stdio1/fcntl.h delete mode 100644 libc/stdio1/fflush.c delete mode 100644 libc/stdio1/fgetc.c delete mode 100644 libc/stdio1/fgets.c delete mode 100644 libc/stdio1/fopen.c delete mode 100644 libc/stdio1/fputc.c delete mode 100644 libc/stdio1/fputs.c delete mode 100644 libc/stdio1/idealgetline.c delete mode 100644 libc/stdio1/makefile delete mode 100644 libc/stdio1/old_printf.c delete mode 100644 libc/stdio1/printf.c delete mode 100644 libc/stdio1/puts.c delete mode 100644 libc/stdio1/scanf.c delete mode 100644 libc/stdio1/stdio.h delete mode 100755 libc/stdio1/test.sh delete mode 100644 libc/stdio2/Config delete mode 100644 libc/stdio2/Makefile delete mode 100644 libc/stdio2/printf.c delete mode 100644 libc/stdio2/scanf.c delete mode 100644 libc/stdio2/stdio.c delete mode 100644 libc/stdio2/stdio.h (limited to 'libc') diff --git a/libc/Config.dflt b/libc/Config.dflt index 7444bae..1927f1e 100644 --- a/libc/Config.dflt +++ b/libc/Config.dflt @@ -5,11 +5,11 @@ getent:+: gtermcap:+: i386fp:+: i386sys:+: -malloc1:+: +malloc:+: misc:+: msdos:+: regexp:+: -stdio2:+: +stdio:+: string:+: syscall:+: termios:+: diff --git a/libc/Makefile b/libc/Makefile index 41865d6..408d92c 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -11,7 +11,7 @@ endif VERMAJOR=0 VERMINOR=15 -VERPATCH=4 +VERPATCH=5 VER=$(VERMAJOR).$(VERMINOR).$(VERPATCH) CC=bcc diff --git a/libc/malloc/Config b/libc/malloc/Config new file mode 100644 index 0000000..45cf008 --- /dev/null +++ b/libc/malloc/Config @@ -0,0 +1 @@ +malloc: Malloc routines diff --git a/libc/malloc/Makefile b/libc/malloc/Makefile new file mode 100644 index 0000000..e762582 --- /dev/null +++ b/libc/malloc/Makefile @@ -0,0 +1,22 @@ +# Copyright (C) 1995,1996 Robert de Bath +# This file is part of the Linux-8086 C library and is distributed +# under the GNU Library General Public License. + +ASRC=malloc.c +AOBJ=malloc.o alloca.o free.o calloc.o realloc.o + +CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) + +all: $(LIBC)($(AOBJ)) + @$(RM) $(OBJ) + +$(LIBC)($(AOBJ)): $(ASRC) + $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o + $(AR) $(ARFLAGS) $@ $*.o + +clean: + rm -f *.o libc.a + +transfer: + -@rm ../include/malloc.h + cp -p malloc.h ../include/. diff --git a/libc/malloc/README b/libc/malloc/README new file mode 100644 index 0000000..95f5928 --- /dev/null +++ b/libc/malloc/README @@ -0,0 +1,9 @@ +Copyright (C) 1995,1996 Robert de Bath +This file is part of the Linux-8086 C library and is distributed +under the GNU Library General Public License. + +This is a combined alloca/malloc package. It uses a classic algorithm +and so may be seen to be quite slow compared to more modern routines +with 'nasty' distributions of allocation. + +-Robert diff --git a/libc/malloc/malloc.c b/libc/malloc/malloc.c new file mode 100644 index 0000000..86ffd42 --- /dev/null +++ b/libc/malloc/malloc.c @@ -0,0 +1,546 @@ +/* Copyright (C) 1995,1996 Robert de Bath + * This file is part of the Linux-8086 C library and is distributed + * under the GNU Library General Public License. + */ + +/* + * This is a combined alloca/malloc package. It uses a classic algorithm + * and so may be seen to be quite slow compared to more modern routines + * with 'nasty' distributions. + */ + +#include +#include + +#define MCHUNK 2048 /* Allocation unit in 'mem' elements */ +#define XLAZY_FREE /* If set frees can be infinitly defered */ +#define XMINALLOC 32 /* Smallest chunk to alloc in 'mem's */ +#define XVERBOSE /* Lots of noise, debuging ? */ + +#undef malloc +#define MAX_INT ((int)(((unsigned)-1)>>1)) + +#ifdef VERBOSE +#define noise __noise +#else +#define noise(y,x) +#endif + +typedef union mem_cell +{ + union mem_cell *next; /* A pointer to the next mem */ + unsigned int size; /* An int >= sizeof pointer */ + char *depth; /* For the alloca hack */ +} +mem; + +#define m_size(p) ((p) [0].size) /* For malloc */ +#define m_next(p) ((p) [1].next) /* For malloc and alloca */ +#define m_deep(p) ((p) [0].depth) /* For alloca */ + +extern void *__mini_malloc __P ((size_t)); +extern void *(*__alloca_alloc) __P ((size_t)); +extern mem *__freed_list; + +#ifdef L_free +/* Start the alloca with just the dumb version of malloc */ + +void *(*__alloca_alloc) __P ((size_t)) = __mini_malloc; +mem *__freed_list = 0; + +#ifdef VERBOSE +/* NB: Careful here, stdio may use malloc - so we can't */ +static +phex(val) +{ + static char hex[] = "0123456789ABCDEF"; + int i; + for (i = sizeof(int)*8-4; i >= 0; i -= 4) + write(2, hex + ((val >> i) & 0xF), 1); +} + +noise(y, x) +char *y; +mem *x; +{ + write(2, "Malloc ", 7); + phex(x); + write(2, " sz ", 4); + if(x) phex(m_size(x)); else phex(0); + write(2, " nxt ", 5); + if(x) phex(m_next(x)); else phex(0); + write(2, " is ", 4); + write(2, y, strlen(y)); + write(2, "\n", 1); +} +#endif + +#endif + +#ifdef L_alloca +static mem *alloca_stack = 0; + +void * +alloca(size) +size_t size; +{ + auto char probe; /* Probes stack depth: */ + register mem *hp; + + /* + * Reclaim garbage, defined as all alloca'd storage that was allocated + * from deeper in the stack than currently. + */ + + for (hp = alloca_stack; hp != 0;) + if (m_deep(hp) < &probe) + { + register mem *np = m_next(hp); + free((void *) hp); /* Collect garbage. */ + hp = np; /* -> next header. */ + } + else + break; /* Rest are not deeper. */ + + alloca_stack = hp; /* -> last valid storage. */ + if (size == 0) + return 0; /* No allocation required. */ + + hp = (mem *) (*__alloca_alloc) (sizeof(mem)*2 + size); + if (hp == 0) + return hp; + + m_next(hp) = alloca_stack; + m_deep(hp) = &probe; + alloca_stack = hp; + + /* User storage begins just after header. */ + return (void *) (hp + 2); +} +#endif /* L_alloca */ + +#ifdef L_free +void +free(ptr) +void *ptr; +{ + register mem *top; + register mem *chk = (mem *) ptr; + + if (chk == 0) + return; /* free(NULL) - be nice */ + chk--; + + try_this:; + top = (mem *) sbrk(0); + if (chk + m_size(chk) == top) + { + noise("FREE brk", chk); + brk(top-m_size(chk)); + /* + * Adding this code allow free to release blocks in any order; they + * can still only be allocated from the top of the heap tho. + */ +#ifdef __MINI_MALLOC__ + if (__alloca_alloc == __mini_malloc && __freed_list) + { + mem *prev, *curr; + chk = __freed_list; + __freed_list = m_next(__freed_list); + goto try_this; + } +#endif + } + else + { /* Nope, not sure where this goes, leave + * it for malloc to deal with */ +#ifdef __MINI_MALLOC__ + if( __freed_list || chk > __freed_list ) + { m_next(chk) = __freed_list; __freed_list = chk; } + else + { + register mem *prev; + prev=__freed_list; + for(top=__freed_list; top && top > chk; prev=top, top=m_next(top)) + ; + m_next(chk) = top; + m_next(prev) = chk; + } +#else + m_next(chk) = __freed_list; + __freed_list = chk; +#endif + noise("ADD LIST", chk); + } +} + +void * +__mini_malloc(size) +size_t size; +{ + register mem *ptr; + register unsigned int sz; + + /* First time round this _might_ be odd, But we won't do that! */ + sz = (unsigned int) sbrk(0); + if (sz & (sizeof(mem) - 1)) + sbrk(4 - (sz & (sizeof(mem) - 1))); + + if (size <= 0) + return 0; + /* Minor oops here, sbrk has a signed argument */ + if( size > (((unsigned)-1)>>1)-sizeof(mem)*3 ) + { + errno = ENOMEM; + return 0; + } + + size += sizeof(mem) * 2 - 1; /* Round up and leave space for size field */ + size /= sizeof(mem); + + ptr = (mem *) sbrk(size * sizeof(mem)); + if ((int) ptr == -1) + return 0; + + m_size(ptr) = size; + noise("CREATE", ptr); + return ptr + 1; +} +#endif /* L_free */ + +#ifdef L_malloc + +/* + * The chunk_list pointer is either NULL or points to a chunk in a + * circular list of all the free blocks in memory + */ + +#define Static static + +static mem *chunk_list = 0; +Static void __insert_chunk(); +Static mem *__search_chunk(); + +void * +malloc(size) +size_t size; +{ + register mem *ptr = 0; + register unsigned int sz; + + if (size == 0) + return 0; /* ANSI STD */ + + sz = size + sizeof(mem) * 2 - 1; + sz /= sizeof(mem); + +#ifdef MINALLOC + if (sz < MINALLOC) + sz = MINALLOC; +#endif + +#ifdef VERBOSE + { + static mem arr[2]; + m_size(arr) = sz; + noise("WANTED", arr); + } +#endif + + __alloca_alloc = malloc; /* We'll be messing with the heap now TVM */ + +#ifdef LAZY_FREE + ptr = __search_chunk(sz); + if (ptr == 0) + { +#endif + + /* First deal with the freed list */ + if (__freed_list) + { + while (__freed_list) + { + ptr = __freed_list; + __freed_list = m_next(__freed_list); + + if (m_size(ptr) == sz) /* Oh! Well that's lucky ain't it + * :-) */ + { + noise("LUCKY MALLOC", ptr); + return ptr + 1; + } + + __insert_chunk(ptr); + } + ptr = m_next(chunk_list); + if (ptr + m_size(ptr) == (void *) sbrk(0)) + { + /* Time to free for real */ + m_next(chunk_list) = m_next(ptr); + if (ptr == m_next(ptr)) + chunk_list = 0; + free(ptr + 1); + } +#ifdef LAZY_FREE + ptr = __search_chunk(sz); +#endif + } +#ifndef LAZY_FREE + ptr = __search_chunk(sz); +#endif + if (ptr == 0) + { +#ifdef MCHUNK + unsigned int alloc; + alloc = sizeof(mem) * (MCHUNK * ((sz + MCHUNK - 1) / MCHUNK) - 1); + ptr = __mini_malloc(alloc); + if (ptr) + __insert_chunk(ptr - 1); + else /* Oooo, near end of RAM */ + { + unsigned int needed = alloc; + for(alloc/=2; alloc>256 && needed; ) + { + ptr = __mini_malloc(alloc); + if (ptr) + { + if( alloc > needed ) needed = 0; else needed -= alloc; + __insert_chunk(ptr - 1); + } + else alloc/=2; + } + } + ptr = __search_chunk(sz); + if (ptr == 0) +#endif + { +#ifndef MCHUNK + ptr = __mini_malloc(size); +#endif +#ifdef VERBOSE + if( ptr == 0 ) + noise("MALLOC FAIL", 0); + else + noise("MALLOC NOW", ptr - 1); +#endif + return ptr; + } + } +#ifdef LAZY_FREE + } +#endif + +#ifdef VERBOSE + ptr[1].size = 0x55555555; +#endif + noise("MALLOC RET", ptr); + return ptr + 1; +} + +/* + * This function takes a pointer to a block of memory and inserts it into + * the chain of memory chunks + */ + +Static void +__insert_chunk(mem_chunk) +mem *mem_chunk; +{ + register mem *p1, *p2; + if (chunk_list == 0) /* Simple case first */ + { + m_next(mem_chunk) = chunk_list = mem_chunk; + noise("FIRST CHUNK", mem_chunk); + return; + } + p1 = mem_chunk; + p2 = chunk_list; + + do + { + if (p1 > p2) + { + if (m_next(p2) <= p2) + { /* We're at the top of the chain, p1 is + * higher */ + + if (p2 + m_size(p2) == p1) + { /* Good, stick 'em together */ + noise("INSERT CHUNK", mem_chunk); + m_size(p2) += m_size(p1); + noise("JOIN 1", p2); + } + else + { + m_next(p1) = m_next(p2); + m_next(p2) = p1; + noise("INSERT CHUNK", mem_chunk); + noise("FROM", p2); + } + return; + } + if (m_next(p2) > p1) + { + /* In chain, p1 between p2 and next */ + + m_next(p1) = m_next(p2); + m_next(p2) = p1; + noise("INSERT CHUNK", mem_chunk); + noise("FROM", p2); + + /* Try to join above */ + if (p1 + m_size(p1) == m_next(p1)) + { + m_size(p1) += m_size(m_next(p1)); + m_next(p1) = m_next(m_next(p1)); + noise("JOIN 2", p1); + } + /* Try to join below */ + if (p2 + m_size(p2) == p1) + { + m_size(p2) += m_size(p1); + m_next(p2) = m_next(p1); + noise("JOIN 3", p2); + } + chunk_list = p2; /* Make sure it's valid */ + return; + } + } + else if (p1 < p2) + { + if (m_next(p2) <= p2 && p1 < m_next(p2)) + { + /* At top of chain, next is bottom of chain, p1 is below next */ + + m_next(p1) = m_next(p2); + m_next(p2) = p1; + noise("INSERT CHUNK", mem_chunk); + noise("FROM", p2); + chunk_list = p2; + + if (p1 + m_size(p1) == m_next(p1)) + { + if (p2 == m_next(p1)) + chunk_list = p1; + m_size(p1) += m_size(m_next(p1)); + m_next(p1) = m_next(m_next(p1)); + noise("JOIN 4", p1); + } + return; + } + } + chunk_list = p2; /* Save for search */ + p2 = m_next(p2); + } + while (p2 != chunk_list); + + /* If we get here we have a problem, ignore it, maybe it'll go away */ + noise("DROPPED CHUNK", mem_chunk); +} + +/* + * This function will search for a chunk in memory of at least 'mem_size' + * when found, if the chunk is too big it'll be split, and pointer to the + * chunk returned. If none is found NULL is returned. + */ + +Static mem * +__search_chunk(mem_size) +unsigned int mem_size; +{ + register mem *p1, *p2; + if (chunk_list == 0) /* Simple case first */ + return 0; + + /* Search for a block >= the size we want */ + p1 = m_next(chunk_list); + p2 = chunk_list; + do + { + noise("CHECKED", p1); + if (m_size(p1) >= mem_size) + break; + + p2 = p1; + p1 = m_next(p1); + } + while (p2 != chunk_list); + + /* None found, exit */ + if (m_size(p1) < mem_size) + return 0; + + /* If it's exactly right remove it */ + if (m_size(p1) < mem_size + 2) + { + noise("FOUND RIGHT", p1); + chunk_list = m_next(p2) = m_next(p1); + if (chunk_list == p1) + chunk_list = 0; + return p1; + } + + noise("SPLIT", p1); + /* Otherwise split it */ + m_next(p2) = p1 + mem_size; + chunk_list = p2; + + p2 = m_next(p2); + m_size(p2) = m_size(p1) - mem_size; + m_next(p2) = m_next(p1); + m_size(p1) = mem_size; + if (chunk_list == p1) + chunk_list = p2; +#ifdef VERBOSE + p1[1].size = 0xAAAAAAAA; +#endif + noise("INSERT CHUNK", p2); + noise("FOUND CHUNK", p1); + noise("LIST IS", chunk_list); + return p1; +} + +#endif /* L_malloc */ + +#ifdef L_calloc +void * +calloc(elm, sz) +unsigned int elm, sz; +{ + register unsigned int v; + register void *ptr; + ptr = malloc(v = elm * sz); + if (ptr) + memset(ptr, 0, v); + return ptr; +} +#endif /* L_calloc */ + +#ifdef L_realloc +void * +realloc(ptr, size) +void *ptr; +size_t size; +{ + void *nptr; + unsigned int osize; + if (ptr == 0) + return malloc(size); + + osize = (m_size(((mem *) ptr) - 1) - 1) * sizeof(mem); + if (size <= osize) + { + return ptr; + } + + nptr = malloc(size); + + if (nptr == 0) + return 0; + + memcpy(nptr, ptr, osize); + free(ptr); + + return nptr; +} +#endif /* L_realloc */ diff --git a/libc/malloc/malloc.h b/libc/malloc/malloc.h new file mode 100644 index 0000000..e8fdb0a --- /dev/null +++ b/libc/malloc/malloc.h @@ -0,0 +1,30 @@ + +#ifndef __MALLOC_H +#define __MALLOC_H +#include +#include + +/* + * Mini malloc allows you to use a less efficient but smaller malloc the + * cost is about 100 bytes of code in free but malloc (700bytes) doesn't + * have to be linked. Unfortunatly memory can only be reused if everything + * above it has been freed + * + */ + +extern void free __P((void *)); +extern void *malloc __P((size_t)); +extern void *realloc __P((void *, size_t)); +extern void *alloca __P((size_t)); + +extern void *(*__alloca_alloc) __P((size_t)); + +#ifdef __LIBC__ +#define __MINI_MALLOC__ +#endif + +#ifdef __MINI_MALLOC__ +#define malloc(x) ((*__alloca_alloc)(x)) +#endif + +#endif diff --git a/libc/malloc1/Config b/libc/malloc1/Config deleted file mode 100644 index 4404398..0000000 --- a/libc/malloc1/Config +++ /dev/null @@ -1 +0,0 @@ -malloc: Robert's malloc routines diff --git a/libc/malloc1/Makefile b/libc/malloc1/Makefile deleted file mode 100644 index e762582..0000000 --- a/libc/malloc1/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 1995,1996 Robert de Bath -# This file is part of the Linux-8086 C library and is distributed -# under the GNU Library General Public License. - -ASRC=malloc.c -AOBJ=malloc.o alloca.o free.o calloc.o realloc.o - -CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) - -all: $(LIBC)($(AOBJ)) - @$(RM) $(OBJ) - -$(LIBC)($(AOBJ)): $(ASRC) - $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o - $(AR) $(ARFLAGS) $@ $*.o - -clean: - rm -f *.o libc.a - -transfer: - -@rm ../include/malloc.h - cp -p malloc.h ../include/. diff --git a/libc/malloc1/README b/libc/malloc1/README deleted file mode 100644 index 95f5928..0000000 --- a/libc/malloc1/README +++ /dev/null @@ -1,9 +0,0 @@ -Copyright (C) 1995,1996 Robert de Bath -This file is part of the Linux-8086 C library and is distributed -under the GNU Library General Public License. - -This is a combined alloca/malloc package. It uses a classic algorithm -and so may be seen to be quite slow compared to more modern routines -with 'nasty' distributions of allocation. - --Robert diff --git a/libc/malloc1/malloc.c b/libc/malloc1/malloc.c deleted file mode 100644 index 86ffd42..0000000 --- a/libc/malloc1/malloc.c +++ /dev/null @@ -1,546 +0,0 @@ -/* Copyright (C) 1995,1996 Robert de Bath - * This file is part of the Linux-8086 C library and is distributed - * under the GNU Library General Public License. - */ - -/* - * This is a combined alloca/malloc package. It uses a classic algorithm - * and so may be seen to be quite slow compared to more modern routines - * with 'nasty' distributions. - */ - -#include -#include - -#define MCHUNK 2048 /* Allocation unit in 'mem' elements */ -#define XLAZY_FREE /* If set frees can be infinitly defered */ -#define XMINALLOC 32 /* Smallest chunk to alloc in 'mem's */ -#define XVERBOSE /* Lots of noise, debuging ? */ - -#undef malloc -#define MAX_INT ((int)(((unsigned)-1)>>1)) - -#ifdef VERBOSE -#define noise __noise -#else -#define noise(y,x) -#endif - -typedef union mem_cell -{ - union mem_cell *next; /* A pointer to the next mem */ - unsigned int size; /* An int >= sizeof pointer */ - char *depth; /* For the alloca hack */ -} -mem; - -#define m_size(p) ((p) [0].size) /* For malloc */ -#define m_next(p) ((p) [1].next) /* For malloc and alloca */ -#define m_deep(p) ((p) [0].depth) /* For alloca */ - -extern void *__mini_malloc __P ((size_t)); -extern void *(*__alloca_alloc) __P ((size_t)); -extern mem *__freed_list; - -#ifdef L_free -/* Start the alloca with just the dumb version of malloc */ - -void *(*__alloca_alloc) __P ((size_t)) = __mini_malloc; -mem *__freed_list = 0; - -#ifdef VERBOSE -/* NB: Careful here, stdio may use malloc - so we can't */ -static -phex(val) -{ - static char hex[] = "0123456789ABCDEF"; - int i; - for (i = sizeof(int)*8-4; i >= 0; i -= 4) - write(2, hex + ((val >> i) & 0xF), 1); -} - -noise(y, x) -char *y; -mem *x; -{ - write(2, "Malloc ", 7); - phex(x); - write(2, " sz ", 4); - if(x) phex(m_size(x)); else phex(0); - write(2, " nxt ", 5); - if(x) phex(m_next(x)); else phex(0); - write(2, " is ", 4); - write(2, y, strlen(y)); - write(2, "\n", 1); -} -#endif - -#endif - -#ifdef L_alloca -static mem *alloca_stack = 0; - -void * -alloca(size) -size_t size; -{ - auto char probe; /* Probes stack depth: */ - register mem *hp; - - /* - * Reclaim garbage, defined as all alloca'd storage that was allocated - * from deeper in the stack than currently. - */ - - for (hp = alloca_stack; hp != 0;) - if (m_deep(hp) < &probe) - { - register mem *np = m_next(hp); - free((void *) hp); /* Collect garbage. */ - hp = np; /* -> next header. */ - } - else - break; /* Rest are not deeper. */ - - alloca_stack = hp; /* -> last valid storage. */ - if (size == 0) - return 0; /* No allocation required. */ - - hp = (mem *) (*__alloca_alloc) (sizeof(mem)*2 + size); - if (hp == 0) - return hp; - - m_next(hp) = alloca_stack; - m_deep(hp) = &probe; - alloca_stack = hp; - - /* User storage begins just after header. */ - return (void *) (hp + 2); -} -#endif /* L_alloca */ - -#ifdef L_free -void -free(ptr) -void *ptr; -{ - register mem *top; - register mem *chk = (mem *) ptr; - - if (chk == 0) - return; /* free(NULL) - be nice */ - chk--; - - try_this:; - top = (mem *) sbrk(0); - if (chk + m_size(chk) == top) - { - noise("FREE brk", chk); - brk(top-m_size(chk)); - /* - * Adding this code allow free to release blocks in any order; they - * can still only be allocated from the top of the heap tho. - */ -#ifdef __MINI_MALLOC__ - if (__alloca_alloc == __mini_malloc && __freed_list) - { - mem *prev, *curr; - chk = __freed_list; - __freed_list = m_next(__freed_list); - goto try_this; - } -#endif - } - else - { /* Nope, not sure where this goes, leave - * it for malloc to deal with */ -#ifdef __MINI_MALLOC__ - if( __freed_list || chk > __freed_list ) - { m_next(chk) = __freed_list; __freed_list = chk; } - else - { - register mem *prev; - prev=__freed_list; - for(top=__freed_list; top && top > chk; prev=top, top=m_next(top)) - ; - m_next(chk) = top; - m_next(prev) = chk; - } -#else - m_next(chk) = __freed_list; - __freed_list = chk; -#endif - noise("ADD LIST", chk); - } -} - -void * -__mini_malloc(size) -size_t size; -{ - register mem *ptr; - register unsigned int sz; - - /* First time round this _might_ be odd, But we won't do that! */ - sz = (unsigned int) sbrk(0); - if (sz & (sizeof(mem) - 1)) - sbrk(4 - (sz & (sizeof(mem) - 1))); - - if (size <= 0) - return 0; - /* Minor oops here, sbrk has a signed argument */ - if( size > (((unsigned)-1)>>1)-sizeof(mem)*3 ) - { - errno = ENOMEM; - return 0; - } - - size += sizeof(mem) * 2 - 1; /* Round up and leave space for size field */ - size /= sizeof(mem); - - ptr = (mem *) sbrk(size * sizeof(mem)); - if ((int) ptr == -1) - return 0; - - m_size(ptr) = size; - noise("CREATE", ptr); - return ptr + 1; -} -#endif /* L_free */ - -#ifdef L_malloc - -/* - * The chunk_list pointer is either NULL or points to a chunk in a - * circular list of all the free blocks in memory - */ - -#define Static static - -static mem *chunk_list = 0; -Static void __insert_chunk(); -Static mem *__search_chunk(); - -void * -malloc(size) -size_t size; -{ - register mem *ptr = 0; - register unsigned int sz; - - if (size == 0) - return 0; /* ANSI STD */ - - sz = size + sizeof(mem) * 2 - 1; - sz /= sizeof(mem); - -#ifdef MINALLOC - if (sz < MINALLOC) - sz = MINALLOC; -#endif - -#ifdef VERBOSE - { - static mem arr[2]; - m_size(arr) = sz; - noise("WANTED", arr); - } -#endif - - __alloca_alloc = malloc; /* We'll be messing with the heap now TVM */ - -#ifdef LAZY_FREE - ptr = __search_chunk(sz); - if (ptr == 0) - { -#endif - - /* First deal with the freed list */ - if (__freed_list) - { - while (__freed_list) - { - ptr = __freed_list; - __freed_list = m_next(__freed_list); - - if (m_size(ptr) == sz) /* Oh! Well that's lucky ain't it - * :-) */ - { - noise("LUCKY MALLOC", ptr); - return ptr + 1; - } - - __insert_chunk(ptr); - } - ptr = m_next(chunk_list); - if (ptr + m_size(ptr) == (void *) sbrk(0)) - { - /* Time to free for real */ - m_next(chunk_list) = m_next(ptr); - if (ptr == m_next(ptr)) - chunk_list = 0; - free(ptr + 1); - } -#ifdef LAZY_FREE - ptr = __search_chunk(sz); -#endif - } -#ifndef LAZY_FREE - ptr = __search_chunk(sz); -#endif - if (ptr == 0) - { -#ifdef MCHUNK - unsigned int alloc; - alloc = sizeof(mem) * (MCHUNK * ((sz + MCHUNK - 1) / MCHUNK) - 1); - ptr = __mini_malloc(alloc); - if (ptr) - __insert_chunk(ptr - 1); - else /* Oooo, near end of RAM */ - { - unsigned int needed = alloc; - for(alloc/=2; alloc>256 && needed; ) - { - ptr = __mini_malloc(alloc); - if (ptr) - { - if( alloc > needed ) needed = 0; else needed -= alloc; - __insert_chunk(ptr - 1); - } - else alloc/=2; - } - } - ptr = __search_chunk(sz); - if (ptr == 0) -#endif - { -#ifndef MCHUNK - ptr = __mini_malloc(size); -#endif -#ifdef VERBOSE - if( ptr == 0 ) - noise("MALLOC FAIL", 0); - else - noise("MALLOC NOW", ptr - 1); -#endif - return ptr; - } - } -#ifdef LAZY_FREE - } -#endif - -#ifdef VERBOSE - ptr[1].size = 0x55555555; -#endif - noise("MALLOC RET", ptr); - return ptr + 1; -} - -/* - * This function takes a pointer to a block of memory and inserts it into - * the chain of memory chunks - */ - -Static void -__insert_chunk(mem_chunk) -mem *mem_chunk; -{ - register mem *p1, *p2; - if (chunk_list == 0) /* Simple case first */ - { - m_next(mem_chunk) = chunk_list = mem_chunk; - noise("FIRST CHUNK", mem_chunk); - return; - } - p1 = mem_chunk; - p2 = chunk_list; - - do - { - if (p1 > p2) - { - if (m_next(p2) <= p2) - { /* We're at the top of the chain, p1 is - * higher */ - - if (p2 + m_size(p2) == p1) - { /* Good, stick 'em together */ - noise("INSERT CHUNK", mem_chunk); - m_size(p2) += m_size(p1); - noise("JOIN 1", p2); - } - else - { - m_next(p1) = m_next(p2); - m_next(p2) = p1; - noise("INSERT CHUNK", mem_chunk); - noise("FROM", p2); - } - return; - } - if (m_next(p2) > p1) - { - /* In chain, p1 between p2 and next */ - - m_next(p1) = m_next(p2); - m_next(p2) = p1; - noise("INSERT CHUNK", mem_chunk); - noise("FROM", p2); - - /* Try to join above */ - if (p1 + m_size(p1) == m_next(p1)) - { - m_size(p1) += m_size(m_next(p1)); - m_next(p1) = m_next(m_next(p1)); - noise("JOIN 2", p1); - } - /* Try to join below */ - if (p2 + m_size(p2) == p1) - { - m_size(p2) += m_size(p1); - m_next(p2) = m_next(p1); - noise("JOIN 3", p2); - } - chunk_list = p2; /* Make sure it's valid */ - return; - } - } - else if (p1 < p2) - { - if (m_next(p2) <= p2 && p1 < m_next(p2)) - { - /* At top of chain, next is bottom of chain, p1 is below next */ - - m_next(p1) = m_next(p2); - m_next(p2) = p1; - noise("INSERT CHUNK", mem_chunk); - noise("FROM", p2); - chunk_list = p2; - - if (p1 + m_size(p1) == m_next(p1)) - { - if (p2 == m_next(p1)) - chunk_list = p1; - m_size(p1) += m_size(m_next(p1)); - m_next(p1) = m_next(m_next(p1)); - noise("JOIN 4", p1); - } - return; - } - } - chunk_list = p2; /* Save for search */ - p2 = m_next(p2); - } - while (p2 != chunk_list); - - /* If we get here we have a problem, ignore it, maybe it'll go away */ - noise("DROPPED CHUNK", mem_chunk); -} - -/* - * This function will search for a chunk in memory of at least 'mem_size' - * when found, if the chunk is too big it'll be split, and pointer to the - * chunk returned. If none is found NULL is returned. - */ - -Static mem * -__search_chunk(mem_size) -unsigned int mem_size; -{ - register mem *p1, *p2; - if (chunk_list == 0) /* Simple case first */ - return 0; - - /* Search for a block >= the size we want */ - p1 = m_next(chunk_list); - p2 = chunk_list; - do - { - noise("CHECKED", p1); - if (m_size(p1) >= mem_size) - break; - - p2 = p1; - p1 = m_next(p1); - } - while (p2 != chunk_list); - - /* None found, exit */ - if (m_size(p1) < mem_size) - return 0; - - /* If it's exactly right remove it */ - if (m_size(p1) < mem_size + 2) - { - noise("FOUND RIGHT", p1); - chunk_list = m_next(p2) = m_next(p1); - if (chunk_list == p1) - chunk_list = 0; - return p1; - } - - noise("SPLIT", p1); - /* Otherwise split it */ - m_next(p2) = p1 + mem_size; - chunk_list = p2; - - p2 = m_next(p2); - m_size(p2) = m_size(p1) - mem_size; - m_next(p2) = m_next(p1); - m_size(p1) = mem_size; - if (chunk_list == p1) - chunk_list = p2; -#ifdef VERBOSE - p1[1].size = 0xAAAAAAAA; -#endif - noise("INSERT CHUNK", p2); - noise("FOUND CHUNK", p1); - noise("LIST IS", chunk_list); - return p1; -} - -#endif /* L_malloc */ - -#ifdef L_calloc -void * -calloc(elm, sz) -unsigned int elm, sz; -{ - register unsigned int v; - register void *ptr; - ptr = malloc(v = elm * sz); - if (ptr) - memset(ptr, 0, v); - return ptr; -} -#endif /* L_calloc */ - -#ifdef L_realloc -void * -realloc(ptr, size) -void *ptr; -size_t size; -{ - void *nptr; - unsigned int osize; - if (ptr == 0) - return malloc(size); - - osize = (m_size(((mem *) ptr) - 1) - 1) * sizeof(mem); - if (size <= osize) - { - return ptr; - } - - nptr = malloc(size); - - if (nptr == 0) - return 0; - - memcpy(nptr, ptr, osize); - free(ptr); - - return nptr; -} -#endif /* L_realloc */ diff --git a/libc/malloc1/malloc.h b/libc/malloc1/malloc.h deleted file mode 100644 index e8fdb0a..0000000 --- a/libc/malloc1/malloc.h +++ /dev/null @@ -1,30 +0,0 @@ - -#ifndef __MALLOC_H -#define __MALLOC_H -#include -#include - -/* - * Mini malloc allows you to use a less efficient but smaller malloc the - * cost is about 100 bytes of code in free but malloc (700bytes) doesn't - * have to be linked. Unfortunatly memory can only be reused if everything - * above it has been freed - * - */ - -extern void free __P((void *)); -extern void *malloc __P((size_t)); -extern void *realloc __P((void *, size_t)); -extern void *alloca __P((size_t)); - -extern void *(*__alloca_alloc) __P((size_t)); - -#ifdef __LIBC__ -#define __MINI_MALLOC__ -#endif - -#ifdef __MINI_MALLOC__ -#define malloc(x) ((*__alloca_alloc)(x)) -#endif - -#endif diff --git a/libc/malloc2/Config b/libc/malloc2/Config deleted file mode 100644 index 11c476d..0000000 --- a/libc/malloc2/Config +++ /dev/null @@ -1 +0,0 @@ -malloc: Joel's malloc functions diff --git a/libc/malloc2/Makefile b/libc/malloc2/Makefile deleted file mode 100644 index edfc8f5..0000000 --- a/libc/malloc2/Makefile +++ /dev/null @@ -1,14 +0,0 @@ - -OBJ=malloc.o stack.o - -CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) - -all: $(LIBC)($(OBJ)) - @$(RM) $(OBJ) - -clean: - rm -f *.o libc.a - -transfer: - -@rm ../include/malloc.h - cp -p malloc.h ../include/. diff --git a/libc/malloc2/README b/libc/malloc2/README deleted file mode 100644 index ecf3fd2..0000000 --- a/libc/malloc2/README +++ /dev/null @@ -1,19 +0,0 @@ -This is just the malloc for libc. It is untested; it won't even compile -right now. In particular, __malloc_init needs some bug fixing! - -Apparently, there is another malloc that Robert Debath wrote which probably -works by now. However, I honestly think that my malloc may be just as -good when it's finished. - -In about six months, you'll probably see something like this: - - -Linux/less-than-32-bit installation program -Do you want - 1. Chad Page's kernel - 2. Alan Cox's kernel -Enter your chioce --> 2 -Do you want - 1. Robert Debath's malloc - 2. Joel Weber's malloc -[more choices for compilers, filetools, etc] diff --git a/libc/malloc2/malloc.c b/libc/malloc2/malloc.c deleted file mode 100644 index 2e1cc04..0000000 --- a/libc/malloc2/malloc.c +++ /dev/null @@ -1,126 +0,0 @@ -/* simplified linux malloc.h - Copyright (C) 1995 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include - -typedef struct __malloc_struct malloc_struct; - -typedef union __malloc_union -{ - char *c; - malloc_struct *m; -} malloc_union; - - -struct __malloc_struct -{ - unsigned char status; -#define ALLOC 0x53 -#define FREE 0x55 -#define END_OF_WORLD 0x57 - malloc_union next; -} *malloc_start; - -extern int __STACKSIZE; - -/* WARNING: this init will only work if there is a hard limit on the - amount of RAM that can be allocated. - */ - -#ifdef __AS386_16__ -#asm - loc 1 ! Make sure the pointer is in the correct segment -auto_func: ! Label for bcc -M to work. - .word _malloc_init ! Pointer to the autorun function - .text ! So the function after is also in the correct seg. -#endasm -#endif - -malloc_init() -{ - extern unsigned int sbrk(); - - unsigned int ptr, sz, count; - - malloc_start = (malloc_struct*) ((sbrk(16)+1)&~1); - malloc_start->status = FREE; - - count=254; - for(sz=16384; sz>64; ) - { - ptr= sbrk(sz); - if( ptr == (unsigned)-1 ) sz>>=1; - else count+=sz; - } - if( __STACKSIZE > count || __STACKSIZE <= 0 ) __STACKSIZE = ((count>>1)&-2); - ptr = sbrk(-__STACKSIZE); - - malloc_start->next.m = ((malloc_struct*)ptr) - 1; - - malloc_start->next.m->status = END_OF_WORLD; -} - -char *malloc(size) -size_t size; -{ - register malloc_union tmp, tmp2; - - /* Make sure we don't lose the alignment */ - size = (size+sizeof(malloc_struct)-1)/sizeof(malloc_struct); - - tmp.m = malloc_start; - while ( ( tmp.m->next.m - tmp.m - 2 ) < size - || ( tmp.m->status == ALLOC )) - tmp.m = tmp.m->next.m; - - if (tmp.m->status == FREE){ - tmp2.m = size + tmp.m + 1; - tmp2.m->status = FREE; - tmp2.m->next.c = tmp.m->next.c; - tmp.m->status = ALLOC; - tmp.m->next.c = tmp2.c; - } - else return 0; - tmp.m++; - return tmp.c; -} - -__malloc_cleanup() /* finds consecutive free blocks and joins them */ -{ - malloc_struct *tmp; - - tmp = malloc_start; - while ((tmp->status != END_OF_WORLD)&&(tmp->next.m->status != END_OF_WORLD)){ - if ((tmp->status==FREE)&&(tmp->next.m->status==FREE)) - tmp->next.m = tmp->next.m->next.m; - else tmp = tmp->next.m; - } -} - -free(what) -char *what; -{ - malloc_union tmp; - - tmp.c = what; tmp.m--; - if( tmp.m->status == ALLOC ) - { - tmp.m->status = FREE; - __malloc_cleanup; - } -} diff --git a/libc/malloc2/malloc.h b/libc/malloc2/malloc.h deleted file mode 100644 index ffcb3a4..0000000 --- a/libc/malloc2/malloc.h +++ /dev/null @@ -1,21 +0,0 @@ -/* simplified linux malloc.h - Copyright (C) 1995 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -char *malloc(size); -void free(what); -char *realloc(what, size); diff --git a/libc/malloc2/stack.c b/libc/malloc2/stack.c deleted file mode 100644 index 5f33e21..0000000 --- a/libc/malloc2/stack.c +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * Under Linux 8086 the stack and heap areas are at the top and bottom - * of the same area of memory, this version of malloc requires that the - * malloc area is of a fixed size this means that there must also be a - * specific amount of stack space reserved outside of this. The number - * of bytes to be reserved is specified below. - */ - -int __STACKSIZE = 2048; diff --git a/libc/stdio/Config b/libc/stdio/Config new file mode 100644 index 0000000..8f2b307 --- /dev/null +++ b/libc/stdio/Config @@ -0,0 +1,4 @@ +# + +stdio: Stdio package + diff --git a/libc/stdio/Makefile b/libc/stdio/Makefile new file mode 100644 index 0000000..0fd8d97 --- /dev/null +++ b/libc/stdio/Makefile @@ -0,0 +1,49 @@ +# Copyright (C) 1995,1996 Robert de Bath +# This file is part of the Linux-8086 C library and is distributed +# under the GNU Library General Public License. + +ifneq ($(LIB_CPU),i86) +CFLAGS=$(CCFLAGS) $(LIBDEFS) -DFLOATS +endif + +ASRC=stdio.c +AOBJ=_stdio_init.o fputc.o fgetc.o fflush.o fgets.o gets.o fputs.o \ + puts.o fread.o fwrite.o fopen.o fclose.o fseek.o rewind.o ftell.o \ + setbuffer.o setvbuf.o ungetc.o + +PSRC=printf.c +POBJ=printf.o sprintf.o fprintf.o vprintf.o vsprintf.o vfprintf.o + +SSRC=scanf.c +SOBJ=scanf.o sscanf.o fscanf.o vscanf.o vsscanf.o vfscanf.o + +OBJ= $(AOBJ) $(POBJ) $(SOBJ) + +CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) + +all: $(LIBC) + @$(RM) $(OBJ) + +$(LIBC): $(LIBC)($(OBJ)) + +$(LIBC)($(AOBJ)): $(ASRC) + $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o + $(AR) $(ARFLAGS) $@ $*.o + +$(LIBC)($(POBJ)): $(PSRC) + $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o + $(AR) $(ARFLAGS) $@ $*.o + +$(LIBC)($(SOBJ)): $(SSRC) + $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o + $(AR) $(ARFLAGS) $@ $*.o + +transfer: + -@rm -f ../include/stdio.h + cp -p stdio.h ../include/. + +clean: + rm -f *.o libc.a + +$(LIBC)($(OBJ)): stdio.h + diff --git a/libc/stdio/printf.c b/libc/stdio/printf.c new file mode 100644 index 0000000..e41eca4 --- /dev/null +++ b/libc/stdio/printf.c @@ -0,0 +1,380 @@ +/* + * This file based on printf.c from 'Dlibs' on the atari ST (RdeBath) + * + * 19-OCT-88: Dale Schumacher + * > John Stanley has again been a great help in debugging, particularly + * > with the printf/scanf functions which are his creation. + * + * Dale Schumacher 399 Beacon Ave. + * (alias: Dalnefre') St. Paul, MN 55104 + * dal@syntel.UUCP United States of America + * "It's not reality that's important, but how you perceive things." + * + */ + +/* Altered to use stdarg, made the core function vfprintf. + * Hooked into the stdio package using 'inside information' + * Altered sizeof() assumptions, now assumes all integers except chars + * will be either + * sizeof(xxx) == sizeof(long) or sizeof(xxx) == sizeof(short) + * + * -RDB + */ + +#include +#include +#ifdef __STDC__ +#include +#define va_strt va_start +#else +#include +#define va_strt(p,i) va_start(p) +#endif + +#include "stdio.h" + +#ifdef L_printf + +#ifdef __STDC__ +int printf(const char * fmt, ...) +#else +int printf(fmt, va_alist) +__const char *fmt; +va_dcl +#endif +{ + va_list ptr; + int rv; + va_strt(ptr, fmt); + rv = vfprintf(stdout,fmt,ptr); + va_end(ptr); + return rv; +} +#endif + +#ifdef L_sprintf +#ifdef __STDC__ +int sprintf(char * sp, const char * fmt, ...) +#else +int sprintf(sp, fmt, va_alist) +char * sp; +__const char *fmt; +va_dcl +#endif +{ +static FILE string[1] = +{ + {0, 0, (char*)(unsigned) -1, 0, (char*) (unsigned) -1, -1, + _IOFBF | __MODE_WRITE} +}; + + va_list ptr; + int rv; + va_strt(ptr, fmt); + string->bufpos = sp; + rv = vfprintf(string,fmt,ptr); + va_end(ptr); + *(string->bufpos) = 0; + return rv; +} +#endif + +#ifdef L_fprintf +#ifdef __STDC__ +int fprintf(FILE * fp, const char * fmt, ...) +#else +int fprintf(fp, fmt, va_alist) +FILE * fp; +__const char *fmt; +va_dcl +#endif +{ + va_list ptr; + int rv; + va_strt(ptr, fmt); + rv = vfprintf(fp,fmt,ptr); + va_end(ptr); + return rv; +} +#endif + +#ifdef L_vprintf +int vprintf(fmt, ap) +__const char *fmt; +va_list ap; +{ + return vfprintf(stdout,fmt,ap); +} +#endif + +#ifdef L_vsprintf +int vsprintf(sp, fmt, ap) +char * sp; +__const char *fmt; +va_list ap; +{ +static FILE string[1] = +{ + {0, 0, (char*)(unsigned) -1, 0, (char*) (unsigned) -1, -1, + _IOFBF | __MODE_WRITE} +}; + + int rv; + string->bufpos = sp; + rv = vfprintf(string,fmt,ap); + *(string->bufpos) = 0; + return rv; +} +#endif + +#ifdef L_vfprintf + +#ifdef FLOATS +int (*__fp_print)() = 0; +#endif + +static int +prtfld(op, buf, ljustf, sign, pad, width, preci, buffer_mode) +register FILE *op; +register unsigned char *buf; +int ljustf; +register char sign; +char pad; +register int width; +int preci; +int buffer_mode; +/* + * Output the given field in the manner specified by the arguments. Return + * the number of characters output. + */ +{ + register int cnt = 0, len; + register unsigned char ch; + + len = strlen(buf); + + if (*buf == '-') + sign = *buf++; + else if (sign) + len++; + + if ((preci != -1) && (len > preci)) /* limit max data width */ + len = preci; + + if (width < len) /* flexible field width or width overflow */ + width = len; + + /* + * at this point: width = total field width len = actual data width + * (including possible sign character) + */ + cnt = width; + width -= len; + + while (width || len) + { + if (!ljustf && width) /* left padding */ + { + if (len && sign && (pad == '0')) + goto showsign; + ch = pad; + --width; + } + else if (len) + { + if (sign) + { + showsign:ch = sign; /* sign */ + sign = '\0'; + } + else + ch = *buf++; /* main field */ + --len; + } + else + { + ch = pad; /* right padding */ + --width; + } + putc(ch, op); + if( ch == '\n' && buffer_mode == _IOLBF ) fflush(op); + } + + return (cnt); +} + +int +vfprintf(op, fmt, ap) +FILE *op; +register __const char *fmt; +register va_list ap; +{ + register int i, cnt = 0, ljustf, lval; + int preci, dpoint, width; + char pad, sign, radix, hash; + register char *ptmp; + char tmp[64], *ltostr(), *ultostr(); + int buffer_mode; + + /* This speeds things up a bit for unbuffered */ + buffer_mode = (op->mode&__MODE_BUF); + op->mode &= (~__MODE_BUF); + + while (*fmt) + { + if (*fmt == '%') + { + if( buffer_mode == _IONBF ) fflush(op); + ljustf = 0; /* left justify flag */ + sign = '\0'; /* sign char & status */ + pad = ' '; /* justification padding char */ + width = -1; /* min field width */ + dpoint = 0; /* found decimal point */ + preci = -1; /* max data width */ + radix = 10; /* number base */ + ptmp = tmp; /* pointer to area to print */ + hash = 0; + lval = (sizeof(int)==sizeof(long)); /* long value flaged */ + fmtnxt: + i = 0; + for(;;) + { + ++fmt; + if(*fmt < '0' || *fmt > '9' ) break; + i = (i * 10) + (*fmt - '0'); + if (dpoint) + preci = i; + else if (!i && (pad == ' ')) + { + pad = '0'; + goto fmtnxt; + } + else + width = i; + } + + switch (*fmt) + { + case '\0': /* early EOS */ + --fmt; + goto charout; + + case '-': /* left justification */ + ljustf = 1; + goto fmtnxt; + + case ' ': + case '+': /* leading sign flag */ + sign = *fmt; + goto fmtnxt; + + case '*': /* parameter width value */ + i = va_arg(ap, int); + if (dpoint) + preci = i; + else + width = i; + goto fmtnxt; + + case '.': /* secondary width field */ + dpoint = 1; + goto fmtnxt; + + case 'l': /* long data */ + lval = 1; + goto fmtnxt; + + case 'h': /* short data */ + lval = 0; + goto fmtnxt; + + case 'd': /* Signed decimal */ + case 'i': + ptmp = ltostr((long) ((lval) + ? va_arg(ap, long) + : va_arg(ap, short)), + 10); + goto printit; + + case 'b': /* Unsigned binary */ + radix = 2; + goto usproc; + + case 'o': /* Unsigned octal */ + radix = 8; + goto usproc; + + case 'p': /* Pointer */ + lval = (sizeof(char*) == sizeof(long)); + pad = '0'; + width = 6; + preci = 8; + /* fall thru */ + + case 'x': /* Unsigned hexadecimal */ + case 'X': + radix = 16; + /* fall thru */ + + case 'u': /* Unsigned decimal */ + usproc: + ptmp = ultostr((unsigned long) ((lval) + ? va_arg(ap, unsigned long) + : va_arg(ap, unsigned short)), + radix); + if( hash && radix == 8 ) { width = strlen(ptmp)+1; pad='0'; } + goto printit; + + case '#': + hash=1; + goto fmtnxt; + + case 'c': /* Character */ + ptmp[0] = va_arg(ap, int); + ptmp[1] = '\0'; + goto nopad; + + case 's': /* String */ + ptmp = va_arg(ap, char*); + nopad: + sign = '\0'; + pad = ' '; + printit: + cnt += prtfld(op, ptmp, ljustf, + sign, pad, width, preci, buffer_mode); + break; + +#if FLOATS + case 'e': /* float */ + case 'f': + case 'g': + case 'E': + case 'G': + if ( __fp_print ) + { + (*__fp_print)(&va_arg(ap, double), *fmt, preci, ptmp); + preci = -1; + goto printit; + } + /* FALLTHROUGH if no floating printf available */ +#endif + + default: /* unknown character */ + goto charout; + } + } + else + { + charout: + putc(*fmt, op); /* normal char out */ + ++cnt; + if( *fmt == '\n' && buffer_mode == _IOLBF ) fflush(op); + } + ++fmt; + } + op->mode |= buffer_mode; + if( buffer_mode == _IONBF ) fflush(op); + if( buffer_mode == _IOLBF ) op->bufwrite = op->bufstart; + return (cnt); +} +#endif diff --git a/libc/stdio/scanf.c b/libc/stdio/scanf.c new file mode 100644 index 0000000..1e0f282 --- /dev/null +++ b/libc/stdio/scanf.c @@ -0,0 +1,536 @@ +/* + * This file based on scanf.c from 'Dlibs' on the atari ST (RdeBath) + * + * 19-OCT-88: Dale Schumacher + * > John Stanley has again been a great help in debugging, particularly + * > with the printf/scanf functions which are his creation. + * + * Dale Schumacher 399 Beacon Ave. + * (alias: Dalnefre') St. Paul, MN 55104 + * dal@syntel.UUCP United States of America + * "It's not reality that's important, but how you perceive things." + * + */ + +#include +#include +#include + +#ifdef __STDC__ +#include +#define va_strt va_start +#else +#include +#define va_strt(p,i) va_start(p) +#endif + +#ifdef L_scanf +#ifdef __STDC__ +int scanf(const char * fmt, ...) +#else +int scanf(fmt, va_alist) +__const char *fmt; +va_dcl +#endif +{ + va_list ptr; + int rv; + va_strt(ptr, fmt); + rv = vfscanf(stdin,fmt,ptr); + va_end(ptr); + return rv; +} +#endif + +#ifdef L_sscanf +#ifdef __STDC__ +int sscanf(char * sp, const char * fmt, ...) +#else +int sscanf(sp, fmt, va_alist) +char * sp; +__const char *fmt; +va_dcl +#endif +{ +static FILE string[1] = +{ + {0, (char*)(unsigned) -1, 0, 0, (char*) (unsigned) -1, -1, + _IOFBF | __MODE_READ} +}; + + va_list ptr; + int rv; + va_strt(ptr, fmt); + string->bufpos = sp; + rv = vfscanf(string,fmt,ptr); + va_end(ptr); + return rv; +} +#endif + +#ifdef L_fscanf +#ifdef __STDC__ +int fscanf(FILE * fp, const char * fmt, ...) +#else +int fscanf(fp, fmt, va_alist) +FILE * fp; +__const char *fmt; +va_dcl +#endif +{ + va_list ptr; + int rv; + va_strt(ptr, fmt); + rv = vfscanf(fp,fmt,ptr); + va_end(ptr); + return rv; +} +#endif + +#ifdef L_vscanf +int vscanf(fmt, ap) +__const char *fmt; +va_list ap; +{ + return vfscanf(stdin,fmt,ap); +} +#endif + +#ifdef L_vsscanf +int vsscanf(sp, fmt, ap) +char * sp; +__const char *fmt; +{ +static FILE string[1] = +{ + {0, (char*)(unsigned) -1, 0, 0, (char*) (unsigned) -1, -1, + _IOFBF | __MODE_READ} +}; + + string->bufpos = sp; + return vfscanf(string,fmt,ap); +} +#endif + +#ifdef L_vfscanf +/* #define skip() do{c=getc(fp); if (c<1) goto done;}while(isspace(c))*/ + +#define skip() while(isspace(c)) { if ((c=getc(fp))<1) goto done; } + +#if FLOATS +/* fp scan actions */ +#define F_NADA 0 /* just change state */ +#define F_SIGN 1 /* set sign */ +#define F_ESIGN 2 /* set exponent's sign */ +#define F_INT 3 /* adjust integer part */ +#define F_FRAC 4 /* adjust fraction part */ +#define F_EXP 5 /* adjust exponent part */ +#define F_QUIT 6 + +#define NSTATE 8 +#define FS_INIT 0 /* initial state */ +#define FS_SIGNED 1 /* saw sign */ +#define FS_DIGS 2 /* saw digits, no . */ +#define FS_DOT 3 /* saw ., no digits */ +#define FS_DD 4 /* saw digits and . */ +#define FS_E 5 /* saw 'e' */ +#define FS_ESIGN 6 /* saw exp's sign */ +#define FS_EDIGS 7 /* saw exp's digits */ + +#define FC_DIG 0 +#define FC_DOT 1 +#define FC_E 2 +#define FC_SIGN 3 + +/* given transition,state do what action? */ +int fp_do[][NSTATE] = { + {F_INT,F_INT,F_INT, + F_FRAC,F_FRAC, + F_EXP,F_EXP,F_EXP}, /* see digit */ + {F_NADA,F_NADA,F_NADA, + F_QUIT,F_QUIT,F_QUIT,F_QUIT,F_QUIT}, /* see '.' */ + {F_QUIT,F_QUIT, + F_NADA,F_QUIT,F_NADA, + F_QUIT,F_QUIT,F_QUIT}, /* see e/E */ + {F_SIGN,F_QUIT,F_QUIT,F_QUIT,F_QUIT, + F_ESIGN,F_QUIT,F_QUIT}, /* see sign */ +}; +/* given transition,state what is new state? */ +int fp_ns[][NSTATE] = { + {FS_DIGS,FS_DIGS,FS_DIGS, + FS_DD,FS_DD, + FS_EDIGS,FS_EDIGS,FS_EDIGS}, /* see digit */ + {FS_DOT,FS_DOT,FS_DD, + }, /* see '.' */ + {0,0, + FS_E,0,FS_E, + }, /* see e/E */ + {FS_SIGNED,0,0,0,0, + FS_ESIGN,0,0}, /* see sign */ +}; +/* which states are valid terminators? */ +int fp_sval[NSTATE] = { + 0,0,1,0,1,0,0,1 +}; +#endif + +vfscanf(fp, fmt, ap) +register FILE *fp; +register char *fmt; +va_list ap; + +{ + register long n; + register int c, width, lval, cnt = 0; + int store, neg, base, wide1, endnull, rngflag, c2; + register unsigned char *p; + unsigned char delim[128], digits[17], *q; +#if FLOATS + long frac, expo; + int eneg, fraclen, fstate, trans; + double fx, fp_scan(); +#endif + + if (!*fmt) + return (0); + + c = getc(fp); + while (c > 0) + { + store = 0; + if (*fmt == '%') + { + n = 0; + width = -1; + wide1 = 1; + base = 10; + lval = (sizeof(long) == sizeof(int)); + store = 1; + endnull = 1; + neg = -1; + + strcpy(delim, "\011\012\013\014\015 "); + strcpy(digits, "0123456789ABCDEF"); + + if (fmt[1] == '*') + { + endnull = store = 0; + ++fmt; + } + + while (isdigit(*++fmt))/* width digit(s) */ + { + if (width == -1) + width = 0; + wide1 = width = (width * 10) + (*fmt - '0'); + } + --fmt; + fmtnxt: + ++fmt; + switch (tolower(*fmt)) /* tolower() is a MACRO! */ + { + case '*': + endnull = store = 0; + goto fmtnxt; + + case 'l': /* long data */ + lval = 1; + goto fmtnxt; + case 'h': /* short data */ + lval = 0; + goto fmtnxt; + + case 'i': /* any-base numeric */ + base = 0; + goto numfmt; + + case 'b': /* unsigned binary */ + base = 2; + goto numfmt; + + case 'o': /* unsigned octal */ + base = 8; + goto numfmt; + + case 'x': /* unsigned hexadecimal */ + base = 16; + goto numfmt; + + case 'd': /* SIGNED decimal */ + neg = 0; + /* FALL-THRU */ + + case 'u': /* unsigned decimal */ + numfmt:skip(); + + if (isupper(*fmt)) + lval = 1; + + if (!base) + { + base = 10; + neg = 0; + if (c == '%') + { + base = 2; + goto skip1; + } + else if (c == '0') + { + c = getc(fp); + if (c < 1) + goto savnum; + if ((c != 'x') + && (c != 'X')) + { + base = 8; + digits[8] = '\0'; + goto zeroin; + } + base = 16; + goto skip1; + } + } + + if ((neg == 0) && (base == 10) + && ((neg = (c == '-')) || (c == '+'))) + { + skip1: + c = getc(fp); + if (c < 1) + goto done; + } + + digits[base] = '\0'; + p = ((unsigned char *) + strchr(digits, toupper(c))); + + if ((!c || !p) && width) + goto done; + + while (p && width-- && c) + { + n = (n * base) + (p - digits); + c = getc(fp); + zeroin: + p = ((unsigned char *) + strchr(digits, toupper(c))); + } + savnum: + if (store) + { + if (neg == 1) + n = -n; + if (lval) + *va_arg(ap, long*) = n; + else + *va_arg(ap, short*) = n; + ++cnt; + } + break; + +#if FLOATS + case 'e': /* float */ + case 'f': + case 'g': + skip(); + + if (isupper(*fmt)) + lval = 1; + + fstate = FS_INIT; + neg = 0; + eneg = 0; + n = 0; + frac = 0; + expo = 0; + fraclen = 0; + + while (c && width--) + { + if (c >= '0' && c <= '9') + trans = FC_DIG; + else if (c == '.') + trans = FC_DOT; + else if (c == '+' || c == '-') + trans = FC_SIGN; + else if (tolower(c) == 'e') + trans = FC_E; + else + goto fdone; + + switch (fp_do[trans][fstate]) + { + case F_SIGN: + neg = (c == '-'); + break; + case F_ESIGN: + eneg = (c == '-'); + break; + case F_INT: + n = 10 * n + (c - '0'); + break; + case F_FRAC: + frac = 10 * frac + (c - '0'); + fraclen++; + break; + case F_EXP: + expo = 10 * expo + (c - '0'); + break; + case F_QUIT: + goto fdone; + } + fstate = fp_ns[trans][fstate]; + c = getc(fp); + } + + fdone: + if (!fp_sval[fstate]) + goto done; + if (store) + { + fx = fp_scan(neg, eneg, n, frac, expo, fraclen); + if (lval) + *va_arg(ap, double *) = fx; + else + *va_arg(ap, float *) = fx; + ++cnt; + } + break; +#endif + + case 'c': /* character data */ + width = wide1; + lval = endnull = 0; + delim[0] = '\0'; + goto strproc; + + case '[': /* string w/ delimiter set */ + + /* get delimiters */ + p = delim; + + if (*++fmt == '^') + { + fmt++; + lval = 0; + } + else + lval = 1; + + rngflag = 2; + if ((*fmt == ']') || (*fmt == '-')) + { + *p++ = *fmt++; + rngflag = 0; + } + + while (*fmt != ']') + { + if (*fmt == '\0') + goto done; + switch (rngflag) + { + case 1: + c2 = *(p - 2); + if (c2 <= *fmt) + { + p -= 2; + while (c2 < *fmt) + *p++ = c2++; + rngflag = 2; + break; + } + /* fall thru intentional */ + + case 0: + rngflag = (*fmt == '-'); + break; + + case 2: + rngflag = 0; + } + + *p++ = *fmt++; + } + + *p = '\0'; + goto strproc; + + case 's': /* string data */ + lval = 0; + skip(); + strproc: + /* process string */ + p = va_arg(ap, unsigned char *); + + /* if the 1st char fails, match fails */ + if (width) + { + q = ((unsigned char *) + strchr(delim, c)); + if ((c < 1) || lval == (q==0)) + { + if (endnull) + *p = '\0'; + goto done; + } + } + + for (;;) /* FOREVER */ + { + if (store) + *p++ = c; + if (((c = getc(fp)) < 1) || + (--width == 0)) + break; + + q = ((unsigned char *) + strchr(delim, c)); + if (lval == (q==0)) + break; + } + + if (store) + { + if (endnull) + *p = '\0'; + ++cnt; + } + break; + + case '\0': /* early EOS */ + --fmt; + /* FALL THRU */ + + default: + goto cmatch; + } + } + else if (isspace(*fmt)) /* skip whitespace */ + { + skip(); + } + else + { /* normal match char */ + cmatch: + if (c != *fmt) + break; + c = getc(fp); + } + + if (!*++fmt) + break; + } + + done: /* end of scan */ + if ((c == EOF) && (cnt == 0)) + return (EOF); + + if( c != EOF ) + ungetc(c, fp); + return (cnt); +} + +#endif + diff --git a/libc/stdio/stdio.c b/libc/stdio/stdio.c new file mode 100644 index 0000000..6b0dba0 --- /dev/null +++ b/libc/stdio/stdio.c @@ -0,0 +1,866 @@ +/* Copyright (C) 1996 Robert de Bath + * This file is part of the Linux-8086 C library and is distributed + * under the GNU Library General Public License. + */ + +/* This is an implementation of the C standard IO package. + */ + +#include + +#include +#include +#include +#include + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +extern FILE *__IO_list; /* For fflush at exit */ + +#ifdef __AS386_16__ +#define Inline_init +#endif + +#ifdef __AS386_32__ +#define Inline_init +#endif + +#ifndef Inline_init +#define Inline_init __io_init_vars() +#endif + +#ifdef L__stdio_init + +#define buferr (stderr->unbuf) /* Stderr is unbuffered */ + +FILE *__IO_list = 0; /* For fflush at exit */ + +static char bufin[BUFSIZ]; +static char bufout[BUFSIZ]; +#ifndef buferr +static char buferr[BUFSIZ]; +#endif + +FILE stdin[1] = +{ + {bufin, bufin, bufin, bufin, bufin + sizeof(bufin), + 0, _IOFBF | __MODE_READ | __MODE_IOTRAN} +}; + +FILE stdout[1] = +{ + {bufout, bufout, bufout, bufout, bufout + sizeof(bufout), + 1, _IOFBF | __MODE_WRITE | __MODE_IOTRAN} +}; + +FILE stderr[1] = +{ + {buferr, buferr, buferr, buferr, buferr + sizeof(buferr), + 2, _IONBF | __MODE_WRITE | __MODE_IOTRAN} +}; + +/* Call the stdio initiliser; it's main job it to call atexit */ + +#ifdef __AS386_16__ +#define STATIC static + +#asm + loc 1 ! Make sure the pointer is in the correct segment +auto_func: ! Label for bcc -M to work. + .word ___io_init_vars ! Pointer to the autorun function + .text ! So the function after is also in the correct seg. +#endasm +#endif + +#ifdef __AS386_32__ +#define STATIC static + +#asm + loc 1 ! Make sure the pointer is in the correct segment +auto_func: ! Label for bcc -M to work. + .long ___io_init_vars ! Pointer to the autorun function + .text ! So the function after is also in the correct seg. +#endasm +#endif + +#ifndef STATIC +#define STATIC +#endif + +STATIC int +__stdio_close_all() +{ + FILE *fp; + fflush(stdout); + fflush(stderr); + for (fp = __IO_list; fp; fp = fp->next) + { + fflush(fp); + close(fp->fd); + /* Note we're not de-allocating the memory */ + /* There doesn't seem to be much point :-) */ + fp->fd = -1; + } +} + +STATIC void +__io_init_vars() +{ +#ifndef __AS386_16__ +#ifndef __AS386_32__ + static int first_time = 1; + if( !first_time ) return ; + first_time = 0; +#endif +#endif + if (isatty(1)) + stdout->mode |= _IOLBF; + atexit(__stdio_close_all); +} +#endif + +#ifdef L_fputc +int +fputc(ch, fp) +int ch; +FILE *fp; +{ + register int v; + Inline_init; + + /* If last op was a read ... note fflush may change fp->mode and ret OK */ + if ((fp->mode & __MODE_READING) && fflush(fp)) + return EOF; + + v = fp->mode; + /* Can't write if there's been an EOF or error then return EOF */ + if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE) + return EOF; + + /* In MSDOS translation mode */ +#if __MODE_IOTRAN && !O_BINARY + if (ch == '\n' && (v & __MODE_IOTRAN) && fputc('\r', fp) == EOF) + return EOF; +#endif + + /* Buffer is full */ + if (fp->bufpos >= fp->bufend && fflush(fp)) + return EOF; + + /* Right! Do it! */ + *(fp->bufpos++) = ch; + fp->mode |= __MODE_WRITING; + + /* Unbuffered or Line buffered and end of line */ + if (((ch == '\n' && (v & _IOLBF)) || (v & _IONBF)) + && fflush(fp)) + return EOF; + + /* Can the macro handle this by itself ? */ + if (v & (__MODE_IOTRAN | _IOLBF | _IONBF)) + fp->bufwrite = fp->bufstart; /* Nope */ + else + fp->bufwrite = fp->bufend; /* Yup */ + + /* Correct return val */ + return (unsigned char) ch; +} +#endif + +#ifdef L_fgetc +int +fgetc(fp) +FILE *fp; +{ + int ch; + + if (fp->mode & __MODE_WRITING) + fflush(fp); + + try_again: + /* Can't read or there's been an EOF or error then return EOF */ + if ((fp->mode & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ) + return EOF; + + /* Nothing in the buffer - fill it up */ + if (fp->bufpos >= fp->bufread) + { + /* Bind stdin to stdout if it's open and line buffered */ + if( fp == stdin && stdout->fd >= 0 && (stdout->mode & _IOLBF )) + fflush(stdout); + + fp->bufpos = fp->bufread = fp->bufstart; + ch = fread(fp->bufpos, 1, fp->bufend - fp->bufstart, fp); + if (ch == 0) + return EOF; + fp->bufread += ch; + fp->mode |= __MODE_READING; + fp->mode &= ~__MODE_UNGOT; + } + ch = *(fp->bufpos++); + +#if __MODE_IOTRAN && !O_BINARY + /* In MSDOS translation mode; WARN: Doesn't work with UNIX macro */ + if (ch == '\r' && (fp->mode & __MODE_IOTRAN)) + goto try_again; +#endif + + return ch; +} +#endif + +#ifdef L_fflush +int +fflush(fp) +FILE *fp; +{ + int len, cc, rv=0; + char * bstart; + if (fp == NULL) /* On NULL flush the lot. */ + { + if (fflush(stdin)) + return EOF; + if (fflush(stdout)) + return EOF; + if (fflush(stderr)) + return EOF; + + for (fp = __IO_list; fp; fp = fp->next) + if (fflush(fp)) + return EOF; + + return 0; + } + + /* If there's output data pending */ + if (fp->mode & __MODE_WRITING) + { + len = fp->bufpos - fp->bufstart; + + if (len) + { + bstart = fp->bufstart; + /* + * The loop is so we don't get upset by signals or partial writes. + */ + do + { + cc = write(fp->fd, bstart, len); + if( cc > 0 ) + { + bstart+=cc; len-=cc; + } + } + while ( len>0 && (cc>0 || (cc == -1 && errno == EINTR))); + /* + * If we get here with len!=0 there was an error, exactly what to + * do about it is another matter ... + * + * I'll just clear the buffer. + */ + if (len) + { + fp->mode |= __MODE_ERR; + rv = EOF; + } + } + } + /* If there's data in the buffer sychronise the file positions */ + else if (fp->mode & __MODE_READING) + { + /* Humm, I think this means sync the file like fpurge() ... */ + /* Anyway the user isn't supposed to call this function when reading */ + + len = fp->bufread - fp->bufpos; /* Bytes buffered but unread */ + /* If it's a file, make it good */ + if (len > 0 && lseek(fp->fd, (long)-len, 1) < 0) + { + /* Hummm - Not certain here, I don't think this is reported */ + /* + * fp->mode |= __MODE_ERR; return EOF; + */ + } + } + + /* All done, no problem */ + fp->mode &= (~(__MODE_READING|__MODE_WRITING|__MODE_EOF|__MODE_UNGOT)); + fp->bufread = fp->bufwrite = fp->bufpos = fp->bufstart; + return rv; +} +#endif + +#ifdef L_fgets +/* Nothing special here ... */ +char * +fgets(s, count, f) +char *s; +size_t count; +FILE *f; +{ + char *ret; + register size_t i; + register int ch; + + ret = s; + for (i = count-1; i > 0; i--) + { + ch = getc(f); + if (ch == EOF) + { + if (s == ret) + return 0; + break; + } + *s++ = (char) ch; + if (ch == '\n') + break; + } + *s = 0; + + if (ferror(f)) + return 0; + return ret; +} +#endif + +#ifdef L_gets +char * +gets(str) /* BAD function; DON'T use it! */ +char *str; +{ + /* Auwlright it will work but of course _your_ program will crash */ + /* if it's given a too long line */ + register char *p = str; + register int c; + + while (((c = getc(stdin)) != EOF) && (c != '\n')) + *p++ = c; + *p = '\0'; + return (((c == EOF) && (p == str)) ? NULL : str); /* NULL == EOF */ +} +#endif + +#ifdef L_fputs +int +fputs(str, fp) +char *str; +FILE *fp; +{ + register int n = 0; + while (*str) + { + if (putc(*str++, fp) == EOF) + return (EOF); + ++n; + } + return (n); +} +#endif + +#ifdef L_puts +int +puts(str) +char *str; +{ + register int n; + + if (((n = fputs(str, stdout)) == EOF) + || (putc('\n', stdout) == EOF)) + return (EOF); + return (++n); +} +#endif + +#ifdef L_fread +/* + * fread will often be used to read in large chunks of data calling read() + * directly can be a big win in this case. Beware also fgetc calls this + * function to fill the buffer. + * + * This ignores __MODE__IOTRAN; probably exactly what you want. (It _is_ what + * fgetc wants) + */ +int +fread(buf, size, nelm, fp) +char *buf; +int size; +int nelm; +FILE *fp; +{ + int len, v; + unsigned bytes, got = 0; + Inline_init; + + v = fp->mode; + + /* Want to do this to bring the file pointer up to date */ + if (v & __MODE_WRITING) + fflush(fp); + + /* Can't read or there's been an EOF or error then return zero */ + if ((v & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ) + return 0; + + /* This could be long, doesn't seem much point tho */ + bytes = size * nelm; + + len = fp->bufread - fp->bufpos; + if (len >= bytes) /* Enough buffered */ + { + memcpy(buf, fp->bufpos, (unsigned) bytes); + fp->bufpos += bytes; + return nelm; + } + else if (len > 0) /* Some buffered */ + { + memcpy(buf, fp->bufpos, len); + fp->bufpos += len; + got = len; + } + + /* Need more; do it with a direct read */ + len = read(fp->fd, buf + got, (unsigned) (bytes - got)); + + /* Possibly for now _or_ later */ + if (len < 0) + { + fp->mode |= __MODE_ERR; + len = 0; + } + else if (len == 0) + fp->mode |= __MODE_EOF; + + return (got + len) / size; +} +#endif + +#ifdef L_fwrite +/* + * Like fread, fwrite will often be used to write out large chunks of + * data; calling write() directly can be a big win in this case. + * + * But first we check to see if there's space in the buffer. + * + * Again this ignores __MODE__IOTRAN. + */ +int +fwrite(buf, size, nelm, fp) +char *buf; +int size; +int nelm; +FILE *fp; +{ + register int v; + int len; + unsigned bytes, put; + + /* If last op was a read ... note fflush may change fp->mode and ret OK */ + if ((fp->mode & __MODE_READING) && fflush(fp)) + return 0; + + v = fp->mode; + /* Can't write or there's been an EOF or error then return 0 */ + if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE) + return 0; + + /* This could be long, doesn't seem much point tho */ + bytes = size * nelm; + + len = fp->bufend - fp->bufpos; + + /* Flush the buffer if not enough room */ + if (bytes > len) + if (fflush(fp)) + return 0; + + len = fp->bufend - fp->bufpos; + if (bytes <= len) /* It'll fit in the buffer ? */ + { + register int do_flush=0; + fp->mode |= __MODE_WRITING; + memcpy(fp->bufpos, buf, bytes); + if (v & _IOLBF) + { + if(memchr(fp->bufpos, '\n', bytes)) + do_flush=1; + } + fp->bufpos += bytes; + + /* If we're unbuffered or line buffered and have seen nl */ + if (do_flush || (v & _IONBF) != 0) + fflush(fp); + + return nelm; + } + else + /* Too big for the buffer */ + { + put = bytes; + do + { + len = write(fp->fd, buf, bytes); + if( len > 0 ) + { + buf+=len; bytes-=len; + } + } + while (len > 0 || (len == -1 && errno == EINTR)); + + if (len < 0) + fp->mode |= __MODE_ERR; + + put -= bytes; + } + + return put / size; +} +#endif + +#ifdef L_rewind +void +rewind(fp) +FILE * fp; +{ + fseek(fp, (long)0, 0); + clearerr(fp); +} +#endif + +#ifdef L_fseek +int +fseek(fp, offset, ref) +FILE *fp; +long offset; +int ref; +{ +#if 1 + /* if __MODE_READING and no ungetc ever done can just move pointer */ + + if ( (fp->mode &(__MODE_READING | __MODE_UNGOT)) == __MODE_READING && + ( ref == SEEK_SET || ref == SEEK_CUR )) + { + long fpos = lseek(fp->fd, 0L, SEEK_CUR); + if( fpos == -1 ) return EOF; + + if( ref == SEEK_CUR ) + { + ref = SEEK_SET; + offset = fpos + offset + fp->bufpos - fp->bufread; + } + if( ref == SEEK_SET ) + { + if ( offset < fpos && offset >= fpos + fp->bufstart - fp->bufread ) + { + fp->bufpos = offset - fpos + fp->bufread; + return 0; + } + } + } +#endif + + /* Use fflush to sync the pointers */ + + if (fflush(fp) == EOF) + return EOF; + if (lseek(fp->fd, offset, ref) < 0) + return EOF; + return 0; +} +#endif + +#ifdef L_ftell +long ftell(fp) +FILE * fp; +{ + long rv; + if (fflush(fp) == EOF) + return EOF; + return lseek(fp->fd, 0L, SEEK_CUR); +} +#endif + +#ifdef L_fopen +/* + * This Fopen is all three of fopen, fdopen and freopen. The macros in + * stdio.h show the other names. + */ +FILE * +__fopen(fname, fd, fp, mode) +char *fname; +int fd; +FILE *fp; +char *mode; +{ + int open_mode = 0; +#if __MODE_IOTRAN && !O_BINARY + int do_iosense = 1; +#endif + int fopen_mode = 0; + FILE *nfp = 0; + + /* If we've got an fp close the old one (freopen) */ + if (fp) + { + /* Careful, don't de-allocate it */ + fopen_mode |= (fp->mode & (__MODE_BUF | __MODE_FREEFIL | __MODE_FREEBUF)); + fp->mode &= ~(__MODE_FREEFIL | __MODE_FREEBUF); + fclose(fp); + } + + /* decode the new open mode */ + while (*mode) + switch (*mode++) + { + case 'r': + fopen_mode |= __MODE_READ; + break; + case 'w': + fopen_mode |= __MODE_WRITE; + open_mode = (O_CREAT | O_TRUNC); + break; + case 'a': + fopen_mode |= __MODE_WRITE; + open_mode = (O_CREAT | O_APPEND); + break; + case '+': + fopen_mode |= __MODE_RDWR; + break; +#if __MODE_IOTRAN || O_BINARY + case 'b': /* Binary */ + fopen_mode &= ~__MODE_IOTRAN; + open_mode |= O_BINARY; +#if __MODE_IOTRAN && !O_BINARY + do_iosense=0; +#endif + break; + case 't': /* Text */ + fopen_mode |= __MODE_IOTRAN; +#if __MODE_IOTRAN && !O_BINARY + do_iosense=0; +#endif + break; +#endif + } + + /* Add in the read/write options to mode for open() */ + switch (fopen_mode & (__MODE_READ | __MODE_WRITE)) + { + case 0: + return 0; + case __MODE_READ: + open_mode |= O_RDONLY; + break; + case __MODE_WRITE: + open_mode |= O_WRONLY; + break; + default: + open_mode |= O_RDWR; + break; + } + + /* Allocate the (FILE) before we do anything irreversable */ + if (fp == 0) + { + nfp = malloc(sizeof(FILE)); + if (nfp == 0) + return 0; + } + + /* Open the file itself */ + if (fname) + fd = open(fname, open_mode, 0666); + if (fd < 0) /* Grrrr */ + { + if (nfp) + free(nfp); + if (fp) + { + fp->mode |= fopen_mode; + fclose(fp); /* Deallocate if required */ + } + return 0; + } + + /* If this isn't freopen create a (FILE) and buffer for it */ + if (fp == 0) + { + fp = nfp; + fp->next = __IO_list; + __IO_list = fp; + + fp->mode = __MODE_FREEFIL; + if( isatty(fd) ) + { + fp->mode |= _IOLBF; +#if __MODE_IOTRAN && !O_BINARY + if( do_iosense ) fopen_mode |= __MODE_IOTRAN; +#endif + } + else + fp->mode |= _IOFBF; + fp->bufstart = malloc(BUFSIZ); + if (fp->bufstart == 0) /* Oops, no mem */ + { /* Humm, full buffering with a two(!) byte + * buffer. */ + fp->bufstart = fp->unbuf; + fp->bufend = fp->unbuf + sizeof(fp->unbuf); + } + else + { + fp->bufend = fp->bufstart + BUFSIZ; + fp->mode |= __MODE_FREEBUF; + } + } + + /* Ok, file's ready clear the buffer and save important bits */ + fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart; + fp->mode |= fopen_mode; + fp->fd = fd; + + return fp; +} +#endif + +#ifdef L_fclose +int +fclose(fp) +FILE *fp; +{ + int rv = 0; + + if (fp == 0) + { + errno = EINVAL; + return EOF; + } + if (fp->fd != -1) + { + if (fflush(fp)) + return EOF; + + if (close(fp->fd)) + rv = EOF; + fp->fd = -1; + } + + if (fp->mode & __MODE_FREEBUF) + { + free(fp->bufstart); + fp->mode &= ~__MODE_FREEBUF; + fp->bufstart = fp->bufend = 0; + } + + if (fp->mode & __MODE_FREEFIL) + { + FILE *prev = 0, *ptr; + fp->mode = 0; + + for (ptr = __IO_list; ptr && ptr != fp; ptr = ptr->next) + ; + if (ptr == fp) + { + if (prev == 0) + __IO_list = fp->next; + else + prev->next = fp->next; + } + free(fp); + } + else + fp->mode = 0; + + return rv; +} +#endif + +#ifdef L_setbuffer +void +setbuffer(fp, buf, size) +FILE * fp; +char * buf; +int size; +{ + fflush(fp); + if( fp->mode & __MODE_FREEBUF ) free(fp->bufstart); + fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF); + + if( buf == 0 ) + { + fp->bufstart = fp->unbuf; + fp->bufend = fp->unbuf + sizeof(fp->unbuf); + fp->mode |= _IONBF; + } + else + { + fp->bufstart = buf; + fp->bufend = buf+size; + fp->mode |= _IOFBF; + } + fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart; +} +#endif + +#ifdef L_setvbuf +int setvbuf(fp, buf, mode, size) +FILE * fp; +char * buf; +int mode; +size_t size; +{ + int rv = 0; + fflush(fp); + if( fp->mode & __MODE_FREEBUF ) free(fp->bufstart); + fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF); + fp->bufstart = fp->unbuf; + fp->bufend = fp->unbuf + sizeof(fp->unbuf); + fp->mode |= _IONBF; + + if( mode == _IOFBF || mode == _IOLBF ) + { + if( size <= 0 ) size = BUFSIZ; + if( buf == 0 ) + { + if( (buf = malloc(size)) != 0 ) + fp->mode |= __MODE_FREEBUF; + else rv = EOF; + } + if( buf ) + { + fp->bufstart = buf; + fp->bufend = buf+size; + fp->mode &= ~__MODE_BUF; + fp->mode |= mode; + } + } + fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart; + return rv; +} +#endif + +#ifdef L_ungetc +int +ungetc(c, fp) +int c; +FILE *fp; +{ + if (fp->mode & __MODE_WRITING) + fflush(fp); + + /* Can't read or there's been an error then return EOF */ + if ((fp->mode & (__MODE_READ | __MODE_ERR)) != __MODE_READ) + return EOF; + + /* Can't do fast fseeks */ + fp->mode |= __MODE_UNGOT; + + if( fp->bufpos > fp->bufstart ) + return *--fp->bufpos = (unsigned char) c; + else if( fp->bufread == fp->bufstart ) + return *fp->bufread++ = (unsigned char) c; + else + return EOF; +} +#endif + diff --git a/libc/stdio/stdio.h b/libc/stdio/stdio.h new file mode 100644 index 0000000..fd10923 --- /dev/null +++ b/libc/stdio/stdio.h @@ -0,0 +1,129 @@ + +#ifndef __STDIO_H +#define __STDIO_H + +#include +#include + +#ifndef SEEK_SET +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif + +#define _IOFBF 0x00 /* full buffering */ +#define _IOLBF 0x01 /* line buffering */ +#define _IONBF 0x02 /* no buffering */ +#define __MODE_BUF 0x03 /* Modal buffering dependent on isatty */ + +#define __MODE_FREEBUF 0x04 /* Buffer allocated with malloc, can free */ +#define __MODE_FREEFIL 0x08 /* FILE allocated with malloc, can free */ + +#define __MODE_READ 0x10 /* Opened in read only */ +#define __MODE_WRITE 0x20 /* Opened in write only */ +#define __MODE_RDWR 0x30 /* Opened in read/write */ + +#define __MODE_READING 0x40 /* Buffer has pending read data */ +#define __MODE_WRITING 0x80 /* Buffer has pending write data */ + +#define __MODE_EOF 0x100 /* EOF status */ +#define __MODE_ERR 0x200 /* Error status */ +#define __MODE_UNGOT 0x400 /* Buffer has been polluted by ungetc */ + +#ifdef __MSDOS__ +#define __MODE_IOTRAN 0x1000 /* MSDOS nl <-> cr,nl translation */ +#else +#define __MODE_IOTRAN 0 +#endif + +/* when you add or change fields here, be sure to change the initialization + * in stdio_init and fopen */ +struct __stdio_file { + unsigned char *bufpos; /* the next byte to write to or read from */ + unsigned char *bufread; /* the end of data returned by last read() */ + unsigned char *bufwrite; /* highest address writable by macro */ + unsigned char *bufstart; /* the start of the buffer */ + unsigned char *bufend; /* the end of the buffer; ie the byte after the last + malloc()ed byte */ + + int fd; /* the file descriptor associated with the stream */ + int mode; + + char unbuf[8]; /* The buffer for 'unbuffered' streams */ + + struct __stdio_file * next; +}; + +#define EOF (-1) +#ifndef NULL +#define NULL ((void*)0) +#endif + +typedef struct __stdio_file FILE; + +#ifdef __AS386_16__ +#define BUFSIZ (256) +#else +#define BUFSIZ (2048) +#endif + +extern FILE stdin[1]; +extern FILE stdout[1]; +extern FILE stderr[1]; + +#ifdef __MSDOS__ +#define putc(c, fp) fputc(c, fp) +#define getc(fp) fgetc(fp) +#else +#define putc(c, stream) \ + (((stream)->bufpos >= (stream)->bufwrite) ? fputc((c), (stream)) \ + : (unsigned char) (*(stream)->bufpos++ = (c)) ) + +#define getc(stream) \ + (((stream)->bufpos >= (stream)->bufread) ? fgetc(stream): \ + (*(stream)->bufpos++)) +#endif + +#define putchar(c) putc((c), stdout) +#define getchar() getc(stdin) + +#define ferror(fp) (((fp)->mode&__MODE_ERR) != 0) +#define feof(fp) (((fp)->mode&__MODE_EOF) != 0) +#define clearerr(fp) ((fp)->mode &= ~(__MODE_EOF|__MODE_ERR),0) +#define fileno(fp) ((fp)->fd) + +/* declare functions; not like it makes much difference without ANSI */ +/* RDB: The return values _are_ important, especially if we ever use + 8086 'large' model + */ + +/* These two call malloc */ +#define setlinebuf(__fp) setvbuf((__fp), (char*)0, _IOLBF, 0) +extern int setvbuf __P((FILE*, char*, int, size_t)); + +/* These don't */ +#define setbuf(__fp, __buf) setbuffer((__fp), (__buf), BUFSIZ) +extern void setbuffer __P((FILE*, char*, int)); + +extern int fgetc __P((FILE*)); +extern int fputc __P((int, FILE*)); + +extern int fclose __P((FILE*)); +extern int fflush __P((FILE*)); +extern char *fgets __P((char*, size_t, FILE*)); +extern FILE *__fopen __P((char*, int, FILE*, char*)); + +#define fopen(__file, __mode) __fopen((__file), -1, (FILE*)0, (__mode)) +#define freopen(__file, __mode, __fp) __fopen((__file), -1, (__fp), (__mode)) +#define fdopen(__file, __mode) __fopen((char*)0, (__file), (FILE*)0, (__mode)) + +extern int fputs __P((char*, FILE*)); +extern int puts __P((char*)); + +extern int printf __P ((__const char*, ...)); +extern int fprintf __P ((FILE*, __const char*, ...)); +extern int sprintf __P ((char*, __const char*, ...)); + +#define stdio_pending(fp) ((fp)->bufread>(fp)->bufpos) + +#endif /* __STDIO_H */ diff --git a/libc/stdio1/BUGS b/libc/stdio1/BUGS deleted file mode 100644 index 0e8e0db..0000000 --- a/libc/stdio1/BUGS +++ /dev/null @@ -1,15 +0,0 @@ -Error checking is known to be wanting. However the author just wants to -get it working right now. - -fread() and fwrite() are not supported. open(), read(), write(), and close() -work very well for binary data. - -fopen() is the only way to open a file. None of the temp stuff is supported, -and frepon() is unsupported. - -GNU extensions are unsupported. - -Some printf specifications may not work. Read the code for details of what -IS supported. - -Other than that, this should be a perfectly normal stdio lib when it's finished. diff --git a/libc/stdio1/Config b/libc/stdio1/Config deleted file mode 100644 index 3b3b35f..0000000 --- a/libc/stdio1/Config +++ /dev/null @@ -1,3 +0,0 @@ - - -stdio: Joel's stdio package altered by Nat diff --git a/libc/stdio1/NOTICE b/libc/stdio1/NOTICE deleted file mode 100644 index 25ca5b6..0000000 --- a/libc/stdio1/NOTICE +++ /dev/null @@ -1,17 +0,0 @@ -/* - Copyright (C) 1996 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ diff --git a/libc/stdio1/README b/libc/stdio1/README deleted file mode 100644 index ead7846..0000000 --- a/libc/stdio1/README +++ /dev/null @@ -1,8 +0,0 @@ -I found that it was helpful to have the extern stuff actually defined in -one file as not external... - -Still trying to find the other problems - -Whether it is desireable to list stdio.h as a dependency is debateable - --Joel diff --git a/libc/stdio1/TODO b/libc/stdio1/TODO deleted file mode 100644 index 481f6d9..0000000 --- a/libc/stdio1/TODO +++ /dev/null @@ -1,33 +0,0 @@ -Sun Jan 21 18:16:03 EST 1996 -- Nat Friedman -============================================ -I've made a load of changes to this code, but there's still a lot to be done. -- scanf, fscanf - - - - -input, file positioning, eof, declarations of functions, printf - -look for unsigned char references - -specifically -fix printf and figure out what's going on in there. -write idealgetline, scanf, other stuff -then deal with above stuff... - - -LATEST LIST: -printf, fprintf -scanf, fscanf -feof -seek support -error handling (not too hard since system calls only in a few places) -atexit stuff (close files; will need to add a linked list of files) -setvbuf if desired -check that fopen() and stdio_init() fill in ALL the fields -testing! - -rm NOTICE - - - diff --git a/libc/stdio1/__ffillbuf.c b/libc/stdio1/__ffillbuf.c deleted file mode 100644 index e705cbf..0000000 --- a/libc/stdio1/__ffillbuf.c +++ /dev/null @@ -1,55 +0,0 @@ -/* simplified linux __ffillbuf.c - Copyright (C) 1995 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include "stdio.h" - -/* this function makes the mistake of assuming the buffer really DOES -need to be filled. */ - -/* RDB: - * Added simple processing for EOF and errors - * As this is _only_ called from getc() the memory footprint is smaller - * if it pretends to be getc in the complex case. - */ - -int -__ffillbuf(stream) -FILE *stream; -{ - int stat; - - if( stream->fd < 0 || ferror(stream) ) return EOF; - - stat = read(stream->fd, (char *) stream->bufstart, stream->bufend - stream->bufstart); - if( stat > 0 ) - stream->bufread = stream->bufstart + stat; - else if( stat == 0 ) - { - stream->fc_eof = 1; - return EOF; - } - else - { - stream->fc_err = 1; - return EOF; - } - - stream->bufpos = stream->bufstart; - - return getc(stream); -} diff --git a/libc/stdio1/__stdio_init.c b/libc/stdio1/__stdio_init.c deleted file mode 100644 index b49bb28..0000000 --- a/libc/stdio1/__stdio_init.c +++ /dev/null @@ -1,66 +0,0 @@ -/* simplified linux __stdio_init.c - Copyright (C) 1995 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include "stdio.h" - -/* - OK, Complete hackup here, I've removed the need for the init function. - Not also I've make the types into 'unsigned char' this is so it doesn't - return EOF when it really means '\377' - */ - -static unsigned char __stdinbuf[BUFSIZ], __stdoutbuf[BUFSIZ], __stderrbuf[80]; - -static FILE __the_stdin = { - 0, - __stdinbuf, - __stdinbuf, - __stdinbuf, - __stdinbuf+sizeof(__stdinbuf), - _IOLBF, - _MODE_READ, - 0, 0, - 0, 0, 1 -}; - -static FILE __the_stdout = { - 1, - __stdoutbuf, - __stdoutbuf, - __stdoutbuf, - __stdoutbuf+sizeof(__stdoutbuf), - _IOLBF, - _MODE_WRITE, - 0, 0, - 0, 0, 1 -}; - -static FILE __the_stderr = { - 2, - __stderrbuf, - __stderrbuf, - __stderrbuf, - __stderrbuf+sizeof(__stderrbuf), - _IOLBF, - _MODE_WRITE, - 0, 0, - 0, 0, 1 -}; - -FILE *stdin = &__the_stdin, - *stdout = &__the_stdout, - *stderr = &__the_stderr; diff --git a/libc/stdio1/fclose.c b/libc/stdio1/fclose.c deleted file mode 100644 index 7ec233e..0000000 --- a/libc/stdio1/fclose.c +++ /dev/null @@ -1,41 +0,0 @@ -/* simplified linux fclose.c - Copyright (C) 1995 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include "stdio.h" - -int fclose (stream) -FILE *stream; -{ - /* only allow fclose() on what was fopen()ed. */ - /* - This isn't right, there's nothing wrong with fclosing stdin - but the next fopen/open will be given fd 0 and so become stdin - Of course you do have to be a little careful :-) - RDB - */ - - if ((stream == stdin) || (stream == stdout) || (stream == stderr)) return EOF; - - if (fflush(stream)) return EOF; - - if (close(stream->fd)) return EOF; - - free(stream->bufstart); - free(stream); - return 0; -} diff --git a/libc/stdio1/fcntl.h b/libc/stdio1/fcntl.h deleted file mode 100644 index 69fdb90..0000000 --- a/libc/stdio1/fcntl.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef __FCNTL_H -#define __FCNTL_H - -/* - * Definitions taken from the i386 Linux kernel. - */ - -/* open/fcntl */ - -#define O_ACCMODE 0003 -#define O_RDONLY 00 -#define O_WRONLY 01 -#define O_RDWR 02 -#define O_CREAT 0100 /* not fcntl */ -#define O_EXCL 0200 /* not fcntl */ -#define O_NOCTTY 0400 /* not fcntl */ -#define O_TRUNC 01000 /* not fcntl */ -#define O_APPEND 02000 -#define O_NONBLOCK 04000 -#define O_NDELAY O_NONBLOCK -#if 0 -#define O_SYNC 010000 /* Not supported */ -#define FASYNC 020000 /* Not supported */ -#endif - -#define F_DUPFD 0 /* dup */ -#define F_GETFD 1 /* get f_flags */ -#define F_SETFD 2 /* set f_flags */ -#define F_GETFL 3 /* more flags (cloexec) */ -#define F_SETFL 4 -#define F_GETLK 5 -#define F_SETLK 6 -#define F_SETLKW 7 - -#define F_SETOWN 8 /* for sockets. */ -#define F_GETOWN 9 /* for sockets. */ - -/* for F_[GET|SET]FL */ -#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ - -/* for posix fcntl() and lockf() */ -#define F_RDLCK 0 -#define F_WRLCK 1 -#define F_UNLCK 2 - -/* for old implementation of bsd flock () */ -#define F_EXLCK 4 /* or 3 */ -#define F_SHLCK 8 /* or 4 */ - -/* operations for bsd flock(), also used by the kernel implementation */ -#define LOCK_SH 1 /* shared lock */ -#define LOCK_EX 2 /* exclusive lock */ -#define LOCK_NB 4 /* or'd with one of the above to prevent - blocking */ -#define LOCK_UN 8 /* remove lock */ - -#ifdef __KERNEL__ -#define F_POSIX 1 -#define F_FLOCK 2 -#endif /* __KERNEL__ */ - -#if 0 -struct flock { - short l_type; - short l_whence; - off_t l_start; - off_t l_len; - pid_t l_pid; -}; -#endif - -#endif diff --git a/libc/stdio1/fflush.c b/libc/stdio1/fflush.c deleted file mode 100644 index c9cdac7..0000000 --- a/libc/stdio1/fflush.c +++ /dev/null @@ -1,36 +0,0 @@ -/* simplified linux fflush.c - Copyright (C) 1995 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include "stdio.h" - -int fflush(stream) -FILE *stream; -{ - if (stream == 0) return 0; - if ((stream->file_mode == _MODE_WRITE) - ||(stream->file_mode == (_MODE_WRITE & _MODE_RDWR))){ - write(stream->fd, (char *) stream->bufstart, - stream->bufpos - stream->bufstart); - stream->bufpos = stream->bufstart; - } - return 0; -} -/* TODO: return EOF or 0; support NULL stream */ -/* The only place an error can come from is the write; you're not checking RDB - */ diff --git a/libc/stdio1/fgetc.c b/libc/stdio1/fgetc.c deleted file mode 100644 index 2c41062..0000000 --- a/libc/stdio1/fgetc.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - Copyright (C) 1996 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "stdio.h" - -/* - * Make this not dependent on getc() then we can: - #define getc(fp) fgetc(fp) - * if memory is _really_ tight. - */ - -int fgetc(stream) -FILE *stream; -{ - if( stream->ungetted ) - { - stream->ungetted = 0; - return stream->ungetchar; - } - if( stream->bufpos == stream->bufread ) - return __ffillbuf(stream); - else - return *stream->bufpos++; -} diff --git a/libc/stdio1/fgets.c b/libc/stdio1/fgets.c deleted file mode 100644 index c085970..0000000 --- a/libc/stdio1/fgets.c +++ /dev/null @@ -1,50 +0,0 @@ -/* fgets.c for limited linux stdio - Copyright (C) 1996 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "stdio.h" - -/* - RDB BZZZT! This should only read upto and including any newline! -*/ - -char *fgets(s, count, f) -char *s; -size_t count; -FILE *f; -{ - char *ret; - register size_t i; - register int ch; - - ret = s; - for(i=count; i>0; i--) - { - ch = getc(f); - if( ch == EOF ) - { - if(s==ret) return 0; - break; - } - *s++ = (char) ch; - if( ch == '\n' ) break; - } - *s = 0; - - if( ferror(f) ) return 0; - return ret; -} diff --git a/libc/stdio1/fopen.c b/libc/stdio1/fopen.c deleted file mode 100644 index 1265ff5..0000000 --- a/libc/stdio1/fopen.c +++ /dev/null @@ -1,80 +0,0 @@ -/* simplified linux fopen.c - Copyright (C) 1995 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include "stdio.h" -#include - -FILE * fopen(name, openmode) -char *name; -char *openmode; -{ - FILE *new; - int openplus=0; - char basemode; - - basemode = openmode[0]; - while (openmode[0] != 0){ - switch(openmode[0]){ - case '+': openplus=1; break; - } - openmode++; - } - - new = malloc(sizeof(new)); - if( new == 0 ) return 0; - new->bufread = new->bufpos = new->bufstart = malloc(BUFSIZ); - if( new->bufstart == 0 ) { free(new) ; return 0; } - - new->bufend = new->bufstart + BUFSIZ; - new->buffer_mode = _IOFBF; - new->iotrans = 0; - new->fd = -1; - if (openplus){ - new->file_mode = _MODE_RDWR; - switch (basemode){ - case 'a': - new->fd = open(name, O_RDWR | O_APPEND | O_CREAT); - break; - case 'r': - new->fd = open(name, O_RDWR); - break; - case 'w': - new->fd = open(name, O_RDWR | O_TRUNC | O_CREAT); - break; - } - } else switch (basemode){ - case 'a': - new->fd = open(name, O_WRONLY | O_APPEND | O_CREAT); - new->file_mode = _MODE_WRITE; - break; - case 'r': - new->fd = open(name, O_RDONLY); - new->file_mode = _MODE_READ; - break; - case 'w': - new->fd = open(name, O_WRONLY | O_TRUNC | O_CREAT); - new->file_mode = _MODE_WRITE; - break; - } - if( new->fd < 0 ) - { - free(new->bufstart); - free(new); - return 0; - } - return new; -} diff --git a/libc/stdio1/fputc.c b/libc/stdio1/fputc.c deleted file mode 100644 index 939a721..0000000 --- a/libc/stdio1/fputc.c +++ /dev/null @@ -1,53 +0,0 @@ -/* simplified linux fputc.c - Copyright (C) 1995 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include "stdio.h" - -/* - * Make this not dependent on putc() then we can: - #define putc(c, fp) fputc(c, fp) - * if memory is _really_ tight. - */ - -#undef putc -#define putc(c, stream) \ - (((stream)->bufpos[0] = (c)), \ - ((stream)->bufpos++), \ - ((((stream)->bufpos == (stream)->bufend) \ - ||((stream)->buffer_mode == _IONBF) \ - ||(((stream)->buffer_mode == _IOLBF) \ - && ((stream)->bufpos != (stream)->bufstart) \ - && ((stream)->bufpos[-1] == '\n'))) \ - ? fflush(stream):0)) - -#define new_putc(c, stream) \ - ((unsigned char)( \ - ((stream)->bufpos>=(stream)->bufread) ? fputc((c), (stream)) \ - : *(stream)->bufpos++ = (c) \ - )) - -int -fputc(int c, FILE * stream) -{ -#ifdef __MSDOS__ - if( c == '\n' && stream->iotrans ) fputc('\r', stream); -#endif - return putc(c, stream); -} - - - diff --git a/libc/stdio1/fputs.c b/libc/stdio1/fputs.c deleted file mode 100644 index 41e2998..0000000 --- a/libc/stdio1/fputs.c +++ /dev/null @@ -1,32 +0,0 @@ -/* simplified linux fputs.c - Copyright (C) 1995 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include "stdio.h" - -int -fputs(__const char * string, FILE * stream) -{ - if (stream->buffer_mode != _IONBF){ - while (string[0] != 0){ - putc(string[0], stream); - string++; - } - } else write(stream->fd, string, strlen(string)); - return 0; -} diff --git a/libc/stdio1/idealgetline.c b/libc/stdio1/idealgetline.c deleted file mode 100644 index 7eacc9e..0000000 --- a/libc/stdio1/idealgetline.c +++ /dev/null @@ -1,67 +0,0 @@ -/* idealgetline.c -- my idea of an ideal getline function for stdio - Copyright (C) 1996 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* I actually intend to use this in 32 bit programs, unlike the other stuff - in this lib. IMHO GNU getline is broken. It is too hard to use. - - Just pass this function a FILE * and it will retrieve a line for you using - getc(). It will realloc() exactly the amount of memory needed, and will - generate error messages for non-ascii characters on stderr. - - This may not be your ideal. It probably generates far too many errors. - It doesn't work well for those who don't use English (but since - Linux-less-than-32 libc and kernels are each being produced by one - person in the US and one in the UK, this isn't a problem). It probably - is not what you (or I) want for interactive input. - - You're welcome to modify this routine to meet your needs. However, if - you change the semantics significantly, please change the name. - - (Maybe I should have put my own name on it so there will be no confusion - about who thought it was ideal). */ - -#include -#include - -char *idealgetline(f) -FILE *f; -{ - char c; - char *ret; - int size = 0, bufsize = 256; - - ret = malloc(256); - c = getc(f); - while ((c != EOF) && (c != '\n')){ - if ((c >= ' ') && (c <= 126)){ - ret[size] = c; - size++; - if (size == bufsize){ - bufsize += 256; - ret = realloc(ret, bufsize); - } - } else { - fprintf(stderr, "Unexpected character 0x%x encountered in input", c); - free(ret); - return 0; - } - } - ret[size] = '\0'; - size++; - return realloc(ret, size); -} diff --git a/libc/stdio1/makefile b/libc/stdio1/makefile deleted file mode 100644 index d8058b0..0000000 --- a/libc/stdio1/makefile +++ /dev/null @@ -1,36 +0,0 @@ -TOP=.. -include $(TOP)/Make.defs -OBJ = __ffillbuf.o __stdio_init.o fflush.o fgetc.o fgets.o \ - fputc.o fputs.o puts.o printf.o fopen.o fclose.o scanf.o - -#missing functions from above: printf etc, scanf etc, idealgetline -#seek - -#fopen.c, fclose.c removed because of malloc() use - -CFLAGS+=$(WALL) - -ifeq ($(PLATFORM),i86-ELKS) -CFLAGS=$(CCFLAGS) $(DEFS) -ansi -endif - -all: $(OBJ) - -libc.a: $(OBJ) - ar r ../$(LIBC) $(OBJ) - @touch libc.a - -$(OBJ): stdio.h - -test: test.o $(OBJ) - $(CC) -o test test.o $(OBJ) - -%.o: %.c - $(CC) $(CFLAGS) -o $@ $< -c - -clean: - rm -f *.o test libc.a - -transfer: - -@rm -f ../include/stdio.h - cp -p stdio.h ../include/. diff --git a/libc/stdio1/old_printf.c b/libc/stdio1/old_printf.c deleted file mode 100644 index 81d62ac..0000000 --- a/libc/stdio1/old_printf.c +++ /dev/null @@ -1,230 +0,0 @@ -/* fprintf.c for limited Linux libc - Copyright (C) 1996 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* Thanks Alan for writing the hard routine for me :-) - * Alan said that this works "most of the time". Something tells me I'm making - * it even worse! */ -/* The basic idea here is to make fprintf the core routine. printf obviously - can just call fprintf with stdout followed by all of its arguments. - sprintf() works using the fake file &the_sprintf. It's marked as fully - buffered, so that it will only write(2) when &the_sprintf->bufpos == - &the_sprintf->bufend, which I doubt will happen since &the_sprintf->bufend - = 0. The trick is that sprintf must set &the_sprintf->bufstart = - &the_sprintf->bufpos = its first argument. Not as orthagonal (is that - the right word?) as glibc's facilities for non-files, but this isn't a - library for people who have unlimited RAM budgets. (not like the libc - I use on linux/i586 enjoys an unlimited RAM budget either; I only have - 8 MB - - I'm not sure what the "correct" way to pass the variable arguments - from one function to the next is. Rather than pass the arguments - themselves, I'm passing a pointer to them. However, the following - explaination from Alan is probably a polite way of saying it will not - work on a 386 anyway. - Joel Weber - - [ I've migrated all of this code over to the ELKS stdarg that I wrote. - The accepted way to do it is for the wrapper function to accept a - variable number of arguments, use stdarg to make an argument pointer, - and then pass the argument pointer on to the core function, as I've - done here. This should definitely work on a 386, as the arguments - are still passed in the stack, and stack order is maintained. -Nat ] - */ - -/* - * This is NOT stunningly portable, but works - * for pretty dumb non ANSI compilers and is - * tight. Adjust the sizes to taste. - * - * Illegal format strings will break it. Only the - * following simple subset is supported - * - * %x - hex - * %d - decimal - * %s - string - * %c - char - * - * And the h/l length specifiers for %d/%x - * - * Alan Cox. - */ - -#include -#include "stdio.h" - -/* 17 to make sure that there's room for the trailing newline. - I'm not really sure if this is ideal... */ -static char nstring[17]="0123456789ABCDEF"; - -static unsigned char * -__numout(long i, int base) -{ - static unsigned char out[16]; - int n; - int flg = 0; - unsigned long val; - - if (i<0 && base==10) - { - flg = 1; - i = -i; - } - val = i; - - for (n = 0; n < 15; n++) - out[n] = ' '; - out[15] = '\0'; - n = 14; - do{ - out[n] = nstring[val % base]; - n--; - val /= base; - } - while(val); - if(flg) out[n--] = '-'; - return &out[n+1]; -} - -static int -internal_fprintf(FILE * stream, __const char * fmt, va_list ap) -{ - register int c; - int count = 0; - int type, base; - - while(c=*fmt++) - { - if(c!='%') - { - putc(c, stream); - count++; - } - else - { - type=1; - do { c=*fmt++; } while( c=='.' || (c>='0' && c<='9')); - if( c == 0 ) break; - if(c=='h') - { - c=*fmt++; - type = 0; - } - else if(c=='l') - { - c=*fmt++; - type = 2; - } - - switch(c) - { - case 'x': - case 'o': - case 'd': - if (c=='x') base=16; - if (c=='o') base=8; - if (c=='d') base=10; - { - long val=0; - switch(type) - { - case 0: - val=va_arg(ap, short); - break; - case 1: - val=va_arg(ap, int); - break; - case 2: - val=va_arg(ap, long); - break; - } - fputs((__const char *)__numout(val,base),stream); - } - break; - case 's': - { - char *cp; - cp=va_arg(ap, char *); - while(*cp) - putc(*cp++, stream); - break; - } - case 'c': - putc(va_arg(ap, int), stream); - break; - default: - putc(c, stream); - } - } - } - return count; -} - - -int -fprintf(FILE * stream, __const char * fmt, ...) -{ - va_list ap; - int retval; - va_start(ap, fmt); - retval=internal_fprintf(stream, fmt, ap); - va_end(ap); - return(retval); -} - -int -printf(__const char * fmt, ...) -{ - va_list ap; - int retval; - va_start(ap, fmt); - retval=internal_fprintf(stdout, fmt, ap); - va_end(ap); - return(retval); -} - -/* This is a strange way of doing sprintf, but it should work */ -int sprintf(char * s, __const char * fmt, ...) -{ - static FILE the_sprintf = { - -1, - 0, - 0, - 0, - 0, - _IOFBF, - _MODE_WRITE, - 0, 0, - 0, 0}; - va_list ap; - int retval; - - va_start(ap, fmt); - the_sprintf.bufstart = the_sprintf.bufpos = (unsigned char *) s; - the_sprintf.fc_err = 0; - - retval = internal_fprintf(&the_sprintf, fmt, ap); - /* null-terminate the string */ - putc('\0', &the_sprintf); - - va_end(ap); - return retval; -} - - - - - diff --git a/libc/stdio1/printf.c b/libc/stdio1/printf.c deleted file mode 100644 index f2a39bd..0000000 --- a/libc/stdio1/printf.c +++ /dev/null @@ -1,649 +0,0 @@ -/* fprintf.c for limited Linux libc - Copyright (C) 1996 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* Thanks Alan for writing the hard routine for me :-) - * Alan said that this works "most of the time". Something tells me I'm making - * it even worse! */ -/* The basic idea here is to make fprintf the core routine. printf obviously - can just call fprintf with stdout followed by all of its arguments. - sprintf() works using the fake file &the_sprintf. It's marked as fully - buffered, so that it will only write(2) when &the_sprintf->bufpos == - &the_sprintf->bufend, which I doubt will happen since &the_sprintf->bufend - = 0. The trick is that sprintf must set &the_sprintf->bufstart = - &the_sprintf->bufpos = its first argument. Not as orthagonal (is that - the right word?) as glibc's facilities for non-files, but this isn't a - library for people who have unlimited RAM budgets. (not like the libc - I use on linux/i586 enjoys an unlimited RAM budget either; I only have - 8 MB - - I'm not sure what the "correct" way to pass the variable arguments - from one function to the next is. Rather than pass the arguments - themselves, I'm passing a pointer to them. However, the following - explaination from Alan is probably a polite way of saying it will not - work on a 386 anyway. - Joel Weber - - [ I've migrated all of this code over to the ELKS stdarg that I wrote. - The accepted way to do it is for the wrapper function to accept a - variable number of arguments, use stdarg to make an argument pointer, - and then pass the argument pointer on to the core function, as I've - done here. This should definitely work on a 386, as the arguments - are still passed in the stack, and stack order is maintained. -Nat ] - */ - -/* - * This is NOT stunningly portable, but works - * for pretty dumb non ANSI compilers and is - * tight. Adjust the sizes to taste. - * - * Illegal format strings will break it. Only the - * following simple subset is supported - * - * %x - hex - * %d - decimal - * %s - string - * %c - char - * - * And the h/l length specifiers for %d/%x - * - * Alan Cox. - */ - -#include -#include "stdio.h" - -/* 17 to make sure that there's room for the trailing newline. - I'm not really sure if this is ideal... */ -static char nstring[17]="0123456789ABCDEF"; - -static unsigned char * -__numout(long i, int base) -{ - static unsigned char out[16]; - int n; - int flg = 0; - unsigned long val; - - if (i<0 && base==10) - { - flg = 1; - i = -i; - } - val = i; - - for (n = 0; n < 15; n++) - out[n] = ' '; - out[15] = '\0'; - n = 14; - do{ - out[n] = nstring[val % base]; - n--; - val /= base; - } - while(val); - if(flg) out[n--] = '-'; - return &out[n+1]; -} - -int -fprintf(FILE * stream, __const char * fmt, ...) -{ - va_list ap; - int retval; - va_start(ap, fmt); - retval=internal_fprintf(stream, fmt, ap); - va_end(ap); - return(retval); -} - -int -printf(__const char * fmt, ...) -{ - va_list ap; - int retval; - va_start(ap, fmt); - retval=internal_fprintf(stdout, fmt, ap); - va_end(ap); - return(retval); -} - -/* This is a strange way of doing sprintf, but it should work */ -int sprintf(char * s, __const char * fmt, ...) -{ - static FILE the_sprintf = { - -1, - 0, - 0, - 0, - 0, - _IOFBF, - _MODE_WRITE, - 0, 0, - 0, 0}; - va_list ap; - int retval; - - va_start(ap, fmt); - the_sprintf.bufstart = the_sprintf.bufpos = (unsigned char *) s; - the_sprintf.fc_err = 0; - - retval = internal_fprintf(&the_sprintf, fmt, ap); - /* null-terminate the string */ - putc('\0', &the_sprintf); - - va_end(ap); - return retval; -} - - - - - -/* - * printf.c - This is the more complete fprintf() replacement for libc8086 - * Copyright (C) 1996 Steven Huang . - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include - -/* - * This decides if the little test main program gets included - */ -#undef TEST -/* - * This decides if printf() should act like standard. When undefined, - * - prints out "(err)" if a bad format is encountered - * - supports the %b (binary) format - */ -#define STANDARD - -/* - * Shut bcc up about 'const', which doesn't seem to be handled right - * by unproto. - */ -#ifdef __BCC__ -#define const -#endif - -#define BUF_SIZE 128 -#define OUTC(c) { putc(c, stream); n++; } -#define max(a, b) ((a > b) ? a : b) -/* - * if you change the ff, you need to change the order of characters in - * the string 'flagstr' defined in _printf() - */ -#define FLAG_PADZERO (1<<0) -#define FLAG_LEFTJUST (1<<1) -#define FLAG_SIGNED (1<<2) -#define FLAG_ALT (1<<3) -#define FLAG_SPACE (1<<4) - -static char *utoa(unsigned int val, char *buf, int radix) -/* - * Converts an integer to a variable-radix string representation - * - * Note: - * Does not perform sanity checking for 'radix' - * Assumes 'buf' has memory allocated to it - */ -{ - int divisor; - char *p = buf; - const char *digitstr = "0123456789abcdef"; - - for (divisor = 1; val / divisor >= radix; divisor *= radix); - do { - *p++ = digitstr[val / divisor]; - val %= divisor; - divisor /= radix; - } while (divisor >= 1); - *p = '\0'; - return(buf); -} - -static -internal_fprintf(FILE * stream, const char * fmt, char *args) - -/* static int _printf(FILE *stream, const char *fmt, char *args) */ -/* - * The one that does all the work. - * This is a fairly complete implementation of printf(), supporting - * everything EXCEPT: - * - floating point (eEDOUfg formats) - * - pointers (realizes them but doesn't understand how to print them) - * - short and long (h/l) modifiers (dunno what to do about them) - * It's even slightly faster than gcc's printf() on Linux. Can't beat - * HP-UX's printf() though ;) - * - * Supports: - * d, signed integer - * i - * o unsigned octal integer - * u unsigned integer - * x unsigned hex lowercase a-f - * X unsigned hex uppercase A-F - * c character - * s string (character pointer) - * p void pointer (ignores it) - * % % character - * n number of characters output so far - * - * Special feature: (no really, it's not a bug =) ) - * b prints an integer in binary form (i think this might come - * in handy *somewhere*) - * - * # alternate format for octal (leading 0) and hex (0x/0X) - * 0 leading zeroes for d, i, o, u, x, and X - * - left justify, overrides '0' - * ' ' (space) force a blank in front of positive numbers - * + force a sign in front of any number - * - * width.precision, including support for '*' (reads value from - * the parameter list (MUST BE INT)) - * - * h, short/long modifiers, recognized but ignored. - * l - * - * Warning: - * The way varargs is implemented in libc is evil. Don't think - * there's a better way, but misaligned or wrong parameters - * passed to printf() can break a lot of things. I've tried my - * best to handle errors in the format string, though. - * - * Each %something field cannot exceed 'BUF_SIZE' characters, - * which I set to 128 right now. %s fields are not subject to - * this limit. - * - * Note: - * The semicolon -looks- missing in a few places but that's - * because of the macro def of 'OUTC'. did it that way to - * save a few lines of source ;) - * - * Expects a 'char *' as varargs parameter, unlike libc8086's - * printf(), which takes a 'int *' then casts it to a 'char *'. - * Either has to change, but it should be trivial. - * - * This function aborts whenever it scans an illegal format, unlike - * gcc's libc which prints out the illegal format as if it's -not- - * a format string. The 'STANDARD' preprocessor flag controls if - * if just aborts (when defined) or prints out "(err)" (when undefined). - */ -{ - /* - * the "0-+# " and "dcs..." strings are listed in my idea of their - * frequency of use, with the most popular in front. not terribly - * important but strchr() might have an easier time that way. - * if you change the ordering of 'flagstr', make sure you update - * the #define FLAG_* stuff on top of this file too. - */ - char c, *s, *f; - const char *flagstr = "0-+# ", -#ifdef STANDARD - *typestr = "dcsixXuop"; -#else - *typestr = "dcsixXuopb"; -#endif - int n = 0, flags, width, actwidth, prec, bad = 0, neg, i; - static char buf[BUF_SIZE]; - - for (c = *fmt++; c && !bad;) { - if (c != '%') { /* just copy */ - OUTC(c); - c = *fmt++; - } - else { - c = *fmt++; /* chew the % sign */ - flags = width = prec = 0; - /* - * Parse the "0-+# " flags - */ - while ((f = strchr(flagstr, c)) != NULL) { - flags |= 1 << (f - flagstr); - c = *fmt++; - } - /* - * The '*' parameter says fetch width value from varargs - */ - if (c == '*') { - width = *(int *) args; - args += sizeof(int); - if (width < 0) { - width = abs(width); - flags |= FLAG_LEFTJUST; /* set '-' flag */ - } - c = *fmt++; - } - else - /* - * scan and convert the width parameter - */ - if (isdigit(c)) - while (isdigit(c)) { - width *= 10; - width += c - '0'; - c = *fmt++; - } - /* - * a '.' means there may be a precision parameter - */ - if (c == '.') { - c = *fmt++; - /* - * fetch precision value from varargs - */ - if (c == '*') { - prec = *(int *) args; - if (prec < 0) - prec = 0; - args += sizeof(int); - c = *fmt++; - } - else - /* - * scan and convert precision field - */ - if (isdigit(c)) - while (isdigit(c)) { - prec *= 10; - prec += c - '0'; - c = *fmt++; - } - } - /* - * short and long modifiers. ignored for the moment - */ - if (c == 'h') { - c = *fmt++; - } - else - if (c == 'l') { - c = *fmt++; - } - /* - * check if it's a valid type "dioux..." - */ - if (strchr(typestr, c) != NULL) { - neg = 0; - switch (c) { - case 'd': - case 'i': { - int val = *(int *) args; - args += sizeof(int); - neg = (val < 0); - val = abs(val); - actwidth = strlen(utoa(val, buf, 10)); } - /* - * if negative or '+'/' ' flags set - */ - if (neg || (flags & FLAG_SIGNED) || (flags & FLAG_SPACE)) - actwidth++; - break; - case 'u': { - unsigned int uval = *(unsigned int *) args; - args += sizeof(unsigned int); - actwidth = strlen(utoa(uval, buf, 10)); } - /* - * if '+'/' ' flags set - */ - if ((flags & FLAG_SIGNED) || (flags & FLAG_SPACE)) - actwidth++; - break; - case 'x': - case 'X': { - int val = *(int *) args; - args += sizeof(int); - actwidth = strlen(utoa(val, buf, 16)); } - if (flags & FLAG_ALT) - actwidth += 2; - break; - case 'o': { - int val = *(int *) args; - args += sizeof(int); - actwidth = strlen(utoa(val, buf, 8)); } - if (flags & FLAG_ALT) - actwidth++; - break; - case 's': - s = *(char **) args; - args += sizeof(char *); - actwidth = strlen(s); - break; - case 'c': - buf[0] = *(char *) args; - buf[1] = '\0'; - args += sizeof(char); - actwidth = 1; - break; - /* - * dunno how to handle pointers - what's the format of - * linux86 pointers?! right now just prints "(ptr)" - */ - case 'p': - strcpy(buf, "(ptr)"); - args += sizeof(void *); - actwidth = strlen(buf); - s = buf; /* pretend we're a string */ - c = 's'; - break; -#ifndef STANDARD - case 'b': { - int val = *(int *) args; - args += sizeof(int); - actwidth = strlen(utoa(val, buf, 2)); } - break; -#endif - } - /* - * strings behave differently to the width.precision - * parameters, so handle separately. besides, we avoid - * an extra 'memcpy' to 'buf' - */ - if (c == 's') { - if (prec == 0) - prec = actwidth; - width = max(width, prec); - /* - * pad to the left if not left justified - */ - if (!(flags & FLAG_LEFTJUST)) { - for (i = width; i > prec; i--) - OUTC(' '); - } - /* - * print out entire string if no precision specified, otherwise - * that's our upper limit - */ - if (prec == 0) - for (; *s; s++) - OUTC(*s) /* no semicolon here */ - else - for (i = 0; i < prec; i++) - OUTC(s[i]); - } - else { - /* - * precision is as wide as width if it's not specified and - * the leading zero '0' flag is set, and left-justify is - * -not- set. c standard says left justify overrides the - * leading 0. - */ - if (prec == 0 && (flags & FLAG_PADZERO) && !(flags & FLAG_LEFTJUST)) - prec = width; - /* - * expand width.precision to fit the actual width. printf - * width specifies the -minimum-, and aside from the - * precision of %s fields, there's no way to specify maximum - */ - prec = max(prec, actwidth); - width = max(width, prec); - /* - * pad to the left if we're not left justified - */ - if (!(flags & FLAG_LEFTJUST)) { - for (i = width; i > prec; i--) - OUTC(' '); - } - /* - * check if we might need to print the sign - */ - if (strchr("diu", c) != NULL) { - if (neg) /* print if negative */ - OUTC('-') /* yes, no ';' here =) */ - else - if (flags & FLAG_SIGNED) /* or '+' specified */ - OUTC('+') /* nor here */ - else - if (flags & FLAG_SPACE) /* or ' ' specified */ - OUTC(' ') /* nor here */ - } - /* - * the alternate '#' flag is set. doesn't affect all though - */ - if (flags & FLAG_ALT) { - switch (c) { - case 'o': - OUTC('0'); /* leading zero for octals */ - break; - case 'x': - case 'X': /* prints 0x or 0X */ - OUTC('0'); - OUTC(c); - break; - } - } - /* - * fill the precision field with either spaces or zeroes, - * depending if we're printing numbers - */ - if (strchr("diuxXo", c) != NULL) - for (i = prec; i > actwidth; i--) - OUTC('0') - else - for (i = prec; i > actwidth; i--) - OUTC(' '); - /* - * print the field, except for 'X', which we convert to caps - */ - if (c != 'X') - for (f = buf; *f; f++) - OUTC(*f) /* none here either */ - else - for (f = buf; *f; f++) - OUTC(toupper(*f)); - } - /* - * if we're left justified, we now need to pad spaces to the - * right so that width will be correct - */ - if (flags & FLAG_LEFTJUST) - for (i = width; i > prec; i--) - OUTC(' '); - } - else { - /* - * miscellaneous %thingies - */ - switch (c) { - case '%': /* %% -> % */ - OUTC('%'); - break; - case 'n': /* %n writes current output count */ - *(*(int **) args) = n; - args += sizeof(int *); - break; - default: /* oops, got a bad %thingy */ - bad = 1; - } - } - c = *fmt++; - } - } -#ifndef STANDARD - /* - * dunno what the standard wants if the format string is badly - * formed, so i print (err) if the debug flag is set - */ - if (bad) { - OUTC('('); - OUTC('e'); - OUTC('r'); - OUTC('r'); - OUTC(')'); - } -#endif - return(n); -} - -#ifdef TEST - -#include - -int main() -{ - static unsigned char xbuf[128], *x; - char *fmt = "%s, %s %d, %.*d:%.*d\n"; - int rv1, rv2, i, dt1, dt2; - clock_t t1, t2; - - x = xbuf; - *(char **) x = "Sun"; - x += sizeof(char *); - *(char **) x = "Feb"; - x += sizeof(char *); - *(int *) x = 18; - x += sizeof(int); - *(int *) x = 2; - x += sizeof(int); - *(int *) x = 10; - x += sizeof(int); - *(int *) x = 2; - x += sizeof(int); - *(int *) x = 56; - x += sizeof(int); - t1 = clock(); - for (i = 0; i < 1000; i++) - rv1 = _printf(stdout, fmt, xbuf); - t2 = clock(); - dt1 = t2 - t1; - - t1 = clock(); - for (i = 0; i < 1000; i++) - rv2 = printf(fmt, "Sun", "Feb", 18, 2, 10, 2, 56); - t2 = clock(); - dt2 = t2 - t1; - - printf("\nrv1: %d, rv2: %d, dt1: %d, dt2: %d\n", rv1, rv2, dt1, dt2); - return(0); -} - -#endif diff --git a/libc/stdio1/puts.c b/libc/stdio1/puts.c deleted file mode 100644 index d9bb8d0..0000000 --- a/libc/stdio1/puts.c +++ /dev/null @@ -1,26 +0,0 @@ -/* simplified linux puts.c - Copyright (C) 1995 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include "stdio.h" - -int puts (string) -char *string; -{ - fputs(string, stdout); - putc('\n', stdout); - return 0; -} diff --git a/libc/stdio1/scanf.c b/libc/stdio1/scanf.c deleted file mode 100644 index 81900a1..0000000 --- a/libc/stdio1/scanf.c +++ /dev/null @@ -1,151 +0,0 @@ -/* scanf.c for limited Linux libc - Copyright (C) 1996 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* This scanf code was derived from my printf code, which in turn was - * derived from Alan Cox's printk. It was tested by [no one so far...] - */ - -/* Disclaimer: I haven't even THOUGHT about testing this. If you do decide - * to be brave and test it, and it doesn't work, you have the following - * options: - * o Send me mail telling me it doesn't work, which I will ignore - * since I already knew that. - * o Fix it yourself - * o isolate the problem and send it to the list, and maybe - * I'll fix it - */ - -/* BTW, the above comment may be destroyed once this has been tested. It's - * not nessisary for my great great grandchildren to see it when they - * take Ancient Linux History... - */ - -/* Incidentally, if it doesn't work, it may well be because I never bothered - * to learn how to use scanf()...I briefly tried it for the usaco qualification - * round, but had some wierd problems...ask me after mid February...BTW the - * problems had nothing to do with scanf(); it was still broken (hopelessly) - * when I went to getchar(). - */ - -/* Note, too that the current version probably assumes some things with - * variable argument handling that it shouldn't. Don't expect this to - * work on a 386 in 32 bit mode, don't expect this to work on a Z80, - * or anything other than an 8086. In fact, don't expect it to even - * work on an 8086 ;-) - */ - -/* One of these days the headers will work painlessly... */ -/* #include */ -/* #include */ -#include "stdio.h" - -/* note that we assume base == 10... */ -static int numin(int *num, int base, FILE *stream, int c) -{ - if ((c < '0') || (c > '9')) return 0; - *num = 0; - while ((c >= '0') && (c <= '9')) { - *num = *num * base + c - '0'; - c = getc(stream); - } - ungetc(c, stream); -} - -/* currently, the h/l specifications are ignored */ -static int internal_scanf(stream,fmt,a1) -FILE *stream; -char *fmt; -int *a1; -{ - unsigned char *p=(char *)a1; - char c; - int inc; - int count = 0; - - while(c=*fmt++) - { - do { - inc = getc(stream); - } while ((inc == ' ') || (inc == '\t') || (inc == '\n')); - - if ((c == '\n') || (c == '\t') || (c == ' ')) - ; - else if (c!='%') { - if (c != inc) { - ungetc(inc, stream); - return count; - } - } else { - int len=2; - c=*fmt++; - if(c=='h') c=*fmt++; - else if(c=='l') c=*fmt++; - - switch(c) - { - case 'x': - if (numin(p, 16, stream, inc)) count++; - else return count; - p+=2; - break; - case 'd': - if (numin(p, 10, stream, inc)) count++; - else return count; - p+=2; - break; - case 's': - { - char *cp=*((char **)p); - p+=sizeof(char *); - while(*cp) - putc(cp++, stream); - while ((inc != ' ') && (inc != '\t') - && (inc != '\n') && (inc != EOF)) { - *cp++ = inc; - inc = getc(stream); - } - ungetc(inc, stream); - break; - } - case 'c': - *p++ = inc; - p++; - break; - default: - putc('?', stream); - } - } - } - return count; -} - - -int fscanf(stream,fmt,a1) -FILE *stream; -char *fmt; -int a1; -{ - return internal_fscanf(stream,fmt,&a1); -} - -int scanf(fmt,a1) -char *fmt; -int a1; -{ - return internal_fscanf(stdout,fmt,&a1); -} diff --git a/libc/stdio1/stdio.h b/libc/stdio1/stdio.h deleted file mode 100644 index 4bd1989..0000000 --- a/libc/stdio1/stdio.h +++ /dev/null @@ -1,135 +0,0 @@ -/* simplified linux stdio.h - Copyright (C) 1995 Joel N. Weber II - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include - -#ifndef __STDIO_H -#define __STDIO_H - -/* when you add or change fields here, be sure to change the initialization - * in stdio_init and fopen */ -struct __stdio_file { - int fd; /* the file descriptor associated with the stream */ - unsigned char *bufstart; /* the start of the buffer */ - unsigned char *bufpos; /* the next byte to write to or read from */ - unsigned char *bufread; /* the end of data returned by last read() */ - unsigned char *bufend; /* the end of the buffer; ie the byte after the last - malloc()ed byte */ - int buffer_mode; -#define _IONBF 0xB111 /* no buffering */ -#define _IOLBF 0xB112 /* line buffering */ -#define _IOFBF 0xB113 /* full buffering */ - int file_mode; -#define _MODE_READ 0xB121 -#define _MODE_WRITE 0xB122 -#define _MODE_RDWR 0xB124 /* used when a file is readwrite and is ord with - what's in the buffer now */ - unsigned char ungetted, ungetchar; - /* ungetted = 1 if there's data unread; else 0 - ungetchar contains the character */ - int fc_eof:1; - int fc_err:1; /* eof and error conditions */ - int iotrans:1; /* Translate \n -> \r\n on MSDOS */ -}; - -#define EOF (-1) - -typedef struct __stdio_file FILE; - -#define BUFSIZ 256 - -extern FILE *stdin, *stdout, *stderr, *__stdsprintf; - -/* The following macros are used for all access to the buffers. If you - * know the file is unbuffered, however, you may write to it directly, as - * fputs.c does. However, be aware that sprintf assumes that by setting - * bufend to 0, no file writing will occur. Also, since NO streams use - * unbuffered mode by default and the function to change this behavior is - * not implemented yet, I'm considering disallowing raw access at the cost - * of having each byte of a string written individually. However, that - * IS what you're asking for with non-buffered mode. - * - * RDB: It's considered very bad form to use the raw read() & write() - * calls on the same files you use the stdio functions. - */ -#ifdef __MSDOS__ -#define putc(c, fp) fputc(c, fp) -#define getc(fp) fgetc(fp) -#else -#define putc(c, stream) \ - (((stream)->bufpos[0] = (c)), \ - ((stream)->bufpos++), \ - ((((stream)->bufpos == (stream)->bufend) \ - ||((stream)->buffer_mode == _IONBF) \ - ||(((stream)->buffer_mode == _IOLBF) \ - && ((stream)->bufpos != (stream)->bufstart) \ - && ((stream)->bufpos[-1] == '\n'))) \ - ? fflush(stream):0)) - -#define getc(stream) \ - ((stream)->ungetted ? (((stream)->ungetted = 0), ((stream)->ungetchar)) : \ - (((stream)->bufpos == (stream)->bufread)?__ffillbuf(stream): \ - (*(stream)->bufpos++))) - -#endif - -#define putchar(c) putc((c), stdout) -#define getchar() getc(stdin) -#define ungetc(c, stream) (((stream)->ungetted = 1), ((stream)->ungetchar = c)) - -#define ferror(fp) ((fp)->fc_err) -#define feof(fp) ((fp)->fc_eof) - -#define fileno(fp) ((fp)->fd) -/* declare functions; not like it makes much difference without ANSI */ -/* RDB: The return values _are_ important, especially if we ever use - 8086 'large' model - */ - -#ifndef __P -#define __P(x) () -#endif - -int setvbuf __P((FILE*, char*, int, size_t)); -int __ffillbuf __P((FILE*)); -void __stdio_init __P((void)); -int fclose __P((FILE*)); -int fflush __P((FILE*)); -int fgetc __P((FILE*)); -char *fgets __P((char*, size_t, FILE*)); -FILE *fopen __P((char*, char*)); - -int fputc __P((int, FILE*)); -int fputs __P((__const char*, FILE*)); -char *idealgetline __P((FILE*)); -int puts __P((char*)); - -int printf __P ((__const char *, ...)); -int fprintf __P ((FILE *, __const char *, ...)); -int sprintf __P ((char *, __const char *, ...)); - -#ifndef SEEK_SET -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 -#endif - -#endif /* __STDIO_H */ -/* TODO: add scanf, fscanf */ diff --git a/libc/stdio1/test.sh b/libc/stdio1/test.sh deleted file mode 100755 index 9d872dc..0000000 --- a/libc/stdio1/test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -echo 'rm -f *.o test *.a' -rm -f *.o test *.a -echo 'make' -make -echo 'ar r libnat.a *.o' -ar r libnat.a *.o -echo 'ranlib libnat.a' -ranlib libnat.a -echo 'gcc test.c -I- -I../include -fno-builtin -o test.o -L./ -lnat' -gcc test.c -I- -I../include -fno-builtin -o test.o -L./ -lnat diff --git a/libc/stdio2/Config b/libc/stdio2/Config deleted file mode 100644 index 665045f..0000000 --- a/libc/stdio2/Config +++ /dev/null @@ -1,4 +0,0 @@ -# - -stdio: Robert's stdio package - diff --git a/libc/stdio2/Makefile b/libc/stdio2/Makefile deleted file mode 100644 index 0fd8d97..0000000 --- a/libc/stdio2/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (C) 1995,1996 Robert de Bath -# This file is part of the Linux-8086 C library and is distributed -# under the GNU Library General Public License. - -ifneq ($(LIB_CPU),i86) -CFLAGS=$(CCFLAGS) $(LIBDEFS) -DFLOATS -endif - -ASRC=stdio.c -AOBJ=_stdio_init.o fputc.o fgetc.o fflush.o fgets.o gets.o fputs.o \ - puts.o fread.o fwrite.o fopen.o fclose.o fseek.o rewind.o ftell.o \ - setbuffer.o setvbuf.o ungetc.o - -PSRC=printf.c -POBJ=printf.o sprintf.o fprintf.o vprintf.o vsprintf.o vfprintf.o - -SSRC=scanf.c -SOBJ=scanf.o sscanf.o fscanf.o vscanf.o vsscanf.o vfscanf.o - -OBJ= $(AOBJ) $(POBJ) $(SOBJ) - -CFLAGS=$(ARCH) $(CCFLAGS) $(DEFS) - -all: $(LIBC) - @$(RM) $(OBJ) - -$(LIBC): $(LIBC)($(OBJ)) - -$(LIBC)($(AOBJ)): $(ASRC) - $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o - $(AR) $(ARFLAGS) $@ $*.o - -$(LIBC)($(POBJ)): $(PSRC) - $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o - $(AR) $(ARFLAGS) $@ $*.o - -$(LIBC)($(SOBJ)): $(SSRC) - $(CC) $(CFLAGS) -DL_$* $< -c -o $*.o - $(AR) $(ARFLAGS) $@ $*.o - -transfer: - -@rm -f ../include/stdio.h - cp -p stdio.h ../include/. - -clean: - rm -f *.o libc.a - -$(LIBC)($(OBJ)): stdio.h - diff --git a/libc/stdio2/printf.c b/libc/stdio2/printf.c deleted file mode 100644 index e41eca4..0000000 --- a/libc/stdio2/printf.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * This file based on printf.c from 'Dlibs' on the atari ST (RdeBath) - * - * 19-OCT-88: Dale Schumacher - * > John Stanley has again been a great help in debugging, particularly - * > with the printf/scanf functions which are his creation. - * - * Dale Schumacher 399 Beacon Ave. - * (alias: Dalnefre') St. Paul, MN 55104 - * dal@syntel.UUCP United States of America - * "It's not reality that's important, but how you perceive things." - * - */ - -/* Altered to use stdarg, made the core function vfprintf. - * Hooked into the stdio package using 'inside information' - * Altered sizeof() assumptions, now assumes all integers except chars - * will be either - * sizeof(xxx) == sizeof(long) or sizeof(xxx) == sizeof(short) - * - * -RDB - */ - -#include -#include -#ifdef __STDC__ -#include -#define va_strt va_start -#else -#include -#define va_strt(p,i) va_start(p) -#endif - -#include "stdio.h" - -#ifdef L_printf - -#ifdef __STDC__ -int printf(const char * fmt, ...) -#else -int printf(fmt, va_alist) -__const char *fmt; -va_dcl -#endif -{ - va_list ptr; - int rv; - va_strt(ptr, fmt); - rv = vfprintf(stdout,fmt,ptr); - va_end(ptr); - return rv; -} -#endif - -#ifdef L_sprintf -#ifdef __STDC__ -int sprintf(char * sp, const char * fmt, ...) -#else -int sprintf(sp, fmt, va_alist) -char * sp; -__const char *fmt; -va_dcl -#endif -{ -static FILE string[1] = -{ - {0, 0, (char*)(unsigned) -1, 0, (char*) (unsigned) -1, -1, - _IOFBF | __MODE_WRITE} -}; - - va_list ptr; - int rv; - va_strt(ptr, fmt); - string->bufpos = sp; - rv = vfprintf(string,fmt,ptr); - va_end(ptr); - *(string->bufpos) = 0; - return rv; -} -#endif - -#ifdef L_fprintf -#ifdef __STDC__ -int fprintf(FILE * fp, const char * fmt, ...) -#else -int fprintf(fp, fmt, va_alist) -FILE * fp; -__const char *fmt; -va_dcl -#endif -{ - va_list ptr; - int rv; - va_strt(ptr, fmt); - rv = vfprintf(fp,fmt,ptr); - va_end(ptr); - return rv; -} -#endif - -#ifdef L_vprintf -int vprintf(fmt, ap) -__const char *fmt; -va_list ap; -{ - return vfprintf(stdout,fmt,ap); -} -#endif - -#ifdef L_vsprintf -int vsprintf(sp, fmt, ap) -char * sp; -__const char *fmt; -va_list ap; -{ -static FILE string[1] = -{ - {0, 0, (char*)(unsigned) -1, 0, (char*) (unsigned) -1, -1, - _IOFBF | __MODE_WRITE} -}; - - int rv; - string->bufpos = sp; - rv = vfprintf(string,fmt,ap); - *(string->bufpos) = 0; - return rv; -} -#endif - -#ifdef L_vfprintf - -#ifdef FLOATS -int (*__fp_print)() = 0; -#endif - -static int -prtfld(op, buf, ljustf, sign, pad, width, preci, buffer_mode) -register FILE *op; -register unsigned char *buf; -int ljustf; -register char sign; -char pad; -register int width; -int preci; -int buffer_mode; -/* - * Output the given field in the manner specified by the arguments. Return - * the number of characters output. - */ -{ - register int cnt = 0, len; - register unsigned char ch; - - len = strlen(buf); - - if (*buf == '-') - sign = *buf++; - else if (sign) - len++; - - if ((preci != -1) && (len > preci)) /* limit max data width */ - len = preci; - - if (width < len) /* flexible field width or width overflow */ - width = len; - - /* - * at this point: width = total field width len = actual data width - * (including possible sign character) - */ - cnt = width; - width -= len; - - while (width || len) - { - if (!ljustf && width) /* left padding */ - { - if (len && sign && (pad == '0')) - goto showsign; - ch = pad; - --width; - } - else if (len) - { - if (sign) - { - showsign:ch = sign; /* sign */ - sign = '\0'; - } - else - ch = *buf++; /* main field */ - --len; - } - else - { - ch = pad; /* right padding */ - --width; - } - putc(ch, op); - if( ch == '\n' && buffer_mode == _IOLBF ) fflush(op); - } - - return (cnt); -} - -int -vfprintf(op, fmt, ap) -FILE *op; -register __const char *fmt; -register va_list ap; -{ - register int i, cnt = 0, ljustf, lval; - int preci, dpoint, width; - char pad, sign, radix, hash; - register char *ptmp; - char tmp[64], *ltostr(), *ultostr(); - int buffer_mode; - - /* This speeds things up a bit for unbuffered */ - buffer_mode = (op->mode&__MODE_BUF); - op->mode &= (~__MODE_BUF); - - while (*fmt) - { - if (*fmt == '%') - { - if( buffer_mode == _IONBF ) fflush(op); - ljustf = 0; /* left justify flag */ - sign = '\0'; /* sign char & status */ - pad = ' '; /* justification padding char */ - width = -1; /* min field width */ - dpoint = 0; /* found decimal point */ - preci = -1; /* max data width */ - radix = 10; /* number base */ - ptmp = tmp; /* pointer to area to print */ - hash = 0; - lval = (sizeof(int)==sizeof(long)); /* long value flaged */ - fmtnxt: - i = 0; - for(;;) - { - ++fmt; - if(*fmt < '0' || *fmt > '9' ) break; - i = (i * 10) + (*fmt - '0'); - if (dpoint) - preci = i; - else if (!i && (pad == ' ')) - { - pad = '0'; - goto fmtnxt; - } - else - width = i; - } - - switch (*fmt) - { - case '\0': /* early EOS */ - --fmt; - goto charout; - - case '-': /* left justification */ - ljustf = 1; - goto fmtnxt; - - case ' ': - case '+': /* leading sign flag */ - sign = *fmt; - goto fmtnxt; - - case '*': /* parameter width value */ - i = va_arg(ap, int); - if (dpoint) - preci = i; - else - width = i; - goto fmtnxt; - - case '.': /* secondary width field */ - dpoint = 1; - goto fmtnxt; - - case 'l': /* long data */ - lval = 1; - goto fmtnxt; - - case 'h': /* short data */ - lval = 0; - goto fmtnxt; - - case 'd': /* Signed decimal */ - case 'i': - ptmp = ltostr((long) ((lval) - ? va_arg(ap, long) - : va_arg(ap, short)), - 10); - goto printit; - - case 'b': /* Unsigned binary */ - radix = 2; - goto usproc; - - case 'o': /* Unsigned octal */ - radix = 8; - goto usproc; - - case 'p': /* Pointer */ - lval = (sizeof(char*) == sizeof(long)); - pad = '0'; - width = 6; - preci = 8; - /* fall thru */ - - case 'x': /* Unsigned hexadecimal */ - case 'X': - radix = 16; - /* fall thru */ - - case 'u': /* Unsigned decimal */ - usproc: - ptmp = ultostr((unsigned long) ((lval) - ? va_arg(ap, unsigned long) - : va_arg(ap, unsigned short)), - radix); - if( hash && radix == 8 ) { width = strlen(ptmp)+1; pad='0'; } - goto printit; - - case '#': - hash=1; - goto fmtnxt; - - case 'c': /* Character */ - ptmp[0] = va_arg(ap, int); - ptmp[1] = '\0'; - goto nopad; - - case 's': /* String */ - ptmp = va_arg(ap, char*); - nopad: - sign = '\0'; - pad = ' '; - printit: - cnt += prtfld(op, ptmp, ljustf, - sign, pad, width, preci, buffer_mode); - break; - -#if FLOATS - case 'e': /* float */ - case 'f': - case 'g': - case 'E': - case 'G': - if ( __fp_print ) - { - (*__fp_print)(&va_arg(ap, double), *fmt, preci, ptmp); - preci = -1; - goto printit; - } - /* FALLTHROUGH if no floating printf available */ -#endif - - default: /* unknown character */ - goto charout; - } - } - else - { - charout: - putc(*fmt, op); /* normal char out */ - ++cnt; - if( *fmt == '\n' && buffer_mode == _IOLBF ) fflush(op); - } - ++fmt; - } - op->mode |= buffer_mode; - if( buffer_mode == _IONBF ) fflush(op); - if( buffer_mode == _IOLBF ) op->bufwrite = op->bufstart; - return (cnt); -} -#endif diff --git a/libc/stdio2/scanf.c b/libc/stdio2/scanf.c deleted file mode 100644 index 1e0f282..0000000 --- a/libc/stdio2/scanf.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * This file based on scanf.c from 'Dlibs' on the atari ST (RdeBath) - * - * 19-OCT-88: Dale Schumacher - * > John Stanley has again been a great help in debugging, particularly - * > with the printf/scanf functions which are his creation. - * - * Dale Schumacher 399 Beacon Ave. - * (alias: Dalnefre') St. Paul, MN 55104 - * dal@syntel.UUCP United States of America - * "It's not reality that's important, but how you perceive things." - * - */ - -#include -#include -#include - -#ifdef __STDC__ -#include -#define va_strt va_start -#else -#include -#define va_strt(p,i) va_start(p) -#endif - -#ifdef L_scanf -#ifdef __STDC__ -int scanf(const char * fmt, ...) -#else -int scanf(fmt, va_alist) -__const char *fmt; -va_dcl -#endif -{ - va_list ptr; - int rv; - va_strt(ptr, fmt); - rv = vfscanf(stdin,fmt,ptr); - va_end(ptr); - return rv; -} -#endif - -#ifdef L_sscanf -#ifdef __STDC__ -int sscanf(char * sp, const char * fmt, ...) -#else -int sscanf(sp, fmt, va_alist) -char * sp; -__const char *fmt; -va_dcl -#endif -{ -static FILE string[1] = -{ - {0, (char*)(unsigned) -1, 0, 0, (char*) (unsigned) -1, -1, - _IOFBF | __MODE_READ} -}; - - va_list ptr; - int rv; - va_strt(ptr, fmt); - string->bufpos = sp; - rv = vfscanf(string,fmt,ptr); - va_end(ptr); - return rv; -} -#endif - -#ifdef L_fscanf -#ifdef __STDC__ -int fscanf(FILE * fp, const char * fmt, ...) -#else -int fscanf(fp, fmt, va_alist) -FILE * fp; -__const char *fmt; -va_dcl -#endif -{ - va_list ptr; - int rv; - va_strt(ptr, fmt); - rv = vfscanf(fp,fmt,ptr); - va_end(ptr); - return rv; -} -#endif - -#ifdef L_vscanf -int vscanf(fmt, ap) -__const char *fmt; -va_list ap; -{ - return vfscanf(stdin,fmt,ap); -} -#endif - -#ifdef L_vsscanf -int vsscanf(sp, fmt, ap) -char * sp; -__const char *fmt; -{ -static FILE string[1] = -{ - {0, (char*)(unsigned) -1, 0, 0, (char*) (unsigned) -1, -1, - _IOFBF | __MODE_READ} -}; - - string->bufpos = sp; - return vfscanf(string,fmt,ap); -} -#endif - -#ifdef L_vfscanf -/* #define skip() do{c=getc(fp); if (c<1) goto done;}while(isspace(c))*/ - -#define skip() while(isspace(c)) { if ((c=getc(fp))<1) goto done; } - -#if FLOATS -/* fp scan actions */ -#define F_NADA 0 /* just change state */ -#define F_SIGN 1 /* set sign */ -#define F_ESIGN 2 /* set exponent's sign */ -#define F_INT 3 /* adjust integer part */ -#define F_FRAC 4 /* adjust fraction part */ -#define F_EXP 5 /* adjust exponent part */ -#define F_QUIT 6 - -#define NSTATE 8 -#define FS_INIT 0 /* initial state */ -#define FS_SIGNED 1 /* saw sign */ -#define FS_DIGS 2 /* saw digits, no . */ -#define FS_DOT 3 /* saw ., no digits */ -#define FS_DD 4 /* saw digits and . */ -#define FS_E 5 /* saw 'e' */ -#define FS_ESIGN 6 /* saw exp's sign */ -#define FS_EDIGS 7 /* saw exp's digits */ - -#define FC_DIG 0 -#define FC_DOT 1 -#define FC_E 2 -#define FC_SIGN 3 - -/* given transition,state do what action? */ -int fp_do[][NSTATE] = { - {F_INT,F_INT,F_INT, - F_FRAC,F_FRAC, - F_EXP,F_EXP,F_EXP}, /* see digit */ - {F_NADA,F_NADA,F_NADA, - F_QUIT,F_QUIT,F_QUIT,F_QUIT,F_QUIT}, /* see '.' */ - {F_QUIT,F_QUIT, - F_NADA,F_QUIT,F_NADA, - F_QUIT,F_QUIT,F_QUIT}, /* see e/E */ - {F_SIGN,F_QUIT,F_QUIT,F_QUIT,F_QUIT, - F_ESIGN,F_QUIT,F_QUIT}, /* see sign */ -}; -/* given transition,state what is new state? */ -int fp_ns[][NSTATE] = { - {FS_DIGS,FS_DIGS,FS_DIGS, - FS_DD,FS_DD, - FS_EDIGS,FS_EDIGS,FS_EDIGS}, /* see digit */ - {FS_DOT,FS_DOT,FS_DD, - }, /* see '.' */ - {0,0, - FS_E,0,FS_E, - }, /* see e/E */ - {FS_SIGNED,0,0,0,0, - FS_ESIGN,0,0}, /* see sign */ -}; -/* which states are valid terminators? */ -int fp_sval[NSTATE] = { - 0,0,1,0,1,0,0,1 -}; -#endif - -vfscanf(fp, fmt, ap) -register FILE *fp; -register char *fmt; -va_list ap; - -{ - register long n; - register int c, width, lval, cnt = 0; - int store, neg, base, wide1, endnull, rngflag, c2; - register unsigned char *p; - unsigned char delim[128], digits[17], *q; -#if FLOATS - long frac, expo; - int eneg, fraclen, fstate, trans; - double fx, fp_scan(); -#endif - - if (!*fmt) - return (0); - - c = getc(fp); - while (c > 0) - { - store = 0; - if (*fmt == '%') - { - n = 0; - width = -1; - wide1 = 1; - base = 10; - lval = (sizeof(long) == sizeof(int)); - store = 1; - endnull = 1; - neg = -1; - - strcpy(delim, "\011\012\013\014\015 "); - strcpy(digits, "0123456789ABCDEF"); - - if (fmt[1] == '*') - { - endnull = store = 0; - ++fmt; - } - - while (isdigit(*++fmt))/* width digit(s) */ - { - if (width == -1) - width = 0; - wide1 = width = (width * 10) + (*fmt - '0'); - } - --fmt; - fmtnxt: - ++fmt; - switch (tolower(*fmt)) /* tolower() is a MACRO! */ - { - case '*': - endnull = store = 0; - goto fmtnxt; - - case 'l': /* long data */ - lval = 1; - goto fmtnxt; - case 'h': /* short data */ - lval = 0; - goto fmtnxt; - - case 'i': /* any-base numeric */ - base = 0; - goto numfmt; - - case 'b': /* unsigned binary */ - base = 2; - goto numfmt; - - case 'o': /* unsigned octal */ - base = 8; - goto numfmt; - - case 'x': /* unsigned hexadecimal */ - base = 16; - goto numfmt; - - case 'd': /* SIGNED decimal */ - neg = 0; - /* FALL-THRU */ - - case 'u': /* unsigned decimal */ - numfmt:skip(); - - if (isupper(*fmt)) - lval = 1; - - if (!base) - { - base = 10; - neg = 0; - if (c == '%') - { - base = 2; - goto skip1; - } - else if (c == '0') - { - c = getc(fp); - if (c < 1) - goto savnum; - if ((c != 'x') - && (c != 'X')) - { - base = 8; - digits[8] = '\0'; - goto zeroin; - } - base = 16; - goto skip1; - } - } - - if ((neg == 0) && (base == 10) - && ((neg = (c == '-')) || (c == '+'))) - { - skip1: - c = getc(fp); - if (c < 1) - goto done; - } - - digits[base] = '\0'; - p = ((unsigned char *) - strchr(digits, toupper(c))); - - if ((!c || !p) && width) - goto done; - - while (p && width-- && c) - { - n = (n * base) + (p - digits); - c = getc(fp); - zeroin: - p = ((unsigned char *) - strchr(digits, toupper(c))); - } - savnum: - if (store) - { - if (neg == 1) - n = -n; - if (lval) - *va_arg(ap, long*) = n; - else - *va_arg(ap, short*) = n; - ++cnt; - } - break; - -#if FLOATS - case 'e': /* float */ - case 'f': - case 'g': - skip(); - - if (isupper(*fmt)) - lval = 1; - - fstate = FS_INIT; - neg = 0; - eneg = 0; - n = 0; - frac = 0; - expo = 0; - fraclen = 0; - - while (c && width--) - { - if (c >= '0' && c <= '9') - trans = FC_DIG; - else if (c == '.') - trans = FC_DOT; - else if (c == '+' || c == '-') - trans = FC_SIGN; - else if (tolower(c) == 'e') - trans = FC_E; - else - goto fdone; - - switch (fp_do[trans][fstate]) - { - case F_SIGN: - neg = (c == '-'); - break; - case F_ESIGN: - eneg = (c == '-'); - break; - case F_INT: - n = 10 * n + (c - '0'); - break; - case F_FRAC: - frac = 10 * frac + (c - '0'); - fraclen++; - break; - case F_EXP: - expo = 10 * expo + (c - '0'); - break; - case F_QUIT: - goto fdone; - } - fstate = fp_ns[trans][fstate]; - c = getc(fp); - } - - fdone: - if (!fp_sval[fstate]) - goto done; - if (store) - { - fx = fp_scan(neg, eneg, n, frac, expo, fraclen); - if (lval) - *va_arg(ap, double *) = fx; - else - *va_arg(ap, float *) = fx; - ++cnt; - } - break; -#endif - - case 'c': /* character data */ - width = wide1; - lval = endnull = 0; - delim[0] = '\0'; - goto strproc; - - case '[': /* string w/ delimiter set */ - - /* get delimiters */ - p = delim; - - if (*++fmt == '^') - { - fmt++; - lval = 0; - } - else - lval = 1; - - rngflag = 2; - if ((*fmt == ']') || (*fmt == '-')) - { - *p++ = *fmt++; - rngflag = 0; - } - - while (*fmt != ']') - { - if (*fmt == '\0') - goto done; - switch (rngflag) - { - case 1: - c2 = *(p - 2); - if (c2 <= *fmt) - { - p -= 2; - while (c2 < *fmt) - *p++ = c2++; - rngflag = 2; - break; - } - /* fall thru intentional */ - - case 0: - rngflag = (*fmt == '-'); - break; - - case 2: - rngflag = 0; - } - - *p++ = *fmt++; - } - - *p = '\0'; - goto strproc; - - case 's': /* string data */ - lval = 0; - skip(); - strproc: - /* process string */ - p = va_arg(ap, unsigned char *); - - /* if the 1st char fails, match fails */ - if (width) - { - q = ((unsigned char *) - strchr(delim, c)); - if ((c < 1) || lval == (q==0)) - { - if (endnull) - *p = '\0'; - goto done; - } - } - - for (;;) /* FOREVER */ - { - if (store) - *p++ = c; - if (((c = getc(fp)) < 1) || - (--width == 0)) - break; - - q = ((unsigned char *) - strchr(delim, c)); - if (lval == (q==0)) - break; - } - - if (store) - { - if (endnull) - *p = '\0'; - ++cnt; - } - break; - - case '\0': /* early EOS */ - --fmt; - /* FALL THRU */ - - default: - goto cmatch; - } - } - else if (isspace(*fmt)) /* skip whitespace */ - { - skip(); - } - else - { /* normal match char */ - cmatch: - if (c != *fmt) - break; - c = getc(fp); - } - - if (!*++fmt) - break; - } - - done: /* end of scan */ - if ((c == EOF) && (cnt == 0)) - return (EOF); - - if( c != EOF ) - ungetc(c, fp); - return (cnt); -} - -#endif - diff --git a/libc/stdio2/stdio.c b/libc/stdio2/stdio.c deleted file mode 100644 index 6b0dba0..0000000 --- a/libc/stdio2/stdio.c +++ /dev/null @@ -1,866 +0,0 @@ -/* Copyright (C) 1996 Robert de Bath - * This file is part of the Linux-8086 C library and is distributed - * under the GNU Library General Public License. - */ - -/* This is an implementation of the C standard IO package. - */ - -#include - -#include -#include -#include -#include - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -extern FILE *__IO_list; /* For fflush at exit */ - -#ifdef __AS386_16__ -#define Inline_init -#endif - -#ifdef __AS386_32__ -#define Inline_init -#endif - -#ifndef Inline_init -#define Inline_init __io_init_vars() -#endif - -#ifdef L__stdio_init - -#define buferr (stderr->unbuf) /* Stderr is unbuffered */ - -FILE *__IO_list = 0; /* For fflush at exit */ - -static char bufin[BUFSIZ]; -static char bufout[BUFSIZ]; -#ifndef buferr -static char buferr[BUFSIZ]; -#endif - -FILE stdin[1] = -{ - {bufin, bufin, bufin, bufin, bufin + sizeof(bufin), - 0, _IOFBF | __MODE_READ | __MODE_IOTRAN} -}; - -FILE stdout[1] = -{ - {bufout, bufout, bufout, bufout, bufout + sizeof(bufout), - 1, _IOFBF | __MODE_WRITE | __MODE_IOTRAN} -}; - -FILE stderr[1] = -{ - {buferr, buferr, buferr, buferr, buferr + sizeof(buferr), - 2, _IONBF | __MODE_WRITE | __MODE_IOTRAN} -}; - -/* Call the stdio initiliser; it's main job it to call atexit */ - -#ifdef __AS386_16__ -#define STATIC static - -#asm - loc 1 ! Make sure the pointer is in the correct segment -auto_func: ! Label for bcc -M to work. - .word ___io_init_vars ! Pointer to the autorun function - .text ! So the function after is also in the correct seg. -#endasm -#endif - -#ifdef __AS386_32__ -#define STATIC static - -#asm - loc 1 ! Make sure the pointer is in the correct segment -auto_func: ! Label for bcc -M to work. - .long ___io_init_vars ! Pointer to the autorun function - .text ! So the function after is also in the correct seg. -#endasm -#endif - -#ifndef STATIC -#define STATIC -#endif - -STATIC int -__stdio_close_all() -{ - FILE *fp; - fflush(stdout); - fflush(stderr); - for (fp = __IO_list; fp; fp = fp->next) - { - fflush(fp); - close(fp->fd); - /* Note we're not de-allocating the memory */ - /* There doesn't seem to be much point :-) */ - fp->fd = -1; - } -} - -STATIC void -__io_init_vars() -{ -#ifndef __AS386_16__ -#ifndef __AS386_32__ - static int first_time = 1; - if( !first_time ) return ; - first_time = 0; -#endif -#endif - if (isatty(1)) - stdout->mode |= _IOLBF; - atexit(__stdio_close_all); -} -#endif - -#ifdef L_fputc -int -fputc(ch, fp) -int ch; -FILE *fp; -{ - register int v; - Inline_init; - - /* If last op was a read ... note fflush may change fp->mode and ret OK */ - if ((fp->mode & __MODE_READING) && fflush(fp)) - return EOF; - - v = fp->mode; - /* Can't write if there's been an EOF or error then return EOF */ - if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE) - return EOF; - - /* In MSDOS translation mode */ -#if __MODE_IOTRAN && !O_BINARY - if (ch == '\n' && (v & __MODE_IOTRAN) && fputc('\r', fp) == EOF) - return EOF; -#endif - - /* Buffer is full */ - if (fp->bufpos >= fp->bufend && fflush(fp)) - return EOF; - - /* Right! Do it! */ - *(fp->bufpos++) = ch; - fp->mode |= __MODE_WRITING; - - /* Unbuffered or Line buffered and end of line */ - if (((ch == '\n' && (v & _IOLBF)) || (v & _IONBF)) - && fflush(fp)) - return EOF; - - /* Can the macro handle this by itself ? */ - if (v & (__MODE_IOTRAN | _IOLBF | _IONBF)) - fp->bufwrite = fp->bufstart; /* Nope */ - else - fp->bufwrite = fp->bufend; /* Yup */ - - /* Correct return val */ - return (unsigned char) ch; -} -#endif - -#ifdef L_fgetc -int -fgetc(fp) -FILE *fp; -{ - int ch; - - if (fp->mode & __MODE_WRITING) - fflush(fp); - - try_again: - /* Can't read or there's been an EOF or error then return EOF */ - if ((fp->mode & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ) - return EOF; - - /* Nothing in the buffer - fill it up */ - if (fp->bufpos >= fp->bufread) - { - /* Bind stdin to stdout if it's open and line buffered */ - if( fp == stdin && stdout->fd >= 0 && (stdout->mode & _IOLBF )) - fflush(stdout); - - fp->bufpos = fp->bufread = fp->bufstart; - ch = fread(fp->bufpos, 1, fp->bufend - fp->bufstart, fp); - if (ch == 0) - return EOF; - fp->bufread += ch; - fp->mode |= __MODE_READING; - fp->mode &= ~__MODE_UNGOT; - } - ch = *(fp->bufpos++); - -#if __MODE_IOTRAN && !O_BINARY - /* In MSDOS translation mode; WARN: Doesn't work with UNIX macro */ - if (ch == '\r' && (fp->mode & __MODE_IOTRAN)) - goto try_again; -#endif - - return ch; -} -#endif - -#ifdef L_fflush -int -fflush(fp) -FILE *fp; -{ - int len, cc, rv=0; - char * bstart; - if (fp == NULL) /* On NULL flush the lot. */ - { - if (fflush(stdin)) - return EOF; - if (fflush(stdout)) - return EOF; - if (fflush(stderr)) - return EOF; - - for (fp = __IO_list; fp; fp = fp->next) - if (fflush(fp)) - return EOF; - - return 0; - } - - /* If there's output data pending */ - if (fp->mode & __MODE_WRITING) - { - len = fp->bufpos - fp->bufstart; - - if (len) - { - bstart = fp->bufstart; - /* - * The loop is so we don't get upset by signals or partial writes. - */ - do - { - cc = write(fp->fd, bstart, len); - if( cc > 0 ) - { - bstart+=cc; len-=cc; - } - } - while ( len>0 && (cc>0 || (cc == -1 && errno == EINTR))); - /* - * If we get here with len!=0 there was an error, exactly what to - * do about it is another matter ... - * - * I'll just clear the buffer. - */ - if (len) - { - fp->mode |= __MODE_ERR; - rv = EOF; - } - } - } - /* If there's data in the buffer sychronise the file positions */ - else if (fp->mode & __MODE_READING) - { - /* Humm, I think this means sync the file like fpurge() ... */ - /* Anyway the user isn't supposed to call this function when reading */ - - len = fp->bufread - fp->bufpos; /* Bytes buffered but unread */ - /* If it's a file, make it good */ - if (len > 0 && lseek(fp->fd, (long)-len, 1) < 0) - { - /* Hummm - Not certain here, I don't think this is reported */ - /* - * fp->mode |= __MODE_ERR; return EOF; - */ - } - } - - /* All done, no problem */ - fp->mode &= (~(__MODE_READING|__MODE_WRITING|__MODE_EOF|__MODE_UNGOT)); - fp->bufread = fp->bufwrite = fp->bufpos = fp->bufstart; - return rv; -} -#endif - -#ifdef L_fgets -/* Nothing special here ... */ -char * -fgets(s, count, f) -char *s; -size_t count; -FILE *f; -{ - char *ret; - register size_t i; - register int ch; - - ret = s; - for (i = count-1; i > 0; i--) - { - ch = getc(f); - if (ch == EOF) - { - if (s == ret) - return 0; - break; - } - *s++ = (char) ch; - if (ch == '\n') - break; - } - *s = 0; - - if (ferror(f)) - return 0; - return ret; -} -#endif - -#ifdef L_gets -char * -gets(str) /* BAD function; DON'T use it! */ -char *str; -{ - /* Auwlright it will work but of course _your_ program will crash */ - /* if it's given a too long line */ - register char *p = str; - register int c; - - while (((c = getc(stdin)) != EOF) && (c != '\n')) - *p++ = c; - *p = '\0'; - return (((c == EOF) && (p == str)) ? NULL : str); /* NULL == EOF */ -} -#endif - -#ifdef L_fputs -int -fputs(str, fp) -char *str; -FILE *fp; -{ - register int n = 0; - while (*str) - { - if (putc(*str++, fp) == EOF) - return (EOF); - ++n; - } - return (n); -} -#endif - -#ifdef L_puts -int -puts(str) -char *str; -{ - register int n; - - if (((n = fputs(str, stdout)) == EOF) - || (putc('\n', stdout) == EOF)) - return (EOF); - return (++n); -} -#endif - -#ifdef L_fread -/* - * fread will often be used to read in large chunks of data calling read() - * directly can be a big win in this case. Beware also fgetc calls this - * function to fill the buffer. - * - * This ignores __MODE__IOTRAN; probably exactly what you want. (It _is_ what - * fgetc wants) - */ -int -fread(buf, size, nelm, fp) -char *buf; -int size; -int nelm; -FILE *fp; -{ - int len, v; - unsigned bytes, got = 0; - Inline_init; - - v = fp->mode; - - /* Want to do this to bring the file pointer up to date */ - if (v & __MODE_WRITING) - fflush(fp); - - /* Can't read or there's been an EOF or error then return zero */ - if ((v & (__MODE_READ | __MODE_EOF | __MODE_ERR)) != __MODE_READ) - return 0; - - /* This could be long, doesn't seem much point tho */ - bytes = size * nelm; - - len = fp->bufread - fp->bufpos; - if (len >= bytes) /* Enough buffered */ - { - memcpy(buf, fp->bufpos, (unsigned) bytes); - fp->bufpos += bytes; - return nelm; - } - else if (len > 0) /* Some buffered */ - { - memcpy(buf, fp->bufpos, len); - fp->bufpos += len; - got = len; - } - - /* Need more; do it with a direct read */ - len = read(fp->fd, buf + got, (unsigned) (bytes - got)); - - /* Possibly for now _or_ later */ - if (len < 0) - { - fp->mode |= __MODE_ERR; - len = 0; - } - else if (len == 0) - fp->mode |= __MODE_EOF; - - return (got + len) / size; -} -#endif - -#ifdef L_fwrite -/* - * Like fread, fwrite will often be used to write out large chunks of - * data; calling write() directly can be a big win in this case. - * - * But first we check to see if there's space in the buffer. - * - * Again this ignores __MODE__IOTRAN. - */ -int -fwrite(buf, size, nelm, fp) -char *buf; -int size; -int nelm; -FILE *fp; -{ - register int v; - int len; - unsigned bytes, put; - - /* If last op was a read ... note fflush may change fp->mode and ret OK */ - if ((fp->mode & __MODE_READING) && fflush(fp)) - return 0; - - v = fp->mode; - /* Can't write or there's been an EOF or error then return 0 */ - if ((v & (__MODE_WRITE | __MODE_EOF | __MODE_ERR)) != __MODE_WRITE) - return 0; - - /* This could be long, doesn't seem much point tho */ - bytes = size * nelm; - - len = fp->bufend - fp->bufpos; - - /* Flush the buffer if not enough room */ - if (bytes > len) - if (fflush(fp)) - return 0; - - len = fp->bufend - fp->bufpos; - if (bytes <= len) /* It'll fit in the buffer ? */ - { - register int do_flush=0; - fp->mode |= __MODE_WRITING; - memcpy(fp->bufpos, buf, bytes); - if (v & _IOLBF) - { - if(memchr(fp->bufpos, '\n', bytes)) - do_flush=1; - } - fp->bufpos += bytes; - - /* If we're unbuffered or line buffered and have seen nl */ - if (do_flush || (v & _IONBF) != 0) - fflush(fp); - - return nelm; - } - else - /* Too big for the buffer */ - { - put = bytes; - do - { - len = write(fp->fd, buf, bytes); - if( len > 0 ) - { - buf+=len; bytes-=len; - } - } - while (len > 0 || (len == -1 && errno == EINTR)); - - if (len < 0) - fp->mode |= __MODE_ERR; - - put -= bytes; - } - - return put / size; -} -#endif - -#ifdef L_rewind -void -rewind(fp) -FILE * fp; -{ - fseek(fp, (long)0, 0); - clearerr(fp); -} -#endif - -#ifdef L_fseek -int -fseek(fp, offset, ref) -FILE *fp; -long offset; -int ref; -{ -#if 1 - /* if __MODE_READING and no ungetc ever done can just move pointer */ - - if ( (fp->mode &(__MODE_READING | __MODE_UNGOT)) == __MODE_READING && - ( ref == SEEK_SET || ref == SEEK_CUR )) - { - long fpos = lseek(fp->fd, 0L, SEEK_CUR); - if( fpos == -1 ) return EOF; - - if( ref == SEEK_CUR ) - { - ref = SEEK_SET; - offset = fpos + offset + fp->bufpos - fp->bufread; - } - if( ref == SEEK_SET ) - { - if ( offset < fpos && offset >= fpos + fp->bufstart - fp->bufread ) - { - fp->bufpos = offset - fpos + fp->bufread; - return 0; - } - } - } -#endif - - /* Use fflush to sync the pointers */ - - if (fflush(fp) == EOF) - return EOF; - if (lseek(fp->fd, offset, ref) < 0) - return EOF; - return 0; -} -#endif - -#ifdef L_ftell -long ftell(fp) -FILE * fp; -{ - long rv; - if (fflush(fp) == EOF) - return EOF; - return lseek(fp->fd, 0L, SEEK_CUR); -} -#endif - -#ifdef L_fopen -/* - * This Fopen is all three of fopen, fdopen and freopen. The macros in - * stdio.h show the other names. - */ -FILE * -__fopen(fname, fd, fp, mode) -char *fname; -int fd; -FILE *fp; -char *mode; -{ - int open_mode = 0; -#if __MODE_IOTRAN && !O_BINARY - int do_iosense = 1; -#endif - int fopen_mode = 0; - FILE *nfp = 0; - - /* If we've got an fp close the old one (freopen) */ - if (fp) - { - /* Careful, don't de-allocate it */ - fopen_mode |= (fp->mode & (__MODE_BUF | __MODE_FREEFIL | __MODE_FREEBUF)); - fp->mode &= ~(__MODE_FREEFIL | __MODE_FREEBUF); - fclose(fp); - } - - /* decode the new open mode */ - while (*mode) - switch (*mode++) - { - case 'r': - fopen_mode |= __MODE_READ; - break; - case 'w': - fopen_mode |= __MODE_WRITE; - open_mode = (O_CREAT | O_TRUNC); - break; - case 'a': - fopen_mode |= __MODE_WRITE; - open_mode = (O_CREAT | O_APPEND); - break; - case '+': - fopen_mode |= __MODE_RDWR; - break; -#if __MODE_IOTRAN || O_BINARY - case 'b': /* Binary */ - fopen_mode &= ~__MODE_IOTRAN; - open_mode |= O_BINARY; -#if __MODE_IOTRAN && !O_BINARY - do_iosense=0; -#endif - break; - case 't': /* Text */ - fopen_mode |= __MODE_IOTRAN; -#if __MODE_IOTRAN && !O_BINARY - do_iosense=0; -#endif - break; -#endif - } - - /* Add in the read/write options to mode for open() */ - switch (fopen_mode & (__MODE_READ | __MODE_WRITE)) - { - case 0: - return 0; - case __MODE_READ: - open_mode |= O_RDONLY; - break; - case __MODE_WRITE: - open_mode |= O_WRONLY; - break; - default: - open_mode |= O_RDWR; - break; - } - - /* Allocate the (FILE) before we do anything irreversable */ - if (fp == 0) - { - nfp = malloc(sizeof(FILE)); - if (nfp == 0) - return 0; - } - - /* Open the file itself */ - if (fname) - fd = open(fname, open_mode, 0666); - if (fd < 0) /* Grrrr */ - { - if (nfp) - free(nfp); - if (fp) - { - fp->mode |= fopen_mode; - fclose(fp); /* Deallocate if required */ - } - return 0; - } - - /* If this isn't freopen create a (FILE) and buffer for it */ - if (fp == 0) - { - fp = nfp; - fp->next = __IO_list; - __IO_list = fp; - - fp->mode = __MODE_FREEFIL; - if( isatty(fd) ) - { - fp->mode |= _IOLBF; -#if __MODE_IOTRAN && !O_BINARY - if( do_iosense ) fopen_mode |= __MODE_IOTRAN; -#endif - } - else - fp->mode |= _IOFBF; - fp->bufstart = malloc(BUFSIZ); - if (fp->bufstart == 0) /* Oops, no mem */ - { /* Humm, full buffering with a two(!) byte - * buffer. */ - fp->bufstart = fp->unbuf; - fp->bufend = fp->unbuf + sizeof(fp->unbuf); - } - else - { - fp->bufend = fp->bufstart + BUFSIZ; - fp->mode |= __MODE_FREEBUF; - } - } - - /* Ok, file's ready clear the buffer and save important bits */ - fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart; - fp->mode |= fopen_mode; - fp->fd = fd; - - return fp; -} -#endif - -#ifdef L_fclose -int -fclose(fp) -FILE *fp; -{ - int rv = 0; - - if (fp == 0) - { - errno = EINVAL; - return EOF; - } - if (fp->fd != -1) - { - if (fflush(fp)) - return EOF; - - if (close(fp->fd)) - rv = EOF; - fp->fd = -1; - } - - if (fp->mode & __MODE_FREEBUF) - { - free(fp->bufstart); - fp->mode &= ~__MODE_FREEBUF; - fp->bufstart = fp->bufend = 0; - } - - if (fp->mode & __MODE_FREEFIL) - { - FILE *prev = 0, *ptr; - fp->mode = 0; - - for (ptr = __IO_list; ptr && ptr != fp; ptr = ptr->next) - ; - if (ptr == fp) - { - if (prev == 0) - __IO_list = fp->next; - else - prev->next = fp->next; - } - free(fp); - } - else - fp->mode = 0; - - return rv; -} -#endif - -#ifdef L_setbuffer -void -setbuffer(fp, buf, size) -FILE * fp; -char * buf; -int size; -{ - fflush(fp); - if( fp->mode & __MODE_FREEBUF ) free(fp->bufstart); - fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF); - - if( buf == 0 ) - { - fp->bufstart = fp->unbuf; - fp->bufend = fp->unbuf + sizeof(fp->unbuf); - fp->mode |= _IONBF; - } - else - { - fp->bufstart = buf; - fp->bufend = buf+size; - fp->mode |= _IOFBF; - } - fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart; -} -#endif - -#ifdef L_setvbuf -int setvbuf(fp, buf, mode, size) -FILE * fp; -char * buf; -int mode; -size_t size; -{ - int rv = 0; - fflush(fp); - if( fp->mode & __MODE_FREEBUF ) free(fp->bufstart); - fp->mode &= ~(__MODE_FREEBUF|__MODE_BUF); - fp->bufstart = fp->unbuf; - fp->bufend = fp->unbuf + sizeof(fp->unbuf); - fp->mode |= _IONBF; - - if( mode == _IOFBF || mode == _IOLBF ) - { - if( size <= 0 ) size = BUFSIZ; - if( buf == 0 ) - { - if( (buf = malloc(size)) != 0 ) - fp->mode |= __MODE_FREEBUF; - else rv = EOF; - } - if( buf ) - { - fp->bufstart = buf; - fp->bufend = buf+size; - fp->mode &= ~__MODE_BUF; - fp->mode |= mode; - } - } - fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart; - return rv; -} -#endif - -#ifdef L_ungetc -int -ungetc(c, fp) -int c; -FILE *fp; -{ - if (fp->mode & __MODE_WRITING) - fflush(fp); - - /* Can't read or there's been an error then return EOF */ - if ((fp->mode & (__MODE_READ | __MODE_ERR)) != __MODE_READ) - return EOF; - - /* Can't do fast fseeks */ - fp->mode |= __MODE_UNGOT; - - if( fp->bufpos > fp->bufstart ) - return *--fp->bufpos = (unsigned char) c; - else if( fp->bufread == fp->bufstart ) - return *fp->bufread++ = (unsigned char) c; - else - return EOF; -} -#endif - diff --git a/libc/stdio2/stdio.h b/libc/stdio2/stdio.h deleted file mode 100644 index fd10923..0000000 --- a/libc/stdio2/stdio.h +++ /dev/null @@ -1,129 +0,0 @@ - -#ifndef __STDIO_H -#define __STDIO_H - -#include -#include - -#ifndef SEEK_SET -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 -#endif - -#define _IOFBF 0x00 /* full buffering */ -#define _IOLBF 0x01 /* line buffering */ -#define _IONBF 0x02 /* no buffering */ -#define __MODE_BUF 0x03 /* Modal buffering dependent on isatty */ - -#define __MODE_FREEBUF 0x04 /* Buffer allocated with malloc, can free */ -#define __MODE_FREEFIL 0x08 /* FILE allocated with malloc, can free */ - -#define __MODE_READ 0x10 /* Opened in read only */ -#define __MODE_WRITE 0x20 /* Opened in write only */ -#define __MODE_RDWR 0x30 /* Opened in read/write */ - -#define __MODE_READING 0x40 /* Buffer has pending read data */ -#define __MODE_WRITING 0x80 /* Buffer has pending write data */ - -#define __MODE_EOF 0x100 /* EOF status */ -#define __MODE_ERR 0x200 /* Error status */ -#define __MODE_UNGOT 0x400 /* Buffer has been polluted by ungetc */ - -#ifdef __MSDOS__ -#define __MODE_IOTRAN 0x1000 /* MSDOS nl <-> cr,nl translation */ -#else -#define __MODE_IOTRAN 0 -#endif - -/* when you add or change fields here, be sure to change the initialization - * in stdio_init and fopen */ -struct __stdio_file { - unsigned char *bufpos; /* the next byte to write to or read from */ - unsigned char *bufread; /* the end of data returned by last read() */ - unsigned char *bufwrite; /* highest address writable by macro */ - unsigned char *bufstart; /* the start of the buffer */ - unsigned char *bufend; /* the end of the buffer; ie the byte after the last - malloc()ed byte */ - - int fd; /* the file descriptor associated with the stream */ - int mode; - - char unbuf[8]; /* The buffer for 'unbuffered' streams */ - - struct __stdio_file * next; -}; - -#define EOF (-1) -#ifndef NULL -#define NULL ((void*)0) -#endif - -typedef struct __stdio_file FILE; - -#ifdef __AS386_16__ -#define BUFSIZ (256) -#else -#define BUFSIZ (2048) -#endif - -extern FILE stdin[1]; -extern FILE stdout[1]; -extern FILE stderr[1]; - -#ifdef __MSDOS__ -#define putc(c, fp) fputc(c, fp) -#define getc(fp) fgetc(fp) -#else -#define putc(c, stream) \ - (((stream)->bufpos >= (stream)->bufwrite) ? fputc((c), (stream)) \ - : (unsigned char) (*(stream)->bufpos++ = (c)) ) - -#define getc(stream) \ - (((stream)->bufpos >= (stream)->bufread) ? fgetc(stream): \ - (*(stream)->bufpos++)) -#endif - -#define putchar(c) putc((c), stdout) -#define getchar() getc(stdin) - -#define ferror(fp) (((fp)->mode&__MODE_ERR) != 0) -#define feof(fp) (((fp)->mode&__MODE_EOF) != 0) -#define clearerr(fp) ((fp)->mode &= ~(__MODE_EOF|__MODE_ERR),0) -#define fileno(fp) ((fp)->fd) - -/* declare functions; not like it makes much difference without ANSI */ -/* RDB: The return values _are_ important, especially if we ever use - 8086 'large' model - */ - -/* These two call malloc */ -#define setlinebuf(__fp) setvbuf((__fp), (char*)0, _IOLBF, 0) -extern int setvbuf __P((FILE*, char*, int, size_t)); - -/* These don't */ -#define setbuf(__fp, __buf) setbuffer((__fp), (__buf), BUFSIZ) -extern void setbuffer __P((FILE*, char*, int)); - -extern int fgetc __P((FILE*)); -extern int fputc __P((int, FILE*)); - -extern int fclose __P((FILE*)); -extern int fflush __P((FILE*)); -extern char *fgets __P((char*, size_t, FILE*)); -extern FILE *__fopen __P((char*, int, FILE*, char*)); - -#define fopen(__file, __mode) __fopen((__file), -1, (FILE*)0, (__mode)) -#define freopen(__file, __mode, __fp) __fopen((__file), -1, (__fp), (__mode)) -#define fdopen(__file, __mode) __fopen((char*)0, (__file), (FILE*)0, (__mode)) - -extern int fputs __P((char*, FILE*)); -extern int puts __P((char*)); - -extern int printf __P ((__const char*, ...)); -extern int fprintf __P ((FILE*, __const char*, ...)); -extern int sprintf __P ((char*, __const char*, ...)); - -#define stdio_pending(fp) ((fp)->bufread>(fp)->bufpos) - -#endif /* __STDIO_H */ -- cgit v1.2.1