diff options
Diffstat (limited to 'libc')
31 files changed, 1940 insertions, 288 deletions
diff --git a/libc/Config.dflt b/libc/Config.dflt new file mode 100644 index 0000000..b2a79b0 --- /dev/null +++ b/libc/Config.dflt @@ -0,0 +1,17 @@ +bcc:+: +bios:+: +error:+: +getent:+: +gtermcap:+: +i386fp:+: +i386sys:+: +kinclude:+: +malloc1:+: +misc:+: +msdos:+: +regexp:+: +stdio2:+: +string:+: +syscall:+: +termios:+: +time:+: diff --git a/libc/Config_sh b/libc/Config_sh index 4beff3e..0b65992 100644 --- a/libc/Config_sh +++ b/libc/Config_sh @@ -6,14 +6,16 @@ main() { rm -f .config.tmp - ALLON=no + ALLON=yes - if [ -f .config.lst ] + if [ "$ALLON" = yes -a -f .config.lst ] then grep '^[^:]*:+:' .config.lst > .config.tmp - if [ ! -s .config.tmp ] - then ALLON=yes - fi - else ALLON=yes + [ -s .config.tmp ] && ALLON=no + fi + + if [ "$ALLON" = yes -a -f Config.dflt ] + then grep '^[^:]*:+:' Config.dflt > .config.tmp + [ -s .config.tmp ] && ALLON=no fi egrep -v '^#|^$' /dev/null */[Cc]onfig | \ diff --git a/libc/Makefile b/libc/Makefile index 593eaab..436c3c6 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -11,7 +11,7 @@ endif VERMAJOR=0 VERMINOR=12 -VERPATCH=0 +VERPATCH=4 VER=$(VERMAJOR).$(VERMINOR).$(VERPATCH) CC=bcc @@ -44,7 +44,8 @@ crt0.o: crt0.c Makefile $(CC) -c $(CFLAGS) -D__LIBC_VER__='"$(VER)"' -o $@ crt0.c crtX.o: - @echo "You need to define the 'PLATFORM=...' variable" + @echo "You need to define the 'PLATFORM=...' variable," + @echo "Preferably by doing make from `dirname \`pwd\``" @exit 1 ############################################################################ diff --git a/libc/gtermcap/Config b/libc/gtermcap/Config new file mode 100644 index 0000000..659749e --- /dev/null +++ b/libc/gtermcap/Config @@ -0,0 +1 @@ +gtermcap:GNU termcap routines diff --git a/libc/misc/cputype.c b/libc/misc/cputype.c index 8417514..d9c3e01 100644 --- a/libc/misc/cputype.c +++ b/libc/misc/cputype.c @@ -1,4 +1,8 @@ -/* +/* Copyright (C) 1989,1996 Robert de Bath <rdebath@cix.compulink.co.uk> + * This file is part of the Linux-8086 C library and is distributed + * under the terms of the GNU Library General Public License. + ********************************************************************** + * * This does a determination of the cpu type that is actually being used. * It can determine the CPU on anything upto and including a 386 accuratly * whatever mode the CPU is in (This is 16 bit code) @@ -12,18 +16,6 @@ * $ cputype # Call cputype(0) and interpret * $ cputype + # Call cputype(1) get a SIGILL (or perhaps interpret) * - * NOTE: This code is COPYRIGHT and not under the GNU Lib copyright, this - * may be distributed freely as source or as a standalone binary - * compiled from this unmodified source. - * - * You may use the cputype() function in your own personal code. - * You may distribute a binary version of code containing the - * cputype() function if either you distribute this source with - * the binary version or distribute a clear reference to a freely - * available copy of this source code and the source code to the - * rest of your package with the binary version of the package. - * - * (C) Copyright R de Bath 1989-1996 */ #ifdef STANDALONE diff --git a/libc/stdio1/BUGS b/libc/stdio1/BUGS new file mode 100644 index 0000000..0e8e0db --- /dev/null +++ b/libc/stdio1/BUGS @@ -0,0 +1,15 @@ +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 new file mode 100644 index 0000000..3b3b35f --- /dev/null +++ b/libc/stdio1/Config @@ -0,0 +1,3 @@ + + +stdio: Joel's stdio package altered by Nat diff --git a/libc/stdio1/NOTICE b/libc/stdio1/NOTICE new file mode 100644 index 0000000..25ca5b6 --- /dev/null +++ b/libc/stdio1/NOTICE @@ -0,0 +1,17 @@ +/* + Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us> + + 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 new file mode 100644 index 0000000..ead7846 --- /dev/null +++ b/libc/stdio1/README @@ -0,0 +1,8 @@ +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 new file mode 100644 index 0000000..481f6d9 --- /dev/null +++ b/libc/stdio1/TODO @@ -0,0 +1,33 @@ +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 new file mode 100644 index 0000000..e705cbf --- /dev/null +++ b/libc/stdio1/__ffillbuf.c @@ -0,0 +1,55 @@ +/* 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 <unistd.h> +#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 new file mode 100644 index 0000000..b49bb28 --- /dev/null +++ b/libc/stdio1/__stdio_init.c @@ -0,0 +1,66 @@ +/* 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 new file mode 100644 index 0000000..7ec233e --- /dev/null +++ b/libc/stdio1/fclose.c @@ -0,0 +1,41 @@ +/* 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 <unistd.h> +#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 new file mode 100644 index 0000000..69fdb90 --- /dev/null +++ b/libc/stdio1/fcntl.h @@ -0,0 +1,72 @@ +#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 new file mode 100644 index 0000000..c9cdac7 --- /dev/null +++ b/libc/stdio1/fflush.c @@ -0,0 +1,36 @@ +/* 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 <unistd.h> +#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 new file mode 100644 index 0000000..2c41062 --- /dev/null +++ b/libc/stdio1/fgetc.c @@ -0,0 +1,39 @@ +/* + Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us> + + 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 new file mode 100644 index 0000000..c085970 --- /dev/null +++ b/libc/stdio1/fgets.c @@ -0,0 +1,50 @@ +/* fgets.c for limited linux stdio + Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us> + + 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 new file mode 100644 index 0000000..1265ff5 --- /dev/null +++ b/libc/stdio1/fopen.c @@ -0,0 +1,80 @@ +/* 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 <malloc.h> + +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 new file mode 100644 index 0000000..939a721 --- /dev/null +++ b/libc/stdio1/fputc.c @@ -0,0 +1,53 @@ +/* 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 new file mode 100644 index 0000000..41e2998 --- /dev/null +++ b/libc/stdio1/fputs.c @@ -0,0 +1,32 @@ +/* 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 <unistd.h> +#include <string.h> +#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 new file mode 100644 index 0000000..7eacc9e --- /dev/null +++ b/libc/stdio1/idealgetline.c @@ -0,0 +1,67 @@ +/* idealgetline.c -- my idea of an ideal getline function for stdio + Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us> + + 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 <stdio.h> +#include <malloc.h> + +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 new file mode 100644 index 0000000..d8058b0 --- /dev/null +++ b/libc/stdio1/makefile @@ -0,0 +1,36 @@ +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 new file mode 100644 index 0000000..81d62ac --- /dev/null +++ b/libc/stdio1/old_printf.c @@ -0,0 +1,230 @@ +/* fprintf.c for limited Linux libc + Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us> + + 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 <stdarg.h> +#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 new file mode 100644 index 0000000..f2a39bd --- /dev/null +++ b/libc/stdio1/printf.c @@ -0,0 +1,649 @@ +/* fprintf.c for limited Linux libc + Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us> + + 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 <stdarg.h> +#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 <sthuang@hns.com>. + * + * 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 <string.h> +#include <ctype.h> + +/* + * 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 <time.h> + +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 new file mode 100644 index 0000000..d9bb8d0 --- /dev/null +++ b/libc/stdio1/puts.c @@ -0,0 +1,26 @@ +/* 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 new file mode 100644 index 0000000..81900a1 --- /dev/null +++ b/libc/stdio1/scanf.c @@ -0,0 +1,151 @@ +/* scanf.c for limited Linux libc + Copyright (C) 1996 Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us> + + 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 <linuxmt/types.h> */ +/* #include <linuxmt/fcntl.h> */ +#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 new file mode 100644 index 0000000..4bd1989 --- /dev/null +++ b/libc/stdio1/stdio.h @@ -0,0 +1,135 @@ +/* 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 <fcntl.h> +#include <sys/types.h> +#include <malloc.h> + +#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 new file mode 100755 index 0000000..9d872dc --- /dev/null +++ b/libc/stdio1/test.sh @@ -0,0 +1,12 @@ +#!/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/syscall/syscall.dat.chad b/libc/syscall/syscall.dat.chad deleted file mode 100644 index a6e8b06..0000000 --- a/libc/syscall/syscall.dat.chad +++ /dev/null @@ -1,55 +0,0 @@ -exit 1 1 * c exit does stdio, _exit in crt0 -fork 2 0 -read 3 3 -write 4 3 -open 5 3 -close 6 1 -wait 7 0 . THIS one is different -creat 8 0 . THIS one is different -link 9 2 -unlink 10 1 -exec 11 3 * minix style exec -chdir 12 1 -time 13 0 . THIS one is different -mknod 14 3 -chmod 15 2 -chown 16 3 -brk 17 1 * This is only to tell the system -stat 18 2 -lseek 19 3 * nb 2nd arg is an io ptr to long not a long. -getpid 20 1 * this gets both pid & ppid -mount 21 5 -umount 22 1 -setuid 23 1 -getuid 24 1 * this gets both uid and euid -stime 25 2 - this must not exist - even as a libc. -ptrace 26 4 -alarm 27 2 -fstat 28 2 -pause 29 0 -utime 30 2 -access 33 2 -nice 34 1 . -sleep 35 0 . THIS one is different -sync 36 0 -kill 37 2 -rename 38 2 -mkdir 39 2 -rmdir 40 1 -dup 41 1 - using nasty fcntl function -pipe 42 1 -times 43 2 * 2nd arg is pointer for long ret val. -profil 44 0 -setgid 46 1 -getgid 47 1 * this gets both gid and egid -signal 48 2 * have put the despatch table in user space. -getinfo 49 1 - possible? gets pid,ppid,uid,euid etc -fcntl 50 3 -acct 51 1 - -phys 52 0 . THIS one is different -lock 53 0 . THIS one is different -ioctl 54 3 . make this and fcntl the same ? -reboot 55 3 . the magic number is 0xfee1,0xdead,... -mpx 56 0 . THIS one is different -dup2 57 0 . THIS one is different -umask 60 1 diff --git a/libc/syscall/syscall.dat.code b/libc/syscall/syscall.dat.code deleted file mode 100644 index a91ca86..0000000 --- a/libc/syscall/syscall.dat.code +++ /dev/null @@ -1,70 +0,0 @@ -( -tr '[A-Z]' '[a-z]' < syscall.dat.rdb -echo %%% -cat <<! -exit 1 0 -fork 2 0 -read 3 0 -write 4 0 -open 5 0 -close 6 0 -wait 7 0 -creat 8 0 -link 9 0 -unlink 10 0 -exec 11 0 -chdir 12 0 -time 13 0 -mknod 14 0 -chmod 15 0 -chown 16 0 -brk 17 0 -stat 18 0 -lseek 19 0 -getpid 20 0 -mount 21 0 -umount 22 0 -setuid 23 0 -getuid 24 0 -stime 25 0 -ptrace 26 0 -alarm 27 0 -fstat 28 0 -pause 29 0 -utime 30 0 -access 33 0 -nice 34 0 -sleep 35 0 -sync 36 0 -kill 37 0 -rename 38 0 -mkdir 39 0 -rmdir 40 0 -dup 41 0 -pipe 42 0 -times 43 0 -profil 44 0 -setgid 46 0 -getgid 47 0 -signal 48 0 -getinfo 49 0 -fcntl 50 0 -acct 51 0 -phys 52 0 -lock 53 0 -ioctl 54 0 -reboot 55 0 -mpx 56 0 -dup2 57 0 -umask 60 0 -! -) | awk '/%%%/{ flg++; OFS="\t"; next;} -flg==0 { save4[$1] = $4; save3[$1] = $3; - for(i=5; i<=NF; i++) saverest[$1] = saverest[$1] " " $i; -} -flg==1 { - if( $1 in save3 ) - print $1, $2, save3[$1]+0, save4[$1] " " saverest[$1] ; - else - print $1, $2, "0", ". THIS one is different"; - }' diff --git a/libc/syscall/syscall.dat.rdb b/libc/syscall/syscall.dat.rdb deleted file mode 100644 index de5ed9b..0000000 --- a/libc/syscall/syscall.dat.rdb +++ /dev/null @@ -1,142 +0,0 @@ -# -# Name No Args Flag, comment -# -# . = Ok, with comment -# * = Needs libc code (Prefix __) -# - = Obsolete/not required -# -# WARNING! -# This file is used to generate includes for ELKSemu too. -# This file is continually changing, when you upgrade you _MUST_ ensure -# that ELKSemu is of a matching build! -# -# Calls that use one fd -READ 3 3 -WRITE 4 3 -CLOSE 6 1 -LSEEK 19 3 * NB 2nd arg is an IO ptr to long not a long. -FSTAT 28 2 -IOCTL 54 3 . Make this and fcntl the same ? -FCNTL 55 3 -FTRUNCATE 93 3 -FCHMOD 94 2 -FCHOWN 95 3 -FSYNC 118 1 -FCHDIR 133 1 -LLSEEK 140 3 * 2nd arg is ptr to two longs -READV 145 3 -WRITEV 146 3 -FLOCK 143 2 - Use fcntl -DUP 41 1 - Using nasty fcntl function - -# -SETUP 0 X -EXIT 1 1 * C exit does stdio, _exit in crt0 -FORK 2 0 -OPEN 5 3 -WAIT4 7 4 -VFORK 8 0 . Needed for 8086 -GETINFO 49 1 - Possible? Gets pid,ppid,uid,euid etc -LINK 9 2 -UNLINK 10 1 -EXEC 11 3 * Minix style exec -CHDIR 12 1 -GETTIMEOFDAY 13 2 . time() exists only in libc -MKNOD 14 3 -CHMOD 15 2 -CHOWN 16 3 -BRK 17 1 * This is only to tell the system -STAT 18 2 -GETPID 20 1 * This gets both pid & ppid -MOUNT 21 5 -UMOUNT 22 1 -SETUID 23 1 -GETUID 24 1 * This gets both uid and euid -SETTIMEOFDAY 25 2 . STIME should _NOT_ exist even as a libc. -STIME 25 2 - This must NOT exist - even as a libc. -PTRACE 26 4 -ALARM 27 2 -PAUSE 29 0 -UTIME 30 2 -ACCESS 33 2 -NICE 34 1 . -FTIME 35 1 - Use gettimeofday -SYNC 36 0 -KILL 37 2 -RENAME 38 2 -MKDIR 39 2 -RMDIR 40 1 -PIPE 42 1 -TIMES 43 2 * 2nd arg is pointer for long ret val. -SETGID 46 1 -GETGID 47 1 * This gets both gid and egid -SIGNAL 48 2 * Have put the despatch table in user space. -ACCT 51 1 - -SETPGID 57 2 -ULIMIT 58 2 -UMASK 60 1 -CHROOT 61 1 -USTAT 62 2 -GETPGRP 65 0 - use getpgid(0) -SETSID 66 0 -SIGACTION 67 X -SGETMASK 68 X -SSETMASK 69 X -SETREUID 70 2 -SETREGID 71 2 -SIGSUSPEND 72 X -SIGPENDING 73 X -SETHOSTNAME 74 2 -SETRLIMIT 75 2 -GETRLIMIT 76 2 -GETRUSAGE 77 2 -GETGROUPS 80 2 -SETGROUPS 81 2 -SYMLINK 83 2 -LSTAT 84 2 -READLINK 85 3 -SWAPON 87 X -REBOOT 88 3 . The magic number is 0xfee1,0xdead,... -MUNMAP 91 X -TRUNCATE 92 3 -GETPRIORITY 96 2 -SETPRIORITY 97 3 -PROFIL 98 X -STATFS 99 2 -FSTATFS 100 2 -SOCKETCALL 102 X -SYSLOG 103 X -SETITIMER 104 3 -GETITIMER 105 2 -UNAME 109 1 -VHANGUP 111 0 -SWAPOFF 115 X -SYSINFO 116 X - Use /proc -IPC 117 5 * This is for all SYSV IPC -SIGRETURN 119 X -SETDOMAINNAME 121 X -ADJTIMEX 124 X -MPROTECT 125 X -SIGPROCMASK 126 X -QUOTACTL 131 X -GETPGID 132 1 -SYSFS 135 X -PERSONALITY 136 X -SETFSUID 138 1 -SETFSGID 139 1 -GETDENTS 141 X -SELECT 142 5 * -MSYNC 144 X -GETSID 147 X -FDATASYNC 148 X -SYSCTL 149 X -MUNLOCK 151 X -MUNLOCKALL 153 X -SCHED_SETPARAM 154 X -SCHED_GETPARAM 155 X -SCHED_SETSCHEDULER 156 X -SCHED_GETSCHEDULER 157 X -SCHED_YIELD 158 X -SCHED_GET_PRIORITY_MAX 159 X -SCHED_GET_PRIORITY_MIN 160 X -SCHED_RR_GET_INTERVAL 161 X |