diff options
author | Christopher Faylor <me@cgf.cx> | 2000-02-17 19:39:52 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2000-02-17 19:39:52 +0000 |
commit | 8a0efa53e44919bcf5ccb1d3353618a82afdf8bc (patch) | |
tree | 68c3dbf3f2c6fd5d49777def9914d77b5cd4589d /newlib/libc/stdio | |
parent | 1fd5e000ace55b323124c7e556a7a864b972a5c4 (diff) | |
download | cygnal-8a0efa53e44919bcf5ccb1d3353618a82afdf8bc.tar.gz cygnal-8a0efa53e44919bcf5ccb1d3353618a82afdf8bc.tar.bz2 cygnal-8a0efa53e44919bcf5ccb1d3353618a82afdf8bc.zip |
import newlib-2000-02-17 snapshot
Diffstat (limited to 'newlib/libc/stdio')
67 files changed, 9220 insertions, 0 deletions
diff --git a/newlib/libc/stdio/Makefile.am b/newlib/libc/stdio/Makefile.am new file mode 100644 index 000000000..234da49b6 --- /dev/null +++ b/newlib/libc/stdio/Makefile.am @@ -0,0 +1,161 @@ +## Process this file with automake to generate Makefile.in + +AUTOMAKE_OPTIONS = cygnus + +INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) + +noinst_LIBRARIES = lib.a + +lib_a_SOURCES = \ + clearerr.c \ + fclose.c \ + fdopen.c \ + feof.c \ + ferror.c \ + fflush.c \ + fgetc.c \ + fgetpos.c \ + fgets.c \ + fileno.c \ + findfp.c \ + fiprintf.c \ + flags.c \ + fopen.c \ + fprintf.c \ + fputc.c \ + fputs.c \ + fread.c \ + freopen.c \ + fscanf.c \ + fseek.c \ + fsetpos.c \ + ftell.c \ + fvwrite.c \ + fwalk.c \ + fwrite.c \ + getc.c \ + getchar.c \ + gets.c \ + iprintf.c \ + makebuf.c \ + mktemp.c \ + perror.c \ + printf.c \ + putc.c \ + putchar.c \ + puts.c \ + refill.c \ + remove.c \ + rename.c \ + rewind.c \ + rget.c \ + scanf.c \ + setbuf.c \ + setvbuf.c \ + siprintf.c \ + snprintf.c \ + sprintf.c \ + sscanf.c \ + stdio.c \ + tmpfile.c \ + tmpnam.c \ + ungetc.c \ + vfprintf.c \ + vfscanf.c \ + vprintf.c \ + vsnprintf.c \ + vsprintf.c \ + wbuf.c \ + wsetup.c + +lib_a_LIBADD = vfiprintf.o + +vfiprintf.o: vfprintf.c + $(COMPILE) -DINTEGER_ONLY -c $(srcdir)/vfprintf.c -o $@ + +CHEWOUT_FILES = \ + clearerr.def \ + fclose.def \ + fdopen.def \ + feof.def \ + ferror.def \ + fflush.def \ + fgetc.def \ + fgetpos.def \ + fgets.def \ + fileno.def \ + fiprintf.def \ + fopen.def \ + fputc.def \ + fputs.def \ + fread.def \ + freopen.def \ + fseek.def \ + fsetpos.def \ + ftell.def \ + fwrite.def \ + getc.def \ + getchar.def \ + gets.def \ + iprintf.def \ + mktemp.def \ + perror.def \ + putc.def \ + putchar.def \ + puts.def \ + remove.def \ + rename.def \ + rewind.def \ + setbuf.def \ + setvbuf.def \ + siprintf.def \ + sprintf.def \ + sscanf.def \ + tmpfile.def \ + tmpnam.def \ + vfprintf.def + +SUFFIXES = .def + +CHEW = ../../doc/makedoc -f $(srcdir)/../../doc/doc.str + +.c.def: + $(CHEW) < $< > $*.def 2> $*.ref + touch stmp-def + +TARGETDOC = ../tmp.texi + +doc: $(CHEWOUT_FILES) + cat $(srcdir)/stdio.tex >> $(TARGETDOC) + +CLEANFILES = $(CHEWOUT_FILES) *.ref + +fclose.o: local.h +fdopen.o: local.h +fflush.o: local.h +findfp.o: local.h +fopen.o: local.h +fputs.o: fvwrite.h +fread.o: local.h +freopen.o: local.h +fseek.o: local.h +ftell.o: local.h +fvwrite.o: local.h fvwrite.h +fwalk.o: local.h +fwrite.o: local.h fvwrite.h +makebuf.o: local.h +puts.o: fvwrite.h +refill.o: local.h +scanf.o: local.h +setbuf.o: local.h +setvbuf.o: local.h +siprintf.o: local.h +sprintf.o: local.h +sscanf.o: local.h +stdio.o: local.h +ungetc.o: local.h +vfiprintf.o: local.h +vfprintf.o: local.h +vfscanf.o: local.h floatio.h +wbuf.o: local.h fvwrite.h +wsetup.o: local.h diff --git a/newlib/libc/stdio/Makefile.in b/newlib/libc/stdio/Makefile.in new file mode 100644 index 000000000..ff2a83845 --- /dev/null +++ b/newlib/libc/stdio/Makefile.in @@ -0,0 +1,441 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +AR = @AR@ +AS = @AS@ +CC = @CC@ +CPP = @CPP@ +CRT0 = @CRT0@ +EXEEXT = @EXEEXT@ +LIBC_MACHINE_LIB = @LIBC_MACHINE_LIB@ +LIBC_POSIX_LIB = @LIBC_POSIX_LIB@ +LIBC_SIGNAL_DEF = @LIBC_SIGNAL_DEF@ +LIBC_SIGNAL_LIB = @LIBC_SIGNAL_LIB@ +LIBC_SYSCALL_LIB = @LIBC_SYSCALL_LIB@ +LIBC_SYS_LIB = @LIBC_SYS_LIB@ +LIBC_UNIX_LIB = @LIBC_UNIX_LIB@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +NEWLIB_CFLAGS = @NEWLIB_CFLAGS@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +VERSION = @VERSION@ +machine_dir = @machine_dir@ +newlib_basedir = @newlib_basedir@ +sys_dir = @sys_dir@ + +AUTOMAKE_OPTIONS = cygnus + +INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) + +noinst_LIBRARIES = lib.a + +lib_a_SOURCES = \ + clearerr.c \ + fclose.c \ + fdopen.c \ + feof.c \ + ferror.c \ + fflush.c \ + fgetc.c \ + fgetpos.c \ + fgets.c \ + fileno.c \ + findfp.c \ + fiprintf.c \ + flags.c \ + fopen.c \ + fprintf.c \ + fputc.c \ + fputs.c \ + fread.c \ + freopen.c \ + fscanf.c \ + fseek.c \ + fsetpos.c \ + ftell.c \ + fvwrite.c \ + fwalk.c \ + fwrite.c \ + getc.c \ + getchar.c \ + gets.c \ + iprintf.c \ + makebuf.c \ + mktemp.c \ + perror.c \ + printf.c \ + putc.c \ + putchar.c \ + puts.c \ + refill.c \ + remove.c \ + rename.c \ + rewind.c \ + rget.c \ + scanf.c \ + setbuf.c \ + setvbuf.c \ + siprintf.c \ + snprintf.c \ + sprintf.c \ + sscanf.c \ + stdio.c \ + tmpfile.c \ + tmpnam.c \ + ungetc.c \ + vfprintf.c \ + vfscanf.c \ + vprintf.c \ + vsnprintf.c \ + vsprintf.c \ + wbuf.c \ + wsetup.c + + +lib_a_LIBADD = vfiprintf.o + +CHEWOUT_FILES = \ + clearerr.def \ + fclose.def \ + fdopen.def \ + feof.def \ + ferror.def \ + fflush.def \ + fgetc.def \ + fgetpos.def \ + fgets.def \ + fileno.def \ + fiprintf.def \ + fopen.def \ + fputc.def \ + fputs.def \ + fread.def \ + freopen.def \ + fseek.def \ + fsetpos.def \ + ftell.def \ + fwrite.def \ + getc.def \ + getchar.def \ + gets.def \ + iprintf.def \ + mktemp.def \ + perror.def \ + putc.def \ + putchar.def \ + puts.def \ + remove.def \ + rename.def \ + rewind.def \ + setbuf.def \ + setvbuf.def \ + siprintf.def \ + sprintf.def \ + sscanf.def \ + tmpfile.def \ + tmpnam.def \ + vfprintf.def + + +SUFFIXES = .def + +CHEW = ../../doc/makedoc -f $(srcdir)/../../doc/doc.str + +TARGETDOC = ../tmp.texi + +CLEANFILES = $(CHEWOUT_FILES) *.ref +mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +lib_a_DEPENDENCIES = vfiprintf.o +lib_a_OBJECTS = clearerr.o fclose.o fdopen.o feof.o ferror.o fflush.o \ +fgetc.o fgetpos.o fgets.o fileno.o findfp.o fiprintf.o flags.o fopen.o \ +fprintf.o fputc.o fputs.o fread.o freopen.o fscanf.o fseek.o fsetpos.o \ +ftell.o fvwrite.o fwalk.o fwrite.o getc.o getchar.o gets.o iprintf.o \ +makebuf.o mktemp.o perror.o printf.o putc.o putchar.o puts.o refill.o \ +remove.o rename.o rewind.o rget.o scanf.o setbuf.o setvbuf.o siprintf.o \ +snprintf.o sprintf.o sscanf.o stdio.o tmpfile.o tmpnam.o ungetc.o \ +vfprintf.o vfscanf.o vprintf.o vsnprintf.o vsprintf.o wbuf.o wsetup.o +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = $(lib_a_SOURCES) +OBJECTS = $(lib_a_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .def .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --cygnus stdio/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.c.o: + $(COMPILE) -c $< + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +lib.a: $(lib_a_OBJECTS) $(lib_a_DEPENDENCIES) + -rm -f lib.a + $(AR) cru lib.a $(lib_a_OBJECTS) $(lib_a_LIBADD) + $(RANLIB) lib.a + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = stdio + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: +check: check-am +installcheck-am: +installcheck: installcheck-am +install-info-am: +install-info: install-info-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(LIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \ + mostlyclean-am + +clean: clean-am + +distclean-am: distclean-noinstLIBRARIES distclean-compile \ + distclean-tags distclean-generic clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \ +check-am installcheck-am installcheck install-info-am install-info \ +install-exec-am install-exec install-data-am install-data install-am \ +install uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +vfiprintf.o: vfprintf.c + $(COMPILE) -DINTEGER_ONLY -c $(srcdir)/vfprintf.c -o $@ + +.c.def: + $(CHEW) < $< > $*.def 2> $*.ref + touch stmp-def + +doc: $(CHEWOUT_FILES) + cat $(srcdir)/stdio.tex >> $(TARGETDOC) + +fclose.o: local.h +fdopen.o: local.h +fflush.o: local.h +findfp.o: local.h +fopen.o: local.h +fputs.o: fvwrite.h +fread.o: local.h +freopen.o: local.h +fseek.o: local.h +ftell.o: local.h +fvwrite.o: local.h fvwrite.h +fwalk.o: local.h +fwrite.o: local.h fvwrite.h +makebuf.o: local.h +puts.o: fvwrite.h +refill.o: local.h +scanf.o: local.h +setbuf.o: local.h +setvbuf.o: local.h +siprintf.o: local.h +sprintf.o: local.h +sscanf.o: local.h +stdio.o: local.h +ungetc.o: local.h +vfiprintf.o: local.h +vfprintf.o: local.h +vfscanf.o: local.h floatio.h +wbuf.o: local.h fvwrite.h +wsetup.o: local.h + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/newlib/libc/stdio/clearerr.c b/newlib/libc/stdio/clearerr.c new file mode 100644 index 000000000..861d9a211 --- /dev/null +++ b/newlib/libc/stdio/clearerr.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<clearerr>>---clear file or stream error indicator + +INDEX + clearerr + +ANSI_SYNOPSIS + #include <stdio.h> + void clearerr(FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + void clearerr(<[fp]>) + FILE *<[fp]>; + +DESCRIPTION +The <<stdio>> functions maintain an error indicator with each file +pointer <[fp]>, to record whether any read or write errors have +occurred on the associated file or stream. Similarly, it maintains an +end-of-file indicator to record whether there is no more data in the +file. + +Use <<clearerr>> to reset both of these indicators. + +See <<ferror>> and <<feof>> to query the two indicators. + + +RETURNS +<<clearerr>> does not return a result. + +PORTABILITY +ANSI C requires <<clearerr>>. + +No supporting OS subroutines are required. +*/ + +#include <stdio.h> +#undef clearerr + +_VOID +_DEFUN (clearerr, (fp), + FILE * fp) +{ + __sclearerr (fp); +} diff --git a/newlib/libc/stdio/fclose.c b/newlib/libc/stdio/fclose.c new file mode 100644 index 000000000..3266d8a55 --- /dev/null +++ b/newlib/libc/stdio/fclose.c @@ -0,0 +1,82 @@ +/* +FUNCTION +<<fclose>>---close a file + +INDEX + fclose + +ANSI_SYNOPSIS + #include <stdio.h> + int fclose(FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int fclose(<[fp]>) + FILE *<[fp]>; + +DESCRIPTION +If the file or stream identified by <[fp]> is open, <<fclose>> closes +it, after first ensuring that any pending data is written (by calling +<<fflush(<[fp]>)>>). + +RETURNS +<<fclose>> returns <<0>> if successful (including when <[fp]> is +<<NULL>> or not an open file); otherwise, it returns <<EOF>>. + +PORTABILITY +<<fclose>> is required by ANSI C. + +Required OS subroutines: <<close>>, <<fstat>>, <<isatty>>, <<lseek>>, +<<read>>, <<sbrk>>, <<write>>. +*/ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include "local.h" + +/* + * Close a file. + */ + +int +_DEFUN (fclose, (fp), + register FILE * fp) +{ + int r; + + if (fp == NULL) + return (0); /* on NULL */ + + CHECK_INIT (fp); + + if (fp->_flags == 0) /* not open! */ + return (0); + r = fp->_flags & __SWR ? fflush (fp) : 0; + if (fp->_close != NULL && (*fp->_close) (fp->_cookie) < 0) + r = EOF; + if (fp->_flags & __SMBF) + _free_r (fp->_data, (char *) fp->_bf._base); + if (HASUB (fp)) + FREEUB (fp); + if (HASLB (fp)) + FREELB (fp); + fp->_flags = 0; /* release this FILE for reuse */ + return (r); +} diff --git a/newlib/libc/stdio/fdopen.c b/newlib/libc/stdio/fdopen.c new file mode 100644 index 000000000..50698cbf6 --- /dev/null +++ b/newlib/libc/stdio/fdopen.c @@ -0,0 +1,116 @@ +/* +FUNCTION +<<fdopen>>---turn open file into a stream + +INDEX + fdopen +INDEX + _fdopen_r + +ANSI_SYNOPSIS + #include <stdio.h> + FILE *fdopen(int <[fd]>, const char *<[mode]>); + FILE *_fdopen_r(void *<[reent]>, + int <[fd]>, const char *<[mode]>); + +TRAD_SYNOPSIS + #include <stdio.h> + FILE *fdopen(<[fd]>, <[mode]>) + int <[fd]>; + char *<[mode]>; + + FILE *_fdopen_r(<[reent]>, <[fd]>, <[mode]>) + char *<[reent]>; + int <[fd]>; + char *<[mode]>); + +DESCRIPTION +<<fdopen>> produces a file descriptor of type <<FILE *>>, from a +descriptor for an already-open file (returned, for example, by the +system subroutine <<open>> rather than by <<fopen>>). +The <[mode]> argument has the same meanings as in <<fopen>>. + +RETURNS +File pointer or <<NULL>>, as for <<fopen>>. + +PORTABILITY +<<fdopen>> is ANSI. +*/ + +#include <sys/types.h> +#include <sys/fcntl.h> + +#include <stdio.h> +#include <errno.h> +#include "local.h" +#include <_syslist.h> + +extern int __sflags (); + +FILE * +_DEFUN (_fdopen_r, (ptr, fd, mode), + struct _reent *ptr _AND + int fd _AND + _CONST char *mode) +{ + register FILE *fp; + int flags, oflags; +#ifdef F_GETFL + int fdflags, fdmode; +#endif + + if ((flags = __sflags (ptr, mode, &oflags)) == 0) + return 0; + + /* make sure the mode the user wants is a subset of the actual mode */ +#ifdef F_GETFL + if ((fdflags = _fcntl (fd, F_GETFL, 0)) < 0) + return 0; + fdmode = fdflags & O_ACCMODE; + if (fdmode != O_RDWR && (fdmode != (oflags & O_ACCMODE))) + { + ptr->_errno = EBADF; + return 0; + } +#endif + + if ((fp = __sfp (ptr)) == 0) + return 0; + fp->_flags = flags; + /* + * If opened for appending, but underlying descriptor + * does not have O_APPEND bit set, assert __SAPP so that + * __swrite() will lseek to end before each write. + */ + if ((oflags & O_APPEND) +#ifdef F_GETFL + && !(fdflags & O_APPEND) +#endif + ) + fp->_flags |= __SAPP; + fp->_file = fd; + fp->_cookie = (_PTR) fp; + +#undef _read +#undef _write +#undef _seek +#undef _close + + fp->_read = __sread; + fp->_write = __swrite; + fp->_seek = __sseek; + fp->_close = __sclose; + return fp; +} + +#ifndef _REENT_ONLY + +FILE * +_DEFUN (fdopen, (fd, mode), + int fd _AND + _CONST char *mode) +{ + return _fdopen_r (_REENT, fd, mode); +} + +#endif diff --git a/newlib/libc/stdio/feof.c b/newlib/libc/stdio/feof.c new file mode 100644 index 000000000..55f151bd4 --- /dev/null +++ b/newlib/libc/stdio/feof.c @@ -0,0 +1,40 @@ +/* +FUNCTION +<<feof>>---test for end of file + +INDEX + feof + +ANSI_SYNOPSIS + #include <stdio.h> + int feof(FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int feof(<[fp]>) + FILE *<[fp]>; + +DESCRIPTION +<<feof>> tests whether or not the end of the file identified by <[fp]> +has been reached. + +RETURNS +<<feof>> returns <<0>> if the end of file has not yet been reached; if +at end of file, the result is nonzero. + +PORTABILITY +<<feof>> is required by ANSI C. + +No supporting OS subroutines are required. +*/ + +#include <stdio.h> + +#undef feof + +int +_DEFUN (feof, (fp), + FILE * fp) +{ + return __sfeof (fp); +} diff --git a/newlib/libc/stdio/ferror.c b/newlib/libc/stdio/ferror.c new file mode 100644 index 000000000..19fa78d14 --- /dev/null +++ b/newlib/libc/stdio/ferror.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<ferror>>---test whether read/write error has occurred + +INDEX + ferror + +ANSI_SYNOPSIS + #include <stdio.h> + int ferror(FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int ferror(<[fp]>) + FILE *<[fp]>; + +DESCRIPTION +The <<stdio>> functions maintain an error indicator with each file +pointer <[fp]>, to record whether any read or write errors have +occurred on the associated file or stream. +Use <<ferror>> to query this indicator. + +See <<clearerr>> to reset the error indicator. + +RETURNS +<<ferror>> returns <<0>> if no errors have occurred; it returns a +nonzero value otherwise. + +PORTABILITY +ANSI C requires <<ferror>>. + +No supporting OS subroutines are required. +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +/* A subroutine version of the macro ferror. */ + +#undef ferror + +int +_DEFUN (ferror, (fp), + FILE * fp) +{ + return __sferror (fp); +} diff --git a/newlib/libc/stdio/fflush.c b/newlib/libc/stdio/fflush.c new file mode 100644 index 000000000..635e5a738 --- /dev/null +++ b/newlib/libc/stdio/fflush.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<fflush>>---flush buffered file output + +INDEX + fflush + +ANSI_SYNOPSIS + #include <stdio.h> + int fflush(FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int fflush(<[fp]>) + FILE *<[fp]>; + +DESCRIPTION +The <<stdio>> output functions can buffer output before delivering it +to the host system, in order to minimize the overhead of system calls. + +Use <<fflush>> to deliver any such pending output (for the file +or stream identified by <[fp]>) to the host system. + +If <[fp]> is <<NULL>>, <<fflush>> delivers pending output from all +open files. + +RETURNS +<<fflush>> returns <<0>> unless it encounters a write error; in that +situation, it returns <<EOF>>. + +PORTABILITY +ANSI C requires <<fflush>>. + +No supporting OS subroutines are required. +*/ + +#include <stdio.h> +#include "local.h" + +/* Flush a single file, or (if fp is NULL) all files. */ + +int +_DEFUN (fflush, (fp), + register FILE * fp) +{ + register unsigned char *p; + register int n, t; + + + + + if (fp == NULL) + return _fwalk (_REENT, fflush); + + CHECK_INIT (fp); + + t = fp->_flags; + if ((t & __SWR) == 0 || (p = fp->_bf._base) == NULL) + return 0; + n = fp->_p - p; /* write this much */ + + /* + * Set these immediately to avoid problems with longjmp + * and to allow exchange buffering (via setvbuf) in user + * write function. + */ + fp->_p = p; + fp->_w = t & (__SLBF | __SNBF) ? 0 : fp->_bf._size; + + while (n > 0) + { + t = (*fp->_write) (fp->_cookie, (char *) p, n); + if (t <= 0) + { + fp->_flags |= __SERR; + return EOF; + } + p += t; + n -= t; + } + return 0; +} diff --git a/newlib/libc/stdio/fgetc.c b/newlib/libc/stdio/fgetc.c new file mode 100644 index 000000000..3d3d2c4ed --- /dev/null +++ b/newlib/libc/stdio/fgetc.c @@ -0,0 +1,46 @@ +/* +FUNCTION +<<fgetc>>---get a character from a file or stream + +INDEX + fgetc + +ANSI_SYNOPSIS + #include <stdio.h> + int fgetc(FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int fgetc(<[fp]>) + FILE *<[fp]>; + +DESCRIPTION +Use <<fgetc>> to get the next single character from the file or stream +identified by <[fp]>. As a side effect, <<fgetc>> advances the file's +current position indicator. + +For a macro version of this function, see <<getc>>. + +RETURNS +The next character (read as an <<unsigned char>>, and cast to +<<int>>), unless there is no more data, or the host system reports a +read error; in either of these situations, <<fgetc>> returns <<EOF>>. + +You can distinguish the two situations that cause an <<EOF>> result by +using the <<ferror>> and <<feof>> functions. + +PORTABILITY +ANSI C requires <<fgetc>>. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <stdio.h> + +int +_DEFUN (fgetc, (fp), + FILE * fp) +{ + return __sgetc (fp); +} diff --git a/newlib/libc/stdio/fgetpos.c b/newlib/libc/stdio/fgetpos.c new file mode 100644 index 000000000..214021a84 --- /dev/null +++ b/newlib/libc/stdio/fgetpos.c @@ -0,0 +1,61 @@ +/* +FUNCTION +<<fgetpos>>---record position in a stream or file + +INDEX + fgetpos + +ANSI_SYNOPSIS + #include <stdio.h> + int fgetpos(FILE *<[fp]>, fpos_t *<[pos]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int fgetpos(<[fp]>, <[pos]>) + FILE *<[fp]>; + fpos_t *<[pos]>; + +DESCRIPTION +Objects of type <<FILE>> can have a ``position'' that records how much +of the file your program has already read. Many of the <<stdio>> functions +depend on this position, and many change it as a side effect. + +You can use <<fgetpos>> to report on the current position for a file +identified by <[fp]>; <<fgetpos>> will write a value +representing that position at <<*<[pos]>>>. Later, you can +use this value with <<fsetpos>> to return the file to this +position. + +In the current implementation, <<fgetpos>> simply uses a character +count to represent the file position; this is the same number that +would be returned by <<ftell>>. + +RETURNS +<<fgetpos>> returns <<0>> when successful. If <<fgetpos>> fails, the +result is <<1>>. Failure occurs on streams that do not support +positioning; the global <<errno>> indicates this condition with the +value <<ESPIPE>>. + +PORTABILITY +<<fgetpos>> is required by the ANSI C standard, but the meaning of the +value it records is not specified beyond requiring that it be +acceptable as an argument to <<fsetpos>>. In particular, other +conforming C implementations may return a different result from +<<ftell>> than what <<fgetpos>> writes at <<*<[pos]>>>. + +No supporting OS subroutines are required. +*/ + +#include <stdio.h> + +int +_DEFUN (fgetpos, (fp, pos), + FILE * fp _AND + fpos_t * pos) +{ + *pos = ftell (fp); + + if (*pos != -1) + return 0; + return 1; +} diff --git a/newlib/libc/stdio/fgets.c b/newlib/libc/stdio/fgets.c new file mode 100644 index 000000000..abc2bb97c --- /dev/null +++ b/newlib/libc/stdio/fgets.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + +FUNCTION + <<fgets>>---get character string from a file or stream +INDEX + fgets + +ANSI_SYNOPSIS + #include <stdio.h> + char *fgets(char *<[buf]>, int <[n]>, FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + char *fgets(<[buf]>,<[n]>,<[fp]>) + char *<[buf]>; + int <[n]>; + FILE *<[fp]>; + +DESCRIPTION + Reads at most <[n-1]> characters from <[fp]> until a newline + is found. The characters including to the newline are stored + in <[buf]>. The buffer is terminated with a 0. + + +RETURNS + <<fgets>> returns the buffer passed to it, with the data + filled in. If end of file occurs with some data already + accumulated, the data is returned with no other indication. If + no data are read, NULL is returned instead. + +PORTABILITY + <<fgets>> should replace all uses of <<gets>>. Note however + that <<fgets>> returns all of the data, while <<gets>> removes + the trailing newline (with no indication that it has done so.) + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <stdio.h> +#include <string.h> + +extern int __srefill (); + +/* + * Read at most n-1 characters from the given file. + * Stop when a newline has been read, or the count runs out. + * Return first argument, or NULL if no characters were read. + */ + +char * +_DEFUN (fgets, (buf, n, fp), + char *buf _AND + int n _AND + FILE * fp) +{ + size_t len; + char *s; + unsigned char *p, *t; + + if (n < 2) /* sanity check */ + return 0; + + s = buf; + n--; /* leave space for NUL */ + do + { + /* + * If the buffer is empty, refill it. + */ + if ((len = fp->_r) <= 0) + { + if (__srefill (fp)) + { + /* EOF: stop with partial or no line */ + if (s == buf) + return 0; + break; + } + len = fp->_r; + } + p = fp->_p; + + /* + * Scan through at most n bytes of the current buffer, + * looking for '\n'. If found, copy up to and including + * newline, and stop. Otherwise, copy entire chunk + * and loop. + */ + if (len > n) + len = n; + t = (unsigned char *) memchr ((_PTR) p, '\n', len); + if (t != 0) + { + len = ++t - p; + fp->_r -= len; + fp->_p = t; + (void) memcpy ((_PTR) s, (_PTR) p, len); + s[len] = 0; + return (buf); + } + fp->_r -= len; + fp->_p += len; + (void) memcpy ((_PTR) s, (_PTR) p, len); + s += len; + } + while ((n -= len) != 0); + *s = 0; + return buf; +} diff --git a/newlib/libc/stdio/fileno.c b/newlib/libc/stdio/fileno.c new file mode 100644 index 000000000..d578c3ede --- /dev/null +++ b/newlib/libc/stdio/fileno.c @@ -0,0 +1,40 @@ +/* +FUNCTION +<<fileno>>---return file descriptor associated with stream + +INDEX + fileno + +ANSI_SYNOPSIS + #include <stdio.h> + int fileno(FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int fileno(<[fp]>) + FILE *<[fp]>; + +DESCRIPTION +You can use <<fileno>> to return the file descriptor identified by <[fp]>. + +RETURNS +<<fileno>> returns a non-negative integer when successful. +If <[fp]> is not an open stream, <<fileno>> returns -1. + +PORTABILITY +<<fileno>> is not part of ANSI C. +POSIX requires <<fileno>>. + +Supporting OS subroutines required: none. +*/ + +#include <stdio.h> +#include "local.h" + +int +_DEFUN (fileno, (f), + FILE * f) +{ + CHECK_INIT (f); + return __sfileno (f); +} diff --git a/newlib/libc/stdio/findfp.c b/newlib/libc/stdio/findfp.c new file mode 100644 index 000000000..650c638e6 --- /dev/null +++ b/newlib/libc/stdio/findfp.c @@ -0,0 +1,153 @@ +/* No user fns here. Pesch 15apr92. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include "local.h" + +static void +std (ptr, flags, file, data) + FILE *ptr; + struct _reent *data; +{ + ptr->_p = 0; + ptr->_r = 0; + ptr->_w = 0; + ptr->_flags = flags; + ptr->_file = file; + ptr->_bf._base = 0; + ptr->_bf._size = 0; + ptr->_lbfsize = 0; + ptr->_cookie = ptr; + ptr->_read = __sread; + ptr->_write = __swrite; + ptr->_seek = __sseek; + ptr->_close = __sclose; + ptr->_data = data; +} + +struct _glue * +__sfmoreglue (d, n) + struct _reent *d; + register int n; +{ + struct _glue *g; + FILE *p; + + g = (struct _glue *) _malloc_r (d, sizeof (*g) + n * sizeof (FILE)); + if (g == NULL) + return NULL; + p = (FILE *) (g + 1); + g->_next = NULL; + g->_niobs = n; + g->_iobs = p; + memset (p, 0, n * sizeof (FILE)); + return g; +} + +/* + * Find a free FILE for fopen et al. + */ + +FILE * +__sfp (d) + struct _reent *d; +{ + FILE *fp; + int n; + struct _glue *g; + + if (!d->__sdidinit) + __sinit (d); + for (g = &d->__sglue;; g = g->_next) + { + for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++) + if (fp->_flags == 0) + goto found; + if (g->_next == NULL && + (g->_next = __sfmoreglue (d, NDYNAMIC)) == NULL) + break; + } + d->_errno = ENOMEM; + return NULL; + +found: + fp->_flags = 1; /* reserve this slot; caller sets real flags */ + fp->_p = NULL; /* no current pointer */ + fp->_w = 0; /* nothing to read or write */ + fp->_r = 0; + fp->_bf._base = NULL; /* no buffer */ + fp->_bf._size = 0; + fp->_lbfsize = 0; /* not line buffered */ + fp->_file = -1; /* no file */ + /* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */ + fp->_ub._base = NULL; /* no ungetc buffer */ + fp->_ub._size = 0; + fp->_lb._base = NULL; /* no line buffer */ + fp->_lb._size = 0; + fp->_data = d; + return fp; +} + +/* + * exit() calls _cleanup() through *__cleanup, set whenever we + * open or buffer a file. This chicanery is done so that programs + * that do not use stdio need not link it all in. + * + * The name `_cleanup' is, alas, fairly well known outside stdio. + */ + +void +_cleanup_r (ptr) + struct _reent *ptr; +{ + /* (void) _fwalk(fclose); */ + (void) _fwalk (ptr, fflush); /* `cheating' */ +} + +#ifndef _REENT_ONLY +void +_cleanup () +{ + _cleanup_r (_REENT); +} +#endif + +/* + * __sinit() is called whenever stdio's internal variables must be set up. + */ + +void +__sinit (s) + struct _reent *s; +{ + /* make sure we clean up on exit */ + s->__cleanup = _cleanup_r; /* conservative */ + s->__sdidinit = 1; + + std (s->__sf + 0, __SRD, 0, s); + std (s->__sf + 1, __SWR | __SLBF, 1, s); + std (s->__sf + 2, __SWR | __SNBF, 2, s); + + s->__sglue._next = NULL; + s->__sglue._niobs = 3; + s->__sglue._iobs = &s->__sf[0]; +} diff --git a/newlib/libc/stdio/fiprintf.c b/newlib/libc/stdio/fiprintf.c new file mode 100644 index 000000000..d490ef403 --- /dev/null +++ b/newlib/libc/stdio/fiprintf.c @@ -0,0 +1,77 @@ +/* +FUNCTION + <<fiprintf>>---format output to file (integer only) +INDEX + fiprintf + +ANSI_SYNOPSIS + #include <stdio.h> + + int fiprintf(FILE *<[fd]>, const char *<[format]>, ...); + +TRAD_SYNOPSIS + #include <stdio.h> + + int fiprintf(<[fd]>, <[format]> [, <[arg]>, ...]); + FILE *<[fd]>; + char *<[format]>; + +DESCRIPTION +<<fiprintf>> is a restricted version of <<fprintf>>: it has the same +arguments and behavior, save that it cannot perform any floating-point +formatting---the <<f>>, <<g>>, <<G>>, <<e>>, and <<F>> type specifiers +are not recognized. + +RETURNS + <<fiprintf>> returns the number of bytes in the output string, + save that the concluding <<NULL>> is not counted. + <<fiprintf>> returns when the end of the format string is + encountered. If an error occurs, <<fiprintf>> + returns <<EOF>>. + +PORTABILITY +<<fiprintf>> is not required by ANSI C. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <_ansi.h> +#include <stdio.h> + +#ifdef _HAVE_STDC + +#include <stdarg.h> + +int +fiprintf (FILE * fp, const char *fmt,...) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + ret = vfiprintf (fp, fmt, ap); + va_end (ap); + return ret; +} + +#else + +#include <varargs.h> + +int +fiprintf (fp, fmt, va_alist) + FILE *fp; + char *fmt; + va_dcl +{ + int ret; + va_list ap; + + va_start (ap); + ret = vfiprintf (fp, fmt, ap); + va_end (ap); + return ret; +} + +#endif diff --git a/newlib/libc/stdio/flags.c b/newlib/libc/stdio/flags.c new file mode 100644 index 000000000..6d62bd5bc --- /dev/null +++ b/newlib/libc/stdio/flags.c @@ -0,0 +1,87 @@ +/* No user fns here. Pesch 15apr92 */ + +/* + * Copyright (c) 1990 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <stdio.h> +#include <time.h> +#include <fcntl.h> + +#include <errno.h> +#include <sys/types.h> + +/* + * Return the (stdio) flags for a given mode. Store the flags + * to be passed to an open() syscall through *optr. + * Return 0 on error. + */ + +int +__sflags (ptr, mode, optr) + struct _reent *ptr; + register char *mode; + int *optr; +{ + register int ret, m, o; + + switch (mode[0]) + { + case 'r': /* open for reading */ + ret = __SRD; + m = O_RDONLY; + o = 0; + break; + + case 'w': /* open for writing */ + ret = __SWR; + m = O_WRONLY; + o = O_CREAT | O_TRUNC; + break; + + case 'a': /* open for appending */ + ret = __SWR | __SAPP; + m = O_WRONLY; + o = O_CREAT | O_APPEND; + break; + default: /* illegal mode */ + ptr->_errno = EINVAL; + return (0); + } + if (mode[1] == '+' || mode[2] == '+') + { + ret = __SRW; + m = O_RDWR; + } + if (mode[1] == 'b' || mode[2] == 'b') + { +#ifdef O_BINARY + m |= O_BINARY; +#endif + } +#ifdef __CYGWIN__ + else if (mode[1] == 't' || mode[2] == 't') +#else + else +#endif + { +#ifdef O_TEXT + m |= O_TEXT; +#endif + } + *optr = m | o; + return ret; +} diff --git a/newlib/libc/stdio/floatio.h b/newlib/libc/stdio/floatio.h new file mode 100644 index 000000000..d9577b2b2 --- /dev/null +++ b/newlib/libc/stdio/floatio.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * %W% (Berkeley) %G% + */ + +/* + * Floating point scanf/printf (input/output) definitions. + */ + +/* 11-bit exponent (VAX G floating point) is 308 decimal digits */ +#define MAXEXP 308 +/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */ +#define MAXFRACT 39 diff --git a/newlib/libc/stdio/fopen.c b/newlib/libc/stdio/fopen.c new file mode 100644 index 000000000..30aa54e04 --- /dev/null +++ b/newlib/libc/stdio/fopen.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<fopen>>---open a file + +INDEX + fopen +INDEX + _fopen_r + +ANSI_SYNOPSIS + #include <stdio.h> + FILE *fopen(const char *<[file]>, const char *<[mode]>); + + FILE *_fopen_r(void *<[reent]>, + const char *<[file]>, const char *<[mode]>); + +TRAD_SYNOPSIS + #include <stdio.h> + FILE *fopen(<[file]>, <[mode]>) + char *<[file]>; + char *<[mode]>; + + FILE *_fopen_r(<[reent]>, <[file]>, <[mode]>) + char *<[reent]>; + char *<[file]>; + char *<[mode]>; + +DESCRIPTION +<<fopen>> initializes the data structures needed to read or write a +file. Specify the file's name as the string at <[file]>, and the kind +of access you need to the file with the string at <[mode]>. + +The alternate function <<_fopen_r>> is a reentrant version. +The extra argument <[reent]> is a pointer to a reentrancy structure. + +Three fundamental kinds of access are available: read, write, and append. +<<*<[mode]>>> must begin with one of the three characters `<<r>>', +`<<w>>', or `<<a>>', to select one of these: + +o+ +o r +Open the file for reading; the operation will fail if the file does +not exist, or if the host system does not permit you to read it. + +o w +Open the file for writing @emph{from the beginning} of the file: +effectively, this always creates a new file. If the file whose name you +specified already existed, its old contents are discarded. + +o a +Open the file for appending data, that is writing from the end of +file. When you open a file this way, all data always goes to the +current end of file; you cannot change this using <<fseek>>. +o- + +Some host systems distinguish between ``binary'' and ``text'' files. +Such systems may perform data transformations on data written to, or +read from, files opened as ``text''. +If your system is one of these, then you can append a `<<b>>' to any +of the three modes above, to specify that you are opening the file as +a binary file (the default is to open the file as a text file). + +`<<rb>>', then, means ``read binary''; `<<wb>>', ``write binary''; and +`<<ab>>', ``append binary''. + +To make C programs more portable, the `<<b>>' is accepted on all +systems, whether or not it makes a difference. + +Finally, you might need to both read and write from the same file. +You can also append a `<<+>>' to any of the three modes, to permit +this. (If you want to append both `<<b>>' and `<<+>>', you can do it +in either order: for example, <<"rb+">> means the same thing as +<<"r+b">> when used as a mode string.) + +Use <<"r+">> (or <<"rb+">>) to permit reading and writing anywhere in +an existing file, without discarding any data; <<"w+">> (or <<"wb+">>) +to create a new file (or begin by discarding all data from an old one) +that permits reading and writing anywhere in it; and <<"a+">> (or +<<"ab+">>) to permit reading anywhere in an existing file, but writing +only at the end. + +RETURNS +<<fopen>> returns a file pointer which you can use for other file +operations, unless the file you requested could not be opened; in that +situation, the result is <<NULL>>. If the reason for failure was an +invalid string at <[mode]>, <<errno>> is set to <<EINVAL>>. + +PORTABILITY +<<fopen>> is required by ANSI C. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <errno.h> +#include "local.h" + +FILE * +_DEFUN (_fopen_r, (ptr, file, mode), + struct _reent *ptr _AND + _CONST char *file _AND + _CONST char *mode) +{ + register FILE *fp; + register int f; + int flags, oflags; + + if ((flags = __sflags (ptr, mode, &oflags)) == 0) + return NULL; + if ((fp = __sfp (ptr)) == NULL) + return NULL; + + if ((f = _open_r (fp->_data, file, oflags, 0666)) < 0) + { + fp->_flags = 0; /* release */ + return NULL; + } + + fp->_file = f; + fp->_flags = flags; + fp->_cookie = (_PTR) fp; + fp->_read = __sread; + fp->_write = __swrite; + fp->_seek = __sseek; + fp->_close = __sclose; + + if (fp->_flags & __SAPP) + fseek (fp, 0, SEEK_END); + + return fp; +} + +#ifndef _REENT_ONLY + +FILE * +_DEFUN (fopen, (file, mode), + _CONST char *file _AND + _CONST char *mode) +{ + return _fopen_r (_REENT, file, mode); +} + +#endif diff --git a/newlib/libc/stdio/fprintf.c b/newlib/libc/stdio/fprintf.c new file mode 100644 index 000000000..de036605f --- /dev/null +++ b/newlib/libc/stdio/fprintf.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <_ansi.h> +#include <stdio.h> + +#ifdef _HAVE_STDC + +#include <stdarg.h> + +int +fprintf (FILE * fp, const char *fmt,...) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + ret = vfprintf (fp, fmt, ap); + va_end (ap); + return ret; +} + +#else + +#include <varargs.h> + +int +fprintf (fp, fmt, va_alist) + FILE *fp; + char *fmt; + va_dcl +{ + int ret; + va_list ap; + + va_start (ap); + ret = vfprintf (fp, fmt, ap); + va_end (ap); + return ret; +} + +#endif diff --git a/newlib/libc/stdio/fputc.c b/newlib/libc/stdio/fputc.c new file mode 100644 index 000000000..966a0dbf7 --- /dev/null +++ b/newlib/libc/stdio/fputc.c @@ -0,0 +1,51 @@ +/* +FUNCTION +<<fputc>>---write a character on a stream or file + +INDEX + fputc + +ANSI_SYNOPSIS + #include <stdio.h> + int fputc(int <[ch]>, FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int fputc(<[ch]>, <[fp]>) + int <[ch]>; + FILE *<[fp]>; + +DESCRIPTION +<<fputc>> converts the argument <[ch]> from an <<int>> to an +<<unsigned char>>, then writes it to the file or stream identified by +<[fp]>. + +If the file was opened with append mode (or if the stream cannot +support positioning), then the new character goes at the end of the +file or stream. Otherwise, the new character is written at the +current value of the position indicator, and the position indicator +oadvances by one. + +For a macro version of this function, see <<putc>>. + +RETURNS +If successful, <<fputc>> returns its argument <[ch]>. If an error +intervenes, the result is <<EOF>>. You can use `<<ferror(<[fp]>)>>' to +query for errors. + +PORTABILITY +<<fputc>> is required by ANSI C. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <stdio.h> + +int +_DEFUN (fputc, (ch, file), + int ch _AND + FILE * file) +{ + return putc (ch, file); +} diff --git a/newlib/libc/stdio/fputs.c b/newlib/libc/stdio/fputs.c new file mode 100644 index 000000000..62ce98fb7 --- /dev/null +++ b/newlib/libc/stdio/fputs.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<fputs>>---write a character string in a file or stream + +INDEX + fputs + +ANSI_SYNOPSIS + #include <stdio.h> + int fputs(const char *<[s]>, FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int fputs(<[s]>, <[fp]>) + char *<[s]>; + FILE *<[fp]>; + +DESCRIPTION +<<fputs>> writes the string at <[s]> (but without the trailing null) +to the file or stream identified by <[fp]>. + +RETURNS +If successful, the result is <<0>>; otherwise, the result is <<EOF>>. + +PORTABILITY +ANSI C requires <<fputs>>, but does not specify that the result on +success must be <<0>>; any non-negative value is permitted. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <stdio.h> +#include <string.h> +#include "fvwrite.h" + +/* + * Write the given string to the given file. + */ + +int +_DEFUN (fputs, (s, fp), + char _CONST * s _AND + FILE * fp) +{ + struct __suio uio; + struct __siov iov; + + iov.iov_base = s; + iov.iov_len = uio.uio_resid = strlen (s); + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + return __sfvwrite (fp, &uio); +} diff --git a/newlib/libc/stdio/fread.c b/newlib/libc/stdio/fread.c new file mode 100644 index 000000000..4de7ce290 --- /dev/null +++ b/newlib/libc/stdio/fread.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<fread>>---read array elements from a file + +INDEX + fread + +ANSI_SYNOPSIS + #include <stdio.h> + size_t fread(void *<[buf]>, size_t <[size]>, size_t <[count]>, + FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + size_t fread(<[buf]>, <[size]>, <[count]>, <[fp]>) + char *<[buf]>; + size_t <[size]>; + size_t <[count]>; + FILE *<[fp]>; + +DESCRIPTION +<<fread>> attempts to copy, from the file or stream identified by +<[fp]>, <[count]> elements (each of size <[size]>) into memory, +starting at <[buf]>. <<fread>> may copy fewer elements than +<[count]> if an error, or end of file, intervenes. + +<<fread>> also advances the file position indicator (if any) for +<[fp]> by the number of @emph{characters} actually read. + +RETURNS +The result of <<fread>> is the number of elements it succeeded in +reading. + +PORTABILITY +ANSI C requires <<fread>>. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <stdio.h> +#include <string.h> +#include "local.h" + +size_t +_DEFUN (fread, (buf, size, count, fp), + _PTR buf _AND + size_t size _AND + size_t count _AND + FILE * fp) +{ + register size_t resid; + register char *p; + register int r; + size_t total; + + if ((resid = count * size) == 0) + return 0; + if (fp->_r < 0) + fp->_r = 0; + total = resid; + p = buf; + while (resid > (r = fp->_r)) + { + (void) memcpy ((void *) p, (void *) fp->_p, (size_t) r); + fp->_p += r; + /* fp->_r = 0 ... done in __srefill */ + p += r; + resid -= r; + if (__srefill (fp)) + { + /* no more input: return partial result */ + return (total - resid) / size; + } + } + (void) memcpy ((void *) p, (void *) fp->_p, resid); + fp->_r -= resid; + fp->_p += resid; + return count; +} diff --git a/newlib/libc/stdio/freopen.c b/newlib/libc/stdio/freopen.c new file mode 100644 index 000000000..a4ab965e9 --- /dev/null +++ b/newlib/libc/stdio/freopen.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<freopen>>---open a file using an existing file descriptor + +INDEX + freopen + +ANSI_SYNOPSIS + #include <stdio.h> + FILE *freopen(const char *<[file]>, const char *<[mode]>, + FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + FILE *freopen(<[file]>, <[mode]>, <[fp]>) + char *<[file]>; + char *<[mode]>; + FILE *<[fp]>; + +DESCRIPTION +Use this variant of <<fopen>> if you wish to specify a particular file +descriptor <[fp]> (notably <<stdin>>, <<stdout>>, or <<stderr>>) for +the file. + +If <[fp]> was associated with another file or stream, <<freopen>> +closes that other file or stream (but ignores any errors while closing +it). + +<[file]> and <[mode]> are used just as in <<fopen>>. + +RETURNS +If successful, the result is the same as the argument <[fp]>. If the +file cannot be opened as specified, the result is <<NULL>>. + +PORTABILITY +ANSI C requires <<freopen>>. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <time.h> +#include <stdio.h> +#include <fcntl.h> +#include <stdlib.h> +#include "local.h" + +/* + * Re-direct an existing, open (probably) file to some other file. + */ + +FILE * +_DEFUN (freopen, (file, mode, fp), + _CONST char *file _AND + _CONST char *mode _AND + register FILE *fp) +{ + register int f; + int flags, oflags, e; + struct _reent *ptr; + + CHECK_INIT (fp); + ptr = fp->_data; + + if ((flags = __sflags (ptr, mode, &oflags)) == 0) + { + (void) fclose (fp); + return NULL; + } + + /* + * Remember whether the stream was open to begin with, and + * which file descriptor (if any) was associated with it. + * If it was attached to a descriptor, defer closing it, + * so that, e.g., freopen("/dev/stdin", "r", stdin) works. + * This is unnecessary if it was not a Unix file. + */ + + if (fp->_flags == 0) + fp->_flags = __SEOF; /* hold on to it */ + else + { + if (fp->_flags & __SWR) + (void) fflush (fp); + /* if close is NULL, closing is a no-op, hence pointless */ + if (fp->_close != NULL) + (void) (*fp->_close) (fp->_cookie); + } + + /* + * Now get a new descriptor to refer to the new file. + */ + + f = _open_r (ptr, (char *) file, oflags, 0666); + e = ptr->_errno; + + /* + * Finish closing fp. Even if the open succeeded above, + * we cannot keep fp->_base: it may be the wrong size. + * This loses the effect of any setbuffer calls, + * but stdio has always done this before. + */ + + if (fp->_flags & __SMBF) + _free_r (ptr, (char *) fp->_bf._base); + fp->_w = 0; + fp->_r = 0; + fp->_p = NULL; + fp->_bf._base = NULL; + fp->_bf._size = 0; + fp->_lbfsize = 0; + if (HASUB (fp)) + FREEUB (fp); + fp->_ub._size = 0; + if (HASLB (fp)) + FREELB (fp); + fp->_lb._size = 0; + + if (f < 0) + { /* did not get it after all */ + fp->_flags = 0; /* set it free */ + ptr->_errno = e; /* restore in case _close clobbered */ + return NULL; + } + + fp->_flags = flags; + fp->_file = f; + fp->_cookie = (_PTR) fp; + fp->_read = __sread; + fp->_write = __swrite; + fp->_seek = __sseek; + fp->_close = __sclose; + return fp; +} diff --git a/newlib/libc/stdio/fscanf.c b/newlib/libc/stdio/fscanf.c new file mode 100644 index 000000000..8980410d3 --- /dev/null +++ b/newlib/libc/stdio/fscanf.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <_ansi.h> +#include <stdio.h> + +#ifdef _HAVE_STDC + +#include <stdarg.h> + +extern int __svfscanf (); + +int +fscanf (FILE * fp, const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + ret = __svfscanf (fp, fmt, ap); + va_end (ap); + return ret; +} + +#else + +#include <varargs.h> + +extern int __svfscanf (); + +int +fscanf (fp, fmt, va_alist) + FILE *fp; + char *fmt; + va_dcl +{ + int ret; + va_list ap; + + va_start (ap); + ret = __svfscanf (fp, fmt, ap); + va_end (ap); + return ret; +} + +#endif diff --git a/newlib/libc/stdio/fseek.c b/newlib/libc/stdio/fseek.c new file mode 100644 index 000000000..d22292e97 --- /dev/null +++ b/newlib/libc/stdio/fseek.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<fseek>>---set file position + +INDEX + fseek + +ANSI_SYNOPSIS + #include <stdio.h> + int fseek(FILE *<[fp]>, long <[offset]>, int <[whence]>) + +TRAD_SYNOPSIS + #include <stdio.h> + int fseek(<[fp]>, <[offset]>, <[whence]>) + FILE *<[fp]>; + long <[offset]>; + int <[whence]>; + +DESCRIPTION +Objects of type <<FILE>> can have a ``position'' that records how much +of the file your program has already read. Many of the <<stdio>> functions +depend on this position, and many change it as a side effect. + +You can use <<fseek>> to set the position for the file identified by +<[fp]>. The value of <[offset]> determines the new position, in one +of three ways selected by the value of <[whence]> (defined as macros +in `<<stdio.h>>'): + +<<SEEK_SET>>---<[offset]> is the absolute file position (an offset +from the beginning of the file) desired. <[offset]> must be positive. + +<<SEEK_CUR>>---<[offset]> is relative to the current file position. +<[offset]> can meaningfully be either positive or negative. + +<<SEEK_END>>---<[offset]> is relative to the current end of file. +<[offset]> can meaningfully be either positive (to increase the size +of the file) or negative. + +See <<ftell>> to determine the current file position. + +RETURNS +<<fseek>> returns <<0>> when successful. If <<fseek>> fails, the +result is <<EOF>>. The reason for failure is indicated in <<errno>>: +either <<ESPIPE>> (the stream identified by <[fp]> doesn't support +repositioning) or <<EINVAL>> (invalid file position). + +PORTABILITY +ANSI C requires <<fseek>>. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <stdio.h> +#include <time.h> +#include <fcntl.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/stat.h> +#include "local.h" + +#define POS_ERR (-(fpos_t)1) + +/* + * Seek the given file to the given offset. + * `Whence' must be one of the three SEEK_* macros. + */ + +int +fseek (fp, offset, whence) + register FILE *fp; + long offset; + int whence; +{ + struct _reent *ptr; + fpos_t _EXFUN ((*seekfn), (void *, fpos_t, int)); + fpos_t target, curoff; + size_t n; + struct stat st; + int havepos; + + /* Make sure stdio is set up. */ + + CHECK_INIT (fp); + ptr = fp->_data; + + /* If we've been doing some writing, and we're in append mode + then we don't really know where the filepos is. */ + + if (fp->_flags & __SAPP && fp->_flags & __SWR) + { + /* So flush the buffer and seek to the end. */ + fflush (fp); + } + + /* Have to be able to seek. */ + + if ((seekfn = fp->_seek) == NULL) + { + ptr->_errno = ESPIPE; /* ??? */ + return EOF; + } + + /* + * Change any SEEK_CUR to SEEK_SET, and check `whence' argument. + * After this, whence is either SEEK_SET or SEEK_END. + */ + + switch (whence) + { + case SEEK_CUR: + /* + * In order to seek relative to the current stream offset, + * we have to first find the current stream offset a la + * ftell (see ftell for details). + */ + fflush(fp); /* may adjust seek offset on append stream */ + if (fp->_flags & __SOFF) + curoff = fp->_offset; + else + { + curoff = (*seekfn) (fp->_cookie, (fpos_t) 0, SEEK_CUR); + if (curoff == -1L) + return EOF; + } + if (fp->_flags & __SRD) + { + curoff -= fp->_r; + if (HASUB (fp)) + curoff -= fp->_ur; + } + else if (fp->_flags & __SWR && fp->_p != NULL) + curoff += fp->_p - fp->_bf._base; + + offset += curoff; + whence = SEEK_SET; + havepos = 1; + break; + + case SEEK_SET: + case SEEK_END: + havepos = 0; + break; + + default: + ptr->_errno = EINVAL; + return (EOF); + } + + /* + * Can only optimise if: + * reading (and not reading-and-writing); + * not unbuffered; and + * this is a `regular' Unix file (and hence seekfn==__sseek). + * We must check __NBF first, because it is possible to have __NBF + * and __SOPT both set. + */ + + if (fp->_bf._base == NULL) + __smakebuf (fp); + if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT)) + goto dumb; + if ((fp->_flags & __SOPT) == 0) + { + if (seekfn != __sseek + || fp->_file < 0 + || _fstat_r (ptr, fp->_file, &st) + || (st.st_mode & S_IFMT) != S_IFREG) + { + fp->_flags |= __SNPT; + goto dumb; + } +#ifdef HAVE_BLKSIZE + fp->_blksize = st.st_blksize; +#else + fp->_blksize = 1024; +#endif + fp->_flags |= __SOPT; + } + + /* + * We are reading; we can try to optimise. + * Figure out where we are going and where we are now. + */ + + if (whence == SEEK_SET) + target = offset; + else + { + if (_fstat_r (ptr, fp->_file, &st)) + goto dumb; + target = st.st_size + offset; + } + + if (!havepos) + { + if (fp->_flags & __SOFF) + curoff = fp->_offset; + else + { + curoff = (*seekfn) (fp->_cookie, 0L, SEEK_CUR); + if (curoff == POS_ERR) + goto dumb; + } + curoff -= fp->_r; + if (HASUB (fp)) + curoff -= fp->_ur; + } + + /* + * Compute the number of bytes in the input buffer (pretending + * that any ungetc() input has been discarded). Adjust current + * offset backwards by this count so that it represents the + * file offset for the first byte in the current input buffer. + */ + + if (HASUB (fp)) + { + curoff += fp->_r; /* kill off ungetc */ + n = fp->_up - fp->_bf._base; + curoff -= n; + n += fp->_ur; + } + else + { + n = fp->_p - fp->_bf._base; + curoff -= n; + n += fp->_r; + } + + /* + * If the target offset is within the current buffer, + * simply adjust the pointers, clear EOF, undo ungetc(), + * and return. (If the buffer was modified, we have to + * skip this; see fgetline.c.) + */ + + if ((fp->_flags & __SMOD) == 0 && + target >= curoff && target < curoff + n) + { + register int o = target - curoff; + + fp->_p = fp->_bf._base + o; + fp->_r = n - o; + if (HASUB (fp)) + FREEUB (fp); + fp->_flags &= ~__SEOF; + return 0; + } + + /* + * The place we want to get to is not within the current buffer, + * but we can still be kind to the kernel copyout mechanism. + * By aligning the file offset to a block boundary, we can let + * the kernel use the VM hardware to map pages instead of + * copying bytes laboriously. Using a block boundary also + * ensures that we only read one block, rather than two. + */ + + curoff = target & ~(fp->_blksize - 1); + if ((*seekfn) (fp->_cookie, curoff, SEEK_SET) == POS_ERR) + goto dumb; + fp->_r = 0; + if (HASUB (fp)) + FREEUB (fp); + fp->_flags &= ~__SEOF; + n = target - curoff; + if (n) + { + if (__srefill (fp) || fp->_r < n) + goto dumb; + fp->_p += n; + fp->_r -= n; + } + return 0; + + /* + * We get here if we cannot optimise the seek ... just + * do it. Allow the seek function to change fp->_bf._base. + */ + +dumb: + if (fflush (fp) || (*seekfn) (fp->_cookie, offset, whence) == POS_ERR) + return EOF; + /* success: clear EOF indicator and discard ungetc() data */ + if (HASUB (fp)) + FREEUB (fp); + fp->_p = fp->_bf._base; + fp->_r = 0; + /* fp->_w = 0; *//* unnecessary (I think...) */ + fp->_flags &= ~__SEOF; + return 0; +} diff --git a/newlib/libc/stdio/fsetpos.c b/newlib/libc/stdio/fsetpos.c new file mode 100644 index 000000000..28cd69ead --- /dev/null +++ b/newlib/libc/stdio/fsetpos.c @@ -0,0 +1,54 @@ +/* +FUNCTION +<<fsetpos>>---restore position of a stream or file + +INDEX + fsetpos + +ANSI_SYNOPSIS + #include <stdio.h> + int fsetpos(FILE *<[fp]>, const fpos_t *<[pos]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int fsetpos(<[fp]>, <[pos]>) + FILE *<[fp]>; + fpos_t *<[pos]>; + +DESCRIPTION +Objects of type <<FILE>> can have a ``position'' that records how much +of the file your program has already read. Many of the <<stdio>> functions +depend on this position, and many change it as a side effect. + +You can use <<fsetpos>> to return the file identified by <[fp]> to a previous +position <<*<[pos]>>> (after first recording it with <<fgetpos>>). + +See <<fseek>> for a similar facility. + +RETURNS +<<fgetpos>> returns <<0>> when successful. If <<fgetpos>> fails, the +result is <<1>>. The reason for failure is indicated in <<errno>>: +either <<ESPIPE>> (the stream identified by <[fp]> doesn't support +repositioning) or <<EINVAL>> (invalid file position). + +PORTABILITY +ANSI C requires <<fsetpos>>, but does not specify the nature of +<<*<[pos]>>> beyond identifying it as written by <<fgetpos>>. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <stdio.h> + +int +_DEFUN (fsetpos, (iop, pos), + FILE * iop _AND + _CONST fpos_t * pos) +{ + int x = fseek (iop, *pos, SEEK_SET); + + if (x != 0) + return 1; + return 0; +} diff --git a/newlib/libc/stdio/ftell.c b/newlib/libc/stdio/ftell.c new file mode 100644 index 000000000..6a8061816 --- /dev/null +++ b/newlib/libc/stdio/ftell.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<ftell>>---return position in a stream or file + +INDEX + ftell + +ANSI_SYNOPSIS + #include <stdio.h> + long ftell(FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + long ftell(<[fp]>) + FILE *<[fp]>; + +DESCRIPTION +Objects of type <<FILE>> can have a ``position'' that records how much +of the file your program has already read. Many of the <<stdio>> functions +depend on this position, and many change it as a side effect. + +The result of <<ftell>> is the current position for a file +identified by <[fp]>. If you record this result, you can later +use it with <<fseek>> to return the file to this +position. + +In the current implementation, <<ftell>> simply uses a character +count to represent the file position; this is the same number that +would be recorded by <<fgetpos>>. + +RETURNS +<<ftell>> returns the file position, if possible. If it cannot do +this, it returns <<-1L>>. Failure occurs on streams that do not support +positioning; the global <<errno>> indicates this condition with the +value <<ESPIPE>>. + +PORTABILITY +<<ftell>> is required by the ANSI C standard, but the meaning of its +result (when successful) is not specified beyond requiring that it be +acceptable as an argument to <<fseek>>. In particular, other +conforming C implementations may return a different result from +<<ftell>> than what <<fgetpos>> records. + +No supporting OS subroutines are required. +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +/* + * ftell: return current offset. + */ + +#include <stdio.h> +#include <errno.h> + +#include "local.h" + +long +_DEFUN (ftell, (fp), + register FILE * fp) +{ + fpos_t pos; + + /* Ensure stdio is set up. */ + + CHECK_INIT (fp); + + if (fp->_seek == NULL) + { + fp->_data->_errno = ESPIPE; + return -1L; + } + + /* Find offset of underlying I/O object, then + adjust for buffered bytes. */ + fflush(fp); /* may adjust seek offset on append stream */ + if (fp->_flags & __SOFF) + pos = fp->_offset; + else + { + pos = (*fp->_seek) (fp->_cookie, (fpos_t) 0, SEEK_CUR); + if (pos == -1L) + return pos; + } + if (fp->_flags & __SRD) + { + /* + * Reading. Any unread characters (including + * those from ungetc) cause the position to be + * smaller than that in the underlying object. + */ + pos -= fp->_r; + if (HASUB (fp)) + pos -= fp->_ur; + } + else if (fp->_flags & __SWR && fp->_p != NULL) + { + /* + * Writing. Any buffered characters cause the + * position to be greater than that in the + * underlying object. + */ + pos += fp->_p - fp->_bf._base; + } + + return pos; +} diff --git a/newlib/libc/stdio/fvwrite.c b/newlib/libc/stdio/fvwrite.c new file mode 100644 index 000000000..00e758a47 --- /dev/null +++ b/newlib/libc/stdio/fvwrite.c @@ -0,0 +1,195 @@ +/* No user fns here. Pesch 15apr92. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <stdio.h> +#include <string.h> +#include "local.h" +#include "fvwrite.h" + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define COPY(n) (void) memmove((void *) fp->_p, (void *) p, (size_t) (n)) + +#define GETIOV(extra_work) \ + while (len == 0) \ + { \ + extra_work; \ + p = iov->iov_base; \ + len = iov->iov_len; \ + iov++; \ + } + +/* + * Write some memory regions. Return zero on success, EOF on error. + * + * This routine is large and unsightly, but most of the ugliness due + * to the three different kinds of output buffering is handled here. + */ + +int +__sfvwrite (fp, uio) + register FILE *fp; + register struct __suio *uio; +{ + register size_t len; + register _CONST char *p; + register struct __siov *iov; + register int w, s; + char *nl; + int nlknown, nldist; + + if ((len = uio->uio_resid) == 0) + return 0; + + /* make sure we can write */ + if (cantwrite (fp)) + return EOF; + + iov = uio->uio_iov; + len = 0; + if (fp->_flags & __SNBF) + { + /* + * Unbuffered: write up to BUFSIZ bytes at a time. + */ + do + { + GETIOV (;); + w = (*fp->_write) (fp->_cookie, p, MIN (len, BUFSIZ)); + if (w <= 0) + goto err; + p += w; + len -= w; + } + while ((uio->uio_resid -= w) != 0); + } + else if ((fp->_flags & __SLBF) == 0) + { + /* + * Fully buffered: fill partially full buffer, if any, + * and then flush. If there is no partial buffer, write + * one _bf._size byte chunk directly (without copying). + * + * String output is a special case: write as many bytes + * as fit, but pretend we wrote everything. This makes + * snprintf() return the number of bytes needed, rather + * than the number used, and avoids its write function + * (so that the write function can be invalid). + */ + do + { + GETIOV (;); + w = fp->_w; + if (fp->_flags & __SSTR) + { + if (len < w) + w = len; + COPY (w); /* copy MIN(fp->_w,len), */ + fp->_w -= w; + fp->_p += w; + w = len; /* but pretend copied all */ + } + else if (fp->_p > fp->_bf._base && len > w) + { + /* fill and flush */ + COPY (w); + /* fp->_w -= w; *//* unneeded */ + fp->_p += w; + if (fflush (fp)) + goto err; + } + else if (len >= (w = fp->_bf._size)) + { + /* write directly */ + w = (*fp->_write) (fp->_cookie, p, w); + if (w <= 0) + goto err; + } + else + { + /* fill and done */ + w = len; + COPY (w); + fp->_w -= w; + fp->_p += w; + } + p += w; + len -= w; + } + while ((uio->uio_resid -= w) != 0); + } + else + { + /* + * Line buffered: like fully buffered, but we + * must check for newlines. Compute the distance + * to the first newline (including the newline), + * or `infinity' if there is none, then pretend + * that the amount to write is MIN(len,nldist). + */ + nlknown = 0; + do + { + GETIOV (nlknown = 0); + if (!nlknown) + { + nl = memchr ((void *) p, '\n', len); + nldist = nl ? nl + 1 - p : len + 1; + nlknown = 1; + } + s = MIN (len, nldist); + w = fp->_w + fp->_bf._size; + if (fp->_p > fp->_bf._base && s > w) + { + COPY (w); + /* fp->_w -= w; */ + fp->_p += w; + if (fflush (fp)) + goto err; + } + else if (s >= (w = fp->_bf._size)) + { + w = (*fp->_write) (fp->_cookie, p, w); + if (w <= 0) + goto err; + } + else + { + w = s; + COPY (w); + fp->_w -= w; + fp->_p += w; + } + if ((nldist -= w) == 0) + { + /* copied the newline: flush and forget */ + if (fflush (fp)) + goto err; + nlknown = 0; + } + p += w; + len -= w; + } + while ((uio->uio_resid -= w) != 0); + } + return 0; + +err: + fp->_flags |= __SERR; + return EOF; +} diff --git a/newlib/libc/stdio/fvwrite.h b/newlib/libc/stdio/fvwrite.h new file mode 100644 index 000000000..f27abdf81 --- /dev/null +++ b/newlib/libc/stdio/fvwrite.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* %W% (Berkeley) %G% */ +#include <_ansi.h> + +/* + * I/O descriptors for __sfvwrite(). + */ +struct __siov { + _CONST _PTR iov_base; + size_t iov_len; +}; +struct __suio { + struct __siov *uio_iov; + int uio_iovcnt; + int uio_resid; +}; + + +extern int _EXFUN(__sfvwrite,(FILE *, struct __suio *)); +extern int _EXFUN(__swsetup,(FILE *)); + + diff --git a/newlib/libc/stdio/fwalk.c b/newlib/libc/stdio/fwalk.c new file mode 100644 index 000000000..516283466 --- /dev/null +++ b/newlib/libc/stdio/fwalk.c @@ -0,0 +1,43 @@ +/* No user fns here. Pesch 15apr92. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include "local.h" + +int +_fwalk (ptr, function) + struct _reent *ptr; + register int (*function) (); +{ + register FILE *fp; + register int n, ret = 0; + register struct _glue *g; + + for (g = &ptr->__sglue; g != NULL; g = g->_next) + for (fp = g->_iobs, n = g->_niobs; --n >= 0; fp++) + if (fp->_flags != 0) + ret |= (*function) (fp); + return ret; +} diff --git a/newlib/libc/stdio/fwrite.c b/newlib/libc/stdio/fwrite.c new file mode 100644 index 000000000..642fb274f --- /dev/null +++ b/newlib/libc/stdio/fwrite.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<fwrite>>---write array elements + +INDEX + fwrite + +ANSI_SYNOPSIS + #include <stdio.h> + size_t fwrite(const void *<[buf]>, size_t <[size]>, + size_t <[count]>, FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + size_t fwrite(<[buf]>, <[size]>, <[count]>, <[fp]>) + char *<[buf]>; + size_t <[size]>; + size_t <[count]>; + FILE *<[fp]>; + +DESCRIPTION +<<fwrite>> attempts to copy, starting from the memory location +<[buf]>, <[count]> elements (each of size <[size]>) into the file or +stream identified by <[fp]>. <<fwrite>> may copy fewer elements than +<[count]> if an error intervenes. + +<<fwrite>> also advances the file position indicator (if any) for +<[fp]> by the number of @emph{characters} actually written. + +RETURNS +If <<fwrite>> succeeds in writing all the elements you specify, the +result is the same as the argument <[count]>. In any event, the +result is the number of complete elements that <<fwrite>> copied to +the file. + +PORTABILITY +ANSI C requires <<fwrite>>. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <string.h> +#if 0 +#include <sys/stdc.h> +#endif +#include "local.h" +#if 1 +#include "fvwrite.h" +#endif + +/* + * Write `count' objects (each size `size') from memory to the given file. + * Return the number of whole objects written. + */ + +size_t +_DEFUN (fwrite, (buf, size, count, fp), + _CONST _PTR buf _AND + size_t size _AND + size_t count _AND + FILE * fp) +{ + size_t n; + struct __suio uio; + struct __siov iov; + + iov.iov_base = buf; + uio.uio_resid = iov.iov_len = n = count * size; + uio.uio_iov = &iov; + uio.uio_iovcnt = 1; + + /* + * The usual case is success (__sfvwrite returns 0); + * skip the divide if this happens, since divides are + * generally slow and since this occurs whenever size==0. + */ + + if (__sfvwrite (fp, &uio) == 0) + return count; + return (n - uio.uio_resid) / size; +} diff --git a/newlib/libc/stdio/getc.c b/newlib/libc/stdio/getc.c new file mode 100644 index 000000000..4b2509737 --- /dev/null +++ b/newlib/libc/stdio/getc.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<getc>>---read a character (macro) + +INDEX + getc + +ANSI_SYNOPSIS + #include <stdio.h> + int getc(FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int getc(<[fp]>) + FILE *<[fp]>; + +DESCRIPTION +<<getc>> is a macro, defined in <<stdio.h>>. You can use <<getc>> +to get the next single character from the file or stream +identified by <[fp]>. As a side effect, <<getc>> advances the file's +current position indicator. + +For a subroutine version of this macro, see <<fgetc>>. + +RETURNS +The next character (read as an <<unsigned char>>, and cast to +<<int>>), unless there is no more data, or the host system reports a +read error; in either of these situations, <<getc>> returns <<EOF>>. + +You can distinguish the two situations that cause an <<EOF>> result by +using the <<ferror>> and <<feof>> functions. + +PORTABILITY +ANSI C requires <<getc>>; it suggests, but does not require, that +<<getc>> be implemented as a macro. The standard explicitly permits +macro implementations of <<getc>> to use the argument more than once; +therefore, in a portable program, you should not use an expression +with side effects as the <<getc>> argument. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +/* + * A subroutine version of the macro getc. + */ + +#undef getc + +int +getc (fp) + register FILE *fp; +{ + /* CHECK_INIT is called (eventually) by __srefill. */ + + return __sgetc (fp); +} diff --git a/newlib/libc/stdio/getchar.c b/newlib/libc/stdio/getchar.c new file mode 100644 index 000000000..475cd138b --- /dev/null +++ b/newlib/libc/stdio/getchar.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<getchar>>---read a character (macro) + +INDEX + getchar +INDEX + _getchar_r + +ANSI_SYNOPSIS + #include <stdio.h> + int getchar(void); + + int _getchar_r(void *<[reent]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int getchar(); + + int _getchar_r(<[reent]>) + char * <[reent]>; + +DESCRIPTION +<<getchar>> is a macro, defined in <<stdio.h>>. You can use <<getchar>> +to get the next single character from the standard input stream. +As a side effect, <<getchar>> advances the standard input's +current position indicator. + +The alternate function <<_getchar_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + + +RETURNS +The next character (read as an <<unsigned char>>, and cast to +<<int>>), unless there is no more data, or the host system reports a +read error; in either of these situations, <<getchar>> returns <<EOF>>. + +You can distinguish the two situations that cause an <<EOF>> result by +using `<<ferror(stdin)>>' and `<<feof(stdin)>>'. + +PORTABILITY +ANSI C requires <<getchar>>; it suggests, but does not require, that +<<getchar>> be implemented as a macro. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +/* + * A subroutine version of the macro getchar. + */ + +#include <stdio.h> +#include <reent.h> + +#undef getchar + +int +_getchar_r (f) + struct _reent *f; +{ + return getc (_stdin_r (f)); +} + +#ifndef _REENT_ONLY + +int +getchar () +{ + /* CHECK_INIT is called (eventually) by __srefill. */ + + return _getchar_r (_REENT); +} + +#endif diff --git a/newlib/libc/stdio/gets.c b/newlib/libc/stdio/gets.c new file mode 100644 index 000000000..796100e32 --- /dev/null +++ b/newlib/libc/stdio/gets.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + + +/* + +FUNCTION + <<gets>>---get character string (obsolete, use <<fgets>> instead) +INDEX + gets +INDEX + _gets_r + +ANSI_SYNOPSIS + #include <stdio.h> + + char *gets(char *<[buf]>); + + char *_gets_r(void *<[reent]>, char *<[buf]>); + +TRAD_SYNOPSIS + #include <stdio.h> + + char *gets(<[buf]>) + char *<[buf]>; + + char *_gets_r(<[reent]>, <[buf]>) + char *<[reent]>; + char *<[buf]>; + +DESCRIPTION + Reads characters from standard input until a newline is found. + The characters up to the newline are stored in <[buf]>. The + newline is discarded, and the buffer is terminated with a 0. + + This is a @emph{dangerous} function, as it has no way of checking + the amount of space available in <[buf]>. One of the attacks + used by the Internet Worm of 1988 used this to overrun a + buffer allocated on the stack of the finger daemon and + overwrite the return address, causing the daemon to execute + code downloaded into it over the connection. + + The alternate function <<_gets_r>> is a reentrant version. The extra + argument <[reent]> is a pointer to a reentrancy structure. + + +RETURNS + <<gets>> returns the buffer passed to it, with the data filled + in. If end of file occurs with some data already accumulated, + the data is returned with no other indication. If end of file + occurs with no data in the buffer, NULL is returned. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <stdio.h> + +char * +_gets_r (ptr, buf) + struct _reent *ptr; + char *buf; +{ + register int c; + register char *s = buf; + + while ((c = _getchar_r (ptr)) != '\n') + if (c == EOF) + if (s == buf) + return NULL; + else + break; + else + *s++ = c; + *s = 0; + return buf; +} + +#ifndef _REENT_ONLY + +char * +gets (buf) + char *buf; +{ + return _gets_r (_REENT, buf); +} + +#endif diff --git a/newlib/libc/stdio/iprintf.c b/newlib/libc/stdio/iprintf.c new file mode 100644 index 000000000..f05404302 --- /dev/null +++ b/newlib/libc/stdio/iprintf.c @@ -0,0 +1,118 @@ +/* +FUNCTION + <<iprintf>>---write formatted output (integer only) +INDEX + iprintf + +ANSI_SYNOPSIS + #include <stdio.h> + + int iprintf(const char *<[format]>, ...); + +TRAD_SYNOPSIS + #include <stdio.h> + + int iprintf(<[format]> [, <[arg]>, ...]) + char *<[format]>; + +DESCRIPTION +<<iprintf>> is a restricted version of <<printf>>: it has the same +arguments and behavior, save that it cannot perform any floating-point +formatting: the <<f>>, <<g>>, <<G>>, <<e>>, and <<F>> type specifiers +are not recognized. + +RETURNS + <<iprintf>> returns the number of bytes in the output string, + save that the concluding <<NULL>> is not counted. + <<iprintf>> returns when the end of the format string is + encountered. If an error occurs, <<iprintf>> + returns <<EOF>>. + +PORTABILITY +<<iprintf>> is not required by ANSI C. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <_ansi.h> +#include <stdio.h> + +#ifndef _REENT_ONLY + +#ifdef _HAVE_STDC + +#include <stdarg.h> + +int +iprintf (const char *fmt,...) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + _stdout_r (_REENT)->_data = _REENT; + ret = vfiprintf (stdout, fmt, ap); + va_end (ap); + return ret; +} + +#else + +#include <varargs.h> + +int +iprintf (fmt, va_alist) + char *fmt; + va_dcl +{ + int ret; + va_list ap; + + va_start (ap); + _stdout_r (_REENT)->_data = _REENT; + ret = vfiprintf (stdout, fmt, ap); + va_end (ap); + return ret; +} + +#endif /* ! _HAVE_STDC */ +#endif /* ! _REENT_ONLY */ + +#ifdef _HAVE_STDC + +#include <stdarg.h> + +int +_iprintf_r (struct _reent *ptr, const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + ret = vfiprintf (_stdout_r (ptr), fmt, ap); + va_end (ap); + return ret; +} + +#else + +#include <varargs.h> + +int +_iprintf_r (data, fmt, va_alist) + char *data; + char *fmt; + va_dcl +{ + int ret; + struct _reent *ptr = data; + va_list ap; + + va_start (ap); + ret = vfiprintf (_stdout_r (ptr), fmt, ap); + va_end (ap); + return ret; +} + +#endif diff --git a/newlib/libc/stdio/local.h b/newlib/libc/stdio/local.h new file mode 100644 index 000000000..71e80cc09 --- /dev/null +++ b/newlib/libc/stdio/local.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * %W% (UofMD/Berkeley) %G% + */ + +/* + * Information local to this implementation of stdio, + * in particular, macros and private variables. + */ + +#include <_ansi.h> +#include <stdarg.h> +#include <reent.h> +#include <unistd.h> + +extern int _EXFUN(__svfscanf,(FILE *, _CONST char *,va_list)); +extern FILE *_EXFUN(__sfp,(struct _reent *)); +extern int _EXFUN(__sflags,(struct _reent *,_CONST char*, int*)); +extern int _EXFUN(__srefill,(FILE *)); +extern int _EXFUN(__sread,(void *, char *, int)); +extern int _EXFUN(__swrite,(void *, char const *, int)); +extern fpos_t _EXFUN(__sseek,(void *, fpos_t, int)); +extern int _EXFUN(__sclose,(void *)); +extern void _EXFUN(__sinit,(struct _reent *)); +extern void _EXFUN(_cleanup_r,(struct _reent *)); +extern void _EXFUN(__smakebuf,(FILE *)); +extern int _EXFUN(_fwalk,(struct _reent *, int (*)(FILE *))); +struct _glue * _EXFUN(__sfmoreglue,(struct _reent *,int n)); +extern int _EXFUN(__srefill,(FILE *fp)); + +/* Called by the main entry point fns to ensure stdio has been initialized. */ + +#define CHECK_INIT(fp) \ + do \ + { \ + if ((fp)->_data == 0) \ + (fp)->_data = _REENT; \ + if (!(fp)->_data->__sdidinit) \ + __sinit ((fp)->_data); \ + } \ + while (0) + +/* Return true iff the given FILE cannot be written now. */ + +#define cantwrite(fp) \ + ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && \ + __swsetup(fp)) + +/* Test whether the given stdio file has an active ungetc buffer; + release such a buffer, without restoring ordinary unread data. */ + +#define HASUB(fp) ((fp)->_ub._base != NULL) +#define FREEUB(fp) { \ + if ((fp)->_ub._base != (fp)->_ubuf) \ + _free_r(fp->_data, (char *)(fp)->_ub._base); \ + (fp)->_ub._base = NULL; \ +} + +/* Test for an fgetline() buffer. */ + +#define HASLB(fp) ((fp)->_lb._base != NULL) +#define FREELB(fp) { _free_r(fp->_data,(char *)(fp)->_lb._base); (fp)->_lb._base = NULL; } + +/* WARNING: _dcvt is defined in the stdlib directory, not here! */ + +char *_EXFUN(_dcvt,(struct _reent *, char *, double, int, int, char, int)); +char *_EXFUN(_sicvt,(char *, short, char)); +char *_EXFUN(_icvt,(char *, int, char)); +char *_EXFUN(_licvt,(char *, long, char)); +#ifdef __GNUC__ +char *_EXFUN(_llicvt,(char *, long long, char)); +#endif + +#define CVT_BUF_SIZE 128 + +#define NDYNAMIC 4 /* add four more whenever necessary */ diff --git a/newlib/libc/stdio/makebuf.c b/newlib/libc/stdio/makebuf.c new file mode 100644 index 000000000..4a09c4d50 --- /dev/null +++ b/newlib/libc/stdio/makebuf.c @@ -0,0 +1,96 @@ +/* No user fns here. Pesch 15apr92. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/unistd.h> + +#include "local.h" + +/* + * Allocate a file buffer, or switch to unbuffered I/O. + * Per the ANSI C standard, ALL tty devices default to line buffered. + * + * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek + * optimization) right after the _fstat() that finds the buffer size. + */ + +void +__smakebuf (fp) + register FILE *fp; +{ + register size_t size, couldbetty; + register _PTR p; + struct stat st; + + if (fp->_flags & __SNBF) + { + fp->_bf._base = fp->_p = fp->_nbuf; + fp->_bf._size = 1; + return; + } + if (fp->_file < 0 || _fstat_r (fp->_data, fp->_file, &st) < 0) + { + couldbetty = 0; + size = BUFSIZ; + /* do not try to optimise fseek() */ + fp->_flags |= __SNPT; + } + else + { + couldbetty = (st.st_mode & S_IFMT) == S_IFCHR; +#ifdef HAVE_BLKSIZE + size = st.st_blksize <= 0 ? BUFSIZ : st.st_blksize; +#else + size = BUFSIZ; +#endif + /* + * Optimize fseek() only if it is a regular file. + * (The test for __sseek is mainly paranoia.) + */ + if ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek) + { + fp->_flags |= __SOPT; +#ifdef HAVE_BLKSIZE + fp->_blksize = st.st_blksize; +#else + fp->_blksize = 1024; +#endif + } + else + fp->_flags |= __SNPT; + } + if ((p = _malloc_r (fp->_data, size)) == NULL) + { + fp->_flags |= __SNBF; + fp->_bf._base = fp->_p = fp->_nbuf; + fp->_bf._size = 1; + } + else + { + fp->_data->__cleanup = _cleanup_r; + fp->_flags |= __SMBF; + fp->_bf._base = fp->_p = (unsigned char *) p; + fp->_bf._size = size; + if (couldbetty && isatty (fp->_file)) + fp->_flags |= __SLBF; + } +} diff --git a/newlib/libc/stdio/mktemp.c b/newlib/libc/stdio/mktemp.c new file mode 100644 index 000000000..f6a6b688f --- /dev/null +++ b/newlib/libc/stdio/mktemp.c @@ -0,0 +1,219 @@ +/* This is file MKTEMP.C */ +/* This file may have been modified by DJ Delorie (Jan 1991). If so, +** these modifications are Coyright (C) 1991 DJ Delorie, 24 Kirsten Ave, +** Rochester NH, 03867-2954, USA. +*/ + +/* + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that: (1) source distributions retain this entire copyright + * notice and comment, and (2) distributions including binaries display + * the following acknowledgement: ``This product includes software + * developed by the University of California, Berkeley and its contributors'' + * in the documentation or other materials provided with the distribution + * and in all advertising materials mentioning features or use of this + * software. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<mktemp>>, <<mkstemp>>---generate unused file name + +INDEX + mktemp +INDEX + mkstemp +INDEX + _mktemp_r +INDEX + _mkstemp_r + +ANSI_SYNOPSIS + #include <stdio.h> + char *mktemp(char *<[path]>); + int mkstemp(char *<[path]>); + + char *_mktemp_r(void *<[reent]>, char *<[path]>); + int *_mkstemp_r(void *<[reent]>, char *<[path]>); + +TRAD_SYNOPSIS + #include <stdio.h> + char *mktemp(<[path]>) + char *<[path]>; + + int mkstemp(<[path]>) + char *<[path]>; + + char *_mktemp_r(<[reent]>, <[path]>) + char *<[reent]>; + char *<[path]>; + + int _mkstemp_r(<[reent]>, <[path]>) + char *<[reent]>; + char *<[path]>; + +DESCRIPTION +<<mktemp>> and <<mkstemp>> attempt to generate a file name that is not +yet in use for any existing file. <<mkstemp>> creates the file and +opens it for reading and writing; <<mktemp>> simply generates the file name. + +You supply a simple pattern for the generated file name, as the string +at <[path]>. The pattern should be a valid filename (including path +information if you wish) ending with some number of `<<X>>' +characters. The generated filename will match the leading part of the +name you supply, with the trailing `<<X>>' characters replaced by some +combination of digits and letters. + +The alternate functions <<_mktemp_r>> and <<_mkstemp_r>> are reentrant +versions. The extra argument <[reent]> is a pointer to a reentrancy +structure. + +RETURNS +<<mktemp>> returns the pointer <[path]> to the modified string +representing an unused filename, unless it could not generate one, or +the pattern you provided is not suitable for a filename; in that case, +it returns <<NULL>>. + +<<mkstemp>> returns a file descriptor to the newly created file, +unless it could not generate an unused filename, or the pattern you +provided is not suitable for a filename; in that case, it returns +<<-1>>. + +PORTABILITY +ANSI C does not require either <<mktemp>> or <<mkstemp>>; the System +V Interface Definition requires <<mktemp>> as of Issue 2. + +Supporting OS subroutines required: <<getpid>>, <<open>>, <<stat>>. +*/ + +#include <sys/types.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <errno.h> +#include <stdio.h> +#include <ctype.h> +#include <reent.h> + +static +_DEFUN (_gettemp, (ptr, path, doopen), + struct _reent *ptr _AND + char *path _AND + register int *doopen) +{ + register char *start, *trv; + struct stat sbuf; + unsigned int pid; + + pid = _getpid_r (ptr); + for (trv = path; *trv; ++trv) /* extra X's get set to 0's */ + continue; + while (*--trv == 'X') + { + *trv = (pid % 10) + '0'; + pid /= 10; + } + + /* + * Check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + + for (start = trv + 1;; --trv) + { + if (trv <= path) + break; + if (*trv == '/') + { + *trv = '\0'; + if (_stat_r (ptr, path, &sbuf)) + return (0); + if (!(sbuf.st_mode & S_IFDIR)) + { + ptr->_errno = ENOTDIR; + return (0); + } + *trv = '/'; + break; + } + } + + for (;;) + { + if (doopen) + { + if ((*doopen = _open_r (ptr, path, O_CREAT | O_EXCL | O_RDWR, 0600)) + >= 0) + return 1; +#if defined(__CYGWIN32__) || defined(__CYGWIN__) + if (ptr->_errno != EEXIST && ptr->_errno != EACCES) +#else + if (ptr->_errno != EEXIST) +#endif + return 0; + } + else if (_stat_r (ptr, path, &sbuf)) + return (ptr->_errno == ENOENT ? 1 : 0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) + { + if (!*trv) + return 0; + if (*trv == 'z') + *trv++ = 'a'; + else + { + if (isdigit (*trv)) + *trv = 'a'; + else + ++ * trv; + break; + } + } + } + /*NOTREACHED*/ +} + +_DEFUN (_mkstemp_r, (ptr, path), + struct _reent *ptr _AND + char *path) +{ + int fd; + + return (_gettemp (ptr, path, &fd) ? fd : -1); +} + +char * +_DEFUN (_mktemp_r, (ptr, path), + struct _reent *ptr _AND + char *path) +{ + return (_gettemp (ptr, path, (int *) NULL) ? path : (char *) NULL); +} + +#ifndef _REENT_ONLY + +_DEFUN (mkstemp, (path), + char *path) +{ + int fd; + + return (_gettemp (_REENT, path, &fd) ? fd : -1); +} + +char * +_DEFUN (mktemp, (path), + char *path) +{ + return (_gettemp (_REENT, path, (int *) NULL) ? path : (char *) NULL); +} + +#endif /* ! defined (_REENT_ONLY) */ diff --git a/newlib/libc/stdio/perror.c b/newlib/libc/stdio/perror.c new file mode 100644 index 000000000..abb595ba9 --- /dev/null +++ b/newlib/libc/stdio/perror.c @@ -0,0 +1,80 @@ +/* +FUNCTION +<<perror>>---print an error message on standard error + +INDEX + perror +INDEX + _perror_r + +ANSI_SYNOPSIS + #include <stdio.h> + void perror(char *<[prefix]>); + + void _perror_r(void *<[reent]>, char *<[prefix]>); + +TRAD_SYNOPSIS + #include <stdio.h> + void perror(<[prefix]>) + char *<[prefix]>; + + void _perror_r(<[reent]>, <[prefix]>) + char *<[reent]>; + char *<[prefix]>; + +DESCRIPTION +Use <<perror>> to print (on standard error) an error message +corresponding to the current value of the global variable <<errno>>. +Unless you use <<NULL>> as the value of the argument <[prefix]>, the +error message will begin with the string at <[prefix]>, followed by a +colon and a space (<<: >>). The remainder of the error message is one +of the strings described for <<strerror>>. + +The alternate function <<_perror_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + + +RETURNS +<<perror>> returns no result. + +PORTABILITY +ANSI C requires <<perror>>, but the strings issued vary from one +implementation to another. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +void +_DEFUN (_perror_r, (ptr, s), + struct _reent *ptr _AND + _CONST char *s) +{ + char *error; + + if (s != NULL && *s != '\0') + { + fputs (s, _stderr_r (ptr)); + fputs (": ", _stderr_r (ptr)); + } + + if ((error = strerror (ptr->_errno)) != NULL) + fputs (error, _stderr_r (ptr)); + + fputc ('\n', _stderr_r (ptr)); +} + +#ifndef _REENT_ONLY + +void +_DEFUN (perror, (s), + _CONST char *s) +{ + _perror_r (_REENT, s); +} + +#endif diff --git a/newlib/libc/stdio/printf.c b/newlib/libc/stdio/printf.c new file mode 100644 index 000000000..81fb8a2cb --- /dev/null +++ b/newlib/libc/stdio/printf.c @@ -0,0 +1,83 @@ + +#include <_ansi.h> +#include <stdio.h> + +#ifdef _HAVE_STDC + +#include <stdarg.h> + +int +_printf_r (struct _reent *ptr, const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + ret = _vfprintf_r (ptr, _stdout_r (ptr), fmt, ap); + va_end (ap); + return ret; +} + +#else + +#include <varargs.h> + +int +_printf_r (ptr, fmt, va_alist) + struct _reent *ptr; + char *fmt; + va_dcl +{ + int ret; + va_list ap; + + va_start (ap); + ret = _vfprintf_r (ptr, _stdout_r (ptr), fmt, ap); + va_end (ap); + return ret; +} + +#endif + + +#ifndef _REENT_ONLY + +#ifdef _HAVE_STDC + +#include <stdarg.h> + +int +printf (const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start (ap, fmt); + _stdout_r (_REENT)->_data = _REENT; + ret = vfprintf (_stdout_r (_REENT), fmt, ap); + va_end (ap); + return ret; +} + +#else + +#include <varargs.h> + +int +printf (fmt, va_alist) + char *fmt; + va_dcl +{ + int ret; + va_list ap; + + va_start (ap); + _stdout_r (_REENT)->_data = _REENT; + ret = vfprintf (_stdout_r (_REENT), fmt, ap); + va_end (ap); + return ret; +} + +#endif /* ! _HAVE_STDC */ + +#endif /* ! _REENT_ONLY */ diff --git a/newlib/libc/stdio/putc.c b/newlib/libc/stdio/putc.c new file mode 100644 index 000000000..27a7a4280 --- /dev/null +++ b/newlib/libc/stdio/putc.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<putc>>---write a character (macro) + +INDEX + putc + +ANSI_SYNOPSIS + #include <stdio.h> + int putc(int <[ch]>, FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int putc(<[ch]>, <[fp]>) + int <[ch]>; + FILE *<[fp]>; + +DESCRIPTION +<<putc>> is a macro, defined in <<stdio.h>>. <<putc>> +writes the argument <[ch]> to the file or stream identified by +<[fp]>, after converting it from an <<int>> to an <<unsigned char>>. + +If the file was opened with append mode (or if the stream cannot +support positioning), then the new character goes at the end of the +file or stream. Otherwise, the new character is written at the +current value of the position indicator, and the position indicator +advances by one. + +For a subroutine version of this macro, see <<fputc>>. + +RETURNS +If successful, <<putc>> returns its argument <[ch]>. If an error +intervenes, the result is <<EOF>>. You can use `<<ferror(<[fp]>)>>' to +query for errors. + +PORTABILITY +ANSI C requires <<putc>>; it suggests, but does not require, that +<<putc>> be implemented as a macro. The standard explicitly permits +macro implementations of <<putc>> to use the <[fp]> argument more than once; +therefore, in a portable program, you should not use an expression +with side effects as this argument. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +/* + * A subroutine version of the macro putc. + */ + +#undef putc + +int +putc (c, fp) + int c; + register FILE *fp; +{ + /* CHECK_INIT is (eventually) called by __swbuf. */ + + return __sputc (c, fp); +} diff --git a/newlib/libc/stdio/putchar.c b/newlib/libc/stdio/putchar.c new file mode 100644 index 000000000..7f7c442e4 --- /dev/null +++ b/newlib/libc/stdio/putchar.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<putchar>>---write a character (macro) + +INDEX + putchar +INDEX + _putchar_r + +ANSI_SYNOPSIS + #include <stdio.h> + int putchar(int <[ch]>); + + int _putchar_r(void *<[reent]>, int <[ch]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int putchar(<[ch]>) + int <[ch]>; + + int _putchar_r(<[reent]>, <[ch]>) + char *<[reent]>; + int <[ch]>; + +DESCRIPTION +<<putchar>> is a macro, defined in <<stdio.h>>. <<putchar>> +writes its argument to the standard output stream, +after converting it from an <<int>> to an <<unsigned char>>. + +The alternate function <<_putchar_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS +If successful, <<putchar>> returns its argument <[ch]>. If an error +intervenes, the result is <<EOF>>. You can use `<<ferror(stdin)>>' to +query for errors. + +PORTABILITY +ANSI C requires <<putchar>>; it suggests, but does not require, that +<<putchar>> be implemented as a macro. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +/* + * A subroutine version of the macro putchar + */ + +#include <stdio.h> + +#undef putchar + +int +_putchar_r (ptr, c) + struct _reent *ptr; + int c; +{ + return __sputc (c, _stdout_r (ptr)); +} + +#ifndef _REENT_ONLY + +int +putchar (c) + int c; +{ + /* CHECK_INIT is (eventually) called by __swbuf. */ + + _putchar_r (_REENT, c); +} + +#endif diff --git a/newlib/libc/stdio/puts.c b/newlib/libc/stdio/puts.c new file mode 100644 index 000000000..44f17cc91 --- /dev/null +++ b/newlib/libc/stdio/puts.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<puts>>---write a character string + +INDEX + puts +INDEX + _puts_r + +ANSI_SYNOPSIS + #include <stdio.h> + int puts(const char *<[s]>); + + int _puts_r(void *<[reent]>, const char *<[s]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int puts(<[s]>) + char *<[s]>; + + int _puts_r(<[reent]>, <[s]>) + char *<[reent]>; + char *<[s]>; + +DESCRIPTION +<<puts>> writes the string at <[s]> (followed by a newline, instead of +the trailing null) to the standard output stream. + +The alternate function <<_puts_r>> is a reentrant version. The extra +argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS +If successful, the result is a nonnegative integer; otherwise, the +result is <<EOF>>. + +PORTABILITY +ANSI C requires <<puts>>, but does not specify that the result on +success must be <<0>>; any non-negative value is permitted. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <string.h> +#include "fvwrite.h" + +/* + * Write the given string to stdout, appending a newline. + */ + +int +_DEFUN (_puts_r, (ptr, s), + struct _reent *ptr _AND + _CONST char * s) +{ + size_t c = strlen (s); + struct __suio uio; + struct __siov iov[2]; + + iov[0].iov_base = s; + iov[0].iov_len = c; + iov[1].iov_base = "\n"; + iov[1].iov_len = 1; + uio.uio_resid = c + 1; + uio.uio_iov = &iov[0]; + uio.uio_iovcnt = 2; + + return (__sfvwrite (_stdout_r (ptr), &uio) ? EOF : '\n'); +} + +#ifndef _REENT_ONLY + +int +_DEFUN (puts, (s), + char _CONST * s) +{ + return _puts_r (_REENT, s); +} + +#endif diff --git a/newlib/libc/stdio/refill.c b/newlib/libc/stdio/refill.c new file mode 100644 index 000000000..bc3b83047 --- /dev/null +++ b/newlib/libc/stdio/refill.c @@ -0,0 +1,113 @@ +/* No user fns here. Pesch 15apr92. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <stdio.h> +#include "local.h" +#include <stdlib.h> + +static int +lflush (fp) + FILE *fp; +{ + if ((fp->_flags & (__SLBF | __SWR)) == __SLBF | __SWR) + return fflush (fp); + return 0; +} + +/* + * Refill a stdio buffer. + * Return EOF on eof or error, 0 otherwise. + */ + +int +_DEFUN (__srefill, (fp), + register FILE * fp) +{ + /* make sure stdio is set up */ + + CHECK_INIT (fp); + + fp->_r = 0; /* largely a convenience for callers */ + + /* SysV does not make this test; take it out for compatibility */ + if (fp->_flags & __SEOF) + return EOF; + + /* if not already reading, have to be reading and writing */ + if ((fp->_flags & __SRD) == 0) + { + if ((fp->_flags & __SRW) == 0) + return EOF; + /* switch to reading */ + if (fp->_flags & __SWR) + { + if (fflush (fp)) + return EOF; + fp->_flags &= ~__SWR; + fp->_w = 0; + fp->_lbfsize = 0; + } + fp->_flags |= __SRD; + } + else + { + /* + * We were reading. If there is an ungetc buffer, + * we must have been reading from that. Drop it, + * restoring the previous buffer (if any). If there + * is anything in that buffer, return. + */ + if (HASUB (fp)) + { + FREEUB (fp); + if ((fp->_r = fp->_ur) != 0) + { + fp->_p = fp->_up; + return 0; + } + } + } + + if (fp->_bf._base == NULL) + __smakebuf (fp); + + /* + * Before reading from a line buffered or unbuffered file, + * flush all line buffered output files, per the ANSI C + * standard. + */ + + if (fp->_flags & (__SLBF | __SNBF)) + (void) _fwalk (fp->_data, lflush); + fp->_p = fp->_bf._base; + fp->_r = (*fp->_read) (fp->_cookie, (char *) fp->_p, fp->_bf._size); + fp->_flags &= ~__SMOD; /* buffer contents are again pristine */ + if (fp->_r <= 0) + { + if (fp->_r == 0) + fp->_flags |= __SEOF; + else + { + fp->_r = 0; + fp->_flags |= __SERR; + } + return EOF; + } + return 0; +} diff --git a/newlib/libc/stdio/remove.c b/newlib/libc/stdio/remove.c new file mode 100644 index 000000000..074dd9ac8 --- /dev/null +++ b/newlib/libc/stdio/remove.c @@ -0,0 +1,69 @@ +/* +FUNCTION +<<remove>>---delete a file's name + +INDEX + remove + +ANSI_SYNOPSIS + #include <stdio.h> + int remove(char *<[filename]>); + + int _remove_r(void *<[reent]>, char *<[filename]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int remove(<[filename]>) + char *<[filename]>; + + int _remove_r(<[reent]>, <[filename]>) + char *<[reent]>; + char *<[filename]>; + +DESCRIPTION +Use <<remove>> to dissolve the association between a particular +filename (the string at <[filename]>) and the file it represents. +After calling <<remove>> with a particular filename, you will no +longer be able to open the file by that name. + +In this implementation, you may use <<remove>> on an open file without +error; existing file descriptors for the file will continue to access +the file's data until the program using them closes the file. + +The alternate function <<_remove_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS +<<remove>> returns <<0>> if it succeeds, <<-1>> if it fails. + +PORTABILITY +ANSI C requires <<remove>>, but only specifies that the result on +failure be nonzero. The behavior of <<remove>> when you call it on an +open file may vary among implementations. + +Supporting OS subroutine required: <<unlink>>. +*/ + +#include <stdio.h> + +int +_remove_r (ptr, filename) + struct _reent *ptr; + _CONST char *filename; +{ + if (_unlink_r (ptr, filename) == -1) + return -1; + + return 0; +} + +#ifndef _REENT_ONLY + +int +remove (filename) + _CONST char *filename; +{ + return _remove_r (_REENT, filename); +} + +#endif diff --git a/newlib/libc/stdio/rename.c b/newlib/libc/stdio/rename.c new file mode 100644 index 000000000..19a6afdd3 --- /dev/null +++ b/newlib/libc/stdio/rename.c @@ -0,0 +1,86 @@ +/* +FUNCTION +<<rename>>---rename a file + +INDEX + rename +INDEX + _rename_r + +ANSI_SYNOPSIS + #include <stdio.h> + int rename(const char *<[old]>, const char *<[new]>); + + int _rename_r(void *<[reent]>, + const char *<[old]>, const char *<[new]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int rename(<[old]>, <[new]>) + char *<[old]>; + char *<[new]>; + + int _rename_r(<[reent]>, <[old]>, <[new]>) + char *<[reent]>; + char *<[old]>; + char *<[new]>; + +DESCRIPTION +Use <<rename>> to establish a new name (the string at <[new]>) for a +file now known by the string at <[old]>. After a successful +<<rename>>, the file is no longer accessible by the string at <[old]>. + +If <<rename>> fails, the file named <<*<[old]>>> is unaffected. The +conditions for failure depend on the host operating system. + +The alternate function <<_rename_r>> is a reentrant version. The +extra argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS +The result is either <<0>> (when successful) or <<-1>> (when the file +could not be renamed). + +PORTABILITY +ANSI C requires <<rename>>, but only specifies that the result on +failure be nonzero. The effects of using the name of an existing file +as <<*<[new]>>> may vary from one implementation to another. + +Supporting OS subroutines required: <<link>>, <<unlink>>, or <<rename>>. +*/ + +#include <stdio.h> +#include <sys/unistd.h> +#include <reent.h> + +int +_rename_r (ptr, old, new) + struct _reent *ptr; + _CONST char *old; + _CONST char *new; +{ +#ifdef HAVE_RENAME + return _rename (old,new); +#else + if (_link_r (ptr, old, new) == -1) + return -1; + + if (_unlink_r (ptr, old) == -1) + { + /* ??? Should we unlink new? (rhetorical question) */ + return -1; + } +#endif + return 0; +} + +#ifndef _REENT_ONLY + +int +rename (old, new) + _CONST char *old; + _CONST char *new; +{ + return _rename_r (_REENT, old, new); +} + +#endif diff --git a/newlib/libc/stdio/rewind.c b/newlib/libc/stdio/rewind.c new file mode 100644 index 000000000..905275741 --- /dev/null +++ b/newlib/libc/stdio/rewind.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<rewind>>---reinitialize a file or stream + +INDEX + rewind + +ANSI_SYNOPSIS + #include <stdio.h> + void rewind(FILE *<[fp]>); + +TRAD_SYNOPSIS + #include <stdio.h> + void rewind(<[fp]>) + FILE *<[fp]>; + +DESCRIPTION +<<rewind>> returns the file position indicator (if any) for the file +or stream identified by <[fp]> to the beginning of the file. It also +clears any error indicator and flushes any pending output. + +RETURNS +<<rewind>> does not return a result. + +PORTABILITY +ANSI C requires <<rewind>>. + +No supporting OS subroutines are required. +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> + +void +_DEFUN (rewind, (fp), + register FILE * fp) +{ + (void) fseek(fp, 0L, SEEK_SET); + clearerr(fp); +} diff --git a/newlib/libc/stdio/rget.c b/newlib/libc/stdio/rget.c new file mode 100644 index 000000000..ea29c2bce --- /dev/null +++ b/newlib/libc/stdio/rget.c @@ -0,0 +1,43 @@ +/* No user fns here. Pesch 15apr92. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include "local.h" + +/* + * Handle getc() when the buffer ran out: + * Refill, then return the first character + * in the newly-filled buffer. + */ + +int +__srget (fp) + register FILE *fp; +{ + if (__srefill (fp) == 0) + { + fp->_r--; + return *fp->_p++; + } + return EOF; +} diff --git a/newlib/libc/stdio/scanf.c b/newlib/libc/stdio/scanf.c new file mode 100644 index 000000000..0a4818934 --- /dev/null +++ b/newlib/libc/stdio/scanf.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <_ansi.h> +#include <stdio.h> +#include "local.h" + +#ifdef _HAVE_STDC +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +#ifndef _REENT_ONLY + +int +#ifdef _HAVE_STDC +scanf (const char *fmt, ...) +#else +scanf (fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + +#ifdef _HAVE_STDC + va_start (ap, fmt); +#else + va_start (ap); +#endif + ret = __svfscanf (_stdin_r (_REENT), fmt, ap); + va_end (ap); + return ret; +} + +#endif + +int +#ifdef _HAVE_STDC +_scanf_r (struct _reent *ptr, const char *fmt, ...) +#else +_scanf_r (ptr, fmt, va_alist) + struct _reent *ptr; + char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + +#ifdef _HAVE_STDC + va_start (ap, fmt); +#else + va_start (ap); +#endif + ret = __svfscanf (_stdin_r (ptr), fmt, ap); + va_end (ap); + return (ret); +} diff --git a/newlib/libc/stdio/setbuf.c b/newlib/libc/stdio/setbuf.c new file mode 100644 index 000000000..15d09e0f3 --- /dev/null +++ b/newlib/libc/stdio/setbuf.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<setbuf>>---specify full buffering for a file or stream + +INDEX + setbuf + +ANSI_SYNOPSIS + #include <stdio.h> + void setbuf(FILE *<[fp]>, char *<[buf]>); + +TRAD_SYNOPSIS + #include <stdio.h> + void setbuf(<[fp]>, <[buf]>) + FILE *<[fp]>; + char *<[buf]>; + +DESCRIPTION +<<setbuf>> specifies that output to the file or stream identified by <[fp]> +should be fully buffered. All output for this file will go to a +buffer (of size <<BUFSIZ>>, specified in `<<stdio.h>>'). Output will +be passed on to the host system only when the buffer is full, or when +an input operation intervenes. + +You may, if you wish, supply your own buffer by passing a pointer to +it as the argument <[buf]>. It must have size <<BUFSIZ>>. You can +also use <<NULL>> as the value of <[buf]>, to signal that the +<<setbuf>> function is to allocate the buffer. + +WARNINGS +You may only use <<setbuf>> before performing any file operation other +than opening the file. + +If you supply a non-null <[buf]>, you must ensure that the associated +storage continues to be available until you close the stream +identified by <[fp]>. + +RETURNS +<<setbuf>> does not return a result. + +PORTABILITY +Both ANSI C and the System V Interface Definition (Issue 2) require +<<setbuf>>. However, they differ on the meaning of a <<NULL>> buffer +pointer: the SVID issue 2 specification says that a <<NULL>> buffer +pointer requests unbuffered output. For maximum portability, avoid +<<NULL>> buffer pointers. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <_ansi.h> +#include <stdio.h> +#include "local.h" + +void +_DEFUN (setbuf, (fp, buf), + FILE * fp _AND + char *buf) +{ + (void) setvbuf (fp, buf, buf ? _IOFBF : _IONBF, BUFSIZ); +} diff --git a/newlib/libc/stdio/setvbuf.c b/newlib/libc/stdio/setvbuf.c new file mode 100644 index 000000000..357ea5142 --- /dev/null +++ b/newlib/libc/stdio/setvbuf.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* +FUNCTION +<<setvbuf>>---specify file or stream buffering + +INDEX + setvbuf + +ANSI_SYNOPSIS + #include <stdio.h> + int setvbuf(FILE *<[fp]>, char *<[buf]>, + int <[mode]>, size_t <[size]>); + +TRAD_SYNOPSIS + #include <stdio.h> + int setvbuf(<[fp]>, <[buf]>, <[mode]>, <[size]>) + FILE *<[fp]>; + char *<[buf]>; + int <[mode]>; + size_t <[size]>; + +DESCRIPTION +Use <<setvbuf>> to specify what kind of buffering you want for the +file or stream identified by <[fp]>, by using one of the following +values (from <<stdio.h>>) as the <[mode]> argument: + +o+ +o _IONBF +Do not use a buffer: send output directly to the host system for the +file or stream identified by <[fp]>. + +o _IOFBF +Use full output buffering: output will be passed on to the host system +only when the buffer is full, or when an input operation intervenes. + +o _IOLBF +Use line buffering: pass on output to the host system at every +newline, as well as when the buffer is full, or when an input +operation intervenes. +o- + +Use the <[size]> argument to specify how large a buffer you wish. You +can supply the buffer itself, if you wish, by passing a pointer to a +suitable area of memory as <[buf]>. Otherwise, you may pass <<NULL>> +as the <[buf]> argument, and <<setvbuf>> will allocate the buffer. + +WARNINGS +You may only use <<setvbuf>> before performing any file operation other +than opening the file. + +If you supply a non-null <[buf]>, you must ensure that the associated +storage continues to be available until you close the stream +identified by <[fp]>. + +RETURNS +A <<0>> result indicates success, <<EOF>> failure (invalid <[mode]> or +<[size]> can cause failure). + +PORTABILITY +Both ANSI C and the System V Interface Definition (Issue 2) require +<<setvbuf>>. However, they differ on the meaning of a <<NULL>> buffer +pointer: the SVID issue 2 specification says that a <<NULL>> buffer +pointer requests unbuffered output. For maximum portability, avoid +<<NULL>> buffer pointers. + +Both specifications describe the result on failure only as a +nonzero value. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <_ansi.h> +#include <stdio.h> +#include <stdlib.h> +#include "local.h" + +/* + * Set one of the three kinds of buffering, optionally including a buffer. + */ + +int +_DEFUN (setvbuf, (fp, buf, mode, size), + register FILE * fp _AND + char *buf _AND + register int mode _AND + register size_t size) +{ + int ret = 0; + CHECK_INIT (fp); + + /* + * Verify arguments. The `int' limit on `size' is due to this + * particular implementation. + */ + + if ((mode != _IOFBF && mode != _IOLBF && mode != _IONBF) || (int)(_POINTER_INT) size < 0) + return (EOF); + + /* + * Write current buffer, if any; drop read count, if any. + * Make sure putc() will not think fp is line buffered. + * Free old buffer if it was from malloc(). Clear line and + * non buffer flags, and clear malloc flag. + */ + + (void) fflush (fp); + fp->_r = 0; + fp->_lbfsize = 0; + if (fp->_flags & __SMBF) + _free_r (fp->_data, (void *) fp->_bf._base); + fp->_flags &= ~(__SLBF | __SNBF | __SMBF); + + if (mode == _IONBF) + goto nbf; + + /* + * Allocate buffer if needed. */ + if (buf == NULL) + { + /* we need this here because malloc() may return a pointer + even if size == 0 */ + if (!size) size = BUFSIZ; + if ((buf = malloc (size)) == NULL) + { + ret = EOF; + /* Try another size... */ + buf = malloc (BUFSIZ); + size = BUFSIZ; + } + if (buf == NULL) + { + /* Can't allocate it, let's try another approach */ +nbf: + fp->_flags |= __SNBF; + fp->_w = 0; + fp->_bf._base = fp->_p = fp->_nbuf; + fp->_bf._size = 1; + return (ret); + } + fp->_flags |= __SMBF; + } + /* + * Now put back whichever flag is needed, and fix _lbfsize + * if line buffered. Ensure output flush on exit if the + * stream will be buffered at all. + * If buf is NULL then make _lbfsize 0 to force the buffer + * to be flushed and hence malloced on first use + */ + + switch (mode) + { + case _IOLBF: + fp->_flags |= __SLBF; + fp->_lbfsize = buf ? -size : 0; + /* FALLTHROUGH */ + + case _IOFBF: + /* no flag */ + fp->_data->__cleanup = _cleanup_r; + fp->_bf._base = fp->_p = (unsigned char *) buf; + fp->_bf._size = size; + break; + } + + /* + * Patch up write count if necessary. + */ + + if (fp->_flags & __SWR) + fp->_w = fp->_flags & (__SLBF | __SNBF) ? 0 : size; + + return 0; +} diff --git a/newlib/libc/stdio/siprintf.c b/newlib/libc/stdio/siprintf.c new file mode 100644 index 000000000..40bd01696 --- /dev/null +++ b/newlib/libc/stdio/siprintf.c @@ -0,0 +1,70 @@ +/* +FUNCTION + <<siprintf>>---write formatted output (integer only) +INDEX + siprintf + +ANSI_SYNOPSIS + #include <stdio.h> + + int siprintf(char *<[str]>, const char *<[format]> [, <[arg]>, ...]); + + +DESCRIPTION +<<siprintf>> is a restricted version of <<sprintf>>: it has the same +arguments and behavior, save that it cannot perform any floating-point +formatting: the <<f>>, <<g>>, <<G>>, <<e>>, and <<F>> type specifiers +are not recognized. + +RETURNS + <<siprintf>> returns the number of bytes in the output string, + save that the concluding <<NULL>> is not counted. + <<siprintf>> returns when the end of the format string is + encountered. + +PORTABILITY +<<siprintf>> is not required by ANSI C. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <stdio.h> +#ifdef _HAVE_STDC +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include <limits.h> +#include <_ansi.h> +#include <reent.h> +#include "local.h" + +int +#ifdef _HAVE_STDC +_DEFUN (siprintf, (str, fmt), char *str _AND _CONST char *fmt _DOTS) +#else +siprintf (str, fmt, va_alist) + char *str; + _CONST char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._w = INT_MAX; + f._data = _REENT; +#ifdef _HAVE_STDC + va_start (ap, fmt); +#else + va_start (ap); +#endif + ret = vfiprintf (&f, fmt, ap); + va_end (ap); + *f._p = 0; + return (ret); +} diff --git a/newlib/libc/stdio/snprintf.c b/newlib/libc/stdio/snprintf.c new file mode 100644 index 000000000..333e808e4 --- /dev/null +++ b/newlib/libc/stdio/snprintf.c @@ -0,0 +1,95 @@ +/* doc in sprintf.c */ + +/* This code created by modifying sprintf.c so copyright inherited. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <stdio.h> +#ifdef _HAVE_STDC +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include <limits.h> +#include <_ansi.h> +#include "local.h" + +int +#ifdef _HAVE_STDC +_DEFUN (_snprintf_r, (ptr, str, size, fmt), struct _reent *ptr _AND char *str _AND size_t size _AND _CONST char *fmt _DOTS) +#else +_snprintf_r (ptr, str, size, fmt, va_alist) + struct _reent *ptr; + char *str; + size_t size; + _CONST char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._w = size; + f._data = ptr; +#ifdef _HAVE_STDC + va_start (ap, fmt); +#else + va_start (ap); +#endif + ret = vfprintf (&f, fmt, ap); + va_end (ap); + *f._p = 0; + return (ret); +} + +#ifndef _REENT_ONLY + +int +#ifdef _HAVE_STDC +_DEFUN (snprintf, (str, size, fmt), char *str _AND size_t size _AND _CONST char *fmt _DOTS) +#else +snprintf (str, size, fmt, va_alist) + char *str; + size_t size; + _CONST char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._w = size; + f._data = _REENT; +#ifdef _HAVE_STDC + va_start (ap, fmt); +#else + va_start (ap); +#endif + ret = vfprintf (&f, fmt, ap); + va_end (ap); + *f._p = 0; + return (ret); +} + +#endif diff --git a/newlib/libc/stdio/sprintf.c b/newlib/libc/stdio/sprintf.c new file mode 100644 index 000000000..b5376327e --- /dev/null +++ b/newlib/libc/stdio/sprintf.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + +FUNCTION + <<printf>>, <<fprintf>>, <<sprintf>>, <<snprintf>>---format output +INDEX + fprintf +INDEX + printf +INDEX + sprintf +INDEX + snprintf + +ANSI_SYNOPSIS + #include <stdio.h> + + int printf(const char *<[format]> [, <[arg]>, ...]); + int fprintf(FILE *<[fd]>, const char *<[format]> [, <[arg]>, ...]); + int sprintf(char *<[str]>, const char *<[format]> [, <[arg]>, ...]); + int snprintf(char *<[str]>, size_t <[size]>, const char *<[format]> [, <[arg]>, ...]); + +TRAD_SYNOPSIS + #include <stdio.h> + + int printf(<[format]> [, <[arg]>, ...]) + char *<[format]>; + + int fprintf(<[fd]>, <[format]> [, <[arg]>, ...]); + FILE *<[fd]>; + char *<[format]>; + + int sprintf(<[str]>, <[format]> [, <[arg]>, ...]); + char *<[str]>; + char *<[format]>; + + int snprintf(<[str]>, size_t <[size]>, <[format]> [, <[arg]>, ...]); + char *<[str]>; + size_t <[size]>; + char *<[format]>; + +DESCRIPTION + <<printf>> accepts a series of arguments, applies to each a + format specifier from <<*<[format]>>>, and writes the + formatted data to <<stdout>>, terminated with a null character. + The behavior of <<printf>> is undefined if there are not enough + arguments for the format. + <<printf>> returns when it reaches the end of the format string. + If there are more arguments than the format requires, excess + arguments are ignored. + + <<fprintf>>, <<sprintf>> and <<snprintf>> are identical to <<printf>>, + other than the destination of the formatted output: <<fprintf>> sends + the output to a specified file <[fd]>, while <<sprintf>> stores the + output in the specified char array <[str]> and <<snprintf>> limits + number of characters written to <[str]> to at most <[size]> (including + terminating <<0>>). For <<sprintf>> and <<snprintf>>, the behavior is + also undefined if the output <<*<[str]>>> overlaps with one of the + arguments. <[format]> is a pointer to a charater string containing + two types of objects: ordinary characters (other than <<%>>), which + are copied unchanged to the output, and conversion + specifications, each of which is introduced by <<%>>. + (To include <<%>> in the output, use <<%%>> in the format string.) + A conversion specification has the following form: + +. %[<[flags]>][<[width]>][.<[prec]>][<[size]>][<[type]>] + + The fields of the conversion specification have the following meanings: + + O+ + o <[flags]> + + an optional sequence of characters which control + output justification, numeric signs, decimal points, + trailing zeroes, and octal and hex prefixes. + The flag characters are minus (<<->>), plus (<<+>>), + space ( ), zero (<<0>>), and sharp (<<#>>). They can + appear in any combination. + + o+ + o - + The result of the conversion is left justified, and the right is + padded with blanks. If you do not use this flag, the result is right + justified, and padded on the left. + + o + + The result of a signed conversion (as determined by <[type]>) + will always begin with a plus or minus sign. (If you do not use + this flag, positive values do not begin with a plus sign.) + + o " " (space) + If the first character of a signed conversion specification + is not a sign, or if a signed conversion results in no + characters, the result will begin with a space. If the + space ( ) flag and the plus (<<+>>) flag both appear, + the space flag is ignored. + + o 0 + If the <[type]> character is <<d>>, <<i>>, <<o>>, <<u>>, + <<x>>, <<X>>, <<e>>, <<E>>, <<f>>, <<g>>, or <<G>>: leading zeroes, + are used to pad the field width (following any indication of sign or + base); no spaces are used for padding. If the zero (<<0>>) and + minus (<<->>) flags both appear, the zero (<<0>>) flag will + be ignored. For <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, and <<X>> + conversions, if a precision <[prec]> is specified, the zero (<<0>>) + flag is ignored. + + Note that <<0>> is interpreted as a flag, not as the beginning + of a field width. + + o # + The result is to be converted to an alternative form, according + to the next character: + + o+ + o 0 + increases precision to force the first digit + of the result to be a zero. + + o x + a non-zero result will have a <<0x>> prefix. + + o X + a non-zero result will have a <<0X>> prefix. + + o e, E or f + The result will always contain a decimal point + even if no digits follow the point. + (Normally, a decimal point appears only if a + digit follows it.) Trailing zeroes are removed. + + o g or G + same as <<e>> or <<E>>, but trailing zeroes + are not removed. + + o all others + undefined. + + o- + o- + + o <[width]> + + <[width]> is an optional minimum field width. You can either + specify it directly as a decimal integer, or indirectly by + using instead an asterisk (<<*>>), in which case an <<int>> + argument is used as the field width. Negative field widths + are not supported; if you attempt to specify a negative field + width, it is interpreted as a minus (<<->>) flag followed by a + positive field width. + + o <[prec]> + + an optional field; if present, it is introduced with `<<.>>' + (a period). This field gives the maximum number of + characters to print in a conversion; the minimum number of + digits of an integer to print, for conversions with <[type]> + <<d>>, <<i>>, <<o>>, <<u>>, <<x>>, and <<X>>; the maximum number of + significant digits, for the <<g>> and <<G>> conversions; + or the number of digits to print after the decimal + point, for <<e>>, <<E>>, and <<f>> conversions. You can specify + the precision either directly as a decimal integer or + indirectly by using an asterisk (<<*>>), in which case + an <<int>> argument is used as the precision. Supplying a negative + precision is equivalent to omitting the precision. + If only a period is specified the precision is zero. + If a precision appears with any other conversion <[type]> + than those listed here, the behavior is undefined. + + o <[size]> + + <<h>>, <<l>>, and <<L>> are optional size characters which + override the default way that <<printf>> interprets the + data type of the corresponding argument. <<h>> forces + the following <<d>>, <<i>>, <<o>>, <<u>>, <<x>> or <<X>> conversion + <[type]> to apply to a <<short>> or <<unsigned short>>. <<h>> also + forces a following <<n>> <[type]> to apply to + a pointer to a <<short>>. Similarily, an + <<l>> forces the following <<d>>, <<i>>, <<o>>, <<u>>, + <<x>> or <<X>> conversion <[type]> to apply to a <<long>> or + <<unsigned long>>. <<l>> also forces a following <<n>> <[type]> to + apply to a pointer to a <<long>>. If an <<h>> + or an <<l>> appears with another conversion + specifier, the behavior is undefined. <<L>> forces a + following <<e>>, <<E>>, <<f>>, <<g>> or <<G>> conversion <[type]> to + apply to a <<long double>> argument. If <<L>> appears with + any other conversion <[type]>, the behavior is undefined. + + o <[type]> + + <[type]> specifies what kind of conversion <<printf>> performs. + Here is a table of these: + + o+ + o % + prints the percent character (<<%>>) + + o c + prints <[arg]> as single character + + o s + prints characters until precision is reached or a null terminator + is encountered; takes a string pointer + + o d + prints a signed decimal integer; takes an <<int>> (same as <<i>>) + + o i + prints a signed decimal integer; takes an <<int>> (same as <<d>>) + + o o + prints a signed octal integer; takes an <<int>> + + o u + prints an unsigned decimal integer; takes an <<int>> + + o x + prints an unsigned hexadecimal integer (using <<abcdef>> as + digits beyond <<9>>); takes an <<int>> + + o X + prints an unsigned hexadecimal integer (using <<ABCDEF>> as + digits beyond <<9>>); takes an <<int>> + + o f + prints a signed value of the form <<[-]9999.9999>>; takes + a floating point number + + o e + prints a signed value of the form <<[-]9.9999e[+|-]999>>; takes a + floating point number + + o E + prints the same way as <<e>>, but using <<E>> to introduce the + exponent; takes a floating point number + + o g + prints a signed value in either <<f>> or <<e>> form, based on given + value and precision---trailing zeros and the decimal point are + printed only if necessary; takes a floating point number + + o G + prints the same way as <<g>>, but using <<E>> for the exponent if an + exponent is needed; takes a floating point number + + o n + stores (in the same object) a count of the characters written; + takes a pointer to <<int>> + + o p + prints a pointer in an implementation-defined format. + This implementation treats the pointer as an + <<unsigned long>> (same as <<Lu>>). + o- +O- + + +RETURNS +<<sprintf>> returns the number of bytes in the output string, +save that the concluding <<NULL>> is not counted. +<<printf>> and <<fprintf>> return the number of characters transmitted. +If an error occurs, <<printf>> and <<fprintf>> return <<EOF>>. No +error returns occur for <<sprintf>>. + +PORTABILITY + The ANSI C standard specifies that implementations must + support at least formatted output of up to 509 characters. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <stdio.h> +#ifdef _HAVE_STDC +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include <limits.h> +#include <_ansi.h> +#include "local.h" + +int +#ifdef _HAVE_STDC +_DEFUN (_sprintf_r, (ptr, str, fmt), struct _reent *ptr _AND char *str _AND _CONST char *fmt _DOTS) +#else +_sprintf_r (ptr, str, fmt, va_alist) + struct _reent *ptr; + char *str; + _CONST char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._w = INT_MAX; + f._data = ptr; +#ifdef _HAVE_STDC + va_start (ap, fmt); +#else + va_start (ap); +#endif + ret = vfprintf (&f, fmt, ap); + va_end (ap); + *f._p = 0; + return (ret); +} + +#ifndef _REENT_ONLY + +int +#ifdef _HAVE_STDC +_DEFUN (sprintf, (str, fmt), char *str _AND _CONST char *fmt _DOTS) +#else +sprintf (str, fmt, va_alist) + char *str; + _CONST char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._w = INT_MAX; + f._data = _REENT; +#ifdef _HAVE_STDC + va_start (ap, fmt); +#else + va_start (ap); +#endif + ret = vfprintf (&f, fmt, ap); + va_end (ap); + *f._p = 0; + return (ret); +} + +#endif diff --git a/newlib/libc/stdio/sscanf.c b/newlib/libc/stdio/sscanf.c new file mode 100644 index 000000000..eb344238d --- /dev/null +++ b/newlib/libc/stdio/sscanf.c @@ -0,0 +1,386 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + +FUNCTION + <<scanf>>, <<fscanf>>, <<sscanf>>---scan and format input + +INDEX + scanf +INDEX + fscanf +INDEX + sscanf + +ANSI_SYNOPSIS + #include <stdio.h> + + int scanf(const char *<[format]> [, <[arg]>, ...]); + int fscanf(FILE *<[fd]>, const char *<[format]> [, <[arg]>, ...]); + int sscanf(const char *<[str]>, const char *<[format]> + [, <[arg]>, ...]); + + +TRAD_SYNOPSIS + #include <stdio.h> + + int scanf(<[format]> [, <[arg]>, ...]) + char *<[format]>; + + int fscanf(<[fd]>, <[format]> [, <[arg]>, ...]); + FILE *<[fd]>; + char *<[format]>; + + int sscanf(<[str]>, <[format]> [, <[arg]>, ...]); + char *<[str]>; + char *<[format]>; + + +DESCRIPTION + <<scanf>> scans a series of input fields from standard input, + one character at a time. Each field is interpreted according to + a format specifier passed to <<scanf>> in the format string at + <<*<[format]>>>. <<scanf>> stores the interpreted input from + each field at the address passed to it as the corresponding argument + following <[format]>. You must supply the same number of + format specifiers and address arguments as there are input fields. + + There must be sufficient address arguments for the given format + specifiers; if not the results are unpredictable and likely + disasterous. Excess address arguments are merely ignored. + + <<scanf>> often produces unexpected results if the input diverges from + an expected pattern. Since the combination of <<gets>> or <<fgets>> + followed by <<sscanf>> is safe and easy, that is the preferred way + to be certain that a program is synchronized with input at the end + of a line. + + <<fscanf>> and <<sscanf>> are identical to <<scanf>>, other than the + source of input: <<fscanf>> reads from a file, and <<sscanf>> + from a string. + + The string at <<*<[format]>>> is a character sequence composed + of zero or more directives. Directives are composed of + one or more whitespace characters, non-whitespace characters, + and format specifications. + + Whitespace characters are blank (<< >>), tab (<<\t>>), or + newline (<<\n>>). + When <<scanf>> encounters a whitespace character in the format string + it will read (but not store) all consecutive whitespace characters + up to the next non-whitespace character in the input. + + Non-whitespace characters are all other ASCII characters except the + percent sign (<<%>>). When <<scanf>> encounters a non-whitespace + character in the format string it will read, but not store + a matching non-whitespace character. + + Format specifications tell <<scanf>> to read and convert characters + from the input field into specific types of values, and store then + in the locations specified by the address arguments. + + Trailing whitespace is left unread unless explicitly + matched in the format string. + + The format specifiers must begin with a percent sign (<<%>>) + and have the following form: + +. %[*][<[width]>][<[size]>]<[type]> + + Each format specification begins with the percent character (<<%>>). + The other fields are: + o+ + o * + an optional marker; if present, it suppresses interpretation and + assignment of this input field. + + o <[width]> + an optional maximum field width: a decimal integer, + which controls the maximum number of characters that + will be read before converting the current input field. If the + input field has fewer than <[width]> characters, <<scanf>> + reads all the characters in the field, and then + proceeds with the next field and its format specification. + + If a whitespace or a non-convertable character occurs + before <[width]> character are read, the characters up + to that character are read, converted, and stored. + Then <<scanf>> proceeds to the next format specification. + + o size + <<h>>, <<l>>, and <<L>> are optional size characters which + override the default way that <<scanf>> interprets the + data type of the corresponding argument. + + +.Modifier Type(s) +. h d, i, o, u, x convert input to short, +. store in short object +. +. h D, I, O, U, X no effect +. e, f, c, s, n, p +. +. l d, i, o, u, x convert input to long, +. store in long object +. +. l e, f, g convert input to double +. store in a double object +. +. l D, I, O, U, X no effect +. c, s, n, p +. +. L d, i, o, u, x convert to long double, +. store in long double +. +. L all others no effect + + + o <[type]> + + A character to specify what kind of conversion + <<scanf>> performs. Here is a table of the conversion + characters: + + o+ + o % + No conversion is done; the percent character (<<%>>) is stored. + + o c + Scans one character. Corresponding <[arg]>: <<(char *arg)>>. + + o s + Reads a character string into the array supplied. + Corresponding <[arg]>: <<(char arg[])>>. + + o [<[pattern]>] + Reads a non-empty character string into memory + starting at <[arg]>. This area must be large + enough to accept the sequence and a + terminating null character which will be added + automatically. (<[pattern]> is discussed in the paragraph following + this table). Corresponding <[arg]>: <<(char *arg)>>. + + o d + Reads a decimal integer into the corresponding <[arg]>: <<(int *arg)>>. + + o D + Reads a decimal integer into the corresponding + <[arg]>: <<(long *arg)>>. + + o o + Reads an octal integer into the corresponding <[arg]>: <<(int *arg)>>. + + o O + Reads an octal integer into the corresponding <[arg]>: <<(long *arg)>>. + + o u + Reads an unsigned decimal integer into the corresponding + <[arg]>: <<(unsigned int *arg)>>. + + + o U + Reads an unsigned decimal integer into the corresponding <[arg]>: + <<(unsigned long *arg)>>. + + o x,X + Read a hexadecimal integer into the corresponding <[arg]>: + <<(int *arg)>>. + + o e, f, g + Read a floating point number into the corresponding <[arg]>: + <<(float *arg)>>. + + o E, F, G + Read a floating point number into the corresponding <[arg]>: + <<(double *arg)>>. + + o i + Reads a decimal, octal or hexadecimal integer into the + corresponding <[arg]>: <<(int *arg)>>. + + o I + Reads a decimal, octal or hexadecimal integer into the + corresponding <[arg]>: <<(long *arg)>>. + + o n + Stores the number of characters read in the corresponding + <[arg]>: <<(int *arg)>>. + + o p + Stores a scanned pointer. ANSI C leaves the details + to each implementation; this implementation treats + <<%p>> exactly the same as <<%U>>. Corresponding + <[arg]>: <<(void **arg)>>. + o- + + A <[pattern]> of characters surrounded by square brackets can be used + instead of the <<s>> type character. <[pattern]> is a set of + characters which define a search set of possible characters making up + the <<scanf>> input field. If the first character in the brackets is a + caret (<<^>>), the search set is inverted to include all ASCII characters + except those between the brackets. There is also a range facility + which you can use as a shortcut. <<%[0-9] >> matches all decimal digits. + The hyphen must not be the first or last character in the set. + The character prior to the hyphen must be lexically less than the + character after it. + + Here are some <[pattern]> examples: + o+ + o %[abcd] + matches strings containing only <<a>>, <<b>>, <<c>>, and <<d>>. + + o %[^abcd] + matches strings containing any characters except <<a>>, <<b>>, + <<c>>, or <<d>> + + o %[A-DW-Z] + matches strings containing <<A>>, <<B>>, <<C>>, <<D>>, <<W>>, + <<X>>, <<Y>>, <<Z>> + + o %[z-a] + matches the characters <<z>>, <<->>, and <<a>> + o- + + Floating point numbers (for field types <<e>>, <<f>>, <<g>>, <<E>>, + <<F>>, <<G>>) must correspond to the following general form: + +. [+/-] ddddd[.]ddd [E|e[+|-]ddd] + + where objects inclosed in square brackets are optional, and <<ddd>> + represents decimal, octal, or hexadecimal digits. + o- + +RETURNS + <<scanf>> returns the number of input fields successfully + scanned, converted and stored; the return value does + not include scanned fields which were not stored. + + If <<scanf>> attempts to read at end-of-file, the return + value is <<EOF>>. + + If no fields were stored, the return value is <<0>>. + + <<scanf>> might stop scanning a particular field before + reaching the normal field end character, or may + terminate entirely. + + <<scanf>> stops scanning and storing the current field + and moves to the next input field (if any) + in any of the following situations: + + O+ + o The assignment suppressing character (<<*>>) appears + after the <<%>> in the format specification; the current + input field is scanned but not stored. + + o <[width]> characters have been read (<[width]> is a + width specification, a positive decimal integer). + + o The next character read cannot be converted + under the the current format (for example, + if a <<Z>> is read when the format is decimal). + + o The next character in the input field does not appear + in the search set (or does appear in the inverted search set). + O- + + When <<scanf>> stops scanning the current input field for one of + these reasons, the next character is considered unread and + used as the first character of the following input field, or the + first character in a subsequent read operation on the input. + + <<scanf>> will terminate under the following circumstances: + + O+ + o The next character in the input field conflicts + with a corresponding non-whitespace character in the + format string. + + o The next character in the input field is <<EOF>>. + + o The format string has been exhausted. + O- + + When the format string contains a character sequence that is + not part of a format specification, the same character + sequence must appear in the input; <<scanf>> will + scan but not store the matched characters. If a + conflict occurs, the first conflicting character remains in the input + as if it had never been read. + +PORTABILITY +<<scanf>> is ANSI C. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +#include <_ansi.h> +#include <reent.h> +#include <stdio.h> +#include <string.h> +#ifdef _HAVE_STDC +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include "local.h" + +/* | ARGSUSED */ +/*SUPPRESS 590*/ +static +int +eofread (cookie, buf, len) + _PTR cookie; + char *buf; + int len; +{ + return 0; +} + +#ifdef _HAVE_STDC +int +_DEFUN (sscanf, (str, fmt), _CONST char *str _AND _CONST char *fmt _DOTS) +#else +int +sscanf (str, fmt, va_alist) + _CONST char *str; + _CONST char *fmt; + va_dcl +#endif +{ + int ret; + va_list ap; + FILE f; + + f._flags = __SRD; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._r = strlen (str); + f._read = eofread; + f._ub._base = NULL; + f._lb._base = NULL; + f._data = _REENT; +#ifdef _HAVE_STDC + va_start (ap, fmt); +#else + va_start (ap); +#endif + ret = __svfscanf (&f, fmt, ap); + va_end (ap); + return ret; +} diff --git a/newlib/libc/stdio/stdio.c b/newlib/libc/stdio/stdio.c new file mode 100644 index 000000000..c06f51aa0 --- /dev/null +++ b/newlib/libc/stdio/stdio.c @@ -0,0 +1,92 @@ +/* No user fns here. Pesch 15apr92. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <stdio.h> +#include <sys/types.h> +#include <fcntl.h> +#include <sys/unistd.h> +#include "local.h" + +/* + * Small standard I/O/seek/close functions. + * These maintain the `known seek offset' for seek optimisation. + */ + +int +__sread (cookie, buf, n) + _PTR cookie; + char *buf; + int n; +{ + register FILE *fp = (FILE *) cookie; + register int ret; + + ret = _read_r (fp->_data, fp->_file, buf, n); + + /* If the read succeeded, update the current offset. */ + + if (ret >= 0) + fp->_offset += ret; + else + fp->_flags &= ~__SOFF; /* paranoia */ + return ret; +} + +int +__swrite (cookie, buf, n) + _PTR cookie; + char _CONST *buf; + int n; +{ + register FILE *fp = (FILE *) cookie; + + if (fp->_flags & __SAPP) + (void) _lseek_r (fp->_data, fp->_file, (off_t) 0, SEEK_END); + fp->_flags &= ~__SOFF; /* in case O_APPEND mode is set */ + return _write_r (fp->_data, fp->_file, buf, n); +} + +fpos_t +__sseek (cookie, offset, whence) + _PTR cookie; + fpos_t offset; + int whence; +{ + register FILE *fp = (FILE *) cookie; + register off_t ret; + + ret = _lseek_r (fp->_data, fp->_file, (off_t) offset, whence); + if (ret == -1L) + fp->_flags &= ~__SOFF; + else + { + fp->_flags |= __SOFF; + fp->_offset = ret; + } + return ret; +} + +int +__sclose (cookie) + _PTR cookie; +{ + FILE *fp = (FILE *) cookie; + + return _close_r (fp->_data, fp->_file); +} diff --git a/newlib/libc/stdio/stdio.tex b/newlib/libc/stdio/stdio.tex new file mode 100644 index 000000000..466e1f0db --- /dev/null +++ b/newlib/libc/stdio/stdio.tex @@ -0,0 +1,183 @@ +@node Stdio +@chapter Input and Output (@file{stdio.h}) + +This chapter comprises functions to manage files +or other input/output streams. Among these functions are subroutines +to generate or scan strings according to specifications from a format string. + +The underlying facilities for input and output depend on the host +system, but these functions provide a uniform interface. + +The corresponding declarations are in @file{stdio.h}. + +The reentrant versions of these functions use macros + +@example +_stdin_r(@var{reent}) +_stdout_r(@var{reent}) +_stderr_r(@var{reent}) +@end example + +@noindent +instead of the globals @code{stdin}, @code{stdout}, and +@code{stderr}. The argument <[reent]> is a pointer to a reentrancy +structure. + +@menu +* clearerr:: Clear file or stream error indicator +* fclose:: Close a file +* feof:: Test for end of file +* ferror:: Test whether read/write error has occurred +* fflush:: Flush buffered file output +* fgetc:: Get a character from a file or stream +* fgetpos:: Record position in a stream or file +* fgets:: Get character string from a file or stream +* fiprintf:: Write formatted output to file (integer only) +* fopen:: Open a file +* fdopen:: Turn an open file into a stream +* fputc:: Write a character on a stream or file +* fputs:: Write a character string in a file or stream +* fread:: Read array elements from a file +* freopen:: Open a file using an existing file descriptor +* fseek:: Set file position +* fsetpos:: Restore position of a stream or file +* ftell:: Return position in a stream or file +* fwrite:: Write array elements from memory to a file or stream +* getc:: Get a character from a file or stream (macro) +* getchar:: Get a character from standard input (macro) +* gets:: Get character string from standard input (obsolete) +* iprintf:: Write formatted output (integer only) +* mktemp:: Generate unused file name +* perror:: Print an error message on standard error +* putc:: Write a character on a stream or file (macro) +* putchar:: Write a character on standard output (macro) +* puts:: Write a character string on standard output +* remove:: Delete a file's name +* rename:: Rename a file +* rewind:: Reinitialize a file or stream +* setbuf:: Specify full buffering for a file or stream +* setvbuf:: Specify buffering for a file or stream +* siprintf:: Write formatted output (integer only) +* printf:: Write formatted output +* scanf:: Scan and format input +* tmpfile:: Create a temporary file +* tmpnam:: Generate name for a temporary file +* vprintf:: Format variable argument list +@end menu + +@page +@include stdio/clearerr.def + +@page +@include stdio/fclose.def + +@page +@include stdio/feof.def + +@page +@include stdio/ferror.def + +@page +@include stdio/fflush.def + +@page +@include stdio/fgetc.def + +@page +@include stdio/fgetpos.def + +@page +@include stdio/fgets.def + +@page +@include stdio/fiprintf.def + +@page +@include stdio/fopen.def + +@page +@include stdio/fdopen.def + +@page +@include stdio/fputc.def + +@page +@include stdio/fputs.def + +@page +@include stdio/fread.def + +@page +@include stdio/freopen.def + +@page +@include stdio/fseek.def + +@page +@include stdio/fsetpos.def + +@page +@include stdio/ftell.def + +@page +@include stdio/fwrite.def + +@page +@include stdio/getc.def + +@page +@include stdio/getchar.def + +@page +@include stdio/gets.def + +@page +@include stdio/iprintf.def + +@page +@include stdio/mktemp.def + +@page +@include stdio/perror.def + +@page +@include stdio/putc.def + +@page +@include stdio/putchar.def + +@page +@include stdio/puts.def + +@page +@include stdio/remove.def + +@page +@include stdio/rename.def + +@page +@include stdio/rewind.def + +@page +@include stdio/setbuf.def + +@page +@include stdio/setvbuf.def + +@page +@include stdio/siprintf.def + +@page +@include stdio/sprintf.def + +@page +@include stdio/sscanf.def + +@page +@include stdio/tmpfile.def + +@page +@include stdio/tmpnam.def + +@page +@include stdio/vfprintf.def diff --git a/newlib/libc/stdio/tmpfile.c b/newlib/libc/stdio/tmpfile.c new file mode 100644 index 000000000..4b31396e2 --- /dev/null +++ b/newlib/libc/stdio/tmpfile.c @@ -0,0 +1,77 @@ +/* +FUNCTION +<<tmpfile>>---create a temporary file + +INDEX + tmpfile +INDEX + _tmpfile_r + +ANSI_SYNOPSIS + #include <stdio.h> + FILE *tmpfile(void); + + FILE *_tmpfile_r(void *<[reent]>); + +TRAD_SYNOPSIS + #include <stdio.h> + FILE *tmpfile(); + + FILE *_tmpfile_r(<[reent]>) + char *<[reent]>; + +DESCRIPTION +Create a temporary file (a file which will be deleted automatically), +using a name generated by <<tmpnam>>. The temporary file is opened with +the mode <<"wb+">>, permitting you to read and write anywhere in it +as a binary file (without any data transformations the host system may +perform for text files). + +The alternate function <<_tmpfile_r>> is a reentrant version. The +argument <[reent]> is a pointer to a reentrancy structure. + +RETURNS +<<tmpfile>> normally returns a pointer to the temporary file. If no +temporary file could be created, the result is NULL, and <<errno>> +records the reason for failure. + +PORTABILITY +Both ANSI C and the System V Interface Definition (Issue 2) require +<<tmpfile>>. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<getpid>>, +<<isatty>>, <<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>. + +<<tmpfile>> also requires the global pointer <<environ>>. +*/ + +#include <stdio.h> +#include <errno.h> + +FILE * +_DEFUN (_tmpfile_r, (ptr), + struct _reent *ptr) +{ + FILE *fp; + int e; + char *f; + char buf[L_tmpnam]; + + if ((f = _tmpnam_r (ptr, buf)) == NULL) + return NULL; + fp = fopen (f, "wb+"); + e = ptr->_errno; + _CAST_VOID remove (f); + ptr->_errno = e; + return fp; +} + +#ifndef _REENT_ONLY + +FILE * +_DEFUN_VOID (tmpfile) +{ + return _tmpfile_r (_REENT); +} + +#endif diff --git a/newlib/libc/stdio/tmpnam.c b/newlib/libc/stdio/tmpnam.c new file mode 100644 index 000000000..28b394f10 --- /dev/null +++ b/newlib/libc/stdio/tmpnam.c @@ -0,0 +1,208 @@ +/* + * tmpname.c + * Original Author: G. Haley + */ + +/* +FUNCTION +<<tmpnam>>, <<tempnam>>---name for a temporary file + +INDEX + tmpnam +INDEX + tempnam +INDEX + _tmpnam_r +INDEX + _tempnam_r + +ANSI_SYNOPSIS + #include <stdio.h> + char *tmpnam(char *<[s]>); + char *tempnam(char *<[dir]>, char *<[pfx]>); + char *_tmpnam_r(void *<[reent]>, char *<[s]>); + char *_tempnam_r(void *<[reent]>, char *<[dir]>, char *<[pfx]>); + +TRAD_SYNOPSIS + #include <stdio.h> + char *tmpnam(<[s]>) + char *<[s]>; + + char *tempnam(<[dir]>, <[pfx]>) + char *<[dir]>; + char *<[pfx]>; + + char *_tmpnam_r(<[reent]>, <[s]>) + char *<[reent]>; + char *<[s]>; + + char *_tempnam_r(<[reent]>, <[dir]>, <[pfx]>) + char *<[reent]>; + char *<[dir]>; + char *<[pfx]>; + +DESCRIPTION +Use either of these functions to generate a name for a temporary file. +The generated name is guaranteed to avoid collision with other files +(for up to <<TMP_MAX>> calls of either function). + +<<tmpnam>> generates file names with the value of <<P_tmpdir>> +(defined in `<<stdio.h>>') as the leading directory component of the path. + +You can use the <<tmpnam>> argument <[s]> to specify a suitable area +of memory for the generated filename; otherwise, you can call +<<tmpnam(NULL)>> to use an internal static buffer. + +<<tempnam>> allows you more control over the generated filename: you +can use the argument <[dir]> to specify the path to a directory for +temporary files, and you can use the argument <[pfx]> to specify a +prefix for the base filename. + +If <[dir]> is <<NULL>>, <<tempnam>> will attempt to use the value of +environment variable <<TMPDIR>> instead; if there is no such value, +<<tempnam>> uses the value of <<P_tmpdir>> (defined in `<<stdio.h>>'). + +If you don't need any particular prefix to the basename of temporary +files, you can pass <<NULL>> as the <[pfx]> argument to <<tempnam>>. + +<<_tmpnam_r>> and <<_tempnam_r>> are reentrant versions of <<tmpnam>> +and <<tempnam>> respectively. The extra argument <[reent]> is a +pointer to a reentrancy structure. + +WARNINGS +The generated filenames are suitable for temporary files, but do not +in themselves make files temporary. Files with these names must still +be explicitly removed when you no longer want them. + +If you supply your own data area <[s]> for <<tmpnam>>, you must ensure +that it has room for at least <<L_tmpnam>> elements of type <<char>>. + +RETURNS +Both <<tmpnam>> and <<tempnam>> return a pointer to the newly +generated filename. + +PORTABILITY +ANSI C requires <<tmpnam>>, but does not specify the use of +<<P_tmpdir>>. The System V Interface Definition (Issue 2) requires +both <<tmpnam>> and <<tempnam>>. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<getpid>>, +<<isatty>>, <<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>. + +The global pointer <<environ>> is also required. +*/ + +#include <_ansi.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <reent.h> +#include <errno.h> + +/* Try to open the file specified, if it can't be opened then try + another one. Return nonzero if successful, otherwise zero. */ + +static int +worker (ptr, result, part1, part2, part3, part4) + struct _reent *ptr; + char *result; + _CONST char *part1; + _CONST char *part2; + int part3; + int *part4; +{ + /* Generate the filename and make sure that there isn't one called + it already. */ + + while (1) + { + int t; + _sprintf_r (ptr, result, "%s/%s%x.%x", part1, part2, part3, *part4); + (*part4)++; + t = _open_r (ptr, result, O_RDONLY, 0); + if (t == -1) + { + if (ptr->_errno == ENOSYS) + { + result[0] = '\0'; + return 0; + } + break; + } + _close_r (ptr, t); + } + return 1; +} + +char * +_DEFUN (_tmpnam_r, (p, s), + struct _reent *p _AND + char *s) +{ + char *result; + int pid; + + if (s == NULL) + { + /* ANSI states we must use an internal static buffer if s is NULL */ + result = p->_emergency; + } + else + { + result = s; + } + pid = _getpid_r (p); + + if (worker (p, result, P_tmpdir, "t", pid, &p->_inc)) + { + p->_inc++; + return result; + } + + return NULL; +} + +char * +_DEFUN (_tempnam_r, (p, dir, pfx), + struct _reent *p _AND + _CONST char *dir _AND + _CONST char *pfx) +{ + char *filename; + int length; + _CONST char *prefix = (pfx) ? pfx : ""; + if (dir == NULL && (dir = getenv ("TMPDIR")) == NULL) + dir = P_tmpdir; + + /* two 8 digit numbers + . / */ + length = strlen (dir) + strlen (prefix) + (4 * sizeof (int)) + 2 + 1; + + filename = _malloc_r (p, length); + if (filename) + { + if (! worker (p, filename, dir, prefix, + _getpid_r (p) ^ (int) (_POINTER_INT) p, &p->_inc)) + return NULL; + } + return filename; +} + +#ifndef _REENT_ONLY + +char * +_DEFUN (tempnam, (dir, pfx), + _CONST char *dir _AND + _CONST char *pfx) +{ + return _tempnam_r (_REENT, dir, pfx); +} + +char * +_DEFUN (tmpnam, (s), + char *s) +{ + return _tmpnam_r (_REENT, s); +} + +#endif diff --git a/newlib/libc/stdio/ungetc.c b/newlib/libc/stdio/ungetc.c new file mode 100644 index 000000000..418717e68 --- /dev/null +++ b/newlib/libc/stdio/ungetc.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "local.h" + +/* + * Expand the ungetc buffer `in place'. That is, adjust fp->_p when + * the buffer moves, so that it points the same distance from the end, + * and move the bytes in the buffer around as necessary so that they + * are all at the end (stack-style). + */ + +/*static*/ +int +__submore (fp) + register FILE *fp; +{ + register int i; + register unsigned char *p; + + if (fp->_ub._base == fp->_ubuf) + { + /* + * Get a new buffer (rather than expanding the old one). + */ + if ((p = (unsigned char *) _malloc_r (fp->_data, (size_t) BUFSIZ)) == NULL) + return EOF; + fp->_ub._base = p; + fp->_ub._size = BUFSIZ; + p += BUFSIZ - sizeof (fp->_ubuf); + for (i = sizeof (fp->_ubuf); --i >= 0;) + p[i] = fp->_ubuf[i]; + fp->_p = p; + return 0; + } + i = fp->_ub._size; + p = (unsigned char *) _realloc_r (fp->_data, (_PTR) (fp->_ub._base), i << 1); + if (p == NULL) + return EOF; + (void) memcpy ((void *) (p + i), (void *) p, (size_t) i); + fp->_p = p + i; + fp->_ub._base = p; + fp->_ub._size = i << 1; + return 0; +} + +int +ungetc (c, fp) + int c; + register FILE *fp; +{ + if (c == EOF) + return (EOF); + + /* Ensure stdio has been initialized. + ??? Might be able to remove this as some other stdio routine should + have already been called to get the char we are un-getting. */ + + CHECK_INIT (fp); + + /* After ungetc, we won't be at eof anymore */ + fp->_flags &= ~__SEOF; + + if ((fp->_flags & __SRD) == 0) + { + /* + * Not already reading: no good unless reading-and-writing. + * Otherwise, flush any current write stuff. + */ + if ((fp->_flags & __SRW) == 0) + return EOF; + if (fp->_flags & __SWR) + { + if (fflush (fp)) + return EOF; + fp->_flags &= ~__SWR; + fp->_w = 0; + fp->_lbfsize = 0; + } + fp->_flags |= __SRD; + } + c = (unsigned char) c; + + /* + * If we are in the middle of ungetc'ing, just continue. + * This may require expanding the current ungetc buffer. + */ + + if (HASUB (fp)) + { + if (fp->_r >= fp->_ub._size && __submore (fp)) + return EOF; + *--fp->_p = c; + fp->_r++; + return c; + } + + /* + * If we can handle this by simply backing up, do so, + * but never replace the original character. + * (This makes sscanf() work when scanning `const' data.) + */ + + if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c) + { + fp->_p--; + fp->_r++; + return c; + } + + /* + * Create an ungetc buffer. + * Initially, we will use the `reserve' buffer. + */ + + fp->_ur = fp->_r; + fp->_up = fp->_p; + fp->_ub._base = fp->_ubuf; + fp->_ub._size = sizeof (fp->_ubuf); + fp->_ubuf[sizeof (fp->_ubuf) - 1] = c; + fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1]; + fp->_r = 1; + return c; +} diff --git a/newlib/libc/stdio/vfieeefp.h b/newlib/libc/stdio/vfieeefp.h new file mode 100644 index 000000000..6843d5f47 --- /dev/null +++ b/newlib/libc/stdio/vfieeefp.h @@ -0,0 +1,205 @@ +/**************************************************************** + * + * The author of this software is David M. Gay. + * + * Copyright (c) 1991 by AT&T. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose without fee is hereby granted, provided that this entire notice + * is included in all copies of any software which is or includes a copy + * or modification of this software and in all copies of the supporting + * documentation for such software. + * + * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY + * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + * + ***************************************************************/ + +/* Please send bug reports to + David M. Gay + AT&T Bell Laboratories, Room 2C-463 + 600 Mountain Avenue + Murray Hill, NJ 07974-2070 + U.S.A. + dmg@research.att.com or research!dmg + */ + +/* This header file is a modification of mprec.h that only contains floating + point union code. */ + +#include <ieeefp.h> +#include <math.h> +#include <float.h> +#include <errno.h> +#include <sys/config.h> + +#ifdef __IEEE_LITTLE_ENDIAN +#define IEEE_8087 +#endif + +#ifdef __IEEE_BIG_ENDIAN +#define IEEE_MC68k +#endif + +#ifdef __Z8000__ +#define Just_16 +#endif + +#ifdef Unsigned_Shifts +#define Sign_Extend(a,b) if (b < 0) a |= (__uint32_t)0xffff0000; +#else +#define Sign_Extend(a,b) /*no-op*/ +#endif + +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 +Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +#endif + +/* If we are going to examine or modify specific bits in a double using + the word0 and/or word1 macros, then we must wrap the double inside + a union. This is necessary to avoid undefined behavior according to + the ANSI C spec. */ +union double_union +{ + double d; + __uint32_t i[2]; +}; + +#ifdef IEEE_8087 +#define word0(x) (x.i[1]) +#define word1(x) (x.i[0]) +#else +#define word0(x) (x.i[0]) +#define word1(x) (x.i[1]) +#endif + +/* #define P DBL_MANT_DIG */ +/* Ten_pmax = floor(P*log(2)/log(5)) */ +/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ +/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ +/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ + +#if defined(IEEE_8087) + defined(IEEE_MC68k) +#if defined (_DOUBLE_IS_32BITS) +#define Exp_shift 23 +#define Exp_shift1 23 +#define Exp_msk1 ((__uint32_t)0x00800000L) +#define Exp_msk11 ((__uint32_t)0x00800000L) +#define Exp_mask ((__uint32_t)0x7f800000L) +#define P 24 +#define Bias 127 +#if 0 +#define IEEE_Arith /* it is, but the code doesn't handle IEEE singles yet */ +#endif +#define Emin (-126) +#define Exp_1 ((__uint32_t)0x3f800000L) +#define Exp_11 ((__uint32_t)0x3f800000L) +#define Ebits 8 +#define Frac_mask ((__uint32_t)0x007fffffL) +#define Frac_mask1 ((__uint32_t)0x007fffffL) +#define Ten_pmax 10 +#define Sign_bit ((__uint32_t)0x80000000L) +#define Ten_pmax 10 +#define Bletch 2 +#define Bndry_mask ((__uint32_t)0x007fffffL) +#define Bndry_mask1 ((__uint32_t)0x007fffffL) +#define LSB 1 +#define Sign_bit ((__uint32_t)0x80000000L) +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 5 +#define Int_max 6 +#define Infinite(x) (word0(x) == ((__uint32_t)0x7f800000L)) +#undef word0 +#undef word1 + +#define word0(x) (x.i[0]) +#define word1(x) 0 +#else + +#define Exp_shift 20 +#define Exp_shift1 20 +#define Exp_msk1 ((__uint32_t)0x100000L) +#define Exp_msk11 ((__uint32_t)0x100000L) +#define Exp_mask ((__uint32_t)0x7ff00000L) +#define P 53 +#define Bias 1023 +#define IEEE_Arith +#define Emin (-1022) +#define Exp_1 ((__uint32_t)0x3ff00000L) +#define Exp_11 ((__uint32_t)0x3ff00000L) +#define Ebits 11 +#define Frac_mask ((__uint32_t)0xfffffL) +#define Frac_mask1 ((__uint32_t)0xfffffL) +#define Ten_pmax 22 +#define Bletch 0x10 +#define Bndry_mask ((__uint32_t)0xfffffL) +#define Bndry_mask1 ((__uint32_t)0xfffffL) +#define LSB 1 +#define Sign_bit ((__uint32_t)0x80000000L) +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 14 +#define Int_max 14 +#define Infinite(x) (word0(x) == ((__uint32_t)0x7ff00000L)) /* sufficient test for here */ +#endif + +#else +#undef Sudden_Underflow +#define Sudden_Underflow +#ifdef IBM +#define Exp_shift 24 +#define Exp_shift1 24 +#define Exp_msk1 ((__uint32_t)0x1000000L) +#define Exp_msk11 ((__uint32_t)0x1000000L) +#define Exp_mask ((__uint32_t)0x7f000000L) +#define P 14 +#define Bias 65 +#define Exp_1 ((__uint32_t)0x41000000L) +#define Exp_11 ((__uint32_t)0x41000000L) +#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ +#define Frac_mask ((__uint32_t)0xffffffL) +#define Frac_mask1 ((__uint32_t)0xffffffL) +#define Bletch 4 +#define Ten_pmax 22 +#define Bndry_mask ((__uint32_t)0xefffffL) +#define Bndry_mask1 ((__uint32_t)0xffffffL) +#define LSB 1 +#define Sign_bit ((__uint32_t)0x80000000L) +#define Log2P 4 +#define Tiny0 ((__uint32_t)0x100000L) +#define Tiny1 0 +#define Quick_max 14 +#define Int_max 15 +#else /* VAX */ +#define Exp_shift 23 +#define Exp_shift1 7 +#define Exp_msk1 0x80 +#define Exp_msk11 ((__uint32_t)0x800000L) +#define Exp_mask ((__uint32_t)0x7f80L) +#define P 56 +#define Bias 129 +#define Exp_1 ((__uint32_t)0x40800000L) +#define Exp_11 ((__uint32_t)0x4080L) +#define Ebits 8 +#define Frac_mask ((__uint32_t)0x7fffffL) +#define Frac_mask1 ((__uint32_t)0xffff007fL) +#define Ten_pmax 24 +#define Bletch 2 +#define Bndry_mask ((__uint32_t)0xffff007fL) +#define Bndry_mask1 ((__uint32_t)0xffff007fL) +#define LSB ((__uint32_t)0x10000L) +#define Sign_bit ((__uint32_t)0x8000L) +#define Log2P 1 +#define Tiny0 0x80 +#define Tiny1 0 +#define Quick_max 15 +#define Int_max 15 +#endif +#endif + + diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c new file mode 100644 index 000000000..4b2043e49 --- /dev/null +++ b/newlib/libc/stdio/vfprintf.c @@ -0,0 +1,939 @@ +/* +FUNCTION +<<vprintf>>, <<vfprintf>>, <<vsprintf>>---format argument list + +INDEX + vprintf +INDEX + vfprintf +INDEX + vsprintf +INDEX + vsnprintf + +ANSI_SYNOPSIS + #include <stdio.h> + #include <stdarg.h> + int vprintf(const char *<[fmt]>, va_list <[list]>); + int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>); + int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>); + int vsnprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>, va_list <[list]>); + + int _vprintf_r(void *<[reent]>, const char *<[fmt]>, + va_list <[list]>); + int _vfprintf_r(void *<[reent]>, FILE *<[fp]>, const char *<[fmt]>, + va_list <[list]>); + int _vsprintf_r(void *<[reent]>, char *<[str]>, const char *<[fmt]>, + va_list <[list]>); + int _vsnprintf_r(void *<[reent]>, char *<[str]>, size_t <[size]>, const char *<[fmt]>, + va_list <[list]>); + +TRAD_SYNOPSIS + #include <stdio.h> + #include <varargs.h> + int vprintf( <[fmt]>, <[list]>) + char *<[fmt]>; + va_list <[list]>; + + int vfprintf(<[fp]>, <[fmt]>, <[list]>) + FILE *<[fp]>; + char *<[fmt]>; + va_list <[list]>; + + int vsprintf(<[str]>, <[fmt]>, <[list]>) + char *<[str]>; + char *<[fmt]>; + va_list <[list]>; + + int vsnprintf(<[str]>, <[size]>, <[fmt]>, <[list]>) + char *<[str]>; + size_t <[size]>; + char *<[fmt]>; + va_list <[list]>; + + int _vprintf_r(<[reent]>, <[fmt]>, <[list]>) + char *<[reent]>; + char *<[fmt]>; + va_list <[list]>; + + int _vfprintf_r(<[reent]>, <[fp]>, <[fmt]>, <[list]>) + char *<[reent]>; + FILE *<[fp]>; + char *<[fmt]>; + va_list <[list]>; + + int _vsprintf_r(<[reent]>, <[str]>, <[fmt]>, <[list]>) + char *<[reent]>; + char *<[str]>; + char *<[fmt]>; + va_list <[list]>; + + int _vsnprintf_r(<[reent]>, <[str]>, <[size]>, <[fmt]>, <[list]>) + char *<[reent]>; + char *<[str]>; + size_t <[size]>; + char *<[fmt]>; + va_list <[list]>; + +DESCRIPTION +<<vprintf>>, <<vfprintf>>, <<vsprintf>> and <<vsnprintf>> are (respectively) +variants of <<printf>>, <<fprintf>>, <<sprintf>> and <<snprintf>>. They differ +only in allowing their caller to pass the variable argument list as a +<<va_list>> object (initialized by <<va_start>>) rather than directly +accepting a variable number of arguments. + +RETURNS +The return values are consistent with the corresponding functions: +<<vsprintf>> returns the number of bytes in the output string, +save that the concluding <<NULL>> is not counted. +<<vprintf>> and <<vfprintf>> return the number of characters transmitted. +If an error occurs, <<vprintf>> and <<vfprintf>> return <<EOF>>. No +error returns occur for <<vsprintf>>. + +PORTABILITY +ANSI C requires all three functions. + +Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>, +<<lseek>>, <<read>>, <<sbrk>>, <<write>>. +*/ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)vfprintf.c 5.50 (Berkeley) 12/16/92";*/ +static char *rcsid = "$Id$"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Actual printf innards. + * + * This code is large and complicated... + */ + +#ifdef INTEGER_ONLY +#define VFPRINTF vfiprintf +#define _VFPRINTF_R _vfiprintf_r +#else +#define VFPRINTF vfprintf +#define _VFPRINTF_R _vfprintf_r +#define FLOATING_POINT +#endif + +#define _NO_LONGLONG +#if defined WANT_PRINTF_LONG_LONG && defined __GNUC__ +# undef _NO_LONGLONG +#endif + +#include <_ansi.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <reent.h> + +#ifdef _HAVE_STDC +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +#include "local.h" +#include "fvwrite.h" +#include "vfieeefp.h" + +/* + * Flush out all the vectors defined by the given uio, + * then reset it so that it can be reused. + */ +static int +__sprint(fp, uio) + FILE *fp; + register struct __suio *uio; +{ + register int err; + + if (uio->uio_resid == 0) { + uio->uio_iovcnt = 0; + return (0); + } + err = __sfvwrite(fp, uio); + uio->uio_resid = 0; + uio->uio_iovcnt = 0; + return (err); +} + +/* + * Helper function for `fprintf to unbuffered unix file': creates a + * temporary buffer. We only work on write-only files; this avoids + * worries about ungetc buffers and so forth. + */ +static int +__sbprintf(fp, fmt, ap) + register FILE *fp; + const char *fmt; + va_list ap; +{ + int ret; + FILE fake; + unsigned char buf[BUFSIZ]; + + /* copy the important variables */ + fake._data = fp->_data; + fake._flags = fp->_flags & ~__SNBF; + fake._file = fp->_file; + fake._cookie = fp->_cookie; + fake._write = fp->_write; + + /* set up the buffer */ + fake._bf._base = fake._p = buf; + fake._bf._size = fake._w = sizeof(buf); + fake._lbfsize = 0; /* not actually used, but Just In Case */ + + /* do the work, then copy any error status */ + ret = VFPRINTF(&fake, fmt, ap); + if (ret >= 0 && fflush(&fake)) + ret = EOF; + if (fake._flags & __SERR) + fp->_flags |= __SERR; + return (ret); +} + + +#ifdef FLOATING_POINT +#include <locale.h> +#include <math.h> +#include "floatio.h" + +#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ +#define DEFPREC 6 + +static char *cvt _PARAMS((struct _reent *, double, int, int, char *, int *, int, int *)); +static int exponent _PARAMS((char *, int, int)); + +#else /* no FLOATING_POINT */ + +#define BUF 40 + +#endif /* FLOATING_POINT */ + + +/* + * Macros for converting digits to letters and vice versa + */ +#define to_digit(c) ((c) - '0') +#define is_digit(c) ((unsigned)to_digit(c) <= 9) +#define to_char(n) ((n) + '0') + +/* + * Flags used during conversion. + */ +#define ALT 0x001 /* alternate form */ +#define HEXPREFIX 0x002 /* add 0x or 0X prefix */ +#define LADJUST 0x004 /* left adjustment */ +#define LONGDBL 0x008 /* long double; unimplemented */ +#define LONGINT 0x010 /* long integer */ +#define QUADINT 0x020 /* quad integer */ +#define SHORTINT 0x040 /* short integer */ +#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ +#define FPT 0x100 /* Floating point number */ + +int +_DEFUN (VFPRINTF, (fp, fmt0, ap), + FILE * fp _AND + _CONST char *fmt0 _AND + va_list ap) +{ + return _VFPRINTF_R (fp->_data, fp, fmt0, ap); +} + +int +_DEFUN (_VFPRINTF_R, (data, fp, fmt0, ap), + struct _reent *data _AND + FILE * fp _AND + _CONST char *fmt0 _AND + va_list ap) +{ + register char *fmt; /* format string */ + register int ch; /* character from fmt */ + register int n, m; /* handy integers (short term usage) */ + register char *cp; /* handy char pointer (short term usage) */ + register struct __siov *iovp;/* for PRINT macro */ + register int flags; /* flags as above */ + int ret; /* return value accumulator */ + int width; /* width from format (%8d), or 0 */ + int prec; /* precision from format (%.3d), or -1 */ + char sign; /* sign prefix (' ', '+', '-', or \0) */ + wchar_t wc; +#ifdef FLOATING_POINT + char *decimal_point = localeconv()->decimal_point; + char softsign; /* temporary negative sign for floats */ + double _double; /* double precision arguments %[eEfgG] */ + int expt; /* integer value of exponent */ + int expsize; /* character count for expstr */ + int ndig; /* actual number of digits returned by cvt */ + char expstr[7]; /* buffer for exponent string */ +#endif + +#ifndef _NO_LONGLONG +#define quad_t long long +#define u_quad_t unsigned long long +#endif + +#ifndef _NO_LONGLONG + u_quad_t _uquad; /* integer arguments %[diouxX] */ +#else + u_long _uquad; +#endif + enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ + int dprec; /* a copy of prec if [diouxX], 0 otherwise */ + int realsz; /* field size expanded by dprec */ + int size; /* size of converted field or string */ + char *xdigs; /* digits for [xX] conversion */ +#define NIOV 8 + struct __suio uio; /* output information: summary */ + struct __siov iov[NIOV];/* ... and individual io vectors */ + char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ + char ox[2]; /* space for 0x hex-prefix */ + int state = 0; /* mbtowc calls from library must not change state */ + + /* + * Choose PADSIZE to trade efficiency vs. size. If larger printf + * fields occur frequently, increase PADSIZE and make the initialisers + * below longer. + */ +#define PADSIZE 16 /* pad chunk size */ + static _CONST char blanks[PADSIZE] = + {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; + static _CONST char zeroes[PADSIZE] = + {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; + + /* + * BEWARE, these `goto error' on error, and PAD uses `n'. + */ +#define PRINT(ptr, len) { \ + iovp->iov_base = (ptr); \ + iovp->iov_len = (len); \ + uio.uio_resid += (len); \ + iovp++; \ + if (++uio.uio_iovcnt >= NIOV) { \ + if (__sprint(fp, &uio)) \ + goto error; \ + iovp = iov; \ + } \ +} +#define PAD(howmany, with) { \ + if ((n = (howmany)) > 0) { \ + while (n > PADSIZE) { \ + PRINT(with, PADSIZE); \ + n -= PADSIZE; \ + } \ + PRINT(with, n); \ + } \ +} +#define FLUSH() { \ + if (uio.uio_resid && __sprint(fp, &uio)) \ + goto error; \ + uio.uio_iovcnt = 0; \ + iovp = iov; \ +} + + /* + * To extend shorts properly, we need both signed and unsigned + * argument extraction methods. + */ +#ifndef _NO_LONGLONG +#define SARG() \ + (flags&QUADINT ? va_arg(ap, quad_t) : \ + flags&LONGINT ? va_arg(ap, long) : \ + flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ + (long)va_arg(ap, int)) +#define UARG() \ + (flags&QUADINT ? va_arg(ap, u_quad_t) : \ + flags&LONGINT ? va_arg(ap, u_long) : \ + flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \ + (u_long)va_arg(ap, u_int)) +#else +#define SARG() \ + (flags&LONGINT ? va_arg(ap, long) : \ + flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ + (long)va_arg(ap, int)) +#define UARG() \ + (flags&LONGINT ? va_arg(ap, u_long) : \ + flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \ + (u_long)va_arg(ap, u_int)) +#endif + + CHECK_INIT (fp); + + /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ + if (cantwrite(fp)) + return (EOF); + + /* optimise fprintf(stderr) (and other unbuffered Unix files) */ + if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && + fp->_file >= 0) + return (__sbprintf(fp, fmt0, ap)); + + fmt = (char *)fmt0; + uio.uio_iov = iovp = iov; + uio.uio_resid = 0; + uio.uio_iovcnt = 0; + ret = 0; + + /* + * Scan the format for conversions (`%' character). + */ + for (;;) { + cp = fmt; + while ((n = _mbtowc_r(_REENT, &wc, fmt, MB_CUR_MAX, &state)) > 0) { + fmt += n; + if (wc == '%') { + fmt--; + break; + } + } + if ((m = fmt - cp) != 0) { + PRINT(cp, m); + ret += m; + } + if (n <= 0) + goto done; + fmt++; /* skip over '%' */ + + flags = 0; + dprec = 0; + width = 0; + prec = -1; + sign = '\0'; + +rflag: ch = *fmt++; +reswitch: switch (ch) { + case ' ': + /* + * ``If the space and + flags both appear, the space + * flag will be ignored.'' + * -- ANSI X3J11 + */ + if (!sign) + sign = ' '; + goto rflag; + case '#': + flags |= ALT; + goto rflag; + case '*': + /* + * ``A negative field width argument is taken as a + * - flag followed by a positive field width.'' + * -- ANSI X3J11 + * They don't exclude field widths read from args. + */ + if ((width = va_arg(ap, int)) >= 0) + goto rflag; + width = -width; + /* FALLTHROUGH */ + case '-': + flags |= LADJUST; + goto rflag; + case '+': + sign = '+'; + goto rflag; + case '.': + if ((ch = *fmt++) == '*') { + n = va_arg(ap, int); + prec = n < 0 ? -1 : n; + goto rflag; + } + n = 0; + while (is_digit(ch)) { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } + prec = n < 0 ? -1 : n; + goto reswitch; + case '0': + /* + * ``Note that 0 is taken as a flag, not as the + * beginning of a field width.'' + * -- ANSI X3J11 + */ + flags |= ZEROPAD; + goto rflag; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + n = 0; + do { + n = 10 * n + to_digit(ch); + ch = *fmt++; + } while (is_digit(ch)); + width = n; + goto reswitch; +#ifdef FLOATING_POINT + case 'L': + flags |= LONGDBL; + goto rflag; +#endif + case 'h': + flags |= SHORTINT; + goto rflag; + case 'l': + if (*fmt == 'l') { + fmt++; + flags |= QUADINT; + } else { + flags |= LONGINT; + } + goto rflag; + case 'q': + flags |= QUADINT; + goto rflag; + case 'c': + *(cp = buf) = va_arg(ap, int); + size = 1; + sign = '\0'; + break; + case 'D': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'd': + case 'i': + _uquad = SARG(); +#ifndef _NO_LONGLONG + if ((quad_t)_uquad < 0) +#else + if ((long) _uquad < 0) +#endif + { + + _uquad = -_uquad; + sign = '-'; + } + base = DEC; + goto number; +#ifdef FLOATING_POINT + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + if (prec == -1) { + prec = DEFPREC; + } else if ((ch == 'g' || ch == 'G') && prec == 0) { + prec = 1; + } + + if (flags & LONGDBL) { + _double = (double) va_arg(ap, long double); + } else { + _double = va_arg(ap, double); + } + + /* do this before tricky precision changes */ + if (isinf(_double)) { + if (_double < 0) + sign = '-'; + cp = "Inf"; + size = 3; + break; + } + if (isnan(_double)) { + cp = "NaN"; + size = 3; + break; + } + + flags |= FPT; + cp = cvt(data, _double, prec, flags, &softsign, + &expt, ch, &ndig); + if (ch == 'g' || ch == 'G') { + if (expt <= -4 || expt > prec) + ch = (ch == 'g') ? 'e' : 'E'; + else + ch = 'g'; + } + if (ch <= 'e') { /* 'e' or 'E' fmt */ + --expt; + expsize = exponent(expstr, expt, ch); + size = expsize + ndig; + if (ndig > 1 || flags & ALT) + ++size; + } else if (ch == 'f') { /* f fmt */ + if (expt > 0) { + size = expt; + if (prec || flags & ALT) + size += prec + 1; + } else /* "0.X" */ + size = prec + 2; + } else if (expt >= ndig) { /* fixed g fmt */ + size = expt; + if (flags & ALT) + ++size; + } else + size = ndig + (expt > 0 ? + 1 : 2 - expt); + + if (softsign) + sign = '-'; + break; +#endif /* FLOATING_POINT */ + case 'n': +#ifndef _NO_LONGLONG + if (flags & QUADINT) + *va_arg(ap, quad_t *) = ret; + else +#endif + if (flags & LONGINT) + *va_arg(ap, long *) = ret; + else if (flags & SHORTINT) + *va_arg(ap, short *) = ret; + else + *va_arg(ap, int *) = ret; + continue; /* no output */ + case 'O': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'o': + _uquad = UARG(); + base = OCT; + goto nosign; + case 'p': + /* + * ``The argument shall be a pointer to void. The + * value of the pointer is converted to a sequence + * of printable characters, in an implementation- + * defined manner.'' + * -- ANSI X3J11 + */ + /* NOSTRICT */ + _uquad = (u_long)(unsigned _POINTER_INT)va_arg(ap, void *); + base = HEX; + xdigs = "0123456789abcdef"; + flags |= HEXPREFIX; + ch = 'x'; + goto nosign; + case 's': + if ((cp = va_arg(ap, char *)) == NULL) + cp = "(null)"; + if (prec >= 0) { + /* + * can't use strlen; can only look for the + * NUL in the first `prec' characters, and + * strlen() will go further. + */ + char *p = memchr(cp, 0, prec); + + if (p != NULL) { + size = p - cp; + if (size > prec) + size = prec; + } else + size = prec; + } else + size = strlen(cp); + sign = '\0'; + break; + case 'U': + flags |= LONGINT; + /*FALLTHROUGH*/ + case 'u': + _uquad = UARG(); + base = DEC; + goto nosign; + case 'X': + xdigs = "0123456789ABCDEF"; + goto hex; + case 'x': + xdigs = "0123456789abcdef"; +hex: _uquad = UARG(); + base = HEX; + /* leading 0x/X only if non-zero */ + if (flags & ALT && _uquad != 0) + flags |= HEXPREFIX; + + /* unsigned conversions */ +nosign: sign = '\0'; + /* + * ``... diouXx conversions ... if a precision is + * specified, the 0 flag will be ignored.'' + * -- ANSI X3J11 + */ +number: if ((dprec = prec) >= 0) + flags &= ~ZEROPAD; + + /* + * ``The result of converting a zero value with an + * explicit precision of zero is no characters.'' + * -- ANSI X3J11 + */ + cp = buf + BUF; + if (_uquad != 0 || prec != 0) { + /* + * Unsigned mod is hard, and unsigned mod + * by a constant is easier than that by + * a variable; hence this switch. + */ + switch (base) { + case OCT: + do { + *--cp = to_char(_uquad & 7); + _uquad >>= 3; + } while (_uquad); + /* handle octal leading 0 */ + if (flags & ALT && *cp != '0') + *--cp = '0'; + break; + + case DEC: + /* many numbers are 1 digit */ + while (_uquad >= 10) { + *--cp = to_char(_uquad % 10); + _uquad /= 10; + } + *--cp = to_char(_uquad); + break; + + case HEX: + do { + *--cp = xdigs[_uquad & 15]; + _uquad >>= 4; + } while (_uquad); + break; + + default: + cp = "bug in vfprintf: bad base"; + size = strlen(cp); + goto skipsize; + } + } + size = buf + BUF - cp; + skipsize: + break; + default: /* "%?" prints ?, unless ? is NUL */ + if (ch == '\0') + goto done; + /* pretend it was %c with argument ch */ + cp = buf; + *cp = ch; + size = 1; + sign = '\0'; + break; + } + + /* + * All reasonable formats wind up here. At this point, `cp' + * points to a string which (if not flags&LADJUST) should be + * padded out to `width' places. If flags&ZEROPAD, it should + * first be prefixed by any sign or other prefix; otherwise, + * it should be blank padded before the prefix is emitted. + * After any left-hand padding and prefixing, emit zeroes + * required by a decimal [diouxX] precision, then print the + * string proper, then emit zeroes required by any leftover + * floating precision; finally, if LADJUST, pad with blanks. + * + * Compute actual size, so we know how much to pad. + * size excludes decimal prec; realsz includes it. + */ + realsz = dprec > size ? dprec : size; + if (sign) + realsz++; + else if (flags & HEXPREFIX) + realsz+= 2; + + /* right-adjusting blank padding */ + if ((flags & (LADJUST|ZEROPAD)) == 0) + PAD(width - realsz, blanks); + + /* prefix */ + if (sign) { + PRINT(&sign, 1); + } else if (flags & HEXPREFIX) { + ox[0] = '0'; + ox[1] = ch; + PRINT(ox, 2); + } + + /* right-adjusting zero padding */ + if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) + PAD(width - realsz, zeroes); + + /* leading zeroes from decimal precision */ + PAD(dprec - size, zeroes); + + /* the string or number proper */ +#ifdef FLOATING_POINT + if ((flags & FPT) == 0) { + PRINT(cp, size); + } else { /* glue together f_p fragments */ + if (ch >= 'f') { /* 'f' or 'g' */ + if (_double == 0) { + /* kludge for __dtoa irregularity */ + PRINT("0", 1); + if (expt < ndig || (flags & ALT) != 0) { + PRINT(decimal_point, 1); + PAD(ndig - 1, zeroes); + } + } else if (expt <= 0) { + PRINT("0", 1); + PRINT(decimal_point, 1); + PAD(-expt, zeroes); + PRINT(cp, ndig); + } else if (expt >= ndig) { + PRINT(cp, ndig); + PAD(expt - ndig, zeroes); + if (flags & ALT) + PRINT(".", 1); + } else { + PRINT(cp, expt); + cp += expt; + PRINT(".", 1); + PRINT(cp, ndig-expt); + } + } else { /* 'e' or 'E' */ + if (ndig > 1 || flags & ALT) { + ox[0] = *cp++; + ox[1] = '.'; + PRINT(ox, 2); + if (_double || flags & ALT == 0) { + PRINT(cp, ndig-1); + } else /* 0.[0..] */ + /* __dtoa irregularity */ + PAD(ndig - 1, zeroes); + } else /* XeYYY */ + PRINT(cp, 1); + PRINT(expstr, expsize); + } + } +#else + PRINT(cp, size); +#endif + /* left-adjusting padding (always blank) */ + if (flags & LADJUST) + PAD(width - realsz, blanks); + + /* finally, adjust ret */ + ret += width > realsz ? width : realsz; + + FLUSH(); /* copy out the I/O vectors */ + } +done: + FLUSH(); +error: + return (__sferror(fp) ? EOF : ret); + /* NOTREACHED */ +} + +#ifdef FLOATING_POINT + +extern char *_dtoa_r _PARAMS((struct _reent *, double, int, + int, int *, int *, char **)); + +static char * +cvt(data, value, ndigits, flags, sign, decpt, ch, length) + struct _reent *data; + double value; + int ndigits, flags, *decpt, ch, *length; + char *sign; +{ + int mode, dsgn; + char *digits, *bp, *rve; + union double_union tmp; + + if (ch == 'f') { + mode = 3; /* ndigits after the decimal point */ + } else { + /* To obtain ndigits after the decimal point for the 'e' + * and 'E' formats, round to ndigits + 1 significant + * figures. + */ + if (ch == 'e' || ch == 'E') { + ndigits++; + } + mode = 2; /* ndigits significant digits */ + } + + tmp.d = value; + if (word0(tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */ + value = -value; + *sign = '-'; + } else + *sign = '\000'; + digits = _dtoa_r(data, value, mode, ndigits, decpt, &dsgn, &rve); + if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */ + bp = digits + ndigits; + if (ch == 'f') { + if (*digits == '0' && value) + *decpt = -ndigits + 1; + bp += *decpt; + } + if (value == 0) /* kludge for __dtoa irregularity */ + rve = bp; + while (rve < bp) + *rve++ = '0'; + } + *length = rve - digits; + return (digits); +} + +static int +exponent(p0, exp, fmtch) + char *p0; + int exp, fmtch; +{ + register char *p, *t; + char expbuf[MAXEXP]; + + p = p0; + *p++ = fmtch; + if (exp < 0) { + exp = -exp; + *p++ = '-'; + } + else + *p++ = '+'; + t = expbuf + MAXEXP; + if (exp > 9) { + do { + *--t = to_char(exp % 10); + } while ((exp /= 10) > 9); + *--t = to_char(exp); + for (; t < expbuf + MAXEXP; *p++ = *t++); + } + else { + *p++ = '0'; + *p++ = to_char(exp); + } + return (p - p0); +} +#endif /* FLOATING_POINT */ diff --git a/newlib/libc/stdio/vfscanf.c b/newlib/libc/stdio/vfscanf.c new file mode 100644 index 000000000..00fd98d76 --- /dev/null +++ b/newlib/libc/stdio/vfscanf.c @@ -0,0 +1,956 @@ +/* No user fns here. Pesch 15apr92. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <_ansi.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#ifdef _HAVE_STDC +#include <stdarg.h> +#else +#include <varargs.h> +#endif +#include "local.h" + +#ifndef NO_FLOATING_POINT +#define FLOATING_POINT +#endif + +#ifdef FLOATING_POINT +#include "floatio.h" +#define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */ +/* An upper bound for how long a long prints in decimal. 4 / 13 approximates + log (2). Add one char for roundoff compensation and one for the sign. */ +#define MAX_LONG_LEN ((CHAR_BIT * sizeof (long) - 1) * 4 / 13 + 2) +#else +#define BUF 40 +#endif + +/* + * Flags used during conversion. + */ + +#define LONG 0x01 /* l: long or double */ +#define LONGDBL 0x02 /* L: long double; unimplemented */ +#define SHORT 0x04 /* h: short */ +#define SUPPRESS 0x08 /* suppress assignment */ +#define POINTER 0x10 /* weird %p pointer (`fake hex') */ +#define NOSKIP 0x20 /* do not skip blanks */ + +/* + * The following are used in numeric conversions only: + * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point; + * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral. + */ + +#define SIGNOK 0x40 /* +/- is (still) legal */ +#define NDIGITS 0x80 /* no digits detected */ + +#define DPTOK 0x100 /* (float) decimal point is still legal */ +#define EXPOK 0x200 /* (float) exponent (e+3, etc) still legal */ + +#define PFXOK 0x100 /* 0x prefix is (still) legal */ +#define NZDIGITS 0x200 /* no zero digits detected */ + +/* + * Conversion types. + */ + +#define CT_CHAR 0 /* %c conversion */ +#define CT_CCL 1 /* %[...] conversion */ +#define CT_STRING 2 /* %s conversion */ +#define CT_INT 3 /* integer, i.e., strtol or strtoul */ +#define CT_FLOAT 4 /* floating, i.e., strtod */ + +#if 0 +#define u_char unsigned char +#endif +#define u_char char +#define u_long unsigned long + +/*static*/ u_char *__sccl (); + +/* + * vfscanf + */ + +#define BufferEmpty (fp->_r <= 0 && __srefill(fp)) + +int +__svfscanf (fp, fmt0, ap) + register FILE *fp; + char _CONST *fmt0; + va_list ap; +{ + register u_char *fmt = (u_char *) fmt0; + register int c; /* character from format, or conversion */ + register size_t width; /* field width, or 0 */ + register char *p; /* points into all kinds of strings */ + register int n; /* handy integer */ + register int flags; /* flags as defined above */ + register char *p0; /* saves original value of p when necessary */ + int nassigned; /* number of fields assigned */ + int nread; /* number of characters consumed from fp */ + int base = 0; /* base argument to strtol/strtoul */ + int nbytes = 1; /* number of bytes read from fmt string */ + wchar_t wc; /* wchar to use to read format string */ + + u_long (*ccfn) () = 0; /* conversion function (strtol/strtoul) */ + char ccltab[256]; /* character class table for %[...] */ + char buf[BUF]; /* buffer for numeric conversions */ + char *lptr; /* literal pointer */ + int state = 0; /* value to keep track of multibyte state */ + + short *sp; + int *ip; + float *flp; + _LONG_DOUBLE *ldp; + double *dp; + long *lp; + + /* `basefix' is used to avoid `if' tests in the integer scanner */ + static _CONST short basefix[17] = + {10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; + + nassigned = 0; + nread = 0; + for (;;) + { +#ifndef MB_CAPABLE + wc = *fmt; +#else + nbytes = _mbtowc_r (_REENT, &wc, fmt, MB_CUR_MAX, &state); +#endif + fmt += nbytes; + if (wc == 0) + return nassigned; + if (nbytes == 1 && isspace (wc)) + { + for (;;) + { + if (BufferEmpty) + return nassigned; + if (!isspace (*fp->_p)) + break; + nread++, fp->_r--, fp->_p++; + } + continue; + } + if (wc != '%') + goto literal; + width = 0; + flags = 0; + + /* + * switch on the format. continue if done; break once format + * type is derived. + */ + + again: + c = *fmt++; + + switch (c) + { + case '%': + literal: + lptr = fmt - nbytes; + for (n = 0; n < nbytes; ++n) + { + if (BufferEmpty) + goto input_failure; + if (*fp->_p != *lptr) + goto match_failure; + fp->_r--, fp->_p++; + nread++; + ++lptr; + } + continue; + + case '*': + flags |= SUPPRESS; + goto again; + case 'l': + flags |= LONG; + goto again; + case 'L': + flags |= LONGDBL; + goto again; + case 'h': + flags |= SHORT; + goto again; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + width = width * 10 + c - '0'; + goto again; + + /* + * Conversions. Those marked `compat' are for + * 4.[123]BSD compatibility. + * + * (According to ANSI, E and X formats are supposed to + * the same as e and x. Sorry about that.) + */ + + case 'D': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'd': + c = CT_INT; + ccfn = (u_long (*)())strtol; + base = 10; + break; + + case 'i': + c = CT_INT; + ccfn = (u_long (*)())strtol; + base = 0; + break; + + case 'O': /* compat */ + flags |= LONG; + /* FALLTHROUGH */ + case 'o': + c = CT_INT; + ccfn = strtoul; + base = 8; + break; + + case 'u': + c = CT_INT; + ccfn = strtoul; + base = 10; + break; + + case 'X': /* compat XXX */ + case 'x': + flags |= PFXOK; /* enable 0x prefixing */ + c = CT_INT; + ccfn = strtoul; + base = 16; + break; + +#ifdef FLOATING_POINT + case 'E': /* compat XXX */ + case 'G': /* compat XXX */ +/* ANSI says that E,G and X behave the same way as e,g,x */ + /* FALLTHROUGH */ + case 'e': + case 'f': + case 'g': + c = CT_FLOAT; + break; +#endif + + case 's': + c = CT_STRING; + break; + + case '[': + fmt = __sccl (ccltab, fmt); + flags |= NOSKIP; + c = CT_CCL; + break; + + case 'c': + flags |= NOSKIP; + c = CT_CHAR; + break; + + case 'p': /* pointer format is like hex */ + flags |= POINTER | PFXOK; + c = CT_INT; + ccfn = strtoul; + base = 16; + break; + + case 'n': + if (flags & SUPPRESS) /* ??? */ + continue; + if (flags & SHORT) + { + sp = va_arg (ap, short *); + *sp = nread; + } + else if (flags & LONG) + { + lp = va_arg (ap, long *); + *lp = nread; + } + else + { + ip = va_arg (ap, int *); + *ip = nread; + } + continue; + + /* + * Disgusting backwards compatibility hacks. XXX + */ + case '\0': /* compat */ + return EOF; + + default: /* compat */ + if (isupper (c)) + flags |= LONG; + c = CT_INT; + ccfn = (u_long (*)())strtol; + base = 10; + break; + } + + /* + * We have a conversion that requires input. + */ + if (BufferEmpty) + goto input_failure; + + /* + * Consume leading white space, except for formats that + * suppress this. + */ + if ((flags & NOSKIP) == 0) + { + while (isspace (*fp->_p)) + { + nread++; + if (--fp->_r > 0) + fp->_p++; + else +#ifndef CYGNUS_NEC + if (__srefill (fp)) +#endif + goto input_failure; + } + /* + * Note that there is at least one character in the + * buffer, so conversions that do not set NOSKIP ca + * no longer result in an input failure. + */ + } + + /* + * Do the conversion. + */ + switch (c) + { + + case CT_CHAR: + /* scan arbitrary characters (sets NOSKIP) */ + if (width == 0) + width = 1; + if (flags & SUPPRESS) + { + size_t sum = 0; + + for (;;) + { + if ((n = fp->_r) < width) + { + sum += n; + width -= n; + fp->_p += n; +#ifndef CYGNUS_NEC + if (__srefill (fp)) + { +#endif + if (sum == 0) + goto input_failure; + break; +#ifndef CYGNUS_NEC + } +#endif + } + else + { + sum += width; + fp->_r -= width; + fp->_p += width; + break; + } + } + nread += sum; + } + else + { +#ifdef CYGNUS_NEC + /* Kludge city for the moment */ + char *dest = va_arg (ap, char *); + int n = width; + if (fp->_r == 0) + goto input_failure; + + while (n && fp->_r) + { + *dest++ = *(fp->_p++); + n--; + fp->_r--; + nread++; + } +#else + size_t r = fread ((_PTR) va_arg (ap, char *), 1, width, fp); + + if (r == 0) + goto input_failure; + nread += r; +#endif + nassigned++; + } + break; + + case CT_CCL: + /* scan a (nonempty) character class (sets NOSKIP) */ + if (width == 0) + width = ~0; /* `infinity' */ + /* take only those things in the class */ + if (flags & SUPPRESS) + { + n = 0; + while (ccltab[*fp->_p]) + { + n++, fp->_r--, fp->_p++; + if (--width == 0) + break; + if (BufferEmpty) + { + if (n == 0) + goto input_failure; + break; + } + } + if (n == 0) + goto match_failure; + } + else + { + p0 = p = va_arg (ap, char *); + while (ccltab[*fp->_p]) + { + fp->_r--; + *p++ = *fp->_p++; + if (--width == 0) + break; + if (BufferEmpty) + { + if (p == p0) + goto input_failure; + break; + } + } + n = p - p0; + if (n == 0) + goto match_failure; + *p = 0; + nassigned++; + } + nread += n; + break; + + case CT_STRING: + /* like CCL, but zero-length string OK, & no NOSKIP */ + if (width == 0) + width = ~0; + if (flags & SUPPRESS) + { + n = 0; + while (!isspace (*fp->_p)) + { + n++, fp->_r--, fp->_p++; + if (--width == 0) + break; + if (BufferEmpty) + break; + } + nread += n; + } + else + { + p0 = p = va_arg (ap, char *); + while (!isspace (*fp->_p)) + { + fp->_r--; + *p++ = *fp->_p++; + if (--width == 0) + break; + if (BufferEmpty) + break; + } + *p = 0; + nread += p - p0; + nassigned++; + } + continue; + + case CT_INT: + /* scan an integer as if by strtol/strtoul */ +#ifdef hardway + if (width == 0 || width > sizeof (buf) - 1) + width = sizeof (buf) - 1; +#else + /* size_t is unsigned, hence this optimisation */ + if (--width > sizeof (buf) - 2) + width = sizeof (buf) - 2; + width++; +#endif + flags |= SIGNOK | NDIGITS | NZDIGITS; + for (p = buf; width; width--) + { + c = *fp->_p; + /* + * Switch on the character; `goto ok' if we + * accept it as a part of number. + */ + switch (c) + { + /* + * The digit 0 is always legal, but is special. + * For %i conversions, if no digits (zero or nonzero) + * have been scanned (only signs), we will have base==0. + * In that case, we should set it to 8 and enable 0x + * prefixing. Also, if we have not scanned zero digits + * before this, do not turn off prefixing (someone else + * will turn it off if we have scanned any nonzero digits). + */ + case '0': + if (base == 0) + { + base = 8; + flags |= PFXOK; + } + if (flags & NZDIGITS) + flags &= ~(SIGNOK | NZDIGITS | NDIGITS); + else + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* 1 through 7 always legal */ + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + base = basefix[base]; + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* digits 8 and 9 ok iff decimal or hex */ + case '8': + case '9': + base = basefix[base]; + if (base <= 8) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* letters ok iff hex */ + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + /* no need to fix base here */ + if (base <= 10) + break; /* not legal here */ + flags &= ~(SIGNOK | PFXOK | NDIGITS); + goto ok; + + /* sign ok only as first character */ + case '+': + case '-': + if (flags & SIGNOK) + { + flags &= ~SIGNOK; + goto ok; + } + break; + + /* x ok iff flag still set & 2nd char */ + case 'x': + case 'X': + if (flags & PFXOK && p == buf + 1) + { + base = 16;/* if %i */ + flags &= ~PFXOK; + goto ok; + } + break; + } + + /* + * If we got here, c is not a legal character + * for a number. Stop accumulating digits. + */ + break; + ok: + /* + * c is legal: store it and look at the next. + */ + *p++ = c; + if (--fp->_r > 0) + fp->_p++; + else +#ifndef CYGNUS_NEC + if (__srefill (fp)) +#endif + break; /* EOF */ + } + /* + * If we had only a sign, it is no good; push back the sign. + * If the number ends in `x', it was [sign] '0' 'x', so push back + * the x and treat it as [sign] '0'. + */ + if (flags & NDIGITS) + { + if (p > buf) + _CAST_VOID ungetc (*(u_char *)-- p, fp); + goto match_failure; + } + c = ((u_char *) p)[-1]; + if (c == 'x' || c == 'X') + { + --p; + /*(void)*/ ungetc (c, fp); + } + if ((flags & SUPPRESS) == 0) + { + u_long res; + + *p = 0; + res = (*ccfn) (buf, (char **) NULL, base); + if (flags & POINTER) + *(va_arg (ap, _PTR *)) = (_PTR) (unsigned _POINTER_INT) res; + else if (flags & SHORT) + { + sp = va_arg (ap, short *); + *sp = res; + } + else if (flags & LONG) + { + lp = va_arg (ap, long *); + *lp = res; + } + else + { + ip = va_arg (ap, int *); + *ip = res; + } + nassigned++; + } + nread += p - buf; + break; + +#ifdef FLOATING_POINT + case CT_FLOAT: + { + /* scan a floating point number as if by strtod */ + /* This code used to assume that the number of digits is reasonable. + However, ANSI / ISO C makes no such stipulation; we have to get + exact results even when there is an unreasonable amount of + leading zeroes. */ + long leading_zeroes, zeroes, exp_adjust; + char *exp_start; +#ifdef hardway + if (width == 0 || width > sizeof (buf) - 1) + width = sizeof (buf) - 1; +#else + /* size_t is unsigned, hence this optimisation */ + if (--width > sizeof (buf) - 2) + width = sizeof (buf) - 2; + width++; +#endif + flags |= SIGNOK | NDIGITS | DPTOK | EXPOK; + zeroes = 0; + exp_adjust = 0; + for (p = buf; width; ) + { + c = *fp->_p; + /* + * This code mimicks the integer conversion + * code, but is much simpler. + */ + switch (c) + { + + case '0': + if (flags & NDIGITS) + { + flags &= ~SIGNOK; + zeroes++; + goto fskip; + } + /* Fall through. */ + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + flags &= ~(SIGNOK | NDIGITS); + goto fok; + + case '+': + case '-': + if (flags & SIGNOK) + { + flags &= ~SIGNOK; + goto fok; + } + break; + case '.': + if (flags & DPTOK) + { + flags &= ~(SIGNOK | DPTOK); + leading_zeroes = zeroes; + goto fok; + } + break; + case 'e': + case 'E': + /* no exponent without some digits */ + if ((flags & (NDIGITS | EXPOK)) == EXPOK + || ((flags & EXPOK) && zeroes)) + { + if (! (flags & DPTOK)) + { + exp_adjust = zeroes - leading_zeroes; + exp_start = p; + } + flags = + (flags & ~(EXPOK | DPTOK)) | + SIGNOK | NDIGITS; + zeroes = 0; + goto fok; + } + break; + } + break; + fok: + *p++ = c; + width--; + fskip: + if (--fp->_r > 0) + fp->_p++; + else +#ifndef CYGNUS_NEC + if (__srefill (fp)) +#endif + break; /* EOF */ + } + if (zeroes) + flags &= ~NDIGITS; + /* + * If no digits, might be missing exponent digits + * (just give back the exponent) or might be missing + * regular digits, but had sign and/or decimal point. + */ + if (flags & NDIGITS) + { + if (flags & EXPOK) + { + /* no digits at all */ + while (p > buf) + ungetc (*(u_char *)-- p, fp); + goto match_failure; + } + /* just a bad exponent (e and maybe sign) */ + c = *(u_char *)-- p; + if (c != 'e' && c != 'E') + { + _CAST_VOID ungetc (c, fp); /* sign */ + c = *(u_char *)-- p; + } + _CAST_VOID ungetc (c, fp); + } + if ((flags & SUPPRESS) == 0) + { + double res; + long new_exp; + + *p = 0; + if ((flags & (DPTOK | EXPOK)) == EXPOK) + { + exp_adjust = zeroes - leading_zeroes; + new_exp = -exp_adjust; + exp_start = p; + } + else if (exp_adjust) + new_exp = atol (exp_start + 1) - exp_adjust; + if (exp_adjust) + { + + /* If there might not be enough space for the new exponent, + truncate some trailing digits to make room. */ + if (exp_start >= buf + sizeof (buf) - MAX_LONG_LEN) + exp_start = buf + sizeof (buf) - MAX_LONG_LEN - 1; + sprintf (exp_start, "e%d", new_exp); + } + res = atof (buf); + if (flags & LONG) + { + dp = va_arg (ap, double *); + *dp = res; + } + else if (flags & LONGDBL) + { + ldp = va_arg (ap, _LONG_DOUBLE *); + *ldp = res; + } + else + { + flp = va_arg (ap, float *); + *flp = res; + } + nassigned++; + } + nread += p - buf; + break; + } +#endif /* FLOATING_POINT */ + } + } +input_failure: + return nassigned ? nassigned : -1; +match_failure: + return nassigned; +} + +/* + * Fill in the given table from the scanset at the given format + * (just after `['). Return a pointer to the character past the + * closing `]'. The table has a 1 wherever characters should be + * considered part of the scanset. + */ + +/*static*/ +u_char * +__sccl (tab, fmt) + register char *tab; + register u_char *fmt; +{ + register int c, n, v; + + /* first `clear' the whole table */ + c = *fmt++; /* first char hat => negated scanset */ + if (c == '^') + { + v = 1; /* default => accept */ + c = *fmt++; /* get new first char */ + } + else + v = 0; /* default => reject */ + /* should probably use memset here */ + for (n = 0; n < 256; n++) + tab[n] = v; + if (c == 0) + return fmt - 1; /* format ended before closing ] */ + + /* + * Now set the entries corresponding to the actual scanset to the + * opposite of the above. + * + * The first character may be ']' (or '-') without being special; the + * last character may be '-'. + */ + + v = 1 - v; + for (;;) + { + tab[c] = v; /* take character c */ + doswitch: + n = *fmt++; /* and examine the next */ + switch (n) + { + + case 0: /* format ended too soon */ + return fmt - 1; + + case '-': + /* + * A scanset of the form [01+-] is defined as `the digit 0, the + * digit 1, the character +, the character -', but the effect of a + * scanset such as [a-zA-Z0-9] is implementation defined. The V7 + * Unix scanf treats `a-z' as `the letters a through z', but treats + * `a-a' as `the letter a, the character -, and the letter a'. + * + * For compatibility, the `-' is not considerd to define a range if + * the character following it is either a close bracket (required by + * ANSI) or is not numerically greater than the character we just + * stored in the table (c). + */ + n = *fmt; + if (n == ']' || n < c) + { + c = '-'; + break; /* resume the for(;;) */ + } + fmt++; + do + { /* fill in the range */ + tab[++c] = v; + } + while (c < n); +#if 1 /* XXX another disgusting compatibility hack */ + /* + * Alas, the V7 Unix scanf also treats formats such + * as [a-c-e] as `the letters a through e'. This too + * is permitted by the standard.... + */ + goto doswitch; +#else + c = *fmt++; + if (c == 0) + return fmt - 1; + if (c == ']') + return fmt; +#endif + + break; + + + case ']': /* end of scanset */ + return fmt; + + default: /* just another character */ + c = n; + break; + } + } + /* NOTREACHED */ +} diff --git a/newlib/libc/stdio/vprintf.c b/newlib/libc/stdio/vprintf.c new file mode 100644 index 000000000..c270141f0 --- /dev/null +++ b/newlib/libc/stdio/vprintf.c @@ -0,0 +1,35 @@ +/* doc in vfprintf.c */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <_ansi.h> +#include <stdio.h> + +#ifdef _HAVE_STDC +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +int +vprintf (fmt, ap) + char _CONST *fmt; + va_list ap; +{ + return vfprintf (stdout, fmt, ap); +} diff --git a/newlib/libc/stdio/vsnprintf.c b/newlib/libc/stdio/vsnprintf.c new file mode 100644 index 000000000..18df5864a --- /dev/null +++ b/newlib/libc/stdio/vsnprintf.c @@ -0,0 +1,73 @@ +/* doc in vfprintf.c */ + +/* This code created by modifying vsprintf.c so copyright inherited. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <_ansi.h> +#include <reent.h> +#include <stdio.h> +#include <limits.h> +#ifdef _HAVE_STDC +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +int +vsnprintf (str, size, fmt, ap) + char *str; + size_t size; + char _CONST *fmt; + va_list ap; +{ + int ret; + FILE f; + + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._w = size; + f._data = _REENT; + ret = vfprintf (&f, fmt, ap); + *f._p = 0; + return ret; +} + +int +vsnprintf_r (ptr, str, size, fmt, ap) + struct _reent *ptr; + char *str; + size_t size; + char _CONST *fmt; + va_list ap; +{ + int ret; + FILE f; + + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._w = size; + f._data = ptr; + ret = vfprintf (&f, fmt, ap); + *f._p = 0; + return ret; +} diff --git a/newlib/libc/stdio/vsprintf.c b/newlib/libc/stdio/vsprintf.c new file mode 100644 index 000000000..416c184e8 --- /dev/null +++ b/newlib/libc/stdio/vsprintf.c @@ -0,0 +1,70 @@ +/* doc in vfprintf.c */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <_ansi.h> +#include <reent.h> +#include <stdio.h> +#include <limits.h> +#ifdef _HAVE_STDC +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +int +vsprintf (str, fmt, ap) + char *str; + char _CONST *fmt; + va_list ap; +{ + int ret; + FILE f; + + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._w = INT_MAX; + f._data = _REENT; + ret = vfprintf (&f, fmt, ap); + *f._p = 0; + return ret; +} + +int +vsprintf_r (ptr, str, fmt, ap) + struct _reent *ptr; + char *str; + char _CONST *fmt; + va_list ap; +{ + int ret; + FILE f; + + f._flags = __SWR | __SSTR; + f._bf._base = f._p = (unsigned char *) str; + f._bf._size = f._w = INT_MAX; + f._data = ptr; + ret = vfprintf (&f, fmt, ap); + *f._p = 0; + return ret; +} + diff --git a/newlib/libc/stdio/wbuf.c b/newlib/libc/stdio/wbuf.c new file mode 100644 index 000000000..110682971 --- /dev/null +++ b/newlib/libc/stdio/wbuf.c @@ -0,0 +1,81 @@ +/* No user fns here. Pesch 15apr92. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "%W% (Berkeley) %G%"; +#endif /* LIBC_SCCS and not lint */ + +#include <stdio.h> +#include "local.h" +#include "fvwrite.h" + +/* + * Write the given character into the (probably full) buffer for + * the given file. Flush the buffer out if it is or becomes full, + * or if c=='\n' and the file is line buffered. + */ + +int +__swbuf (c, fp) + register int c; + register FILE *fp; +{ + register int n; + + /* Ensure stdio has been initialized. */ + + CHECK_INIT (fp); + + /* + * In case we cannot write, or longjmp takes us out early, + * make sure _w is 0 (if fully- or un-buffered) or -_bf._size + * (if line buffered) so that we will get called again. + * If we did not do this, a sufficient number of putc() + * calls might wrap _w from negative to positive. + */ + + fp->_w = fp->_lbfsize; + if (cantwrite (fp)) + return EOF; + c = (unsigned char) c; + + /* + * If it is completely full, flush it out. Then, in any case, + * stuff c into the buffer. If this causes the buffer to fill + * completely, or if c is '\n' and the file is line buffered, + * flush it (perhaps a second time). The second flush will always + * happen on unbuffered streams, where _bf._size==1; fflush() + * guarantees that putc() will always call wbuf() by setting _w + * to 0, so we need not do anything else. + */ + + n = fp->_p - fp->_bf._base; + if (n >= fp->_bf._size) + { + if (fflush (fp)) + return EOF; + n = 0; + } + fp->_w--; + *fp->_p++ = c; + if (++n == fp->_bf._size || (fp->_flags & __SLBF && c == '\n')) + if (fflush (fp)) + return EOF; + return c; +} diff --git a/newlib/libc/stdio/wsetup.c b/newlib/libc/stdio/wsetup.c new file mode 100644 index 000000000..23b032efe --- /dev/null +++ b/newlib/libc/stdio/wsetup.c @@ -0,0 +1,79 @@ +/* No user fns here. Pesch 15apr92. */ + +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include "local.h" + +/* + * Various output routines call wsetup to be sure it is safe to write, + * because either _flags does not include __SWR, or _buf is NULL. + * _wsetup returns 0 if OK to write, nonzero otherwise. + */ + +int +_DEFUN (__swsetup, (fp), + register FILE * fp) +{ + /* Make sure stdio is set up. */ + + CHECK_INIT (fp); + + /* + * If we are not writing, we had better be reading and writing. + */ + + if ((fp->_flags & __SWR) == 0) + { + if ((fp->_flags & __SRW) == 0) + return EOF; + if (fp->_flags & __SRD) + { + /* clobber any ungetc data */ + if (HASUB (fp)) + FREEUB (fp); + fp->_flags &= ~(__SRD | __SEOF); + fp->_r = 0; + fp->_p = fp->_bf._base; + } + fp->_flags |= __SWR; + } + + /* + * Make a buffer if necessary, then set _w. + */ + /* NOT NEEDED FOR CYGNUS SPRINTF ONLY jpg */ + if (fp->_bf._base == NULL) + __smakebuf (fp); + + if (fp->_flags & __SLBF) + { + /* + * It is line buffered, so make _lbfsize be -_bufsize + * for the putc() macro. We will change _lbfsize back + * to 0 whenever we turn off __SWR. + */ + fp->_w = 0; + fp->_lbfsize = -fp->_bf._size; + } + else + fp->_w = fp->_flags & __SNBF ? 0 : fp->_bf._size; + + return 0; +} |