NOTICE000644 151361 151361 00000001764 07317131241 011443 0ustar00kpvkpv000000 000000 /******************************************************************************** * This product contains certain software code or other information * * ("AT&T Software") proprietary to AT&T Corp. ("AT&T"). * * The AT&T Software is provided to you "AS IS". YOU ASSUME TOTAL * * RESPONSIBILITY AND RISK FOR USE OF THE AT&T SOFTWARE. * * AT&T DOES NOT MAKE, AND EXPRESSLY DISCLAIMS, ANY EXPRESS OR * * IMPLIED WARRANTIES OF ANY KIND WHATSOEVER, INCLUDING, * * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR * * FITNESS FOR A PARTICULAR PURPOSE, WARRANTIES OF TITLE OR * * NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS, * * ANY WARRANTIES ARISING BY USAGE OF TRADE, COURSE OF DEALING OR * * COURSE OF PERFORMANCE, OR ANY WARRANTY THAT THE AT&T SOFTWARE * * IS "ERROR FREE" OR WILL MEET YOUR REQUIREMENTS. * * * * All rights reserved. AT&T is a registered trademark of AT&T Corp. * ********************************************************************************/ ARRANTIES OFREADME000644 151361 151361 00000003221 07501450524 011410 0ustar00kpvkpv000000 000000 This directory contains the following: Standard directories: ./bin for generated executables ./include for package header files ./lib for constructed libraries ./man for manual pages ./src for source code of packages Package directories: ./src/lib/sfio ./src/lib/vthread Before building a package, you should add the above "bin" directory to your PATH environment variable. In most shell environments, the PATH variable can be set as follows: PATH=$PATH:$PWD/bin Changing the PATH variable as shown makes available the command "iffe" which is invoked by the "make" command while it builds the package(s). Iffe (IF Features Exist) is the interpreter of the IFFE language used to define probes for any configuration parameters needed from the local platform that you are building the software on. Examples of such probes can be found in the sub-directory "features" in each package directory. The iffe command carries its own documentation. Its manual pages can be obtained in either text or html forms as follows: iffe --man iffe --html Each package directory also has a local README file that explains the local directory hierarchy and may give specific directions to build and test the respective package. Barring further package-specific instructions, below are the general steps for package building: change the PATH environment variable as described, then for each package, do: change directory to package-directory, read the README file for any specific instructions, run "make -f Makefile install". Let me know of any problems. Good luck and have fun. Phong Vo AT&T Labs - Research 180 Park Avenue Florham Park, NJ07932 kpv@research.att.com ecific directions to build and test the respective package. Barring further package-specific instructions, below are the general steps for package building: change the PATH environment variable as described, then for each package, do: change directory to package-directory, read the README file for any specific instructions, run "make -f Makefile install". include/000755 151361 151361 00000000000 07163673113 012162 5ustar00kpvkpv000000 000000 lib/000755 151361 151361 00000000000 07163673132 011306 5ustar00kpvkpv000000 000000 man/man3/sfio.3000644 151361 151361 00000260631 07323062710 013175 0ustar00kpvkpv000000 000000 .TH SFIO 3 "01 August 2001" .SH NAME \fBsfio\fR \- safe/fast string/file input/output .SH SYNOPSIS .de Tp .fl .ne 3 .TP .. .de Ss .fl .ne 3 .SS "\\$1" .. .ta 1.0i 2.0i 3.0i 4.0i 5.0i .Ss "LIBRARIES" .nf .ft 5 #include libsfio.a -lsfio libstdio.a -lstdio libsfio-mt.a -lsfio-mt libstdio-mt.a -lstdio-mt .ft 1 .fi .Ss "DATA TYPES" .nf .ft 5 Void_t; Sfoff_t; Sflong_t; Sfulong_t; Sfdouble_t; Sfio_t; Sfdisc_t; ssize_t (*Sfread_f)(Sfio_t*, Void_t*, size_t, Sfdisc_t*); ssize_t (*Sfwrite_f)(Sfio_t*, const Void_t*, size_t, Sfdisc_t*); Sfoff_t (*Sfseek_f)(Sfio_t*, Sfoff_t, int, Sfdisc_t*); int (*Sfexcept_f)(Sfio_t*, int, Void_t*, Sfdisc_t*); Sffmt_t; int (*Sffmtext_f)(Sfio_t*, Void_t*, Sffmt_t*); int (*Sffmtevent_f)(Sfio_t*, int, Void_t*, Sffmt_t*); SFIO_VERSION .ft 1 .fi .Ss "BIT FLAGS" .nf .ft 5 SF_STRING SF_READ SF_WRITE SF_APPENDWR (SF_APPEND) SF_LINE SF_SHARE SF_PUBLIC SF_MALLOC SF_STATIC SF_IOCHECK SF_WHOLE SF_MTSAFE .ft 1 .fi .Ss "OPENING/CLOSING STREAMS" .nf .ft 5 Sfio_t* sfnew(Sfio_t* f, Void_t* buf, size_t size, int fd, int flags); Sfio_t* sfopen(Sfio_t* f, const char* string, const char* mode); Sfio_t* sfpopen(Sfio_t* f, const char* cmd, const char* mode); Sfio_t* sftmp(size_t size); int sfclose(Sfio_t* f); .ft 1 .fi .Ss "THREAD SAFETY" .nf .ft 5 int sfmutex(Sfio_t* f, int type); SFMTX_LOCK SFMTX_TRYLOCK SFMTX_UNLOCK SFMTX_CLRLOCK .ft 1 .fi .Ss "INPUT/OUTPUT OPERATIONS" .nf .ft 5 int sfgetc(Sfio_t* f); int sfputc(Sfio_t* f, int c); int sfnputc(Sfio_t* f, int c, int n); int sfungetc(Sfio_t* f, int c); Sfulong_t sfgetm(Sfio_t* f, Sfulong_t max); int sfputm(Sfio_t* f, Sfulong_t v, Sfulong_t max); Sfulong_t sfgetu(Sfio_t* f); int sfputu(Sfio_t* f, Sfulong_t v); Sflong_t sfgetl(Sfio_t* f); int sfputl(Sfio_t* f, Sflong_t v); Sfdouble_t sfgetd(Sfio_t* f); int sfputd(Sfio_t* f, Sfdouble_t v); char* sfgetr(Sfio_t* f, int rsc, int type); ssize_t sfputr(Sfio_t* f, const char* s, int rsc); Sfoff_t sfmove(Sfio_t* fr, Sfio_t* fw, Sfoff_t n, int rsc); ssize_t sfread(Sfio_t* f, Void_t* buf, size_t n); ssize_t sfwrite(Sfio_t* f, const Void_t* buf, size_t n); Sfoff_t sfseek(Sfio_t* f, Sfoff_t offset, int type); Void_t* sfreserve(Sfio_t* f, ssize_t n, int type); .ft 1 .fi .Ss "DATA FORMATTING" .nf .ft 5 int sfscanf(Sfio_t* f, const char* format, ...); int sfsscanf(const char* s, const char* format, ...); int sfvsscanf(const char* s, const char* format, va_list args); int sfvscanf(Sfio_t* f, const char* format, va_list args); int sfprintf(Sfio_t* f, const char* format, ...); char* sfprints(const char* format, ...); int sfsprintf(char* s, int n, const char* format, ...); int sfvsprintf(char* s, int n, const char* format, va_list args); int sfvprintf(Sfio_t* f, const char* format, va_list args); Sffmt_t; SFFMT_LEFT SFFMT_SIGN SFFMT_BLANK SFFMT_ZERO SFFMT_THOUSAND SFFMT_LONG SFFMT_LLONG SFFMT_SHORT SFFMT_LDOUBLE SFFMT_IFLAG SFFMT_ALTER SFFMT_SKIP SFFMT_ARGPOS SFFMT_VALUE int (*Sffmtext_f)(Sfio_t* f, Void_t* v, Sffmt_t* fe); int (*Sffmtevent_f)(Sfio_t* f, int type, Void_t* v, Sffmt_t* fe); void va_copy(va_list to, va_list fr); long sffmtversion(Sffmt_t* fe, type); .ft 1 .fi .Ss "BUFFERING, SYNCHRONIZATION" .nf .ft 5 Void_t* sfsetbuf(Sfio_t* f, Void_t* buf, size_t size); int sfsync(Sfio_t* f); int sfpoll(Sfio_t** flist, int n, int timeout); Sfio_t* sfpool(Sfio_t* f, Sfio_t* poolf, int mode); int sfpurge(Sfio_t* f); .ft 1 .fi .Ss "DISCIPLINE, EVENT HANDLING" .nf .ft 5 Sfdisc_t* sfdisc(Sfio_t* f, Sfdisc_t* disc); int sfraise(Sfio_t* f, int type, Void_t* data); ssize_t sfrd(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc); ssize_t sfwr(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc); Sfoff_t sfsk(Sfio_t* f, Sfoff_t offset, int type, Sfdisc_t* disc); SF_NEW SF_READ SF_WRITE SF_SEEK SF_CLOSING (SF_CLOSE) SF_DPUSH SF_DPOP SF_DPOLL SF_DBUFFER SF_SYNC SF_PURGE SF_FINAL SF_READY SF_LOCKED SF_ATEXIT SF_EVENT .ft 1 .fi .Ss "STREAM CONTROL" .nf .ft 5 int sfresize(Sfio_t* f, Sfoff_t size); int sfset(Sfio_t* f, int flags, int i); int sfsetfd(Sfio_t* f, int fd); Sfio_t* sfstack(Sfio_t* base, Sfio_t* top); Sfio_t* sfswap(Sfio_t* f1, Sfio_t* f2); .ft 1 .fi .Ss "STREAM INFORMATION" .nf .ft 5 Sfoff_t sfsize(Sfio_t* f); Sfoff_t sftell(Sfio_t* f); ssize_t sfvalue(Sfio_t* f); int sffileno(Sfio_t* f); int sfstacked(Sfio_t* f); int sfeof(Sfio_t* f); int sferror(Sfio_t* f); int sfclrerr(Sfio_t* f); int sfclrlock(Sfio_t* f); int sfnotify(void (*notify)(Sfio_t* f, int type, int fd)); .ft 1 .fi .Ss "MISCELLANEOUS FUNCTIONS" .nf .ft 5 ssize_t sfslen(); int sfulen(Sfulong_t v); int sfllen(Sflong_t v); int sfdlen(Sfdouble_t v); ssize_t sfpkrd(int fd, Void_t* buf, size_t n, int rsc, long tm, int peek); .ft 1 .fi .Ss "FULL STRUCTURE SFIO_T" .nf .ft 5 #include #define SFNEW(buf,size,file,flags,disc) .ft 1 .fi .Ss "EXAMPLE DISCIPLINES" .nf .ft 5 #include int sfdcdio(Sfio_t* f, size_t bufsize); int sfdcdos(Sfio_t* f); int sfdcfilter(Sfio_t* f, const char* cmd); int sfdclzw(Sfio_t* f); int sfdcseekable(Sfio_t* f); int sfdcslow(Sfio_t* f); int sfdcsubstream(Sfio_t* f, Sfio_t* parent, Sfoff_t offset, Sfoff_t extent); int sfdctee(Sfio_t* f, Sfio_t* tee); int sfdcunion(Sfio_t* f, Sfio_t** array, int n); .ft 1 .fi .Ss "STDIO-COMPATIBILITY" .nf .ft 5 #include cc ... -lstdio -lsfio cc ... -lstdio-mt -lsfio-mt .ft 1 .fi .SH DESCRIPTION .PP Sfio provides I/O functions to manage buffered streams. Each Sfio stream is a \fIfile stream\fP, representing a file (see \f5open(2)\fP), or a \fIstring stream\fP, representing a memory segment. Beyond the usual I/O operations on streams, Sfio provides I/O disciplines for extended data processing, stream stacks for recursive stream processing, and stream pools for automatic data synchronization. Applications can extend the \f5sfprintf()/sfscanf()\fP functions to define their own conversion patterns as well as redefine existing ones. .PP A discipline defines analogues of the system calls \f5read(2), write(2)\fP and \f5lseek(2)\fP. Such system calls or their discipline replacements are used to process stream data. Henceforth, ``\fIsystem call\fP'' will refer to either a system call or its discipline replacement. .PP A system call is said to cause an exception if its return value is non-positive. Unless overridden by exception handlers (see \f5sfdisc()\fP), an interrupted system call (\f5errno == EINTR\fP on UNIX systems) will be automatically reinvoked to continue the ongoing operation. .PP The buffer of a stream is typically a memory segment allocated via \f5malloc(3)\fP or supplied by the application. File streams may also use memory mapping (\f5mmap(2)\fP) if that is more efficient. When memory mapping is used, the underlying file should not be truncated while the stream is active. Memory mapping can be turned off using \f5sfsetbuf()\fP. .PP There are three \fIstandard streams\fP: \f5sfstdin\fP for input (file descriptor \f50\fP on UNIX systems), \f5sfstdout\fP for normal output (file descriptor \f51\fP), and \f5sfstderr\fP for error output (file descriptor \f52\fP). .PP .Ss "LIBRARIES" .PP This version of Sfio can be built and used for both uni-threaded and multi-threaded environments. In the former case, streams are not protected from simultaneous accesses by different threads. In the latter case, a stream is typically locked with a mutex during access so that another thread trying to access the same stream will block until the mutex is released. A program that does not use multiple threads can link with \fBlibsfio.a\fP while a program that uses multiple threads should link with \fBlibsfio-mt.a\fP. The libraries \fBlibstdio.a\fP and \fBlibstdio-mt.a\fP provide corresponding Stdio functions to link with code already compiled using the native header \fBstdio.h\fP instead of the one provided by Sfio. .PP .Ss "DATA TYPES" .PP .Ss " Void_t*" This defines a type suitable to exchange data of unknown types between application and Sfio. \f5Void_t\fP is a macro defined as \f5void\fP for ANSI-C and C++ and \f5char\fP for other compilation environments. .PP .Ss " Sfoff_t" This defines an integral type suitable to address the largest possible file extent. .PP .Ss " Sfulong_t, Sflong_t, Sfdouble_t" These are respectively the largest unsigned integer, signed integer, and floating point value types on the local platform. .PP .Ss " Sfio_t" This defines the type of a stream handle. .PP .Ss " Sfdisc_t" .Ss " ssize_t (*Sfread_f)(Sfio_t*, Void_t*, size_t, Sfdisc_t*)" .Ss " ssize_t (*Sfwrite_f)(Sfio_t*, const Void_t*, size_t, Sfdisc_t*)" .Ss " Sfoff_t (*Sfseek_f)(Sfio_t*, Sfoff_t, int, Sfdisc_t*)" .Ss " int (*Sfexcept_f)(Sfio_t*, int, Void_t*, Sfdisc_t*)" \f5Sfdisc_t\fP defines a stream discipline structure. \f5Sfread_f\fP, \f5Sfwrite_f\fP and \f5Sfseek_f\fP are the types of discipline functions to replace the system calls: \f5read(2)\fP, \f5write(2)\fP and \f5lseek(2)\fP. \f5Sfexcept_f\fP is the type of an event-handling function. See \f5sfdisc()\fP for more details. .PP .Ss " Sffmt_t" .Ss " int (*Sffmtext_f)(Sfio_t*, Void_t*, Sffmt_t*)" .Ss " int (*Sffmtevent_f)(Sfio_t*, int, Void_t*, Sffmt_t*)" \f5Sffmt_t\fP defines a formatting environment that can be used to extend scanning and printing in the \f5sfprint()/sfscanf()\fP functions. \f5Sffmtext_f\fP and \f5Sffmtevent_f\fP define the types of extension functions definable in \f5Sffmt_t\fP. See \f5Sffmt_t\fP below for more details. .PP .Ss " SFIO_VERSION" This is a macro value of type \f5long int\fP that defines the current version number of Sfio. For example, the Sfio2000's version number is \f520000515L\fP (which also indicates its latest version date: 05/15/2000). .Ss "BIT FLAGS" A number of bit flags control stream operations. They are set either at stream initialization or by calling \f5sfset()\fP. Following are the flags: .Tp \f5SF_STRING\fP: The stream is memory-based. .Tp \f5SF_READ\fP, \f5SF_WRITE\fP, \f5SF_APPENDWR\fP (\f5SF_APPEND\fP): Flags \f5SF_READ\fP and \f5SF_WRITE\fP indicate readability and writability. Flag \f5SF_APPENDWR\fP asserts that the stream is a file opened in append mode (see \f5open(2)\fP and \f5fcntl(2)\fP) so that data is always output at the end of file. On systems without direct support for append mode, Sfio uses \f5lseek(2)\fP or its discipline replacement to approximate this behavior. .Tp \f5SF_LINE\fP: The stream is line-oriented. For a \f5SF_WRITE\fP stream, this means that buffered data is flushed whenever a new-line character, \f5\en\fP, is output. For a \f5SF_READ\fP stream, \f5SF_LINE\fP is only significant during calls to functions in the \f5sfscanf()\fP family. \f5SF_LINE\fP is set on initialization of any stream representing a terminal device. .Tp \f5SF_SHARE\fP, \f5SF_PUBLIC\fP: Flag \f5SF_SHARE\fP means that the underlying file descriptor is shared by independent entities (for example, multiple processes). For a seekable file stream, \f5SF_SHARE\fP means that the logical stream and the physical file positions will be made the same before a system call to perform physical I/O. There are different possibilities. If \f5SF_PUBLIC\fP is not set, the physical file position is made equal to the logical stream position. If \f5SF_PUBLIC\fP is set, there are two cases. If the physical file position has changed from its last known position, the logical stream position is made equal to the new physical file position. Finally, if the physical file location remains the same as its last known position, the physical file position is made the same as the logical stream position. For an unseekable stream (e.g., pipes or terminal devices), if possible, \f5SF_SHARE\fP means that the block and record I/O operations (\f5sfread()\fP, \f5sfwrite()\fP, \f5sfmove()\fP, \f5sfgetr()\fP, \f5sfputr()\fP, \f5sfreserve()\fP, \f5sfscanf()\fP and \f5sfvprintf()\fP) will ensure: (1) after each writing operation, the stream is synchronized and (2) each reading operation only reads the requested amount. Note, however, that (2) is not always possible without proper OS facilities such as \f5recv(2)\fP or \f5streamio(4)\fP. A standard stream that is seekable will be initialized with \f5SF_SHARE|SF_PUBLIC\fP. .Tp \f5SF_MALLOC\fP: The stream buffer was obtained via \f5malloc(3)\fP and can be reallocated or freed. .Tp \f5SF_STATIC\fP: The stream structure should not be freed when closed (\f5sfclose()\fP). This flag is used by an applications that allocate their own stream structures. Such applications must use the header file \f5sfio_t.h\fP instead of \f5sfio.h\fP. .Tp \f5SF_IOCHECK\fP: If the stream has a discipline exception handler, exceptions will be raised in \f5sfsync()\fP, \f5sfpurge()\fP or before a system call \f5read(2)\fP or \f5write(2)\fP (see \f5sfdisc()\fP). .Tp \f5SF_WHOLE\fP: This flag guarantees that data written in any single \f5sfwrite()\fP or \f5sfputr()\fP call will always be output as a whole to the output device. This is useful in certain applications (e.g., networking) where a complex object must be output without being split in different system calls. Note that the respective stream still buffers data as the buffer can accomodate. .Tp \f5SF_MTSAFE\fP: This flag indicates that the respective stream may be accessed by more than one threads. A mutex lock will be used to ensure that only one thread at a time can access the stream. Note that this flag can only be set at stream opening time (see \f5sfopen()\fP, \f5sfpopen()\fP and \f5sfnew()\fP). Certain fast macro functions such as \f5sfgetc()\fP and \f5sfputc()\fP will no longer behave as macros. Thus, an application that requires such fast macro functions should leave \f5SF_MTSAFE\fP off and performs explicit locking with \f5sfmutex()\fP. .PP .Ss "OPENING/CLOSING STREAMS" .PP .Ss " Sfio_t* sfnew(Sfio_t* f, Void_t* buf, size_t size, int fd, int flags)" This function creates or renews a stream. It returns the new stream on success and \f5NULL\fP on error. .Tp \f5f\fP: If \f5f\fP is \f5NULL\fP, a new stream is created. Otherwise, \f5f\fP is reused. In this case, if \f5flags\fP does not have \f5SF_EOF\fP, \f5f\fP shall be closed via \f5sfclose()\fP before being reused. During a stream renewal, buffer, pool and discipline stack are preserved. Note that, except for \f5SF_STATIC\fP streams, renewing a stream already closed will result in undefined behavior. .Tp \f5buf\fP, \f5size\fP: These determine a buffering scheme. See \f5sfsetbuf()\fP for more details. .Tp \f5fd\fP: If \f5SF_STRING\fP is specified in \f5flags\fP, this is ignored. Otherwise, \f5fd\fP is a file descriptor (e.g., from \f5open(2)\fP) to use for raw data I/O. Note that Sfio supports unseekable file descriptors opened for both read and write, e.g., sockets. .Tp \f5flags\fP: This is composed from \f5SF_EOF\fP and bit values defined in the \fBBIT FLAGS\fP section. Note, in particular, that a multi-threaded application should set the bit \f5SF_MTSAFE\fP to protect the new stream from being simultaneously accessed by multiple threads. .Ss " Sfio_t* sfopen(Sfio_t* f, const char* string, const char* mode)" If \f5string\fP is \f5NULL\fP and \f5f\fP is a file stream that has not been operated on, \f5sfopen()\fP changes the modes of \f5f\fP according to \f5mode\fP. In this case, \f5sfopen()\fP returns \f5f\fP on success and \f5NULL\fP on error. This somewhat unusual usage of \f5sfopen()\fP is good for resetting certain predefined modes in standard streams including \fItext/binary\fP and \fIappend\fP that are inherited from some parent process. \f5sfopen()\fP is normally used to create a new stream or renew a stream. In this case, it returns the new stream on success and \f5NULL\fP on error. Below are the meanings of the arguments: .Tp \f5f\fP: This is treated as in \f5sfnew()\fP. .Tp \f5string\fP: This is a file name or a string to perform I/O on. See above for when this is \f5NULL\fP. .Tp \f5mode\fP: This is composed from the set of letters \f5{s, r, w, +, a, b, t, x, m, u}\fP. When conflicting options are present in the same \f5mode\fP string, the last one will take effect. \f5s\fP specifies opening a string stream. \f5string\fP can be a null-terminated string or \f5NULL\fP. Specifying \f5s\fP alone is equivalent to specifying \f5sr\fP. If \f5s\fP is not specified, \f5string\fP defines a file name. \f5r\fP and \f5w\fP specify read and write modes. Write mode creates and/or truncates the given file to make an empty file. The \f5+\fP modifier indicates that the stream is opened for both read and write. \f5a\fP specifies append mode, i.e., data is always output at end of file. \f5b\fP and \f5t\fP specify binary and text modes. \f5x\fP specifies exclusive mode, i.e., a file opened for writing should not already exist. \f5m\fP specifies that the stream needs to be protected from simultaneous accesses by multiple threads. This turns on the bit flag \f5SF_MTSAFE\fP. \f5u\fP specifies that the stream is guaranteed to be accessed by only one thread at a time. The bit flag \f5SF_MTSAFE\fP is left off. The absence of option \f5m\fP is the same as the presence of option \f5u\fP. .Ss " Sfio_t* sfpopen(Sfio_t* f, const char* cmd, const char* mode)" This function opens a stream that corresponds to the coprocess \f5cmd\fP. The argument \f5mode\fP should be composed from \f5r\fP, \f5w\fP, and \f5+\fP. The argument \f5f\fP, if not \f5NULL\fP, is a stream to be renewed (see \f5sfnew()\fP). \f5sfpopen()\fP returns the new stream or \f5NULL\fP on error. The standard input/output of \f5cmd\fP is connected to the application via a pipe if the stream is opened for writing/reading. If the stream is opened for both reading and writing, there will be two different associated file descriptors, one for each type of I/O (note the effect on \f5sffileno()\fP). On opening a coprocess for writing (i.e., \f5mode\fP contains \f5w\fP or \f5+\fP), the signal handler for \f5SIGPIPE\fP in the parent application will be set to \f5SIG_IGN\fP if it is \f5SIG_DFL\fP at that time. This protects the parent application from being accidentally killed on writing to a coprocess that closes its reading end. Applications that need to detect such write errors should use disciplines and exception handlers (see \f5sfdisc()\fP). The command \f5cmd\fP is executed by an \fIinterpreter\fP which is either \f5/bin/sh\fP or an executable command defined by the environment variable \f5SHELL\fP. In either case, the interpreter is invoked with 2 arguments, respectively \f5-c\fP and the given command \f5cmd\fP. When the interpreter is \f5/bin/sh\fP or \f5/bin/ksh\fP, \f5sfpopen()\fP may execute the command \f5cmd\fP itself if there are no shell meta-characters in \f5cmd\fP. .Ss " Sfio_t* sftmp(size_t size)" This function creates a stream for temporary data. It returns the new stream or \f5NULL\fP on error. A stream created by \f5sftmp()\fP can be completely or partially memory-resident. If \f5size\fP is \f5SF_UNBOUND\fP, the stream is a pure string stream. If \f5size\fP is zero, the stream is a pure file stream. Otherwise, the stream is first created as a string stream but when its buffer grows larger than \f5size\fP or on any attempt to change disciplines, a temporary file is created. Two environment variables, \f5TMPPATH\fP and \f5TMPDIR\fP, direct where temporary files are created. \f5TMPPATH\fP, if defined, specifies a colon-separated set of directories to be used in a round-robin fashion to create files. If \f5TMPPATH\fP is undefined, \f5TMPDIR\fP can be used to specify a single directory to create files. If neither of \f5TMPPATH\fP and \f5TMPDIR\fP are defined, \f5/tmp\fP is used. .Ss " int sfclose(Sfio_t* f)" This function closes the stream \f5f\fP and frees its resources. \f5SF_STATIC\fP should be used if the stream space is to be preserved. If \f5f\fP is the base of a stream stack (see \f5sfstack()\fP), all streams on the stack are closed. If \f5f\fP is a \f5sfpopen\fP-stream, \f5sfclose()\fP waits until the associated command terminates and returns its exit status. \f5sfclose()\fP returns \f5-1\fP for failure and \f50\fP for success. \f5SF_READ|SF_SHARE\fP and \f5SF_WRITE\fP streams are synchronized before closing (see \f5sfsync()\fP). If \f5f\fP has disciplines, their exception handlers will be called twice. The first exception handler call has the \f5type\fP argument as one of \f5SF_CLOSING\fP or \f5SF_NEW\fP (see \f5sfdisc()\fP.) The latter, \f5SF_NEW\fP is used when a stream is being closed via \f5sfnew()\fP so that it can be renewed. The second call uses \f5type\fP as \f5SF_FINAL\fP and is done after all closing operations have succeeded but before the stream itself is deallocated. In either case, if the exception handler returns a negative value, \f5sfclose()\fP will immediately return this value. If the exception handler returns a positive value, \f5sfclose()\fP will immediately return a zero value. .PP .Ss "THREAD SAFETY" .PP The libraries \f5libsfio.a\fP and \f5libstdio.a\fP (providing binary compatibility to Stdio-based code) only support uni-threaded code. Multi-threaded applications should link with \f5libsfio-mt.a\fP and \f5libstdio-mt.a\fP. When this is done, certain platforms may require additional thread libraries for linkage. For example, Linux, Irix and Solaris require \f5-lpthread\fP while HPUX requires \f5-lcma\fP. Aside from linkage differences, the Sfio API remains identical in all cases. Note that unlike Stdio streams which are in thread-safe mode by default. Sfio streams can be opened in either uni-threaded or multi-threaded mode. A uni-threaded stream is more efficient than a multi-threaded one. For example, functions such as \f5sfgetc()\fP and \f5sfputc()\fP remain as macro or inline functions for a uni-threaded stream while they will act as full function calls in a multi-threaded case. The three standard streams \f5sfstdin/sfstdout/sfstderr\fP are in multi-threaded mode by default (however, see \f5sfopen()\fP for how this may be changed). Other Sfio streams are normally opened uni-threaded unless the flag \f5SF_MTSAFE\fP or the option \f5m\fP were specified. Stdio-based code can also make a Stdio stream uni-threaded by using the option \f5u\fP when opening a file. .PP .Ss "int sfmutex(Sfio_t* f, int type)" This function acquires or releases a mutex (mutually exclusive) lock on the stream \f5f\fP. It can be used by a thread to delineate a sequence of I/O operations executed together in some critical section. \f5sfmutex()\fP is implicitly used by all Sfio operations on a stream with the flag \f5SF_MTSAFE\fP. \f5sfmutex()\fP returns \f50\fP on success and some non-zero value on failure. Each stream has a lock count which starts at \f50\fP. When the count is positive, a single thread holds the stream. Only this thread can further lock or unlock the stream. A different thread attempting to acquire such a locked stream will suspend until the lock count returns to \f50\fP. Each successful locking operation increases the lock count while each successful unlocking operation decreases it, thus, allowing nesting of matching lock/unlock operations. The \f5type\fP argument of \f5sfmutex()\fP takes on the below values: .Tp \f5SFMTX_LOCK\fP: Locking a stream if it is unlocked or increasing the lock count of the stream if it is already locked by the same thread. .Tp \f5SFMTX_TRYLOCK\fP: This is the non-blocking version of \f5SFMTX_LOCK\fP. If the stream is already locked by a different thread, \f5sfmutex()\fP will immediately return with an error status. .Tp \f5SFMTX_UNLOCK\fP: Decreasing the lock count and releasing the stream when the lock count reaches 0. An attempt to unlock a stream without a previously successful lock may result in undefined behavior in certain implementations. The current Sfio implementation returns an error status. .Tp \f5SFMTX_CLRLOCK\fP: Resetting the lock count to \f50\fP and releasing the stream. As with \f5SFMTX_LOCK\fP, an attempt to clear the lock count without a previously successful lock may result in undefined behavior. .PP .Ss "INPUT/OUPUT OPERATIONS" .PP .Ss " int sfgetc(Sfio_t* f)" .Ss " int sfputc(Sfio_t* f, int c)" These functions read/write a byte from/to stream \f5f\fP. \f5sfgetc()\fP returns the byte read or \f5-1\fP on error. \f5sfputc()\fP returns \f5c\fP on success and \f5-1\fP on error. .Ss " ssize_t sfnputc(Sfio_t* f, int c, size_t n)" This function attempts to write the byte \f5c\fP to \f5f\fP \f5n\fP times. It returns the number of bytes actually written or \f5-1\fP on failure. .Ss " int sfungetc(Sfio_t* f, int c)" This function pushes the byte \f5c\fP back into \f5f\fP. If \f5c\fP matches the byte immediately before the current position in buffered data, the current position is simply backed up (note the effect on \f5sftell()\fP and \f5sfseek()\fP). There is no theoretical limit on the number of bytes that can be pushed back into a stream. Pushed back bytes not part of buffered data will be discarded on any operation that implies buffer synchronization. \f5sfungetc()\fP returns \f5c\fP on success and \f5-1\fP on failure. .Ss " Sfulong_t sfgetm(Sfio_t* f, Sfulong_t max)" .Ss " int sfputm(Sfio_t* f, Sfulong_t v, Sfulong_t max)" These functions read and write \f5Sfulong_t\fP values encoded in a portable format given that the values are at most \f5max\fP. Portability across a write architecture and a read architecture requires that the bit order in a byte is the same on both architectures and the written value is storable in an \f5Sfulong_t\fP on the read architecture. \f5sfgetm()\fP returns the value read or \f5-1\fP on error. \f5sfputm()\fP returns the number of bytes written or \f5-1\fP on error. .Ss " Sfulong_t sfgetu(Sfio_t* f)" .Ss " int sfputu(Sfio_t* f, Sfulong_t v)" These functions read and write \f5Sfulong_t\fP values in a compact variable-length portable format. Portability across a write architecture and a read architecture requires that the bit order in a byte is the same on both architectures and the written value is storable in an \f5Sfulong_t\fP on the read architecture. \f5sfgetu()\fP returns the value read or \f5-1\fP on error. \f5sfputu()\fP returns the number of bytes written or \f5-1\fP on error. See also \f5sfulen()\fP. .Ss " Sflong_t sfgetl(Sfio_t* f)" .Ss " int sfputl(Sfio_t* f, Sflong_t v)" These functions are similar to \f5sfgetu()\fP and \f5sfputu()\fP but for reading and writing (signed) \f5Sflong_t\fP values. See also \f5sfllen()\fP. .Ss " Sfdouble_t sfgetd(Sfio_t* f)" .Ss " int sfputd(Sfio_t* f, Sfdouble_t v)" These functions read and write \f5Sfdouble_t\fP values. In this case, portability depends on the input and output architectures having the same floating point value representation. Values are coded and decoded using \f5ldexp(3)\fP and \f5frexp(3)\fP so they are constrained to the sizes supported by these functions. See also \f5sfdlen()\fP. .Ss " char* sfgetr(Sfio_t* f, int rsc, int type)" This function reads a record of data ending in the record separator \f5rsc\fP. After \f5sfgetr()\fP returns, the length of the record even if it is incomplete can be retrieved with \f5sfvalue()\fP. \f5sfgetr()\fP returns the record on success and \f5NULL\fP on error. The \f5type\fP argument is composed of some subset of the below bit flags: .Tp \f5SF_STRING\fP: A null byte will replace the record separator to make the record into a C string. Otherwise, the record separator is left alone. .Tp \f5SF_LOCKR\fP: Upon successfully obtaining a record \f5r\fP, the stream will be locked from further access until it is released with a call \f5sfread(f,r,0)\fP. .Tp \f5SF_LASTR\fP: This should be used only after a failed \f5sfgetr()\fP to retrieve the last incomplete record. In this case, \f5rsc\fP is ignored. .Ss " ssize_t sfputr(Sfio_t* f, const char* s, int rsc)" This function writes the null-terminated string \f5s\fP to \f5f\fP. If \f5rsc\fP is non-negative, \f5(unsigned char)rsc\fP is output after the string. \f5sfputr()\fP returns the number of bytes written or \f5-1\fP on failure. .Ss " Sfoff_t sfmove(Sfio_t* fr, Sfio_t* fw, Sfoff_t n, int rsc)" This function moves objects from input stream \f5fr\fP to output stream \f5fw\fP. \f5sfmove()\fP returns the number of objects moved or \f5-1\fP on failure. An object is either a byte or a record. The latter is indicated by a non-negative value for the record separator character \f5rsc\fP. If \f5n\fP is negative, all of \f5fr\fP will be moved. Otherwise, \f5n\fP indicates the number of objects to move. If either \f5fr\fP or \f5fw\fP is \f5NULL\fP, it acts as if it is a stream corresponding to \f5/dev/null\fP, the UNIX device that has no read data and throws away any write data. For example, the call \f5sfmove(f,(Sfio_t*)0,(Sfoff_t)(-1),'\en')\fP simply counts the number of lines in stream \f5f\fP. .Ss " ssize_t sfread(Sfio_t* f, Void_t* buf, size_t n)" This function reads up to \f5n\fP bytes from \f5f\fP into buffer \f5buf\fP. It returns the number of bytes actually read or \f5-1\fP on error. .Ss " ssize_t sfwrite(Sfio_t* f, const Void_t* buf, size_t n)" This function writes \f5n\fP bytes from \f5buf\fP to \f5f\fP. If \f5f\fP is \f5SF_STRING\fP, and the buffer is not large enough, an \f5SF_WRITE\fP exception shall be raised. \f5sfwrite()\fP returns the number of bytes written or \f5-1\fP on failure. .Ss " Sfoff_t sfseek(Sfio_t* f, Sfoff_t offset, int type)" This function sets a new I/O position for \f5f\fP. It returns the new position or \f5-1\fP on failure. If the stream is a \f5SF_STRING\fP stream and the new address is beyond the current buffer extent, an \f5SF_SEEK\fP exception will be raised (see \f5sfdisc()\fP). The new position is determined based on \f5offset\fP and \f5type\fP which is composed from the bit flags: .Tp \f50\fP or \f5SEEK_SET\fP: \f5offset\fP is the desired position. .Tp \f51\fP or \f5SEEK_CUR\fP: \f5offset\fP is relative to the current position (see \f5SF_PUBLIC\fP below). .Tp \f52\fP or \f5SEEK_END\fP: \f5offset\fP is relative to the physical end of file. .Tp \f5SF_SHARE\fP: The stream is treated as if it has the control bit \f5SF_SHARE\fP on. This implies that a system call seek will be done to ensure that the location seeking to is valid. .Tp \f5SF_PUBLIC\fP: The stream is treated as if it has the control bit \f5SF_PUBLIC\fP on. If the physical file position has changed from its last known location, the current position is taken as the new physical position. Otherwise, the current position is the logical stream position. .Ss " Void_t* sfreserve(Sfio_t* f, ssize_t n, int type)" This function reserves a data block from the stream \f5f\fP. If \f5f\fP is a \f5SF_READ\fP stream, the data block is a segment of input data and if it is a \f5SF_WRITE\fP stream, the data block is a buffer suitable for writing output data. For consistency, if \f5f\fP is opened with \f5SF_READ|SF_WRITE\fP, it will be treated as if it is a \f5SF_READ\fP stream (see \f5sfset()\fP for forcing a particular mode.) Note that a reserved data block is only valid until a future access to the stream \f5f\fP. Thus, after a successful reservation, the application should process the reserved data block before accessing the stream \f5f\fP again. A \f5sfreserve()\fP call is successful if it can reserve a data block of size at least the absolute value of \f5n\fP when \f5n\fP is negative or exactly \f5n\fP when \f5n\fP is non-negative. After a \f5sfreserve()\fP call, whether or not it succeeds, \f5sfvalue(f)\fP can be used to obtain the size of the would-have-been available data block. \f5sfreserve()\fP returns the reserved data block on success and \f5NULL\fP on failure. When \f5type <= 0\fP and \f5f\fP is in \f5SF_READ\fP mode, even if \f5sfreserve()\fP fails to obtain a large enough data block, the I/O position of \f5f\fP will be advanced by the size of the available data block (but only up to \f5n\fP if \f5n\fP is positive.) Such a partial data block can be obtained using a subsequent \f5sfreserve()\fP call with \f5type\fP being \f5SF_LASTR\fP. When \f5type > 0\fP, there are two cases: .Tp \f5type == SF_LASTR\fP: The last partially reserved data block, if any, is returned. This call should be used only after a failed \f5sfreserve()\fP call. The second argument to \f5sfreserve()\fP will be ignored. .Tp \f5type == 1\fP or \f5type == SF_LOCKR\fP: The I/O position of stream \f5f\fP remains unchanged after the \f5sfreserve()\fP call. In addition, if the reservation is successful, \f5f\fP will be locked from further access. As appropriate to the stream type (\f5SF_READ\fP, \f5SF_WRITE\fP or both), \f5f\fP can be unlocked later with one of \f5sfread(f,rsrv,size)\fP or \f5sfwrite(f,rsrv,size)\fP where \f5rsrv\fP is the reserved data block and \f5size\fP is the amount of data to be consumed. For example, if \f5f\fP is a locked \f5SF_READ\fP stream, the call \f5sfread(f,rsrv,0)\fP will reopen the stream without advancing the stream I/O position. Finally, a stream opened for both reading and writing can release the lock with either call (with associated operational semantics!) For example, the below code modify data in place: .nf .ft 5 rsrv = sfreserve(f, 10, 1); memset(rsrv, 0, 10); sfwrite(f, rsrv, 10); .ft 1 .fi Note that when \f5f\fP is \f5SF_SHARE\fP and unseekable, \f5sfreserve()\fP will attempt to peek at input data without consuming it. This allows processes that share unseekable file descriptors (e.g., pipes or devices) to properly share input data. Since peeking on unseekable file descriptors is not uniformly supported on all platforms, \f5sfreserve()\fP may fail in some cases. Finally, since \f5SF_SHARE\fP is automatically on for \f5sfstdin\fP, applications that do not share \f5sffileno(sfstdin)\fP with other processes should turn this bit off to reduce system calls. .ne 6 .PP .Ss "DATA FORMATTING" .PP Data printing and scanning are done via the \f5sfprintf()\fP and \f5sfscanf()\fP family of functions. These functions are similar to their ANSI-C \f5fprintf()\fP and \f5fscanf()\fP counterparts. However, the Sfio versions have been extended for both portability and generality. In particular, a notion of a formatting environment stack is introduced. Each formatting element on the stack defines a separate \fIformatting pair\fP of a format specification string, \f5char* format\fP (the usual second argument in the formatting functions), and an argument list, \f5va_list args\fP (the third argument in functions \f5sfvprintf()\fP and \f5sfvscanf()\fP). A formatting environment element may also specify extension functions to obtain or assign arguments and to provide new semantics for pattern processing. To simplify the description below, whenever we talk about an argument list, unless noted otherwise, it is understood that this means either the true argument list when there is no extension function or the action to be taken by such a function in processing arguments. The manipulation of the formatting environment stack is done via the pattern \f5!\fP discussed below. .Ss "%! and Sffmt_t" The pattern \f5%!\fP manipulates the formatting environment stack to (1) change the top environment to a new environment, (2) stack a new environment on top of the current top, or (3) pop the top environment. The bottom of the environment stack always contains a virtual environment with the original formatting pair and without any extension functions. The top environment of a stack, say \f5fe\fP, is automatically popped whenever its format string is completely processed. In this case, its event-handling function (if any) is called as \f5(*eventf)(f,SF_FINAL,NIL(Void_t*),fe)\fP. The top environment can also be popped by giving an argument \f5NULL\fP to \f5%!\fP or by returning a negative value in an extension function. In these cases, the event-handling function is called as \f5(*eventf)(f,SF_DPOP,form,fe)\fP where \f5form\fP is the remainder of the format string. A negative return value from the event handling function will prevent the environment from being popped. A formatting environment is a structure of type \f5Sffmt_t\fP which contains the following elements: .nf .ft 5 Sffmtext_f extf; /* extension processor */ Sffmtevent_f eventf; /* event handler */ char* form; /* format string to stack */ va_list args; /* corresponding arg list */ int fmt; /* pattern being processed */ ssize_t size; /* object size */ int flags; /* formatting control flags */ int width; /* width of field */ int precis; /* precision required */ int base; /* conversion base */ char* t_str; /* extfdata string */ int n_str; /* length of t_str */ .ft 1 .fi The first four elements of \f5Sffmt_t\fP must be defined by the application before the structure is passed to a formatting function. The two function fields should not be changed during processing. Other elements of \f5Sffmt_t\fP are set by the respective formatting function before it calls the extension function \f5Sffmt_t.extf\fP and, subsequently, can be modified by this function to redirect formatting or scanning. For example, consider a call from a \f5sfprintf()\fP function to process an unknown pattern \f5%t\fP (which we may take to mean ``time'') based on a formatting environment \f5fe\fP. \f5fe->extf\fP may reset \f5fe->fmt\fP to `\f5d\fP' upon returing to cause \f5sfprintf()\fP to process the value being formatted as an integer. Below are the fields of \f5Sffmt_t\fP: .Tp \f5extf\fP: \f5extf\fP is a function to extend scanning and formatting patterns. Its usage is discussed below. .Tp \f5eventf\fP: This is a function to process events as discussed earlier. .Tp \f5form\fP and \f5args\fP: This is the formatting pair of a specification string and corresponding argument list. When an environment \f5fe\fP is being inserted into the stack, if \f5fe->form\fP is \f5NULL\fP, the top environment is changed to \f5fe\fP and its associated extension functions but processing of the current formatting pair continues. On the other hand, if \f5fe->form\fP is not \f5NULL\fP, the new environment is pushed onto the stack so that pattern processing will start with the new formatting pair as well as any associated extension functions. During processing, whenever \f5extf\fP is called, \f5form\fP and \f5args\fP will be set to the current values of the formatting pair in use. .Tp \f5fmt\fP: This is set to the pattern being processed or one of '.', 'I', '('. .Tp \f5size\fP: This is the size of the object being processed. .Tp \f5flags\fP: This is a collection of bits defining the formatting flags specified for the pattern. The bits are: \f5SFFMT_LEFT\fP: Flag \f5-\fP in \f5sfprintf()\fP. \f5SFFMT_SIGN\fP: Flag \f5+\fP in \f5sfprintf()\fP. \f5SFFMT_BLANK\fP: Flag \fIspace\fP in \f5sfprintf()\fP. \f5SFFMT_ZERO\fP: Flag \f50\fP in \f5sfprintf()\fP. \f5SFFMT_THOUSAND\fP: Flag \f5'\fP in \f5sfprintf()\fP. \f5SFFMT_LONG\fP: Flag \f5l\fP in \f5sfprintf()\fP and \f5sfscanf()\fP. \f5SFFMT_LLONG\fP: Flag \f5ll\fP in \f5sfprintf()\fP and \f5sfscanf()\fP. \f5SFFMT_SHORT\fP: Flag \f5h\fP in \f5sfprintf()\fP and \f5sfscanf()\fP. \f5SFFMT_LDOUBLE\fP: Flag \f5L\fP in \f5sfprintf()\fP and \f5sfscanf()\fP. \f5SFFMT_IFLAG\fP: flag \f5I\fP in \f5sfprintf()\fP and \f5sfscanf()\fP. \f5SFFMT_ALTER\fP: Flag \f5#\fP in \f5sfprintf()\fP and \f5sfscanf()\fP. \f5SFFMT_SKIP\fP: Flag \f5*\fP in \f5sfscanf()\fP. \f5SFFMT_ARGPOS\fP: This indicates argument processing for \f5pos$\fP. \f5SFFMT_VALUE\fP: This is set by \f5fe->extf\fP to indicate that it is returning a value to be formatted or the address of an object to be assigned. .Tp \f5width\fP: This is the field width. .Tp \f5precis\fP: This is the precision. .Tp \f5base\fP: This is the conversion base. .Tp \f5t_str\fP and \f5n_str\fP: This is the type string and its size. .Ss " int (*Sffmtext_f)(Sfio_t* f, Void_t* v, Sffmt_t* fe)" This is the type of the extension function \f5fe->extf\fP to process patterns and arguments. Arguments are always processed in order and \f5fe->extf\fP is called exactly once per argument. Note that, when \f5pos$\fP (below) is not used anywhere in a format string, each argument is used exactly once per a corresponding pattern. In that case, \f5fe->extf\fP is called as soon as the pattern is recognized and before any scanning or formatting. On the other hand, when \f5pos$\fP is used in a format string, an argument may be used multiple times. In this case, all arguments shall be processed in order by calling \f5fe->extf\fP exactly once per argument before any pattern processing. This case is signified by the flag \f5SFFMT_ARGPOS\fP in \f5fe->flags\fP. In addition to the predefined formatting patterns and other application-defined patterns, \f5fe->extf\fP may be called with \f5fe->fmt\fP being one of `\f5(\fP' (left parenthesis), `\f5.\fP' (dot), and `\f5I\fP'. The left parenthesis requests a string to be used as the \f5extfdata\fP string discussed below. In this case, upon returning, \f5fe->extf\fP should set the \f5fe->size\fP field to be the length of the string or a negative value to indicate a null-terminated string. The `\f5I\fP' requests an integer to define the object size. The dot requests an integer for width, precision, base, or a separator. In this case, the \f5fe->size\fP field will indicate how many dots have appeared in the pattern specification. Note that, if the actual conversion pattern is 'c' or 's', the value \f5*form\fP will be one of these characters. .Tp \f5f\fP: This is the input/output stream in the calling formatting function. During a call to \f5fe->extf\fP, the stream shall be unlocked so that \f5fe->extf\fP can read from or write to it as appropriate. .Tp \f5v\fP: For both \f5sfscanf()\fP and \f5sfprintf()\fP functions, \f5v\fP points to a location suitable for storing any scalars or pointers. On return, \f5fe->extf\fP treats \f5v\fP as discussed below. .Tp \f5fe\fP: This is the current formatting environment. .PP The return value \f5rv\fP of \f5fe->extf\fP directs further processing. There are two cases. When \f5pos$\fP is present, a negative return value means to ignore \f5fe\fP in further argument processing while a non-negative return value is treated as the case \f5rv == 0\fP below. When \f5pos$\fP is not present, \f5fe->extf\fP is called per argument immediately before pattern processing and its return values are treated as below: .Tp \f5rv < 0:\fP The environment stack is immediately popped. .Tp \f5rv == 0:\fP The extension function has not consumed (in a scanning case) or output (in a printing case) data out of or into the given stream \f5f\fP. The fields \f5fmt\fP, \f5flags\fP, \f5size\fP, \f5width\fP, \f5precis\fP and \f5base\fP of \f5fe\fP shall direct further processing. For \f5sfprintf()\fP functions, if \f5fe->flags\fP has the bit \f5SFFMT_VALUE\fP, \f5fe->extf\fP should have set \f5*v\fP to the value to be processed; otherwise, a value should be obtained from the argument list. Likewise, for \f5sfscanf()\fP functions, \f5SFFMT_VALUE\fP means that \f5*v\fP should have a suitable address; otherwise, an address to assign value should be obtained from the argument list. When \f5pos$\fP is present, if \f5fe->extf\fP changes \f5fe->fmt\fP, this pattern shall be used regardless of the pattern defined in the format string. On the other hand, if \f5fe->fmt\fP is unchanged by \f5fe->extf\fP, the pattern in the format string is used. In any case, the effective pattern should be one of the standardly defined pattern. Otherwise, it shall be treated as unmatched. .Tp \f5rv > 0:\fP The extension function has accessed the stream \f5f\fP to the extent of \f5rv\fP bytes. Processing of the current pattern ceases except that, for scanning functions, if \f5fe->flags\fP does not contain the bit \f5SFFMT_SKIP\fP, the assignment count shall increase by 1. .Ss "void va_copy(va_list to, va_list fr)" This macro function portably copies the argument list \f5fr\fP to the argument list \f5to\fP. It should be used to set the field \f5Sffmt_t.args\fP. .Ss "long sffmtversion(Sffmt_t* fe, int type)" This macro function initializes the formatting environment \f5fe\fP with a version number if \f5type\fP is non-zero. Otherwise, it returns the current value of the version number of \f5fe\fP. This is useful for applications to find out when the format of the structure \f5Sffmt_t\fP changes. Note that the version number corresponds to the Sfio version number which is defined in the macro value \f5SFIO_VERSION\fP. .Ss " int sfprintf(Sfio_t* f, const char* format, ...)" .Ss " char* sfprints(const char* format, ...)" .Ss " int sfsprintf(char* s, int n, const char* format, ...)" .Ss " int sfvsprintf(char* s, int n, const char* format, va_list args)" .Ss " int sfvprintf(Sfio_t* f, const char* format, va_list args)" These functions format output data. \f5sfprintf()\fP and \f5sfvprintf()\fP write to output stream \f5f\fP. \f5sfsprintf()\fP and \f5sfvsprintf()\fP write to buffer \f5s\fP which is of size \f5n\fP. \f5sfprints()\fP constructs output in some Sfio-defined buffer. \f5sfvprintf()\fP is the underlying primitive for the other functions. Except for \f5sfprints()\fP which returns a null-terminated string or \f5NULL\fP, other functions return the number of output bytes or \f5-1\fP on failure. The length of string constructed by \f5sfprints()\fP, \f5sfsprintf()\fP, or \f5sfvsprintf()\fP can be retrieved by \f5sfslen()\fP. .PP The standard patterns are: \f5n, s, c, %, h, i, d, p, u, o, x, X, g, G, e, E, f\fP and \f5!\fP. Except for \f5!\fP which shall be described below, see the ANSI-C specification of \f5fprintf(3)\fP for details on the other patterns. Let \f5z\fP be some pattern type. A formatting pattern is defined as below: .nf .ft 5 %[pos$][flag][width][.precision[.base]][(extfdata)]z .ft 1 .fi .Tp \f5pos$\fP: A pattern can specify which argument in the argument list to use. This is done via \f5pos$\fP where \f5pos\fP is the argument position. Arguments are numbered so that the first argument after \f5format\fP is at position 1. If \f5pos\fP is not specified, the argument following the most recently used one will be used. The pattern \f5%!\fP (see below) cannot be used subsequent to a usage of \f5pos$\fP. Doing so may cause unexpected behaviors. .Tp \f5flag\fP: The flag characters are \f5h\fP, \f5hh\fP, \f5l\fP, \f5ll\fP, \f5L\fP, \f5I\fP, \f5j\fP, \f5t\fP, \f5z\fP, \f5\-\fP, \f5+\fP, \fIspace\fP, \f50\fP, \f5'\fP and \f5#\fP. Flag \f5I\fP defines the size or type of the object being formatted. There are two cases: (1) \f5I\fP by itself and (2) \f5I\fP followed by either a decimal number or `*'. In the first case, for integer and floating point patterns, the object type is taken to be the largest appropriate type (i.e., one of \f5Sflong_t\fP, \f5Sfulong_t\fP or \f5Sfdouble_t\fP). For conversion specifiers \f5s\fP and \f5c\fP, the flag is ignored. In the second case, a given decimal value would define a size while `*' would cause the size to be obtained from the argument list. Then, if the conversion specifier is \f5s\fP, this size defines the length of the string or strings being formatted (see the discussion of \f5base\fP below). For integer and floating point patterns, the size is used to select a type from one of the below lists as indicated by the conversion specifier: .nf .ft 5 Sflong_t, long, int, short Sfulong_t, unsigned long, unsigned int, unsigned short Sfdouble_t, double, float .ft 1 .fi The selection algorithm always matches types from left to right in any given list. Although selection is generally based on sizes in bytes, for compatibility with Microsoft-C, the size 64 is matched with an appropriate type with the same number of bits, if any. If the given size does not match any of the listed types, it shall match one of \f5int\fP, \f5unsigned int\fP, and \f5double\fP as defined by the formatting pattern. Below are a few examples of using the \f5I\fP flag. The first example prints an \f5Sflong_t\fP integer. This example is actually not portable and only works on platforms where \f5sizeof(Sflong_t)\fP is 8. The second example shows how to that portably. The third example specifies printing a string of length 16. This length shall be used regardless of whether or not the given string is shorter or longer than 16. The last example shows the use of the pattern \f5%n\fP to assign the amount of data already output into a \f5short\fP integer \f5n_output\fP. .nf .ft 5 sfprintf(sfstdout,"%I8d", Sflong_obj); sfprintf(sfstdout,"%I*d", sizeof(Sflong_obj), Sflong_obj); sfprintf(sfstdout,"%I*s", 16, s); sfprintf(sfstdout,"%d%I*n", 1001, sizeof(short), &n_output); .ft 1 .fi Flags \f5h\fP, \f5l\fP, and \f5L\fP are the ANSI-C conventions to select the types of input objects. For example, \f5%hd\fP indicates a \f5short int\fP while \f5%ld\fP indicates a \f5long int\fP. Flag \f5hh\fP addresses the byte value types, i.e., \f5char\fP and \f5unsigned char\fP. Flags \f5z\fP, \f5t\fP and \f5j\fP address respectively the types \f5size_t\fP, \f5ptrdiff_t\fP and \f5Sflong_t\fP. Flags \f5ll\fP and \f5L\fP address respectively the largest integer and floating value types, i.e., \f5Sfulong_t\fP, \f5Sflong_t\fP, and \f5Sfdouble_t\fP. Flag \f5-\fP left-justifies data within the field (otherwise, right-justification). Flag \f5+\fP means that a signed conversion will always begin with a plus or minus sign. Flag \fIspace\fP is ignored if \f5+\fP is specified; otherwise, it means that if the first character of a signed conversion is not a sign or if the result is empty, a space will be prepended. Flag \f50\fP means padding with zeros on the left. Flag \f5'\fP outputs thousands-separator used by the current locale. \f5setlocale(3)\fP should have been used to set the desired locale. Flag \f5#\fP indicates an alternative format processing. For \f5%o\fP, the first digit is always a zero. For \f5%x\fP and \f5%X\fP, a non-zero result will have a prefix \f50x\fP or \f50X\fP. For \f5%e\fP, \f5%E\fP, \f5%f\fP, \f5%g\fP, and \f5%G\fP, the result always contains a decimal point. For \f5%g\fP and \f5%G\fP, trailing zeros will not be removed. For \f5%d\fP, \f5%i\fP and \f5%u\fP, the form is \fIbase#number\fP where \fIbase\fP is the conversion base and \fInumber\fP is represented by digits for this \fIbase\fP. For example, a base \f52\fP conversion with \f5%#..2d\fP for \f510\fP is \f52#1010\fP instead of \f51010\fP as printed with \f5%..2d\fP. .Tp \f5width\fP: This defines the width of the printing field. A value to be printed will be justified and padded if necessary to fill out the field width. .Tp \f5precis\fP: After a first dot appears, an integral value defines a precision. For floating point value patterns, precision is the number of precision digits. For \f5%c\fP, precision defines the number of times to repeat the character being formatted. For \f5%s\fP, precision defines the maximum number of characters to output. .Tp \f5base\fP: This is defined after exactly two dots have appeared. For \f5%i\fP, \f5%d\fP, and \f5%u\fP, \f5base\fP should be an integer value in the inclusive range \f5[2,64]\fP and defines a conversion base. If \f5base\fP is not in this range, it is defined to be \f510\fP. The digits to represent numbers are: .nf .ft 5 01234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ @_ .ft 1 .fi For \f5%s\fP and \f5%c\fP, \f5base\fP defines a separator. Then, for \f5%s\fP, the input argument is taken to be a NULL-terminated array of strings while, for \f5%c\fP, this is a null-terminated array of characters. The strings or characters will be formatted one of a time based on the usual width and precision rules. After each formatted string or character, except for the last one, the separator \f5base\fP is output if it is a non-zero. There are further restrictions on the syntax of \f5%s\fP and \f5%c\fP when a separator is defined. Below are the legitimate sequences for \f5%s\fP and \f5%c\fP after the second dot: .nf \f5 s c\fP \f5 *s *c\fP \f5 \fP\fIz\fP\f5s \fP\fIz\fP\f5c\fP .fi In the first case, no separator is defined so \f5base\fP is set to zero. In the second case, \f5base\fP is obtained from the argument list. In the third case, the character \fIz\fP must be non-alphanumeric and \f5base\fP will be set to this character. The below example shows both the call and the result of printing a \f5NULL\fP-terminated array of three strings \f5apple\fP, \f5orange\fP, and \f5grape\fP: .nf .ft 5 sfprintf(sfstdout,"|%8..:s|",list); | apple: orange: grape| .ft 1 .fi .Tp \f5(extfdata)\fP: This defines a string \f5extfdata\fP to be passed to the extension function \f5Sffmt_t.extf\fP. Parentheses shall be balanced. If \f5extfdata\fP is \f5*\fP, the string is obtained from the argument list. .PP .Ss " int sfscanf(Sfio_t* f, const char* format, ...)" .Ss " int sfsscanf(const char* s, const char* format, ...)" .Ss " int sfvsscanf(const char* s, const char* format, va_list args)" .Ss " int sfvscanf(Sfio_t* f, const char* format, va_list args)" These functions scan data items. \f5sfscanf()\fP scans from the input stream \f5f\fP while \f5sfsscanf()\fP and \f5sfvsscanf()\fP scan from the null-terminated string \f5s\fP. \f5sfvscanf()\fP is the underlying primitive that performs the actual scanning. Item types are determined from patterns in string \f5format\fP. These functions return the number of items successfully scanned or \f5-1\fP on error. .PP A white space character (blank, tab, or new-line) in \f5format\fP normally matches a maximal sequence of input white space characters. However, if the input stream is in \f5SF_LINE\fP mode (see \f5sfset()\fP), a new-line character only matches white spaces up to an input new-line character. This is useful to avoid blocking when scanning typed inputs. .PP The standard scan patterns are: \f5i, d, u, o, x, X, p, n, f, e, E, g, G, c, %, s, []\fP and \f5!\fP. Except for \f5!\fP which shall be described below, see the ANSI-C specification of \f5fscanf(3)\fP for details on other patterns. Let \f5z\fP be some pattern type. A formatting pattern is specified as below: .nf .ft 5 %[*][pos$][width][.width.base][(extfdata)][flag]z .ft 1 .fi .Tp \f5pos$\fP: A pattern can specify which argument in the argument list to use. This is done via \f5pos$\fP where \f5pos\fP is the argument position. Arguments are numbered so that the first argument after \f5format\fP is at position 1. If \f5pos\fP is not specified, the argument following the most recently used one will be used. The pattern \f5%!\fP (see below) cannot be used subsequent to a usage of \f5pos$\fP. .Tp \f5*:\fP This discards the corresponding scanned item. .Tp \f5width\fP and \f5base\fP: \f5width\fP defines the maximum number of bytes to scan and \f5base\fP defines the base of an integral value being scanned. The `.' (dot) notation also allows specifying a `*' (star) to obtain the value from the argument list. The below example specifies scanning 4 bytes to obtain the value of an integer in base 10. At the end of scanning, the variable \f5v\fP should have the value \f51234\fP. .nf .ft 5 sfsscanf("12345678","%.*.*d", 4, 10, &v); .ft 1 .fi .Tp \f5(extfdata)\fP: This defines a string \f5extfdata\fP to be passed to the extension function \f5Sffmt_t.extf\fP. Parentheses shall be balanced. If \f5extfdata\fP is \f5*\fP, the string is obtained from the argument list. .Tp \f5flag:\fP This is \f5#\fP, \f5I\fP, or some sequence of \f5h\fP, \f5l\fP, and \f5L\fP. Flag \f5#\fP is significant for pattern \f5%i\fP and \f5%[\fP. For \f5%i\fP, it means that the \f5#\fP symbol does not have its usual meaning in an input sequence \f5base#value\fP. For example, the scanning result of \f5%#i\fP on input \f52#1001\fP is \f52\fP and the next \f5sfgetc()\fP call will return \f5#\fP. For \f5%[\fP, if the next character in the input stream does not match the given scan set of characters, \f5#\fP causes a match to a null string instead of a failure. Flag \f5I\fP defines the size or type of the object being formatted. There are two cases: (1) \f5I\fP by itself and (2) \f5I\fP followed by either a decimal number or `*'. In the first case, for integer and floating point patterns, the object type is taken to be the largest appropriate type (i.e., one of \f5Sflong_t\fP, \f5Sfulong_t\fP or \f5Sfdouble_t\fP). For string patterns such as \f5%s\fP, the flag is ignored. In the second case, a given decimal value would define a size while `*' would cause the size to be obtained from the argument list. For string patterns such as \f5%s\fP or \f5%[\fP, this size defines the length of the buffer to store scanned data. Specifying a buffer size only limits the amount of data copied into the buffer. Scanned data beyond the buffer limit will be discarded. For integer and floating point patterns, the size is used to select a type from one of the below lists as indicated by the conversion specifier: .nf .ft 5 Sflong_t, long, int, short Sfulong_t, unsigned long, unsigned int, unsigned short Sfdouble_t, double, float .ft 1 .fi The selection algorithm always matches types from left to right in any given list. Although selection is generally based on sizes in bytes, for compatibility with Microsoft-C, the size 64 is matched with an appropriate type with the same number of bits, if any. If the given size does not match any of the listed types, it shall match one of \f5int\fP, \f5unsigned int\fP, and \f5double\fP as indicated by the formatting pattern. Below are examples of using the \f5I\fP flag. The first example scans a 64-bit integer. The second scans some floating point value whose size is explicitly computed and given. The last example scans a string into a buffer with the given size 128. Note that if the scanned string is longer than 127, only the first 127 bytes shall be copied into the buffer. The rest of the scanned data shall be discarded. .nf .ft 5 sfscanf(sfstdin,"%I64d", &int64_obj); sfscanf(sfstdin,"%I*f", sizeof(float_obj), &float_obj); sfscanf(sfstdin,"%I*s", 128, buffer); .ft 1 .fi Flags \f5h\fP, \f5l\fP, and \f5L\fP are the ANSI-C conventions for indicating the type of a scanned element. For example, \f5%hd\fP means scanning a \f5short int\fP. The flags \f5ll\fP and \f5L\fP mean respectively scanning an integer or a floating point value with largest size (i.e, \f5Sflong_t\fP or \f5Sfdouble_t\fP). .PP The \f5%i\fP, \f5%d\fP and \f5%u\fP patterns scan numbers in bases from \f52\fP to \f564\fP. \f5%i\fP scans integral values in self-describing formats. Except for octal, decimal and hexadecimal numbers with the usual formats, numbers in general bases are assumed to be of the form: \fIbase#value\fP where \fIbase\fP is a number in base 10 and \fIvalue\fP is a number in the given base. For example, \f52#1001\fP is the binary representation of the decimal value \f59\fP. If \fIbase\fP is \f536\fP or less, the digits for \fIvalue\fP can be any combination of \f5[0-9], [a-z], [A-Z]\fP where upper and lower case digits are not distinguishable. If \fIbase\fP is larger than \f536\fP, the set of digits is: .nf .ft 5 0123456789 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ @_ .ft 1 .fi .PP .Ss "BUFFERING, SYNCHRONIZATION" .PP .Ss " Void_t* sfsetbuf(Sfio_t* f, Void_t* buf, size_t size)" This function changed the buffering scheme for \f5f\fP. Except for buffer inquiry (the case \f5size == 0\fP), \f5f\fP will be synchronized before any buffer modification. If a new buffer is successfully set and the old buffer has not been freed, \f5sfsetbuf()\fP returns the old buffer. Otherwise, it returns \f5NULL\fP. After a \f5sfsetbuf()\fP call, \f5sfvalue()\fP returns the size of the returned buffer. .Tp \f5size == SF_UNBOUND\fP: Sfio will pick a suitable buffer size. If \f5buf\fP is \f5NULL\fP, Sfio will also pick a suitable buffering scheme (such as memory mapping.) If \f5buf\fP is not \f5NULL\fP, its actual value is ignored but the buffer will be allocated via \f5malloc(3)\fP. This can be used to avoid memory mapping. .Tp \f5size > 0\fP: This is the suggested size to use for buffering or memory mapping. If \f5buf\fP is \f5NULL\fP, Sfio will pick a suitable buffering scheme as discussed above. If \f5buf\fP is not \f5NULL\fP, then \f5buf\fP and \f5size\fP determine a buffer of the given size. .Tp \f5size == 0\fP: If \f5buf\fP is \f5NULL\fP, the stream will be unbuffered. If \f5buf\fP is not \f5NULL\fP, \f5sfsetbuf()\fP simply returns the stream buffer. In this case, no attempt will be made to synchronize the stream. .Ss " int sfsync(Sfio_t* f)" This function synchronizes the logical and physical views of stream \f5f\fP. It returns a negative value for failure and \f50\fP for success. For a \f5SF_WRITE\fP stream, synchronization means to write out any buffered data. For a seekable \f5SF_READ\fP file stream, the physical file position is aligned with the logical stream position and, if \f5SF_SHARE\fP is on, buffered data is discarded. If \f5f\fP is \f5NULL\fP, all streams are synchronized. If \f5f\fP is the base of a stream stack (see \f5sfstack()\fP), all stacked streams are synchronized. Note that a stacked stream can only be synchronized this way. If \f5f\fP is in a pool (see \f5sfpool()\fP) but not being the head, the pool head is synchronized. If \f5f\fP has flag \f5SF_IOCHECK\fP, the \f5SF_SYNC\fP event is raised before and after synchronization. See \f5sfdisc()\fP for details. .Ss " int sfpoll(Sfio_t** flist, int n, int timeout)" This function polls a set of streams to see if I/O operations can be performed on them without blocking. This is useful for multiplexing I/O over a set of streams. If a stream has a discipline, the exception function may be called before and after the stream is polled (see \f5sfdisc()\fP for details). After a successful \f5sfpoll()\fP call, for each ready stream \f5f\fP, \f5sfvalue(f)\fP returns a bit combination of \f5SF_READ\fP and \f5SF_WRITE\fP to tell which I/O mode is available. If \f5SF_READ\fP is available, an attempt to read a byte will not block. If \f5SF_WRITE\fP is available, an attempt to flush will not block. \f5sfpoll()\fP returns the number of ready streams or \f5-1\fP on failure. .Tp \f5flist\fP and \f5n\fP: \f5flist\fP is an array of \f5n\fP streams to be polled. Upon return, ready streams are moved to the front of \f5flist\fP in the same relative order. .Tp \f5timeout\fP: This defines an elapse time in milliseconds to wait to see if any stream is ready for I/O. If \f5timeout\fP is negative, \f5sfpoll()\fP will block until some stream become ready. Note that \f5SF_STRING\fP and normal file streams never block and are always ready for I/O. If a stream with discipline is being polled and its readiness is as yet undetermined (e.g., empty buffer,) the discipline exception function will be called with \f5SF_DPOLL\fP before querying the operating system. .Ss " Sfio_t* sfpool(Sfio_t* f, Sfio_t* poolf, int mode)" This function manipulates pools of streams. In a pool, only one stream is at the head and can have buffered data. All other streams in the pool will be synchronized. A stream becomes head when it is used for some I/O operation. \f5sfpool()\fP returns \f5NULL\fP on failure. .Tp \f5f\fP and \f5poolf\fP: If \f5f\fP is \f5NULL\fP, \f5sfpool()\fP simply returns the head of the pool containing \f5poolf\fP. If \f5f\fP is not \f5NULL\fP and \f5poolf\fP is \f5NULL\fP, \f5f\fP is deleted from its pool. In this case, if no other stream from the same pool can become head, \f5sfpool()\fP will return \f5NULL\fP; otherwise, it returns some stream from the remainder of the pool. If both \f5f\fP and \f5poolf\fP are not \f5NULL\fP, \f5f\fP is moved from its current pool (if any) into the same pool with \f5poolf\fP. In this case, \f5poolf\fP is returned. .Tp \f5mode\fP: If \f5poolf\fP is already in a pool, \f5mode\fP is ignored. Otherwise, \f5mode\fP should be \f50\fP or \f5SF_SHARE\fP. A \f5SF_SHARE\fP pool contains streams with \f5SF_WRITE\fP mode. In addition, on change to a new head stream, buffered write data of the current head is transferred to the new head. .Ss " int sfpurge(Sfio_t* f)" This function discards all buffered data unless \f5f\fP is a \f5SF_STRING\fP stream. Note that if \f5f\fP is a \f5SF_READ\fP stream based on an unseekable device, purged data will not be recoverable. If \f5f\fP is a \f5sfpopen\fP-stream opened for both read and write, data of both the read and write pipe ends will be purged (see \f5sfset()\fP to selectively turn off read or write mode if one set of data is to be preserved.) After purging, if \f5f\fP has flag \f5SF_IOCHECK\fP, the event \f5SF_PURGE\fP is raised. \f5sfpurge()\fP returns \f5-1\fP for failure and \f50\fP for success. .PP .Ss "DISCIPLINE, EVENT-HANDLING" .PP A file stream uses the system calls \f5read(2)\fP, \f5write(2)\fP and \f5lseek(2)\fP to read, write and position in the underlying file. Disciplines enable application-defined I/O methods including exception handling and data pre/post-processing. .Ss " Sfdisc_t* sfdisc(Sfio_t* f, Sfdisc_t* disc)" Each stream has a discipline stack whose bottom is a virtual discipline representing the actual system calls. \f5sfdisc()\fP manipulates the discipline stack of stream \f5f\fP. \f5f\fP will be synchronized before any discipline stack manipulation. After a successful discipline stack manipulation, the stream I/O position (see \f5sfseek()\fP and \f5sftell()\fP) and extent (see \f5sfsize()\fP) are updated to reflect that defined by the top discipline. If \f5disc\fP is \f5SF_POPDISC\fP or \f5(Sfdisc_t*)0\fP, the top element of the stack, if any, is popped and its address is returned. Otherwise, \f5disc\fP is pushed onto the discipline stack. In this case, if successful, \f5sfdisc()\fP returns the discipline that was pushed down. \f5sfdisc()\fP returns \f5NULL\fP on failure. Note that a discipline can be used only on one stream at a time. An application should take care to allocate different discipline structures for use with different streams. A discipline structure is of the type \f5Sfdisc_t\fP which contains the following public fields: .nf .ft 5 Sfread_f readf; Sfwrite_f writef; Sfseek_f seekf; Sfexcept_f exceptf; .ft 1 .fi .PP The first three fields of \f5Sfdisc_t\fP specify alternative I/O functions. If any of them is \f5NULL\fP, it is inherited from a discipline pushed earlier on the stack. Note that a file stream always has \f5read(2)\fP, \f5write(2)\fP, \f5lseek(2)\fP and \f5NIL(Sfexcept_f)\fP as the \fIlogical bottom discipline\fP. Arguments to I/O discipline functions have the same meaning as that of the functions \f5sfrd()\fP, \f5sfwr()\fP and \f5sfsk()\fP described below. .PP The exception function, \f5(*exceptf)()\fP announces exceptional events during I/O operations. It is called as \f5(*exceptf)(Sfio_t* f, int type, Void_t* value, Sfdisc_t* disc)\fP. Unless noted otherwise, the return value of \f5(*exceptf)()\fP is used as follows: .Tp \f5<0\fP: The on-going operation shall terminate. .Tp \f5>0\fP: If the event was raised due to an I/O error, the error has been repaired and the on-going operation shall continue normally. For some events, e.g., \f5SF_DPOLL\fP, the return value may also have additional meanings. .Tp \f5=0\fP: The on-going operation performs default actions with respect to the raised event. For example, on a reading error or reaching end of file, the top stream of a stack will be popped and closed and the on-going operation continue with the new top stream. .PP The argument \f5type\fP of \f5(*exceptf)()\fP identifies the particular exceptional event: .Tp \f5SF_LOCKED\fP: The stream cannot be accessed. Note that this lock state is not related to the mutex lock that protects a stream from multiple accesses by different threads (see section THREAD SAFETY). Rather, the stream was frozen by certain operations such as \f5sfreserve()\fP or \f5sfstack()\fP. Thus, a stream can be in this state even if the application is uni-threaded. .Tp \f5SF_READ\fP, \f5SF_WRITE\fP: These events are raised around reading and writing operations. If \f5SF_IOCHECK\fP is on, \f5SF_READ\fP and \f5SF_WRITE\fP are raised immediately before \f5read(2) and write(2)\fP calls. In this case, \f5*((ssize_t*)value)\fP is the amount of data to be processed. The return value of \f5(*exceptf)()\fP, if negative, indicates that the stream is not ready for I/O and the calling operation will abort with failure. If it is positive, the stream is ready for I/O but the amount should be restricted to the amount specified by this value. If the return value is zero, the I/O operation is carried out normally. \f5SF_READ\fP and \f5SF_WRITE\fP are also raised on operation failures. In such a case, \f5*((ssize_t*)value)\fP is the return value from the failed operation. .Tp \f5SF_SEEK\fP: This event is raised when a seek operation fails. .Tp \f5SF_NEW\fP, \f5SF_CLOSING\fP (\f5SF_CLOSE\fP), \f5SF_FINAL\fP: These events are raised during a stream closing. \f5SF_NEW\fP is raised for a stream about to be closed to be renewed (see \f5sfnew()\fP). \f5SF_CLOSING\fP is raised for a stream about to be closed. \f5SF_FINAL\fP is raised after a stream has been closed and before its space is to be destroyed (see \f5sfclose()\fP). For these events, a non-zero return value from \f5(*exceptf)()\fP causes \f5sfclose()\fP to return immediately with the same value. .Tp \f5SF_DPUSH\fP, \f5SF_DPOP\fP, \f5SF_DBUFFER\fP: Events \f5SF_DPUSH\fP and \f5SF_DPOP\fP are raised when a discipline is about to be pushed or popped. \f5(Sfdisc_t*)value\fP is the to-be top discipline, if any. A stream buffer is always synchronized before pushing or popping a discipline. If this synchronization fails, \f5SF_DBUFFER\fP will be raised with \f5*((size_t*)value)\fP being the amount of buffered data. If the return value of \f5exceptf\fP is positive, the push or pop operation will continue normally; otherwise, \f5sfdisc()\fP returns failure. .Tp \f5SF_DPOLL\fP: This event is raised by \f5sfpoll()\fP to see if the stream is ready for I/O. \f5*((int*)value)\fP indicates a time-out interval to wait. A negative return value from the exception function means blocking. A zero return value means that \f5sfpoll()\fP should query the underlying file descriptor. A positive return value means non-blocking. In addition, this value will be a bit combination of \f5SF_READ\fP and \f5SF_WRITE\fP to indicate what I/O modes are ready. .Tp \f5SF_READY\fP: This event is raised by \f5sfpoll()\fP for each ready stream. The third argument to the event handler is an integer composed with the two bits \f5SF_READ\fP and \f5SF_WRITE\fP to indicate which I/O modes are ready. .Tp \f5SF_SYNC\fP, \f5SF_PURGE\fP: If \f5SF_IOCHECK\fP is set, these events are raised respectively for a \f5sfsync()\fP or \f5sfpurge()\fP call. In each case, the respective event is raised once before the appropriate operation (synchronization or purging) with \f5((int)value)\fP being \f51\fP and once after with \f5((int)value)\fP being \f50\fP. Note that \f5sfsync()\fP is called for each \f5SF_WRITE\fP or \f5SF_SHARE|SF_READ\fP stream on closing. .Tp \f5SF_ATEXIT\fP: This event is raised for each open stream before the process exits. .Ss " int sfraise(Sfio_t* f, int type, Void_t* data)" This function calls all exception handlers of stream \f5f\fP with the event \f5type\fP and associated \f5data\fP. If an exception handler returns a non-zero value, \f5sfraise()\fP immediate returns the same value. Application-defined events should start from the value \f5SF_EVENT\fP so as to avoid confusion with system-defined events, \f5sfraise()\fP returns \f50\fP on success and \f5-1\fP on failure. .Ss " ssize_t sfrd(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)" .Ss " ssize_t sfwr(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)" .Ss " Sfoff_t sfsk(Sfio_t* f, Sfoff_t offset, int type, Sfdisc_t* disc)" These functions provides safe methods for a discipline I/O function to invoke earlier discipline I/O functions and to properly handle exceptions. They should not be used in any other context. \f5sfrd()\fP and \f5sfwr()\fP return the number of bytes read or written. \f5sfsk()\fP returns the new seek position. On error, all three functions return a negative value which should be \f5-1\fP or the value returned by the exception handler. .PP .Ss "STREAM CONTROL" .PP .Ss " int sfresize(Sfio_t* f, Sfoff_t size)" This function resizes the stream \f5f\P so that its extent is \f5size\fP. If the stream corresponds to a file, the file size is set to \f5size\fP via the system call \f5ftruncate()\fP. When a stream is made larger, the new data space is filled with zero's. \f5sfresize()\fP returns \f50\fP on success and a negative value on failure. .Ss " int sfset(Sfio_t* f, int flags, int set)" This function sets control flags for the stream \f5f\fP. It returns the previous set of flags or \f50\fP on error. Settable flags are: \f5SF_READ\fP, \f5SF_WRITE\fP, \f5SF_IOCHECK\fP, \f5SF_LINE\fP, \f5SF_SHARE\fP, \f5SF_PUBLIC\fP, \f5SF_MALLOC\fP and \f5SF_STATIC\fP. Note that \f5SF_READ\fP and \f5SF_WRITE\fP can be turned on or off only if the stream was opened as \f5SF_READ|SF_WRITE\fP. Turning off one of them means that the stream is to be treated exclusively in the other mode. It is not possible to turn off both. If legal, an attempt to turn on either \f5SF_READ\fP or \f5SF_WRITE\fP will cause the stream to be in the given I/O mode. .Tp \f5set == 0:\fP If \f5flags\fP is zero, the current set of flags is simply returned. Note that when a stream is first opened, not all of its flags are initialized yet (more below). If \f5flags\fP is non-zero, an attempt is made to turn off the specified flags. .Tp \f5set != 0:\fP If \f5flags\fP is zero, the stream is initialized if not yet done so. Then the current set of flags is returned. If \f5flags\fP is non-zero, an attempt is made to turn on the specified flags. .Ss " int sfsetfd(Sfio_t* f, int fd)" This function changes the file descriptor of \f5f\fP. Before a change is realized, \f5(*notify)(f,SF_SETFD,newfd)\fP (see \f5sfnotify()\fP) is called. \f5sfsetfd()\fP returns \f5-1\fP on failure and the new file descriptor on success. .Tp \f5fd >= 0\fP: If the current file descriptor is non-negative, it will be changed using \f5dup(3)\fP to a value larger or equal to \f5fd\fP. Upon a successful change, the previous file descriptor will be closed. If the current file descriptor is negative, it will be set to \f5fd\fP and the stream will be reinitialized. .Tp \f5fd < 0\fP: The stream is synchronized (see \f5sfsync()\fP) and its file descriptor will be set to this value. Then, except for \f5sfclose()\fP, the stream will be inaccessible until a future \f5sfsetfd()\fP call resets the file descriptor to a non-negative value. Thus, \f5sfsetfd(f,-1)\fP can be used to avoid closing the file descriptor of \f5f\fP when \f5f\fP is closed. .Ss " Sfio_t* sfstack(Sfio_t* base, Sfio_t* top)" This function stacks or unstacks stream. Every stream stack is identified by a base stream via which all I/O operations are performed. However, an I/O operation always takes effect on the top stream. If the top stream reaches the end of file or has an unrecoverable error condition, it is automatically popped and closed (see also \f5sfdisc()\fP for alternative handling of these conditions). .Tp \f5base\fP: This is the base stream of the stack. If it is \f5NULL\fP, \f5sfstack()\fP does nothing and returns \f5top\fP. .Tp \f5top\fP: If this is \f5SF_POPSTACK\fP or \f5(Sfio_t*)0\fP, the stack is popped and \f5sfstack()\fP returns the popped stream. Otherwise, \f5top\fP is pushed on top of the stack identified by \f5base\fP and \f5sfstack()\fP returns the \f5base\fP stream. .Ss " Sfio_t* sfswap(Sfio_t* f1, Sfio_t* f2)" This function swaps contents of \f5f1\fP and \f5f2\fP. This fails if either stream is in a stream stack but not being a base stream. If \f5f2\fP is \f5NULL\fP, a new stream is constructed as a duplicate of \f5f1\fP. \f5sfswap()\fP returns \f5f2\fP or \f5f1\fP duplicate on success and \f5NULL\fP on failure. .PP .Ss "STREAM INFORMATION" .PP .Ss " Sfoff_t sfsize(Sfio_t* f)" This function returns the size of stream \f5f\fP (see \f5sfnew()\fP). If \f5f\fP is not seekable or if its size is not determinable, \f5sfsize()\fP returns \f5-1\fP. .Ss " Sfoff_t sftell(Sfio_t* f)" This function returns the current I/O position in stream \f5f\fP. Note that if \f5f\fP is \f5SF_APPEND\fP and a writing operation was just performed, the current I/O position is at the physical end of file. If \f5f\fP is unseekable, \f5sftell\fP returns the number of bytes read from or written to \f5f\fP. See also \f5sfungetc()\fP. .Ss " ssize_t sfvalue(Sfio_t* f)" This function returns the string or buffer length for \f5sfreserve()\fP, \f5sfsetbuf()\fP, and \f5sfgetr()\fP. .Ss " int sffileno(Sfio_t* f)" This function returns the file descriptor of stream \f5f\fP. .Ss " int sfstacked(Sfio_t* f)" This function returns a non-zero value if stream \f5f\fP has been stacked. .Ss " int sfeof(Sfio_t* f)" .Ss " int sferror(Sfio_t* f)" .Ss " int sfclrerr(Sfio_t* f)" \f5sfeof()\fP tells whether or not the stream has an end-of-file condition. \f5sferror()\fP tells whether or not the stream has an error condition. \f5sfclrerr()\fP clears both end-of-file and error conditions. The end-of-file and error conditions are also cleared on an I/O operation. .Ss " int sfclrlock(Sfio_t* f)" This function restores the stream back to a normal state. This means clearing locks and possibly throwing away unprocessed data. As such, this operation is unsafe and should be used with care. For example, it may be used before a long jump (\f5longjmp(3)\fP) out of some discipline I/O function to restore the internal stream states. \f5sfclrlock()\fP returns the current set of flags. .Ss " int sfnotify((void(*)notify)(Sfio_t*, int, int) )" This sets a function \f5(*notify)()\fP to be called as \f5(*notify)(f,type,file)\fP on various stream events. Arguments \f5f\fP and \f5file\fP are stream and related file descriptor. Argument \f5type\fP indicates the reason for the call: .Tp \f5SF_NEW\fP: \f5f\fP is being opened and \f5file\fP is the underlying file descriptor. .Tp \f5SF_CLOSING\fP (\f5SF_CLOSE\fP): \f5f\fP and \f5file\fP are being closed. .Tp \f5SF_SETFD\fP: The file descriptor of \f5f\fP is being changed to \f5file\fP (see \f5sfsetfd()\fP.) .Tp \f5SF_READ\fP: An attempt to change \f5f\fP to read mode failed. .Tp \f5SF_WRITE\fP: An attempt to change \f5f\fP to write mode failed. .PP .Ss "MISCELLANEOUS FUNCTIONS" .PP .Ss " ssize_t sfslen()" This function returns the length of a string just constructed by \f5sfsprintf()\fP or \f5sfprints()\fP. See also \f5sfvalue()\fP. .Ss " int sfulen(Sfulong_t v)" .Ss " int sfllen(Sflong_t v)" .Ss " int sfdlen(Sfdouble_t v)" These functions return respectively the number of bytes required to code the \f5Sfulong_t\fP, \f5Sflong_t\fP or \f5Sfdouble_t\fP value \f5v\fP by \f5sfputu()\fP, \f5sfputl()\fP or \f5sfputd()\fP. .Ss " ssize_t sfpkrd(int fd, char* buf, size_t n, int rsc, long tm, int action)" This function acts directly on the file descriptor \f5fd\fP. It does a combination of peeking on incoming data and a time-out read. Upon success, it returns the number of bytes received. A return value of \f50\fP means that the end-of-file condition has been detected. A negative value represents an error. .Tp \f5buf\fP, \f5n\fP: These define a buffer and its size to read data into. .Tp \f5rsc\fP: If \f5>=0\fP, this defines a record separator. See \f5action\fP for detail. .Tp \f5tm\fP: If \f5>=0\fP, this defines a time interval in milliseconds to wait for incoming data. .Tp \f5action\fP: When \f5rsc >= 0\fP, the absolute value of \f5action\fP, \fIr\fP, determines the number of records to be read. If \f5action > 0\fP, \f5sfpkrd()\fP will peek on incoming data but will not read past it. Therefore, a future \f5sfpkrd()\fP or \f5read(2)\fP will see the same data again. If \f5action == 0\fP, \f5sfpkrd()\fP will not peek. If \f5action < 0\fP, there are two cases: if \f5rsc < 0\fP, \f5sfpkrd()\fP reads \f5n\fP bytes; otherwise, exactly \fIr\fP records will be read. Note that, in the last case, reading records from an unseekable device may be slow if the underlying platform does not allow peeking on such a device. .PP .Ss "FULL STRUCTURE SFIO_T" .PP .Ss " #include " Most applications based on Sfio only need to include the header file \f5sfio.h\fP which defines an abbreviated \f5Sfio_t\fP structure without certain fields private to Sfio. However, there are times (e.g., debugging) when an application may require more details about the full \f5Sfio_t\fP structure. In such cases, the header file \f5sfio_t.h\fP can be used in place of \f5sfio.h\fP. Note that an application doing this will become sensitive to changes in the internal architecture of Sfio. .Ss " #define SFNEW(buf,size,file,flags,disc)" This macro function is defined in \f5sfio_t.h\fP for use in static initialization of an \f5Sfio_t\fP structure. It requires five arguments: .Tp \f5buf, size\fP: These define a buffer and its size. .Tp \f5file\fP: This defines the underlying file descriptor if any. .Tp \f5flags\fP: This is composed from bit flags described above. .Tp \f5disc\fP: This defines a discipline if any. .PP .Ss "EXAMPLE DISCIPLINES" .PP The below functions create disciplines and insert them into the given streams \f5f\fP. These functions return \f50\fP on success and \f5-1\fP on failure. .Ss "int sfdcdio(Sfio_t* f, size_t bufsize)" This creates a discipline that uses the direct IO feature available on file systems such as SGI's XFS to speed up IO. The argument \f5bufsize\fP suggests a buffer size to use for data transfer. .Ss "int sfdcdos(Sfio_t* f)" This creates a discipline to read DOS text files. It basically transforms pairs of \er\en to \en. .Ss "int sfdcfilter(Sfio_t* f, const char* cmd)" This creates a discipline that sends data from \f5f\fP to the given command \f5cmd\fP to process, then reads back the processed data. .Ss "int sfdclzw(Sfio_t* f)" This creates a discipline that would decompress data in \f5f\fP. The stream \f5f\fP should have data from a source compressed by the Unix \fBcompress\fP program. .Ss "int sfdcseekable(Sfio_t* f)" This creates a discipline that makes an unseekable reading stream seekable. .Ss "int sfdcslow(Sfio_t* f)" This creates a discipline that makes all Sfio operations return immediately on interrupts. This is useful for dealing with slow devices. .Ss "int sfdcsubstream(Sfio_t* f, Sfio_t* parent, Sfoff_t offset, Sfoff_t extent)" This creates a discipline that makes \f5f\fP acts as if it corresponds exactly to the subsection of \f5parent\fP starting at \f5offset\fP with size \f5extent\fP. .Ss "int sfdctee(Sfio_t* f, Sfio_t* tee)" This creates a discipline that copies to the stream \f5tee\fP any data written to \f5f\fP. .Ss "int sfdcunion(Sfio_t* f, Sfio_t** array, int n)" This creates a discipline that makes \f5f\fP act as if it is the concatenation of the \f5n\fP streams given in \f5array\fP. .PP .Ss "STDIO-COMPATIBILITY" .PP Sfio provides compatibility functions for all various popular Stdio implementations at source and binary level. The source Stdio-compatibility interface provides the header file \f5stdio.h\fP that defines a set of macros or inlined functions to map Stdio calls to Sfio ones. This mapping may benignly extend or change the meaning of certain original Stdio operations. For example, the Sfio's version of \f5popen()\fP allows a coprocess to be opened for both reading and writing unlike the original call which only allows a coprocess to be opened for a single mode. Similarly, the Sfio's \f5fopen()\fP call can be used to create string streams in addition to file streams. The standard streams \f5stdin\fP, \f5stdout\fP and \f5stderr\fP are mapped via \f5#define\fP to \f5sfstdin\fP, \f5sfstdout\fP and \f5sfstderr\fP. The latter are typically declared of the type \f5Sfio_t*\fP. Certain older Stdio applications require these to be declared as addresses of structures so that static initializations of the sort ``\f5FILE*\ f\ =\ stdin;\fP'' would work. Such applications should use the compile time flag \f5SF_FILE_STRUCT\fP to achieve the desired effect. .PP The binary Stdio-compatibility libraries, \f5libstdio.a\fP and \f5libstdio-mt.a\fP, provide complete implementations of Stdio functions suitable for linking applications already compiled with native header \f5stdio.h\fP. These functions are also slightly altered or extended as discussed above. .PP Below are the supported Stdio functions: .PP .nf .ft 5 FILE* fopen(const char* file, const char* mode); FILE* freopen(const char* file, const char* mode, FILE* stream); FILE* fdopen(int filedesc, const char* mode); FILE* popen(const char* command, const char* mode); FILE* tmpfile(); int fclose(FILE* stream); int pclose(FILE* stream); void flockfile(FILE* stream) int ftrylockfile(FILE* stream) void funlockfile(FILE* stream) void setbuf(FILE* stream, char* buf); int setvbuf(FILE* stream, char* buf, int mode, size_t size); void setbuffer(FILE* stream, char* buf, size_t size); int setlinebuf(FILE* stream); int fflush(FILE* stream); int fpurge(FILE* stream); int fseek(FILE* stream, long offset, int whence); void rewind(FILE* stream); int fgetpos(FILE* stream, fpos_t* pos); int fsetpos(FILE* stream, fpos_t* pos); long ftell(FILE* stream); int getc(FILE* stream); int fgetc(FILE* stream); int getchar(void); int ungetc(int c, FILE* stream); int getw(FILE* stream); char* gets(char* s); char* fgets(char* s, int n, FILE* stream); size_t fread(Void_t* ptr, size_t size, size_t nelt, FILE* stream); int putc(int c, FILE* stream); int fputc(int c, FILE* stream); int putchar(int c); int putw(int w, FILE* stream); int puts(const char* s, FILE* stream); int fputs(const char* s, FILE* stream); size_t fwrite(const Void_t* ptr, size_t size, size_t nelt, FILE* stream); int fscanf(FILE* stream, const char* format, ...); int vfscanf(FILE* stream, const char* format, va_list args); int _doscan(FILE* stream, const char* format, va_list args); int scanf(const char* format, ...); int vscanf(const char* format, va_list args); int sscanf(const char* s, const char* format, ...); int vsscanf(const char* s, const char* format, va_list args); int fprintf(FILE* stream, const char* format, ...); int vfprintf(FILE* stream, const char* format, va_list args); int _doprnt(FILE* stream, const char* format, va_list args); int printf(const char* format, ...); int vprintf(const char* format, va_list args); int sprintf(const char* s, const char* format, ...); int snprintf(const char* s, int n, const char* format, ...); int vsprintf(const char* s, const char* format, va_list args); int vsnprintf(const char* s, int n, const char* format, va_list args); int feof(FILE* stream); int ferror(FILE* stream); int clearerr(FILE* stream); .ft 1 .fi .PP .Ss "RECENT CHANGES" .PP A few exception types have been added. In particular, exception handlers shall be raised with \f5SF_LOCKED\fP on accessing a stream frozen either by an ongoing operation or a previous operation (e.g., \f5sfgetr()\fP). Before a process exits, the event \f5SF_ATEXIT\fP is raised for each open stream. .PP A number of disciplines were added for various processing functions. Of interests are disciplines to use the direct I/O feature on IRIX6.2, read DOS text files, and decompress files compressed by Unix \fIcompress\fP. .PP Various new stream and function flags have been added. For example, the third argument of \f5sfgetr()\fP is now a set of bit flags and not just a three-value object. However, the old semantics of this argument of \f5sfgetr()\fP is still supported. .PP The \f5sfopen()\fP call has been extended so that sfopen(f,NULL,mode) can be used to changed the mode of a file stream before any I/O operations. This is most useful for changing the modes of the standard streams. .PP The buffering strategy has been significantly enhanced for streams that perform many seek operations. Also, the handling of stream and file positions have been better clarified so that applications that share file descriptors across streams and/or processes can be sure that the file states will be consistent. .PP The strategy for mapping between Sfio and Stdio streams in the binary compatibility package has been significantly enhanced for efficiency. For most platforms, the mapping is now constant time per look-up. .PP The \f5SF_BUFCONST\fP flag was deleted. This is largely unused anyway. .PP The library is now thread-safe. This is based largely on Posix pthread mutexes. .PP The functions \f5sfgetm()\fP and \f5sfputm()\fP were added to encode unsigned integer values with known ranges. .PP The flag \f5SF_APPEND\fP is identical to \f5SF_APPENDWR\fP. However it conflicts with a different token of the same name defined in the system header \f5stat.h\fP of BSDI Unix systems. On such systems, we shall not define \f5SF_APPEND\fP and this symbol may be removed in a future release. .PP Similarly, the exception \f5SF_CLOSE\fP is identical to \f5SF_CLOSING\fP. However it conflicts with a different token of the same name defined in the system header \f5socket.h\fP of AIX Unix systems. On such systems, we shall not define \f5SF_CLOSE\fP and this symbol may be removed in a future release. .PP The printing and scanning functions were extended to handle multibyte characters and to conform to the C99 standard. .PP The function \f5sfpoll()\fP was rehauled to make it useful for writing servers that must commnunicate with multiple streams without blocking. .SH AUTHORS Kiem-Phong Vo, kpv@research.att.com, .br David G. Korn, dgk@research.att.com, and .br Glenn S. Fowler, gsf@research.att.com. s. On such systems, we shall not define \f5SF_CLOSE\fP and this symbol may be removed in a future releaman/man3/vthread.3000644 151361 151361 00000020324 07211007160 013655 0ustar00kpvkpv000000 000000 .TH LIBVTHREAD 3 .SH NAME \fBVthread\fR \- portable threads .SH SYNOPSIS .de Tp .fl .ne 2 .TP .. .de Ss .fl .ne 2 .SS "\\$1" .. .de Cs .nf .ft 5 .. .de Ce .ft 1 .fi .. .ta 1.0i 2.0i 3.0i 4.0i 5.0i .Cs #include .Ce .Ss "VTHREAD TYPES" .Cs Void_t*; Vthread_t; Vtmutex_t; Vtonce_t; .Ce .Ss "THREAD MANAGEMENT" .Cs Vthread_t* vtopen(Vthread_t* vt, int flags); int vtclose(Vthread_t* vt); int vtset(Vthread_t* vt, int type, Void_t* val); Vthread_t* vtself(); int vtrun(Vthread_t* vt, Void_t*(*startf)(Void_t*), Void_t* arg); int vtwait(Vthread_t* vt); int vtkill(Vthread_t* vt); .Ce .Ss "MUTEX MANAGEMENT" .Cs Vtmutex_t* vtmtxopen(Vtmutex_t* mtx, int flags); int vtmtxclose(Vtmutex_t* mtx); int vtmtxlock(Vtmutex_t* mtx); int vtmtxtrylock(Vtmutex_t* mtx); int vtmtxunlock(Vtmutex_t* mtx); int vtmtxclrlock(Vtmutex_t* mtx); .Ce .Ss "EXECUTING EXACTLY ONCE" .Cs #define VTONCE_INITDATA int vtonce(Vtonce_t* once, void(*func)() ); .Ce .Ss "GETTING STATUS" .Cs int vtstatus(Vthread_t* vt); int vterror(Vthread_t* vt); int vtmtxerror(Vtmutex_t* mtx); int vtonceerror(Vtonce_t* once); .Ce .SH DESCRIPTION .PP \fIVthread\fP provides a portable set of functions to create and manage threads within a single process. The restriction to a single process allows portable and efficient implementations of mutexes on top of native primitives available on different platforms. The mutex interface is kept simple by restricting mutexes to be of the recursive or counting type. .PP .Ss "VTHREAD TYPES" .PP .Ss " Void_t*" This type is used to pass objects with unknown type between different code variety. \f5Void_t\fP is defined as \f5void\fP for ANSI-C and C++ and \f5char\fP for other compilation environments. .PP .Ss " Vthread_t" This is the type of a thread handle. .PP .Ss " Vtmutex_t" This is the type of a mutex. .PP .Ss " Vtonce_t" This is the type of a structure used to execute certain actions exactly once per process no matter how many attempts to do so are made from different threads. .PP .Ss "THREAD MANAGEMENT" .PP .Ss " Vthread_t* vtopen(Vthread_t* vt, int flags)" This function creates a new thread handle or renews an existing one. It returns the resulting thread handle or \f5NULL\fP on error. .Tp \f5vt\fP: If \f5vt\fP is \f5NULL\fP, a new thread handle is created. In this case, the bits \f5VT_INIT\fP and \f5VT_FREE\fP will be added to \f5flags\fP (below). If \f5vt\fP is not \f5NULL\fP, \f5vt\fP is an existing thread to be renewed. In this case, if the thread is running, it will be waited until execution finishes before renewing. .Tp \f5flags\fP: The bit \f5VT_INIT\fP indicates that the handle should be initialized. Otherwise, the handle is assumed to have been initialized already. The bit \f5VT_FREE\fP indicates that the space occupied by the handle was obtained via \f5malloc()\fP and can be freed when the handle is closed. .PP .Ss " int vtclose(Vthread_t* vt)" This function closes the handle \f5vt\fP and also frees it if appropriate (see vtopen()). If currently running, closing is done only after execution finishes. This function returns \f50\fP on success and \f5-1\fP on error. .PP .Ss " int vtset(Vthread_t* vt, int type, Void_t* val);" This function sets certain attributes of the thread \f5vt\fP. It returns \f50\fP on success and \f5-1\fP on error. .Tp \f5type\fP: This currently can be only \f5VT_STACK\fP to set the execution stack size for the thread \f5vt\fP. In the case, the stack size is \f5(size_t)val\fP. .PP .Ss " Vthread_t* vtself();" This function returns the handle of the calling thread. .PP .Ss " int vtrun(Vthread_t* vt, Void_t*(*startf)(Void_t*), Void_t* arg);" This function starts the thread running with the call \f5(*startf)(arg)\fP. It returns \f50\fP on success and \f5-1\fP on error. .PP .Ss " int vtwait(Vthread_t* vt)" This function waits for the termination of the execution of the thread \f5vt\fP if currently running. It returns \f50\fP on success and \f5-1\fP on error. .PP .Ss " int vtkill(Vthread_t* vt)" This function cancels the execution of the thread \f5vt\fP if currently running. It returns \f50\fP on success and \f5-1\fP on error. .PP .Ss "MUTEX MANAGEMENT" Mutexes are recursive. That is, each mutex maintains a lock count. A thread that successfully locks a mutex can relock it as often as needed. Each successful locking attempt increases the lock count by one. Only the thread that owns the lock on a mutex can unlock it. Each successful unlocking attempt decreases the lock count by one. .PP .Ss " Vtmutex_t* vtmtxopen(Vtmutex_t* mtx, int flags);" This function creates a new mutex or renews an existing mutex structure. In the latter case, the mutex structure should not be currently locked or some undefined behavior will result. The function returns the resulting mutex or \f5NULL\fP on error. .Tp \f5mtx\fP: If \f5mtx\fP is \f5NULL\fP, a new mutex is created. In this case, the bits \f5VT_INIT\fP and \f5VT_FREE\fP will be added to \f5flags\fP (below). If \f5mtx\fP is not \f5NULL\fP, \f5mtx\fP is an existing mutex to be renewed. .Tp \f5flags\fP: The bit \f5VT_INIT\fP indicates that the mutex should be initialized. Otherwise, the mutex is assumed to have been initialized already. The bit \f5VT_FREE\fP indicates that the space occupied by the mutex was obtained via \f5malloc()\fP and can be freed when the mutex is closed. .PP .Ss " int vtmtxclose(Vtmutex_t* mtx);" This function clears the lock count of the mutex \f5mtx\fP, then closes it. It returns \f50\fP on success and \f5-1\fP on error. .PP .Ss " int vtmtxlock(Vtmutex_t* mtx);" This function attempts to lock the mutex \f5mtx\fP. If the lock is currently clear, the current thread becomes its owner. Then, only this thread can relock the mutex as many times as desired. Any attempt to lock \f5mtx\fP from a different thread will block. This function returns \f50\fP on success and \f5-1\fP on error. .PP .Ss " int vtmtxtrylock(Vtmutex_t* mtx);" This function attempts to lock the mutex \f5mtx\fP without blocking. It returns \f50\fP on success and \f5-1\fP on error. .PP .Ss " int vtmtxunlock(Vtmutex_t* mtx);" This function attempts to decrease the lock count on the mutex \f5mtx\fP by one. Only the thread owning \f5mtx\fP can unlock it. Any other attempt will result in failure. The function returns \f50\fP on success and \f5-1\fP on error. .PP .Ss " int vtmtxclrlock(Vtmutex_t* mtx);" This function attempts to clear the lock on the mutex \f5mtx\fP, i.e., to reset the lock count to zero. Only the thread owning \f5mtx\fP can clear it. Any other attempt will result in failure. The function returns \f50\fP on success and \f5-1\fP on error. .PP .Ss "EXECUTING EXACTLY ONCE" .PP .Ss " VTONCE_INITDATA" This macro is used to initialize a \f5Vtonce_t\fP structure in the following manner: .nf .ft 5 Vtonce_t once = VTONCE_INITDATA; .ft 1 .fi .PP .Ss " int vtonce(Vtonce_t* once, void(*func)() );" This function ensures that the call \f5(*func)()\fP is made exactly once per process and \f5once\fP structure regardless of how many attempts are made. It is useful for initialization of shared data across threads. It returns \f50\P on success and \f5-1\fP on error. .PP .Ss "GETTING STATUS" .PP .Ss " Void_t* vtstatus(Vthread_t* vt);" This function returns the exit status of \f5vt\fP after execution finishes. .PP .Ss " int vterror(Vthread_t* vt);" This function returns the error status of \f5vt\fP after a failed operation. .PP .Ss " int vtmtxerror(Vtmutex_t* mtx);" This function returns the error status of \f5mtx\fP after a failed operation. .PP .Ss " int vtonceerror(Vtonce_t* once);" This function returns the error status of \f5once\fP after a failed operation. .PP .SH "IMPLEMENTATION NOTES" .PP The current Vthread implementation is sufficient for use in writing thread-safe libraries (e.g., the Sfio library). It still lacks useful facilities such as condition variables, private thread data, etc. Some future versions will support these. .PP The library has been ported to popular Unix versions including various flavors of BSD, LINUX, SOLARIS, IRIX, HPUX and Dave Korn's UWIN. For HPUX, it has only been tested on version B.11.00. Threads on older versions of HPUX do not compile/work properly to be usable under Vthread. .PP .SH AUTHOR Kiem-Phong Vo, kpv@research.att.com read-safe libraries (e.g., the Sfio library). It still lacks useful facilities such as condition variables, private thread data, etc. Some future versions will support these. .PP The library has been ported to popular Unix versions including various flavors of BSD, LINUX, SOLARIS, IRIX, HPUX and Davbin/iffe000755 151361 151361 00000224501 07476550714 012162 0ustar00kpvkpv000000 000000 USAGE_LICENSE="[-author?Glenn Fowler ][-author?Phong Vo ][-copyright?Copyright (c) 1994-2002 AT&T Corp.][-license?http://www.research.att.com/sw/license/ast-open.html][--catalog?INIT]" # Glenn Fowler & Phong Vo # AT&T Labs Research # # test if feature exists # this script written to make it through all sh variants # # NOTE: .exe a.out suffix and [\\/] in path patterns for dos/nt case $-:$BASH_VERSION in *x*:[0123456789]*) : bash set -x is broken :; set +ex ;; esac command=iffe version=2002-02-14 # update in USAGE too # pkg() # package { case $1 in '<') shift ;; *) return ;; esac case $1 in X|X11*) i="openwin" case $1 in X) set X11 ;; esac case $1 in X11) case $# in 1) set $1 6 5 4 ;; esac ;; esac ;; *) i= ;; esac pth="{ usr . - . contrib local $i - . share - . lib - $1" i=$1 while : do shift case $# in 0) break ;; esac case $1 in '>') shift; break ;; esac pth="$pth ${i}R$1 ${i}.$1" done pth="$pth . } $*" } is() # op name { case $verbose in 1) case $complete in 1) failure ;; esac oo=$1 shift case $1 in ?*) yy=is ii=$1 complete=1 case $oo in cmd) mm="a command" ;; dat) mm="a library data symbol" ;; dfn) mm="a macro with extractable value" ;; exp) mm="true" ;; hdr) mm="a header" ;; lcl) mm="a native header" ;; key) mm="a reserved keyword" ;; lib) mm="a library function" ;; LIB) case $2 in "") mm="a library" ;; *) ii=$*; mm="a library group" ;; esac ;; mac) mm="a macro" ;; mem) mm="a member of $2" ;; mth) mm="a math library symbol" ;; nos) mm="a non-opaque struct" ;; npt) mm="a symbol that needs a prototype" ;; num) mm="a numeric constant or enum" ;; nxt) mm="an include path for the native header" ;; pth) mm="a file" ;; run) yy="capture output of" mm= ;; siz) mm="a type with know size" ;; sym) mm="a typed variable" ;; sys) mm="a system header" ;; typ) mm="a type or typedef" ;; val) yy="determine" mm="value" ;; *) yy= mm= ;; esac case $ii in [abcdefghijklmnopqrstuvwxyz]*[abcdefghijklmnopqrstuvwxyz]"{") ii="$ii ... }end" ;; esac $show "$command: test:" $yy $ii $mm "...$SHOW" >&$stderr complete=1 ;; esac ;; esac } success() { case $complete:$verbose in 1:1) case $suspended in 1) suspended=0 $show "$command: test:" $yy $ii $mm "...$SHOW" >&$stderr ;; esac complete=0 case $# in 0) mm="yes" ;; *) mm="'$*'" ;; esac case $debug in 0) echo " $mm" >&$stderr ;; *) echo "$command: ... $mm" >&$stderr ;; esac ;; esac } failure() { case $complete:$verbose in 1:1) case $suspended in 1) suspended=0 $show "$command: test:" $yy $ii $mm "...$SHOW" >&$stderr ;; esac complete=0 case $# in 0) mm="no" ;; *) mm=$* ;; esac case $debug in 0) echo " $mm" >&$stderr ;; *) echo "$command: ... $mm" >&$stderr ;; esac ;; esac } noisy() { case $complete:$verbose in 1:1) suspended=1 echo >&$stderr ;; esac } here_broken=0 copy() # output-file data { case $shell in ksh) case $1 in -) print -r -- "$2" ;; *) print -r -- "$2" > "$1" ;; esac ;; *) case $1 in -) if cat <&$stderr ;; esac sh -c "cat < "$1" <&$stderr ;; esac sh -c "cat > '$1' </dev/null <&$stderr exit 1 fi ;; esac case `(set -f && set x * && echo $# && set +f) 2>/dev/null` in 2) posix_noglob="set -f" posix_glob="set +f" ;; *) case `(set -F && set x * && echo $# && set +F) 2>/dev/null` in 2) posix_noglob="set -F" posix_glob="set +F" ;; *) posix_noglob=":" posix_glob=":" ;; esac ;; esac } execute() { if test -d /NextDeveloper then $tmp.exe <&$nullin >&$nullout _execute_=$? $tmp.exe <&$nullin | cat elif test "" != "$cross" then crossexec $cross "$@" _execute_=$? else "$@" _execute_=$? fi return $_execute_ } exclude() { case $excludes in '') return 0 ;; esac for _exclude_var do eval _exclude_old=\$$_exclude_var case $_exclude_old in *" -I"*);; *) continue ;; esac _exclude_new= _exclude_sep= for _exclude_arg in $_exclude_old do for _exclude_dir in $excludes do case $_exclude_arg in -I$_exclude_dir|-I*/$_exclude_dir) ;; *) _exclude_new="$_exclude_new$_exclude_sep$_exclude_arg" _exclude_sep=" " ;; esac done done eval $_exclude_var=\$_exclude_new case $debug in 0) ;; *) echo $command: exclude $_exclude_var: "$_exclude_old => $_exclude_new" >&$stderr ;; esac done } all=0 binding="-dy -dn -Bdynamic -Bstatic -Wl,-ashared -Wl,-aarchive -call_shared -non_shared '' -static" complete=0 config=0 defhdr= iff= usr= cross= debug=0 deflib= dir=FEATURE excludes= executable="test -x" exists="test -e" gothdr= gotlib= ifs=$IFS in= includes= intrinsic= libpaths="LD_LIBRARY_PATH LD_LIBRARYN32_PATH LD_LIBRARY64_PATH LIBPATH SHLIB_PATH" nl=" " occ=cc one= out= posix_read= protoflags= puthdr= putlib= pragma= case $RANDOM in $RANDOM)shell=bsh ($executable .) 2>/dev/null || executable='test -r' ($exists .) 2>/dev/null || exists='test -r' ;; *) case $BASH_VERSION in ?*) shell=bash ;; *) shell=ksh ;; esac ;; esac reallystatic= reallystatictest= static=. statictest= style=C case $COTEMP in "") case $HOSTNAME in ""|?|??|???|????|????) tmp=${HOSTNAME} ;; *) case $shell in bsh) eval `echo $HOSTNAME | sed 's/\\(....\\).*/tmp=\\1/'` ;; *) eval 'tmp=${HOSTNAME%${HOSTNAME#????}}' ;; esac ;; esac tmp=${tmp}$$ ;; *) tmp=$COTEMP ;; esac case $tmp in ??????????*) case $shell in bsh) eval `echo $tmp | sed 's/\\(.........\\).*/tmp=\\1/'` ;; *) eval 'tmp=${tmp%${tmp#?????????}}' ;; esac ;; ?????????) ;; ????????) tmp=F$tmp ;; esac tmp=./$tmp undef=0 verbose=0 # options -- `-' for output to stdout otherwise usage case $1 in -) out=-; shift ;; esac set= case `(getopts '[-][123:xyz]' opt --xyz; echo 0$opt) 2>/dev/null` in 0123) USAGE=$' [-? @(#)$Id: iffe (AT&T Labs Research) 2002-02-14 $ ] '$USAGE_LICENSE$' [+NAME?iffe - host C compilation environment feature probe] [+DESCRIPTION?\biffe\b is a command interpreter that probes the host C compilation environment for features. A feature is any file, option or symbol that controls or is controlled by the C compiler. \biffe\b tests features by generating and compiling C programs and observing the behavior of the C compiler and generated programs.] [+?\biffe\b statements are line oriented. Statements may appear in the operand list with the \b:\b operand or \bnewline\b as the line delimiter. The standard input is read if there are no command line statements or if \afile\a\b.iffe\b is omitted.] [+?Though similar in concept to \bautoconfig\b(1) and \bconfig\b(1), there are fundamental differences. The latter tend to generate global headers accessed by all components in a package, whereas \biffe\b is aimed at localized, self contained feature testing.] [+?Output is generated in \bFEATURE/\b\atest\a by default, where \atest\a is the base name of \afile\a\b.iffe\b or the \biffe\b \brun\b command file operand. Output is first generated in a temporary file; the output file is updated if it does not exist or if the temporary file is different. If the first operand is \b-\b then the output is written to the standard output and no update checks are done.] [+?Files with suffixes \b.iffe\b and \b.iff\b are assumed to contain \biffe\b statements.] [a:all?Define failed test macros \b0\b. By default only successful test macros are defined \b1\b.] [c:cc?Sets the C compiler name and flags to be used in the feature tests.]:[C-compiler-name [C-compiler-flags ...]]] [C:config?Generate \bconfig\b(1) style \aHAVE_\a* macro names. This implies \b--undef\b. Since \bconfig\b(1) has inconsistent naming conventions, the \bexp\b command may be needed to translate from the (consistent) \biffe\b names. Unless otherwise noted a \bconfig\b macro name is the \biffe\b macro name prefixed with \bHAVE\b and converted to upper case. \b--config\b is set by default if the command arguments contain a \brun\b command on an input file with the base name \bconfig\b.] [d:debug?Sets the debug level. Level 0 inhibits most error messages, level 1 shows compiler messages, and level 2 traces internal \biffe\b \bsh\b(1) actions.]#[level] [i:input?Sets the input file name to \afile\a, which must contain \biffe\b statements.]:[file] [I:include?Adds \b-I\b\adir\a to the C compiler flags.]:[dir] [L:library?Adds \b-L\b\adir\a to the C compiler flags.]:[dir] [o:output?Sets the output file name to \afile\a.]:[file] [e:package?Sets the \bproto\b(1) package name to \aname\a.]:[name] [p:prototyped?Emits \b#pragma prototyped\b at the top of the output file. See \bproto\b(1).] [P:pragma?Emits \b#pragma\b \atext\a at the top of the output file.]:[text] [s:shell?Sets the internal shell name to \ashell-path\a. Used for debugging Bourne shell compatibility (otherwise \biffe\b uses \aksh\a constructs if available).]:[shell-path] [S:static?Sets the C compiler flags that force static linking. If not set then \biffe\b probes the compiler to determine the flags. \biffe\b must use static linking (no dlls) because on some systems missing library symbols are only detected when referenced at runtime from dynamically linked executables.]:[flags] [u:undef?\b#undef\b failed test macros. By default only successful test macros are defined \b1\b.] [v:verbose?Produce a message line on the standard error for each test as it is performed.] [x:cross?Some tests compile an executable (\ba.out\b) and then run it. If the C compiler is a cross compiler and the executable format is incompatible with the execution environment then the generated executables must be run in a different environment, possibly on another host. \acrosstype\a is the HOSTTYPE for generated executables (the \bpackage\b(1) command generates a consistent HOSTTYPE namespace). Generated executables are run via \bcrossexec\b(1) with \acrosstype\a as the first argument. \bcrossexec\b supports remote execution for cross-compiled executables. See \bcrossexec\b(1) for details.]:[crosstype] [X:exclude?Removes \b-I\b\adir\a and \b-I\b*/\adir\a C compiler flags.]:[dir] [ - ] [ file.iffe | statement [ : statement ... ] ] [+SYNTAX?\biffe\b input consists of a sequence of statement lines. Statements that span more than one line contain \abegin\a\b{\b as the last operand (where \abegin\a is command specific) and zero or more data lines terminated by a line containing \b}end\b as the first operand. The statements syntax is: \aop\a[,\aop\a...]] [\aarg\a[,\aarg\a...]]]] [\aprereq\a ...]] [\abegin\a{ ... |\bend\b ...]] [= [\adefault\a]]]]. \aop\as and \aarg\as may be combined, separated by commas, to perform a set of operations on a set of arguments.] [+?\aprereq\as are used when applying the features tests and may be combinations of:]{ [+compiler options?\b-D\b*, \b-L\b*, etc.] [+library references?\b-l\b*, *\b.a\b, etc. \b_LIB_\b\aname\a is defined to be 1 if \b-l\b\aname\a is a library.] [+header references?*\b.h\b. \a_dir_name\a is defined to be 1 if \adir/name\a\b.h\b is a header, or if \adir\a is omitted, \b_hdr_\b\aname\a is defined to be 1 if \aname\a\b.h\b is a header.] [+-?Prereq grouping mark; prereqs before the first \b-\b are passed to all feature tests. Subsequent groups are attempted in left-to-right order until the first successful group is found.] } [+?\abegin\a\b{\b ... \b}end\b delimit multiline code blocks that override or augment the default code provided by \biffe\b. User supplied code blocks should be compatible with the K&R, ANSI, and C++ C language dialects for maximal portability. In addition to all macro definitions generated by previous tests, all generated code contains the following at the top to hide dialect differences:]{ [+#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)?] [+#define _STD_ 1?] [+#define _ARG_(x) x?] [+#define _VOID_ void?] [+#else?] [+#define _STD_ 0?] [+#define _ARG_(x) ()?] [+#define _VOID_ char?] [+#endif?] [+#if defined(__cplusplus)?] [+#define _BEGIN_EXTERNS_ extern "C" {?] [+#define _END_EXTERNS_ }?] [+#else?] [+#define _BEGIN_EXTERNS_?] [+#define _END_EXTERNS_?] [+#endif?] [+#define _NIL_(x) ((x)0)?] } [+?= \adefault\a may be specified for the \bkey\b, \blib\b, \bmth\b and \btyp\b commands. If the test fails for \aarg\a then \b#define\b \aarg\a \adefault\a is emitted. \bkey\b accepts multiple \b= \b\adefault\a values; the first valid one is used.] [+?Each test statement generates a portion of a C language header that contains macro defintions, comments, and other text corresponding to the feature test commands. \b#ifndef _def_\b\aname\a\b_\b\adirectory\a ... \b#endif\b guards the generated header from multiple \b#include\bs, where \aname\a is determined by either the \brun\b command input file name if any, or the first \aop\a of the first command, and \adirectory\a is the basname component of either the \brun\b command file, if any, or the current working directory. The output file name is determined in this order:]{ [+-?If the first command line operand is \b-\b then the output is written to the standard output.] [+--output=\afile\a?Output is \afile\a.] [+set out \afile\a?Output is \afile\a.] [+[run]] [\adirectory\a/]]\abase\a[\a.suffix\a]]?Output is \bFEATURE/\b\abase\a.] } [+?Generated \biffe\b headers are often referenced in C source as: \b#include "FEATURE/\b\afile\a". The \bnmake\b(1) base rules contain metarules for generating \bFEATURE/\b\afile\a from \bfeatures/\b\afile\a[\asuffix\a]], where \asuffix\a may be omitted, \b.c\b, or \b.sh\b (see the \brun\b command below). Because \b#include\b prerequisites are automatically detected, \bnmake\b(1) ensures that all prerequisite \biffe\b headers are generated before compilation. Note that the directories are deliberately named \bFEATURE\b and \bfeatures\b to keep case-insensitive file systems happy.] [+?The feature test commands are:]{ [+# \acomment\a?Comment line - ignored.] [+cmd \aname\a?Defines \b_cmd_\b\aname\a if \aname\a is an executable in one of the standard system directories (\b/bin, /etc, /usr/bin, /usr/etc, /usr/ucb\b). \b_\b\adirectory\a\b_\b\aname\a is defined for \adirectory\a in which \aname\a is found (with \b/\b translated to \b_\b).] [+dat \aname\a?Defines \b_dat_\b\aname\a if \aname\a is a data symbol in the default libraries.] [+def \aname\a?Equivalent to \bcmd,dat,hdr,key,lib,mth,sys,typ\b \aname\a.] [+dfn \aname\a?If \aname\a is a macro in the candidate headers then a \b#define\b \aname\a \avalue\a statment is output for the \avalue\a defined in the headers. The definition is \b#ifndef\b guarded.] [+exp \aname\a \aexpression\a?If \aexpression\a is a \"...\" string then \aname\a is defined to be the string, else if the \bexpr\b(1) evaluation of \aexpression\a is not 0 then \aname\a is defined to be 1, otherwise \aname\a is defined to be 0. Identifiers in \aexpression\a may be previously defined names from other \biffe\b commands; undefined names evaluate to 0. If \aname\a was defined in a previous successful test then the current and subsequent \bexp\b test on \aname\a are skipped.] [+hdr \aname\a?Defines \b_hdr_\b\aname\a if the header \b<\b\aname\a\b.h>\b exists. The \b--config\b macro name is \bHAVE_\b\aNAME\a\b_H\b.] [+iff \aname\a?The generated header \b#ifndef-#endif\b macro guard is \b_\b\aname\a\b_H\b.] [+key \aname\a?Defines \b_key_\b\aname\a if \aname\a is a reserved word (keyword).] [+lcl \aname\a?Generates a \b#include\b statement for the native version of either the header \b<\b\aname\a\b.h>\b if it exists or the header \b\b if it exists. Defines \b_lcl_\b\aname\a on success. The \b--config\b macro name is \bHAVE_\b\aNAME\a\b_H\b.] [+lib \aname\a?Defines \b_lib_\b\aname\a if \aname\a is an external symbol in the default libraries.] [+mac \aname\a?Defines \b_mac_\b\aname\a if \aname\a is a macro.] [+mem \astruct.member\a?Defines \b_mem_\b\amember\a\b_\b\astruct\a if \amember\a is a member of the structure \astruct\a.] [+mth \aname\a?Defines \b_mth_\b\aname\a if \aname\a is an external symbol in the math library.] [+nop \aname\a?If this is the first command then \aname\a may be used to name the output file and/or the output header guard macro. Otherwise this command is ignored.] [+npt \aname\a?Defines \b_npt_\b\aname\a if the \aname\a symbol requires a prototype. The \b--config\b macro name is \b\aNAME\a\b_DECLARED\b with the opposite sense.] [+num \aname\a?Defines \b_num_\b\aname\a if \aname\a is a numeric constant \aenum\a or \amacro\a.] [+nxt \aname\a?Defines a string macro \b_nxt_\b\aname\a suitable for a \b#include\b statement to include the next (on the include path) or native version of either the header \b<\b\aname\a\b.h>\b if it exists or the header \b\b if it exists. Also defines the \"...\" form \b_nxt_\b\aname\a\b_str\b. The \b--config\b macro name is \bHAVE_\b\aNAME\a\b_NEXT\b.] [+one \aheader\a ...?Generates a \b#include\b statement for the first header found in the \aheader\a list.] [+pth \afile\a [ \adir\a ... | { \ag1\a - ... - \agn\a } | < \apkg\a [\aver\a ...]] > ]]?Defines \b_pth_\b\afile\a, with embedded \b/\b chars translated to \b_\b, to the path of the first instance of \afile\a in the \adir\a directories. \b{\b ... \b}\b forms a directory list from the cross-product of \b-\b separated directory groups \ag1\a ... \agn\a. < ... > forms a directory list for the package \apkg\a with optional versions. The \b--config\b macro name is \aNAME\a\b_PATH\b.] [+run \afile\a?Runs the tests in \afile\a based on the \afile\a suffix:]{ [+.c?\afile\a is compiled and executed and the output is copied to the \biffe\b output file.] [+.sh?\afile\a is executed as a shell script and the output is copied to the \biffe\b output file.] [+.iffe \bor no suffix?\afile\a contains \biffe\b statements.] } [+set \aoption value\a?Sets option values. The options are described above.] [+siz \aname\a?Defines \b_siz_\b\aname\a to be \bsizeof\b(\aname\a) if \aname\a is a type in any of \b, , , \b. Any \b.\b characters in \aname\a are translated to space before testing and are translated to \b_\b in the output macro name.] [+sym \aname\a?Defines \b_ary_\b\aname\a if \aname\a is an array, \b_fun_\b\aname\a if \aname\a is a function pointer, \b_ptr_\b\aname\a if \aname\a is a pointer, or \b_reg_\b\aname\a if \aname\a is a scalar. In most cases \aname\a is part of a macro expansion.] [+sys \aname\a?Defines \b_sys_\b\aname\a if the header \b\b exists. The \b--config\b macro name is \bHAVE_SYS_\b\aNAME\a\b_H\b.] [+tst \aname\a?A user defined test on name. A source block must be supplied. Defines \b_\b\aname\a on success.] [+typ \aname\a?Defines \b_typ_\b\aname\a if \aname\a is a type in any of \b, , , \b. Any \b.\b characters in \aname\a are translated to space before testing and are translated to \b_\b in the output macro name.] [+val \aname\a?The output of \becho\b \aname\a is written to the output file.] } [+?Code block names may be prefixed by \bno\b to invert the test sense. The block names are:]{ [+cat?The block is copied to the output file.] [+compile?The block is compiled (\bcc -c\b).] [+execute?The block is compiled, linked, and executed. \b0\b exit status means success.] [+fail?If the test fails then the block text evaluated by \bsh\b(1).] [+link?The block is compiled and linked (\bcc -o\b).] [+macro?The block is preprocessed (\bcc -E\b) and lines containing text bracketed by \b<<"\b ... \b">>\b (\aless-than less-than double-quote ... double-quote greater-than greater-than\a) are copied to the output file with the brackets omitted.] [+no?If the test fails then the block text is copied to the output file.] [+note?If the test succeeds then the block is copied to the output as a \b/*\b ... \b*/\b comment.] [+output?The block is compiled, linked, and executed, and the output is copied to the output file.] [+pass?If the test succeeds then the block text evaluated by \bsh\b(1).] [+preprocess?The block is preprocessed (\bcc -E\b).] [+run?The block is executed as a shell script and the output is copied to the output file. Succesful test macros are also defined as shell variables with value \b1\b and are available within the block. Likewise, failed test macros are defined as shell variables with value \b0\b.] [+yes?If the test succeeds then the block text is copied to the output file.] } [+SEE ALSO?\bautoconfig\b(1), \bconfig\b(1), \bcrossexec\b(1), \bnmake\b(1), \bpackage\b(1), \bproto\b(1), \bsh\b(1)] ' while getopts -a "$command" "$USAGE" OPT do case $OPT in a) set="$set set all :" ;; c) set="$set set cc $OPTARG :" ;; C) set="$set set config :" ;; d) set="$set set debug $OPTARG :" ;; i) set="$set set input $OPTARG :" ;; I) set="$set set include $OPTARG :" ;; L) set="$set set library $OPTARG :" ;; o) set="$set set output $OPTARG :" ;; e) set="$set set package $OPTARG :" ;; p) set="$set set prototyped :" ;; P) set="$set set pragma $OPTARG :" ;; s) set="$set set shell $OPTARG :" ;; S) set="$set set static $OPTARG :" ;; u) set="$set set undef :" ;; v) set="$set set verbose :" ;; x) set="$set set cross $OPTARG :" ;; X) set="$set set exclude $OPTARG :" ;; esac done shift `expr $OPTIND - 1` ;; *) while : do case $# in 0) break ;; esac case $1 in -) break ;; --) shift break ;; --a|--al|--all) REM=a ;; --cc=*) REM=c`echo $1 | sed -e 's,[^=]*=,,'` ;; --co|--con|--conf|--confi|--config) REM=C ;; --cr=*|--cro=*|--cros=*|--cross=*) REM=x`echo $1 | sed -e 's,[^=]*=,,'` ;; --d=*|--de=*|--deb=*|--debu=*|--debug=*) REM=d`echo $1 | sed -e 's,[^=]*=,,'` ;; --e=*|--ex=*|--exc=*|--excl=*|--exclu=*|--exclud=*|--exclude=*) REM=X`echo $1 | sed -e 's,[^=]*=,,'` ;; --inp=*|--inpu=*|--input=*) REM=i`echo $1 | sed -e 's,[^=]*=,,'` ;; --inc=*|--incl=*|--inclu=*|--includ=*|--include=*) REM=I`echo $1 | sed -e 's,[^=]*=,,'` ;; --l=*|--li=*|--lib=*|--libr=*|--libra=*|--librar=*|--library=*) REM=L`echo $1 | sed -e 's,[^=]*=,,'` ;; --o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*) REM=o`echo $1 | sed -e 's,[^=]*=,,'` ;; --pa=*|--pac=*|--pack=*|--packa=*|--packag=*|--package=*) REM=e`echo $1 | sed -e 's,[^=]*=,,'` ;; --pro|--prot|--proto|--protot|--prototy|--prototyp|--prototype|--prototyped) REM=p ;; --pra=*|--prag=*|--pragma=*) REM=P`echo $1 | sed -e 's,[^=]*=,,'` ;; --sh=*|--she=*|--shel=*|--shell=*) REM=s`echo $1 | sed -e 's,[^=]*=,,'` ;; --st=*|--sta=*|--stat=*|--stati=*|--static=*) REM=S`echo $1 | sed -e 's,[^=]*=,,'` ;; --u|--un|--und|--unde|--undef) REM=u ;; --v|--ve|--ver|--verb|--verbo|--verbos|--verbose) REM=v ;; --*) echo $command: $1: unknown option >&2 exit 2 ;; -*) REM=`echo $1 | sed -e 's,-,,'` ;; *) break ;; esac shift while : do case $REM in '') break ;; esac eval `echo $REM | sed -e "s,\(.\)\(.*\),OPT='\1' REM='\2',"` case $OPT in [cdiILoePsSxX]) case $REM in '') case $# in 0) echo $command: -$OPT: option argument expected >&2 exit 1 ;; esac OPTARG=$1 shift ;; *) OPTARG=$REM REM='' ;; esac esac case $OPT in a) set="$set set all :" ;; c) set="$set set cc $OPTARG :" ;; C) set="$set set config :" ;; d) set="$set set debug $OPTARG :" ;; i) set="$set set input $OPTARG :" ;; I) set="$set set include $OPTARG :" ;; L) set="$set set library $OPTARG :" ;; o) set="$set set output $OPTARG :" ;; e) set="$set set package $OPTARG :" ;; p) set="$set set prototyped :" ;; P) set="$set set pragma $OPTARG :" ;; s) set="$set set shell $OPTARG :" ;; S) set="$set set static $OPTARG :" ;; u) set="$set set undef :" ;; v) set="$set set verbose :" ;; x) set="$set set cross $OPTARG :" ;; X) set="$set set exclude $OPTARG :" ;; *) echo "Usage: $command [-aCpuv] [-c C-compiler-name [C-compiler-flags ...]] [-d level] [-i file] [-o file] [-e name] [-P text] [-s shell-path] [-S[flags]] [-x cross-exec-prefix] [-I dir] [-L dir] [-X dir] [ - ] [ file.iffe | statement [ : statement ... ] ]" >&2 exit 2 ;; esac done done ;; esac case $1 in -) out=-; shift ;; esac case $# in 0) in=- ;; esac set -- $set "$@" case " $* " in *' set config '*|*' run config.'*|*' run '*' config.'*|*' run '*'/config.'*) config=1 ;; esac # standard error to /dev/null unless debugging # standard output to the current output file # # stdout original standard output # stderr original standard error # nullin /dev/null input # nullout /dev/null output stdin=4 stdout=5 stderr=6 nullin=7 nullout=8 eval "exec $stdin<&0 $nullin/dev/null $stdout>&1 $stderr>&2" case " $* " in *" set debug "[3456789]*) ;; *) eval "exec 2>&$nullout" ;; esac # prompt complications case `print -n aha 2>/dev/null` in aha) show='print -n' SHOW='' ;; *) case `echo -n aha 2>/dev/null` in -n*) show=echo SHOW='\c' ;; *) show='echo -n' SHOW='' ;; esac ;; esac # tmp files cleaned up on exit # status: 0:success 1:failure 2:interrupt status=1 if (ulimit -c 0) >/dev/null 2>&1 then ulimit -c 0 core= else core=core fi trap "rm -f $core $tmp*.*; exit \$status" 0 1 2 if (:>$tmp.c) 2>/dev/null then rm -f $tmp.c else echo "$command: cannot create tmp files in current dir" >&2 exit 1 fi status=2 # standard header for c source std='#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus) #define _STD_ 1 #define _ARG_(x) x #define _VOID_ void #else #define _STD_ 0 #define _ARG_(x) () #define _VOID_ char #endif #if defined(__cplusplus) #define _BEGIN_EXTERNS_ extern "C" { #define _END_EXTERNS_ } #else #define _BEGIN_EXTERNS_ #define _END_EXTERNS_ #endif #define _NIL_(x) ((x)0)' ext='#ifndef feof _BEGIN_EXTERNS_ #if _STD_ extern int printf(const char*, ...); #else extern int printf(); #endif _END_EXTERNS_ #endif' # loop on op [ arg [ ... ] ] [ : op [ arg [ ... ] ] ] argx=0 cur=. can= cansep= cctest= hdrtest= while : do case $in in "") case $argx:$* in 1:$argv);; 1:*) argx=0 set x $argv shift ;; esac case $# in 0) set set out + ;; esac ;; *) read lin || lin="set out +" set x $lin shift ;; esac # check if "run xxx" is equivalent to "set in xxx" case $1 in *.iffe|*.iff) set run "$@" ;; esac case $1 in :) shift continue ;; run) case $shell in bsh) case $2 in */*) x=`echo $2 | sed -e 's,.*[\\/],,'` ;; *) x=$2 ;; esac ;; *) eval 'x=${2##*[\\/]}' ;; esac case $x in *.iffe|*.iff) set set in $2 ;; *.*) ;; *) set set in $2 ;; esac ;; esac # set drops out early case $1 in ""|\#*) continue ;; set) shift case $1 in ""|\#*) op= ;; *) arg= op=$1 case $op in --*) case $shell in bsh) op=`echo '' $op | sed 's/.*--//'` ;; *) op=${op#--} ;; esac ;; -*) case $op in -??*) case $shell in bsh) arg=`echo '' $op | sed 's/-.//'` op=`echo '' $op | sed 's/\\(-.\\).*/\\1/'` ;; *) arg=${op#-?} op=${op%$arg} ;; esac ;; esac case $op in a) op=all ;; c) op=cc ;; C) op=config ;; d) op=debug ;; i) op=input ;; I) op=include ;; L) op=library ;; o) op=output ;; e) op=package ;; p) op=prototyped ;; P) op=pragma ;; s) op=shell ;; S) op=static ;; u) op=undef ;; v) op=verbose ;; x) op=cross ;; X) op=exclude ;; esac ;; esac shift while : do case $# in 0) break ;; esac case $1 in *" "*) shift continue ;; ""|\#*) break ;; :) shift break ;; esac case $arg in "") arg=$1 ;; *) arg="$arg $1" ;; esac shift done ;; esac case $op in all) all=1 continue ;; cc) occ= for x in $arg do case $occ in "") case $x in *=*) case $shell in bsh) eval $x export `echo $x | sed -e 's/=.*//'` ;; *) export $x ;; esac ;; *) occ=$x ;; esac ;; *) occ="$occ $x" ;; esac done exclude occ continue ;; config) config=1 continue ;; cross) case $arg in ""|-) cross= ;; *) cross="$arg" libpaths= ;; esac continue ;; debug) debug=$arg case $arg in 0) exec 2>&$nullout set - show=echo SHOW= ;; ""|1) exec 2>&$stderr set - show=echo SHOW= ;; 2|3) exec 2>&$stderr case $shell in ksh) eval 'PS4="${PS4%+*([ ])}+\$LINENO+ "' esac show=echo SHOW= set -x ;; *) echo "$command: $arg: debug levels are 0, 1, 2, 3" >&$stderr ;; esac continue ;; exclude)case $arg in ""|-) excludes= ;; *) excludes="$excludes $arg" ;; esac exclude includes occ continue ;; "in"|input) case $arg in "") in=- ;; *) in=$arg if test ! -r $in then echo "$command: $in: not found" >&$stderr exit 1 fi exec < $in case $out in "") case $in in *[.\\/]*) case $shell in bsh) eval `echo $in | sed -e 's,.*[\\/],,' -e 's/\\.[^.]*//' -e 's/^/out=/'` ;; *) eval 'out=${in##*[\\/]}' eval 'out=${out%.*}' ;; esac ;; *) out=$in ;; esac ;; esac ;; esac continue ;; include)case $arg in ""|-) includes= ;; *) includes="$includes -I$arg" ;; esac exclude includes continue ;; library)for y in $libpaths do eval $y=\"\$$y:\$arg\" eval export $y done continue ;; nodebug)exec 2>&$nullout set - continue ;; out|output) out=$arg defhdr= usr= deflib= one= puthdr= putlib= case $op in output) continue ;; esac ;; package)protoflags="$protoflags -e $arg" continue ;; prototyped|noprototyped) pragma="$pragma $op" continue ;; pragma) pragma="$pragma $arg" continue ;; shell) shell=$arg continue ;; static) static=$arg continue ;; undef) undef=1 continue ;; verbose)verbose=1 continue ;; *) echo "$command: $op: unknown option" >&$stderr exit 1 ;; esac ;; *) case $1 in *\{) op=- ;; *) op=$1 shift ;; esac arg= cc="$occ $includes" fail= hdr= lib= mac= no= note= opt= pass= pth= run= set= src= test= yes= case $op in pth) lst=$op ;; *) lst=hdr ;; esac case $# in 0) ;; *) case $1 in \#*) set x shift ;; *) case $op in ref) ;; *) case $1 in *\{) arg=- ;; *) arg=$1 shift esac ;; esac ;; esac while : do case $# in 0) break ;; esac case $1 in "") ;; \#*) set x ;; \=) shift set=$* case $set in "") set=" " ;; esac while : do case $# in 0) break ;; esac shift done break ;; [abcdefghijklmnopqrstuvwxyz]*\{) v=$1 shift x= case $v in note\{) sep=" " ;; *) sep=$nl ;; esac SEP= while : do case $# in 0) case $posix_read in '') checkread ;; esac case $in in "") echo "$command: missing }end" >&$stderr exit 1 ;; esac while : do case $posix_read in 1) read -r lin ;; *) lin=`$posix_read` ;; esac case $? in 0) $posix_noglob set x $lin $posix_glob case $2 in \}end) shift break 2 ;; esac x="$x$SEP$lin" SEP=$sep ;; *) echo "$command: missing }end" >&$stderr exit 1 ;; esac done ;; esac case $1 in \}end) break ;; *) x="$x$SEP$1" SEP=$sep ;; esac shift done x="$x$nl" # \r\n bash needs this barf # case $v in fail\{) fail=$x ;; nofail\{) pass=$x v=pass\{ ;; nopass\{) fail=$x v=fail\{ ;; no\{) no=$x ;; note\{) note=$x ;; pass\{) pass=$x ;; test\{) test=$x ;; yes\{) yes=$x ;; *) src=$x run=$v ;; esac ;; :) shift break ;; *[\"\'\(\)\{\}\ \ ]*) case $op in pth) pth="$pth $1" lst=pth ;; *) test="$test $1" ;; esac ;; -) case $2 in [-+]l*) lst=lib ;; -D*) lst=mac ;; esac case $lst in hdr) hdr="$hdr $1" ;; lib) lib="$lib $1" ;; mac) mac="$mac $1" ;; pth) pth="$pth $1" ;; esac ;; -l*) lib="$lib $1" lst=lib ;; +l*) case $shell in bsh) x=`echo '' $1 | sed 's/.*+//'` ;; *) eval 'x=${1#+}' ;; esac lib="$lib -$x" lst=lib ;; -*|+*) case $op in ref) cc="$cc $1" occ="$occ $1" case $1 in -L*) case $shell in ksh) x=${1#-L} ;; *) x=`echo x$1 | sed 's,^x-L,,'` ;; esac for y in $libpaths do eval $y=\"\$$y:\$x\" eval export $y done ;; esac ;; run) opt="$opt $1" ;; *) case $1 in -D*) mac="$mac $1" lst=mac ;; *) cc="$cc $1" ;; esac ;; esac ;; *.[aAxX]|*.[dD][lL][lL]|*.[lL][iI][bB]) lib="$lib $1" lst=lib ;; *[.\\/]*) case $op in pth) pth="$pth $1" lst=pth ;; *) hdr="$hdr $1" lst=hdr ;; esac ;; *) case $op in pth) pth="$pth $1" lst=pth ;; *) test="$test $1" ;; esac ;; esac shift done ;; esac ;; esac # check for local package root directories case $PACKAGE_PATH in ?*) for i in `echo $PACKAGE_PATH | sed 's,:, ,g'` do if test -d $i/include then cc="$cc -I$i/include" occ="$occ -I$i/include" fi if test -d $i/lib then cc="$cc -L$i/lib" occ="$occ -L$i/lib" for y in $libpaths do eval $y=\"\$$y:\$i/lib\" eval export $y done fi done ;; esac case $cc in "") cc="$occ $includes" ;; esac # save $* for ancient shells argx=1 argv=$* # check the candidate macros case $mac in ?*) case " $mac " in *" - "*);; *) cc="$cc $mac" mac= ;; esac ;; esac # make sure $cc compiles C case $cctest in "") echo "int i = 1;" > $tmp.c if $cc -c $tmp.c <&$nullin >&$nullout then echo "(;" > $tmp.c if $cc -c $tmp.c <&$nullin >&$nullout then cctest="should not compile '(;'" fi else cctest="should compile 'int i = 1;'" fi case $cctest in "") cctest=0 ;; *) echo "$command: $cc: not a C compiler: $cctest" >&$stderr exit 1 ;; esac ;; esac # check for global default headers (some cc -E insist on compiling) case $hdrtest in '') hdrtest=1 allinc= for x in types do case $config in 0) c=_sys_${x} ;; 1) case $shell in ksh) typeset -u u=$x ;; *) u=`echo $x | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;; esac c=HAVE_SYS_${u}_H ;; esac x=sys/$x.h echo "${allinc}#include <$x>" > $tmp.c is hdr $x if $cc -E $tmp.c <&$nullin >&$nullout then success gothdr="$gothdr + $x" can="$can$cansep#define $c 1 /* #include <$x> ok */" cansep=$nl eval $c=1 allinc="${allinc}#include <$x>$nl" else failure gothdr="$gothdr - $x" case $all$config$undef in ?1?|??1)can="$can$cansep#undef $c /* #include <$x> not ok */" cansep=$nl ;; 1??) can="$can$cansep#define $c 0 /* #include <$x> not ok */" cansep=$nl ;; esac fi done ;; esac # add implicit headers/libraries before the checks case $op in npt) hdr="sys/types.h stdlib.h unistd.h $hdr" ;; siz|typ)hdr="sys/types.h time.h sys/time.h sys/times.h stddef.h stdlib.h $hdr" ;; esac # check the candidate headers case $hdr in ?*) z=$hdr hdr= hit=0 for x in $z do case $x in -) case $hit in 0) hit=1 ;; 1) ;; *) break ;; esac continue ;; *.h) case " $gothdr " in *" - $x "*) continue ;; *" + $x "*) ;; *) case $shell in bsh) eval `echo $x | sed -e 's,^\\([^\\/]*\\).*[\\/]\\([^\\/]*\\)\$,\\1_\\2,' -e 's/\\..*//' -e 's/^/c=/'` ;; *) eval 'c=${x##*[\\/]}' eval 'c=${c%%.*}' case $x in */*) eval 'c=${x%%[\\/]*}_${c}' ;; esac ;; esac case $config in 0) case $x in */*) c=_${c} ;; *) c=_hdr_${c} ;; esac ;; 1) case $shell in ksh) typeset -u u=$c ;; *) u=`echo $c | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;; esac c=HAVE_${u}_H ;; esac echo "${allinc}#include <$x>" > $tmp.c is hdr $x if $cc -E $tmp.c <&$nullin >&$nullout then success gothdr="$gothdr + $x" can="$can$cansep#define $c 1 /* #include <$x> ok */" cansep=$nl eval $c=1 else failure gothdr="$gothdr - $x" case $all$config$undef in ?1?|??1)can="$can$cansep#undef $c /* #include <$x> not ok */" cansep=$nl ;; 1??) can="$can$cansep#define $c 0 /* #include <$x> not ok */" cansep=$nl ;; esac continue fi ;; esac ;; *) test -r $x || continue ;; esac hdr="$hdr $x" case $hit in 0) ;; 1) hit=2 ;; esac done ;; esac # check the candidate libraries case $lib in ?*) z=$lib lib= p= hit=0 echo "main(){return(0);}" > $tmp.c for x in $z - do case $x in -) case $hit in 0) hit=1 continue ;; esac ;; *) case $hit in 0) p=$x ;; *) case $p in '') p=$x ;; *) p="$p $x" ;; esac continue ;; esac ;; esac case " $gotlib " in *"- $p "*) p= ;; *"+ $p "*) lib="$lib $p" ;; *) rm -f $tmp.exe is LIB $p if $cc -o $tmp.exe $tmp.c $p <&$nullin >&$nullout then success gotlib="$gotlib + $p" lib="$lib $p" e=0 else failure gotlib="$gotlib - $p" e=1 fi y= for x in $p do case $shell in bsh) c=`echo '' $x | sed 's, *-l,,'` ;; *) eval 'c=${x#-l}' ;; esac case $c in *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*) c=`echo '' $c | sed -e 's,.*[\\\\/],,' -e 's,\.[^.]*$,,' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g' -e '/^lib./s,^lib,,'` ;; esac case $config in 0) case $e$p in 0*' '*) case " $gotlib " in *[-+]" $x "*) ;; *) can="$can$cansep#define _LIB_$c 1 /* $x is a library */" cansep=$nl eval _LIB_$c=1 ;; esac ;; esac ;; 1) case $shell in ksh) typeset -u u=$c ;; *) u=`echo $c | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;; esac c=$u case $e in 0*' '*) case " $gotlib " in *[-+]" $x "*) ;; *) can="$can$cansep#define HAVE_${c}_LIB 1 /* $x is a library */" cansep=$nl eval HAVE_${c}_LIB=1 ;; esac ;; esac ;; esac y=${y}_$c done case $config in 0) c=_LIB${y} ;; 1) c=HAVE${y}_LIB ;; esac case $p in *' '*) q="a library group" ;; *) q="a library" ;; esac case $e in 0) can="$can$cansep#define $c 1 /* $p is $q */" cansep=$nl eval $c=1 case $hit in 1) break ;; esac ;; 1) case $all$config$undef in ?1?|??1)can="$can$cansep#undef $c /* $p is not $q */" cansep=$nl ;; 1??) can="$can$cansep#define $c 0 /* $p is not $q */" cansep=$nl ;; esac eval $c=0 ;; esac p= ;; esac done ;; esac # last op precheck case $op in ref) deflib="$deflib $lib" defhdr="$defhdr $hdr" continue ;; esac IFS=" ," case $shell in bash) op=`echo $op` arg=`echo $arg` ;; *) eval op=\"$op\" eval arg=\"$arg\" ;; esac IFS=$ifs # check for op aliases x= for o in $op do case $o in def|default) x="$x cmd dat hdr key lib mth sys typ" ;; *) x="$x $o" ;; esac done # loop on the ops o and args a for o in $x do for a in $arg do user_pf= user_yn= case $a in *[.\\/]*) case $o in hdr|pth|sys) case $a in *[\\/]*) x=/ ;; *) x=. ;; esac case $shell in bsh) case $x in .) x="\\$x" ;; esac eval `echo $a | sed -e 's,\\(.*\\)'"${x}"'\\(.*\\),p=\\1 v=\\2,'` ;; *) eval 'p=${a%%${x}*}' eval 'v=${a##*${x}}' ;; esac case $v in lcl|nxt)t=$p p=$v v=$t ;; esac ;; *) case $shell in bsh) eval `echo $a | sed -e 's,.*[\\/],,' -e 's/\\(.*\\)\\.\\(.*\\)/p=\\1 v=\\2/'` ;; *) eval 'p=${a%.*}' eval 'p=${p##*[\\/]}' eval 'v=${a##*.}' eval 'v=${v##*[\\/]}' ;; esac ;; esac f=${p}/${v} case $o in run) v=$p p= m=_${v} ;; mem) case $p in *.*) case $shell in bsh) eval `echo $p | sed -e 's/\\([^.]*\\)\\.\\(.*\\)/p=\\1 m=\\2/'` ;; *) eval 'm=${p#*.}' eval 'p=${p%%.*}' ;; esac v=${m}.${v} esac case $config in 0) m=_${v}_${p} ;; 1) m=_${v}_in_${p} ;; esac ;; *) m=_${p}_${v} ;; esac ;; *) p= v=$a f=$a m=_${v} ;; esac M=$m case $m in *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*) m=`echo "X$m" | sed -e 's,^.,,' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g'` ;; esac # check output redirection case $out in $cur) ;; *) case $cur in $a|$v) ;; *) case $cur in .) ;; -) case $iff in ?*) echo "#endif" ;; esac ;; *) case $iff in ?*) echo "#endif" ;; esac exec >/dev/null case $cur in *[\\/]*|*.h) x=$cur ;; *) x=$dir/$cur ;; esac case $style in C) (proto -r $protoflags $tmp.h) >/dev/null 2>&1 sed 's,/\*[^/]*\*/, ,g' $tmp.h > $tmp.c sed 's,/\*[^/]*\*/, ,g' $x > $tmp.t ;; *) sed '/^#/d' $tmp.h > $tmp.c sed '/^#/d' $x > $tmp.t ;; esac if cmp -s $tmp.c $tmp.t then rm -f $tmp.h case $verbose in 1) echo "$command: $x: unchanged" >&$stderr ;; esac else case $x in ${dir}[\\/]$cur) test -d $dir || mkdir $dir || exit 1 ;; esac mv $tmp.h $x fi ;; esac case $out in +) case $status in 1) ;; *) status=0 ;; esac exit $status ;; -) eval "exec >&$stdout" ;; *) exec >$tmp.h ;; esac case $out in "") case $a in *[\\/]*|???????????????*) cur=$v ;; *) cur=$a ;; esac ;; *) cur=$out ;; esac case $in in ""|-|+) case $o in run) x=" from $a" ;; *) x= ;; esac ;; *) x=" from $in" ;; esac # output header comments case $style in C) echo "/* : : generated$x by $command version $version : : */" for x in $pragma do echo "#pragma $x" done case $out in ""|-|+) x=$m ;; *.*) case $shell in bsh) eval `echo $in | sed -e 's,\\.,_,g' -e 's/^/x=/'` ;; *) i=$out x=_ while : do case $i in *.*) eval 'x=$x${i%%.*}_' eval 'i=${i#*.}' ;; *) x=$x$i break ;; esac done ;; esac ;; *) x=_$out ;; esac case $o in iff) case $M in ""|*-*) ;; *) iff=${m}_H ;; esac ;; *) case $x in *-*) ;; *) x=`pwd | sed -e 's,.*[\\/],,' -e 's,\\..*,,' -e 's,^lib,,' -e 's,^,'${x}_',' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g'` iff=_def${x} ;; esac ;; esac case $iff in ?*) echo "#ifndef $iff" echo "#define $iff 1" ;; esac ;; *) echo "# : : generated$x by $command version $version : : #" ;; esac ;; esac ;; esac case $can in ?*) echo "$can" can= cansep= ;; esac # set up the candidate include list inc= for x in $defhdr $hdr do case $x in *.h) case $shell in bsh) eval `echo $x | sed -e 's,^\\([^\\/]*\\).*[\\/]\\([^\\/]*\\)\$,\\1_\\2,' -e 's/\\..*//' -e 's/^/c=/'` ;; *) eval 'c=${x##*[\\/]}' eval 'c=${c%%.*}' case $x in */*) eval 'c=${x%%[\\/]*}_${c}' ;; esac ;; esac case $config in 0) case $x in */*) c=_${c} ;; *) c=_hdr_${c} ;; esac ;; 1) case $shell in ksh) typeset -u u=$c ;; *) u=`echo $c | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;; esac c=HAVE_${u}_H ;; esac case " $puthdr " in *" $c "*) ;; *) puthdr="$puthdr $c" usr="$usr$nl#define $c 1" ;; esac inc="$inc #include <$x>" ;; esac done # set up the candidate lib list for x in $lib $deflib do case $shell in ksh) eval 'c=${x#-l}' ;; *) c=`echo '' $x | sed 's, *-l,,'` ;; esac case $c in *[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*) c=`echo '' $c | sed -e 's,.*[\\\\/],,' -e 's,\.[^.]*$,,' -e 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_],_,g' -e '/^lib./s,^lib,,'` ;; esac case $config in 0) c=_LIB_${c} ;; 1) case $shell in ksh) typeset -u u=$c ;; *) u=`echo $c | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;; esac c=HAVE_${u}_LIB ;; esac case " $putlib " in *" $c "*) ;; *) putlib="$putlib $c" usr="$usr$nl#define $c 1" ;; esac done # src overrides builtin test case $config in 0) case $o in tst) ;; *) m=_${o}${m} ;; esac ;; 1) case $o in tst) m=${v} ;; esac case $shell in ksh) typeset -u u=$m ;; *) u=`echo $m | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` ;; esac case $o in tst) case $m in $u) ;; *) case $m in hdr_*|lib_*|sys_*) case $shell in ksh) u=${u#????} ;; *) u=`echo $u | sed 's/....//'` ;; esac ;; esac m=HAVE_${u} ;; esac ;; hdr|lcl)m=HAVE${u}_H ;; npt|pth)case $op in npt) m=${u}_DECLARED ;; pth) m=${u}_PATH ;; esac case $shell in ksh) m=${m#_} ;; *) m=`echo $m | sed 's,^_,,'` ;; esac ;; nxt) m=HAVE${u}_NEXT ;; sys) m=HAVE_SYS${u}_H ;; *) m=HAVE${u} ;; esac ;; esac case $v in *.*) pre= for x in `echo $v | sed 's,\\., ,g'` do pre="$pre #undef $x" done ;; *) pre="#undef $v" ;; esac case $src in ?*) case $src in *['<"'][Ss][Tt][Dd][Ii][Oo].[Hh]['">']*)EXT= ;; *) EXT=$ext ;; esac copy $tmp.c "$std $usr $inc $EXT $src" e= is tst "${note:-$run}" case $run in cat*|nocat*) copy - "$src" ;; run*|norun*) (eval "$src") <&$nullin || e=1 ;; mac*|nomac*) if $cc -E $tmp.c <&$nullin >$tmp.i then sed -e '/<<[ ]*".*"[ ]*>>/!d' -e 's/<<[ ]*"//g' -e 's/"[ ]*>>//g' $tmp.i else e=1 fi ;; p*|nop*)$cc -DTEST=$p -DID=$v -E $tmp.c <&$nullin >&$nullout || e=1 ;; c*|noc*)$cc -DTEST=$p -DID=$v -c $tmp.c <&$nullin >&$nullout || e=1 ;; *) case $run in s*|nos*)case $reallystatictest in '') #UNDENT... reallystatictest=. echo '#include main(){printf("hello");return(0);}' > ${tmp}s.c rm -f ${tmp}s.exe if $cc -c ${tmp}s.c <&$nullin >&$nullout && $cc -o ${tmp}s.exe ${tmp}s.o <&$nullin >&$nullout 2>${tmp}s.e && $executable ${tmp}s.exe then e=`wc -l ${tmp}s.e` eval set x x $binding while : do shift shift case $# in 0) break ;; esac rm -f ${tmp}s.exe $cc -o ${tmp}s.exe $1 ${tmp}s.o <&$nullin >&$nullout 2>${tmp}s.e && $executable ${tmp}s.exe || continue case `wc -l ${tmp}s.e` in $e) ;; *) continue ;; esac d=`ls -s ${tmp}s.exe` rm -f ${tmp}s.exe $cc -o ${tmp}s.exe $2 ${tmp}s.o <&$nullin >&$nullout 2>${tmp}s.e && $executable ${tmp}s.exe || continue case `wc -l ${tmp}s.e` in $e) ;; *) continue ;; esac case `ls -s ${tmp}s.exe` in $d) ;; *) reallystatic=$2 set x shift break ;; esac done fi rm -f ${tmp}s.* #...INDENT ;; esac ccflags=$reallystatic ;; *) ccflags= ;; esac set x $mac e=1 while : do o= shift while : do case $# in 0) break ;; esac case $1 in -) break ;; esac o="$o $1" shift done rm -f $tmp.exe if $cc $ccflags $o -DTEST=$p -DID=$v -o $tmp.exe $tmp.c $lib $deflib <&$nullin >&$nullout && $executable $tmp.exe then case $run in no[ls]*);; [ls]*) e= && break ;; noo*) execute $tmp.exe <&$nullin || break ;; o*) execute $tmp.exe <&$nullin && e= && break ;; no*) execute $tmp.exe <&$nullin >&$nullout || break ;; *) execute $tmp.exe <&$nullin >&$nullout && e= && break ;; esac else case $run in no[els]*)e=1 && break ;; esac fi case $# in 0) case $run in no*) e= ;; esac break ;; esac done ;; esac case $run in no*) case $e in "") e=1 ;; *) e= ;; esac ;; esac case $e in "") success case $M in *-*) ;; *) usr="$usr$nl#define $m 1" echo "#define $m 1 /* "${note:-"$run passed"}" */" eval $m=1 ;; esac user_pf=$pass user_yn=$yes ;; *) failure case $M in *-*) ;; *) case $all$config$undef in ?1?|??1)echo "#undef $m /* "${note:-"$run"}" failed */" ;; 1??) echo "#define $m 0 /* "${note:-"$run"}" failed */" ;; esac eval $m=0 ;; esac user_pf=$fail user_yn=$no ;; esac case $user_pf in ?*) (eval "$user_pf") <&$nullin ;; esac case $user_yn in ?*) case $note in ?*) user_yn="$user_yn /* $note */" ;; esac copy - "$user_yn" ;; esac continue ;; esac # initialize common builtin state case $o in dat|lib|mth|run) case $statictest in "") statictest=FoobaR copy $tmp.c " $std $usr $ext _BEGIN_EXTERNS_ extern int $statictest; _END_EXTERNS_ main(){char* i = (char*)&$statictest; return i!=0;} " rm -f $tmp.exe if $cc -o $tmp.exe $tmp.c <&$nullin >&$nullout && $executable $tmp.exe then case $static in .) static= echo '#include main(){printf("hello");return(0);}' > $tmp.c rm -f $tmp.exe if $cc -c $tmp.c <&$nullin >&$nullout && $cc -o $tmp.exe $tmp.o <&$nullin >&$nullout 2>$tmp.e && $executable $tmp.exe then e=`wc -l $tmp.e` eval set x x $binding while : do shift shift case $# in 0) break ;; esac rm -f $tmp.exe $cc -o $tmp.exe $1 $tmp.o <&$nullin >&$nullout 2>$tmp.e && $executable $tmp.exe || continue case `wc -l $tmp.e` in $e) ;; *) continue ;; esac d=`ls -s $tmp.exe` rm -f $tmp.exe $cc -o $tmp.exe $2 $tmp.o <&$nullin >&$nullout 2>$tmp.e && $executable $tmp.exe || continue case `wc -l $tmp.e` in $e) ;; *) continue ;; esac case `ls -s $tmp.exe` in $d) ;; *) static=$2 set x shift break ;; esac done fi ;; esac else static= fi ;; esac ;; esac # builtin tests case $o in cmd) case $p in ?*) continue ;; esac k= for j in "" usr do case $j in "") d= s= ;; *) d=/$j s=_$j ;; esac for i in bin etc ucb do if test -f $d/$i/$a then case $k in "") k=1 usr="$usr$nl#define $m 1" echo "#define $m 1 /* $a in ?(/usr)/(bin|etc|ucb) */" ;; esac c=${s}_${i}_${v} usr="$usr$nl#define $c 1" echo "#define $c 1 /* $d/$i/$a found */" fi done done ;; dat) case $p in ?*) continue ;; esac { copy - " $std $usr $pre " case $inc in ?*) echo "$inc" ;; *) echo "_BEGIN_EXTERNS_ extern int $v; _END_EXTERNS_" ;; esac echo "$ext #ifdef _DLL #define _REF_ #else #define _REF_ & #endif main(){char* i = (char*) _REF_ $v; return i!=0;}" } > $tmp.c is $o $v rm -f $tmp.exe if $cc -c $tmp.c <&$nullin >&$nullout && $cc $static -o $tmp.exe $tmp.o $lib $deflib <&$nullin >&$nullout && $executable $tmp.exe then success usr="$usr$nl#define $m 1" echo "#define $m 1 /* $v in default lib(s) */" eval $m=1 else failure case $all$config$undef in ?1?|??1)echo "#undef $m /* $v not in default lib(s) */" ;; 1??) echo "#define $m 0 /* $v not in default lib(s) */" ;; esac eval $m=0 fi ;; dfn) case $p in ?*) continue ;; esac is dfn $v echo "$pre $inc #ifdef $v <<\"#ifndef $v\">> <<\"#define $v\">> $v <<\"/* native $v */\">> <<\"#endif\">> #endif" > $tmp.c if $cc -E $tmp.c <&$nullin >$tmp.i then sed -e '/<<[ ]*".*"[ ]*>>/!d' -e 's/<<[ ]*"//g' -e 's/"[ ]*>>//g' $tmp.i > $tmp.t if test -s $tmp.t then success cat $tmp.t else failure fi else failure fi ;; exp) case $a in -) ;; *) eval x='$'$a case $x in 1) continue ;; esac ;; esac case $test in \ \"*\"|\ [01]) case $a in -) ;; *) case $note in '') echo "#define $a $test" ;; *) echo "#define $a $test /* $note */" ;; esac ;; esac ;; *) case $note in '') note=$test ;; *) note=' '$note ;; esac is exp "$note" x= for i in `echo '' $test | sed 's,[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_], & ,g'` do case $i in [\ \ ]) ;; [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]*) x="$x \${$i:-0}" ;; '!') x="$x 0 =" ;; '&'|'|')case $x in *"$i") ;; *) x="$x \\$i" ;; esac ;; *) x="$x \\$i" ;; esac done case `eval expr $x 2>&$stderr` in 0) failure case $a in -) ;; *) case $all$config$undef in ?1?|??1)echo "#undef $a /*$note is false */" ;; 1??) echo "#define $a 0 /*$note is false */" ;; esac eval $a=0 ;; esac user_pf=$fail user_yn=$no ;; *) success case $a in -) ;; *) usr="$usr$nl#define $a 1" echo "#define $a 1 /*$note is true */" eval $a=1 ;; esac user_pf=$pass user_yn=$yes ;; esac ;; esac ;; hdr|lcl|nxt|sys) case $o in lcl|nxt)p=$o ;; esac case $p in lcl|nxt)eval f='$'_${p}_$v case $f in ?*) continue ;; esac eval _${p}_$v=1 f=$v ;; *) case $o in hdr) x=$f.h ;; sys) x=sys/$f.h ;; esac case " $gothdr " in *" - $x "*) ;; *" + $x "*) ;; *) echo "${allinc}#include <$x>" > $tmp.c is hdr $x if $cc -E $tmp.c <&$nullin >&$nullout then success case " $puthdr " in *" $m "*) ;; *) puthdr="$puthdr $m" usr="$usr$nl#define $m 1" ;; esac gothdr="$gothdr + $x" echo "#define $m 1 /* #include <$x> ok */" eval $m=1 else failure gothdr="$gothdr - $x" case $all$config$undef in ?1?|??1)echo "#undef $m /* #include <$x> not ok */" ;; 1??) echo "#define $m 0 /* #include <$x> not ok */" ;; esac eval $m=0 fi ;; esac continue ;; esac x=$f case $f in *[\\/]*)g=$f ;; *) g="$f sys/$f" ;; esac is $o $x for f in $g do echo "$pre $inc #include <$f.h>" > $tmp.c case $f in sys/*) e= ;; *) e='-e /[\\\/]sys[\\\/]'$x'\\.h"/d' ;; esac if $cc -E $tmp.c <&$nullin >$tmp.i then i=`sed -e '/^#[line ]*[0123456789][0123456789]*[ ][ ]*"[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:]*[\\\\\\/].*[\\\\\\/]'$x'\\.h"/!d' $e -e s'/.*"\\(.*\\)".*/\\1/' -e 's,\\\\,/,g' -e 's,///*,/,g' $tmp.i | sed 1q` case $i in [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]:[\\/]*) ;; */*/*) k=`echo "$i" | sed 's,.*/\([^/]*/[^/]*\)$,../\1,'` echo "$pre $inc #include <$k>" > $tmp.c if $cc -E $tmp.c <&$nullin >$tmp.i then j=`sed -e '/^#[line ]*[0123456789][0123456789]*[ ][ ]*"[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:]*[\\\\\\/].*[\\\\\\/]'$x'\\.h"/!d' $e -e s'/.*"\\(.*\\)".*/\\1/' -e 's,\\\\,/,g' -e 's,///*,/,g' $tmp.i | sed 1q` wi=`wc < "$i"` wj=`wc < "$j"` case $wi in $wj) i=$k ;; esac fi ;; *) echo "$pre $inc #include <../include/$f.h>" > $tmp.c if $cc -E $tmp.c <&$nullin >&$nullout then i=../include/$f.h fi ;; esac else i= fi case $i in [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]:[\\/]*|[\\/]*) success case $p in lcl) echo "#if defined(__STDPP__directive)" echo "__STDPP__directive pragma pp:hosted" echo "#endif" echo "#include <$i> /* the native <$f.h> */" echo "#undef $m" usr="$usr$nl#define $m 1" echo "#define $m 1" ;; nxt) echo "#define $m <$i> /* include path for the native <$f.h> */" echo "#define ${m}_str \"$i\" /* include string for the native <$f.h> */" usr="$usr$nl#define $m <$i>$nl#define ${m}_str \"$i\"" eval $m=\\\<$i\\\> ;; esac break ;; ../*/*) success case $p in lcl) echo "#include <$i> /* the native <$f.h> */" echo "#undef $m" usr="$usr$nl#define $m 1" echo "#define $m 1" eval $m=1 ;; nxt) echo "#define $m <$i> /* include path for the native <$f.h> */" echo "#define ${m}_str \"$i\" /* include string for the native <$f.h> */" usr="$usr$nl#define $m <$i>$nl#define ${m}_str \"$i\"" eval $m=\\\<$i\\\> ;; esac break ;; *) failure case $p in lcl) case $all$config$undef in ?1?|??1)echo "#undef $m /* no native <$f.h> */" ;; 1??) echo "#define $m 0 /* no native <$f.h> */" ;; esac eval $m=0 ;; nxt) case $all$config$undef in ?1?|??1)echo "#undef $m /* no include path for the native <$f.h> */" ;; esac ;; esac ;; esac done ;; iff) ;; key) case $p in ?*) continue ;; esac w=$v while : do is $o $w echo "$pre int f(){int $w = 1;return($w);}" > $tmp.c if $cc -c $tmp.c <&$nullin >&$nullout then failure case $set in *" ="|*" = "*) set x $set shift w= while : do case $# in 0) break ;; esac case $1 in =) break ;; esac w="$w $1" shift done case $1 in =) shift set=" $*" ;; *) set= ;; esac continue ;; esac case $all$config$undef in ?1?|??1)echo "#undef $m /* $w is not a reserved keyword */" ;; 1??) echo "#define $m 0 /* $w is not a reserved keyword */" ;; esac eval $m=0 case $set in ?*) echo "#define $v $set /* default for reserved keyword $v */" ;; esac else success usr="$usr$nl#define $m 1" echo "#define $m 1 /* $v is a reserved keyword */" eval $m=1 case $w in $v) ;; *) echo "#define $v $w /* alternate for reserved keyword $v */" ;; esac fi break done ;; lib|mth)case $p in ?*) continue ;; esac case $v in -) continue ;; esac is $o $v copy $tmp.c " $std $usr $pre $inc $ext typedef int (*_IFFE_fun)(); #ifdef _IFFE_extern _BEGIN_EXTERNS_ extern int $v(); _END_EXTERNS_ #endif static _IFFE_fun i=(_IFFE_fun)$v;main(){return(i==0);} " if $cc -D_IFFE_extern -c $tmp.c <&$nullin >&$nullout || $cc -c $tmp.c <&$nullin >&$nullout then rm -f $tmp.exe if $cc $static -o $tmp.exe $tmp.o $lib $deflib <&$nullin >&$nullout && $executable $tmp.exe then case $o in lib) success usr="$usr$nl#define $m 1" echo "#define $m 1 /* $v() in default lib(s) */" eval $m=1 ;; *) failure case $all$config$undef in ?1?|??1)echo "#undef $m /* $v() not in math lib */" ;; 1??) echo "#define $m 0 /* $v() not in math lib */" ;; esac eval $m=0 case $set in ?*) echo "#define $v $set /* default for function $v() */" ;; esac ;; esac else case $o in mth) rm -f $tmp.exe if $cc $static -o $tmp.exe $tmp.o -lm <&$nullin >&$nullout && $executable $tmp.exe then success usr="$usr$nl#define $m 1" echo "#define $m 1 /* $v() in math lib */" eval $m=1 else failure case $all$config$undef in ?1?|??1)echo "#undef $m /* $v() not in math lib */" ;; 1??) echo "#define $m 0 /* $v() not in math lib */" ;; esac eval $m=0 case $set in ?*) echo "#define $v $set /* default for function $v() */" ;; esac fi ;; *) failure case $all$config$undef in ?1?|??1)echo "#undef $m /* $v() not in default lib(s) */" ;; 1??) echo "#define $m 0 /* $v() not in default lib(s) */" ;; esac eval $m=0 case $set in ?*) echo "#define $v $set /* default for function $v() */" ;; esac ;; esac fi else case $intrinsic in '') copy $tmp.c " $std $usr $pre $inc $ext _BEGIN_EXTERNS_ extern int foo(); _END_EXTERNS_ static int ((*i)())=foo;main(){return(i==0);} " if $cc -c $tmp.c <&$nullin >&$nullout then intrinsic=1 else intrinsic=0 fi ;; esac case $intrinsic in 0) failure case $o in mth) case $all$config$undef in ?1?|??1)echo "#undef $m /* $v() not in math lib */" ;; 1??) echo "#define $m 0 /* $v() not in math lib */" ;; esac eval $m=0 ;; *) case $all$config$undef in ?1?|??1)echo "#undef $m /* $v() not in default lib(s) */" ;; 1??) echo "#define $m 0 /* $v() not in default lib(s) */" ;; esac eval $m=0 ;; esac case $set in ?*) echo "#define $v $set /* default for function $v() */" ;; esac ;; 1) success case $o in lib) usr="$usr$nl#define $m 1" echo "#define $m 1 /* $v() in default lib(s) */" ;; mth) usr="$usr$nl#define $m 1" echo "#define $m 1 /* $v() in math lib */" ;; esac ;; esac fi ;; mac) case $p in ?*) continue ;; esac is mac $v echo "$pre $inc #ifdef $v '#define $m 1 /* $v is a macro */' #endif" > $tmp.c if $cc -E $tmp.c <&$nullin | sed -e "/#define/!d" -e "s/'//g" -e "s/^[ ][ ]*//" then success usr="$usr$nl#define $m 1" else failure case $all$config$undef in ?1?|??1)echo "#undef $m 0 /* $v is not a macro */" ;; 1??) echo "#define $m 0 /* $v is not a macro */" ;; esac eval $m=0 fi ;; mem) case $p in ?*) eval i='$'_iffe_typedef_$p case $i in 0|1) ;; *) echo "$pre $inc static $p i; int n = sizeof(i);" > $tmp.c is typ $p if $cc -c $tmp.c <&$nullin >&$nullout then success eval _iffe_typedef_$p=1 i=1 else failure eval _iffe_typedef_$p=0 i=0 fi ;; esac case $i in 0) p="struct $p" ;; esac is mem $v "$p" echo "$pre $inc static $p i; int n = sizeof(i.$v);" > $tmp.c if $cc -c $tmp.c <&$nullin >&$nullout then success usr="$usr$nl#define $m 1" echo "#define $m 1 /* $v is a member of $p */" eval $m=1 else failure case $all$config$undef$i in ?1?0|??10)echo "#undef $m /* $v is not a member of $p */" ;; 1??0) echo "#define $m 0 /* $v is not a member of $p */" ;; esac eval $m=0 fi ;; *) p=$v eval i='$'_iffe_typedef_$p case $i in 0|1) ;; *) echo "$pre $inc static $p i; int n = sizeof(i);" > $tmp.c is typ $p if $cc -c $tmp.c <&$nullin >&$nullout then success eval _iffe_typedef_$p=1 i=1 else failure eval _iffe_typedef_$p=0 i=0 fi ;; esac case $i in 0) p="struct $p" ;; esac is nos "$p" echo "$pre $inc static $p i; int n = sizeof(i);" > $tmp.c if $cc -c $tmp.c <&$nullin >&$nullout then echo "$pre $inc static $p i; unsigned long f() { return (unsigned long)i; }" > $tmp.c if $cc -c $tmp.c <&$nullin >&$nullout then : else success usr="$usr$nl#define $m 1" echo "#define $m 1 /* $p is a non-opaque struct */" continue fi fi failure case $all$config$undef$i in ?1?0|??10)echo "#undef $m /* $p is not a non-opaque struct */" ;; 1??0) echo "#define $m 0 /* $p is not a non-opaque struct */" ;; esac eval $m=0 ;; esac ;; nop) ;; npt) is npt $v copy $tmp.c " $std $usr $pre $inc $ext _BEGIN_EXTERNS_ struct _iffe_struct { int _iffe_member; }; extern struct _iffe_struct* $v _ARG_((struct _iffe_struct*)); _END_EXTERNS_ " if $cc -c $tmp.c <&$nullin >&$nullout then success case $config in 1) echo "#undef $m /* $v() needs a prototype */" eval $m=0 ;; *) usr="$usr$nl#define $m 1" echo "#define $m 1 /* $v() needs a prototype */" eval $m=1 ;; esac else failure case $config in 1) usr="$usr$nl#define $m 1" echo "#define $m 1 /* $v() does not need a prototype */" eval $m=1 ;; *) case $all$undef in ?1) echo "#undef $m /* $v() does not need a prototype */" ;; 1?) echo "#define $m 0 /* $v() does not need a prototype */" ;; esac eval $m=0 ;; esac fi ;; num) is num $v copy $tmp.c " $std $usr $pre $inc $ext _BEGIN_EXTERNS_ int _iffe_int = $v / 2; _END_EXTERNS_ " if $cc -c $tmp.c <&$nullin >&$nullout then success usr="$usr$nl#define $m 1" echo "#define $m 1 /* $v is a numeric constant */" eval $m=1 else failure case $all$config$undef in ?1?|??1)echo "#undef $m /* $v is not a numeric constant */" ;; 1??) echo "#define $m 0 /* $v is not a numeric constant */" ;; esac eval $m=0 fi ;; one) for i in $a $hdr do x="#include <$i>" case " $gothdr " in *" - $i "*) continue ;; *" + $i "*) ;; *) is hdr $x echo "$x" > $tmp.c if $cc -E $tmp.c <&$nullin >&$nullout then success gothdr="$gothdr + $x" else failure gothdr="$gothdr - $x" continue fi ;; esac case $one in "") one=$x ;; *"$x"*) break ;; *) echo "$one" > $tmp.c if $cc -E $tmp.c <&$nullin >$tmp.i then c=$i case $c in *[\\/]*) c=`echo $c | sed 's,[\\\\\\/],[\\\\\\/],g'` ;; esac case `sed -e '/^#[line ]*1[ ][ ]*"[\\\\\\/].*[\\\\\\/]'$c'"/!d' $tmp.i` in ?*) break ;; esac fi one="$one$nl$x" ;; esac echo "$x" break done ;; out|output) ;; pth) is pth $a pkg $pth tab=" " e= f= for i in $pth do case $i in '{') e="${nl}}" l= x=i v="\$${x}" t=${nl}${tab} b="fnd()${nl}{${t}for ${x} in" ;; '}') b="${b}${t}do${tab}if test -e ${v}/\${1}${t}${tab}${tab}then${tab}f=${v}/\${1}${t}${tab}${tab}${tab}return${t}${tab}${tab}fi" e="${t}done${e}" eval "${b}${e}" fnd $a case $f in ?*) break ;; esac ;; -) b="${b}${t}do${tab}test \"${v}\" = '' -o -d \"${v}\" &&${t}${tab}${tab}" x=${x}i v="${v}\$${x}" b="${b}for ${x} in" e="${t}done${e}" t="${t}${tab}${tab}" ;; *) case $e in '') if test -e ${i}/${a} then f=${i}/${a} break fi ;; *) case $i in /|.) b="${b} ''" ;; *) b="${b} /${i}" ;; esac ;; esac ;; esac done case $f in '') case $set in ' ') f=$a ;; ?*) f=$set ;; esac ;; esac case $f in '') failure case $all$config$undef in ?1?|??1)echo "#undef $m /* $a path not found */" ;; esac ;; ?*) success echo "#define $m \"$f\" /* ${note:-$a path} */" eval $m=\\\"$f\\\" ;; esac ;; run) is run $a if test ! -r $a then failure not found case $verbose in 0) echo "$command: $a: not found" >&$stderr ;; esac exit 1 fi noisy case $a in *.c) rm -f $tmp.exe cp $a $tmp.c $cc -o $tmp.exe $tmp.c $lib $deflib <&$nullin >&$stderr 2>&$stderr && $executable $tmp.exe && execute $tmp.exe $opt <&$nullin ;; *.sh) { cat < $tmp.sh chmod +x $tmp.sh ( . $tmp.sh ) <&$nullin ;; *) false ;; esac case $? in 0) success ;; *) failure cannot run case $verbose in 0) echo "$command: $a: cannot run" >&$stderr ;; esac exit 1 ;; esac ;; siz) case $p in "") x= ;; *) x="$p " ;; esac is siz "$x$v" { case $p:$v in long:*|*:*[_0123456789]int[_0123456789]*) echo "$pre $inc #include static $x$v i; $x$v f() { $x$v v; i = 1; v = i;" echo "i = v * i; i = i / v; v = v + i; i = i - v;" case $v in float|double) ;; *) echo "v <<= 4; i = v >> 2; i = 10; i = v % i; i |= v; v ^= i; i = 123; v &= i;" ;; esac echo "return v; }" ;; *) echo "$pre $inc struct xxx { $x$v mem; }; static struct xxx v; struct xxx* f() { return &v; }" ;; esac case $x in ""|"struct "|"union ") echo "int g() { return 0; }" ;; *) echo "int g() { return sizeof($x$v)<=sizeof($v); }" ;; esac copy - " main() { f(); g(); printf(\"%u\\n\", sizeof($x$v)); return 0; }" } > $tmp.c rm -f $tmp.exe $tmp.dat if $cc -o $tmp.exe $tmp.c $lib $deflib <&$nullin >&$nullout && $executable $tmp.exe && execute $tmp.exe > $tmp.dat then success z=`cat $tmp.dat` usr="$usr$nl#define $m $z" echo "#define $m $z /* sizeof($x$v) */" eval $m=1 user_pf=$pass user_yn=$yes else failure case $all$config$undef in ?1?|??1)echo "#undef $m /* $x$v not a type with known size */" ;; 1??) echo "#define $m 0 /* $x$v not a type with known size */" ;; esac eval $m=0 user_pf=$fail user_yn=$no fi ;; sym) case $test in "") x=$v ;; *) x=$test ;; esac echo "$pre $inc '=' $x '='" > $tmp.c $cc -E $tmp.c <&$nullin \ | sed \ -e "/'='/!d" \ -e "s/'='//g" \ -e 's/[ ]//g' \ -e 's/((([^()]*)))->/->/g' \ -e 's/(([^()]*))->/->/g' \ -e 's/([^()]*)->/->/g' \ -e 's/\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*\)\[/\ ary \1[/g' \ -e 's/\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*\)(/\ fun \1[/g' \ -e 's/\*->\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]\)/->\ ptr \1/g' \ -e 's/->\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]\)/->\ reg \1/g' \ -e "/^$v\$/d" \ -e 's/^[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*$/\ nam &/g' \ | sed \ -e '/^... /!d' \ | sort \ -u \ | sed \ -e 's/\(...\) \([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_][abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789]*\).*/#ifndef _\1_'$v'\ #define _\1_'$v' \2\ #define _\1_'$v'_str "\2"\ #endif/' ;; typ) case $p in "") x= ;; *) x="$p " ;; esac is typ "$x$v" { case $p:$v in long:*|*:*[_0123456789]int[_0123456789]*) echo "$pre $inc static $x$v i; $x$v f() { $x$v v; i = 1; v = i;" echo "i = v * i; i = i / v; v = v + i; i = i - v;" case $v in float|double) ;; *) echo "v <<= 4; i = v >> 2; i = 10; i = v % i; i |= v; v ^= i; i = 123; v &= i;" ;; esac echo "return v; }" ;; *) echo "$pre $inc struct xxx { $x$v mem; }; static struct xxx v; struct xxx* f() { return &v; }" ;; esac case $x in ""|"struct "|"union ") echo "main() { f(); return 0; }" ;; *) echo "main() { f(); return sizeof($x$v)<=sizeof($v); }" ;; esac } > $tmp.c rm -f $tmp.exe if $cc -o $tmp.exe $tmp.c $lib $deflib <&$nullin >&$nullout && $executable $tmp.exe && execute $tmp.exe then success usr="$usr$nl#define $m 1" echo "#define $m 1 /* $x$v is a type */" eval $m=1 user_pf=$pass user_yn=$yes else failure case $all$config$undef in ?1?|??1)echo "#undef $m /* $x$v is not a type */" ;; 1??) echo "#define $m 0 /* $x$v is not a type */" ;; esac eval $m=0 case $set in ?*) echo "#define $v $set /* default for type $x$v */" ;; esac user_pf=$fail user_yn=$no fi ;; val) case $arg in \"*\") echo $arg=\'$val\' ;; *) echo $arg=\"$val\" ;; esac ;; :) shift ;; *) echo "$command: $o: unknown feature test" >&$stderr status=1 ;; esac case $user_pf in ?*) (eval "$user_pf") <&$nullin ;; esac case $user_yn in ?*) case $note in ?*) user_yn="$user_yn /* $note */" ;; esac copy - "$user_yn" ;; esac done done done $v $set /* default for type $x$v */" ;; esac user_pf=$fail user_yn=$no fi ;; val) case $arg in \"*\") echo $arg=\'$val\' ;; *) echo $arg=\"$val\" ;; esac src/lib/sfio/sfprintf.c000644 151361 151361 00000002512 07432261524 015031 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Print data with a given format ** ** Written by Kiem-Phong Vo. */ #if __STD_C int sfprintf(Sfio_t* f, const char* form, ...) #else int sfprintf(va_alist) va_dcl #endif { va_list args; reg int rv; #if __STD_C va_start(args,form); #else reg Sfio_t* f; reg char* form; va_start(args); f = va_arg(args,Sfio_t*); form = va_arg(args,char*); #endif rv = sfvprintf(f,form,args); va_end(args); return rv; } #if __STD_C int sfvsprintf(char* s, int n, const char* form, va_list args) #else int sfvsprintf(s, n, form, args) char* s; int n; char* form; va_list args; #endif { Sfio_t f; reg int rv; if(!s || n <= 0) return -1; /* make a fake stream */ SFCLEAR(&f, NIL(Vtmutex_t*)); f.flags = SF_STRING|SF_WRITE; f.bits = SF_PRIVATE; f.mode = SF_WRITE; f.size = n-1; f.data = f.next = f.endr = (uchar*)s; f.endb = f.endw = f.data+f.size; rv = sfvprintf(&f,form,args); *f.next = '\0'; _Sfi = f.next - f.data; return rv; } #if __STD_C int sfsprintf(char* s, int n, const char* form, ...) #else int sfsprintf(va_alist) va_dcl #endif { va_list args; reg int rv; #if __STD_C va_start(args,form); #else reg char* s; reg int n; reg char* form; va_start(args); s = va_arg(args,char*); n = va_arg(args,int); form = va_arg(args,char*); #endif rv = sfvsprintf(s,n,form,args); va_end(args); return rv; } f.endb = f.endw = f.data+f.size; rv = sfvprintf(&f,form,args); *f.next = '\0'; _Sfi = f.next - f.data; return rv; } #if __STD_C int sfsprintf(char* s, int n, const char* formsrc/lib/sfio/sfprints.c000644 151361 151361 00000001501 07432261524 015043 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Construct a string with the given format and data. ** This function allocates space as necessary to store the string. ** This avoids overflow problems typical with sprintf() in stdio. ** ** Written by Kiem-Phong Vo. */ #if __STD_C char* sfprints(const char* form, ...) #else char* sfprints(va_alist) va_dcl #endif { va_list args; reg int rv; static Sfio_t* f; #if __STD_C va_start(args,form); #else reg char *form; va_start(args); form = va_arg(args,char*); #endif /* make a fake stream */ if(!f && !(f = sfnew(NIL(Sfio_t*),NIL(char*),(size_t)SF_UNBOUND, -1,SF_WRITE|SF_STRING)) ) return NIL(char*); sfseek(f,(Sfoff_t)0,0); rv = sfvprintf(f,form,args); va_end(args); if(rv < 0 || sfputc(f,'\0') < 0) return NIL(char*); _Sfi = (f->next - f->data) - 1; return (char*)f->data; } t) va_dcl #endif { va_list args; reg int rv; static Sfio_t* f; #if __STD_C va_start(args,form); #else reg char *form; va_start(args); form = va_arg(args,char*); #endif /* make a fsrc/lib/sfio/sfopen.c000644 151361 151361 00000010101 07432261524 014461 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Open a file/string for IO. ** If f is not nil, it is taken as an existing stream that should be ** closed and its structure reused for the new stream. ** ** Written by Kiem-Phong Vo. */ #if __STD_C Sfio_t* sfopen(reg Sfio_t* f, const char* file, const char* mode) #else Sfio_t* sfopen(f,file,mode) reg Sfio_t* f; /* old stream structure */ char* file; /* file/string to be opened */ reg char* mode; /* mode of the stream */ #endif { int fd, oldfd, oflags, sflags; /* get the control flags */ if((sflags = _sftype(mode,&oflags,NIL(int*))) == 0) return NIL(Sfio_t*); /* usually used on the standard streams to change control flags */ if(f && !file && (f->mode&SF_INIT) ) { SFMTXSTART(f, NIL(Sfio_t*)); if(f->mode&SF_INIT) /* paranoia in case another thread snuck in */ { if(f->file >= 0 && !(f->flags&SF_STRING) && (oflags &= (O_TEXT|O_BINARY|O_APPEND)) != 0 ) { /* set the wanted file access control flags */ int ctl = fcntl(f->file, F_GETFL, 0); ctl = (ctl & ~(O_TEXT|O_BINARY|O_APPEND)) | oflags; fcntl(f->file, F_SETFL, ctl); } /* set all non read-write flags */ f->flags |= (sflags & (SF_FLAGS & ~SF_RDWR)); /* reset read/write modes */ if((sflags &= SF_RDWR) != 0) { f->flags = (f->flags & ~SF_RDWR) | sflags; if((f->flags&SF_RDWR) == SF_RDWR) f->bits |= SF_BOTH; else f->bits &= ~SF_BOTH; if(f->flags&SF_READ) f->mode = (f->mode&~SF_WRITE)|SF_READ; else f->mode = (f->mode&~SF_READ)|SF_WRITE; } SFMTXRETURN(f,f); } else SFMTXRETURN(f,NIL(Sfio_t*)); } if(sflags&SF_STRING) { f = sfnew(f,(char*)file, file ? (size_t)strlen((char*)file) : (size_t)SF_UNBOUND, -1,sflags); } else { if(!file) return NIL(Sfio_t*); #if _has_oflags /* open the file */ while((fd = open((char*)file,oflags,SF_CREATMODE)) < 0 && errno == EINTR) errno = 0; #else while((fd = open(file,oflags&(O_WRONLY|O_RDWR))) < 0 && errno == EINTR) errno = 0; if(fd >= 0) { if((oflags&(O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ) { CLOSE(fd); /* error: file already exists */ return NIL(Sfio_t*); } if(oflags&O_TRUNC ) /* truncate file */ { reg int tf; while((tf = creat(file,SF_CREATMODE)) < 0 && errno == EINTR) errno = 0; CLOSE(tf); } } else if(oflags&O_CREAT) { while((fd = creat(file,SF_CREATMODE)) < 0 && errno == EINTR) errno = 0; if(!(oflags&O_WRONLY)) { /* the file now exists, reopen it for read/write */ CLOSE(fd); while((fd = open(file,oflags&(O_WRONLY|O_RDWR))) < 0 && errno == EINTR) errno = 0; } } #endif if(fd < 0) return NIL(Sfio_t*); /* we may have to reset the file descriptor to its old value */ oldfd = f ? f->file : -1; if((f = sfnew(f,NIL(char*),(size_t)SF_UNBOUND,fd,sflags)) && oldfd >= 0) (void)sfsetfd(f,oldfd); } return f; } #if __STD_C int _sftype(reg const char* mode, int* oflagsp, int* uflagp) #else int _sftype(mode, oflagsp, uflagp) reg char* mode; int* oflagsp; int* uflagp; #endif { reg int sflags, oflags, uflag; if(!mode) return 0; /* construct the open flags */ sflags = oflags = uflag = 0; while(1) switch(*mode++) { case 'w' : sflags |= SF_WRITE; oflags |= O_WRONLY | O_CREAT; if(!(sflags&SF_READ)) oflags |= O_TRUNC; continue; case 'a' : sflags |= SF_WRITE | SF_APPENDWR; oflags |= O_WRONLY | O_APPEND | O_CREAT; continue; case 'r' : sflags |= SF_READ; oflags |= O_RDONLY; continue; case 's' : sflags |= SF_STRING; continue; case 'b' : oflags |= O_BINARY; continue; case 't' : oflags |= O_TEXT; continue; case 'x' : oflags |= O_EXCL; continue; case '+' : if(sflags) sflags |= SF_READ|SF_WRITE; continue; case 'm' : sflags |= SF_MTSAFE; uflag = 0; continue; case 'u' : sflags &= ~SF_MTSAFE; uflag = 1; continue; default : if(!(oflags&O_CREAT) ) oflags &= ~O_EXCL; if((sflags&SF_RDWR) == SF_RDWR) oflags = (oflags&~(O_RDONLY|O_WRONLY))|O_RDWR; if(oflagsp) *oflagsp = oflags; if(uflagp) *uflagp = uflag; if((sflags&(SF_STRING|SF_RDWR)) == SF_STRING) sflags |= SF_READ; return sflags; } } O_EXCL; continue; case '+' : if(sflags) sflags |= SF_READ|SF_WRITE; continue; case 'm' : sflags |= SF_MTSAFE; uflag = 0; continue; case 'u' : sflags &= ~SF_MTSAFE; uflag = 1; continue; default : if(!(oflags&O_CREAT) ) oflags &= ~O_EXCL; if((sflags&SF_RDWR) == SF_RDWR) oflags = (oflags&~(O_RDONLY|O_WRONLY))|O_RDWR; if(oflagsp) *oflagsp = oflags; if(uflagp) *uflagp = uflag; if((sflags&(SF_STRING|SF_src/lib/sfio/vthread.h000644 151361 151361 00000012735 07432261527 014653 0ustar00kpvkpv000000 000000 #ifndef _VTHREAD_H #define _VTHREAD_H 1 /******************************************************************************** * This product contains certain software code or other information * * ("AT&T Software") proprietary to AT&T Corp. ("AT&T"). * * The AT&T Software is provided to you "AS IS". YOU ASSUME TOTAL * * RESPONSIBILITY AND RISK FOR USE OF THE AT&T SOFTWARE. * * AT&T DOES NOT MAKE, AND EXPRESSLY DISCLAIMS, ANY EXPRESS OR * * IMPLIED WARRANTIES OF ANY KIND WHATSOEVER, INCLUDING, * * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR * * FITNESS FOR A PARTICULAR PURPOSE, WARRANTIES OF TITLE OR * * NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS, * * ANY WARRANTIES ARISING BY USAGE OF TRADE, COURSE OF DEALING OR * * COURSE OF PERFORMANCE, OR ANY WARRANTY THAT THE AT&T SOFTWARE * * IS "ERROR FREE" OR WILL MEET YOUR REQUIREMENTS. * * * * All rights reserved. AT&T is a registered trademark of AT&T Corp. * ********************************************************************************/ #define VTHREAD_VERSION 20001201L /* Header for the Vthread library. ** Note that the macro vt_threaded may be defined ** outside of vthread.h to suppress threading. ** ** Written by Kiem-Phong Vo, kpv@research.att.com */ #include #include /* ast doesn't do threads yet */ #if _PACKAGE_ast && !defined(vt_threaded) #define vt_threaded 0 #endif #if !defined(vt_threaded) || (defined(vt_threaded) && vt_threaded == 1) #define _may_use_threads 1 #else #define _may_use_threads 0 #endif #undef vt_threaded #if _may_use_threads && !defined(vt_threaded) && _hdr_pthread #define vt_threaded 1 #include typedef pthread_mutex_t _vtmtx_t; typedef pthread_once_t _vtonce_t; typedef pthread_t _vtself_t; typedef pthread_t _vtid_t; typedef pthread_attr_t _vtattr_t; #if !defined(PTHREAD_ONCE_INIT) && defined(pthread_once_init) #define PTHREAD_ONCE_INIT pthread_once_init #endif #endif #if _may_use_threads && !defined(vt_threaded) && _WIN32 #define vt_threaded 1 #include typedef CRITICAL_SECTION _vtmtx_t; typedef int _vtonce_t; typedef HANDLE _vtself_t; typedef DWORD _vtid_t; typedef SECURITY_ATTRIBUTES _vtattr_t; #endif #ifndef vt_threaded #define vt_threaded 0 #endif /* common attributes for various structures */ #define VT_RUNNING 000000001 /* thread is running */ #define VT_SUSPENDED 000000002 /* thread is suspended */ #define VT_WAITED 000000004 /* thread has been waited */ #define VT_FREE 000010000 /* object can be freed */ #define VT_INIT 000020000 /* object was initialized */ #define VT_BITS 000030007 /* bits that we care about */ /* directives for vtset() */ #define VT_STACK 1 /* set stack size */ typedef struct _vtmutex_s Vtmutex_t; typedef struct _vtonce_s Vtonce_t; typedef struct _vthread_s Vthread_t; #ifndef EINVAL #define EINVAL 22 #endif #ifndef EBUSY #define EBUSY 16 #endif #ifndef EDEADLK #define EDEADLK 45 #endif #ifndef EPERM #define EPERM 1 #endif _BEGIN_EXTERNS_ extern Vthread_t* vtopen _ARG_((Vthread_t*, int)); extern int vtclose _ARG_((Vthread_t*)); extern int vtset _ARG_((Vthread_t*, int, Void_t*)); extern int vtrun _ARG_((Vthread_t*, void*(*)(void*), void*)); extern int vtkill _ARG_((Vthread_t*)); extern int vtwait _ARG_((Vthread_t*)); extern int vtonce _ARG_((Vtonce_t*, void(*)() )); extern Vtmutex_t* vtmtxopen _ARG_((Vtmutex_t*, int)); extern int vtmtxclose _ARG_((Vtmutex_t*)); extern int vtmtxlock _ARG_((Vtmutex_t*)); extern int vtmtxtrylock _ARG_((Vtmutex_t*)); extern int vtmtxunlock _ARG_((Vtmutex_t*)); extern int vtmtxclrlock _ARG_((Vtmutex_t*)); extern Void_t* vtstatus _ARG_((Vthread_t*)); extern int vterror _ARG_((Vthread_t*)); extern int vtmtxerror _ARG_((Vtmutex_t*)); extern int vtonceerror _ARG_((Vtonce_t*)); _END_EXTERNS_ #if vt_threaded /* mutex structure */ struct _vtmutex_s { _vtmtx_t lock; int count; _vtid_t owner; int state; int error; }; /* structure for states of thread */ struct _vthread_s { _vtself_t self; /* self-handle */ _vtid_t id; /* thread id */ _vtattr_t attrs; /* attributes */ size_t stack; /* stack size */ int state; /* execution state */ int error; /* error status */ Void_t* exit; /* exit value */ }; /* structure for exactly once execution */ struct _vtonce_s { int done; _vtonce_t once; int error; }; #if _WIN32 #define VTONCE_INITDATA {0, 0} #else #define VTONCE_INITDATA {0, PTHREAD_ONCE_INIT } #endif #define vtstatus(vt) ((vt)->exit) #define vterror(vt) ((vt)->error) #define vtmtxerror(mtx) ((mtx)->error) #define vtonceerror(once) ((once)->error) #endif /*vt_threaded*/ /* fake structures and functions */ #if !vt_threaded struct _vtmutex_s { int error; }; struct _vtattr_s { int error; }; struct _vthread_s { int error; }; struct _vtonce_s { int error; }; typedef int _vtmtx_t; typedef int _vtonce_t; typedef int _vtself_t; typedef int _vtid_t; typedef int _vtattr_t; #define VTONCE_INITDATA {0} #define vtopen(vt,flgs) ((Vthread_t*)0) #define vtclose(vt) (-1) #define vtkill(vt) (-1) #define vtwait(vt) (-1) #define vtrun(vt,fn,arg) (-1) #define vtset(vt,t,v) (-1) #define vtonce(on,fu) (-1) #define vtmtxopen(mtx,flgs) ((Vtmutex_t*)0) #define vtmtxclose(mtx) (-1) #define vtmtxlock(mtx) (-1) #define vtmtxtrylock(mtx) (-1) #define vtmtxunlock(mtx) (-1) #define vtmtxclrlock(mtx) (-1) #define vtstatus(vt) ((Void_t*)0) #define vterror(vt) (0) #define vtmtxerror(mtx) (0) #define vtonceerror(once) (0) #endif /*!vt_threaded*/ #endif /*_VTHREAD_H*/ (vt) (-1) #define vtkill(vt) (-1)src/lib/sfio/sffrexp.c000644 151361 151361 00000005120 07436775771 014673 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #if !_PACKAGE_ast /* * frexp[l]/ldexp[l] implementation */ /* this is the template part. We expect the following macros to be defined: _dbl_t: type of a double. _pow2: name of array of power of twos. _initpow2: function to initialize the table. _dbl_max: max for a double value _dbl_max_exp: max exponent for a double value. */ #if defined(_frexp_) || defined(_ldexp_) static _dbl_t _pow2[_dbl_max_exp]; static void _initpow2() { int x; _dbl_t g; for(g = 1, x = 0;; x++, g *= 2) { _pow2[x] = g; if(x == sizeof(_pow2)/sizeof(_pow2[0])-1) break; } } #endif /* _frexp_ || _ldexp_ */ #if defined(_frexp_) /* now define the function frexp or frexpl */ #if __STD_C extern _dbl_t _frexp_(_dbl_t f, int* p) #else extern _dbl_t _frexp_(f, p) _dbl_t f; int* p; #endif { int k, x; _dbl_t g; /* initialize power-of-2 table. the below test handles concurrency */ if(_pow2[sizeof(_pow2)/sizeof(_pow2[0])-1] == 0) _initpow2(); /* * normalize */ x = k = _dbl_max_exp / 2; if (f < 1) { g = ((_dbl_t)1) / f; for (;;) { k = (k + 1) / 2; if (g < _pow2[x]) x -= k; else if (k == 1 && g < _pow2[x+1]) break; else x += k; } if (g == _pow2[x]) x--; x = -x; } else if (f > 1) { for (;;) { k = (k + 1) / 2; if (f > _pow2[x]) x += k; else if (k == 1 && f > _pow2[x-1]) break; else x -= k; } if (f == _pow2[x]) x++; } else x = 1; *p = x; /* * shift */ x = -x; if (x < 0) f /= _pow2[-x]; else if (x < _dbl_max_exp) f *= _pow2[x]; else f = (f * _pow2[_dbl_max_exp - 1]) * _pow2[x - (_dbl_max_exp - 1)]; return f; } #endif /* defined(_frexp_) */ #if defined(_ldexp_) #if __STD_C extern _dbl_t _ldexp_(_dbl_t f, int x) #else extern _dbl_t _ldexp_(f, x) _dbl_t f; int x; #endif { if(_pow2[0] == 0) _initpow2(); if (x < 0) f /= _pow2[-x]; else if (x < _dbl_max_exp) f *= _pow2[x]; else f = (f * _pow2[_dbl_max_exp - 1]) * _pow2[x - (_dbl_max_exp - 1)]; return f; } #endif /* defined(_ldexp_) */ /* now define frexpl and ldexpl as needed */ #if !_lib_frexpl && _ast_fltmax_double && _lib_frexp #undef _lib_frexpl #define _lib_frexpl 1 /* frexpl will be redefined to frexp */ #endif #if !_lib_frexpl #undef _lib_frexpl #define _lib_frexpl 2 #define _dbl_t _ast_fltmax_t #define _pow2 ldblpow2 #if defined(LDBL_MAX_EXP) #define _dbl_max_exp LDBL_MAX_EXP #else #define _dbl_max_exp DBL_MAX_EXP #endif #define _frexp_ frexpl #define _ldexp_ ldexpl #include "sffrexp.c" #endif /* !_lib_frexpl */ #endif /*!_PACKAGE_ast*/ #if _PACKAGE_ast || _lib_frexpl == 1 int _Sf_frexpl_in_standard_library = 1; #endif def _lib_frexpl #define _lib_frexpl 1 /* frexpl will be redefined to frexp */ #endif #if !_lib_frexpl #undef _lib_frexpl #define _lib_frexpl 2 #define _dbl_t _ast_fltmax_t #define _pow2 ldblpow2 #if defined(LDBL_MAX_EXP) #define _dbl_max_exp LDBL_MAX_EXP #else #define _dbl_max_exp DBL_MAX_EXP #endif #define _frexp_ frexpl #define _ldexp_ ldexpl #include "sffrexp.c" #endif /* !_lib_frexpl */ #endif /*!_PACKAGE_ast*/ #if src/lib/sfio/sfnputc.c000644 151361 151361 00000002013 07432261524 014654 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Write out a character n times ** ** Written by Kiem-Phong Vo. */ #if __STD_C ssize_t sfnputc(reg Sfio_t* f, reg int c, reg size_t n) #else ssize_t sfnputc(f,c,n) reg Sfio_t* f; /* file to write */ reg int c; /* char to be written */ reg size_t n; /* number of time to repeat */ #endif { reg uchar* ps; reg ssize_t p, w; uchar buf[128]; reg int local; SFMTXSTART(f,-1); GETLOCAL(f,local); if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0) SFMTXRETURN(f, -1); SFLOCK(f,local); /* write into a suitable buffer */ if((size_t)(p = (f->endb-(ps = f->next))) < n) { ps = buf; p = sizeof(buf); } if((size_t)p > n) p = n; MEMSET(ps,c,p); ps -= p; w = n; if(ps == f->next) { /* simple sfwrite */ f->next += p; if(c == '\n') (void)SFFLSBUF(f,-1); goto done; } for(;;) { /* hard write of data */ if((p = SFWRITE(f,(Void_t*)ps,p)) <= 0 || (n -= p) <= 0) { w -= n; goto done; } if((size_t)p > n) p = n; } done : SFOPEN(f,local); SFMTXRETURN(f, w); } ocal); /* write into a suitable buffer */ if((size_t)(p = (f->endb-(ps = f->next))) < n) { ps = buf; p = sizeof(buf); } if((size_t)p > n) p = n; MEMSET(ps,c,p); ps -= p; w = n; if(ps == f->next) { /* simple sfwrite */ f->next += p; if(c == '\n') (void)SFFLSBUF(f,-1); goto done; } for(;;) { /* hard write of data */ if((p = SFWRITE(f,(Void_t*)ps,p)) <= 0 || (n -= p) <= 0) { w -= n; goto done; } if((size_t)p > n) p = n; } done : SFOPEN(f,local); SFMTXRETURsrc/lib/sfio/sfset.c000644 151361 151361 00000002573 07432261526 014333 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Set some control flags or file descript for the stream ** ** Written by Kiem-Phong Vo. */ #if __STD_C int sfset(reg Sfio_t* f, reg int flags, reg int set) #else int sfset(f,flags,set) reg Sfio_t* f; reg int flags; reg int set; #endif { reg int oflags; SFMTXSTART(f,0); if(flags == 0 && set == 0) SFMTXRETURN(f, (f->flags&SF_FLAGS)); if((oflags = (f->mode&SF_RDWR)) != (int)f->mode && _sfmode(f,oflags,0) < 0) SFMTXRETURN(f, 0); if(flags == 0) SFMTXRETURN(f, (f->flags&SF_FLAGS)); SFLOCK(f,0); /* preserve at least one rd/wr flag */ oflags = f->flags; if(!(f->bits&SF_BOTH) || (flags&SF_RDWR) == SF_RDWR ) flags &= ~SF_RDWR; /* set the flag */ if(set) f->flags |= (flags&SF_SETS); else f->flags &= ~(flags&SF_SETS); /* must have at least one of read/write */ if(!(f->flags&SF_RDWR)) f->flags |= (oflags&SF_RDWR); if(f->extent < 0) f->flags &= ~SF_APPENDWR; /* turn to appropriate mode as necessary */ if((flags &= SF_RDWR) ) { if(!set) { if(flags == SF_READ) flags = SF_WRITE; else flags = SF_READ; } if((flags == SF_WRITE && !(f->mode&SF_WRITE)) || (flags == SF_READ && !(f->mode&(SF_READ|SF_SYNCED))) ) (void)_sfmode(f,flags,1); } /* if not shared or unseekable, public means nothing */ if(!(f->flags&SF_SHARE) || f->extent < 0) f->flags &= ~SF_PUBLIC; SFOPEN(f,0); SFMTXRETURN(f, (oflags&SF_FLAGS)); } ) f->flags &= ~SF_APPENDWR; /* turn to appropriate mode as necessary */ if((flags &= SF_RDWR) ) { if(!set) { if(flags == SF_Rsrc/lib/sfio/sfcvt.c000644 151361 151361 00000013155 07457435107 014337 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Convert a floating point value to ASCII. ** ** Written by Kiem-Phong Vo and Glenn Fowler (SFFMT_AFORMAT) */ static char *Inf = "Inf", *Zero = "0"; #define SF_INTPART (SF_IDIGITS/2) #define SF_INFINITE ((_Sfi = 3), Inf) #define SF_ZERO ((_Sfi = 1), Zero) #if __STD_C char* _sfcvt(Sfdouble_t dv, char* buf, size_t size, int n_digit, int* decpt, int* sign, int* len, int format) #else char* _sfcvt(dv,buf,size,n_digit,decpt,sign,len,format) Sfdouble_t dv; /* value to convert */ char* buf; /* conversion goes here */ size_t size; /* size of buf */ int n_digit; /* number of digits wanted */ int* decpt; /* to return decimal point */ int* sign; /* to return sign */ int* len; /* return string length */ int format; /* conversion format */ #endif { reg char *sp; reg long n, v; reg char *ep, *b, *endsp; _ast_flt_unsigned_max_t m; static char lx[] = "0123456789abcdef"; static char ux[] = "0123456789ABCDEF"; *sign = *decpt = 0; #if !_ast_fltmax_double if(format&SFFMT_LDOUBLE) { Sfdouble_t f = dv; if(f == 0.) return SF_ZERO; else if((*sign = (f < 0.)) ) /* assignment = */ f = -f; if(f < LDBL_MIN) return SF_ZERO; else if(f > LDBL_MAX) return SF_INFINITE; if(format & SFFMT_AFORMAT) { Sfdouble_t g; int x; b = sp = buf; ep = (format & SFFMT_UPPER) ? ux : lx; if(n_digit <= 0 || n_digit >= (size - 9)) n_digit = size - 9; endsp = sp + n_digit + 1; g = frexpl(f, &x); *decpt = x; f = ldexpl(g, 8 * sizeof(m) - 3); for (;;) { m = f; x = 8 * sizeof(m); while ((x -= 4) >= 0) { *sp++ = ep[(m >> x) & 0xf]; if (sp >= endsp) { ep = sp + 1; goto done; } } f -= m; f = ldexpl(f, 8 * sizeof(m)); } } n = 0; if(f >= (Sfdouble_t)SF_MAXLONG) { /* scale to a small enough number to fit an int */ v = SF_MAXEXP10-1; do { if(f < _Sfpos10[v]) v -= 1; else { f *= _Sfneg10[v]; if((n += (1<= SF_IDIGITS) return SF_INFINITE; } } while(f >= (Sfdouble_t)SF_MAXLONG); } *decpt = (int)n; b = sp = buf + SF_INTPART; if((v = (int)f) != 0) { /* translate the integer part */ f -= (Sfdouble_t)v; sfucvt(v,sp,n,ep,long,ulong); n = b-sp; if((*decpt += (int)n) >= SF_IDIGITS) return SF_INFINITE; b = sp; sp = buf + SF_INTPART; } else n = 0; /* remaining number of digits to compute; add 1 for later rounding */ n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n; if(n_digit > 0) { if(n_digit > LDBL_DIG) n_digit = LDBL_DIG; n += n_digit; } if((ep = (sp+n)) > (endsp = buf+(size-2))) ep = endsp; if(sp > ep) sp = ep; else { if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.) { Sfdouble_t d; while((int)(d = f*10.) == 0) { f = d; *decpt -= 1; } } while(sp < ep) { /* generate fractional digits */ if(f <= 0.) { /* fill with 0's */ do { *sp++ = '0'; } while(sp < ep); goto done; } else if((n = (long)(f *= 10.)) < 10) { *sp++ = '0' + n; f -= n; } else /* n == 10 */ { do { *sp++ = '9'; } while(sp < ep); } } } } else #endif { double f = (double)dv; if(f == 0.) return SF_ZERO; else if((*sign = (f < 0.)) ) /* assignment = */ f = -f; if(f < DBL_MIN) return SF_ZERO; else if(f > DBL_MAX) return SF_INFINITE; if(format & SFFMT_AFORMAT) { double g; int x; b = sp = buf; ep = (format & SFFMT_UPPER) ? ux : lx; if(n_digit <= 0 || n_digit >= (size - 9)) n_digit = size - 9; endsp = sp + n_digit; g = frexp(f, &x); *decpt = x; f = ldexp(g, 8 * sizeof(m) - 3); for (;;) { m = f; x = 8 * sizeof(m); while ((x -= 4) >= 0) { *sp++ = ep[(m >> x) & 0xf]; if (sp >= endsp) { ep = sp + 1; goto done; } } f -= m; f = ldexp(f, 8 * sizeof(m)); } } n = 0; if(f >= (double)SF_MAXLONG) { /* scale to a small enough number to fit an int */ v = SF_MAXEXP10-1; do { if(f < _Sfpos10[v]) v -= 1; else { f *= _Sfneg10[v]; if((n += (1<= SF_IDIGITS) return SF_INFINITE; } } while(f >= (double)SF_MAXLONG); } *decpt = (int)n; b = sp = buf + SF_INTPART; if((v = (int)f) != 0) { /* translate the integer part */ f -= (double)v; sfucvt(v,sp,n,ep,long,ulong); n = b-sp; if((*decpt += (int)n) >= SF_IDIGITS) return SF_INFINITE; b = sp; sp = buf + SF_INTPART; } else n = 0; /* remaining number of digits to compute; add 1 for later rounding */ n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n; if(n_digit > 0) { if(n_digit > DBL_DIG) n_digit = DBL_DIG; n += n_digit; } if((ep = (sp+n)) > (endsp = buf+(size-2))) ep = endsp; if(sp > ep) sp = ep; else { if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.) { reg double d; while((int)(d = f*10.) == 0) { f = d; *decpt -= 1; } } while(sp < ep) { /* generate fractional digits */ if(f <= 0.) { /* fill with 0's */ do { *sp++ = '0'; } while(sp < ep); goto done; } else if((n = (int)(f *= 10.)) < 10) { *sp++ = (char)('0' + n); f -= n; } else /* n == 10 */ { do { *sp++ = '9'; } while(sp < ep); } } } } if(ep <= b) ep = b+1; else if(ep < endsp) { /* round the last digit */ *--sp += 5; while(*sp > '9') { *sp = '0'; if(sp > b) *--sp += 1; else { /* next power of 10 */ *sp = '1'; *decpt += 1; if(!(format&SFFMT_EFORMAT)) { /* add one more 0 for %f precision */ ep[-1] = '0'; ep += 1; } } } } done: *--ep = '\0'; if(len) *len = ep-b; return b; } f -= n; } else /* n == 10 */ { do { *sp++ = '9'; } while(sp < ep); } } } } if(ep <= b) ep = b+1; else if(ep < endsp) { /* round the last digit */ *--sp += 5; while(*sp > '9') { *sp = '0'; if(sp > b) *--sp += 1; else { /* next power of 10 */ *sp = '1'; *decpt += 1; if(!(format&SFFMT_EFORMAT)) { /* add one more 0 for %f precision */ src/lib/sfio/sfsetfd.c000644 151361 151361 00000004201 07432261526 014633 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Change the file descriptor ** ** Written by Kiem-Phong Vo. */ #if __STD_C static int _sfdup(reg int fd, reg int newfd) #else static int _sfdup(fd,newfd) reg int fd; reg int newfd; #endif { reg int dupfd; #ifdef F_DUPFD /* the simple case */ while((dupfd = fcntl(fd,F_DUPFD,newfd)) < 0 && errno == EINTR) errno = 0; return dupfd; #else /* do it the hard way */ if((dupfd = dup(fd)) < 0 || dupfd >= newfd) return dupfd; /* dup() succeeded but didn't get the right number, recurse */ newfd = _sfdup(fd,newfd); /* close the one that didn't match */ CLOSE(dupfd); return newfd; #endif } #if __STD_C int sfsetfd(reg Sfio_t* f, reg int newfd) #else int sfsetfd(f,newfd) reg Sfio_t *f; reg int newfd; #endif { reg int oldfd; SFMTXSTART(f, -1); if(f->flags&SF_STRING) SFMTXRETURN(f, -1); if((f->mode&SF_INIT) && f->file < 0) { /* restoring file descriptor after a previous freeze */ if(newfd < 0) SFMTXRETURN(f, -1); } else { /* change file descriptor */ if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0) SFMTXRETURN(f, -1); SFLOCK(f,0); oldfd = f->file; if(oldfd >= 0) { if(newfd >= 0) { if((newfd = _sfdup(oldfd,newfd)) < 0) { SFOPEN(f,0); SFMTXRETURN(f, -1); } CLOSE(oldfd); } else { /* sync stream if necessary */ if(((f->mode&SF_WRITE) && f->next > f->data) || (f->mode&SF_READ) || f->disc == _Sfudisc) { if(SFSYNC(f) < 0) { SFOPEN(f,0); SFMTXRETURN(f, -1); } } if(((f->mode&SF_WRITE) && f->next > f->data) || ((f->mode&SF_READ) && f->extent < 0 && f->next < f->endb) ) { SFOPEN(f,0); SFMTXRETURN(f, -1); } #ifdef MAP_TYPE if((f->bits&SF_MMAP) && f->data) { SFMUNMAP(f,f->data,f->endb-f->data); f->data = NIL(uchar*); } #endif /* make stream appears uninitialized */ f->endb = f->endr = f->endw = f->data; f->extent = f->here = 0; f->mode = (f->mode&SF_RDWR)|SF_INIT; f->bits &= ~SF_NULL; /* off /dev/null handling */ } } SFOPEN(f,0); } /* notify changes */ if(_Sfnotify) (*_Sfnotify)(f,SF_SETFD,newfd); f->file = newfd; SFMTXRETURN(f,newfd); } RN(f, -1); } #ifdef MAP_TYPE if((f->bits&SF_MMAP) && f->data) { SFMUNMAP(f,f->data,f->endb-f->data); f->data = NIL(uchar*); } #endif /* make stream appears uninitialized */ f->endb = f->endr = f->endw = f->data; f->extent = f->here = 0; f->mode = (f->mode&SF_RDWR)|SF_INIT; f->bits &= ~SF_NULL; /* off /dev/null handling */ } } SFOPsrc/lib/sfio/sfmutex.c000644 151361 151361 00000001463 07432516301 014671 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Obtain/release exclusive use of a stream. ** ** Written by Kiem-Phong Vo. */ /* the main locking/unlocking interface */ #if __STD_C int sfmutex(Sfio_t* f, int type) #else int sfmutex(f, type) Sfio_t* f; int type; #endif { #if !vt_threaded NOTUSED(f); NOTUSED(type); return 0; #else SFONCE(); if(!f) return -1; if(!f->mutex) { if(f->bits&SF_PRIVATE) return 0; vtmtxlock(_Sfmutex); f->mutex = vtmtxopen(NIL(Vtmutex_t*), VT_INIT); vtmtxunlock(_Sfmutex); if(!f->mutex) return -1; } if(type == SFMTX_LOCK) return vtmtxlock(f->mutex); else if(type == SFMTX_TRYLOCK) return vtmtxtrylock(f->mutex); else if(type == SFMTX_UNLOCK) return vtmtxunlock(f->mutex); else if(type == SFMTX_CLRLOCK) return vtmtxclrlock(f->mutex); else return -1; #endif /*vt_threaded*/ } SFONCE(); if(!f) return -1; if(!f->mutex) { if(f->bits&SF_PRIVATE) return 0; vtmtxlock(_Sfmutex); f->mutex = vtmtxopen(NIL(Vtmutex_t*), VT_INIT); vtmtxunlock(_Sfmutex); if(!f->mutex) src/lib/sfio/sftmp.c000644 151361 151361 00000020342 07432261527 014333 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Create a temporary stream for read/write. ** The stream is originally created as a memory-resident stream. ** When this memory is exceeded, a real temp file will be created. ** The temp file creation sequence is somewhat convoluted so that ** pool/stack/discipline will work correctly. ** ** Written by David Korn and Kiem-Phong Vo. */ #if _tmp_rmfail /* File not removable while there is an open file descriptor. ** To ensure that temp files are properly removed, we need: ** 1. A discipline to remove a file when the corresponding stream is closed. ** Care must be taken to close the file descriptor before removing the ** file because systems such as NT do not allow file removal while ** there is an open file handle. ** 2. An atexit() function is set up to close temp files when process exits. ** 3. On systems with O_TEMPORARY (e.g., NT), this is used to further ensure ** that temp files will be removed after the last handle is closed. */ typedef struct _file_s File_t; struct _file_s { File_t* next; /* link list */ Sfio_t* f; /* associated stream */ char name[1]; /* temp file name */ }; static File_t* File; /* list pf temp files */ #if __STD_C static int _tmprmfile(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc) #else static int _tmprmfile(f, type, val, disc) Sfio_t* f; int type; Void_t* val; Sfdisc_t* disc; #endif { reg File_t *ff, *last; NOTUSED(val); if(type == SF_DPOP) /* don't allow this to pop */ return -1; if(type == SF_CLOSING) { vtmtxlock(_Sfmutex); for(last = NIL(File_t*), ff = File; ff; last = ff, ff = ff->next) if(ff->f == f) break; if(ff) { if(!last) File = ff->next; else last->next = ff->next; if(_Sfnotify) (*_Sfnotify)(f,SF_CLOSING,f->file); CLOSE(f->file); f->file = -1; while(remove(ff->name) < 0 && errno == EINTR) errno = 0; free((Void_t*)ff); } vtmtxunlock(_Sfmutex); } return 0; } #if __STD_C static void _rmfiles(void) #else static void _rmfiles() #endif { reg File_t *ff, *next; vtmtxlock(_Sfmutex); for(ff = File; ff; ff = next) { next = ff->next; _tmprmfile(ff->f, SF_CLOSING, NIL(Void_t*), ff->f->disc); } vtmtxunlock(_Sfmutex); } static Sfdisc_t Rmdisc = { NIL(Sfread_f), NIL(Sfwrite_f), NIL(Sfseek_f), _tmprmfile, NIL(Sfdisc_t*) }; #endif /*_tmp_rmfail*/ #if __STD_C static int _rmtmp(Sfio_t* f, char* file) #else static int _rmtmp(f, file) Sfio_t* f; char* file; #endif { #if _tmp_rmfail /* remove only when stream is closed */ reg File_t* ff; if(!File) atexit(_rmfiles); if(!(ff = (File_t*)malloc(sizeof(File_t)+strlen(file))) ) return -1; vtmtxlock(_Sfmutex); ff->f = f; strcpy(ff->name,file); ff->next = File; File = ff; vtmtxunlock(_Sfmutex); #else /* can remove now */ f = 0; while(remove(file) < 0 && errno == EINTR) errno = 0; #endif return 0; } #if !_PACKAGE_ast #define TMPDFLT "/tmp" static char **Tmppath, **Tmpcur; #if __STD_C char** _sfgetpath(char* path) #else char** _sfgetpath(path) char* path; #endif { reg char *p, **dirs; reg int n; if(!(path = getenv(path)) ) return NIL(char**); for(p = path, n = 0;;) /* count number of directories */ { while(*p == ':') ++p; if(*p == 0) break; n += 1; while(*p && *p != ':') /* skip dir name */ ++p; } if(n == 0 || !(dirs = (char**)malloc((n+1)*sizeof(char*))) ) return NIL(char**); if(!(p = (char*)malloc(strlen(path)+1)) ) { free(dirs); return NIL(char**); } strcpy(p,path); for(n = 0;; ++n) { while(*p == ':') ++p; if(*p == 0) break; dirs[n] = p; while(*p && *p != ':') ++p; if(*p == ':') *p++ = 0; } dirs[n] = NIL(char*); return dirs; } #endif /*!_PACKAGE_ast*/ #if __STD_C static int _tmpfd(Sfio_t* f) #else static int _tmpfd(f) Sfio_t* f; #endif { reg char* file; reg int fd; int t; #if !_PACKAGE_ast /* set up path of dirs to create temp files */ if(!Tmppath && !(Tmppath = _sfgetpath("TMPPATH")) ) { if(!(Tmppath = (char**)malloc(2*sizeof(char*))) ) return -1; if(!(file = getenv("TMPDIR")) ) file = TMPDFLT; if(!(Tmppath[0] = (char*)malloc(strlen(file)+1)) ) { free(Tmppath); Tmppath = NIL(char**); return -1; } strcpy(Tmppath[0],file); Tmppath[1] = NIL(char*); } /* set current directory to create this temp file */ if(Tmpcur) Tmpcur += 1; if(!Tmpcur || !Tmpcur[0]) Tmpcur = Tmppath; #endif /*!_PACKAGE_ast*/ file = NIL(char*); fd = -1; for(t = 0; t < 10; ++t) { /* compute a random name */ #if !_PACKAGE_ast static ulong Key, A; if(A == 0 || t > 0) /* get a quasi-random coefficient */ { reg int r; A = (ulong)time(NIL(time_t*)) ^ (((ulong)(&t)) >> 3); if(Key == 0) Key = (A >> 16) | ((A&0xffff)<<16); A ^= Key; if((r = (A-1) & 03) != 0) /* Knuth vol.2, page.16, Thm.A */ A += 4-r; } Key = A*Key + 987654321; file = sfprints("%s/sf%3.3.32lu.%3.3.32lu", Tmpcur[0], (Key>>15)&0x7fff, Key&0x7fff); #else file = pathtmp(file,NiL,"sf",NiL); #endif /*!_PACKAGE_ast*/ if(!file) return -1; #if _has_oflags if((fd = open(file,O_RDWR|O_CREAT|O_EXCL|O_TEMPORARY,SF_CREATMODE)) >= 0) break; #else if((fd = open(file,O_RDONLY)) >= 0) { /* file already exists */ CLOSE(fd); fd = -1; } else if((fd = creat(file,SF_CREATMODE)) >= 0) { /* reopen for read and write */ CLOSE(fd); if((fd = open(file,O_RDWR)) >= 0) break; /* don't know what happened but must remove file */ while(remove(file) < 0 && errno == EINTR) errno = 0; } #endif } if(fd >= 0) _rmtmp(f, file); #if _PACKAGE_ast free(file); #endif /*_PACKAGE_ast*/ return fd; } #if __STD_C static int _tmpexcept(Sfio_t* f, int type, Void_t* val, Sfdisc_t* disc) #else static int _tmpexcept(f,type,val,disc) Sfio_t* f; int type; Void_t* val; Sfdisc_t* disc; #endif { reg int fd, m; reg Sfio_t* sf; Sfio_t newf, savf; void (*notifyf)_ARG_((Sfio_t*, int, int)); NOTUSED(val); /* the discipline needs to change only under the following exceptions */ if(type != SF_WRITE && type != SF_SEEK && type != SF_DPUSH && type != SF_DPOP && type != SF_DBUFFER) return 0; /* notify function */ notifyf = _Sfnotify; /* try to create the temp file */ SFCLEAR(&newf,NIL(Vtmutex_t*)); newf.flags = SF_STATIC; newf.mode = SF_AVAIL; if((fd = _tmpfd(f)) < 0 ) return -1; /* make sure that the notify function won't be called here since we are only interested in creating the file, not the stream */ _Sfnotify = 0; sf = sfnew(&newf,NIL(Void_t*),(size_t)SF_UNBOUND,fd,SF_READ|SF_WRITE); _Sfnotify = notifyf; if(!sf) return -1; if(newf.mutex) /* don't need a mutex for this stream */ { vtmtxclrlock(newf.mutex); vtmtxclose(newf.mutex); newf.mutex = NIL(Vtmutex_t*); } /* make sure that new stream has the same mode */ if((m = f->flags&(SF_READ|SF_WRITE)) != (SF_READ|SF_WRITE)) sfset(sf, ((~m)&(SF_READ|SF_WRITE)), 0); sfset(sf, (f->mode&(SF_READ|SF_WRITE)), 1); /* now remake the old stream into the new image */ memcpy((Void_t*)(&savf), (Void_t*)f, sizeof(Sfio_t)); memcpy((Void_t*)f, (Void_t*)sf, sizeof(Sfio_t)); f->push = savf.push; f->pool = savf.pool; f->rsrv = savf.rsrv; f->proc = savf.proc; f->mutex = savf.mutex; f->stdio = savf.stdio; if(savf.data) { SFSTRSIZE(&savf); if(!(savf.flags&SF_MALLOC) ) (void)sfsetbuf(f,(Void_t*)savf.data,savf.size); if(savf.extent > 0) (void)sfwrite(f,(Void_t*)savf.data,(size_t)savf.extent); (void)sfseek(f,(Sfoff_t)(savf.next - savf.data),0); if((savf.flags&SF_MALLOC) ) free((Void_t*)savf.data); } /* announce change of status */ if(notifyf) (*notifyf)(f,SF_NEW,f->file); f->disc = disc->disc; /* erase all traces of newf */ newf.data = newf.endb = newf.endr = newf.endw = NIL(uchar*); newf.file = -1; sfclose(&newf); return 1; } #if __STD_C Sfio_t* sftmp(reg size_t s) #else Sfio_t* sftmp(s) reg size_t s; #endif { reg Sfio_t* f; static Sfdisc_t Tmpdisc = { NIL(Sfread_f), NIL(Sfwrite_f), NIL(Sfseek_f), _tmpexcept, #if _tmp_rmfail &Rmdisc #else NIL(Sfdisc_t*) #endif }; /* start with a memory resident stream */ if(!(f = sfnew(NIL(Sfio_t*),NIL(char*),s,-1,SF_STRING|SF_READ|SF_WRITE)) ) return NIL(Sfio_t*); if(s != (size_t)SF_UNBOUND) /* set up a discipline for out-of-bound, etc. */ f->disc = &Tmpdisc; /* make the file now */ if(s == 0 && _tmpexcept(f,SF_DPOP,NIL(Void_t*),f->disc) < 0) { sfclose(f); return NIL(Sfio_t*); } return f; } NIL(Sfread_f), NIL(Sfwrite_f), NIL(Sfseek_f), _tmpexcept, #if _tmp_rmfail &Rmdisc #else NIL(Sfdisc_t*) #endif }; /* start with a memory resident stream */ if(!(f = sfnew(NIL(Sfio_t*),NIL(char*),s,-1,SF_STRING|SF_READ|SF_WRITE)) ) return NIL(Sfio_t*); if(s != (size_t)src/lib/sfio/README000644 151361 151361 00000007345 07477226126 013733 0ustar00kpvkpv000000 000000 This directory hierarchy has the source of Sfio, the Safe/Fast I/O library. Sfio provides all aspects of buffered I/O. Its interface is saner and its implementation is better than existing versions of the ANSI-C Stdio library. For backward compatibility, Sfio also provides packages allowing existing code based on Stdio to either recompile or relink using Sfio. DIRECTORY HIERARCHY: . : source code for Sfio. ./features: source code for generating configuration parameters. ./Sfio_f: function versions of sfio macros. ./Stdio_s: the source level compatibility package. ./Stdio_b: the binary level compatibility package. ./Sfio_dc: a collection of functions to create useful disciplines. ./Sfio_t: a set of regression tests for the Sfio library. ./Stdio_t: a set of regression tests for certain Stdio behaviors and for the compatibility packages. SOFTWARE CONSTRUCTION: The build procedure is based on the iffe language for automatic configuration. An iffe interpreter and its manual pages are included in this code distribution. See the files in ./features for examples of iffe probes to generate configuration parameters. There are two sets of libraries libsfio.a and libstdio.a: for uni-threaded applications, and libsfio-mt.a and libstdio-mt.a: for multi-threaded applications. To build the uni-threaded libraries, run the below command: make -f Makefile install To build the multi-threaded libraries, run the below command: make -f Makefile install_mt Depending on the local platform, an application using the multi-threaded libraries may need to specify a thread library at linkage time. For example, below are the known requirements for a few popular platforms: Irix, Linux, Solaris systems: -lpthread Hpux: -lcma BSD: none REGRESSION TESTING: To run the regression tests of Sfio only, first do "cd Sfio_t", then do: runtest this tests the uni-threaded library runtest -mt [-lthread_library as discussed above] this tests the multi-threaded library There are also a few regression tests for Stdio. To run these, first do "cd Stdio_t", then do: runtest this tests the native Stdio library. runtest -src this tests the uni-threaded library using the source compatibility mode. runtest -bin this tests the uni-threaded library using the binary compatibility mode. runtest -src -mt [-lthread_library as discussed above] this tests the multi-threaded library using the source compatibility mode. runtest -bin -mt [-lthread_library as discussed above] this tests the multi-threaded library using the binary compatibility mode. SFIO DISCIPLINES: IO disciplines allow applications to extend stream data processing. See the Sfio manual pages for detail on creating discipline structures and inserting them into streams. The directory Sfio_dc contains a number of useful disciplines, including one to uncompress a file compressed by the Unix compress program and one to make reading DOS text files more comfortable by translating \r\n to \n. Disciplines are reusable code, please contribute any interesting disciplines that you come up with. This is best done by sending such code to me at the address below. Sharing reusable code means that the name space must be managed. Therefore, I recommend that each discipline package provides the following public interface: Sfdisc_t* sfdcXXX(Sfio_t* f, other arguments): Create a discipline of the type XXX and insert it into the stream f. For example, the below call create a discipline that make the stream "f" act as if it's the union of the "n" streams given in "array". sfdcunion(Sfio_t* f, Sfio_t** array, int n); CORRESPONDENCE: Comments, etc. should be sent to: Phong Vo AT&T Labs - Research 180 Park Avenue Florham Park, NJ 07932 e-mail: kpv@research.att.com ne package provides the following public interface: Sfdisc_t* sfdcXXX(Sfio_t* f, other arguments): Create a discipline of the type XXX and insert it into the stream f. For example, the below call create a discipline that make the stream "f" act as if it's the union of the "n" stsrc/lib/sfio/sfreserve.c000644 151361 151361 00000006114 07432261525 015205 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Reserve a segment of data or buffer. ** ** Written by Kiem-Phong Vo. */ #if __STD_C Void_t* sfreserve(reg Sfio_t* f, ssize_t size, int type) #else Void_t* sfreserve(f,size,type) reg Sfio_t* f; /* file to peek */ ssize_t size; /* size of peek */ int type; /* LOCKR: lock stream, LASTR: last record */ #endif { reg ssize_t n, sz; reg Sfrsrv_t* rsrv; reg Void_t* data; reg int mode; SFMTXSTART(f,NIL(Void_t*)); /* initialize io states */ rsrv = NIL(Sfrsrv_t*); _Sfi = f->val = -1; /* return the last record */ if(type == SF_LASTR ) { if((rsrv = f->rsrv) && (n = -rsrv->slen) > 0) { rsrv->slen = 0; _Sfi = f->val = n; SFMTXRETURN(f, (Void_t*)rsrv->data); } else SFMTXRETURN(f, NIL(Void_t*)); } if(type > 0 && !(type == SF_LOCKR || type == 1) ) SFMTXRETURN(f, NIL(Void_t*)); if((sz = size) == 0 && type != 0) { /* only return the current status and possibly lock stream */ if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0) SFMTXRETURN(f, NIL(Void_t*)); SFLOCK(f,0); if((n = f->endb - f->next) < 0) n = 0; if(!f->data && type > 0) rsrv = _sfrsrv(f,0); goto done; } if(sz < 0) sz = -sz; /* iterate until get to a stream that has data or buffer space */ for(;;) { /* prefer read mode so that data is always valid */ if(!(mode = (f->flags&SF_READ)) ) mode = SF_WRITE; if((int)f->mode != mode && _sfmode(f,mode,0) < 0) { n = -1; goto done; } SFLOCK(f,0); if((n = f->endb - f->next) < 0) /* possible for string+rw */ n = 0; if(n > 0 && n >= sz) /* all done */ break; /* do a buffer refill or flush */ if(f->mode&SF_WRITE) (void)SFFLSBUF(f, -1); else if(type > 0 && f->extent < 0 && (f->flags&SF_SHARE) ) { if(n == 0) /* peek-read only if there is no buffered data */ { f->mode |= SF_RV; (void)SFFILBUF(f, sz == 0 ? -1 : (sz-n) ); } if((n = f->endb - f->next) < sz) { if(f->mode&SF_PKRD) { f->endb = f->endr = f->next; f->mode &= ~SF_PKRD; } goto done; } } else (void)SFFILBUF(f, sz == 0 ? -1 : (sz-n) ); /* now have data */ if((n = f->endb - f->next) > 0) break; else if(n < 0) n = 0; /* this test fails only if unstacked to an opposite stream */ if((f->mode&mode) != 0) break; } if(n > 0 && n < sz && (f->mode&mode) != 0 ) { /* try to accomodate request size */ if(f->flags&SF_STRING) { if((f->mode&SF_WRITE) && (f->flags&SF_MALLOC) ) { (void)SFWR(f,f->next,sz,f->disc); n = f->endb - f->next; } } else if(f->mode&SF_WRITE) { if(type > 0 && (rsrv = _sfrsrv(f,sz)) ) n = sz; } else /*if(f->mode&SF_READ)*/ { if(type <= 0 && (rsrv = _sfrsrv(f,sz)) && (n = SFREAD(f,(Void_t*)rsrv->data,sz)) < sz) rsrv->slen = -n; } } done: /* return true buffer size */ _Sfi = f->val = n; SFOPEN(f,0); if((sz > 0 && n < sz) || (n == 0 && type <= 0) ) SFMTXRETURN(f, NIL(Void_t*)); if((data = rsrv ? (Void_t*)rsrv->data : (Void_t*)f->next) ) { if(type > 0) { f->mode |= SF_PEEK; f->endr = f->endw = f->data; } else if(data == (Void_t*)f->next) f->next += (size >= 0 ? size : n); } SFMTXRETURN(f, data); } e <= 0 && (rsrv = _sfrsrv(f,sz)) && (n = SFREAD(f,(Void_t*)rsrv->data,sz)) < sz) rsrv->slen = -n; } } done: /* return true buffer size */ _Sfi = f->val = n; SFOPEN(f,0); if((sz > 0 && n < sz) || (n == 0 && type <= 0) ) SFMTXRETURN(f, NIL(Void_t*)); if((data = rsrv ? (Void_t*)rsrv->data : (Void_t*)f->next) ) { if(type > 0) { f->mode |= SF_PEEK; f->endr = f->endw = f->data; } else if(data == (Void_t*)src/lib/sfio/Makefile000644 151361 151361 00000015544 07433032446 014503 0ustar00kpvkpv000000 000000 # This Makefile builds both uni-threaded and multi-threaded versions # of the libraries. It can be used as: # 1. make install: build the uni-threaded version # 2. make install_mt: build the multi-threaded version # # Written by Kiem-Phong Vo LIBTYPE= INCDIR= ../../../include LIBDIR= ../../../lib BINDIR= ../../../bin # Compiler and flags to use CXFLAGS= CCMODE= -O CCFLAGS= -I. $(CCMODE) $(LIBTYPE) $(CXFLAGS) AR= ar CC= cc # sfio HDRS= sfio.h sfio_s.h sfio_t.h sfhdr.h vthread.h SRCS= sfclose.c sfclrlock.c sfcvt.c sfdisc.c sfdlen.c sfexcept.c \ sfextern.c sffilbuf.c sfflsbuf.c sfprints.c sfgetd.c sfgetl.c \ sfgetr.c sfgetu.c sfllen.c sfmode.c sfmove.c sfnew.c \ sfnotify.c sfnputc.c sfopen.c sfpkrd.c sfpool.c sfpopen.c \ sfprintf.c sfputd.c sfputl.c sfputr.c sfputu.c sfrd.c sfread.c \ sfscanf.c sfseek.c sfset.c sfsetbuf.c sfsetfd.c sfsize.c sfsk.c \ sfstack.c sfsync.c sftable.c sftell.c sftmp.c \ sfungetc.c sfvprintf.c sfvscanf.c sfwr.c sfwrite.c sfexit.c \ sfpurge.c sfpoll.c sfreserve.c sfswap.c sfraise.c sfmutex.c \ sfgetm.c sfputm.c sfresize.c sffrexp.c sfstrtof.c OBJS= sfclose.o sfclrlock.o sfcvt.o sfdisc.o sfdlen.o sfexcept.o \ sfextern.o sffilbuf.o sfflsbuf.o sfprints.o sfgetd.o sfgetl.o \ sfgetr.o sfgetu.o sfllen.o sfmode.o sfmove.o sfnew.o \ sfnotify.o sfnputc.o sfopen.o sfpkrd.o sfpool.o sfpopen.o \ sfprintf.o sfputd.o sfputl.o sfputr.o sfputu.o sfrd.o sfread.o \ sfscanf.o sfseek.o sfset.o sfsetbuf.o sfsetfd.o sfsize.o sfsk.o \ sfstack.o sfsync.o sftable.o sftell.o sftmp.o \ sfungetc.o sfvprintf.o sfvscanf.o sfwr.o sfwrite.o sfexit.o \ sfpurge.o sfpoll.o sfreserve.o sfswap.o sfraise.o sfmutex.o \ sfgetm.o sfputm.o sfresize.o sffrexp.o sfstrtof.o # function versions of macros SFIO_F= Sfio_f/_sfclrerr.o Sfio_f/_sfdlen.o Sfio_f/_sfeof.o \ Sfio_f/_sferror.o Sfio_f/_sffileno.o Sfio_f/_sfgetc.o \ Sfio_f/_sfllen.o Sfio_f/_sfputc.o Sfio_f/_sfputd.o \ Sfio_f/_sfputl.o Sfio_f/_sfputm.o Sfio_f/_sfputu.o \ Sfio_f/_sfslen.o Sfio_f/_sfstacked.o Sfio_f/_sfulen.o \ Sfio_f/_sfvalue.o # stdio-source compatibility code STDIO_S=Stdio_s/stdfgetc.o Stdio_s/stdfprintf.o Stdio_s/stdfputc.o \ Stdio_s/stdfscanf.o Stdio_s/stdgetc.o Stdio_s/stdgets.o \ Stdio_s/stdgetw.o Stdio_s/stdfdopen.o Stdio_s/stdprintf.o \ Stdio_s/stdputc.o Stdio_s/stdputw.o Stdio_s/stdscanf.o \ Stdio_s/stdsprintf.o Stdio_s/stdsetvbuf.o Stdio_s/stdtmpfile.o \ Stdio_s/stdfopen.o Stdio_s/stdpopen.o Stdio_s/stdfreopen.o \ Stdio_s/stdfwrite.o Stdio_s/stdfread.o Stdio_s/stdfflush.o # Thread-safety MTSAFE= ../vthread/vtextern.o ../vthread/vtmtxclrlock.o \ ../vthread/vtmtxclose.o ../vthread/vtmtxlock.o \ ../vthread/vtmtxopen.o ../vthread/vtmtxtrylock.o \ ../vthread/vtmtxunlock.o ../vthread/vtonce.o # IO disciplines SFIO_DC=Sfio_dc/sfdcdio.o Sfio_dc/sfdcdos.o Sfio_dc/sfdcfilter.o \ Sfio_dc/sfdclzw.o Sfio_dc/sfdcseekable.o Sfio_dc/sfdcslow.o \ Sfio_dc/sfdcsubstream.o Sfio_dc/sfdctee.o Sfio_dc/sfdcunion.o .c.o: $(CC) -c $(CCFLAGS) $*.c %.o : %.c $(CC) -c $(CCFLAGS) $*.c # this target builds the uni-threaded version of Sfio install: echo""; echo "BUILDING UNI-THREADED libsfio.a" $(SHELL) ./Makestate.sh unithreaded $(MAKE) LIBTYPE="-Dvt_threaded=0" SHELL="$(SHELL)" CC="$(CC)" \ CCMODE="$(CCMODE)" CXFLAGS="$(CXFLAGS)" install_unithreaded # this target builds the multi-threaded version of Sfio install_mt: vthread echo""; echo "BUILDING MULTI-THREADED libsfio-mt.a"; $(SHELL) ./Makestate.sh multithreaded $(MAKE) LIBTYPE="-Dvt_threaded=1" SHELL="$(SHELL)" CC="$(CC)" \ CCMODE="$(CCMODE)" CXFLAGS="$(CXFLAGS)" install_multithreaded # this target builds the Vthread library vthread: cd ../vthread; $(MAKE) -f Makefile SHELL="$(SHELL)" CC="$(CC)" \ CCMODE="$(CCMODE)" CXFLAGS="$(CXFLAGS)" install install_unithreaded: libsfio.a libstdio.a cp ast_common.h sfio.h sfio_s.h sfio_t.h Stdio_s/stdio.h Sfio_dc/sfdisc.h \ $(INCDIR) cp libsfio.a $(LIBDIR) -(ranlib $(LIBDIR)/libsfio.a; exit 0) >/dev/null 2>&1 cp Stdio_b/libstdio.a $(LIBDIR) -(ranlib $(LIBDIR)/libstdio.a; exit 0) >/dev/null 2>&1 libsfio.a: FEATURES $(OBJS) mksfio_f mkstdio_s mksfio_dc $(AR) cr libsfio.a $(OBJS) $(SFIO_F) $(STDIO_S) $(SFIO_DC) -(ranlib libsfio.a; exit 0) >/dev/null 2>&1 libstdio.a: cd Stdio_b; $(MAKE) -f Makefile LIBTYPE="$(LIBTYPE)" SHELL="$(SHELL)" \ CC="$(CC)" CCMODE="$(CCMODE)" CXFLAGS="$(CXFLAGS)" libstdio.a install_multithreaded: libsfio-mt.a libstdio-mt.a cp ast_common.h sfio.h sfio_s.h sfio_t.h Stdio_s/stdio.h Sfio_dc/sfdisc.h \ $(INCDIR) cp libsfio-mt.a $(LIBDIR) -(ranlib $(LIBDIR)/libsfio-mt.a; exit 0) >/dev/null 2>&1 cp Stdio_b/libstdio-mt.a $(LIBDIR) -(ranlib $(LIBDIR)/libstdio-mt.a; exit 0) >/dev/null 2>&1 libsfio-mt.a: FEATURES $(OBJS) mksfio_f mkstdio_s mksfio_dc $(AR) cr libsfio-mt.a $(OBJS) $(SFIO_F) $(STDIO_S) $(SFIO_DC) $(MTSAFE) -(ranlib libsfio-mt.a; exit 0) >/dev/null 2>&1 libstdio-mt.a: cd Stdio_b; $(MAKE) -f Makefile LIBTYPE="$(LIBTYPE)" SHELL="$(SHELL)" \ CC="$(CC)" CCMODE="$(CCMODE)" CXFLAGS="$(CXFLAGS)" libstdio-mt.a # the make goals below are common to both uni&multi-threaded versions FEATURES: FEATURE/common FEATURE/float FEATURE/sfio FEATURE/iffeio FEATURE/sfinit FEATURE/iffeio: FEATURE/common FEATURE/stdio.lcl $(BINDIR)/iffe set cc $(CC) $(CCFLAGS) : run features/iffeio FEATURE/stdio.lcl: features/stdio_lcl $(BINDIR)/iffe - set cc $(CC) $(CCFLAGS) : run features/stdio_lcl > \ FEATURE/stdio.lcl FEATURE/common: features/common $(BINDIR)/iffe set cc $(CC) $(CCFLAGS) : run features/common -(rm ast_common.h; ln FEATURE/common ast_common.h; exit 0) >/dev/null 2>&1 FEATURE/float: features/float $(BINDIR)/iffe set cc $(CC) $(CCFLAGS) : run features/float FEATURE/sfinit: features/sfinit.c $(BINDIR)/iffe set cc $(CC) $(CCFLAGS) : run features/sfinit.c FEATURE/sfio: features/sfio $(BINDIR)/iffe set cc $(CC) $(CCFLAGS) : run features/sfio mksfio_f: cd Sfio_f; $(MAKE) -f Makefile LIBTYPE="$(LIBTYPE)" SHELL="$(SHELL)" \ CC="$(CC)" CCMODE="$(CCMODE)" CXFLAGS="$(CXFLAGS)" mkstdio_s: cd Stdio_s; $(MAKE) -f Makefile LIBTYPE="$(LIBTYPE)" SHELL="$(SHELL)" \ CC="$(CC)" CCMODE="$(CCMODE)" CXFLAGS="$(CXFLAGS)" mksfio_dc: cd Sfio_dc; $(MAKE) -f Makefile LIBTYPE="$(LIBTYPE)" SHELL="$(SHELL)" \ CC="$(CC)" CCMODE="$(CCMODE)" CXFLAGS="$(CXFLAGS)" 3dupdate: cp Makefile $(SRCS) $(HDRS) ... cd features; cp common float iffeio sfinit.c sfio stdio stdio_lcl ... cd Sfio_f; $(MAKE) -f Makefile SHELL="$(SHELL)" 3dupdate cd Stdio_s; $(MAKE) -f Makefile SHELL="$(SHELL)" 3dupdate cd Stdio_b; $(MAKE) -f Makefile SHELL="$(SHELL)" 3dupdate cd Sfio_dc; $(MAKE) -f Makefile SHELL="$(SHELL)" 3dupdate clean: -(rm -rf FEATURE $(OBJS) ast_common.h Makefile.state; exit 0) >/dev/null 2>&1 -(rm libsfio.a libstdio.a libsfio-mt.a libstdio-mt.a; exit 0) >/dev/null 2>&1 cd Sfio_f; $(MAKE) -f Makefile SHELL="$(SHELL)" clean cd Stdio_s; $(MAKE) -f Makefile SHELL="$(SHELL)" clean cd Stdio_b; $(MAKE) -f Makefile SHELL="$(SHELL)" clean cd Sfio_dc; $(MAKE) -f Makefile SHELL="$(SHELL)" clean ate cd Stdio_b; $(MAKE) -f Makefile SHELL="$(SHELL)" 3dupdate cd Sfio_dc; $(MAKE) -f Makefile SHELL="$(SHELL)" 3dupdate clean: -(rm -rf FEATURE $(OBJS) src/lib/sfio/sfseek.c000644 151361 151361 00000013475 07432261526 014472 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Set the IO pointer to a specific location in the stream ** ** Written by Kiem-Phong Vo. */ #if __STD_C static void newpos(Sfio_t* f, Sfoff_t p) #else static void newpos(f, p) Sfio_t* f; Sfoff_t p; #endif { #ifdef MAP_TYPE if((f->bits&SF_MMAP) && f->data) { SFMUNMAP(f, f->data, f->endb-f->data); f->data = NIL(uchar*); } #endif f->next = f->endr = f->endw = f->data; f->endb = (f->mode&SF_WRITE) ? f->data+f->size : f->data; if((f->here = p) < 0) { f->extent = -1; f->here = 0; } } #if __STD_C Sfoff_t sfseek(Sfio_t* f, Sfoff_t p, int type) #else Sfoff_t sfseek(f,p,type) Sfio_t* f; /* seek to a new location in this stream */ Sfoff_t p; /* place to seek to */ int type; /* 0: from org, 1: from here, 2: from end */ #endif { Sfoff_t r, s; size_t a, b, c; int mode, local, hardseek, mustsync; SFMTXSTART(f, (Sfoff_t)(-1)); GETLOCAL(f,local); hardseek = (type|f->flags)&(SF_SHARE|SF_PUBLIC); if(hardseek && f->mode == (SF_READ|SF_SYNCED) ) { newpos(f,f->here); f->mode = SF_READ; } /* set and initialize the stream to a definite mode */ if((int)SFMODE(f,local) != (mode = f->mode&SF_RDWR)) { int flags = f->flags; if(hardseek&SF_PUBLIC) /* seek ptr must follow file descriptor */ f->flags |= SF_SHARE|SF_PUBLIC; mode = _sfmode(f,mode,local); if(hardseek&SF_PUBLIC) f->flags = flags; if(mode < 0) SFMTXRETURN(f, (Sfoff_t)(-1)); } mustsync = (type&SF_SHARE) && !(type&SF_PUBLIC) && (f->mode&SF_READ) && !(f->flags&SF_STRING); /* Xopen-compliant */ if((type &= (SEEK_SET|SEEK_CUR|SEEK_END)) != SEEK_SET && type != SEEK_CUR && type != SEEK_END ) { errno = EINVAL; SFMTXRETURN(f, (Sfoff_t)(-1)); } if(f->extent < 0) { /* let system call set errno */ (void)SFSK(f,(Sfoff_t)0,SEEK_CUR,f->disc); SFMTXRETURN(f, (Sfoff_t)(-1)); } /* throw away ungetc data */ if(f->disc == _Sfudisc) (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*))); /* lock the stream for internal manipulations */ SFLOCK(f,local); /* clear error and eof bits */ f->flags &= ~(SF_EOF|SF_ERROR); while(f->flags&SF_STRING) { SFSTRSIZE(f); if(type == SEEK_CUR) r = p + (f->next - f->data); else if(type == SEEK_END) r = p + f->extent; else r = p; if(r >= 0 && r <= f->size) { p = r; f->next = f->data+p; f->here = p; if(p > f->extent) memclear((char*)(f->data+f->extent),(int)(p-f->extent)); goto done; } /* check exception handler, note that this may pop stream */ if(SFSK(f,r,SEEK_SET,f->disc) != r) { p = -1; goto done; } else if(!(f->flags&SF_STRING)) { p = r; goto done; } } if(f->mode&SF_WRITE) { /* see if we can avoid flushing buffer */ if(!hardseek && type < SEEK_END && !(f->flags&SF_APPENDWR) ) { s = f->here + (f->next - f->data); r = p + (type == SEEK_SET ? 0 : s); if(r == s) { p = r; goto done; } } if(f->next > f->data && SFSYNC(f) < 0) { p = -1; goto done; } } if(type == SEEK_END || (f->mode&SF_WRITE) ) { if((hardseek&SF_PUBLIC) || type == SEEK_END) p = SFSK(f, p, type, f->disc); else { r = p + (type == SEEK_CUR ? f->here : 0); p = (hardseek || r != f->here) ? SFSK(f,r,SEEK_SET,f->disc) : r; } if(p >= 0) newpos(f,p); goto done; } /* if get here, must be a read stream */ s = f->here - (f->endb - f->next); r = p + (type == SEEK_CUR ? s : 0); if(r <= f->here && r >= (f->here - (f->endb-f->data)) ) { if((hardseek || (type == SEEK_CUR && p == 0)) ) { if((s = SFSK(f, (Sfoff_t)0, SEEK_CUR, f->disc)) == f->here || (s >= 0 && !(hardseek&SF_PUBLIC) && (s = SFSK(f, f->here, SEEK_SET, f->disc)) == f->here) ) goto near_done; else if(s < 0) { p = -1; goto done; } else { newpos(f,s); hardseek = 0; } } else { near_done: f->next = f->endb - (f->here - r); p = r; goto done; } } /* desired position */ if((p += type == SEEK_CUR ? s : 0) < 0) goto done; #ifdef MAP_TYPE if(f->bits&SF_MMAP) { /* if mmap is not great, stop mmaping if moving around too much */ #if _mmap_worthy < 2 if((f->next - f->data) < ((f->endb - f->data)/4) ) { SFSETBUF(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND); hardseek = 1; /* this forces a hard seek below */ } else #endif { /* for mmap, f->here can be virtual */ newpos(f,p); goto done; } } #endif b = f->endb - f->data; /* amount of buffered data */ c = f->next - f->data; /* amount of data consumed */ if(b > 0) { /* gradually reduce wastage */ if(b <= SF_GRAIN) f->iosz = SF_GRAIN; else { c *= 2; a = c + 3*(b-c)/4; a = ((a + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN; b = ((b + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN; f->iosz = a < b ? a : c < b/2 ? b/2 : b; } } /* else, believe previous setting of f->iosz */ if(f->iosz >= f->size) f->iosz = 0; /* buffer is now considered empty */ f->next = f->endr = f->endb = f->data; /* small backseeks often come in bunches, so seek back as far as possible */ if(p < f->lpos && f->size > SF_GRAIN && (p + SF_GRAIN) > s) { if((r = s - f->size) < 0) r = 0; } else { r = p; /* seeking around and wasting data, be conservative */ if(f->iosz > 0 && (p > f->lpos || p < f->lpos-f->size) ) f->bits |= SF_JUSTSEEK; } if((hardseek || r != f->here) && (f->here = SFSK(f,r,SEEK_SET,f->disc)) != r) { if(r < p) /* now try to just get to p */ f->here = SFSK(f,p,SEEK_SET,f->disc); if(f->here != p) p = -1; goto done; } if(r < p) /* read to cover p */ { (void)SFRD(f, f->data, f->size, f->disc); if(p <= f->here && p >= (f->here - (f->endb - f->data)) ) f->next = f->endb - (size_t)(f->here-p); else /* recover from read failure by just seeking to p */ { f->next = f->endb = f->data; if((f->here = SFSK(f,p,SEEK_SET,f->disc)) != p) p = -1; } } done : if(f->here < 0) /* hasn't been the best of time */ { f->extent = -1; f->here = 0; } f->lpos = p; SFOPEN(f,local); if(mustsync) sfsync(f); SFMTXRETURN(f, p); } read to cover p */ { (void)SFRD(f, f->data, f->size, f->disc); if(p <= f->here && p >= (f->here - (f->endb - f->data)) ) f->next = f->endb - (size_t)(f->here-p); else /* recover from readsrc/lib/sfio/sfread.c000644 151361 151361 00000005043 07432261525 014445 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Read n bytes from a stream into a buffer ** ** Written by Kiem-Phong Vo. */ #if __STD_C ssize_t sfread(reg Sfio_t* f, Void_t* buf, reg size_t n) #else ssize_t sfread(f,buf,n) reg Sfio_t* f; /* read from this stream. */ Void_t* buf; /* buffer to read into */ reg size_t n; /* number of bytes to be read. */ #endif { reg uchar *s, *begs; reg ssize_t r; reg int local, justseek; SFMTXSTART(f, (ssize_t)(-1)); GETLOCAL(f,local); justseek = f->bits&SF_JUSTSEEK; f->bits &= ~SF_JUSTSEEK; if(!buf) SFMTXRETURN(f, (ssize_t)(n == 0 ? 0 : -1) ); /* release peek lock */ if(f->mode&SF_PEEK) { if(!(f->mode&SF_READ) ) SFMTXRETURN(f, (ssize_t)(-1)); if(f->mode&SF_GETR) { if(((uchar*)buf + f->val) != f->next && (!f->rsrv || f->rsrv->data != (uchar*)buf) ) SFMTXRETURN(f, (ssize_t)(-1)); f->mode &= ~SF_PEEK; SFMTXRETURN(f, 0); } else { if((uchar*)buf != f->next) SFMTXRETURN(f, (ssize_t)(-1)); f->mode &= ~SF_PEEK; if(f->mode&SF_PKRD) { /* actually read the data now */ f->mode &= ~SF_PKRD; if(n > 0) n = (r = read(f->file,f->data,n)) < 0 ? 0 : r; f->endb = f->data+n; f->here += n; } f->next += n; f->endr = f->endb; SFMTXRETURN(f, n); } } s = begs = (uchar*)buf; for(;; f->mode &= ~SF_LOCK) { /* check stream mode */ if(SFMODE(f,local) != SF_READ && _sfmode(f,SF_READ,local) < 0) { n = s > begs ? s-begs : (size_t)(-1); SFMTXRETURN(f, (ssize_t)n); } SFLOCK(f,local); if((r = f->endb - f->next) > 0) /* has buffered data */ { if(r > (ssize_t)n) r = (ssize_t)n; if(s != f->next) memcpy(s, f->next, r); f->next += r; s += r; n -= r; } if(n <= 0) /* all done */ break; if(!(f->flags&SF_STRING) && !(f->bits&SF_MMAP) ) { f->next = f->endb = f->data; /* exact IO is desirable for these cases */ if(SFDIRECT(f,n) || ((f->flags&SF_SHARE) && f->extent < 0) ) r = (ssize_t)n; else if(justseek && n <= f->iosz && f->iosz <= f->size) r = f->iosz; /* limit buffering */ else r = f->size; /* full buffering */ /* if read almost full size, then just do it direct */ if(r > (ssize_t)n && (r - r/8) <= (ssize_t)n) r = (ssize_t)n; /* read directly to user's buffer */ if(r == (ssize_t)n && (r = SFRD(f,s,r,f->disc)) >= 0) { s += r; n -= r; if(r == 0 || n == 0) /* eof or eob */ break; } else goto do_filbuf; } else { do_filbuf: if(justseek) f->bits |= SF_JUSTSEEK; if(SFFILBUF(f,-1) <= 0) break; } } SFOPEN(f,local); r = s-begs; SFMTXRETURN(f, r); } ring */ /* if read almost full size, then just do it direct */ if(r > (ssize_t)n && (r - r/8) <= (ssize_t)n) r = (ssize_t)n; /* read directly to user's buffer */ if(r == (ssize_t)n && (r = SFRD(f,s,r,f->disc)) >= 0) { s += r; n -= r; if(r == 0 || n == 0) /* eof or eob */ break; } else goto do_filbuf; } else { do_filbuf: if(justseek) f->bits |= SF_JUSTSEEK; if(SFFILBUF(f,-1) <= 0) break; } } SFOPEN(f,local); src/lib/sfio/sftell.c000644 151361 151361 00000001441 07432261527 014472 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Tell the current location in a given stream ** ** Written by Kiem-Phong Vo. */ #if __STD_C Sfoff_t sftell(reg Sfio_t* f) #else Sfoff_t sftell(f) reg Sfio_t *f; #endif { reg int mode; Sfoff_t p; SFMTXSTART(f, (Sfoff_t)(-1)); /* set the stream to the right mode */ if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0) SFMTXRETURN(f, (Sfoff_t)(-1)); /* throw away ungetc data */ if(f->disc == _Sfudisc) (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*))); if(f->flags&SF_STRING) SFMTXRETURN(f, (Sfoff_t)(f->next-f->data)); /* let sfseek() handle the hard case */ if(f->extent >= 0 && (f->flags&(SF_SHARE|SF_APPENDWR)) ) p = sfseek(f,(Sfoff_t)0,1); else p = f->here + ((f->mode&SF_WRITE) ? f->next-f->data : f->next-f->endb); SFMTXRETURN(f,p); } e */ if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0) SFMTXRETURN(f, (Sfoff_t)(-1)); /* throw away ungetc data */ if(f->disc == _Sfudisc) (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*))); if(f->flagsrc/lib/sfio/sftable.c000644 151361 151361 00000030232 07446131366 014623 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Dealing with $ argument addressing stuffs. ** ** Written by Kiem-Phong Vo. */ #if _PACKAGE_ast #include #define Sfsignal_f Sig_handler_t #else #include typedef void(* Sfsignal_f)_ARG_((int)); #endif #if __STD_C static char* sffmtint(const char* str, int* v) #else static char* sffmtint(str, v) char* str; int* v; #endif { for(*v = 0; isdigit(*str); ++str) *v = *v * 10 + (*str - '0'); *v -= 1; return (char*)str; } #if __STD_C static Fmtpos_t* sffmtpos(Sfio_t* f, const char* form, va_list args, int type) #else static Fmtpos_t* sffmtpos(f,form,args,type) Sfio_t* f; char* form; va_list args; int type; #endif { int base, fmt, flags, dot, width, precis; ssize_t n_str, size; char *t_str, *sp; int v, n, skip, dollar, decimal, thousand; Sffmt_t *ft, savft; Fmtpos_t* fp; /* position array of arguments */ int argp, argn, maxp, need[FP_INDEX]; #if _has_multibyte SFMBDCL(fmbs) #endif if(type < 0) fp = NIL(Fmtpos_t*); else if(!(fp = sffmtpos(f,form,args,-1)) ) return NIL(Fmtpos_t*); dollar = decimal = thousand = 0; argn = maxp = -1; SFMBCLR(&fmbs); while((n = *form) ) { if(n != '%') /* collect the non-pattern chars */ { sp = (char*)form; for(;;) { form += SFMBLEN(form, &fmbs); if(*form == 0 || *form == '%') break; } continue; } else form += 1; if(*form == 0) break; else if(*form == '%') { form += 1; continue; } if(*form == '*' && type > 0) /* skip in scanning */ { skip = 1; form += 1; argp = -1; } else /* get the position of this argument */ { skip = 0; sp = sffmtint(form,&argp); if(*sp == '$') { dollar = 1; form = sp+1; } else argp = -1; } flags = dot = 0; t_str = NIL(char*); n_str = 0; size = width = precis = base = -1; for(n = 0; n < FP_INDEX; ++n) need[n] = -1; loop_flags: /* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */ switch((fmt = *form++) ) { case LEFTP : /* get the type enclosed in balanced parens */ t_str = (char*)form; for(v = 1;;) { switch(*form++) { case 0 : /* not balancable, retract */ form = t_str; t_str = NIL(char*); n_str = 0; goto loop_flags; case LEFTP : /* increasing nested level */ v += 1; continue; case RIGHTP : /* decreasing nested level */ if((v -= 1) != 0) continue; n_str = form-t_str; if(*t_str == '*') { t_str = sffmtint(t_str+1,&n); if(*t_str == '$') dollar = 1; else n = -1; if((n = FP_SET(n,argn)) > maxp) maxp = n; if(fp && fp[n].ft.fmt == 0) { fp[n].ft.fmt = LEFTP; fp[n].ft.form = (char*)form; } need[FP_STR] = n; } goto loop_flags; } } case '-' : flags |= SFFMT_LEFT; flags &= ~SFFMT_ZERO; goto loop_flags; case '0' : if(!(flags&SFFMT_LEFT) ) flags |= SFFMT_ZERO; goto loop_flags; case ' ' : if(!(flags&SFFMT_SIGN) ) flags |= SFFMT_BLANK; goto loop_flags; case '+' : flags |= SFFMT_SIGN; flags &= ~SFFMT_BLANK; goto loop_flags; case '#' : flags |= SFFMT_ALTER; goto loop_flags; case QUOTE: SFSETLOCALE(&decimal,&thousand); if(thousand > 0) flags |= SFFMT_THOUSAND; goto loop_flags; case '.' : if((dot += 1) == 2) base = 0; /* for %s,%c */ if(isdigit(*form)) { fmt = *form++; goto dot_size; } else if(*form != '*') goto loop_flags; else form += 1; /* drop thru below */ case '*' : form = sffmtint(form,&n); if(*form == '$' ) { dollar = 1; form += 1; } else n = -1; if((n = FP_SET(n,argn)) > maxp) maxp = n; if(fp && fp[n].ft.fmt == 0) { fp[n].ft.fmt = '.'; fp[n].ft.size = dot; fp[n].ft.form = (char*)form; } if(dot <= 2) need[dot] = n; goto loop_flags; case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : dot_size : for(v = fmt - '0', fmt = *form; isdigit(fmt); fmt = *++form) v = v*10 + (fmt - '0'); if(dot == 0) width = v; else if(dot == 1) precis = v; else if(dot == 2) base = v; goto loop_flags; case 'I' : /* object length */ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG; if(isdigit(*form) ) { for(size = 0, n = *form; isdigit(n); n = *++form) size = size*10 + (n - '0'); } else if(*form == '*') { form = sffmtint(form+1,&n); if(*form == '$' ) { dollar = 1; form += 1; } else n = -1; if((n = FP_SET(n,argn)) > maxp) maxp = n; if(fp && fp[n].ft.fmt == 0) { fp[n].ft.fmt = 'I'; fp[n].ft.size = sizeof(int); fp[n].ft.form = (char*)form; } need[FP_SIZE] = n; } goto loop_flags; case 'l' : size = -1; flags &= ~SFFMT_TYPES; if(*form == 'l') { form += 1; flags |= SFFMT_LLONG; } else flags |= SFFMT_LONG; goto loop_flags; case 'h' : size = -1; flags &= ~SFFMT_TYPES; if(*form == 'h') { form += 1; flags |= SFFMT_SSHORT; } else flags |= SFFMT_SHORT; goto loop_flags; case 'L' : size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE; goto loop_flags; } /* set object size for scalars */ if(flags & SFFMT_TYPES) { if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n') { if(flags&SFFMT_LONG) size = sizeof(long); else if(flags&SFFMT_SHORT) size = sizeof(short); else if(flags&SFFMT_SSHORT) size = sizeof(char); else if(flags&SFFMT_TFLAG) size = sizeof(ptrdiff_t); else if(flags&SFFMT_ZFLAG) size = sizeof(size_t); else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) ) size = sizeof(Sflong_t); else if(flags&SFFMT_IFLAG) { if(size <= 0 || size == sizeof(Sflong_t)*CHAR_BIT ) size = sizeof(Sflong_t); } else if(size < 0) size = sizeof(int); } else if(_Sftype[fmt]&SFFMT_FLOAT) { if(flags&(SFFMT_LONG|SFFMT_LLONG)) size = sizeof(double); else if(flags&SFFMT_LDOUBLE) size = sizeof(Sfdouble_t); else if(flags&SFFMT_IFLAG) { if(size <= 0) size = sizeof(Sfdouble_t); } else if(size < 0) size = sizeof(float); } else if(_Sftype[fmt]&SFFMT_CHAR) { #if _has_multibyte if((flags&SFFMT_LONG) || fmt == 'C') { size = sizeof(wchar_t) > sizeof(int) ? sizeof(wchar_t) : sizeof(int); } else #endif if(size < 0) size = sizeof(int); } } if(skip) continue; if((argp = FP_SET(argp,argn)) > maxp) maxp = argp; if(dollar && fmt == '!') return NIL(Fmtpos_t*); if(fp && fp[argp].ft.fmt == 0) { fp[argp].ft.form = (char*)form; fp[argp].ft.fmt = fp[argp].fmt = fmt; fp[argp].ft.size = size; fp[argp].ft.flags = flags; fp[argp].ft.width = width; fp[argp].ft.precis = precis; fp[argp].ft.base = base; fp[argp].ft.t_str = t_str; fp[argp].ft.n_str = n_str; for(n = 0; n < FP_INDEX; ++n) fp[argp].need[n] = need[n]; } } if(!fp) /* constructing position array only */ { if(!dollar || !(fp = (Fmtpos_t*)malloc((maxp+1)*sizeof(Fmtpos_t))) ) return NIL(Fmtpos_t*); for(n = 0; n <= maxp; ++n) fp[n].ft.fmt = 0; return fp; } /* get value for positions */ for(n = 0, ft = NIL(Sffmt_t*); n <= maxp; ++n) { if(fp[n].ft.fmt == 0) /* gap: pretend it's a 'd' pattern */ { fp[n].ft.fmt = 'd'; fp[n].ft.width = 0; fp[n].ft.precis = 0; fp[n].ft.base = 0; fp[n].ft.size = 0; fp[n].ft.t_str = 0; fp[n].ft.n_str = 0; fp[n].ft.flags = 0; for(v = 0; v < FP_INDEX; ++v) fp[n].need[v] = -1; } if(ft && ft->extf) { fp[n].ft.version = ft->version; fp[n].ft.extf = ft->extf; fp[n].ft.eventf = ft->eventf; if((v = fp[n].need[FP_WIDTH]) >= 0 && v < n) fp[n].ft.width = fp[v].argv.i; if((v = fp[n].need[FP_PRECIS]) >= 0 && v < n) fp[n].ft.precis = fp[v].argv.i; if((v = fp[n].need[FP_BASE]) >= 0 && v < n) fp[n].ft.base = fp[v].argv.i; if((v = fp[n].need[FP_STR]) >= 0 && v < n) fp[n].ft.t_str = fp[v].argv.s; if((v = fp[n].need[FP_SIZE]) >= 0 && v < n) fp[n].ft.size = fp[v].argv.i; memcpy(ft,&fp[n].ft,sizeof(Sffmt_t)); va_copy(ft->args,args); ft->flags |= SFFMT_ARGPOS; v = (*ft->extf)(f, (Void_t*)(&fp[n].argv), ft); va_copy(args,ft->args); memcpy(&fp[n].ft,ft,sizeof(Sffmt_t)); if(v < 0) { memcpy(ft,&savft,sizeof(Sffmt_t)); ft = NIL(Sffmt_t*); } if(!(fp[n].ft.flags&SFFMT_VALUE) ) goto arg_list; else if(_Sftype[fp[n].ft.fmt]&(SFFMT_INT|SFFMT_UINT) ) { if(fp[n].ft.size == sizeof(short)) { if(_Sftype[fp[n].ft.fmt]&SFFMT_INT) fp[n].argv.i = fp[n].argv.h; else fp[n].argv.i = fp[n].argv.uh; } else if(fp[n].ft.size == sizeof(char)) { if(_Sftype[fp[n].ft.fmt]&SFFMT_INT) fp[n].argv.i = fp[n].argv.c; else fp[n].argv.i = fp[n].argv.uc; } } else if(_Sftype[fp[n].ft.fmt]&SFFMT_FLOAT ) { if(fp[n].ft.size == sizeof(float) ) fp[n].argv.d = fp[n].argv.f; } } else { arg_list: if(fp[n].ft.fmt == LEFTP) { fp[n].argv.s = va_arg(args, char*); fp[n].ft.size = strlen(fp[n].argv.s); } else if(fp[n].ft.fmt == '.' || fp[n].ft.fmt == 'I') fp[n].argv.i = va_arg(args, int); else if(fp[n].ft.fmt == '!') { if(ft) memcpy(ft,&savft,sizeof(Sffmt_t)); fp[n].argv.ft = ft = va_arg(args, Sffmt_t*); if(ft->form) ft = NIL(Sffmt_t*); if(ft) memcpy(&savft,ft,sizeof(Sffmt_t)); } else if(type > 0) /* from sfvscanf */ fp[n].argv.vp = va_arg(args, Void_t*); else switch(_Sftype[fp[n].ft.fmt]) { case SFFMT_INT: case SFFMT_UINT: #if !_ast_intmax_long if(size == sizeof(Sflong_t) ) fp[n].argv.ll = va_arg(args, Sflong_t); else #endif if(size == sizeof(long) ) fp[n].argv.l = va_arg(args, long); else fp[n].argv.i = va_arg(args, int); break; case SFFMT_FLOAT: #if !_ast_fltmax_double if(size == sizeof(Sfdouble_t) ) fp[n].argv.ld = va_arg(args,Sfdouble_t); else #endif fp[n].argv.d = va_arg(args,double); break; case SFFMT_POINTER: fp[n].argv.vp = va_arg(args,Void_t*); break; case SFFMT_CHAR: if(fp[n].ft.base >= 0) fp[n].argv.s = va_arg(args,char*); #if _has_multibyte else if((fp[n].ft.flags & SFFMT_LONG) || fp[n].ft.fmt == 'C' ) { if(sizeof(wchar_t) <= sizeof(int) ) fp[n].argv.wc = (wchar_t)va_arg(args,int); else fp[n].argv.wc = va_arg(args,wchar_t); } #endif else fp[n].argv.c = (char)va_arg(args,int); break; default: /* unknown pattern */ break; } } } if(ft) memcpy(ft,&savft,sizeof(Sffmt_t)); return fp; } /* function to initialize conversion tables */ static int sfcvinit() { reg int d, l; #ifdef SIGFPE Sfsignal_f fpe; #endif for(d = 0; d <= SF_MAXCHAR; ++d) { _Sfcv36[d] = SF_RADIX; _Sfcv64[d] = SF_RADIX; } /* [0-9] */ for(d = 0; d < 10; ++d) { _Sfcv36[(uchar)_Sfdigits[d]] = d; _Sfcv64[(uchar)_Sfdigits[d]] = d; } /* [a-z] */ for(; d < 36; ++d) { _Sfcv36[(uchar)_Sfdigits[d]] = d; _Sfcv64[(uchar)_Sfdigits[d]] = d; } /* [A-Z] */ for(l = 10; d < 62; ++l, ++d) { _Sfcv36[(uchar)_Sfdigits[d]] = l; _Sfcv64[(uchar)_Sfdigits[d]] = d; } /* remaining digits */ for(; d < SF_RADIX; ++d) { _Sfcv36[(uchar)_Sfdigits[d]] = d; _Sfcv64[(uchar)_Sfdigits[d]] = d; } _Sftype['d'] = _Sftype['i'] = SFFMT_INT; _Sftype['u'] = _Sftype['o'] = _Sftype['x'] = _Sftype['X'] = SFFMT_UINT; _Sftype['e'] = _Sftype['E'] = _Sftype['a'] = _Sftype['A'] = _Sftype['g'] = _Sftype['G'] = _Sftype['f'] = SFFMT_FLOAT; _Sftype['s'] = _Sftype['n'] = _Sftype['p'] = _Sftype['!'] = SFFMT_POINTER; _Sftype['c'] = SFFMT_CHAR; _Sftype['['] = SFFMT_CLASS; #if _has_multibyte _Sftype['S'] = SFFMT_POINTER; _Sftype['C'] = SFFMT_CHAR; #endif /* floating point huge values */ #ifdef SIGFPE fpe = signal(SIGFPE, SIG_IGN); #endif #ifdef HUGE_VALF _Sffhuge = HUGE_VALF; #else { float fn = FLT_MAX; _Sffhuge = (fn *= 2) > FLT_MAX ? fn : FLT_MAX; } #endif #ifdef HUGE_VAL _Sfdhuge = HUGE_VAL; #else { double dn = DBL_MAX; _Sfdhuge = (dn *= 2) > DBL_MAX ? dn : DBL_MAX; } #endif #ifdef HUGE_VALL _Sflhuge = HUGE_VALL; #else { Sfdouble_t ln, lnmax; #ifdef LDBL_MAX ln = lnmax = LDBL_MAX; #else ln = lnmax = DBL_MAX; #endif _Sflhuge = (ln *= 2) > lnmax ? ln : lnmax; } #endif #ifdef SIGFPE signal(SIGFPE, fpe); #endif return 1; } /* table for floating point and integer conversions */ #include "FEATURE/sfinit" 2) > FLT_MAX ? fn : FLT_MAX; } #endif #ifdef HUGE_VAL _Sfdhuge = HUGE_VAL; #else { double dn = DBL_MAX; _Sfdhuge = (dn *= 2) > DBL_MAX ? dn : DBL_MAX; } #endif #ifdef HUGE_VALL _Sflhuge = HUGE_VALL; #else { Sfdouble_t ln, lnmax; #ifdef LDBL_MAX ln = lnmax = LDBL_MAX; #else ln = lnmax = DBL_MAX; #endif _Sflhuge = (ln *= 2) > lnmax ? ln : lnmsrc/lib/sfio/sfgetu.c000644 151361 151361 00000001306 07432261523 014472 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Read an unsigned long value coded in a portable format. ** ** Written by Kiem-Phong Vo */ #if __STD_C Sfulong_t sfgetu(reg Sfio_t* f) #else Sfulong_t sfgetu(f) reg Sfio_t* f; #endif { Sfulong_t v; reg uchar *s, *ends, c; reg int p; SFMTXSTART(f, (Sfulong_t)(-1)); if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) SFMTXRETURN(f, (Sfulong_t)(-1)); SFLOCK(f,0); for(v = 0;;) { if(SFRPEEK(f,s,p) <= 0) { f->flags |= SF_ERROR; v = (Sfulong_t)(-1); goto done; } for(ends = s+p; s < ends;) { c = *s++; v = (v << SF_UBITS) | SFUVALUE(c); if(!(c&SF_MORE)) { f->next = s; goto done; } } f->next = s; } done: SFOPEN(f,0); SFMTXRETURN(f, v); } #endif { Sfulong_t v; reg uchar *s, *ends, c; reg int p; SFMTXSTART(f, (Sfulong_t)(-1)); if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) SFMTXRETURN(f, (Sfulong_t)(-1)); SFLOCK(f,0); for(v = 0;;) { if(SFRPEEK(f,s,p) <= 0) { f->flags |= SF_ERROR; v = (Sfulong_t)(-1); goto done; } forsrc/lib/sfio/sfputu.c000644 151361 151361 00000002065 07432261525 014530 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Write out an unsigned long value in a portable format. ** ** Written by Kiem-Phong Vo. */ #if __STD_C int _sfputu(reg Sfio_t* f, Sfulong_t v) #else int _sfputu(f,v) reg Sfio_t* f; /* write a portable ulong to this stream */ Sfulong_t v; /* the unsigned value to be written */ #endif { #define N_ARRAY (2*sizeof(Sfulong_t)) reg uchar *s, *ps; reg ssize_t n, p; uchar c[N_ARRAY]; SFMTXSTART(f, -1); if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0) SFMTXRETURN(f, -1); SFLOCK(f,0); /* code v as integers in base SF_UBASE */ s = ps = &(c[N_ARRAY-1]); *s = (uchar)SFUVALUE(v); while((v >>= SF_UBITS) ) *--s = (uchar)(SFUVALUE(v) | SF_MORE); n = (ps-s)+1; if(n > 8 || SFWPEEK(f,ps,p) < n) n = SFWRITE(f,(Void_t*)s,n); /* write the hard way */ else { switch(n) { case 8 : *ps++ = *s++; case 7 : *ps++ = *s++; case 6 : *ps++ = *s++; case 5 : *ps++ = *s++; case 4 : *ps++ = *s++; case 3 : *ps++ = *s++; case 2 : *ps++ = *s++; case 1 : *ps++ = *s++; } f->next = ps; } SFOPEN(f,0); SFMTXRETURN(f, (int)n); } = ps = &(c[N_ARRAY-1]); *s = (uchar)SFUVALUE(v); while((v >>= SF_UBITS) ) *--s = (uchar)(SFUVALUE(v) | SF_MORE); n = (ps-s)+1; if(n > 8 || SFWPEEK(f,ps,p) < n) n = SFWRITE(f,(Void_t*)s,n); /* write the hard way */ else { switch(n) { case 8 : *ps++ = *s++; case 7 : *ps++ = *s++; case 6 : *ps++ = *s++; case 5 : *ps++ = *s++; case 4 : *ps++ = *s++; case 3 : *ps++ = *s++; case 2 : *ps++ = *s++; case 1 : *ps++ = *s++; } f->nexsrc/lib/sfio/sfgetr.c000644 151361 151361 00000005071 07432261523 014472 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Read a record delineated by a character. ** The record length can be accessed via sfvalue(f). ** ** Written by Kiem-Phong Vo */ #if __STD_C char* sfgetr(reg Sfio_t *f, reg int rc, int type) #else char* sfgetr(f,rc,type) reg Sfio_t* f; /* stream to read from. r11 on vax */ reg int rc; /* record separator. r10 on Vax */ int type; #endif { reg ssize_t n; reg uchar *s, *ends, *us; reg ssize_t un; reg int found; reg Sfrsrv_t* rsrv; SFMTXSTART(f, NIL(char*)); if(rc < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) ) SFMTXRETURN(f, NIL(char*)); SFLOCK(f,0); /* buffer to be returned */ rsrv = NIL(Sfrsrv_t*); us = NIL(uchar*); un = 0; found = 0; /* compatibility mode */ type = type < 0 ? SF_LASTR : type == 1 ? SF_STRING : type; if(type&SF_LASTR) /* return the broken record */ { if((rsrv = f->rsrv) && (un = -rsrv->slen) > 0) { us = rsrv->data; found = 1; } goto done; } while(!found) { /* fill buffer if necessary */ if((n = (ends = f->endb) - (s = f->next)) <= 0) { /* for unseekable devices, peek-read 1 record */ f->getr = rc; f->mode |= SF_RC; /* fill buffer the conventional way */ if(SFRPEEK(f,s,n) <= 0) { us = NIL(uchar*); goto done; } else { ends = s+n; if(f->mode&SF_RC) { s = ends[-1] == rc ? ends-1 : ends; goto do_copy; } } } #if _lib_memchr if(!(s = (uchar*)memchr((char*)s,rc,n))) s = ends; #else while(*s != rc) if((s += 1) == ends) break; #endif do_copy: if(s < ends) { s += 1; /* include the separator */ found = 1; if(!us && (!(type&SF_STRING) || !(f->flags&SF_STRING) || ((f->flags&SF_STRING) && (f->bits&SF_BOTH) ) ) ) { /* returning data in buffer */ us = f->next; un = s - f->next; f->next = s; goto done; } } /* amount to be read */ n = s - f->next; /* get internal buffer */ if(!rsrv || rsrv->size < un+n+1) { if(rsrv) rsrv->slen = un; if((rsrv = _sfrsrv(f,un+n+1)) != NIL(Sfrsrv_t*)) us = rsrv->data; else { us = NIL(uchar*); goto done; } } /* now copy data */ s = us+un; un += n; ends = f->next; f->next += n; MEMCPY(s,ends,n); } done: _Sfi = f->val = un; f->getr = 0; if(found && rc != 0 && (type&SF_STRING) ) { us[un-1] = '\0'; if(us >= f->data && us < f->endb) { f->getr = rc; f->mode |= SF_GETR; } } /* prepare for a call to get the broken record */ if(rsrv) rsrv->slen = found ? 0 : -un; SFOPEN(f,0); if(us && (type&SF_LOCKR) ) { f->mode |= SF_PEEK|SF_GETR; f->endr = f->data; } SFMTXRETURN(f, (char*)us); } now copy data */ s = us+un; un += n; ends = f->next; f->next += n; MEMCPY(s,ends,n); } done: _Sfi = f->val = un; f->getr = 0; if(found && rc != 0 && (type&SF_STRING) ) { us[un-1] = '\0'; if(us >= f->data && us < f->endb) { f->getr = rc; f->mode |= SF_GETR; } } /* prepare for a call to get the broken record */ if(rsrv) rsrv->slen = found ? 0 : -un; SFOPEN(f,0); if(us && (type&SF_LOCKR) ) { f->mode |= SF_PEEK|SF_GETRsrc/lib/sfio/sfputr.c000644 151361 151361 00000003410 07432261525 014520 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Put out a null-terminated string ** ** Written by Kiem-Phong Vo. */ #if __STD_C ssize_t sfputr(reg Sfio_t* f, const char* s, reg int rc) #else ssize_t sfputr(f,s,rc) reg Sfio_t* f; /* write to this stream */ char* s; /* string to write */ reg int rc; /* record separator. */ #endif { reg ssize_t p, n, w; reg uchar* ps; SFMTXSTART(f,-1); if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0) SFMTXRETURN(f, -1); SFLOCK(f,0); for(w = 0; (*s || rc >= 0); ) { SFWPEEK(f,ps,p); if(p == 0 || (f->flags&SF_WHOLE) ) { n = strlen(s); if(p >= (n + (rc < 0 ? 0 : 1)) ) { /* buffer can hold everything */ if(n > 0) { memcpy(ps, s, n); ps += n; w += n; } if(rc >= 0) { *ps++ = rc; w += 1; } f->next = ps; } else { /* create a reserve buffer to hold data */ Sfrsrv_t* rsrv; p = n + (rc >= 0 ? 1 : 0); if(!(rsrv = _sfrsrv(f, p)) ) n = 0; else { if(n > 0) memcpy(rsrv->data, s, n); if(rc >= 0) rsrv->data[n] = rc; if((n = SFWRITE(f,rsrv->data,p)) < 0 ) n = 0; } w += n; } break; } if(*s == 0) { *ps++ = rc; f->next = ps; w += 1; break; } #if _lib_memccpy if((ps = (uchar*)memccpy(ps,s,'\0',p)) != NIL(uchar*)) ps -= 1; else ps = f->next+p; s += ps - f->next; #else for(; p > 0; --p, ++ps, ++s) if((*ps = *s) == 0) break; #endif w += ps - f->next; f->next = ps; } /* sync unseekable shared streams */ if(f->extent < 0 && (f->flags&SF_SHARE) ) (void)SFFLSBUF(f,-1); /* check for line buffering */ else if((f->flags&SF_LINE) && !(f->flags&SF_STRING) && (n = f->next-f->data) > 0) { if(n > w) n = w; f->next -= n; (void)SFWRITE(f,(Void_t*)f->next,n); } SFOPEN(f,0); SFMTXRETURN(f, w); } ps -= 1; else ps = f->next+p; s += ps - f->next; #else for(; p > 0; --p, ++ps, ++s) if((*ps = *s) == 0) break; #endif w += ps - f->next; f->next = ps; } /* sync unseekable shared streams */ if(f->extent < 0 && (f->flags&SF_SHAsrc/lib/sfio/sfgetl.c000644 151361 151361 00000001504 07432261523 014461 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Read a long value coded in a portable format. ** ** Written by Kiem-Phong Vo */ #if __STD_C Sflong_t sfgetl(reg Sfio_t* f) #else Sflong_t sfgetl(f) reg Sfio_t* f; #endif { Sflong_t v; reg uchar *s, *ends, c; reg int p; SFMTXSTART(f,(Sflong_t)(-1)); if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) SFMTXRETURN(f, (Sflong_t)(-1)); SFLOCK(f,0); for(v = 0;;) { if(SFRPEEK(f,s,p) <= 0) { f->flags |= SF_ERROR; v = (Sflong_t)(-1); goto done; } for(ends = s+p; s < ends;) { c = *s++; if(c&SF_MORE) v = ((Sfulong_t)v << SF_UBITS) | SFUVALUE(c); else { /* special translation for this byte */ v = ((Sfulong_t)v << SF_SBITS) | SFSVALUE(c); f->next = s; v = (c&SF_SIGN) ? -v-1 : v; goto done; } } f->next = s; } done : SFOPEN(f,0); SFMTXRETURN(f, v); } 0) < 0) SFMTXRETURN(f, (Sflong_t)(-1)); SFLOCK(f,0); for(v = 0;;) { if(SFRPEEK(f,s,p) <= 0) { f->flags |= SF_ERROR; v = (Sflong_t)(-1); goto done; } for(ends = s+p; s < esrc/lib/sfio/sfputl.c000644 151361 151361 00000002253 07432261525 014516 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Write out a long value in a portable format ** ** Written by Kiem-Phong Vo. */ #if __STD_C int _sfputl(reg Sfio_t* f, Sflong_t v) #else int _sfputl(f,v) reg Sfio_t* f; /* write a portable long to this stream */ Sflong_t v; /* the value to be written */ #endif { #define N_ARRAY (2*sizeof(Sflong_t)) reg uchar *s, *ps; reg ssize_t n, p; uchar c[N_ARRAY]; SFMTXSTART(f,-1); if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0) SFMTXRETURN(f, -1); SFLOCK(f,0); s = ps = &(c[N_ARRAY-1]); if(v < 0) { /* add 1 to avoid 2-complement problems with -SF_MAXINT */ v = -(v+1); *s = (uchar)(SFSVALUE(v) | SF_SIGN); } else *s = (uchar)(SFSVALUE(v)); v = (Sfulong_t)v >> SF_SBITS; while(v > 0) { *--s = (uchar)(SFUVALUE(v) | SF_MORE); v = (Sfulong_t)v >> SF_UBITS; } n = (ps-s)+1; if(n > 8 || SFWPEEK(f,ps,p) < n) n = SFWRITE(f,(Void_t*)s,n); /* write the hard way */ else { switch(n) { case 8 : *ps++ = *s++; case 7 : *ps++ = *s++; case 6 : *ps++ = *s++; case 5 : *ps++ = *s++; case 4 : *ps++ = *s++; case 3 : *ps++ = *s++; case 2 : *ps++ = *s++; case 1 : *ps++ = *s++; } f->next = ps; } SFOPEN(f,0); SFMTXRETURN(f, n); } v = (Sfulong_t)v >> SF_SBITS; while(v > 0) { *--s = (uchar)(SFUVALUE(v) | SF_MORE); v = (Sfulong_t)v >> SF_UBITS; } n = (ps-s)+1; if(n > 8 || SFWPEEK(f,ps,p) < n) n = SFWRITE(f,(Void_t*)s,n); /* write the hard way */ else { switch(n) { case 8 : *ps++ = *s++; case 7 : *ps++ = *s++; case 6 : *ps++ = *s++; case 5 : *pssrc/lib/sfio/sfgetm.c000644 151361 151361 00000001363 07432261523 014465 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Read an unsigned long value coded portably for a given range. ** ** Written by Kiem-Phong Vo */ #if __STD_C Sfulong_t sfgetm(reg Sfio_t* f, Sfulong_t m) #else Sfulong_t sfgetm(f, m) reg Sfio_t* f; Sfulong_t m; #endif { Sfulong_t v; reg uchar *s, *ends, c; reg int p; SFMTXSTART(f, (Sfulong_t)(-1)); if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) SFMTXRETURN(f, (Sfulong_t)(-1)); SFLOCK(f,0); for(v = 0;; ) { if(SFRPEEK(f,s,p) <= 0) { f->flags |= SF_ERROR; v = (Sfulong_t)(-1); goto done; } for(ends = s+p; s < ends;) { c = *s++; v = (v << SF_BBITS) | SFBVALUE(c); if((m >>= SF_BBITS) <= 0) { f->next = s; goto done; } } f->next = s; } done: SFOPEN(f,0); SFMTXRETURN(f, v); } Sfulong_t v; reg uchar *s, *ends, c; reg int p; SFMTXSTART(f, (Sfulong_t)(-1)); if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) SFMTXRETURN(f, (Sfulong_t)(-1)); SFLOCK(f,0); for(v = 0;; ) { if(SFRPEEK(f,s,p) <= 0) { f->flags |= SF_ERROR; v = (Sfusrc/lib/sfio/sfputm.c000644 151361 151361 00000002226 07432261525 014517 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Write out an unsigned long value in a portable format. ** ** Written by Kiem-Phong Vo. */ #if __STD_C int _sfputm(reg Sfio_t* f, Sfulong_t v, Sfulong_t max) #else int _sfputm(f,v,max) reg Sfio_t* f; /* write a portable ulong to this stream */ Sfulong_t v; /* the unsigned value to be written */ Sfulong_t max; /* the max value of the range */ #endif { #define N_ARRAY (2*sizeof(Sfulong_t)) reg uchar *s, *ps; reg ssize_t n, p; uchar c[N_ARRAY]; SFMTXSTART(f, -1); if(v > max || (f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0) ) SFMTXRETURN(f, -1); SFLOCK(f,0); /* code v as integers in base SF_UBASE */ s = ps = &(c[N_ARRAY-1]); *s = (uchar)SFBVALUE(v); while((max >>= SF_BBITS) > 0 ) { v >>= SF_BBITS; *--s = (uchar)SFBVALUE(v); } n = (ps-s)+1; if(n > 8 || SFWPEEK(f,ps,p) < n) n = SFWRITE(f,(Void_t*)s,n); /* write the hard way */ else { switch(n) { case 8 : *ps++ = *s++; case 7 : *ps++ = *s++; case 6 : *ps++ = *s++; case 5 : *ps++ = *s++; case 4 : *ps++ = *s++; case 3 : *ps++ = *s++; case 2 : *ps++ = *s++; case 1 : *ps++ = *s++; } f->next = ps; } SFOPEN(f,0); SFMTXRETURN(f, (int)n); } RAY-1]); *s = (uchar)SFBVALUE(v); while((max >>= SF_BBITS) > 0 ) { v >>= SF_BBITS; *--s = (uchar)SFBVALUE(v); } n = (ps-s)+1; if(n > 8 || SFWPEEK(f,ps,p) < n) n = SFWRITE(f,(Void_t*)s,n); /* write the hard way */ else { switch(n) { case 8 : *ps++ = *s++; case 7 : *ps++ = *s++; case 6 : *ps++ = *s++; case 5 : *ps++ = *s++; case 4 : *ps+src/lib/sfio/sfgetd.c000644 151361 151361 00000001521 07436606753 014464 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Read a portably coded double value ** ** Written by Kiem-Phong Vo */ #if __STD_C Sfdouble_t sfgetd(Sfio_t* f) #else Sfdouble_t sfgetd(f) Sfio_t* f; #endif { reg uchar *s, *ends, c; reg int p, sign, exp; Sfdouble_t v; SFMTXSTART(f,-1.); if((sign = sfgetc(f)) < 0 || (exp = (int)sfgetu(f)) < 0) SFMTXRETURN(f, -1.); if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) SFMTXRETURN(f, -1.); SFLOCK(f,0); v = 0.; for(;;) { /* fast read for data */ if(SFRPEEK(f,s,p) <= 0) { f->flags |= SF_ERROR; v = -1.; goto done; } for(ends = s+p; s < ends; ) { c = *s++; v += SFUVALUE(c); v = ldexpl(v,-SF_PRECIS); if(!(c&SF_MORE)) { f->next = s; goto done; } } f->next = s; } done: v = ldexpl(v,(sign&02) ? -exp : exp); if(sign&01) v = -v; SFOPEN(f,0); SFMTXRETURN(f, v); } N(f, -1.); if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) SFMTXRETURN(f, -1.); SFLOCK(f,0); v = 0.; for(;;) { /* fast read for data */ if(SFRPEEK(f,s,p) <= 0) src/lib/sfio/sfputd.c000644 151361 151361 00000002337 07436606753 014523 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Write out a floating point value in a portable format ** ** Written by Kiem-Phong Vo. */ #if __STD_C int _sfputd(Sfio_t* f, Sfdouble_t v) #else int _sfputd(f,v) Sfio_t* f; Sfdouble_t v; #endif { #define N_ARRAY (16*sizeof(Sfdouble_t)) reg ssize_t n, w; reg uchar *s, *ends; int exp; uchar c[N_ARRAY]; Sfdouble_t x; SFMTXSTART(f,-1); if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0) SFMTXRETURN(f, -1); SFLOCK(f,0); /* get the sign of v */ if(v < 0.) { v = -v; n = 1; } else n = 0; /* make the magnitude of v < 1 */ if(v != 0.) v = frexpl(v,&exp); else exp = 0; /* code the sign of v and exp */ if((w = exp) < 0) { n |= 02; w = -w; } /* write out the signs and the exp */ SFOPEN(f,0); if(sfputc(f,n) < 0 || (w = sfputu(f,w)) < 0) SFMTXRETURN(f, -1); SFLOCK(f,0); w += 1; s = (ends = &c[0])+sizeof(c); while(s > ends) { /* get 2^SF_PRECIS precision at a time */ n = (int)(x = ldexpl(v,SF_PRECIS)); *--s = n|SF_MORE; v = x-n; if(v <= 0.) break; } /* last byte is not SF_MORE */ ends = &c[0] + sizeof(c) -1; *ends &= ~SF_MORE; /* write out coded bytes */ n = ends - s + 1; w = SFWRITE(f,(Void_t*)s,n) == n ? w+n : -1; SFOPEN(f,0); SFMTXRETURN(f,w); } */ SFOPEN(f,0); if(sfputc(f,n) < 0 || (w = sfputu(f,w)) < 0) SFMTXRETURN(f, -1); SFLOCK(f,0); w += 1; s = (ends = &c[0])+sizeof(c); while(s > ends) { /* get 2^SF_PRECIS precision at a time */ n = (int)(x = ldexpl(v,SF_PRECIS)); *--s = n|SF_MORE; v = x-n; if(v <= 0.) bsrc/lib/sfio/sfpurge.c000644 151361 151361 00000002771 07432261525 014661 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Delete all pending data in the buffer ** ** Written by Kiem-Phong Vo. */ #if __STD_C int sfpurge(reg Sfio_t* f) #else int sfpurge(f) reg Sfio_t* f; #endif { reg int mode; SFMTXSTART(f,-1); if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0) SFMTXRETURN(f, -1); if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf) (void)(*f->disc->exceptf)(f,SF_PURGE,(Void_t*)((int)1),f->disc); if(f->disc == _Sfudisc) (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*))); /* cannot purge read string streams */ if((f->flags&SF_STRING) && (f->mode&SF_READ) ) goto done; SFLOCK(f,0); /* if memory map must be a read stream, pretend data is gone */ #ifdef MAP_TYPE if(f->bits&SF_MMAP) { f->here -= f->endb - f->next; if(f->data) { SFMUNMAP(f,f->data,f->endb-f->data); SFSK(f,f->here,SEEK_SET,f->disc); } SFOPEN(f,0); SFMTXRETURN(f, 0); } #endif switch(f->mode&~SF_LOCK) { default : SFOPEN(f,0); SFMTXRETURN(f, -1); case SF_WRITE : f->next = f->data; if(!f->proc || !(f->flags&SF_READ) || !(f->mode&SF_WRITE) ) break; /* 2-way pipe, must clear read buffer */ (void)_sfmode(f,SF_READ,1); /* fall through */ case SF_READ: if(f->extent >= 0 && f->endb > f->next) { f->here -= f->endb-f->next; SFSK(f,f->here,SEEK_SET,f->disc); } f->endb = f->next = f->data; break; } SFOPEN(f,0); done: if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf) (void)(*f->disc->exceptf)(f,SF_PURGE,(Void_t*)((int)0),f->disc); SFMTXRETURN(f, 0); } ; if(src/lib/sfio/sfio.h000644 151361 151361 00000035415 07477150066 014162 0ustar00kpvkpv000000 000000 #ifndef _SFIO_H #define _SFIO_H 1 /******************************************************************************** * This product contains certain software code or other information * * ("AT&T Software") proprietary to AT&T Corp. ("AT&T"). * * The AT&T Software is provided to you "AS IS". YOU ASSUME TOTAL * * RESPONSIBILITY AND RISK FOR USE OF THE AT&T SOFTWARE. * * AT&T DOES NOT MAKE, AND EXPRESSLY DISCLAIMS, ANY EXPRESS OR * * IMPLIED WARRANTIES OF ANY KIND WHATSOEVER, INCLUDING, * * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR * * FITNESS FOR A PARTICULAR PURPOSE, WARRANTIES OF TITLE OR * * NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS, * * ANY WARRANTIES ARISING BY USAGE OF TRADE, COURSE OF DEALING OR * * COURSE OF PERFORMANCE, OR ANY WARRANTY THAT THE AT&T SOFTWARE * * IS "ERROR FREE" OR WILL MEET YOUR REQUIREMENTS. * * * * All rights reserved. AT&T is a registered trademark of AT&T Corp. * ********************************************************************************/ #define SFIO_VERSION 20020531L /* Public header file for the sfio library ** ** Written by Kiem-Phong Vo */ typedef struct _sfio_s Sfio_t; typedef struct _sfdisc_s Sfdisc_t; #if defined(_AST_STD_H) || defined(_PACKAGE_ast) && defined(_SFIO_PRIVATE) #include #else #include #endif /* _PACKAGE_ast */ /* Sfoff_t should be large enough for largest file address */ #define Sfoff_t _ast_intmax_t #define Sflong_t _ast_intmax_t #define Sfulong_t unsigned _ast_intmax_t #define Sfdouble_t _ast_fltmax_t typedef ssize_t (*Sfread_f)_ARG_((Sfio_t*, Void_t*, size_t, Sfdisc_t*)); typedef ssize_t (*Sfwrite_f)_ARG_((Sfio_t*, const Void_t*, size_t, Sfdisc_t*)); typedef Sfoff_t (*Sfseek_f)_ARG_((Sfio_t*, Sfoff_t, int, Sfdisc_t*)); typedef int (*Sfexcept_f)_ARG_((Sfio_t*, int, Void_t*, Sfdisc_t*)); /* discipline structure */ struct _sfdisc_s { Sfread_f readf; /* read function */ Sfwrite_f writef; /* write function */ Sfseek_f seekf; /* seek function */ Sfexcept_f exceptf; /* to handle exceptions */ Sfdisc_t* disc; /* the continuing discipline */ }; #include /* formatting environment */ typedef struct _sffmt_s Sffmt_t; typedef int (*Sffmtext_f)_ARG_((Sfio_t*, Void_t*, Sffmt_t*)); typedef int (*Sffmtevent_f)_ARG_((Sfio_t*, int, Void_t*, Sffmt_t*)); struct _sffmt_s { long version;/* version of this structure */ Sffmtext_f extf; /* function to process arguments */ Sffmtevent_f eventf; /* process events */ char* form; /* format string to stack */ _ast_va_list args; /* corresponding arg list */ int fmt; /* format character */ ssize_t size; /* object size */ int flags; /* formatting flags */ int width; /* width of field */ int precis; /* precision required */ int base; /* conversion base */ char* t_str; /* type string */ ssize_t n_str; /* length of t_str */ Void_t* mbs; /* multibyte state for format string */ Void_t* none; /* unused for now */ }; #define sffmtversion(fe,type) \ (type ? ((fe)->version = SFIO_VERSION) : (fe)->version) #define SFFMT_SSHORT 00000010 /* 'hh' flag, char */ #define SFFMT_TFLAG 00000020 /* 't' flag, ptrdiff_t */ #define SFFMT_ZFLAG 00000040 /* 'z' flag, size_t */ #define SFFMT_LEFT 00000100 /* left-justification */ #define SFFMT_SIGN 00000200 /* must have a sign */ #define SFFMT_BLANK 00000400 /* if not signed, prepend a blank */ #define SFFMT_ZERO 00001000 /* zero-padding on the left */ #define SFFMT_ALTER 00002000 /* alternate formatting */ #define SFFMT_THOUSAND 00004000 /* thousand grouping */ #define SFFMT_SKIP 00010000 /* skip assignment in scanf() */ #define SFFMT_SHORT 00020000 /* 'h' flag */ #define SFFMT_LONG 00040000 /* 'l' flag */ #define SFFMT_LLONG 00100000 /* 'll' flag */ #define SFFMT_LDOUBLE 00200000 /* 'L' flag */ #define SFFMT_VALUE 00400000 /* value is returned */ #define SFFMT_ARGPOS 01000000 /* getting arg for $ patterns */ #define SFFMT_IFLAG 02000000 /* 'I' flag */ #define SFFMT_JFLAG 04000000 /* 'j' flag, intmax_t */ #define SFFMT_SET 07777770 /* flags settable on calling extf */ /* for sfmutex() call */ #define SFMTX_LOCK 0 /* up mutex count */ #define SFMTX_TRYLOCK 1 /* try to up mutex count */ #define SFMTX_UNLOCK 2 /* down mutex count */ #define SFMTX_CLRLOCK 3 /* clear mutex count */ /* various constants */ #ifndef NULL #define NULL 0 #endif #ifndef EOF #define EOF (-1) #endif #ifndef SEEK_SET #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 #endif /* bits for various types of files */ #define SF_READ 0000001 /* open for reading */ #define SF_WRITE 0000002 /* open for writing */ #define SF_STRING 0000004 /* a string stream */ #define SF_APPENDWR 0000010 /* file is in append mode only */ #define SF_MALLOC 0000020 /* buffer is malloc-ed */ #define SF_LINE 0000040 /* line buffering */ #define SF_SHARE 0000100 /* stream with shared file descriptor */ #define SF_EOF 0000200 /* eof was detected */ #define SF_ERROR 0000400 /* an error happened */ #define SF_STATIC 0001000 /* a stream that cannot be freed */ #define SF_IOCHECK 0002000 /* call exceptf before doing IO */ #define SF_PUBLIC 0004000 /* SF_SHARE and follow physical seek */ #define SF_MTSAFE 0010000 /* need thread safety */ #define SF_WHOLE 0020000 /* preserve wholeness of sfwrite/sfputr */ #define SF_FLAGS 0077177 /* PUBLIC FLAGS PASSABLE TO SFNEW() */ #define SF_SETS 0027163 /* flags passable to sfset() */ #ifndef _SF_NO_OBSOLETE #define SF_BUFCONST 0400000 /* unused flag - for compatibility only */ #endif /* for sfgetr/sfreserve to hold a record */ #define SF_LOCKR 0000010 /* lock record, stop access to stream */ #define SF_LASTR 0000020 /* get the last incomplete record */ /* exception events: SF_NEW(0), SF_READ(1), SF_WRITE(2) and the below */ #define SF_SEEK 3 /* seek error */ #define SF_CLOSING 4 /* when stream is about to be closed */ #define SF_DPUSH 5 /* when discipline is being pushed */ #define SF_DPOP 6 /* when discipline is being popped */ #define SF_DPOLL 7 /* see if stream is ready for I/O */ #define SF_DBUFFER 8 /* buffer not empty during push or pop */ #define SF_SYNC 9 /* announcing start/end synchronization */ #define SF_PURGE 10 /* a sfpurge() call was issued */ #define SF_FINAL 11 /* closing is done except stream free */ #define SF_READY 12 /* a polled stream is ready */ #define SF_LOCKED 13 /* stream is in a locked state */ #define SF_ATEXIT 14 /* process is exiting */ #define SF_EVENT 100 /* start of user-defined events */ /* for stack and disciplines */ #define SF_POPSTACK ((Sfio_t*)0) /* pop the stream stack */ #define SF_POPDISC ((Sfdisc_t*)0) /* pop the discipline stack */ /* for the notify function and discipline exception */ #define SF_NEW 0 /* new stream */ #define SF_SETFD (-1) /* about to set the file descriptor */ #define SF_BUFSIZE 8192 /* default buffer size */ #define SF_UNBOUND (-1) /* unbounded buffer size */ /* namespace incursion workarounds -- migrate to the new names */ #if !_mac_SF_APPEND #define SF_APPEND SF_APPENDWR /* BSDI sys/stat.h */ #endif #if !_mac_SF_CLOSE #define SF_CLOSE SF_CLOSING /* AIX sys/socket.h */ #endif _BEGIN_EXTERNS_ extern ssize_t _Sfi; /* standard in/out/err streams */ #if _BLD_sfio && defined(__EXPORT__) #define __PUBLIC_DATA__ __EXPORT__ #else #if !_BLD_sfio && defined(__IMPORT__) #define __PUBLIC_DATA__ __IMPORT__ #else #define __PUBLIC_DATA__ #endif #endif extern __PUBLIC_DATA__ Sfio_t* sfstdin; extern __PUBLIC_DATA__ Sfio_t* sfstdout; extern __PUBLIC_DATA__ Sfio_t* sfstderr; #if _UWIN #undef __PUBLIC_DATA__ #define __PUBLIC_DATA__ #endif extern __PUBLIC_DATA__ Sfio_t _Sfstdin; extern __PUBLIC_DATA__ Sfio_t _Sfstdout; extern __PUBLIC_DATA__ Sfio_t _Sfstderr; #undef __PUBLIC_DATA__ #if _BLD_sfio && defined(__EXPORT__) #define extern __EXPORT__ #endif extern Sfio_t* sfnew _ARG_((Sfio_t*, Void_t*, size_t, int, int)); extern Sfio_t* sfopen _ARG_((Sfio_t*, const char*, const char*)); extern Sfio_t* sfpopen _ARG_((Sfio_t*, const char*, const char*)); extern Sfio_t* sfstack _ARG_((Sfio_t*, Sfio_t*)); extern Sfio_t* sfswap _ARG_((Sfio_t*, Sfio_t*)); extern Sfio_t* sftmp _ARG_((size_t)); extern int sfpurge _ARG_((Sfio_t*)); extern int sfpoll _ARG_((Sfio_t**, int, int)); extern Void_t* sfreserve _ARG_((Sfio_t*, ssize_t, int)); extern int sfresize _ARG_((Sfio_t*, Sfoff_t)); extern int sfsync _ARG_((Sfio_t*)); extern int sfclrlock _ARG_((Sfio_t*)); extern Void_t* sfsetbuf _ARG_((Sfio_t*, Void_t*, size_t)); extern Sfdisc_t* sfdisc _ARG_((Sfio_t*,Sfdisc_t*)); extern int sfraise _ARG_((Sfio_t*, int, Void_t*)); extern int sfnotify _ARG_((void(*)(Sfio_t*, int, int))); extern int sfset _ARG_((Sfio_t*, int, int)); extern int sfsetfd _ARG_((Sfio_t*, int)); extern Sfio_t* sfpool _ARG_((Sfio_t*, Sfio_t*, int)); extern ssize_t sfread _ARG_((Sfio_t*, Void_t*, size_t)); extern ssize_t sfwrite _ARG_((Sfio_t*, const Void_t*, size_t)); extern Sfoff_t sfmove _ARG_((Sfio_t*, Sfio_t*, Sfoff_t, int)); extern int sfclose _ARG_((Sfio_t*)); extern Sfoff_t sftell _ARG_((Sfio_t*)); extern Sfoff_t sfseek _ARG_((Sfio_t*, Sfoff_t, int)); extern ssize_t sfputr _ARG_((Sfio_t*, const char*, int)); extern char* sfgetr _ARG_((Sfio_t*, int, int)); extern ssize_t sfnputc _ARG_((Sfio_t*, int, size_t)); extern int sfungetc _ARG_((Sfio_t*, int)); extern int sfprintf _ARG_((Sfio_t*, const char*, ...)); extern char* sfprints _ARG_((const char*, ...)); extern int sfsprintf _ARG_((char*, int, const char*, ...)); extern int sfvsprintf _ARG_((char*, int, const char*, _ast_va_list)); extern int sfvprintf _ARG_((Sfio_t*, const char*, _ast_va_list)); extern int sfscanf _ARG_((Sfio_t*, const char*, ...)); extern int sfsscanf _ARG_((const char*, const char*, ...)); extern int sfvsscanf _ARG_((const char*, const char*, _ast_va_list)); extern int sfvscanf _ARG_((Sfio_t*, const char*, _ast_va_list)); /* mutex locking for thread-safety */ extern int sfmutex _ARG_((Sfio_t*, int)); /* io functions with discipline continuation */ extern ssize_t sfrd _ARG_((Sfio_t*, Void_t*, size_t, Sfdisc_t*)); extern ssize_t sfwr _ARG_((Sfio_t*, const Void_t*, size_t, Sfdisc_t*)); extern Sfoff_t sfsk _ARG_((Sfio_t*, Sfoff_t, int, Sfdisc_t*)); extern ssize_t sfpkrd _ARG_((int, Void_t*, size_t, int, long, int)); /* portable handling of primitive types */ extern int sfdlen _ARG_((Sfdouble_t)); extern int sfllen _ARG_((Sflong_t)); extern int sfulen _ARG_((Sfulong_t)); extern int sfputd _ARG_((Sfio_t*, Sfdouble_t)); extern int sfputl _ARG_((Sfio_t*, Sflong_t)); extern int sfputu _ARG_((Sfio_t*, Sfulong_t)); extern int sfputm _ARG_((Sfio_t*, Sfulong_t, Sfulong_t)); extern int sfputc _ARG_((Sfio_t*, int)); extern Sfdouble_t sfgetd _ARG_((Sfio_t*)); extern Sflong_t sfgetl _ARG_((Sfio_t*)); extern Sfulong_t sfgetu _ARG_((Sfio_t*)); extern Sfulong_t sfgetm _ARG_((Sfio_t*, Sfulong_t)); extern int sfgetc _ARG_((Sfio_t*)); extern int _sfputd _ARG_((Sfio_t*, Sfdouble_t)); extern int _sfputl _ARG_((Sfio_t*, Sflong_t)); extern int _sfputu _ARG_((Sfio_t*, Sfulong_t)); extern int _sfputm _ARG_((Sfio_t*, Sfulong_t, Sfulong_t)); extern int _sfflsbuf _ARG_((Sfio_t*, int)); extern int _sffilbuf _ARG_((Sfio_t*, int)); extern int _sfdlen _ARG_((Sfdouble_t)); extern int _sfllen _ARG_((Sflong_t)); extern int _sfulen _ARG_((Sfulong_t)); /* miscellaneous function analogues of fast in-line functions */ extern Sfoff_t sfsize _ARG_((Sfio_t*)); extern int sfclrerr _ARG_((Sfio_t*)); extern int sfeof _ARG_((Sfio_t*)); extern int sferror _ARG_((Sfio_t*)); extern int sffileno _ARG_((Sfio_t*)); extern int sfstacked _ARG_((Sfio_t*)); extern ssize_t sfvalue _ARG_((Sfio_t*)); extern ssize_t sfslen _ARG_((void)); #undef extern _END_EXTERNS_ /* coding long integers in a portable and compact fashion */ #define SF_SBITS 6 #define SF_UBITS 7 #define SF_BBITS 8 #define SF_SIGN (1 << SF_SBITS) #define SF_MORE (1 << SF_UBITS) #define SF_BYTE (1 << SF_BBITS) #define SF_U1 SF_MORE #define SF_U2 (SF_U1*SF_U1) #define SF_U3 (SF_U2*SF_U1) #define SF_U4 (SF_U3*SF_U1) #if __cplusplus #define _SF_(f) (f) #else #define _SF_(f) ((Sfio_t*)(f)) #endif #define __sf_putd(f,v) (_sfputd(_SF_(f),(Sfdouble_t)(v))) #define __sf_putl(f,v) (_sfputl(_SF_(f),(Sflong_t)(v))) #define __sf_putu(f,v) (_sfputu(_SF_(f),(Sfulong_t)(v))) #define __sf_putm(f,v,m) (_sfputm(_SF_(f),(Sfulong_t)(v),(Sfulong_t)(m))) #define __sf_putc(f,c) (_SF_(f)->_next >= _SF_(f)->_endw ? \ _sfflsbuf(_SF_(f),(int)((unsigned char)(c))) : \ (int)(*_SF_(f)->_next++ = (unsigned char)(c)) ) #define __sf_getc(f) (_SF_(f)->_next >= _SF_(f)->_endr ? _sffilbuf(_SF_(f),0) : \ (int)(*_SF_(f)->_next++) ) #define __sf_dlen(v) (_sfdlen((Sfdouble_t)(v)) ) #define __sf_llen(v) (_sfllen((Sflong_t)(v)) ) #define __sf_ulen(v) ((Sfulong_t)(v) < SF_U1 ? 1 : (Sfulong_t)(v) < SF_U2 ? 2 : \ (Sfulong_t)(v) < SF_U3 ? 3 : (Sfulong_t)(v) < SF_U4 ? 4 : 5) #define __sf_fileno(f) (_SF_(f)->_file) #define __sf_eof(f) (_SF_(f)->_flags&SF_EOF) #define __sf_error(f) (_SF_(f)->_flags&SF_ERROR) #define __sf_clrerr(f) (_SF_(f)->_flags &= ~(SF_ERROR|SF_EOF)) #define __sf_stacked(f) (_SF_(f)->_push != (Sfio_t*)0) #define __sf_value(f) (_SF_(f)->_val) #define __sf_slen() (_Sfi) #if defined(__INLINE__) && !_BLD_sfio __INLINE__ int sfputd(Sfio_t* f, Sfdouble_t v) { return __sf_putd(f,v); } __INLINE__ int sfputl(Sfio_t* f, Sflong_t v) { return __sf_putl(f,v); } __INLINE__ int sfputu(Sfio_t* f, Sfulong_t v) { return __sf_putu(f,v); } __INLINE__ int sfputm(Sfio_t* f, Sfulong_t v, Sfulong_t m) { return __sf_putm(f,v,m); } __INLINE__ int sfputc(Sfio_t* f, int c) { return __sf_putc(f,c); } __INLINE__ int sfgetc(Sfio_t* f) { return __sf_getc(f); } __INLINE__ int sfdlen(Sfdouble_t v) { return __sf_dlen(v); } __INLINE__ int sfllen(Sflong_t v) { return __sf_llen(v); } __INLINE__ int sfulen(Sfulong_t v) { return __sf_ulen(v); } __INLINE__ int sffileno(Sfio_t* f) { return __sf_fileno(f); } __INLINE__ int sfeof(Sfio_t* f) { return __sf_eof(f); } __INLINE__ int sferror(Sfio_t* f) { return __sf_error(f); } __INLINE__ int sfclrerr(Sfio_t* f) { return __sf_clrerr(f); } __INLINE__ int sfstacked(Sfio_t* f) { return __sf_stacked(f); } __INLINE__ ssize_t sfvalue(Sfio_t* f) { return __sf_value(f); } #else #define sfputd(f,v) ( __sf_putd((f),(v)) ) #define sfputl(f,v) ( __sf_putl((f),(v)) ) #define sfputu(f,v) ( __sf_putu((f),(v)) ) #define sfputm(f,v,m) ( __sf_putm((f),(v),(m)) ) #define sfputc(f,c) ( __sf_putc((f),(c)) ) #define sfgetc(f) ( __sf_getc(f) ) #define sfdlen(v) ( __sf_dlen(v) ) #define sfllen(v) ( __sf_llen(v) ) #define sfulen(v) ( __sf_ulen(v) ) #define sffileno(f) ( __sf_fileno(f) ) #define sfeof(f) ( __sf_eof(f) ) #define sferror(f) ( __sf_error(f) ) #define sfclrerr(f) ( __sf_clrerr(f) ) #define sfstacked(f) ( __sf_stacked(f) ) #define sfvalue(f) ( __sf_value(f) ) #define sfslen() ( __sf_slen() ) #endif /*__INLINE__*/ #endif /* _SFIO_H */ c(f,c) ( __sf_putc((f),(c)) ) #define sfgetc(f) ( __sf_getc(f) ) #define sfdlen(v) ( __sf_dlen(v) ) #define sfllen(v) ( __sf_llen(v) ) #define sfulen(v) ( __sf_ulen(v) ) #define sffileno(f) ( __sf_fileno(f) ) #define sfeof(src/lib/sfio/Sfio_c000755 151361 151361 00000000000 07432261522 014146 0ustar00kpvkpv000000 000000 src/lib/sfio/sfscanf.c000644 151361 151361 00000002375 07432261526 014632 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Read formated data from a stream ** ** Written by Kiem-Phong Vo. */ #if __STD_C int sfscanf(Sfio_t* f, const char* form, ...) #else int sfscanf(va_alist) va_dcl #endif { va_list args; reg int rv; #if __STD_C va_start(args,form); #else reg Sfio_t* f; reg char* form; va_start(args); f = va_arg(args,Sfio_t*); form = va_arg(args,char*); #endif rv = (f && form) ? sfvscanf(f,form,args) : -1; va_end(args); return rv; } #if __STD_C int sfvsscanf(const char* s, const char* form, va_list args) #else int sfvsscanf(s, form, args) char* s; char* form; va_list args; #endif { Sfio_t f; if(!s || !form) return -1; /* make a fake stream */ SFCLEAR(&f,NIL(Vtmutex_t*)); f.flags = SF_STRING|SF_READ; f.bits = SF_PRIVATE; f.mode = SF_READ; f.size = strlen((char*)s); f.data = f.next = f.endw = (uchar*)s; f.endb = f.endr = f.data+f.size; return sfvscanf(&f,form,args); } #if __STD_C int sfsscanf(const char* s, const char* form,...) #else int sfsscanf(va_alist) va_dcl #endif { va_list args; reg int rv; #if __STD_C va_start(args,form); #else reg char* s; reg char* form; va_start(args); s = va_arg(args,char*); form = va_arg(args,char*); #endif rv = (s && form) ? sfvsscanf(s,form,args) : -1; va_end(args); return rv; } = SF_READ; f.size = strlen((char*)s); f.data = f.next = f.endw = (uchar*)s; f.endb = f.endr = f.data+f.size; return sfvscanf(&f,form,args); } #if __STD_C int sfsscanf(const char* s, const char* form,...) #else int sfsscanf(va_alist) va_dcl #endif { va_src/lib/sfio/sfrd.c000644 151361 151361 00000014226 07432261525 014142 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Internal function to do a hard read. ** This knows about discipline and memory mapping, peek read. ** ** Written by Kiem-Phong Vo. */ /* synchronize unseekable write streams */ #if __STD_C static void _sfwrsync(void) #else static void _sfwrsync() #endif { reg Sfpool_t* p; reg Sfio_t* f; reg int n; /* sync all pool heads */ for(p = _Sfpool.next; p; p = p->next) { if(p->n_sf <= 0) continue; f = p->sf[0]; if(!SFFROZEN(f) && f->next > f->data && (f->mode&SF_WRITE) && f->extent < 0 ) (void)_sfflsbuf(f,-1); } /* and all the ones in the discrete pool */ for(n = 0; n < _Sfpool.n_sf; ++n) { f = _Sfpool.sf[n]; if(!SFFROZEN(f) && f->next > f->data && (f->mode&SF_WRITE) && f->extent < 0 ) (void)_sfflsbuf(f,-1); } } #if __STD_C ssize_t sfrd(reg Sfio_t* f, reg Void_t* buf, reg size_t n, Sfdisc_t* disc) #else ssize_t sfrd(f,buf,n,disc) reg Sfio_t* f; reg Void_t* buf; reg size_t n; Sfdisc_t* disc; #endif { Sfoff_t r; reg Sfdisc_t* dc; reg int local, rcrv, dosync, oerrno; SFMTXSTART(f,-1); GETLOCAL(f,local); if((rcrv = f->mode & (SF_RC|SF_RV)) ) f->mode &= ~(SF_RC|SF_RV); f->bits &= ~SF_JUSTSEEK; if(f->mode&SF_PKRD) SFMTXRETURN(f, -1); if(!local && !(f->bits&SF_DCDOWN)) /* an external user's call */ { if(f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) SFMTXRETURN(f, -1); if(f->next < f->endb) { if(SFSYNC(f) < 0) SFMTXRETURN(f, -1); #ifdef MAP_TYPE if((f->bits&SF_MMAP) && f->data) { SFMUNMAP(f, f->data, f->endb-f->data); f->data = NIL(uchar*); } #endif f->next = f->endb = f->endr = f->endw = f->data; } } for(dosync = 0;;) { /* stream locked by sfsetfd() */ if(!(f->flags&SF_STRING) && f->file < 0) SFMTXRETURN(f, 0); f->flags &= ~(SF_EOF|SF_ERROR); dc = disc; if(f->flags&SF_STRING) { if((r = (f->data+f->extent) - f->next) < 0) r = 0; if(r <= 0) goto do_except; SFMTXRETURN(f, (ssize_t)r); } /* warn that a read is about to happen */ SFDISC(f,dc,readf); if(dc && dc->exceptf && (f->flags&SF_IOCHECK) ) { reg int rv; if(local) SETLOCAL(f); if((rv = _sfexcept(f,SF_READ,n,dc)) > 0) n = rv; else if(rv < 0) { f->flags |= SF_ERROR; SFMTXRETURN(f, (ssize_t)rv); } } #ifdef MAP_TYPE if(f->bits&SF_MMAP) { reg ssize_t a, round; sfstat_t st; /* determine if we have to copy data to buffer */ if((uchar*)buf >= f->data && (uchar*)buf <= f->endb) { n += f->endb - f->next; buf = NIL(char*); } /* actual seek location */ if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC) && (r = SFSK(f,(Sfoff_t)0,SEEK_CUR,dc)) != f->here) f->here = r; else f->here -= f->endb-f->next; /* before mapping, make sure we have data to map */ if((f->flags&SF_SHARE) || (size_t)(r = f->extent-f->here) < n) { if((r = fstat(f->file,&st)) < 0) goto do_except; if((r = (f->extent = st.st_size) - f->here) <= 0 ) { r = 0; /* eof */ goto do_except; } } /* make sure current position is page aligned */ if((a = (size_t)(f->here%_Sfpage)) != 0) { f->here -= a; r += a; } /* map minimal requirement */ if(r > (round = (1 + (n+a)/f->size)*f->size) ) r = round; if(f->data) SFMUNMAP(f, f->data, f->endb-f->data); for(;;) { f->data = (uchar*) mmap((caddr_t)0, (size_t)r, (PROT_READ|PROT_WRITE), MAP_PRIVATE, f->file, (sfoff_t)f->here); if(f->data && (caddr_t)f->data != (caddr_t)(-1)) break; else { f->data = NIL(uchar*); if((r >>= 1) < (_Sfpage*SF_NMAP) || (errno != EAGAIN && errno != ENOMEM) ) break; } } if(f->data) { if(f->bits&SF_SEQUENTIAL) SFMMSEQON(f,f->data,r); f->next = f->data+a; f->endr = f->endb = f->data+r; f->endw = f->data; f->here += r; /* make known our seek location */ (void)SFSK(f,f->here,SEEK_SET,dc); if(buf) { if(n > (size_t)(r-a)) n = (ssize_t)(r-a); memcpy(buf,f->next,n); f->next += n; } else n = f->endb - f->next; SFMTXRETURN(f, n); } else { r = -1; f->here += a; /* reset seek pointer to its physical location */ (void)SFSK(f,f->here,SEEK_SET,dc); /* make a buffer */ (void)SFSETBUF(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND); if(!buf) { buf = (Void_t*)f->data; n = f->size; } } } #endif /* sync unseekable write streams to prevent deadlock */ if(!dosync && f->extent < 0) { dosync = 1; _sfwrsync(); } /* make sure file pointer is right */ if(f->extent >= 0 && (f->flags&SF_SHARE) ) { if(!(f->flags&SF_PUBLIC) ) f->here = SFSK(f,f->here,SEEK_SET,dc); else f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,dc); } oerrno = errno; errno = 0; if(dc && dc->readf) { int share = f->flags&SF_SHARE; if(rcrv) /* pass on rcrv for possible continuations */ f->mode |= rcrv; /* tell readf that no peeking necessary */ else f->flags &= ~SF_SHARE; SFDCRD(f,buf,n,dc,r); /* reset flags */ if(rcrv) f->mode &= ~rcrv; else f->flags |= share; } else if(SFISNULL(f)) r = 0; else if(f->extent < 0 && (f->flags&SF_SHARE) && rcrv) { /* try peek read */ r = sfpkrd(f->file, (char*)buf, n, (rcrv&SF_RC) ? (int)f->getr : -1, -1L, (rcrv&SF_RV) ? 1 : 0); if(r > 0) { if(rcrv&SF_RV) f->mode |= SF_PKRD; else f->mode |= SF_RC; } } else r = read(f->file,buf,n); if(errno == 0 ) errno = oerrno; if(r > 0 ) { if(!(f->bits&SF_DCDOWN) ) /* not a continuation call */ { if(!(f->mode&SF_PKRD) ) { f->here += r; if(f->extent >= 0 && f->extent < f->here) f->extent = f->here; } if((uchar*)buf >= f->data && (uchar*)buf < f->data+f->size) f->endb = f->endr = ((uchar*)buf) + r; } SFMTXRETURN(f, (ssize_t)r); } do_except: if(local) SETLOCAL(f); switch(_sfexcept(f,SF_READ,(ssize_t)r,dc)) { case SF_ECONT : goto do_continue; case SF_EDONE : n = local ? 0 : (ssize_t)r; SFMTXRETURN(f,n); case SF_EDISC : if(!local && !(f->flags&SF_STRING)) goto do_continue; /* else fall thru */ case SF_ESTACK : SFMTXRETURN(f, -1); } do_continue: for(dc = f->disc; dc; dc = dc->disc) if(dc == disc) break; disc = dc; } } = ((uchar*)buf) + r; } SFMTXRETURN(f, (ssize_t)r); } do_except: if(local) SETLOCAL(f); switch(_sfexcept(f,SF_READ,(ssize_t)r,dc)) { case SF_ECONT : goto do_continue; case SF_EDONE : n = local ? 0 : (ssize_t)r; SFMTXRETURN(f,n); case SF_EDISC : if(!local && !(f->flags&SF_STRING)) goto do_continue; /* else fall thru src/lib/sfio/sfsk.c000644 151361 151361 00000003164 07432261526 014152 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Seek function that knows discipline ** ** Written by Kiem-Phong Vo. */ #if __STD_C Sfoff_t sfsk(reg Sfio_t* f, Sfoff_t addr, reg int type, Sfdisc_t* disc) #else Sfoff_t sfsk(f,addr,type,disc) reg Sfio_t* f; Sfoff_t addr; reg int type; Sfdisc_t* disc; #endif { Sfoff_t p; reg Sfdisc_t* dc; reg ssize_t s; reg int local, mode; SFMTXSTART(f, (Sfoff_t)(-1)); GETLOCAL(f,local); if(!local && !(f->bits&SF_DCDOWN)) { if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0) SFMTXRETURN(f, (Sfoff_t)(-1)); if(SFSYNC(f) < 0) SFMTXRETURN(f, (Sfoff_t)(-1)); #if MAP_TYPE if(f->mode == SF_READ && (f->bits&SF_MMAP) && f->data) { SFMUNMAP(f, f->data, f->endb-f->data); f->data = NIL(uchar*); } #endif f->next = f->endb = f->endr = f->endw = f->data; } if((type &= (SEEK_SET|SEEK_CUR|SEEK_END)) > SEEK_END) SFMTXRETURN(f, (Sfoff_t)(-1)); for(;;) { dc = disc; if(f->flags&SF_STRING) { SFSTRSIZE(f); if(type == SEEK_SET) s = (ssize_t)addr; else if(type == SEEK_CUR) s = (ssize_t)(addr + f->here); else s = (ssize_t)(addr + f->extent); } else { SFDISC(f,dc,seekf); if(dc && dc->seekf) { SFDCSK(f,addr,type,dc,p); } else { p = lseek(f->file,(sfoff_t)addr,type); } if(p >= 0) SFMTXRETURN(f,p); s = -1; } if(local) SETLOCAL(f); switch(_sfexcept(f,SF_SEEK,s,dc)) { case SF_EDISC: case SF_ECONT: if(f->flags&SF_STRING) SFMTXRETURN(f, (Sfoff_t)s); goto do_continue; default: SFMTXRETURN(f, (Sfoff_t)(-1)); } do_continue: for(dc = f->disc; dc; dc = dc->disc) if(dc == disc) break; disc = dc; } } f,dc,seekf); if(dc && dc->seekf) { SFDCSK(f,addr,type,dc,p); } else { p = lseek(f->file,(sfoff_t)addr,type); } if(p >= 0) SFMTXRETURN(f,p); s = -1; } if(local) SETLOCAL(f); switch(_sfexcept(f,SF_SEEK,s,dc)) { case SF_EDISC: case SF_ECONT: if(f->flags&SF_STRING) SFMTXRETURN(f, (Sfoff_t)s); goto do_continue; default: SFMTXRETURN(f, (Sfofsrc/lib/sfio/sfwr.c000644 151361 151361 00000011032 07432261527 014157 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Write with discipline. ** ** Written by Kiem-Phong Vo. */ /* hole preserving writes */ #if __STD_C static ssize_t sfoutput(Sfio_t* f, reg char* buf, reg size_t n) #else static ssize_t sfoutput(f,buf,n) Sfio_t* f; reg char* buf; reg size_t n; #endif { reg char *sp, *wbuf, *endbuf; reg ssize_t s, w, wr; s = w = 0; wbuf = buf; endbuf = buf+n; while(n > 0) { if((ssize_t)n < _Sfpage) /* no hole possible */ { buf += n; s = n = 0; } else while((ssize_t)n >= _Sfpage) { /* see if a hole of 0's starts here */ sp = buf+1; if(buf[0] == 0 && buf[_Sfpage-1] == 0) { /* check byte at a time until int-aligned */ while(((ulong)sp)%sizeof(int)) { if(*sp != 0) goto chk_hole; sp += 1; } /* check using int to speed up */ while(sp < endbuf) { if(*((int*)sp) != 0) goto chk_hole; sp += sizeof(int); } /* check the remaining bytes */ if(sp > endbuf) { sp -= sizeof(int); while(sp < endbuf) { if(*sp != 0) goto chk_hole; sp += 1; } } } chk_hole: if((s = sp-buf) >= _Sfpage) /* found a hole */ break; /* skip a dirty page */ n -= _Sfpage; buf += _Sfpage; } /* write out current dirty pages */ if(buf > wbuf) { if((ssize_t)n < _Sfpage) { buf = endbuf; n = s = 0; } if((wr = write(f->file,wbuf,buf-wbuf)) > 0) { w += wr; f->bits &= ~SF_HOLE; } if(wr != (buf-wbuf)) break; wbuf = buf; } /* seek to a rounded boundary within the hole */ if(s >= _Sfpage) { s = (s/_Sfpage)*_Sfpage; if(SFSK(f,(Sfoff_t)s,SEEK_CUR,NIL(Sfdisc_t*)) < 0) break; w += s; n -= s; wbuf = (buf += s); f->bits |= SF_HOLE; if(n > 0) { /* next page must be dirty */ s = (ssize_t)n <= _Sfpage ? 1 : _Sfpage; buf += s; n -= s; } } } return w > 0 ? w : -1; } #if __STD_C ssize_t sfwr(reg Sfio_t* f, reg const Void_t* buf, reg size_t n, reg Sfdisc_t* disc) #else ssize_t sfwr(f,buf,n,disc) reg Sfio_t* f; reg Void_t* buf; reg size_t n; reg Sfdisc_t* disc; #endif { reg ssize_t w; reg Sfdisc_t* dc; reg int local, oerrno; SFMTXSTART(f,(ssize_t)(-1)); GETLOCAL(f,local); if(!local && !(f->bits&SF_DCDOWN)) /* an external user's call */ { if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0 ) SFMTXRETURN(f, (ssize_t)(-1)); if(f->next > f->data && SFSYNC(f) < 0 ) SFMTXRETURN(f, (ssize_t)(-1)); } for(;;) { /* stream locked by sfsetfd() */ if(!(f->flags&SF_STRING) && f->file < 0) SFMTXRETURN(f,(ssize_t)0); /* clear current error states */ f->flags &= ~(SF_EOF|SF_ERROR); dc = disc; if(f->flags&SF_STRING) /* total required buffer */ w = n + (f->next - f->data); else { /* warn that a write is about to happen */ SFDISC(f,dc,writef); if(dc && dc->exceptf && (f->flags&SF_IOCHECK) ) { reg int rv; if(local) SETLOCAL(f); if((rv = _sfexcept(f,SF_WRITE,n,dc)) > 0) n = rv; else if(rv < 0) { f->flags |= SF_ERROR; SFMTXRETURN(f, rv); } } if(f->extent >= 0) { /* make sure we are at the right place to write */ if(f->flags&SF_APPENDWR) { if(f->here != f->extent || (f->flags&SF_SHARE)) { f->here = SFSK(f,(Sfoff_t)0,SEEK_END,dc); f->extent = f->here; } } else if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC)) f->here = SFSK(f,f->here,SEEK_SET,dc); } oerrno = errno; errno = 0; if(dc && dc->writef) { SFDCWR(f,buf,n,dc,w); } else if(SFISNULL(f)) w = n; else if(f->flags&SF_WHOLE) goto do_write; else if((ssize_t)n >= _Sfpage && !(f->flags&(SF_SHARE|SF_APPENDWR)) && f->here == f->extent && (f->here%_Sfpage) == 0) { if((w = sfoutput(f,(char*)buf,n)) <= 0) goto do_write; } else { do_write: if((w = write(f->file,(char*)buf,n)) > 0) f->bits &= ~SF_HOLE; } if(errno == 0) errno = oerrno; if(w > 0) { if(!(f->bits&SF_DCDOWN)) { if(f->flags&(SF_APPENDWR|SF_PUBLIC) ) f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,dc); else f->here += w; if(f->extent >= 0 && f->here > f->extent) f->extent = f->here; } SFMTXRETURN(f, (ssize_t)w); } } if(local) SETLOCAL(f); switch(_sfexcept(f,SF_WRITE,w,dc)) { case SF_ECONT : goto do_continue; case SF_EDONE : w = local ? 0 : w; SFMTXRETURN(f, (ssize_t)w); case SF_EDISC : if(!local && !(f->flags&SF_STRING)) goto do_continue; /* else fall thru */ case SF_ESTACK : SFMTXRETURN(f, (ssize_t)(-1)); } do_continue: for(dc = f->disc; dc; dc = dc->disc) if(dc == disc) break; disc = dc; } } f->extent = f->here; } SFMTXRETURN(f, (ssize_t)w); } } if(local) SETLOCAL(f); switch(_sfexcept(f,SF_WRITE,w,dc)) { case SF_ECONT : goto do_continue; case SF_EDONE : w = local ? 0 : w; SFMTXRETURN(f, (ssize_t)w); case SF_EDISC : if(!local && !(f->flags&SF_STRING)) goto do_continue; /* else fall thru */ case SF_ESTACK : SFMTXRETURN(f, (ssize_t)(-1)); } do_continue: for(dc = f->disc; dc; dc = dc->disc) if(dc == disc) src/lib/sfio/sfstack.c000644 151361 151361 00000003601 07432261526 014636 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Push/pop streams ** ** Written by Kiem-Phong Vo. */ #define STKMTXLOCK(f1,f2) \ { if(f1) SFMTXLOCK(f1); \ if(f2) SFMTXLOCK(f2); \ } #define STKMTXRETURN(f1,f2,rv) \ { if(f1) SFMTXUNLOCK(f1); \ if(f2) SFMTXUNLOCK(f2); \ return(rv); \ } #if __STD_C Sfio_t* sfstack(Sfio_t* f1, Sfio_t* f2) #else Sfio_t* sfstack(f1,f2) Sfio_t* f1; /* base of stack */ Sfio_t* f2; /* top of stack */ #endif { reg int n; reg Sfio_t* rf; reg Sfrsrv_t* rsrv; reg Void_t* mtx; STKMTXLOCK(f1,f2); if(f1 && (f1->mode&SF_RDWR) != f1->mode && _sfmode(f1,0,0) < 0) STKMTXRETURN(f1,f2, NIL(Sfio_t*)); if(f2 && (f2->mode&SF_RDWR) != f2->mode && _sfmode(f2,0,0) < 0) STKMTXRETURN(f1,f2, NIL(Sfio_t*)); if(!f1) STKMTXRETURN(f1,f2, f2); /* give access to other internal functions */ _Sfstack = sfstack; if(f2 == SF_POPSTACK) { if(!(f2 = f1->push)) STKMTXRETURN(f1,f2, NIL(Sfio_t*)); f2->mode &= ~SF_PUSH; } else { if(f2->push) STKMTXRETURN(f1,f2, NIL(Sfio_t*)); if(f1->pool && f1->pool != &_Sfpool && f1->pool != f2->pool && f1 == f1->pool->sf[0]) { /* get something else to pool front since f1 will be locked */ for(n = 1; n < f1->pool->n_sf; ++n) { if(SFFROZEN(f1->pool->sf[n]) ) continue; (*_Sfpmove)(f1->pool->sf[n],0); break; } } } if(f2->pool && f2->pool != &_Sfpool && f2 != f2->pool->sf[0]) (*_Sfpmove)(f2,0); /* swap streams */ sfswap(f1,f2); /* but the reserved buffer and mutex must remain the same */ rsrv = f1->rsrv; f1->rsrv = f2->rsrv; f2->rsrv = rsrv; mtx = f1->mutex; f1->mutex = f2->mutex; f2->mutex = mtx; SFLOCK(f1,0); SFLOCK(f2,0); if(f2->push != f2) { /* freeze the pushed stream */ f2->mode |= SF_PUSH; f1->push = f2; rf = f1; } else { /* unfreeze the just exposed stream */ f1->mode &= ~SF_PUSH; f2->push = NIL(Sfio_t*); rf = f2; } SFOPEN(f1,0); SFOPEN(f2,0); STKMTXRETURN(f1,f2, rf); } ms */ sfswap(f1,f2); /* but the reserved buffer and mutex must remain the same */ rsrv = f1->rsrv; f1->rsrv = f2->rsrv; f2-src/lib/sfio/sfresize.c000644 151361 151361 00000002076 07432261525 015036 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Resize a stream. Written by Kiem-Phong Vo. */ #if __STD_C int sfresize(Sfio_t* f, Sfoff_t size) #else int sfresize(f, size) Sfio_t* f; Sfoff_t size; #endif { SFMTXSTART(f, -1); if(size < 0 || f->extent < 0 || (f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0) ) SFMTXRETURN(f, -1); SFLOCK(f,0); if(f->flags&SF_STRING) { SFSTRSIZE(f); if(f->extent >= size) { if((f->flags&SF_MALLOC) && (f->next - f->data) <= size) { size_t s = (((size_t)size + 1023)/1024)*1024; Void_t* d; if(s < f->size && (d = realloc(f->data, s)) ) { f->data = d; f->size = s; f->extent = s; } } memclear((char*)(f->data+size), (int)(f->extent-size)); } else { if(SFSK(f, size, SEEK_SET, f->disc) != size) SFMTXRETURN(f, -1); memclear((char*)(f->data+f->extent), (int)(size-f->extent)); } } else { if(f->next > f->data) SFSYNC(f); #if _lib_ftruncate if(ftruncate(f->file, (sfoff_t)size) < 0) SFMTXRETURN(f, -1); #else SFMTXRETURN(f, -1); #endif } f->extent = size; SFOPEN(f, 0); SFMTXRETURN(f, 0); } ) { f->data = d; f->size = s; f->extent = s; } } memclear((char*)(f->data+size), (int)(f->extent-size)); } else { if(SFSK(f, size, SEEK_SET, f->disc) != size) SFMTXRETURN(f, -1); memclear((char*)(f->data+f->extent), (int)(size-f->extent)); } } else { if(f->next > f->data) SFSYNC(f); #if _lib_ftruncate if(ftruncate(f->file, (sfoff_t)size) < 0) SFMTXRETURN(f, -1); #else SFMTXRETURN(f, -1); #endif src/lib/sfio/sfnotify.c000644 151361 151361 00000000417 07432261524 015041 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Set the function to be called when a stream is opened or closed ** ** Written by Kiem-Phong Vo. */ #if __STD_C int sfnotify(void (*notify)(Sfio_t*, int, int)) #else int sfnotify(notify) void (*notify)(); #endif { _Sfnotify = notify; return 0; } 1); memclear((char*)(f->data+f->extent), (int)(size-f->extent)); } } else { if(f->next > f->data) SFSYNC(f); #if _lib_ftruncate if(f36A V=PAx<|Tg)<|Tg)@src/lib/sfio/sfswap.c000644 151361 151361 00000004254 07432261526 014510 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Swap two streams. If the second argument is NULL, ** a new stream will be created. Always return the second argument ** or the new stream. Note that this function will always work ** unless streams are locked by SF_PUSH. ** ** Written by Kiem-Phong Vo. */ #if __STD_C Sfio_t* sfswap(reg Sfio_t* f1, reg Sfio_t* f2) #else Sfio_t* sfswap(f1,f2) reg Sfio_t* f1; reg Sfio_t* f2; #endif { Sfio_t tmp; int f1pool, f2pool, f1mode, f2mode, f1flags, f2flags; if(!f1 || (f1->mode&SF_AVAIL) || (SFFROZEN(f1) && (f1->mode&SF_PUSH)) ) return NIL(Sfio_t*); if(f2 && SFFROZEN(f2) && (f2->mode&SF_PUSH) ) return NIL(Sfio_t*); if(f1 == f2) return f2; f1mode = f1->mode; SFLOCK(f1,0); f1->mode |= SF_PUSH; /* make sure there is no recursion on f1 */ if(f2) { f2mode = f2->mode; SFLOCK(f2,0); f2->mode |= SF_PUSH; /* make sure there is no recursion on f2 */ } else { f2 = f1->file == 0 ? sfstdin : f1->file == 1 ? sfstdout : f1->file == 2 ? sfstderr : NIL(Sfio_t*); if((!f2 || !(f2->mode&SF_AVAIL)) ) { if(!(f2 = (Sfio_t*)malloc(sizeof(Sfio_t))) ) { f1->mode = f1mode; SFOPEN(f1,0); return NIL(Sfio_t*); } SFCLEAR(f2,NIL(Vtmutex_t*)); } f2->mode = SF_AVAIL|SF_LOCK; f2mode = SF_AVAIL; } if(!f1->pool) f1pool = -1; else for(f1pool = f1->pool->n_sf-1; f1pool >= 0; --f1pool) if(f1->pool->sf[f1pool] == f1) break; if(!f2->pool) f2pool = -1; else for(f2pool = f2->pool->n_sf-1; f2pool >= 0; --f2pool) if(f2->pool->sf[f2pool] == f2) break; f1flags = f1->flags; f2flags = f2->flags; /* swap image and pool entries */ memcpy((Void_t*)(&tmp),(Void_t*)f1,sizeof(Sfio_t)); memcpy((Void_t*)f1,(Void_t*)f2,sizeof(Sfio_t)); memcpy((Void_t*)f2,(Void_t*)(&tmp),sizeof(Sfio_t)); if(f2pool >= 0) f1->pool->sf[f2pool] = f1; if(f1pool >= 0) f2->pool->sf[f1pool] = f2; if(f2flags&SF_STATIC) f2->flags |= SF_STATIC; else f2->flags &= ~SF_STATIC; if(f1flags&SF_STATIC) f1->flags |= SF_STATIC; else f1->flags &= ~SF_STATIC; if(f2mode&SF_AVAIL) /* swapping to a closed stream */ { if(!(f1->flags&SF_STATIC) ) free(f1); } else { f1->mode = f2mode; SFOPEN(f1,0); } f2->mode = f1mode; SFOPEN(f2,0); return f2; } t)); memcpy((Void_t*)f2,(Void_t*)(&tmp),sizeof(Sfio_t)); if(f2pool >= 0) f1->pool->sf[f2pool] = f1; if(f1pool >= 0) f2->pool->sf[f1pool] = f2; if(f2flags&SF_STATIC) f2->flags |= SF_STATIC; else f2->flags &= ~SF_STATIC; if(f1flags&SF_STATIC) f1->flags |= SF_STATIC; else f1->flags &= ~SF_STATIC; if(f2mode&SF_AVAIL) /* swasrc/lib/sfio/sfpopen.c000644 151361 151361 00000013202 07432261524 014646 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Create a coprocess. ** Written by Kiem-Phong Vo. */ #if _PACKAGE_ast #include #else #define EXIT_NOTFOUND 127 #define READ 0 #define WRITE 1 #ifndef CHAR_BIT #define CHAR_BIT 8 #endif static char Meta[1<= cmd; --s) if(*s == '/') break; argv[0] = s+1; /* Non-standard pathnames as in nDFS should be handled by the shell */ for(s = cmd+strlen(cmd)-1; s >= cmd+2; --s) if(s[0] == '.' && s[-1] == '.' && s[-2] == '.') goto do_interp; if(cmd[0] == '/' || (cmd[0] == '.' && cmd[1] == '/') || (cmd[0] == '.' && cmd[1] == '.' && cmd[2] == '/') ) { if(access(cmd,X_OK) != 0) goto do_interp; else execv(cmd,argv); } else { for(p = Path; *p; ++p) { s = sfprints("%s/%s", *p, cmd); if(access(s,X_OK) == 0) execv(s,argv); } } /* if get here, let the interpreter do it */ do_interp: for(s = interp+strlen(interp)-1; s >= interp; --s) if(*s == '/') break; execl(interp, s+1, "-c", argcmd, NIL(char*)); _exit(EXIT_NOTFOUND); } #endif /*_PACKAGE_ast*/ #if __STD_C Sfio_t* sfpopen(Sfio_t* f, const char* command, const char* mode) #else Sfio_t* sfpopen(f,command,mode) Sfio_t* f; char* command; /* command to execute */ char* mode; /* mode of the stream */ #endif { #if _PACKAGE_ast reg Proc_t* proc; reg int sflags; reg long flags; reg int bits; char* av[4]; if (!command || !command[0] || !(sflags = _sftype(mode, NiL, NiL))) return 0; if(f == (Sfio_t*)(-1)) { /* stdio compatibility mode */ f = NIL(Sfio_t*); bits = SF_STDIO; } else bits = 0; flags = 0; if (sflags & SF_READ) flags |= PROC_READ; if (sflags & SF_WRITE) flags |= PROC_WRITE; av[0] = "sh"; av[1] = "-c"; av[2] = (char*)command; av[3] = 0; if (!(proc = procopen(0, av, 0, 0, flags))) return 0; if (!(f = sfnew(f, NIL(Void_t*), (size_t)SF_UNBOUND, (sflags&SF_READ) ? proc->rfd : proc->wfd, sflags)) || ((f->bits |= bits), _sfpopen(f, (sflags&SF_READ) ? proc->wfd : -1, proc->pid)) < 0) { if (f) sfclose(f); procclose(proc); return 0; } procfree(proc); return f; #else reg int pid, fd, pkeep, ckeep, sflags; int stdio, parent[2], child[2]; Sfio_t sf; /* set shell meta characters */ if(Meta[0] == 0) { reg char* s; Meta[0] = 1; for(s = "!@#$%&*(){}[]:;<>~`'|\"\\"; *s; ++s) Meta[(uchar)s[0]] = 1; } if(!Path) Path = _sfgetpath("PATH"); /* sanity check */ if(!command || !command[0] || !(sflags = _sftype(mode,NIL(int*),NIL(int*)))) return NIL(Sfio_t*); /* make pipes */ parent[0] = parent[1] = child[0] = child[1] = -1; if(pipe(parent) < 0) goto error; if((sflags&SF_RDWR) == SF_RDWR && pipe(child) < 0) goto error; switch((pid = fork()) ) { default : /* in parent process */ if(sflags&SF_READ) { pkeep = READ; ckeep = WRITE; } else { pkeep = WRITE; ckeep = READ; } if(f == (Sfio_t*)(-1)) { /* stdio compatibility mode */ f = NIL(Sfio_t*); stdio = 1; } else stdio = 0; /* make the streams */ if(!(f = sfnew(f,NIL(Void_t*),(size_t)SF_UNBOUND,parent[pkeep],sflags))) goto error; CLOSE(parent[!pkeep]); SETCLOEXEC(parent[pkeep]); if((sflags&SF_RDWR) == SF_RDWR) { CLOSE(child[!ckeep]); SETCLOEXEC(child[ckeep]); } /* save process info */ fd = (sflags&SF_RDWR) == SF_RDWR ? child[ckeep] : -1; if(_sfpopen(f,fd,pid,stdio) < 0) { (void)sfclose(f); goto error; } return f; case 0 : /* in child process */ /* determine what to keep */ if(sflags&SF_READ) { pkeep = WRITE; ckeep = READ; } else { pkeep = READ; ckeep = WRITE; } /* zap fd that we don't need */ CLOSE(parent[!pkeep]); if((sflags&SF_RDWR) == SF_RDWR) CLOSE(child[!ckeep]); /* use sfsetfd to make these descriptors the std-ones */ SFCLEAR(&sf,NIL(Vtmutex_t*)); /* must be careful so not to close something useful */ if((sflags&SF_RDWR) == SF_RDWR && pkeep == child[ckeep]) if((child[ckeep] = dup(pkeep)) < 0) _exit(EXIT_NOTFOUND); if(parent[pkeep] != pkeep) { sf.file = parent[pkeep]; CLOSE(pkeep); if(sfsetfd(&sf,pkeep) != pkeep) _exit(EXIT_NOTFOUND); } if((sflags&SF_RDWR) == SF_RDWR && child[ckeep] != ckeep) { sf.file = child[ckeep]; CLOSE(ckeep); if(sfsetfd(&sf,ckeep) != ckeep) _exit(EXIT_NOTFOUND); } execute(command); return NIL(Sfio_t*); case -1 : /* error */ error: if(parent[0] >= 0) { CLOSE(parent[0]); CLOSE(parent[1]); } if(child[0] >= 0) { CLOSE(child[0]); CLOSE(child[1]); } return NIL(Sfio_t*); } #endif /*_PACKAGE_ast*/ } keep]; CLOSE(pkeep); if(sfsetfd(&sf,pkeep) != pkeep) _exit(EXIT_NOTFOUND); } if((sflags&SF_RDWR) == SF_RDWR && child[ckeep] != ckeep) { sf.file = child[ckeep]; CLOSE(ckeep); if(sfsetfd(&sf,ckeep) != ckeep) _exit(EXIT_NOTFOUND); } execute(command); return NIL(Sfio_t*); case -1 : /* error */ error: if(parent[0] >= 0) { CLOSE(parent[0]); CLOsrc/lib/sfio/sfhdr.h000644 151361 151361 00000074112 07446222306 014316 0ustar00kpvkpv000000 000000 #ifndef _SFHDR_H #define _SFHDR_H 1 #if !defined(_BLD_sfio) && !defined(_BLD_stdio) #define _BLD_sfio 1 #endif /* Internal definitions for sfio. ** Written by Kiem-Phong Vo */ /* map members to the library implementation form */ #define _next next #define _endw endw #define _endr endr #define _endb endb #define _push push #define _flags flags #define _file file #define _data data #define _size size #define _val val #include "FEATURE/sfio" #if _hdr_stdarg #include #else #include #endif #include "FEATURE/common" #include "FEATURE/float" #include "sfio_t.h" /* note that the macro vt_threaded has effect on vthread.h */ #include /* file system info */ #if _PACKAGE_ast #include #include #include #include /* ast always provides multibyte handling */ #undef _hdr_wchar #undef _lib_mbrtowc #undef _lib_wcrtomb #define _hdr_wchar 1 #define _lib_mbrtowc 1 #define _lib_wcrtomb 1 #if _mem_st_blksize_stat #define _stat_blksize 1 #endif #if _lib_localeconv && _hdr_locale #define _lib_locale 1 #endif #else /*!_PACKAGE_ast*/ /* these guys don't know large files */ #if (__hppa || __mips == 2) && !defined(NO_LARGEFILE64_SOURCE) #define NO_LARGEFILE64_SOURCE 1 #undef _LARGEFILE64_SOURCE #endif #if !defined(_NO_LARGEFILE64_SOURCE) && _typ_off64_t && _lib_lseek64 && _lib_stat64 #if !defined(_LARGEFILE64_SOURCE) #define _LARGEFILE64_SOURCE 1 /* enabling the *64 stuff */ #endif #endif /* when building the binary compatibility package, a number of header files are not needed and they may get in the way so we remove them here. */ #if _SFBINARY_H #undef _hdr_time #undef _sys_time #undef _sys_stat #undef _hdr_stat #undef _hdr_filio #undef _sys_filio #undef _lib_poll #undef _stream_peek #undef _socket_peek #undef _hdr_vfork #undef _sys_vfork #undef _lib_vfork #undef _hdr_values #undef _hdr_math #undef _sys_mman #undef _hdr_mman #undef _sys_ioctl #endif #if _hdr_stdlib #include #endif #if _hdr_string #include #endif #if _hdr_time #include #endif #if _sys_time #include #endif #if _sys_stat #include #else #if _hdr_stat #include #ifndef _sys_stat #define _sys_stat 1 #endif #endif #endif /*_sys_stat*/ #ifndef _sys_stat #define _sys_stat 0 #endif #include #ifndef F_SETFD #ifndef FIOCLEX #if _hdr_filio #include #else #if _sys_filio #include #endif /*_sys_filio*/ #endif /*_hdr_filio*/ #endif /*_FIOCLEX*/ #endif /*F_SETFD*/ #if _hdr_unistd #include #endif #if !_LARGEFILE64_SOURCE /* turn off the *64 stuff */ #undef _typ_off64_t #undef _typ_struct_stat64 #undef _lib_creat64 #undef _lib_open64 #undef _lib_close64 #undef _lib_stat64 #undef _lib_fstat64 #undef _lib_ftruncate64 #undef _lib_lseek64 #undef _lib_mmap64 #undef _lib_munmap64 #endif /*!_LARGEFILE64_SOURCE */ /* see if we can use memory mapping for io */ #if _LARGEFILE64_SOURCE && !_lib_mmap64 #undef _mmap_worthy #endif #if !_mmap_worthy #undef _hdr_mman #undef _sys_mman #endif #if _hdr_man #include #endif #if _sys_mman #include #endif #if _typ_off64_t #define sfoff_t off64_t #else #define sfoff_t off_t #endif #if _typ_struct_stat64 #define sfstat_t struct stat64 #else #define sfstat_t struct stat #endif #if _lib_lseek64 #define lseek lseek64 #endif #if _lib_stat64 #define stat stat64 #endif #if _lib_fstat64 #define fstat fstat64 #endif #if _lib_mmap64 #define mmap mmap64 #endif #if _lib_munmap64 #define munmap munmap64 #endif #if _lib_open64 #define open open64 #endif #if _lib_creat64 #define creat creat64 #endif #if _lib_close64 #define close close64 #endif #if _lib_ftruncate64 #define ftruncate ftruncate64 #endif #endif /*_PACKAGE_ast*/ #include #include /* deal with multi-byte character and string conversions */ #if _hdr_wchar && _typ_mbstate_t && _lib_wcrtomb && _lib_mbrtowc #define _has_multibyte 1 /* Xopen-compliant */ #include #ifndef MB_CUR_MAX #define MB_CUR_MAX sizeof(Sflong_t) #endif #define SFMBCPY(to,fr) memcpy((to), (fr), sizeof(mbstate_t)) #define SFMBCLR(mb) memset((mb), 0, sizeof(mbstate_t)) #define SFMBSET(lhs,v) (lhs = (v)) #define SFMBLEN(s,mb) mbrtowc(0, (s), MB_CUR_MAX, (mb) ) #define SFMBDCL(mb) mbstate_t mb; #endif /*_hdr_wchar && _typ_mbstate_t && _lib_wcrtomb && _lib_mbrtowc*/ #if !_has_multibyte && _hdr_wchar && _lib_mbtowc && _lib_wctomb #define _has_multibyte 2 /* no shift states */ #include #ifndef MB_CUR_MAX #define MB_CUR_MAX sizeof(Sflong_t) #endif #undef mbrtowc #define mbrtowc(wp,s,n,mb) mbtowc(wp, s, n) #undef wcrtomb #define wcrtomb(s,wc,mb) wctomb(s, wc) #define SFMBCPY(to,fr) #define SFMBCLR(mb) #define SFMBSET(lhs,v) #define SFMBLEN(s,mb) mbrtowc(0, (s), MB_CUR_MAX, (mb) ) #define SFMBDCL(mb) #endif /*!_has_multibyte && _hdr_wchar && _lib_mbtowc && _lib_wctomb*/ #if !_has_multibyte #define _has_multibyte 0 /* no multibyte support */ #define SFMBCPY(to,fr) #define SFMBCLR(mb) #define SFMBSET(lhs,v) #define SFMBLEN(s,mb) (*(s) ? 1 : 0) #define SFMBDCL(mb) #endif /* _has_multibyte */ #if vt_threaded /* initialization */ #define SFONCE() (_Sfdone ? 0 : vtonce(_Sfonce,_Sfoncef)) /* to lock/unlock a stream on entering and returning from some function */ #define SFMTXLOCK(f) (((f)->flags&SF_MTSAFE) ? sfmutex(f,SFMTX_LOCK) : 0) #define SFMTXUNLOCK(f) (((f)->flags&SF_MTSAFE) ? sfmutex(f,SFMTX_UNLOCK) : 0) #define SFMTXSTART(f,v) { if(!f || SFMTXLOCK(f) != 0) return(v); } #define SFMTXRETURN(f,v) { SFMTXUNLOCK(f); return(v); } /* start and end critical region for a pool */ #define POOLMTXLOCK(p) ( vtmtxlock(&(p)->mutex) ) #define POOLMTXUNLOCK(p) ( vtmtxunlock(&(p)->mutex) ) #define POOLMTXSTART(p) { POOLMTXLOCK(p); } #define POOLMTXRETURN(p,v) { POOLMTXUNLOCK(p); return(v); } #else /*!vt_threaded*/ #undef SF_MTSAFE /* no need to worry about thread-safety */ #define SF_MTSAFE 0 #define SFONCE() (0) #define SFMTXLOCK(f) (0) #define SFMTXUNLOCK(f) (0) #define SFMTXSTART(f,v) { if(!f) return(v); } #define SFMTXRETURN(f,v) { return(v); } #define POOLMTXLOCK(p) #define POOLMTXUNLOCK(p) #define POOLMTXSTART(p) #define POOLMTXRETURN(p,v) { return(v); } #endif /*vt_threaded*/ /* functions for polling readiness of streams */ #if _lib_select #undef _lib_poll #else #if _lib_poll_fd_1 || _lib_poll_fd_2 #define _lib_poll 1 #endif #endif /*_lib_select_*/ #if _lib_poll #include #if _lib_poll_fd_1 #define SFPOLL(pfd,n,tm) poll((pfd),(ulong)(n),(tm)) #else #define SFPOLL(pfd,n,tm) poll((ulong)(n),(pfd),(tm)) #endif #endif /*_lib_poll*/ #if _stream_peek #include #endif #if _socket_peek #include #endif /* to test for executable access mode of a file */ #ifndef X_OK #define X_OK 01 #endif /* alternative process forking */ #if _lib_vfork && !defined(fork) && !defined(sparc) && !defined(__sparc) #if _hdr_vfork #include #endif #if _sys_vfork #include #endif #define fork vfork #endif #if _lib_unlink #define remove unlink #endif /* to get rid of pesky compiler warnings */ #if __STD_C #define NOTUSED(x) (void)(x) #else #define NOTUSED(x) (&x,1) #endif /* Private flags in the "bits" field */ #define SF_MMAP 00000001 /* in memory mapping mode */ #define SF_BOTH 00000002 /* both read/write */ #define SF_HOLE 00000004 /* a hole of zero's was created */ #define SF_NULL 00000010 /* stream is /dev/null */ #define SF_SEQUENTIAL 00000020 /* sequential access */ #define SF_JUSTSEEK 00000040 /* just did a sfseek */ #define SF_PRIVATE 00000100 /* private stream to Sfio, no mutex */ #define SF_ENDING 00000200 /* no re-io on interrupts at closing */ #define SF_WIDE 00000400 /* in wide mode - stdio only */ /* "bits" flags that must be cleared in sfclrlock */ #define SF_TMPBITS 00170000 #define SF_DCDOWN 00010000 /* recurse down the discipline stack */ #define SF_WCFORMAT 00020000 /* wchar_t formatting - stdio only */ #if _has_multibyte #define SFWCSET(f) ((f)->bits |= SF_WCFORMAT) #define SFWCGET(f,v) (((v) = (f)->bits & SF_WCFORMAT), ((f)->bits &= ~SF_WCFORMAT) ) #else #define SFWCSET(f) #define SFWCGET(f,v) #endif #define SF_MVSIZE 00040000 /* f->size was reset in sfmove() */ #define SFMVSET(f) (((f)->size *= SF_NMAP), ((f)->bits |= SF_MVSIZE) ) #define SFMVUNSET(f) (!((f)->bits&SF_MVSIZE) ? 0 : \ (((f)->bits &= ~SF_MVSIZE), ((f)->size /= SF_NMAP)) ) #define SFCLRBITS(f) (SFMVUNSET(f), ((f)->bits &= ~SF_TMPBITS) ) /* bits for the mode field, SF_INIT defined in sfio_t.h */ #define SF_RC 00000010 /* peeking for a record */ #define SF_RV 00000020 /* reserve without read or most write */ #define SF_LOCK 00000040 /* stream is locked for io op */ #define SF_PUSH 00000100 /* stream has been pushed */ #define SF_POOL 00000200 /* stream is in a pool but not current */ #define SF_PEEK 00000400 /* there is a pending peek */ #define SF_PKRD 00001000 /* did a peek read */ #define SF_GETR 00002000 /* did a getr on this stream */ #define SF_SYNCED 00004000 /* stream was synced */ #define SF_STDIO 00010000 /* given up the buffer to stdio */ #define SF_AVAIL 00020000 /* was closed, available for reuse */ #define SF_LOCAL 00100000 /* sentinel for a local call */ #ifdef DEBUG #define ASSERT(p) ((p) ? 0 : (abort(),0) ) #else #define ASSERT(p) #endif /* short-hands */ #define NIL(t) ((t)0) #define reg register #ifndef uchar #define uchar unsigned char #endif #ifndef ulong #define ulong unsigned long #endif #ifndef uint #define uint unsigned int #endif #ifndef ushort #define ushort unsigned short #endif #define SECOND 1000 /* millisecond units */ /* macros do determine stream types from sfstat_t data */ #ifndef S_IFMT #define S_IFMT 0 #endif #ifndef S_IFDIR #define S_IFDIR 0 #endif #ifndef S_IFREG #define S_IFREG 0 #endif #ifndef S_IFCHR #define S_IFCHR 0 #endif #ifndef S_IFIFO #define S_IFIFO 0 #endif #ifndef S_ISDIR #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) #endif #ifndef S_ISREG #define S_ISREG(m) (((m)&S_IFMT) == S_IFREG) #endif #ifndef S_ISCHR #define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR) #endif #ifndef S_ISFIFO # ifdef S_IFIFO # define S_ISFIFO(m) (((m)&S_IFIFO) == S_IFIFO) # else # define S_ISFIFO(m) (0) # endif #endif #ifdef S_IRUSR #define SF_CREATMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) #else #define SF_CREATMODE 0666 #endif /* set close-on-exec */ #ifdef F_SETFD # ifndef FD_CLOEXEC # define FD_CLOEXEC 1 # endif /*FD_CLOEXEC*/ # define SETCLOEXEC(fd) ((void)fcntl((fd),F_SETFD,FD_CLOEXEC)) #else # ifdef FIOCLEX # define SETCLOEXEC(fd) ((void)ioctl((fd),FIOCLEX,0)) # else # define SETCLOEXEC(fd) # endif /*FIOCLEX*/ #endif /*F_SETFD*/ /* a couple of error number that we use, default values are like Linux */ #ifndef EINTR #define EINTR 4 #endif #ifndef EBADF #define EBADF 9 #endif #ifndef EAGAIN #define EAGAIN 11 #endif #ifndef ENOMEM #define ENOMEM 12 #endif #ifndef EINVAL #define EINVAL 22 #endif #ifndef ESPIPE #define ESPIPE 29 #endif /* function to get the decimal point for local environment */ #if !defined(SFSETLOCALE) && _PACKAGE_ast #include "lclib.h" #define SFSETLOCALE(dp,tp) \ do if (*(dp) == 0) { \ Lc_numeric_t* lv = (Lc_numeric_t*)LCINFO(AST_LC_NUMERIC)->data; \ *(dp) = lv->decimal; \ *(tp) = lv->thousand; \ } while (0) #endif /*!defined(SFSETLOCALE) && _PACKAGE_ast*/ #if !defined(SFSETLOCALE) && _lib_locale #include #define SFSETLOCALE(decimal,thousand) \ do { struct lconv* lv; \ if(*(decimal) == 0) \ { *(decimal) = '.'; \ *(thousand) = 0; \ if((lv = localeconv())) \ { if(lv->decimal_point && lv->decimal_point[0]) \ *(decimal) = lv->decimal_point[0]; \ if(thousand && lv->thousands_sep && lv->thousands_sep[0]) \ *(thousand) = lv->thousands_sep[0]; \ } \ } \ } while (0) #endif /*!defined(SFSETLOCALE) && _lib_locale*/ #if !defined(SFSETLOCALE) #define SFSETLOCALE(decimal,thousand) (*(decimal)='.') #endif /* stream pool structure. */ typedef struct _sfpool_s Sfpool_t; struct _sfpool_s { Sfpool_t* next; int mode; /* type of pool */ int s_sf; /* size of pool array */ int n_sf; /* number currently in pool */ Sfio_t** sf; /* array of streams */ Sfio_t* array[3]; /* start with 3 */ Vtmutex_t mutex; /* mutex lock object */ }; /* reserve buffer structure */ typedef struct _sfrsrv_s Sfrsrv_t; struct _sfrsrv_s { ssize_t slen; /* last string length */ ssize_t size; /* buffer size */ uchar data[1]; /* data buffer */ }; /* co-process structure */ typedef struct _sfproc_s Sfproc_t; struct _sfproc_s { int pid; /* process id */ uchar* rdata; /* read data being cached */ int ndata; /* size of cached data */ int size; /* buffer size */ int file; /* saved file descriptor */ int sigp; /* sigpipe protection needed */ }; /* extensions to sfvprintf/sfvscanf */ #define FP_SET(fp,fn) (fp < 0 ? (fn += 1) : (fn = fp) ) #define FP_WIDTH 0 #define FP_PRECIS 1 #define FP_BASE 2 #define FP_STR 3 #define FP_SIZE 4 #define FP_INDEX 5 /* index size */ typedef struct _fmt_s Fmt_t; typedef struct _fmtpos_s Fmtpos_t; typedef union { int i, *ip; long l, *lp; short h, *hp; uint ui; ulong ul; ushort uh; Sflong_t ll, *llp; Sfulong_t lu; Sfdouble_t ld; double d; float f; #if _has_multibyte wchar_t wc; wchar_t *ws, **wsp; #endif char c, *s, **sp; uchar uc, *us, **usp; Void_t *vp; Sffmt_t *ft; } Argv_t; struct _fmt_s { char* form; /* format string */ va_list args; /* corresponding arglist */ SFMBDCL(mbs) /* multibyte parsing state */ char* oform; /* original format string */ va_list oargs; /* original arg list */ int argn; /* number of args already used */ Fmtpos_t* fp; /* position list */ Sffmt_t* ft; /* formatting environment */ Sffmtevent_f eventf; /* event function */ Fmt_t* next; /* stack frame pointer */ }; struct _fmtpos_s { Sffmt_t ft; /* environment */ Argv_t argv; /* argument value */ int fmt; /* original format */ int need[FP_INDEX]; /* positions depending on */ }; #define LEFTP '(' #define RIGHTP ')' #define QUOTE '\'' #ifndef CHAR_BIT #define CHAR_BIT 8 #endif #define FMTSET(ft, frm,ags, fv, sz, flgs, wid,pr,bs, ts,ns) \ ((ft->form = (char*)frm), va_copy(ft->args,ags), \ (ft->fmt = fv), (ft->size = sz), \ (ft->flags = (flgs&SFFMT_SET)), \ (ft->width = wid), (ft->precis = pr), (ft->base = bs), \ (ft->t_str = ts), (ft->n_str = ns) ) #define FMTGET(ft, frm,ags, fv, sz, flgs, wid,pr,bs) \ ((frm = ft->form), va_copy(ags,ft->args), \ (fv = ft->fmt), (sz = ft->size), \ (flgs = (flgs&~(SFFMT_SET))|(ft->flags&SFFMT_SET)), \ (wid = ft->width), (pr = ft->precis), (bs = ft->base) ) /* format flags&types, must coexist with those in sfio.h */ #define SFFMT_FORBIDDEN 000077777777 /* for sfio.h only */ #define SFFMT_EFORMAT 001000000000 /* sfcvt converting %e */ #define SFFMT_MINUS 002000000000 /* minus sign */ #define SFFMT_AFORMAT 004000000000 /* sfcvt converting %a */ #define SFFMT_UPPER 010000000000 /* sfcvt converting upper */ #define SFFMT_TYPES (SFFMT_SHORT|SFFMT_SSHORT | SFFMT_LONG|SFFMT_LLONG|\ SFFMT_LDOUBLE | SFFMT_IFLAG|SFFMT_JFLAG| \ SFFMT_TFLAG | SFFMT_ZFLAG ) /* type of elements to be converted */ #define SFFMT_INT 001 /* %d,%i */ #define SFFMT_UINT 002 /* %u,o,x etc. */ #define SFFMT_FLOAT 004 /* %f,e,g etc. */ #define SFFMT_CHAR 010 /* %c,C */ #define SFFMT_POINTER 020 /* %p,n,s,S */ #define SFFMT_CLASS 040 /* %[ */ /* local variables used across sf-functions */ #define _Sfpage (_Sfextern.sf_page) #define _Sfpool (_Sfextern.sf_pool) #define _Sfpmove (_Sfextern.sf_pmove) #define _Sfstack (_Sfextern.sf_stack) #define _Sfnotify (_Sfextern.sf_notify) #define _Sfstdsync (_Sfextern.sf_stdsync) #define _Sfudisc (&(_Sfextern.sf_udisc)) #define _Sfcleanup (_Sfextern.sf_cleanup) #define _Sfexiting (_Sfextern.sf_exiting) #define _Sfdone (_Sfextern.sf_done) #define _Sfonce (_Sfextern.sf_once) #define _Sfoncef (_Sfextern.sf_oncef) #define _Sfmutex (_Sfextern.sf_mutex) typedef struct _sfextern_s { ssize_t sf_page; struct _sfpool_s sf_pool; int (*sf_pmove)_ARG_((Sfio_t*, int)); Sfio_t* (*sf_stack)_ARG_((Sfio_t*, Sfio_t*)); void (*sf_notify)_ARG_((Sfio_t*, int, int)); int (*sf_stdsync)_ARG_((Sfio_t*)); struct _sfdisc_s sf_udisc; void (*sf_cleanup)_ARG_((void)); int sf_exiting; int sf_done; Vtonce_t* sf_once; void (*sf_oncef)_ARG_((void)); Vtmutex_t* sf_mutex; } Sfextern_t; /* get the real value of a byte in a coded long or ulong */ #define SFUVALUE(v) (((ulong)(v))&(SF_MORE-1)) #define SFSVALUE(v) ((( long)(v))&(SF_SIGN-1)) #define SFBVALUE(v) (((ulong)(v))&(SF_BYTE-1)) /* pick this many bits in each iteration of double encoding */ #define SF_PRECIS 7 /* grain size for buffer increment */ #define SF_GRAIN 1024 #define SF_PAGE ((ssize_t)(SF_GRAIN*sizeof(int)*2)) /* when the buffer is empty, certain io requests may be better done directly on the given application buffers. The below condition determines when. */ #define SFDIRECT(f,n) (((ssize_t)(n) >= (f)->size) || \ ((n) >= SF_GRAIN && (ssize_t)(n) >= (f)->size/16 ) ) /* number of pages to memory map at a time */ #define SF_NMAP 8 /* set/unset sequential states for mmap */ #if _lib_madvise && defined(MADV_SEQUENTIAL) && defined(MADV_NORMAL) #define SFMMSEQON(f,a,s) \ do { int oerrno = errno; \ (void)madvise((caddr_t)(a),(size_t)(s),MADV_SEQUENTIAL); \ errno = oerrno; \ } while(0) #define SFMMSEQOFF(f,a,s) \ do { int oerrno = errno; \ (void)madvise((caddr_t)(a),(size_t)(s),MADV_NORMAL); \ errno = oerrno; \ } while(0) #else #define SFMMSEQON(f,a,s) #define SFMMSEQOFF(f,a,s) #endif #define SFMUNMAP(f,a,s) (munmap((caddr_t)(a),(size_t)(s)), \ ((f)->endb = (f)->endr = (f)->endw = (f)->next = \ (f)->data = NIL(uchar*)) ) #ifndef MAP_VARIABLE #define MAP_VARIABLE 0 #endif #ifndef _mmap_fixed #define _mmap_fixed 0 #endif /* the bottomless bit bucket */ #define DEVNULL "/dev/null" #define SFSETNULL(f) ((f)->extent = (Sfoff_t)(-1), (f)->bits |= SF_NULL) #define SFISNULL(f) ((f)->extent < 0 && ((f)->bits&SF_NULL) ) #define SFKILL(f) ((f)->mode = (SF_AVAIL|SF_LOCK) ) #define SFKILLED(f) (((f)->mode&(SF_AVAIL|SF_LOCK)) == (SF_AVAIL|SF_LOCK) ) /* exception types */ #define SF_EDONE 0 /* stop this operation and return */ #define SF_EDISC 1 /* discipline says it's ok */ #define SF_ESTACK 2 /* stack was popped */ #define SF_ECONT 3 /* can continue normally */ #define SETLOCAL(f) ((f)->mode |= SF_LOCAL) #define GETLOCAL(f,v) ((v) = ((f)->mode&SF_LOCAL), (f)->mode &= ~SF_LOCAL, (v)) #define SFWRALL(f) ((f)->mode |= SF_RV) #define SFISALL(f,v) ((((v) = (f)->mode&SF_RV) ? ((f)->mode &= ~SF_RV) : 0), \ ((v) || (f)->extent < 0 || \ ((f)->flags&(SF_SHARE|SF_APPENDWR|SF_WHOLE)) ) ) #define SFSK(f,a,o,d) (SETLOCAL(f),sfsk(f,(Sfoff_t)a,o,d)) #define SFRD(f,b,n,d) (SETLOCAL(f),sfrd(f,(Void_t*)b,n,d)) #define SFWR(f,b,n,d) (SETLOCAL(f),sfwr(f,(Void_t*)b,n,d)) #define SFSYNC(f) (SETLOCAL(f),sfsync(f)) #define SFCLOSE(f) (SETLOCAL(f),sfclose(f)) #define SFFLSBUF(f,n) (SETLOCAL(f),_sfflsbuf(f,n)) #define SFFILBUF(f,n) (SETLOCAL(f),_sffilbuf(f,n)) #define SFSETBUF(f,s,n) (SETLOCAL(f),sfsetbuf(f,s,n)) #define SFWRITE(f,s,n) (SETLOCAL(f),sfwrite(f,s,n)) #define SFREAD(f,s,n) (SETLOCAL(f),sfread(f,s,n)) #define SFSEEK(f,p,t) (SETLOCAL(f),sfseek(f,p,t)) #define SFNPUTC(f,c,n) (SETLOCAL(f),sfnputc(f,c,n)) #define SFRAISE(f,e,d) (SETLOCAL(f),sfraise(f,e,d)) /* lock/open a stream */ #define SFMODE(f,l) ((f)->mode & ~(SF_RV|SF_RC|((l) ? SF_LOCK : 0)) ) #define SFLOCK(f,l) (void)((f)->mode |= SF_LOCK, (f)->endr = (f)->endw = (f)->data) #define _SFOPENRD(f) ((f)->endr = ((f)->flags&SF_MTSAFE) ? (f)->data : (f)->endb) #define _SFOPENWR(f) ((f)->endw = ((f)->flags&(SF_MTSAFE|SF_LINE)) ? (f)->data : (f)->endb) #define _SFOPEN(f) ((f)->mode == SF_READ ? _SFOPENRD(f) : \ (f)->mode == SF_WRITE ? _SFOPENWR(f) : \ ((f)->endr = (f)->endr = (f)->data) ) #define SFOPEN(f,l) (void)((l) ? 0 : \ ((f)->mode &= ~(SF_LOCK|SF_RC|SF_RV), _SFOPEN(f), 0) ) /* check to see if the stream can be accessed */ #define SFFROZEN(f) ((f)->mode&(SF_PUSH|SF_LOCK|SF_PEEK) ? 1 : \ ((f)->mode&SF_STDIO) ? (*_Sfstdsync)(f) : 0) /* set discipline code */ #define SFDISC(f,dc,iof) \ { Sfdisc_t* d; \ if(!(dc)) \ d = (dc) = (f)->disc; \ else d = (f->bits&SF_DCDOWN) ? ((dc) = (dc)->disc) : (dc); \ while(d && !(d->iof)) d = d->disc; \ if(d) (dc) = d; \ } #define SFDCRD(f,buf,n,dc,rv) \ { int dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \ rv = (*dc->readf)(f,buf,n,dc); \ if(!dcdown) f->bits &= ~SF_DCDOWN; \ } #define SFDCWR(f,buf,n,dc,rv) \ { int dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \ rv = (*dc->writef)(f,buf,n,dc); \ if(!dcdown) f->bits &= ~SF_DCDOWN; \ } #define SFDCSK(f,addr,type,dc,rv) \ { int dcdown = f->bits&SF_DCDOWN; f->bits |= SF_DCDOWN; \ rv = (*dc->seekf)(f,addr,type,dc); \ if(!dcdown) f->bits &= ~SF_DCDOWN; \ } /* fast peek of a stream */ #define _SFAVAIL(f,s,n) ((n) = (f)->endb - ((s) = (f)->next) ) #define SFRPEEK(f,s,n) (_SFAVAIL(f,s,n) > 0 ? (n) : \ ((n) = SFFILBUF(f,-1), (s) = (f)->next, (n)) ) #define SFWPEEK(f,s,n) (_SFAVAIL(f,s,n) > 0 ? (n) : \ ((n) = SFFLSBUF(f,-1), (s) = (f)->next, (n)) ) /* more than this for a line buffer, we might as well flush */ #define HIFORLINE 128 /* safe closing function */ #define CLOSE(f) { while(close(f) < 0 && errno == EINTR) errno = 0; } /* string stream extent */ #define SFSTRSIZE(f) { Sfoff_t s = (f)->next - (f)->data; \ if(s > (f)->here) \ { (f)->here = s; if(s > (f)->extent) (f)->extent = s; } \ } /* control flags for open() */ #ifdef O_CREAT #define _has_oflags 1 #else /* for example, research UNIX */ #define _has_oflags 0 #define O_CREAT 004 #define O_TRUNC 010 #define O_APPEND 020 #define O_EXCL 040 #ifndef O_RDONLY #define O_RDONLY 000 #endif #ifndef O_WRONLY #define O_WRONLY 001 #endif #ifndef O_RDWR #define O_RDWR 002 #endif #endif /*O_CREAT*/ #ifndef O_BINARY #define O_BINARY 000 #endif #ifndef O_TEXT #define O_TEXT 000 #endif #ifndef O_TEMPORARY #define O_TEMPORARY 000 #endif #define SF_RADIX 64 /* maximum integer conversion base */ #if _PACKAGE_ast #define SF_MAXINT INT_MAX #define SF_MAXLONG LONG_MAX #else #define SF_MAXINT ((int)(((uint)~0) >> 1)) #define SF_MAXLONG ((long)(((ulong)~0L) >> 1)) #endif #define SF_MAXCHAR ((uchar)(~0)) /* floating point to ascii conversion */ #define SF_MAXEXP10 6 #define SF_MAXPOW10 (1 << SF_MAXEXP10) #if !_ast_fltmax_double #define SF_FDIGITS 1024 /* max allowed fractional digits */ #define SF_IDIGITS (8*1024) /* max number of digits in int part */ #else #define SF_FDIGITS 256 /* max allowed fractional digits */ #define SF_IDIGITS 1024 /* max number of digits in int part */ #endif #define SF_MAXDIGITS (((SF_FDIGITS+SF_IDIGITS)/sizeof(int) + 1)*sizeof(int)) /* tables for numerical translation */ #define _Sfpos10 (_Sftable.sf_pos10) #define _Sfneg10 (_Sftable.sf_neg10) #define _Sfdec (_Sftable.sf_dec) #define _Sfdigits (_Sftable.sf_digits) #define _Sfcvinitf (_Sftable.sf_cvinitf) #define _Sfcvinit (_Sftable.sf_cvinit) #define _Sffmtposf (_Sftable.sf_fmtposf) #define _Sffmtintf (_Sftable.sf_fmtintf) #define _Sfcv36 (_Sftable.sf_cv36) #define _Sfcv64 (_Sftable.sf_cv64) #define _Sftype (_Sftable.sf_type) #define _Sffhuge (_Sftable.sf_flt_huge) #define _Sfdhuge (_Sftable.sf_dbl_huge) #define _Sflhuge (_Sftable.sf_ldbl_huge) #define _Sffpow10 (_Sftable.sf_flt_pow10) #define _Sfdpow10 (_Sftable.sf_dbl_pow10) #define _Sflpow10 (_Sftable.sf_ldbl_pow10) typedef struct _sftab_ { Sfdouble_t sf_pos10[SF_MAXEXP10]; /* positive powers of 10 */ Sfdouble_t sf_neg10[SF_MAXEXP10]; /* negative powers of 10 */ uchar sf_dec[200]; /* ascii reps of values < 100 */ char* sf_digits; /* digits for general bases */ int (*sf_cvinitf)(); /* initialization function */ int sf_cvinit; /* initialization state */ Fmtpos_t* (*sf_fmtposf)_ARG_((Sfio_t*,const char*,va_list,int)); char* (*sf_fmtintf)_ARG_((const char*,int*)); float* sf_flt_pow10; /* float powers of 10 */ double* sf_dbl_pow10; /* double powers of 10 */ Sfdouble_t* sf_ldbl_pow10; /* Sfdouble_t powers of 10 */ float sf_flt_huge; /* float HUGE_VALUE */ double sf_dbl_huge; /* double HUGE_VALUE */ Sfdouble_t sf_ldbl_huge; /* Sfdouble_t HUGE_VALUE */ uchar sf_cv36[SF_MAXCHAR+1]; /* conversion for base [2-36] */ uchar sf_cv64[SF_MAXCHAR+1]; /* conversion for base [37-64] */ uchar sf_type[SF_MAXCHAR+1]; /* conversion formats&types */ } Sftab_t; /* thread-safe macro/function to initialize _Sfcv* conversion tables */ #define SFCVINIT() (_Sfcvinit ? 1 : (_Sfcvinit = (*_Sfcvinitf)()) ) /* sfucvt() converts decimal integers to ASCII */ #define SFDIGIT(v,scale,digit) \ { if(v < 5*scale) \ if(v < 2*scale) \ if(v < 1*scale) \ { digit = '0'; } \ else { digit = '1'; v -= 1*scale; } \ else if(v < 3*scale) \ { digit = '2'; v -= 2*scale; } \ else if(v < 4*scale) \ { digit = '3'; v -= 3*scale; } \ else { digit = '4'; v -= 4*scale; } \ else if(v < 7*scale) \ if(v < 6*scale) \ { digit = '5'; v -= 5*scale; } \ else { digit = '6'; v -= 6*scale; } \ else if(v < 8*scale) \ { digit = '7'; v -= 7*scale; } \ else if(v < 9*scale) \ { digit = '8'; v -= 8*scale; } \ else { digit = '9'; v -= 9*scale; } \ } #define sfucvt(v,s,n,list,type,utype) \ { while((utype)v >= 10000) \ { n = v; v = (type)(((utype)v)/10000); \ n = (type)((utype)n - ((utype)v)*10000); \ s -= 4; SFDIGIT(n,1000,s[0]); SFDIGIT(n,100,s[1]); \ s[2] = *(list = (char*)_Sfdec + (n <<= 1)); s[3] = *(list+1); \ } \ if(v < 100) \ { if(v < 10) \ { s -= 1; s[0] = (char)('0'+v); \ } else \ { s -= 2; s[0] = *(list = (char*)_Sfdec + (v <<= 1)); s[1] = *(list+1); \ } \ } else \ { if(v < 1000) \ { s -= 3; SFDIGIT(v,100,s[0]); \ s[1] = *(list = (char*)_Sfdec + (v <<= 1)); s[2] = *(list+1); \ } else \ { s -= 4; SFDIGIT(v,1000,s[0]); SFDIGIT(v,100,s[1]); \ s[2] = *(list = (char*)_Sfdec + (v <<= 1)); s[3] = *(list+1); \ } \ } \ } /* handy functions */ #undef min #undef max #define min(x,y) ((x) < (y) ? (x) : (y)) #define max(x,y) ((x) > (y) ? (x) : (y)) /* fast functions for memory copy and memory clear */ #if _PACKAGE_ast #define memclear(s,n) memzero(s,n) #else #if _lib_bcopy && !_lib_memcpy #define memcpy(to,fr,n) bcopy((fr),(to),(n)) #endif #if _lib_bzero && !_lib_memset #define memclear(s,n) bzero((s),(n)) #else #define memclear(s,n) memset((s),'\0',(n)) #endif #endif /*_PACKAGE_ast*/ /* note that MEMCPY advances the associated pointers */ #define MEMCPY(to,fr,n) \ switch(n) \ { default : memcpy((Void_t*)to,(Void_t*)fr,n); to += n; fr += n; break; \ case 7 : *to++ = *fr++; \ case 6 : *to++ = *fr++; \ case 5 : *to++ = *fr++; \ case 4 : *to++ = *fr++; \ case 3 : *to++ = *fr++; \ case 2 : *to++ = *fr++; \ case 1 : *to++ = *fr++; \ } #define MEMSET(s,c,n) \ switch(n) \ { default : memset((Void_t*)s,(int)c,n); s += n; break; \ case 7 : *s++ = c; \ case 6 : *s++ = c; \ case 5 : *s++ = c; \ case 4 : *s++ = c; \ case 3 : *s++ = c; \ case 2 : *s++ = c; \ case 1 : *s++ = c; \ } _BEGIN_EXTERNS_ extern Sftab_t _Sftable; extern int _sfpopen _ARG_((Sfio_t*, int, int, int)); extern int _sfpclose _ARG_((Sfio_t*)); extern int _sfexcept _ARG_((Sfio_t*, int, ssize_t, Sfdisc_t*)); extern Sfrsrv_t* _sfrsrv _ARG_((Sfio_t*, ssize_t)); extern int _sfsetpool _ARG_((Sfio_t*)); extern char* _sfcvt _ARG_((Sfdouble_t,char*,size_t,int,int*,int*,int*,int)); extern char** _sfgetpath _ARG_((char*)); extern Sfdouble_t _sfdscan _ARG_((Void_t*, int(*)(Void_t*))); #if _BLD_sfio && defined(__EXPORT__) #define extern __EXPORT__ #endif #if _BLD_stdio && defined(__IMPORT__) #define extern __IMPORT__ #endif extern Sfextern_t _Sfextern; extern int _sfmode _ARG_((Sfio_t*, int, int)); extern int _sftype _ARG_((const char*, int*, int*)); #undef extern #ifndef errno extern int errno; #endif /* for portable encoding of double values */ #if _ast_fltmax_double #define frexpl frexp #define ldexpl ldexp #endif #if !__STDC__ extern Sfdouble_t frexpl _ARG_((Sfdouble_t, int*)); extern Sfdouble_t ldexpl _ARG_((Sfdouble_t, int)); #endif #if !_PACKAGE_ast #if !__STDC__ && !_hdr_stdlib extern void abort _ARG_((void)); extern int atexit _ARG_((void(*)(void))); extern char* getenv _ARG_((const char*)); extern void* malloc _ARG_((size_t)); extern void* realloc _ARG_((void*, size_t)); extern void free _ARG_((void*)); extern size_t strlen _ARG_((const char*)); extern char* strcpy _ARG_((char*, const char*)); extern Void_t* memset _ARG_((void*, int, size_t)); extern Void_t* memchr _ARG_((const void*, int, size_t)); extern Void_t* memccpy _ARG_((void*, const void*, int, size_t)); #ifndef memcpy extern Void_t* memcpy _ARG_((void*, const void*, size_t)); #endif #if !defined(strtod) extern double strtod _ARG_((const char*, char**)); #endif #if !defined(remove) extern int remove _ARG_((const char*)); #endif #endif /* !__STDC__ && !_hdr_stdlib */ #if !_hdr_unistd extern int close _ARG_((int)); extern ssize_t read _ARG_((int, void*, size_t)); extern ssize_t write _ARG_((int, const void*, size_t)); extern sfoff_t lseek _ARG_((int, sfoff_t, int)); extern int dup _ARG_((int)); extern int isatty _ARG_((int)); extern int wait _ARG_((int*)); extern int pipe _ARG_((int*)); extern int access _ARG_((const char*, int)); extern uint sleep _ARG_((uint)); extern int execl _ARG_((const char*, const char*,...)); extern int execv _ARG_((const char*, char**)); #if !defined(fork) extern int fork _ARG_((void)); #endif #if _lib_unlink extern int unlink _ARG_((const char*)); #endif #endif /*_hdr_unistd*/ #if _lib_bcopy && !_proto_bcopy extern void bcopy _ARG_((const void*, void*, size_t)); #endif #if _lib_bzero && !_proto_bzero extern void bzero _ARG_((void*, size_t)); #endif extern time_t time _ARG_((time_t*)); extern int waitpid _ARG_((int,int*,int)); extern void _exit _ARG_((int)); typedef int(* Onexit_f)_ARG_((void)); extern Onexit_f onexit _ARG_((Onexit_f)); #if _sys_stat extern int fstat _ARG_((int, sfstat_t*)); #endif #if _lib_vfork && !_hdr_vfork && !_sys_vfork extern pid_t vfork _ARG_((void)); #endif /*_lib_vfork*/ #if _lib_poll #if _lib_poll_fd_1 extern int poll _ARG_((struct pollfd*, ulong, int)); #else extern int poll _ARG_((ulong, struct pollfd*, int)); #endif #endif /*_lib_poll*/ #if _proto_open && __cplusplus extern int open _ARG_((const char*, int, ...)); #endif #endif /* _PACKAGE_ast */ _END_EXTERNS_ #endif /*_SFHDR_H*/ it _ARG_((Onexit_f)); #if _sys_stat extern int fstat _ARG_((int, sfstat_t*)); #endif #if _lib_vfork && !_hdr_vfork && !_sys_vfork extern pid_t vfork _ARG_((void)); #endif /*_lib_vfork*/ #if _lib_poll #if _lib_poll_fd_1 extern int poll _ARG_((struct pollfd*, ulong, int)); #else extern int poll _ARG_((ulong, struct pollfd*, int)); #endif #endif /*_lib_poll*/ #if _proto_open && __cplusplus extern int open _ARG_((const char*, int, ...src/lib/sfio/sfclose.c000644 151361 151361 00000005350 07432261522 014635 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Close a stream. A file stream is synced before closing. ** ** Written by Kiem-Phong Vo */ #if __STD_C int sfclose(reg Sfio_t* f) #else int sfclose(f) reg Sfio_t* f; #endif { reg int local, ex, rv; Void_t* data = NIL(Void_t*); SFMTXSTART(f, -1); GETLOCAL(f,local); if(!(f->mode&SF_INIT) && SFMODE(f,local) != (f->mode&SF_RDWR) && SFMODE(f,local) != (f->mode&(SF_READ|SF_SYNCED)) && _sfmode(f,0,local) < 0) SFMTXRETURN(f,-1); /* closing a stack of streams */ while(f->push) { reg Sfio_t* pop; if(!(pop = (*_Sfstack)(f,NIL(Sfio_t*))) ) SFMTXRETURN(f,-1); if(sfclose(pop) < 0) { (*_Sfstack)(f,pop); SFMTXRETURN(f,-1); } } rv = 0; if(f->disc == _Sfudisc) /* closing the ungetc stream */ f->disc = NIL(Sfdisc_t*); else if(f->file >= 0) /* sync file pointer */ { f->bits |= SF_ENDING; rv = sfsync(f); } SFLOCK(f,0); /* raise discipline exceptions */ if(f->disc && (ex = SFRAISE(f,local ? SF_NEW : SF_CLOSING,NIL(Void_t*))) != 0) SFMTXRETURN(f,ex); if(!local && f->pool) { /* remove from pool */ if(f->pool == &_Sfpool) { reg int n; POOLMTXLOCK(&_Sfpool); for(n = 0; n < _Sfpool.n_sf; ++n) { if(_Sfpool.sf[n] != f) continue; /* found it */ _Sfpool.n_sf -= 1; for(; n < _Sfpool.n_sf; ++n) _Sfpool.sf[n] = _Sfpool.sf[n+1]; break; } POOLMTXUNLOCK(&_Sfpool); } else { f->mode &= ~SF_LOCK; /**/ASSERT(_Sfpmove); if((*_Sfpmove)(f,-1) < 0) { SFOPEN(f,0); SFMTXRETURN(f,-1); } f->mode |= SF_LOCK; } f->pool = NIL(Sfpool_t*); } if(f->data && (!local || (f->flags&SF_STRING) || (f->bits&SF_MMAP) ) ) { /* free buffer */ #ifdef MAP_TYPE if(f->bits&SF_MMAP) SFMUNMAP(f,f->data,f->endb-f->data); else #endif if(f->flags&SF_MALLOC) data = (Void_t*)f->data; f->data = NIL(uchar*); f->size = -1; } /* zap the file descriptor */ if(_Sfnotify) (*_Sfnotify)(f,SF_CLOSING,f->file); if(f->file >= 0 && !(f->flags&SF_STRING)) CLOSE(f->file); f->file = -1; SFKILL(f); f->flags &= SF_STATIC; f->here = 0; f->extent = -1; f->endb = f->endr = f->endw = f->next = f->data; /* zap any associated auxiliary buffer */ if(f->rsrv) { free(f->rsrv); f->rsrv = NIL(Sfrsrv_t*); } /* delete any associated sfpopen-data */ if(f->proc) rv = _sfpclose(f); /* destroy the mutex */ if(f->mutex) { vtmtxclrlock(f->mutex); if(f != sfstdin && f != sfstdout && f != sfstderr) { vtmtxclose(f->mutex); f->mutex = NIL(Vtmutex_t*); } } if(!local) { if(f->disc && (ex = SFRAISE(f,SF_FINAL,NIL(Void_t*))) != 0 ) { rv = ex; goto done; } if(!(f->flags&SF_STATIC) ) free(f); else { f->disc = NIL(Sfdisc_t*); f->stdio = NIL(Void_t*); f->mode = SF_AVAIL; } } done: if(data) free(data); return rv; } */ if(f->proc) rv = _sfpclose(f); /* destroy the mutex */ if(f->mutex) { vtmtxclrlock(f->mutex); if(f != sfstdin && f != sfstdout && f != sfstderr) { vtmtxclose(f->mutex); f->mutex = NIL(Vtmutex_t*); } } if(!local) { if(f->disc && (ex = SFRAISE(f,SF_FINAL,NILsrc/lib/sfio/sfexit.c000644 151361 151361 00000004644 07432516301 014504 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* ** Any required functions for process exiting. ** Written by Kiem-Phong Vo */ #if PACKAGE_ast int _AST_already_has_them; #else #if !_lib_atexit #if _lib_onexit #if __STD_C int atexit(void (*exitf)(void)) #else int atexit(exitf) void (*exitf)(); #endif { #if _lib_onexit return onexit(exitf); #endif } #else /* !_lib_onexit */ typedef struct _exit_s { struct _exit_s* next; void (*exitf)_ARG_((void)); } Exit_t; static Exit_t* Exit; #if __STD_C atexit(void (*exitf)(void)) #else atexit(exitf) void (*exitf)(); #endif { Exit_t* e; int rv; vtmtxlock(_Sfmutex); if(!(e = (Exit_t*)malloc(sizeof(Exit_t))) ) rv = -1; else { e->exitf = exitf; e->next = Exit; Exit = e; rv = 0; } vtmtxunlock(_Sfmutex); return rv; } #if _exit_cleanup /* since exit() calls _cleanup(), we only need to redefine _cleanup() */ #if __STD_C _cleanup(void) #else _cleanup() #endif { Exit_t* e; for(e = Exit; e; e = e->next) (*e->exitf)(); if(_Sfcleanup) (*_Sfcleanup)(); } #else /* in this case, we have to redefine exit() itself */ #if __STD_C void exit(int type) #else void exit(type) int type; #endif { Exit_t* e; for(e = Exit; e; e = e->next) (*e->exitf)(); _exit(type); } #endif /* _exit_cleanup */ #endif /* _lib_onexit */ #endif /* !_lib_atexit */ #if _lib_waitpid int _Sf_no_need_for_waitpid; #else /* we need to supply our own waitpid here so that sfpclose() can wait ** for the right process to die. */ typedef struct _wait_ { int pid; int status; struct _wait_* next; } Waitpid_t; static Waitpid_t* Wait; #if __STD_C waitpid(int pid, int* status, int options) #else waitpid(pid, status, options) int pid; int* status; int options; #endif { int id, ps; Waitpid_t* w; Waitpid_t* last; /* we don't know options */ if(options != 0) return -1; vtmtxlock(_Sfmutex); for(w = Wait, last = NIL(Waitpid_t*); w; last = w, w = w->next) { if(pid > 0 && pid != w->pid) continue; if(last) last->next = w->next; else Wait = w->next; if(status) *status = w->status; pid = w->pid; free(w); vtmtxunlock(_Sfmutex); return pid; } while((id = wait(&ps)) >= 0) { if(pid <= 0 || id == pid) { if(status) *status = ps; vtmtxunlock(_Sfmutex); return pid; } if(!(w = (Waitpid_t*)malloc(sizeof(Waitpid_t))) ) continue; w->pid = id; w->status = ps; w->next = Wait; Wait = w; } vtmtxunlock(_Sfmutex); return -1; } #endif /*_lib_waitpid*/ #endif /*!PACKAGE_ast*/ ast->next = w->next; else Wait = w->next; if(status) *status = w->status; pid = w->src/lib/sfio/sfvprintf.c000644 151361 151361 00000065517 07436471341 015241 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* The engine for formatting data. ** 1. Argument positioning is done in sftable.c so any changes ** made here should be reflected in sftable.c as well. ** 2. For internationalization, Sfio only supports I/O of multibyte strings. ** However, this code does provide minimal support so that Stdio functions ** such as fwprintf/swprintf can be emulated (see stdvwprintf()). ** ** Written by Kiem-Phong Vo. */ #define HIGHBITI (~((~((uint)0)) >> 1)) #define HIGHBITL (~((~((Sfulong_t)0)) >> 1)) #define SFFMT_PREFIX (SFFMT_MINUS|SFFMT_SIGN|SFFMT_BLANK) #define FPRECIS 6 /* default precision for floats */ /* On some platform(s), large functions are not compilable. ** In such a case, the below macro should be defined non-zero so that ** some in-lined macros will be made smaller, trading time for space. */ #if !defined(_sffmt_small) && defined(_UTS) #define _sffmt_small 1 #endif #if __STD_C int sfvprintf(Sfio_t* f, const char* form, va_list args) #else int sfvprintf(f,form,args) Sfio_t* f; /* file to print to */ char* form; /* format to use */ va_list args; /* arg list if !argf */ #endif { int n, v, n_s, base, fmt, flags; Sflong_t lv; char *sp, *ssp, *endsp, *ep, *endep; int dot, width, precis, sign, decpt; ssize_t size; Sfdouble_t dval; char *tls[2], **ls; /* for %..[separ]s */ char* t_str; /* stuff between () */ ssize_t n_str; /* its length */ Argv_t argv; /* for extf to return value */ Sffmt_t *ft; /* format environment */ Fmt_t *fm, *fmstk; /* stack contexts */ char* oform; /* original format string */ va_list oargs; /* original arg list */ Fmtpos_t* fp; /* arg position list */ int argp, argn; /* arg position and number */ #define SLACK 1024 char buf[SF_MAXDIGITS+SLACK], tmp[SF_MAXDIGITS], data[SF_GRAIN]; int decimal = 0, thousand = 0; #if _has_multibyte wchar_t* wsp; SFMBDCL(fmbs) /* state of format string */ SFMBDCL(mbs) /* state of some string */ #endif /* local io system */ int w, n_output; #define SMputc(f,c) { if((w = SFFLSBUF(f,c)) >= 0 ) n_output += 1; \ else goto done; \ } #define SMnputc(f,c,n) { if((w = SFNPUTC(f,c,n)) > 0 ) n_output += 1; \ if(w != n) goto done; \ } #define SMwrite(f,s,n) { if((w = SFWRITE(f,(Void_t*)s,n)) > 0 ) n_output += w; \ if(w != n) goto done; \ } #if _sffmt_small /* these macros are made smaller at some performance cost */ #define SFBUF(f) #define SFINIT(f) (n_output = 0) #define SFEND(f) #define SFputc(f,c) SMputc(f,c) #define SFnputc(f,c,n) SMnputc(f,c,n) #define SFwrite(f,s,n) SMwrite(f,s,n) #else uchar *d, *endd; #define SFBUF(f) (d = f->next, endd = f->endb) #define SFINIT(f) (SFBUF(f), n_output = 0) #define SFEND(f) ((n_output += d - f->next), (f->next = d)) #define SFputc(f,c) { if(d < endd) { *d++ = (uchar)c; } \ else { SFEND(f); SMputc(f,c); SFBUF(f); } \ } #define SFnputc(f,c,n) { if(d+n <= endd) { while(n--) *d++ = (uchar)(c); } \ else { SFEND(f); SMnputc(f,c,n); SFBUF(f); } \ } #define SFwrite(f,s,n) { if(d+n <= endd) { while(n--) *d++ = (uchar)(*s++); } \ else { SFEND(f); SMwrite(f,s,n); SFBUF(f); } \ } #endif /* _sffmt_small */ SFCVINIT(); /* initialize conversion tables */ SFMTXSTART(f,-1); if(!form) SFMTXRETURN(f, -1); /* make sure stream is in write mode and buffer is not NULL */ if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0) SFMTXRETURN(f, -1); SFLOCK(f,0); if(!f->data && !(f->flags&SF_STRING)) { f->data = f->next = (uchar*)data; f->endb = f->data+sizeof(data); } SFINIT(f); tls[1] = NIL(char*); fmstk = NIL(Fmt_t*); ft = NIL(Sffmt_t*); oform = (char*)form; va_copy(oargs,args); argn = -1; fp = NIL(Fmtpos_t*); loop_fmt : SFMBCLR(&fmbs); /* clear multibyte states to parse the format string */ while((n = *form) ) { if(n != '%') /* collect the non-pattern chars */ { sp = (char*)form; for(;;) { form += SFMBLEN(form, &fmbs); if(*form == 0 || *form == '%') break; } n = form-sp; SFwrite(f,sp,n); continue; } else form += 1; flags = 0; size = width = precis = base = n_s = argp = -1; ssp = _Sfdigits; endep = ep = NIL(char*); endsp = sp = buf+(sizeof(buf)-1); t_str = NIL(char*); n_str = dot = 0; loop_flags: /* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */ switch((fmt = *form++) ) { case '\0': SFputc(f,'%'); goto pop_fmt; case '%' : SFputc(f,'%'); continue; case LEFTP : /* get the type enclosed in balanced parens */ t_str = (char*)form; for(v = 1;;) { switch(*form++) { case 0 : /* not balancable, retract */ form = t_str; t_str = NIL(char*); n_str = 0; goto loop_flags; case LEFTP : /* increasing nested level */ v += 1; continue; case RIGHTP : /* decreasing nested level */ if((v -= 1) != 0) continue; if(*t_str != '*' ) n_str = (form-1)-t_str; else { t_str = (*_Sffmtintf)(t_str+1,&n); if(*t_str == '$') { if(!fp && !(fp = (*_Sffmtposf) (f,oform,oargs,0)) ) goto pop_fmt; n = FP_SET(n,argn); } else n = FP_SET(-1,argn); if(fp) { t_str = fp[n].argv.s; n_str = fp[n].ft.size; } else if(ft && ft->extf ) { FMTSET(ft, form,args, LEFTP, 0, 0, 0,0,0, NIL(char*),0); n = (*ft->extf) (f,(Void_t*)&argv,ft); if(n < 0) goto pop_fmt; if(!(ft->flags&SFFMT_VALUE) ) goto t_arg; if((t_str = argv.s) && (n_str = (int)ft->size) < 0) n_str = strlen(t_str); } else { t_arg: if((t_str = va_arg(args,char*)) ) n_str = strlen(t_str); } } goto loop_flags; } } case '-' : flags = (flags & ~SFFMT_ZERO) | SFFMT_LEFT; goto loop_flags; case '0' : if(!(flags&SFFMT_LEFT) ) flags |= SFFMT_ZERO; goto loop_flags; case ' ' : if(!(flags&SFFMT_SIGN) ) flags |= SFFMT_BLANK; goto loop_flags; case '+' : flags = (flags & ~SFFMT_BLANK) | SFFMT_SIGN; goto loop_flags; case '#' : flags |= SFFMT_ALTER; goto loop_flags; case QUOTE: SFSETLOCALE(&decimal,&thousand); if(thousand) flags |= SFFMT_THOUSAND; goto loop_flags; case '.' : dot += 1; if(dot == 1) { /* so base can be defined without setting precis */ if(*form != '.') precis = 0; } else if(dot == 2) { base = 0; /* for %s,%c */ v = form[0] == 'l' ? form[1] : form[0]; if(v == 'c' || v == 'C' || v == 's' || v == 'S') goto loop_flags; if(*form && !isalnum(*form)) { v = form[1] == 'l' ? form[2] : form[1]; if(v == 'c' || v == 'C' || v == 's' || v == 'S') { if(*form == '*') goto do_star; else { base = *form++; goto loop_flags; } } } } if(isdigit(*form) ) { fmt = *form++; goto dot_size; } else if(*form != '*') goto loop_flags; do_star: form += 1; /* fall thru for '*' */ case '*' : form = (*_Sffmtintf)(form,&n); if(*form == '$') { form += 1; if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,0)) ) goto pop_fmt; n = FP_SET(n,argn); } else n = FP_SET(-1,argn); if(fp) v = fp[n].argv.i; else if(ft && ft->extf) { FMTSET(ft, form,args, '.',dot, 0, 0,0,0, NIL(char*), 0); if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0) goto pop_fmt; fmt = ft->fmt; flags = (flags&~SFFMT_TYPES) | (ft->flags&SFFMT_TYPES); if(ft->flags&SFFMT_VALUE) v = argv.i; else v = (dot <= 2) ? va_arg(args,int) : 0; } else v = dot <= 2 ? va_arg(args,int) : 0; goto dot_set; case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : dot_size : for(v = fmt - '0'; isdigit(*form); ++form) v = v*10 + (*form - '0'); if(*form == '$') { form += 1; if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,0)) ) goto pop_fmt; argp = v-1; goto loop_flags; } dot_set : if(dot == 0) { if((width = v) < 0) { width = -width; flags = (flags & ~SFFMT_ZERO) | SFFMT_LEFT; } } else if(dot == 1) precis = v; else if(dot == 2) base = v; goto loop_flags; case 'I' : /* object length */ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG; if(isdigit(*form) ) { for(size = 0, n = *form; isdigit(n); n = *++form) size = size*10 + (n - '0'); } else if(*form == '*') { form = (*_Sffmtintf)(form+1,&n); if(*form == '$') { form += 1; if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,0))) goto pop_fmt; n = FP_SET(n,argn); } else n = FP_SET(-1,argn); if(fp) /* use position list */ size = fp[n].argv.i; else if(ft && ft->extf) { FMTSET(ft, form,args, 'I',sizeof(int), 0, 0,0,0, NIL(char*), 0); if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0) goto pop_fmt; if(ft->flags&SFFMT_VALUE) size = argv.i; else size = va_arg(args,int); } else size = va_arg(args,int); } goto loop_flags; case 'l' : size = -1; flags &= ~SFFMT_TYPES; if(*form == 'l') { form += 1; flags |= SFFMT_LLONG; } else flags |= SFFMT_LONG; goto loop_flags; case 'h' : size = -1; flags &= ~SFFMT_TYPES; if(*form == 'h') { form += 1; flags |= SFFMT_SSHORT; } else flags |= SFFMT_SHORT; goto loop_flags; case 'L' : size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE; goto loop_flags; case 'j' : size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_JFLAG; goto loop_flags; case 'z' : size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_ZFLAG; goto loop_flags; case 't' : size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_TFLAG; goto loop_flags; default: break; } /* set object size for scalars */ if(flags & SFFMT_TYPES) { if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n') { if(flags&SFFMT_LONG) size = sizeof(long); else if(flags&SFFMT_SHORT) size = sizeof(short); else if(flags&SFFMT_SSHORT) size = sizeof(char); else if(flags&SFFMT_TFLAG) size = sizeof(ptrdiff_t); else if(flags&SFFMT_ZFLAG) size = sizeof(size_t); else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) ) size = sizeof(Sflong_t); else if(flags&SFFMT_IFLAG) { if(size <= 0 || size == sizeof(Sflong_t)*CHAR_BIT ) size = sizeof(Sflong_t); } else if(size < 0) size = sizeof(int); } else if(_Sftype[fmt]&SFFMT_FLOAT) { if(flags&(SFFMT_LONG|SFFMT_LLONG)) size = sizeof(double); else if(flags&SFFMT_LDOUBLE) size = sizeof(Sfdouble_t); else if(flags&SFFMT_IFLAG) { if(size <= 0) size = sizeof(Sfdouble_t); } else if(size < 0) size = sizeof(float); } else if(_Sftype[fmt]&SFFMT_CHAR) { #if _has_multibyte if((flags&SFFMT_LONG) || fmt == 'C') { size = sizeof(wchar_t) > sizeof(int) ? sizeof(wchar_t) : sizeof(int); } else #endif if(size < 0) size = sizeof(int); } } argp = FP_SET(argp,argn); if(fp) { if(ft && ft->extf && fp[argp].ft.fmt != fp[argp].fmt) fmt = fp[argp].ft.fmt; argv = fp[argp].argv; size = fp[argp].ft.size; } else if(ft && ft->extf ) /* extended processing */ { FMTSET(ft, form,args, fmt, size,flags, width,precis,base, t_str,n_str); SFEND(f); SFOPEN(f,0); v = (*ft->extf)(f, (Void_t*)(&argv), ft); SFLOCK(f,0); SFBUF(f); if(v < 0) /* no further processing */ goto pop_fmt; else if(v > 0) /* extf output v bytes */ { n_output += v; continue; } else /* extf did not output */ { FMTGET(ft, form,args, fmt, size,flags, width,precis,base); if(!(ft->flags&SFFMT_VALUE)) goto arg_list; else if(_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT) ) { if(size == sizeof(short)) { if(_Sftype[fmt]&SFFMT_INT) argv.i = argv.h; else argv.i = argv.uh; } else if(size == sizeof(char)) { if(_Sftype[fmt]&SFFMT_INT) argv.i = argv.c; else argv.i = argv.uc; } } else if(_Sftype[fmt]&SFFMT_FLOAT ) { if(size == sizeof(float) ) argv.d = argv.f; } } } else { arg_list: switch(_Sftype[fmt]) { case SFFMT_INT: case SFFMT_UINT: #if !_ast_intmax_long if(size == sizeof(Sflong_t)) argv.ll = va_arg(args, Sflong_t); else #endif if(size == sizeof(long) ) argv.l = va_arg(args, long); else argv.i = va_arg(args, int); break; case SFFMT_FLOAT: #if !_ast_fltmax_double if(size == sizeof(Sfdouble_t)) argv.ld = va_arg(args,Sfdouble_t); else #endif argv.d = va_arg(args,double); break; case SFFMT_POINTER: argv.vp = va_arg(args,Void_t*); break; case SFFMT_CHAR: if(base >= 0) argv.s = va_arg(args,char*); #if _has_multibyte else if((flags & SFFMT_LONG) || fmt == 'C') { if(sizeof(wchar_t) <= sizeof(uint) ) argv.wc = (wchar_t)va_arg(args,uint); else argv.wc = va_arg(args,wchar_t); } #endif else argv.c = (char)va_arg(args,int); break; default: /* unknown pattern */ break; } } switch(fmt) /* PRINTF DIRECTIVES */ { default : /* unknown directive */ form -= 1; argn -= 1; continue; case '!' : /* stacking a new environment */ if(!fp) fp = (*_Sffmtposf)(f,oform,oargs,0); else goto pop_fmt; if(!argv.ft) goto pop_fmt; if(!argv.ft->form && ft ) /* change extension functions */ { if(ft->eventf && (*ft->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0) continue; fmstk->ft = ft = argv.ft; } else /* stack a new environment */ { if(!(fm = (Fmt_t*)malloc(sizeof(Fmt_t))) ) goto done; ft = fm->ft = argv.ft; SFMBSET(ft->mbs, &fmbs); if(ft->form) { fm->form = (char*)form; SFMBCPY(&fm->mbs,&fmbs); va_copy(fm->args,args); fm->oform = oform; va_copy(fm->oargs,oargs); fm->argn = argn; fm->fp = fp; form = ft->form; SFMBCLR(ft->mbs); va_copy(args,ft->args); argn = -1; fp = NIL(Fmtpos_t*); oform = (char*)form; va_copy(oargs,args); } else fm->form = NIL(char*); fm->eventf = ft->eventf; fm->next = fmstk; fmstk = fm; } continue; case 'S': flags = (flags & ~SFFMT_TYPES) | SFFMT_LONG; case 's': if(base >= 0) /* list of strings */ { if(!(ls = argv.sp) || !ls[0]) continue; } else { if(!(sp = argv.s)) { sp = "(null)"; flags &= ~SFFMT_LONG; } ls = tls; tls[0] = sp; } for(sp = *ls;;) { /* set v to the number of bytes to output */ #if _has_multibyte if(flags & SFFMT_LONG) { v = 0; SFMBCLR(&mbs); for(n = 0, wsp = (wchar_t*)sp;; ++wsp, ++n) { if((size >= 0 && n >= size) || (size < 0 && *wsp == 0) ) break; n_s = wcrtomb(buf, *wsp, &mbs); if(precis >= 0 && (v+n_s) > precis) break; v += n_s; } } else #endif { if((v = size) < 0) v = strlen(sp); } if(precis >= 0 && v > precis) v = precis; if((n = width - v) > 0 && !(flags&SFFMT_LEFT) ) { SFnputc(f, ' ', n); n = 0; } #if _has_multibyte if(flags & SFFMT_LONG) { SFMBCLR(&mbs); for(wsp = (wchar_t*)sp; v > 0; ++wsp, v -= n_s) { n_s = wcrtomb(buf, *wsp, &mbs); sp = buf; SFwrite(f, sp, n_s); } } else #endif { SFwrite(f,sp,v); } if(n > 0) { SFnputc(f,' ',n); } if(!(sp = *++ls)) break; else if(base > 0) { SFputc(f,base); } } continue; case 'C': flags = (flags & ~SFFMT_TYPES) | SFFMT_LONG; case 'c': if(precis <= 0) /* # of times to repeat a character */ precis = 1; #if _has_multibyte if(flags & SFFMT_LONG) { if(base >= 0) { if(!(wsp = (wchar_t*)argv.s) ) continue; for(size = 0; wsp[size]; ++size) ; } else { wsp = &argv.wc; size = 1; } } else #endif { if(base >= 0) { if(!(sp = argv.s) ) continue; size = strlen(sp); } else { sp = &argv.c; size = 1; } } while(size > 0) { #if _has_multibyte if(flags & SFFMT_LONG) { SFMBCLR(&mbs); sp = buf; if((n_s = wcrtomb(sp, *wsp++, &mbs)) <= 0) break; n = width - precis*n_s; /* padding amount */ } else #endif { fmt = *sp++; n = width - precis; } if(n > 0 && !(flags&SFFMT_LEFT) ) { SFnputc(f,' ',n); n = 0; }; v = precis; /* need this because SFnputc may clear it */ #if _has_multibyte if(flags & SFFMT_LONG) { for(; v > 0; --v) { SFwrite(f, sp, n_s); } } else #endif { SFnputc(f, fmt, v); } if(n > 0) { SFnputc(f,' ',n); }; if((size -= 1) > 0 && base > 0) { SFputc(f,base); } } continue; case 'n': /* return current output length */ SFEND(f); #if !_ast_intmax_long if(size == sizeof(Sflong_t) ) *((Sflong_t*)argv.vp) = (Sflong_t)n_output; else #endif if(size == sizeof(long)) *((long*)argv.vp) = (long)n_output; else if(size == sizeof(short) ) *((short*)argv.vp) = (short)n_output; else if(size == sizeof(uchar) ) *((uchar*)argv.vp) = (uchar)n_output; else *((int*)argv.vp) = (int)n_output; continue; case 'p': /* pointer value */ fmt = 'x'; base = 16; n_s = 15; n = 4; flags = (flags&~(SFFMT_SIGN|SFFMT_BLANK|SFFMT_ZERO))|SFFMT_ALTER; #if _more_void_int lv = (Sflong_t)((Sfulong_t)argv.vp); goto long_cvt; #else v = (int)((uint)argv.vp); goto int_cvt; #endif case 'o': base = 8; n_s = 7; n = 3; flags &= ~(SFFMT_SIGN|SFFMT_BLANK); goto int_arg; case 'X': ssp = "0123456789ABCDEF"; case 'x': base = 16; n_s = 15; n = 4; flags &= ~(SFFMT_SIGN|SFFMT_BLANK); goto int_arg; case 'i': fmt = 'd'; goto d_format; case 'u': flags &= ~(SFFMT_SIGN|SFFMT_BLANK); case 'd': d_format: if(base < 2 || base > SF_RADIX) base = 10; if((base&(n_s = base-1)) == 0) { if(base < 8) n = base < 4 ? 1 : 2; else if(base < 32) n = base < 16 ? 3 : 4; else n = base < 64 ? 5 : 6; } else n_s = base == 10 ? -1 : 0; int_arg: #if !_ast_intmax_long || _more_long_int || _more_void_int if(size == sizeof(Sflong_t)) { lv = argv.ll; goto long_cvt; } else if(sizeof(long) < sizeof(Sflong_t) && size == sizeof(long)) { if(fmt == 'd') lv = (Sflong_t)argv.l; else lv = (Sflong_t)argv.ul; long_cvt: if(lv == 0 && precis == 0) break; if(lv < 0 && fmt == 'd' ) { flags |= SFFMT_MINUS; if(lv == HIGHBITL) /* avoid overflow */ { lv = (Sflong_t)(HIGHBITL/base); *--sp = _Sfdigits[HIGHBITL - ((Sfulong_t)lv)*base]; } else lv = -lv; } if(n_s < 0) /* base 10 */ { Sflong_t nv; sfucvt(lv,sp,nv,ssp,Sflong_t,Sfulong_t); } else if(n_s > 0) /* base power-of-2 */ { do { *--sp = ssp[lv&n_s]; } while((lv = ((Sfulong_t)lv) >> n) ); } else /* general base */ { do { *--sp = ssp[((Sfulong_t)lv)%base]; } while((lv = ((Sfulong_t)lv)/base) ); } } else #endif if(sizeof(short) < sizeof(int) && size == sizeof(short) ) { if(fmt == 'd') v = (int)((short)argv.i); else v = (int)((ushort)argv.i); goto int_cvt; } else if(size == sizeof(char)) { if(fmt == 'd') v = (int)((char)argv.i); else v = (int)((uchar)argv.i); goto int_cvt; } else { v = argv.i; int_cvt: if(v == 0 && precis == 0) break; if(v < 0 && fmt == 'd' ) { flags |= SFFMT_MINUS; if(v == HIGHBITI) /* avoid overflow */ { v = (int)(HIGHBITI/base); *--sp = _Sfdigits[HIGHBITI - ((uint)v)*base]; } else v = -v; } if(n_s < 0) /* base 10 */ { sfucvt(v,sp,n,ssp,int,uint); } else if(n_s > 0) /* base power-of-2 */ { do { *--sp = ssp[v&n_s]; } while((v = ((uint)v) >> n) ); } else /* n_s == 0, general base */ { do { *--sp = ssp[((uint)v)%base]; } while((v = ((uint)v)/base) ); } } if(n_s < 0 && (flags&SFFMT_THOUSAND) && (n = endsp-sp) > 3) { if((n %= 3) == 0) n = 3; for(ep = buf+SLACK, endep = ep + n; ; ) { while(ep < endep) *ep++ = *sp++; if(sp == endsp) break; if(sp <= endsp-3) *ep++ = thousand; endep = ep+3; } sp = buf+SLACK; endsp = ep; } /* zero padding for precision if have room in buffer */ if(precis > 0 && (precis -= (endsp-sp)) < (sp-buf)-64) while(precis-- > 0) *--sp = '0'; if(flags&SFFMT_ALTER) /* prefix */ { if(fmt == 'o') { if(*sp != '0') *--sp = '0'; } else { if(width > 0 && (flags&SFFMT_ZERO)) { /* do 0 padding first */ if(fmt == 'x' || fmt == 'X') n = 0; else if(dot < 2) n = width; else n = base < 10 ? 2 : 3; n += (flags&(SFFMT_MINUS|SFFMT_SIGN)) ? 1 : 0; n = width - (n + (endsp-sp)); while(n-- > 0) *--sp = '0'; } if(fmt == 'x' || fmt == 'X') { *--sp = (char)fmt; *--sp = '0'; } else if(dot >= 2) { /* base#value notation */ *--sp = '#'; if(base < 10) *--sp = (char)('0'+base); else { *--sp = _Sfdec[(base <<= 1)+1]; *--sp = _Sfdec[base]; } } } } break; case 'g': case 'G': /* these ultimately become %e or %f */ case 'a': case 'A': case 'e': case 'E': case 'f': #if !_ast_fltmax_double if(size == sizeof(Sfdouble_t) ) { v = SFFMT_LDOUBLE; dval = argv.ld; } else #endif { v = 0; dval = argv.d; } if(fmt == 'e' || fmt == 'E') { n = (precis = precis < 0 ? FPRECIS : precis)+1; v |= SFFMT_EFORMAT; ep = _sfcvt(dval,tmp,sizeof(tmp), min(n,SF_FDIGITS), &decpt, &sign, &n_s, v); goto e_format; } else if(fmt == 'f' || fmt == 'F') { precis = precis < 0 ? FPRECIS : precis; ep = _sfcvt(dval,tmp,sizeof(tmp), min(precis,SF_FDIGITS), &decpt, &sign, &n_s, v); goto f_format; } else if(fmt == 'a' || fmt == 'A') { if(precis < 0) { if(v == SFFMT_LDOUBLE) precis = 2*(sizeof(Sfdouble_t) - 2); else precis = 2*(sizeof(double) - 2); } n = precis + 1; v |= SFFMT_AFORMAT | (fmt == 'A' ? SFFMT_UPPER : 0); ep = _sfcvt(dval,tmp,sizeof(tmp), min(n,SF_FDIGITS), &decpt, &sign, &n_s, v); sp = endsp = buf+1; /* reserve space for sign */ *endsp++ = '0'; *endsp++ = fmt == 'a' ? 'x' : 'X'; if (!isxdigit(*ep)) goto infinite; goto a_format; } else /* 'g' or 'G' format */ { precis = precis < 0 ? FPRECIS : precis == 0 ? 1 : precis; v |= SFFMT_EFORMAT; ep = _sfcvt(dval,tmp,sizeof(tmp), min(precis,SF_FDIGITS), &decpt, &sign, &n_s, v); if(dval == 0.) decpt = 1; else if(*ep == 'I') goto infinite; if(!(flags&SFFMT_ALTER)) { /* zap trailing 0s */ if((n = n_s) > precis) n = precis; while((n -= 1) >= 1 && ep[n] == '0') ; n += 1; } else n = precis; if(decpt < -3 || decpt > precis) { precis = n-1; goto e_format; } else { precis = n - decpt; goto f_format; } } e_format: /* build the x.yyyy string */ if(isalpha(*ep)) goto infinite; sp = endsp = buf+1; /* reserve space for sign */ a_format: *endsp++ = *ep ? *ep++ : '0'; SFSETLOCALE(&decimal,&thousand); if(precis > 0 || (flags&SFFMT_ALTER)) *endsp++ = decimal; ssp = endsp; endep = ep+precis; while((*endsp++ = *ep++) && ep <= endep) ; precis -= (endsp -= 1) - ssp; /* build the exponent */ ep = endep = buf+(sizeof(buf)-1); if(dval != 0.) { if((n = decpt - 1) < 0) n = -n; while(n > 9) { v = n; n /= 10; *--ep = (char)('0' + (v - n*10)); } } else n = 0; *--ep = (char)('0' + n); if(endep-ep <= 1) /* at least 2 digits */ *--ep = '0'; /* the e/Exponent separator and sign */ *--ep = (decpt > 0 || dval == 0.) ? '+' : '-'; *--ep = fmt == 'a' ? 'p' : fmt == 'A' ? 'P' : isupper(fmt) ? 'E' : 'e'; goto end_aefg; f_format: /* data before the decimal point */ if(isalpha(*ep)) { infinite: endsp = (sp = ep)+sfslen(); ep = endep; precis = 0; goto end_aefg; } SFSETLOCALE(&decimal,&thousand); endsp = sp = buf+1; /* save a space for sign */ endep = ep+decpt; if(decpt > 3 && (flags&SFFMT_THOUSAND) ) { if((n = decpt%3) == 0) n = 3; while(ep < endep && (*endsp++ = *ep++) ) { if(--n == 0 && (ep <= endep-3) ) { *endsp++ = thousand; n = 3; } } } else { while(ep < endep && (*endsp++ = *ep++)) ; } if(endsp == sp) *endsp++ = '0'; if(precis > 0 || (flags&SFFMT_ALTER)) *endsp++ = decimal; if((n = -decpt) > 0) { /* output zeros for negative exponent */ ssp = endsp + min(n,precis); precis -= n; while(endsp < ssp) *endsp++ = '0'; } ssp = endsp; endep = ep+precis; while((*endsp++ = *ep++) && ep <= endep) ; precis -= (endsp -= 1) - ssp; ep = endep; end_aefg: flags |= SFFMT_FLOAT; if(sign) flags |= SFFMT_MINUS; break; } if(flags == 0 && width <= 0) goto do_output; if(flags&SFFMT_PREFIX) fmt = (flags&SFFMT_MINUS) ? '-' : (flags&SFFMT_SIGN) ? '+' : ' '; n = (endsp-sp) + (endep-ep) + (precis <= 0 ? 0 : precis) + ((flags&SFFMT_PREFIX) ? 1 : 0); if((v = width-n) <= 0) v = 0; else if(!(flags&SFFMT_ZERO)) /* right padding */ { if(flags&SFFMT_LEFT) v = -v; else if(flags&SFFMT_PREFIX) /* blank padding, output prefix now */ { *--sp = fmt; flags &= ~SFFMT_PREFIX; } } if(flags&SFFMT_PREFIX) /* put out the prefix */ { SFputc(f,fmt); if(fmt != ' ') flags |= SFFMT_ZERO; } if((n = v) > 0) /* left padding */ { v = (flags&SFFMT_ZERO) ? '0' : ' '; SFnputc(f,v,n); } if((n = precis) > 0 && !(flags&SFFMT_FLOAT)) { /* padding for integer precision */ SFnputc(f,'0',n); precis = 0; } do_output: if((n = endsp-sp) > 0) SFwrite(f,sp,n); if(flags&(SFFMT_FLOAT|SFFMT_LEFT)) { /* SFFMT_FLOAT: right padding for float precision */ if((n = precis) > 0) SFnputc(f,'0',n); /* SFFMT_FLOAT: the exponent of %eE */ if((n = endep - (sp = ep)) > 0) SFwrite(f,sp,n); /* SFFMT_LEFT: right padding */ if((n = -v) > 0) SFnputc(f,' ',n); } } pop_fmt: if(fp) { free(fp); fp = NIL(Fmtpos_t*); } while((fm = fmstk) ) /* pop the format stack and continue */ { if(fm->eventf) { if(!form || !form[0]) (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),ft); else if((*fm->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0) goto loop_fmt; } fmstk = fm->next; if((form = fm->form) ) { SFMBCPY(&fmbs,&fm->mbs); va_copy(args, fm->args); oform = fm->oform; va_copy(oargs,fm->oargs); argn = fm->argn; fp = fm->fp; } ft = fm->ft; free(fm); if(form && form[0]) goto loop_fmt; } done: if(fp) free(fp); while((fm = fmstk) ) { if(fm->eventf) (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),fm->ft); fmstk = fm->next; free(fm); } SFEND(f); n = f->next - f->data; if((sp = (char*)f->data) == data) f->endw = f->endr = f->endb = f->data = NIL(uchar*); f->next = f->data; if((((flags = f->flags)&SF_SHARE) && !(flags&SF_PUBLIC) ) || (n > 0 && (sp == data || (flags&SF_LINE) ) ) ) (void)SFWRITE(f,(Void_t*)sp,n); else f->next += n; SFOPEN(f,0); SFMTXRETURN(f, n_output); } done: if(fp) free(fp); while((fm = fmstk) ) { if(fm->eventf) (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),fm->ft); fmstk = fm->next; free(fm); } SFEND(f); n = f->nexsrc/lib/sfio/sfsync.c000644 151361 151361 00000006277 07432261526 014521 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Synchronize data in buffers with the file system. ** If f is nil, all streams are sync-ed ** ** Written by Kiem-Phong Vo. */ #if __STD_C static int _sfall(void) #else static int _sfall() #endif { reg Sfpool_t *p, *next; reg Sfio_t* f; reg int n, rv; reg int nsync, count, loop; #define MAXLOOP 3 for(loop = 0; loop < MAXLOOP; ++loop) { rv = nsync = count = 0; for(p = &_Sfpool; p; p = next) { /* find the next legitimate pool */ for(next = p->next; next; next = next->next) if(next->n_sf > 0) break; /* walk the streams for _Sfpool only */ for(n = 0; n < ((p == &_Sfpool) ? p->n_sf : 1); ++n) { count += 1; f = p->sf[n]; if(f->flags&SF_STRING ) goto did_sync; if(SFFROZEN(f)) continue; if((f->mode&SF_READ) && (f->mode&SF_SYNCED) ) goto did_sync; if((f->mode&SF_READ) && !(f->bits&SF_MMAP) && f->next == f->endb) goto did_sync; if((f->mode&SF_WRITE) && !(f->bits&SF_HOLE) && f->next == f->data) goto did_sync; if(sfsync(f) < 0) rv = -1; did_sync: nsync += 1; } } if(nsync == count) break; } return rv; } #if __STD_C int sfsync(reg Sfio_t* f) #else int sfsync(f) reg Sfio_t* f; /* stream to be synchronized */ #endif { int local, rv, mode; Sfio_t* origf; if(!(origf = f) ) return _sfall(); SFMTXSTART(origf,-1); GETLOCAL(origf,local); if(origf->disc == _Sfudisc) /* throw away ungetc */ (void)sfclose((*_Sfstack)(origf,NIL(Sfio_t*))); rv = 0; if((origf->mode&SF_RDWR) != SFMODE(origf,local) && _sfmode(origf,0,local) < 0) { rv = -1; goto done; } for(; f; f = f->push) { if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf) (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)1),f->disc); SFLOCK(f,local); /* pretend that this stream is not on a stack */ mode = f->mode&SF_PUSH; f->mode &= ~SF_PUSH; /* these streams do not need synchronization */ if((f->flags&SF_STRING) || (f->mode&SF_SYNCED)) goto next; if((f->mode&SF_WRITE) && (f->next > f->data || (f->bits&SF_HOLE)) ) { /* sync the buffer, make sure pool don't move */ reg int pool = f->mode&SF_POOL; f->mode &= ~SF_POOL; if(f->next > f->data && (SFWRALL(f), SFFLSBUF(f,-1)) < 0) rv = -1; if(!SFISNULL(f) && (f->bits&SF_HOLE) ) { /* realize a previously created hole of 0's */ if(SFSK(f,(Sfoff_t)(-1),SEEK_CUR,f->disc) >= 0) (void)SFWR(f,"",1,f->disc); f->bits &= ~SF_HOLE; } f->mode |= pool; } if((f->mode&SF_READ) && f->extent >= 0 && ((f->bits&SF_MMAP) || f->next < f->endb) ) { /* make sure the file pointer is at the right place */ f->here -= (f->endb-f->next); f->endr = f->endw = f->data; f->mode = SF_READ|SF_SYNCED|SF_LOCK; (void)SFSK(f,f->here,SEEK_SET,f->disc); if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) && !(f->bits&SF_MMAP) ) { f->endb = f->next = f->data; f->mode &= ~SF_SYNCED; } } next: f->mode |= mode; SFOPEN(f,local); if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf) (void)(*f->disc->exceptf)(f,SF_SYNC,(Void_t*)((int)0),f->disc); } done: if(!local && f && (f->mode&SF_POOL) && f->pool && f != f->pool->sf[0]) SFSYNC(f->pool->sf[0]); SFMTXRETURN(origf, rv); } F_LOCK; (void)SFSK(f,f->here,SEEK_SET,f->disc); if((f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) && !(f->bits&SF_MMAP) ) { f->endb = f->next = f->data; f->mode &= ~SF_SYNCED; } } next: f->mode |= mode; SFOPEN(f,local); if((f->flags&SF_IOCHECK) && f->disc && f->disc->exceptf) (void)(*fsrc/lib/sfio/sfdisc.c000644 151361 151361 00000006413 07432261522 014453 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Set a new discipline for a stream. ** ** Written by Kiem-Phong Vo */ #if __STD_C Sfdisc_t* sfdisc(reg Sfio_t* f, reg Sfdisc_t* disc) #else Sfdisc_t* sfdisc(f,disc) reg Sfio_t* f; reg Sfdisc_t* disc; #endif { reg Sfdisc_t *d, *rdisc; reg Sfread_f oreadf; reg Sfwrite_f owritef; reg Sfseek_f oseekf; ssize_t n; SFMTXSTART(f, NIL(Sfdisc_t*)); if((f->flags&SF_READ) && f->proc && (f->mode&SF_WRITE) ) { /* make sure in read mode to check for read-ahead data */ if(_sfmode(f,SF_READ,0) < 0) SFMTXRETURN(f, NIL(Sfdisc_t*)); } else if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0) SFMTXRETURN(f, NIL(Sfdisc_t*)); SFLOCK(f,0); rdisc = NIL(Sfdisc_t*); /* synchronize before switching to a new discipline */ if(!(f->flags&SF_STRING)) { if(((f->mode&SF_WRITE) && f->next > f->data) || (f->mode&SF_READ) || f->disc == _Sfudisc ) (void)SFSYNC(f); if(((f->mode&SF_WRITE) && (n = f->next-f->data) > 0) || ((f->mode&SF_READ) && f->extent < 0 && (n = f->endb-f->next) > 0) ) { reg Sfexcept_f exceptf; reg int rv = 0; exceptf = disc ? disc->exceptf : f->disc ? f->disc->exceptf : NIL(Sfexcept_f); /* check with application for course of action */ if(exceptf) { SFOPEN(f,0); rv = (*exceptf)(f,SF_DBUFFER,&n, disc ? disc : f->disc); SFLOCK(f,0); } /* can't switch discipline at this time */ if(rv <= 0) goto done; } } /* save old readf, writef, and seekf to see if stream need reinit */ #define GETDISCF(func,iof,type) \ { for(d = f->disc; d && !d->iof; d = d->disc) ; \ func = d ? d->iof : NIL(type); \ } GETDISCF(oreadf,readf,Sfread_f); GETDISCF(owritef,writef,Sfwrite_f); GETDISCF(oseekf,seekf,Sfseek_f); if(disc == SF_POPDISC) { /* popping, warn the being popped discipline */ if(!(d = f->disc) ) goto done; disc = d->disc; if(d->exceptf) { SFOPEN(f,0); if((*(d->exceptf))(f,SF_DPOP,(Void_t*)disc,d) < 0 ) goto done; SFLOCK(f,0); } f->disc = disc; rdisc = d; } else { /* pushing, warn being pushed discipline */ do { /* loop to handle the case where d may pop itself */ d = f->disc; if(d && d->exceptf) { SFOPEN(f,0); if( (*(d->exceptf))(f,SF_DPUSH,(Void_t*)disc,d) < 0 ) goto done; SFLOCK(f,0); } } while(d != f->disc); /* make sure we are not creating an infinite loop */ for(; d; d = d->disc) if(d == disc) goto done; /* set new disc */ disc->disc = f->disc; f->disc = disc; rdisc = disc; } if(!(f->flags&SF_STRING) ) { /* this stream may have to be reinitialized */ reg int reinit = 0; #define DISCF(dst,iof,type) (dst ? dst->iof : NIL(type)) #define REINIT(oiof,iof,type) \ if(!reinit) \ { for(d = f->disc; d && !d->iof; d = d->disc) ; \ if(DISCF(d,iof,type) != oiof) \ reinit = 1; \ } REINIT(oreadf,readf,Sfread_f); REINIT(owritef,writef,Sfwrite_f); REINIT(oseekf,seekf,Sfseek_f); if(reinit) { SETLOCAL(f); f->bits &= ~SF_NULL; /* turn off /dev/null handling */ if((f->bits&SF_MMAP) || (f->mode&SF_INIT)) sfsetbuf(f,NIL(Void_t*),(size_t)SF_UNBOUND); else if(f->data == f->tiny) sfsetbuf(f,NIL(Void_t*),0); else { int flags = f->flags; sfsetbuf(f,(Void_t*)f->data,f->size); f->flags |= (flags&SF_MALLOC); } } } done : SFOPEN(f,0); SFMTXRETURN(f, rdisc); } oreadf,readf,Sfread_f); REINIT(owritef,writef,Sfwrite_f); REINIT(oseekf,seekf,Sfseek_f); if(reinit) { SETLOCAL(f); f->bits &= ~SF_NULL; /* turn off /dev/null handling */ if((f->bits&SF_MMAP) || (f->mode&SF_INIT)) sfsetbuf(f,NIsrc/lib/sfio/sfclrlock.c000644 151361 151361 00000001431 07432261522 015155 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Function to clear a locked stream. ** This is useful for programs that longjmp from the mid of an sfio function. ** There is no guarantee on data integrity in such a case. ** ** Written by Kiem-Phong Vo */ #if __STD_C int sfclrlock(reg Sfio_t* f) #else int sfclrlock(f) reg Sfio_t *f; #endif { int rv; /* already closed */ if(f && (f->mode&SF_AVAIL)) return 0; SFMTXSTART(f,0); /* clear error bits */ f->flags &= ~(SF_ERROR|SF_EOF); /* clear peek locks */ if(f->mode&SF_PKRD) { f->here -= f->endb-f->next; f->endb = f->next; } SFCLRBITS(f); /* throw away all lock bits except for stacking state SF_PUSH */ f->mode &= (SF_RDWR|SF_INIT|SF_POOL|SF_PUSH|SF_SYNCED|SF_STDIO); rv = (f->mode&SF_PUSH) ? 0 : (f->flags&SF_FLAGS); SFMTXRETURN(f, rv); } fclrlock(f) reg Sfio_t *f; #endif { int rv; /* already closed */ if(f && (f->mode&SF_AVAIL)) return 0; SFMTXSTART(f,0); /* clear error bits */ f->flags &= ~(SF_ERROR|SF_EOF); /* clear peek locks */ if(f->mode&SF_PKRD)src/lib/sfio/sfsize.c000644 151361 151361 00000003275 07432261526 014512 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Get the size of a stream. ** ** Written by Kiem-Phong Vo. */ #if __STD_C Sfoff_t sfsize(reg Sfio_t* f) #else Sfoff_t sfsize(f) reg Sfio_t* f; #endif { Sfdisc_t* disc; reg int mode; Sfoff_t s; SFMTXSTART(f, (Sfoff_t)(-1)); if((mode = f->mode&SF_RDWR) != (int)f->mode && _sfmode(f,mode,0) < 0) SFMTXRETURN(f, (Sfoff_t)(-1)); if(f->flags&SF_STRING) { SFSTRSIZE(f); SFMTXRETURN(f, f->extent); } SFLOCK(f,0); s = f->here; if(f->extent >= 0) { if(f->flags&(SF_SHARE|SF_APPENDWR)) { for(disc = f->disc; disc; disc = disc->disc) if(disc->seekf) break; if(!_sys_stat || disc) { Sfoff_t e; if((e = SFSK(f,0,SEEK_END,disc)) >= 0) f->extent = e; if(SFSK(f,f->here,SEEK_SET,disc) != f->here) f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,disc); } #if _sys_stat else { sfstat_t st; if(fstat(f->file,&st) < 0) f->extent = -1; else if((f->extent = st.st_size) < f->here) f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,disc); } #endif } if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC)) f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,f->disc); } if(f->here != s && (f->mode&SF_READ) ) { /* buffered data is known to be invalid */ #ifdef MAP_TYPE if((f->bits&SF_MMAP) && f->data) { SFMUNMAP(f,f->data,f->endb-f->data); f->data = NIL(uchar*); } #endif f->next = f->endb = f->endr = f->endw = f->data; } if(f->here < 0) f->extent = -1; else if(f->extent < f->here) f->extent = f->here; if((s = f->extent) >= 0) { if(f->flags&SF_APPENDWR) s += (f->next - f->data); else if(f->mode&SF_WRITE) { s = f->here + (f->next - f->data); if(s < f->extent) s = f->extent; } } SFOPEN(f,0); SFMTXRETURN(f, s); } d */ #ifdef MAP_TYPE if((f->bits&SF_MMAP) && f->data) { SFMUNMAP(f,f->data,f->endb-f->data); f->data = NIL(uchar*); } #endif f->next = f->endb = f->endr = f->endw = f->data; } if(f->here < 0) f->extent = -1; else if(f->extent < f->here) f->extent = f->here; if((s = f->extent) >= 0) { if(f->flags&SF_Asrc/lib/sfio/Makestate.sh000755 151361 151361 00000000203 07001670326 015276 0ustar00kpvkpv000000 000000 if test "`cat Make.state`" != "$1" then rm *.o Stdio_b/*.o Stdio_s/*.o Sfio_f/*.o fi >/dev/null 2>&1 echo "$1" > Make.state exit 0 = f->extent; } } SFOPEN(f,0); SFMTXRETURN(f, s); } d */ #ifdef MAP_TYPE if((f->bits&SF_MMAP) && f->data) { SFMUNMAP(f,f->data,f->endb-f->data); f->data = NIL(uchar*); } #endif f->next = f->endb = f->endr = f->endw = f->data; } if(f->here < 0) f->extent = -1; el36A V=PAx<|Tg)<|Tg)@src/lib/sfio/sfstrtof.c000644 151361 151361 00000017401 07436547171 015064 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* * AT&T Labs Research * Glenn Fowler & Phong Vo * * common header and implementation for * * strtof strtod strtold _sfscand * * define these macros to instantiate an implementation: * * S2F_function the function name * S2F_static 1 if S2F_function is static * S2F_type 0:float 1:double 2:long.double * S2F_scan 1 for alternate interface with these arguments: * void* handle * int (*getchar)(void* handle) * exactly one extra (*getchar)() is done, i.e., * the caller must do the pushback */ /* for Sfio, we'll define the function _sfdscan() here. This helps with ** debugging on systems whose debuggers can't handle #include code. */ #if !defined(S2F_function) #define S2F_function _sfdscan #define S2F_static 0 #define S2F_type 2 #define S2F_scan 1 #endif #if S2F_type == 2 && _ast_fltmax_double #undef S2F_type #define S2F_type 1 #endif #if S2F_type == 0 #define S2F_number float #define S2F_ldexp ldexp #define S2F_pow10 _Sffpow10 #define S2F_huge _Sffhuge #define S2F_min (FLT_MIN) #define S2F_max (FLT_MAX) #define S2F_exp_10_min (FLT_MIN_10_EXP) #define S2F_exp_10_max (FLT_MAX_10_EXP) #define S2F_exp_2_min (FLT_MIN_EXP) #define S2F_exp_2_max (FLT_MAX_EXP) #endif #if S2F_type == 1 #define S2F_number double #define S2F_ldexp ldexp #define S2F_pow10 _Sfdpow10 #define S2F_huge _Sfdhuge #define S2F_min (DBL_MIN) #define S2F_max (DBL_MAX) #define S2F_exp_10_min (DBL_MIN_10_EXP) #define S2F_exp_10_max (DBL_MAX_10_EXP) #define S2F_exp_2_min (DBL_MIN_EXP) #define S2F_exp_2_max (DBL_MAX_EXP) #endif #if S2F_type == 2 #define S2F_number long double #define S2F_ldexp ldexpl #define S2F_pow10 _Sflpow10 #define S2F_huge _Sflhuge #define S2F_min (LDBL_MIN) #define S2F_max (LDBL_MAX) #define S2F_exp_10_min (LDBL_MIN_10_EXP) #define S2F_exp_10_max (LDBL_MAX_10_EXP) #define S2F_exp_2_min (LDBL_MIN_EXP) #define S2F_exp_2_max (LDBL_MAX_EXP) #endif #if -S2F_exp_10_min < S2F_exp_10_max #define S2F_exp_10_abs (-S2F_exp_10_min) #else #define S2F_exp_10_abs S2F_exp_10_max #endif #define S2F_batch _ast_flt_unsigned_max_t #if S2F_scan typedef int (*S2F_get_f)_ARG_((void*)); #define ERR(e) #define GET(p) (*get)(p) #define PUT(p) #define SET(p,t) #else #define ERR(e) (errno=(e)) #define GET(p) (*p++) #define PUT(p) (end?(*end=(char*)p-1):(char*)0) #define SET(p,t) (t=p) #endif typedef struct S2F_part_s { S2F_batch batch; int digits; } S2F_part_t; #ifndef ERANGE #define ERANGE EINVAL #endif #if S2F_static static #else #if defined(__EXPORT__) #define extern __EXPORT__ #endif extern #undef extern #endif S2F_number #if S2F_scan #if __STD_C S2F_function(void* s, S2F_get_f get) #else S2F_function(s, get) void* s; S2F_get_f get; #endif #else #if __STD_C S2F_function(const char* str, char** end) #else S2F_function(str, end) char* str; char** end; #endif #endif { #if !S2F_scan register unsigned char* s = (unsigned char*)str; unsigned char* t; #endif register S2F_batch n; register int c; register int digits; register int m; register unsigned char* cv; int negative; int enegative; int fraction; int decimal = 0; int thousand = 0; int part = 0; S2F_number v; S2F_number p; S2F_part_t parts[16]; /* * radix char and thousands separator are locale specific */ SFSETLOCALE(&decimal, &thousand); SFCVINIT(); /* * skip initial blanks */ do c = GET(s); while (isspace(c)); SET(s, t); /* * get the sign */ if ((negative = (c == '-')) || c == '+') c = GET(s); /* * drop leading 0's */ digits = 0; fraction = -1; if (c == '0') { c = GET(s); if (c == 'x' || c == 'X') { /* * hex floating point -- easy */ cv = _Sfcv36; v = 0; for (;;) { c = GET(s); if ((part = cv[c]) < 16) { digits++; v *= 16; v += part; } else if (c == decimal) { decimal = -1; fraction = digits; } else break; } m = 0; if (c == 'p' || c == 'P') { c = GET(s); if ((enegative = c == '-') || c == '+') c = GET(s); while (c >= '0' && c <= '9') { m = (m << 3) + (m << 1) + (c - '0'); c = GET(s); } if (enegative) m = -m; } /* * consume the optional suffix */ switch (c) { case 'f': case 'F': case 'l': case 'L': c = GET(s); break; } PUT(s); if (v == 0) return v; if (fraction >= 0) m -= 4 * (digits - fraction); if (m < S2F_exp_2_min) { if ((m -= S2F_exp_2_min) < S2F_exp_2_min) { ERR(ERANGE); return 0; } v = S2F_ldexp(v, S2F_exp_2_min); } else if (m > S2F_exp_2_max) { ERR(ERANGE); return negative ? -S2F_huge : S2F_huge; } v = S2F_ldexp(v, m); goto check; } while (c == '0') c = GET(s); } else if (c == decimal) { decimal = -1; fraction = 0; for (;;) { c = GET(s); if (c != '0') break; digits++; } } else if (c == 'i' || c == 'I') { if ((c = GET(s)) != 'n' && c != 'N' || (c = GET(s)) != 'f' && c != 'F') { PUT(t); return 0; } c = GET(s); SET(s, t); if (((c) == 'i' || c == 'I') && ((c = GET(s)) == 'n' || c == 'N') && ((c = GET(s)) == 'i' || c == 'I') && ((c = GET(s)) == 't' || c == 'T') && ((c = GET(s)) == 'y' || c == 'Y')) { c = GET(s); SET(s, t); } PUT(t); return negative ? -S2F_huge : S2F_huge; } else if (c == 'n' || c == 'N') { if ((c = GET(s)) != 'a' && c != 'A' || (c = GET(s)) != 'n' && c != 'N') { PUT(t); return 0; } do c = GET(s); while (c && !isspace(c)); PUT(s); return negative ? -S2F_huge : S2F_huge; } else if (c < '1' || c > '9') { PUT(t); #if S2F_scan /* KPV: this returns an indicator that no number was specified */ *((int*)s) = 1; #endif return 0; } /* * consume the integral and fractional parts */ n = 0; m = 0; for (;;) { if (c >= '0' && c <= '9') { digits++; n = (n << 3) + (n << 1) + (c - '0'); if (n >= ((~((S2F_batch)0)) / 10) && part < sizeof(parts)/sizeof(parts[0]) ) { parts[part].batch = n; n = 0; parts[part].digits = digits; part++; } } else if (m && (digits - m) != 3) break; else if (c == decimal) { decimal = -1; m = 0; fraction = digits; } else if (c != thousand) break; else if (!(m = digits)) break; c = GET(s); } /* * don't forget the last part */ if (n && part < sizeof(parts)/sizeof(parts[0]) ) { parts[part].batch = n; parts[part].digits = digits; part++; } /* * consume the exponent */ if (fraction >= 0) digits = fraction; if (c == 'e' || c == 'E') { c = GET(s); if ((enegative = (c == '-')) || c == '+') c = GET(s); n = 0; while (c >= '0' && c <= '9') { n = (n << 3) + (n << 1) + (c - '0'); c = GET(s); } if (enegative) digits -= n; else digits += n; } /* * consume the optional suffix */ switch (c) { case 'f': case 'F': case 'l': case 'L': c = GET(s); break; } PUT(s); /* * adjust for at most one multiply per part * and at most one divide overall */ if (!part) return 0; else if ((m = parts[part-1].digits - digits) > 0) digits += m; else m = 0; /* * combine the parts */ v = 0; while (part--) { p = parts[part].batch; c = digits - parts[part].digits; if (c > S2F_exp_10_max) { ERR(ERANGE); v = S2F_huge; break; } if (c > 0) { #if _ast_mpy_overflow_fpe if ((S2F_max / p) < S2F_pow10[c]) { ERR(ERANGE); return negative ? -S2F_huge : S2F_huge; } #endif p *= S2F_pow10[c]; } v += p; } if (m) { while (m > S2F_exp_10_max) { m -= S2F_exp_10_max; v /= S2F_pow10[S2F_exp_10_max]; } v /= S2F_pow10[m]; } /* * check the range */ check: if (v < S2F_min) { ERR(ERANGE); v = 0; } else if (v > S2F_max) { ERR(ERANGE); v = S2F_huge; } /* * done */ return negative ? -v : v; } { #if _ast_mpy_overflow_fpe if ((S2F_max / p) < S2F_pow10[c]) { ERR(ERANGE); return negative ? -S2F_huge : S2F_huge; } #endif p *= S2F_pow10[c]; } v += p; } if (m) { while (m > S2F_exp_10_max) { m -= S2F_exp_10_max; src/lib/sfio/sfungetc.c000644 151361 151361 00000003231 07432261527 015016 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Push back one byte to a given SF_READ stream ** ** Written by Kiem-Phong Vo. */ #if __STD_C static int _uexcept(reg Sfio_t* f, reg int type, Void_t* val, reg Sfdisc_t* disc) #else static int _uexcept(f,type,val,disc) reg Sfio_t *f; reg int type; Void_t* val; reg Sfdisc_t *disc; #endif { NOTUSED(val); /* hmm! This should never happen */ if(disc != _Sfudisc) return -1; /* close the unget stream */ if(type != SF_CLOSING) (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*))); return 1; } #if __STD_C int sfungetc(reg Sfio_t* f, reg int c) #else int sfungetc(f,c) reg Sfio_t* f; /* push back one byte to this stream */ reg int c; /* the value to be pushed back */ #endif { reg Sfio_t* uf; SFMTXSTART(f, -1) if(c < 0 || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)) SFMTXRETURN(f, -1); SFLOCK(f,0); /* fast handling of the typical unget */ if(f->next > f->data && f->next[-1] == (uchar)c) { f->next -= 1; goto done; } /* make a string stream for unget characters */ if(f->disc != _Sfudisc) { if(!(uf = sfnew(NIL(Sfio_t*),NIL(char*),(size_t)SF_UNBOUND, -1,SF_STRING|SF_READ))) { c = -1; goto done; } _Sfudisc->exceptf = _uexcept; sfdisc(uf,_Sfudisc); SFOPEN(f,0); (void)sfstack(f,uf); SFLOCK(f,0); } /* space for data */ if(f->next == f->data) { reg uchar* data; if(f->size < 0) f->size = 0; if(!(data = (uchar*)malloc(f->size+16))) { c = -1; goto done; } f->flags |= SF_MALLOC; if(f->data) memcpy((char*)(data+16),(char*)f->data,f->size); f->size += 16; f->data = data; f->next = data+16; f->endb = data+f->size; } *--f->next = (uchar)c; done: SFOPEN(f,0); SFMTXRETURN(f, c); } eptf = _uexcept; sfdisc(uf,_Sfudisc); SFOPEN(f,0); (void)sfstack(f,uf); SFLOCK(f,0); } /* space for data */ if(f->next == f->data) { reg uchar* data; if(f->size < 0) f->size = 0; if(!(data = (uchar*)malloc(f->size+16))) { c = -1; goto done; } f->flags |= SF_MALLOC; if(f->data) memcpy((char*)(data+16),(char*)f->data,f->size); src/lib/sfio/sfextern.c000644 151361 151361 00000003764 07432261522 015044 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* External variables and functions used only by Sfio ** Written by Kiem-Phong Vo */ /* code to initialize mutexes */ static Vtmutex_t Sfmutex; static Vtonce_t Sfonce = VTONCE_INITDATA; static void _sfoncef() { vtmtxopen(_Sfmutex, VT_INIT); vtmtxopen(&_Sfpool.mutex, VT_INIT); vtmtxopen(sfstdin->mutex, VT_INIT); vtmtxopen(sfstdout->mutex, VT_INIT); vtmtxopen(sfstderr->mutex, VT_INIT); _Sfdone = 1; } /* global variables used internally to the package */ Sfextern_t _Sfextern = { 0, /* _Sfpage */ { NIL(Sfpool_t*), 0, 0, 0, NIL(Sfio_t**) }, /* _Sfpool */ NIL(int(*)_ARG_((Sfio_t*,int))), /* _Sfpmove */ NIL(Sfio_t*(*)_ARG_((Sfio_t*, Sfio_t*))), /* _Sfstack */ NIL(void(*)_ARG_((Sfio_t*, int, int))), /* _Sfnotify */ NIL(int(*)_ARG_((Sfio_t*))), /* _Sfstdsync */ { NIL(Sfread_f), /* _Sfudisc */ NIL(Sfwrite_f), NIL(Sfseek_f), NIL(Sfexcept_f), NIL(Sfdisc_t*) }, NIL(void(*)_ARG_((void)) ), /* _Sfcleanup */ 0, /* _Sfexiting */ 0, /* _Sfdone */ &Sfonce, /* _Sfonce */ _sfoncef, /* _Sfoncef */ &Sfmutex /* _Sfmutex */ }; /* accessible to application code for a few fast macro functions */ ssize_t _Sfi = -1; #if vt_threaded static Vtmutex_t _Sfmtxin, _Sfmtxout, _Sfmtxerr; #define SFMTXIN (&_Sfmtxin) #define SFMTXOUT (&_Sfmtxout) #define SFMTXERR (&_Sfmtxerr) #else #define SFMTXIN (0) #define SFMTXOUT (0) #define SFMTXERR (0) #endif Sfio_t _Sfstdin = SFNEW(NIL(char*),-1,0, (SF_READ |SF_STATIC|SF_MTSAFE),NIL(Sfdisc_t*),SFMTXIN); Sfio_t _Sfstdout = SFNEW(NIL(char*),-1,1, (SF_WRITE|SF_STATIC|SF_MTSAFE),NIL(Sfdisc_t*),SFMTXOUT); Sfio_t _Sfstderr = SFNEW(NIL(char*),-1,2, (SF_WRITE|SF_STATIC|SF_MTSAFE),NIL(Sfdisc_t*),SFMTXERR); Sfio_t* sfstdin = &_Sfstdin; Sfio_t* sfstdout = &_Sfstdout; Sfio_t* sfstderr = &_Sfstderr; __EXTERN__(ssize_t,_Sfi); __EXTERN__(Sfio_t,_Sfstdin); __EXTERN__(Sfio_t,_Sfstdout); __EXTERN__(Sfio_t,_Sfstderr); __EXTERN__(Sfio_t*,sfstdin); __EXTERN__(Sfio_t*,sfstdout); __EXTERN__(Sfio_t*,sfstderr); XIN); Sfio_tsrc/lib/sfio/sfexcept.c000644 151361 151361 00000004640 07432261522 015021 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Function to handle io exceptions. ** Written by Kiem-Phong Vo */ #if __STD_C int _sfexcept(Sfio_t* f, int type, ssize_t io, Sfdisc_t* disc) #else int _sfexcept(f,type,io,disc) Sfio_t* f; /* stream where the exception happened */ int type; /* io type that was performed */ ssize_t io; /* the io return value that indicated exception */ Sfdisc_t* disc; /* discipline in use */ #endif { reg int ev, local, lock; reg ssize_t size; reg uchar* data; SFMTXSTART(f,-1); GETLOCAL(f,local); lock = f->mode&SF_LOCK; if(local && io <= 0) f->flags |= io < 0 ? SF_ERROR : SF_EOF; if(disc && disc->exceptf) { /* let the stream be generally accessible for this duration */ if(local && lock) SFOPEN(f,0); /* so that exception handler knows what we are asking for */ _Sfi = f->val = io; ev = (*(disc->exceptf))(f,type,&io,disc); /* relock if necessary */ if(local && lock) SFLOCK(f,0); if(io > 0 && !(f->flags&SF_STRING) ) SFMTXRETURN(f, ev); if(ev < 0) SFMTXRETURN(f, SF_EDONE); if(ev > 0) SFMTXRETURN(f, SF_EDISC); } if(f->flags&SF_STRING) { if(type == SF_READ) goto chk_stack; else if(type != SF_WRITE && type != SF_SEEK) SFMTXRETURN(f, SF_EDONE); if(local && io >= 0) { if(f->size >= 0 && !(f->flags&SF_MALLOC)) goto chk_stack; /* extend buffer */ if((size = f->size) < 0) size = 0; if((io -= size) <= 0) io = SF_GRAIN; size = ((size+io+SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN; if(f->size > 0) data = (uchar*)realloc((char*)f->data,size); else data = (uchar*)malloc(size); if(!data) goto chk_stack; f->endb = data + size; f->next = data + (f->next - f->data); f->endr = f->endw = f->data = data; f->size = size; } SFMTXRETURN(f, SF_EDISC); } if(errno == EINTR) { if(_Sfexiting || (f->bits&SF_ENDING)) /* stop being a hero */ SFMTXRETURN(f, SF_EDONE); /* a normal interrupt, we can continue */ errno = 0; f->flags &= ~(SF_EOF|SF_ERROR); SFMTXRETURN(f, SF_ECONT); } chk_stack: if(local && f->push && ((type == SF_READ && f->next >= f->endb) || (type == SF_WRITE && f->next <= f->data))) { /* pop the stack */ reg Sfio_t *pf; if(lock) SFOPEN(f,0); /* pop and close */ pf = (*_Sfstack)(f,NIL(Sfio_t*)); if((ev = sfclose(pf)) < 0) /* can't close, restack */ (*_Sfstack)(f,pf); if(lock) SFLOCK(f,0); ev = ev < 0 ? SF_EDONE : SF_ESTACK; } else ev = SF_EDONE; SFMTXRETURN(f, ev); } ags &= ~(SF_EOF|SF_ERROR); SFMTXRETURN(f, SF_ECONT); } chk_stack: if(local && f->push && src/lib/sfio/sfpkrd.c000644 151361 151361 00000011610 07432261524 014466 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #if !_PACKAGE_ast #ifndef FIONREAD #if _sys_ioctl #include #endif #endif #endif /* Read/Peek a record from an unseekable device ** ** Written by Kiem-Phong Vo. */ #define STREAM_PEEK 001 #define SOCKET_PEEK 002 #if __STD_C ssize_t sfpkrd(int fd, Void_t* argbuf, size_t n, int rc, long tm, int action) #else ssize_t sfpkrd(fd, argbuf, n, rc, tm, action) int fd; /* file descriptor */ Void_t* argbuf; /* buffer to read data */ size_t n; /* buffer size */ int rc; /* record character */ long tm; /* time-out */ int action; /* >0: peeking, if rc>=0, get action records, <0: no peeking, if rc>=0, get -action records, =0: no peeking, if rc>=0, must get a single record */ #endif { reg ssize_t r; reg int ntry, t; reg char *buf = (char*)argbuf, *endbuf; if(rc < 0 && tm < 0 && action <= 0) return read(fd,buf,n); t = (action > 0 || rc >= 0) ? (STREAM_PEEK|SOCKET_PEEK) : 0; #if !_stream_peek t &= ~STREAM_PEEK; #endif #if !_socket_peek t &= ~SOCKET_PEEK; #endif for(ntry = 0; ntry < 2; ++ntry) { r = -1; #if _stream_peek if((t&STREAM_PEEK) && (ntry == 1 || tm < 0) ) { struct strpeek pbuf; pbuf.flags = 0; pbuf.ctlbuf.maxlen = -1; pbuf.ctlbuf.len = 0; pbuf.ctlbuf.buf = NIL(char*); pbuf.databuf.maxlen = n; pbuf.databuf.buf = buf; pbuf.databuf.len = 0; if((r = ioctl(fd,I_PEEK,&pbuf)) < 0) { if(errno == EINTR) return -1; t &= ~STREAM_PEEK; } else { t &= ~SOCKET_PEEK; if(r > 0 && (r = pbuf.databuf.len) <= 0) { if(action <= 0) /* read past eof */ r = read(fd,buf,1); return r; } if(r == 0) r = -1; else if(r > 0) break; } } #endif /* stream_peek */ if(ntry == 1) break; /* poll or select to see if data is present. */ while(tm >= 0 || action > 0 || /* block until there is data before peeking again */ ((t&STREAM_PEEK) && rc >= 0) || /* let select be interrupted instead of recv which autoresumes */ (t&SOCKET_PEEK) ) { r = -2; #if _lib_poll if(r == -2) { struct pollfd po; po.fd = fd; po.events = POLLIN; po.revents = 0; if((r = SFPOLL(&po,1,tm)) < 0) { if(errno == EINTR) return -1; else if(errno == EAGAIN) { errno = 0; continue; } else r = -2; } else r = (po.revents&POLLIN) ? 1 : -1; } #endif /*_lib_poll*/ #if _lib_select if(r == -2) { #if _hpux_threads && vt_threaded #define fd_set int #endif fd_set rd; struct timeval tmb, *tmp; FD_ZERO(&rd); FD_SET(fd,&rd); if(tm < 0) tmp = NIL(struct timeval*); else { tmp = &tmb; tmb.tv_sec = tm/SECOND; tmb.tv_usec = (tm%SECOND)*SECOND; } r = select(fd+1,&rd,NIL(fd_set*),NIL(fd_set*),tmp); if(r < 0) { if(errno == EINTR) return -1; else if(errno == EAGAIN) { errno = 0; continue; } else r = -2; } else r = FD_ISSET(fd,&rd) ? 1 : -1; } #endif /*_lib_select*/ if(r == -2) { #if !_lib_poll && !_lib_select /* both poll and select cann't be used */ #ifdef FIONREAD /* quick and dirty check for availability */ long nsec = tm < 0 ? 0 : (tm+999)/1000; while(nsec > 0 && r < 0) { long avail = -1; if((r = ioctl(fd,FIONREAD,&avail)) < 0) { if(errno == EINTR) return -1; else if(errno == EAGAIN) { errno = 0; continue; } else /* ioctl failed completely */ { r = -2; break; } } else r = avail <= 0 ? -1 : (ssize_t)avail; if(r < 0 && nsec-- > 0) sleep(1); } #endif #endif } if(r > 0) /* there is data now */ { if(action <= 0 && rc < 0) return read(fd,buf,n); else r = -1; } else if(tm >= 0) /* timeout exceeded */ return -1; else r = -1; break; } #if _socket_peek if(t&SOCKET_PEEK) { while((r = recv(fd,(char*)buf,n,MSG_PEEK)) < 0) { if(errno == EINTR) return -1; else if(errno == EAGAIN) { errno = 0; continue; } t &= ~SOCKET_PEEK; break; } if(r >= 0) { t &= ~STREAM_PEEK; if(r > 0) break; else /* read past eof */ { if(action <= 0) r = read(fd,buf,1); return r; } } } #endif } if(r < 0) { if(tm >= 0 || action > 0) return -1; else /* get here means: tm < 0 && action <= 0 && rc >= 0 */ { /* number of records read at a time */ if((action = action ? -action : 1) > (int)n) action = n; r = 0; while((t = read(fd,buf,action)) > 0) { r += t; for(endbuf = buf+t; buf < endbuf;) if(*buf++ == rc) action -= 1; if(action == 0 || (int)(n-r) < action) break; } return r == 0 ? t : r; } } /* successful peek, find the record end */ if(rc >= 0) { reg char* sp; t = action == 0 ? 1 : action < 0 ? -action : action; for(endbuf = (sp = buf)+r; sp < endbuf; ) if(*sp++ == rc) if((t -= 1) == 0) break; r = sp - buf; } /* advance */ if(action <= 0) r = read(fd,buf,r); return r; } n)) > 0) { r += t; for(endbuf = buf+t; buf < endbuf;) if(*buf++ == rc) action -= 1; if(action == 0src/lib/sfio/sfsetbuf.c000644 151361 151361 00000016664 07432261526 015036 0ustar00kpvkpv000000 000000 #if defined(__STDPP__directive) && defined(__STDPP__hide) __STDPP__directive pragma pp:hide getpagesize #else #define getpagesize ______getpagesize #endif #include "sfhdr.h" #if defined(__STDPP__directive) && defined(__STDPP__hide) __STDPP__directive pragma pp:nohide getpagesize #else #undef getpagesize #endif #if _lib_getpagesize _BEGIN_EXTERNS_ extern int getpagesize _ARG_((void)); _END_EXTERNS_ #endif /* Set a (new) buffer for a stream. ** If size < 0, it is assigned a suitable value depending on the ** kind of stream. The actual buffer size allocated is dependent ** on how much memory is available. ** ** Written by Kiem-Phong Vo. */ #if !_sys_stat struct stat { int st_mode; int st_size; }; #define fstat(fd,st) (-1) #endif /*_sys_stat*/ #if __STD_C Void_t* sfsetbuf(reg Sfio_t* f, reg Void_t* buf, reg size_t size) #else Void_t* sfsetbuf(f,buf,size) reg Sfio_t* f; /* stream to be buffered */ reg Void_t* buf; /* new buffer */ reg size_t size; /* buffer size, -1 for default size */ #endif { reg int sf_malloc; reg uchar* obuf; reg Sfdisc_t* disc; reg ssize_t osize, blksize; reg int oflags, init, okmmap, local; sfstat_t st; SFONCE(); SFMTXSTART(f,NIL(Void_t*)); GETLOCAL(f,local); if(size == 0 && buf) { /* special case to get buffer info */ _Sfi = f->val = (f->bits&SF_MMAP) ? (f->endb-f->data) : f->size; SFMTXRETURN(f, (Void_t*)f->data); } /* cleanup actions already done, don't allow write buffering any more */ if(_Sfexiting && !(f->flags&SF_STRING) && (f->mode&SF_WRITE)) { buf = NIL(Void_t*); size = 0; } if((init = f->mode&SF_INIT) ) { if(!f->pool && _sfsetpool(f) < 0) SFMTXRETURN(f, NIL(Void_t*)); } else if((f->mode&SF_RDWR) != SFMODE(f,local) && _sfmode(f,0,local) < 0) SFMTXRETURN(f, NIL(Void_t*)); if(init) f->mode = (f->mode&SF_RDWR)|SF_LOCK; else { int rv; /* make sure there is no hidden read data */ if(f->proc && (f->flags&SF_READ) && (f->mode&SF_WRITE) && _sfmode(f,SF_READ,local) < 0) SFMTXRETURN(f, NIL(Void_t*)); /* synchronize first */ SFLOCK(f,local); rv = SFSYNC(f); SFOPEN(f,local); if(rv < 0) SFMTXRETURN(f, NIL(Void_t*)); /* turn off the SF_SYNCED bit because buffer is changing */ f->mode &= ~SF_SYNCED; } SFLOCK(f,local); blksize = 0; oflags = f->flags; /* see if memory mapping is possible (see sfwrite for SF_BOTH) */ okmmap = (buf || (f->flags&SF_STRING) || (f->flags&SF_RDWR) == SF_RDWR) ? 0 : 1; /* save old buffer info */ #ifdef MAP_TYPE if(f->bits&SF_MMAP) { if(f->data) { SFMUNMAP(f,f->data,f->endb-f->data); f->data = NIL(uchar*); } } else #endif if(f->data == f->tiny) { f->data = NIL(uchar*); f->size = 0; } obuf = f->data; osize = f->size; f->flags &= ~SF_MALLOC; f->bits &= ~SF_MMAP; /* pure read/string streams must have a valid string */ if((f->flags&(SF_RDWR|SF_STRING)) == SF_RDSTR && (size == (size_t)SF_UNBOUND || !buf)) size = 0; /* set disc to the first discipline with a seekf */ for(disc = f->disc; disc; disc = disc->disc) if(disc->seekf) break; if((init || local) && !(f->flags&SF_STRING)) { /* ASSERT(f->file >= 0) */ st.st_mode = 0; /* if has discipline, set size by discipline if possible */ if(!_sys_stat || disc) { if((f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,disc)) < 0) goto unseekable; else { Sfoff_t e; if((e = SFSK(f,(Sfoff_t)0,SEEK_END,disc)) >= 0) f->extent = e > f->here ? e : f->here; (void)SFSK(f,f->here,SEEK_SET,disc); goto setbuf; } } /* get file descriptor status */ if(fstat((int)f->file,&st) < 0) f->here = -1; else { #if _sys_stat && _stat_blksize /* preferred io block size */ if((blksize = (ssize_t)st.st_blksize) > 0) while((blksize + (ssize_t)st.st_blksize) <= SF_PAGE) blksize += (ssize_t)st.st_blksize; #endif if(S_ISDIR(st.st_mode) || (int)st.st_size < SF_GRAIN) okmmap = 0; if(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) f->here = SFSK(f,(Sfoff_t)0,SEEK_CUR,f->disc); else f->here = -1; #if O_TEXT /* no memory mapping with O_TEXT because read()/write() alter data stream */ if(okmmap && f->here >= 0 && (fcntl((int)f->file,F_GETFL,0) & O_TEXT) ) okmmap = 0; #endif } if(f->here >= 0) { f->extent = (Sfoff_t)st.st_size; /* seekable std-devices are share-public by default */ if(f == sfstdin || f == sfstdout || f == sfstderr) f->flags |= SF_SHARE|SF_PUBLIC; } else { unseekable: f->extent = -1; f->here = 0; if(init) { if(S_ISCHR(st.st_mode) ) { int oerrno = errno; blksize = SF_GRAIN; /* set line mode for terminals */ if(!(f->flags&SF_LINE) && isatty(f->file)) f->flags |= SF_LINE; #if _sys_stat else /* special case /dev/null */ { reg int dev, ino; dev = (int)st.st_dev; ino = (int)st.st_ino; if(stat(DEVNULL,&st) >= 0 && dev == (int)st.st_dev && ino == (int)st.st_ino) SFSETNULL(f); } #endif errno = oerrno; } /* initialize side buffer for r+w unseekable streams */ if(!f->proc && (f->bits&SF_BOTH) ) (void)_sfpopen(f,-1,-1,0); } } /* set page size, this is also the desired default buffer size */ if(_Sfpage <= 0) { #if _lib_getpagesize if((_Sfpage = (size_t)getpagesize()) <= 0) #endif _Sfpage = SF_PAGE; } } #ifdef MAP_TYPE if(okmmap && size && (f->mode&SF_READ) && f->extent >= 0 ) { /* see if we can try memory mapping */ if(!disc) for(disc = f->disc; disc; disc = disc->disc) if(disc->readf) break; if(!disc) { f->bits |= SF_MMAP; if(size == (size_t)SF_UNBOUND) { if(blksize > _Sfpage) size = blksize * SF_NMAP; else size = _Sfpage * SF_NMAP; if(size > 256*1024) size = 256*1024; } } } #endif /* get buffer space */ setbuf: if(size == (size_t)SF_UNBOUND) { /* define a default size suitable for block transfer */ if(init && osize > 0) size = osize; else if(f == sfstderr && (f->mode&SF_WRITE)) size = 0; else if(f->flags&SF_STRING ) size = SF_GRAIN; else if((f->flags&SF_READ) && !(f->bits&SF_BOTH) && f->extent > 0 && f->extent < (Sfoff_t)_Sfpage ) size = (((size_t)f->extent + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN; else if((ssize_t)(size = _Sfpage) < blksize) size = blksize; buf = NIL(Void_t*); } sf_malloc = 0; if(size > 0 && !buf && !(f->bits&SF_MMAP)) { /* try to allocate a buffer */ if(obuf && size == (size_t)osize && init) { buf = (Void_t*)obuf; obuf = NIL(uchar*); sf_malloc = (oflags&SF_MALLOC); } if(!buf) { /* do allocation */ while(!buf && size > 0) { if((buf = (Void_t*)malloc(size)) ) break; else size /= 2; } if(size > 0) sf_malloc = SF_MALLOC; } } if(size == 0 && !(f->flags&SF_STRING) && !(f->bits&SF_MMAP) && (f->mode&SF_READ)) { /* use the internal buffer */ size = sizeof(f->tiny); buf = (Void_t*)f->tiny; } /* set up new buffer */ f->size = size; f->next = f->data = f->endr = f->endw = (uchar*)buf; f->endb = (f->mode&SF_READ) ? f->data : f->data+size; if(f->flags&SF_STRING) { /* these fields are used to test actual size - see sfseek() */ f->extent = (!sf_malloc && ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ) ? size : 0; f->here = 0; /* read+string stream should have all data available */ if((f->mode&SF_READ) && !sf_malloc) f->endb = f->data+size; } f->flags = (f->flags & ~SF_MALLOC)|sf_malloc; if(obuf && obuf != f->data && osize > 0 && (oflags&SF_MALLOC)) { free((Void_t*)obuf); obuf = NIL(uchar*); } _Sfi = f->val = obuf ? osize : 0; SFOPEN(f,local); SFMTXRETURN(f, (Void_t*)obuf); } l size - see sfseek() */ f->extent = (!sf_malloc && ((f->flags&SF_src/lib/sfio/sfflsbuf.c000644 151361 151361 00000003601 07432261523 015007 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Write a buffer out to a file descriptor or ** extending a buffer for a SF_STRING stream. ** ** Written by Kiem-Phong Vo */ #if __STD_C int _sfflsbuf(reg Sfio_t* f, reg int c) #else int _sfflsbuf(f,c) reg Sfio_t* f; /* write out the buffered content of this stream */ reg int c; /* if c>=0, c is also written out */ #endif { reg ssize_t n, w; reg uchar* data; uchar outc; reg int local, isall; int inpc = c; SFMTXSTART(f,-1); GETLOCAL(f,local); for(;; f->mode &= ~SF_LOCK) { /* check stream mode */ if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0) SFMTXRETURN(f, -1); SFLOCK(f,local); /* current data extent */ n = f->next - (data = f->data); if(n == (f->endb-data) && (f->flags&SF_STRING)) { /* extend string stream buffer */ (void)SFWR(f,data,1,f->disc); /* !(f->flags&SF_STRING) is required because exception handlers may turn a string stream to a file stream */ if(f->next < f->endb || !(f->flags&SF_STRING) ) n = f->next - (data = f->data); else { SFOPEN(f,local); SFMTXRETURN(f, -1); } } if(c >= 0) { /* write into buffer */ if(n < (f->endb - (data = f->data))) { *f->next++ = c; if(c == '\n' && (f->flags&SF_LINE) && !(f->flags&SF_STRING)) { c = -1; n += 1; } else break; } else if(n == 0) { /* unbuffered io */ outc = (uchar)c; data = &outc; c = -1; n = 1; } } if(n == 0 || (f->flags&SF_STRING)) break; isall = SFISALL(f,isall); if((w = SFWR(f,data,n,f->disc)) > 0) { if((n -= w) > 0) /* save unwritten data, then resume */ memcpy((char*)f->data,(char*)data+w,n); f->next = f->data+n; if(c < 0 && (!isall || n == 0)) break; } else if(w == 0) { SFOPEN(f,local); SFMTXRETURN(f, -1); } else if(c < 0) break; } SFOPEN(f,local); if(inpc < 0) inpc = f->endb-f->next; SFMTXRETURN(f,inpc); } utc; c = -1; n = 1; } } if(n == 0 || (f->flags&SF_STRING)) break; isall = SFISALL(f,isall); if((w = SFWsrc/lib/sfio/sffilbuf.c000644 151361 151361 00000004417 07432261522 015002 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Fill the buffer of a stream with data. ** If n < 0, sffilbuf() attempts to fill the buffer if it's empty. ** If n == 0, if the buffer is not empty, just return the first byte; ** otherwise fill the buffer and return the first byte. ** If n > 0, even if the buffer is not empty, try a read to get as ** close to n as possible. n is reset to -1 if stack pops. ** ** Written by Kiem-Phong Vo */ #if __STD_C int _sffilbuf(Sfio_t* f, reg int n) #else int _sffilbuf(f,n) Sfio_t* f; /* fill the read buffer of this stream */ reg int n; /* see above */ #endif { reg ssize_t r; reg int first, local, rcrv, rc, justseek; SFMTXSTART(f,-1); GETLOCAL(f,local); /* any peek data must be preserved across stacked streams */ rcrv = f->mode&(SF_RC|SF_RV|SF_LOCK); rc = f->getr; justseek = f->bits&SF_JUSTSEEK; f->bits &= ~SF_JUSTSEEK; for(first = 1;; first = 0, (f->mode &= ~SF_LOCK) ) { /* check mode */ if(SFMODE(f,local) != SF_READ && _sfmode(f,SF_READ,local) < 0) SFMTXRETURN(f,-1); SFLOCK(f,local); /* current extent of available data */ if((r = f->endb-f->next) > 0) { /* on first iteration, n is amount beyond current buffer; afterward, n is the exact amount requested */ if((first && n <= 0) || (!first && n <= r) || (f->flags&SF_STRING)) break; /* try shifting left to make room for new data */ if(!(f->bits&SF_MMAP) && f->next > f->data && n > (f->size - (f->endb-f->data)) ) { memcpy(f->data, f->next, r); f->next = f->data; f->endb = f->data + r; } } else if(!(f->flags&SF_STRING) && !(f->bits&SF_MMAP) ) f->next = f->endb = f->endr = f->data; if(f->bits&SF_MMAP) r = n > 0 ? n : f->size; else if(!(f->flags&SF_STRING) ) { r = f->size - (f->endb - f->data); /* available buffer */ if(n > 0) { if(r > n && f->extent < 0 && (f->flags&SF_SHARE) ) r = n; /* read only as much as requested */ else if(justseek && n <= f->iosz && f->iosz <= f->size) r = f->iosz; /* limit buffer filling */ } } /* SFRD takes care of discipline read and stack popping */ f->mode |= rcrv; f->getr = rc; if((r = SFRD(f,f->endb,r,f->disc)) >= 0) { r = f->endb - f->next; break; } } SFOPEN(f,local); rcrv = (n == 0) ? (r > 0 ? (int)(*f->next++) : EOF) : (int)r; SFMTXRETURN(f,rcrv); } { if(r > n && f->extent < 0 && (f->flags&SF_SHARE) ) r = n; /* read only as much as requested */ else if(justseek && n <= f->iosz && f->iosz <= f->size) r = f->iosz; /* limit buffer filling */ } } /* SFRD takes caresrc/lib/sfio/sfllen.c000644 151361 151361 00000000432 07432261524 014460 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Get size of a long value coded in a portable format ** ** Written by Kiem-Phong Vo */ #if __STD_C int _sfllen(Sflong_t v) #else int _sfllen(v) Sflong_t v; #endif { if(v < 0) v = -(v+1); v = (Sfulong_t)v >> SF_SBITS; return 1 + (v > 0 ? sfulen(v) : 0); } > n && f->extent < 0 && (f->flags&SF_SHARE) ) r = n; /* read only as much as requested */ else if(justseek && n <= f->iosz &&36A V=PAx<|Tg)<|Tg)@src/lib/sfio/sfdlen.c000644 151361 151361 00000001106 07436606752 014461 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Return the length of a double value if coded in a portable format ** ** Written by Kiem-Phong Vo */ #if __STD_C int _sfdlen(Sfdouble_t v) #else int _sfdlen(v) Sfdouble_t v; #endif { #define N_ARRAY (16*sizeof(Sfdouble_t)) reg int n, w; Sfdouble_t x; int exp; if(v < 0) v = -v; /* make the magnitude of v < 1 */ if(v != 0.) v = frexpl(v,&exp); else exp = 0; for(w = 1; w <= N_ARRAY; ++w) { /* get 2^SF_PRECIS precision at a time */ n = (int)(x = ldexpl(v,SF_PRECIS)); v = x-n; if(v <= 0.) break; } return 1 + sfulen(exp) + w; } a portable format ** ** Written by Kiem-Phong Vo */ #if __STD_C int _sfdlen(Sfdouble_t v) #else int _sfdlen(v) Sfdouble_t v; #endif { #define N_ARRAY (16*sizeof(Sfdouble_t)) reg int n, w; Sfdouble_t x; int exp; if(v < 0) v = -v; /* make the magnitude of v < 1 */ if(v != 0.) v = frexpl(v,&exp); else exp = 0; for(w = 1; w <= N_ARRAY; ++w) { /* get 2^SF_PRECIS precision at a time */ n = (int)(x = ldexpl(v,SF_PRECIS)); src/lib/sfio/Makefile.nmake000644 151361 151361 00000004501 07037160435 015564 0ustar00kpvkpv000000 000000 /* libsfio.a nmake Makefile ** Written by Kiem-Phong Vo (12/10/90) */ VERSION = 1.0 .SOURCE : Sfio_f Stdio_b Stdio_s Sfio_dc .INCLUDE : Stdio_b ancestor = 2 CCFLAGS = -O SFIO= sfexit.c sfclose.c sfclrlock.c sfcvt.c sfdlen.c sfexcept.c sfextern.c \ sffilbuf.c sfflsbuf.c sfprints.c sfgetd.c sfgetl.c sfgetr.c sfgetu.c \ sfllen.c sfmode.c sfmove.c sfnew.c sfnputc.c sfopen.c sfpeek.c \ sfpool.c sfpopen.c sfprintf.c sfputd.c sfputl.c sfputr.c sfputu.c \ sfpkrd.c sfread.c sfscanf.c sfseek.c sfset.c sfsetbuf.c sfdisc.c \ sfstack.c sfstrtod.c sfsync.c sftable.c sftell.c sftmp.c \ sfungetc.c sfvprintf.c sfvscanf.c sfwrite.c sfnotify.c sfsetfd.c \ sfrd.c sfwr.c sfsk.c sfsize.c sfpurge.c sfpoll.c sfreserve.c \ sfswap.c sfraise.c sfrdwr.c sfmutex.c SFIO_F= _sfclrerr.c _sfdlen.c _sfeof.c _sferror.c _sffileno.c \ _sfgetc.c _sfllen.c _sfputc.c _sfputd.c _sfputl.c _sfputm.c \ _sfputu.c _sfslen.c _sfstacked.c _sfulen.c _sfvalue.c STDIO_S=stdfgetc.c stdfprintf.c stdfputc.c stdfscanf.c stdgetc.c stdgets.c \ stdgetw.c stdopen.c stdprintf.c stdputc.c stdputw.c stdscanf.c \ stdsprintf.c stdvbuf.c stdfopen.c stdfreopen.c stdtmpfile.c stdpopen.c STDIO_B=fclose.c fdopen.c fflush.c fgetc.c fgets.c filbuf.c flsbuf.c \ fopen.c fprintf.c fputc.c fputs.c fread.c freopen.c fscanf.c fseek.c \ ftell.c fwrite.c getc.c getchar.c gets.c getw.c pclose.c popen.c printf.c \ putc.c putchar.c puts.c putw.c rewind.c scanf.c setbuf.c setbuffer.c \ setlinebuf.c setvbuf.c sprintf.c sscanf.c stdextern.c stdstream.c \ tmpfile.c ungetc.c vfprintf.c vfscanf.c vprintf.c vscanf.c vsprintf.c \ vsscanf.c doprnt.c doscan.c fileno.c feof.c ferror.c clearerr.c \ fgetpos.c fsetpos.c cleanup.c snprintf.c vsnprintf.c \ flockfile.c funlockfile.c ftrylockfile.c SFIO_DC=sfdcdio.c sfdcdos.c sfdcfilter.c sfdchdr.h sfdclzw.c sfdcseekable.c \ sfdcslow.c sfdcsubstream.c sfdctee.c sfdcunion.c sfio $(VERSION) :LIBRARY: $(SFIO) $(SFIO_F) $(STDIO_S) $(SFIO_DC) stdio $(VERSION) :LIBRARY: $(STDIO_B) ast_common.h : features/common iffe - run features/common > ast_common.h sfstdgen : sfstdio.c $(CC) -I. $(*) -o sfstdgen sfstdhdr.h : Stdio_b/sfstdhdr.sh $(CC) sfstdio.h : sfstdgen $(*) > $(<) rm sfstdgen sfstdhdr.h $(INCLUDEDIR):INSTALLDIR: sfio.h $(INCLUDEDIR)/stdio.h : .DONTCARE $(INCLUDEDIR):INSTALLDIR: stdio.h test -f Stdio_b/sfstdhdr.h && cp $(*) $(<) || true eam.c sfdctee.c sfdcunion.c sfio $(VERSION) :LIBRARY: $(SFIO) $(SFIO_F) $(STDIO_S) $(SFIO_DC) stdio $(VERSION) :LIBRARY: $(STDIO_B) ast_common.h : features/common iffe - run features/commsrc/lib/sfio/sfnew.c000644 151361 151361 00000005005 07432261524 014320 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Fundamental function to create a new stream. ** The argument flags defines the type of stream and the scheme ** of buffering. ** ** Written by Kiem-Phong Vo. */ #if __STD_C Sfio_t* sfnew(Sfio_t* oldf, Void_t* buf, size_t size, int file, int flags) #else Sfio_t* sfnew(oldf,buf,size,file,flags) Sfio_t* oldf; /* old stream to be reused */ Void_t* buf; /* a buffer to read/write, if NULL, will be allocated */ size_t size; /* buffer size if buf is given or desired buffer size */ int file; /* file descriptor to read/write from */ int flags; /* type of file stream */ #endif { reg Sfio_t* f; reg int sflags; SFONCE(); /* initialize mutexes */ if(!(flags&SF_RDWR)) return NIL(Sfio_t*); sflags = 0; if((f = oldf) ) { if(flags&SF_EOF) { if(f != sfstdin && f != sfstdout && f != sfstderr) f->mutex = NIL(Vtmutex_t*); SFCLEAR(f, f->mutex); oldf = NIL(Sfio_t*); } else if(f->mode&SF_AVAIL) { /* only allow SF_STATIC to be already closed */ if(!(f->flags&SF_STATIC) ) return NIL(Sfio_t*); sflags = f->flags; oldf = NIL(Sfio_t*); } else { /* reopening an open stream, close it first */ sflags = f->flags; if(((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0) || SFCLOSE(f) < 0 ) return NIL(Sfio_t*); if(f->data && ((flags&SF_STRING) || size != (size_t)SF_UNBOUND) ) { if(sflags&SF_MALLOC) free((Void_t*)f->data); f->data = NIL(uchar*); } if(!f->data) sflags &= ~SF_MALLOC; } } if(!f) { /* reuse a standard stream structure if possible */ if(!(flags&SF_STRING) && file >= 0 && file <= 2) { f = file == 0 ? sfstdin : file == 1 ? sfstdout : sfstderr; if(f) { if(f->mode&SF_AVAIL) { sflags = f->flags; SFCLEAR(f, f->mutex); } else f = NIL(Sfio_t*); } } if(!f) { if(!(f = (Sfio_t*)malloc(sizeof(Sfio_t))) ) return NIL(Sfio_t*); SFCLEAR(f, NIL(Vtmutex_t*)); } } /* create a mutex */ if(!f->mutex) f->mutex = vtmtxopen(NIL(Vtmutex_t*), VT_INIT); /* stream type */ f->mode = (flags&SF_READ) ? SF_READ : SF_WRITE; f->flags = (flags&SF_FLAGS) | (sflags&(SF_MALLOC|SF_STATIC)); f->bits = (flags&SF_RDWR) == SF_RDWR ? SF_BOTH : 0; f->file = file; f->here = f->extent = 0; f->getr = f->tiny[0] = 0; f->mode |= SF_INIT; if(size != (size_t)SF_UNBOUND) { f->size = size; f->data = size <= 0 ? NIL(uchar*) : (uchar*)buf; } f->endb = f->endr = f->endw = f->next = f->data; if(_Sfnotify) (*_Sfnotify)(f,SF_NEW,f->file); if(f->flags&SF_STRING) (void)_sfmode(f,f->mode&SF_RDWR,0); return f; } ? SF_READ : SF_WRITE; f->flags = (flags&SF_FLAGS) | (sflags&(SF_MALLOC|SF_STATIC)); f->bits = (flags&SF_RDWR) == SF_RDWR ? SF_BOTH : 0; f->file = file; f->here = f->extent = 0; f->getr = f->tiny[0] = 0; f->mode |= SF_INIT; if(size != (size_t)SF_UNBOUND) { f->size = size; f->data = size <= 0 ? NIL(uchar*) : (uchar*)buf; } f->endb = f->endr = f->endw = f->next = f->data; if(_Sfnotify) (*_Sfnotify)(f,SF_NEW,f->file); if(f->flags&SF_STRING) (void)_sfmode(f,f->mode&SF_RDWR,0); return src/lib/sfio/sfwrite.c000644 151361 151361 00000006006 07501450361 014657 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Write data out to the file system ** ** Written by Kiem-Phong Vo. */ #if __STD_C ssize_t sfwrite(reg Sfio_t* f, const Void_t* buf, reg size_t n) #else ssize_t sfwrite(f,buf,n) reg Sfio_t* f; /* write to this stream. */ Void_t* buf; /* buffer to be written. */ reg size_t n; /* number of bytes. */ #endif { reg uchar *s, *begs, *next; reg ssize_t w; reg int local; SFMTXSTART(f, (ssize_t)(-1)); GETLOCAL(f,local); if(!buf) SFMTXRETURN(f, (ssize_t)(n == 0 ? 0 : -1) ); /* release peek lock */ if(f->mode&SF_PEEK) { if(!(f->mode&SF_WRITE) && (f->flags&SF_RDWR) != SF_RDWR) SFMTXRETURN(f, (ssize_t)(-1)); if((uchar*)buf != f->next && (!f->rsrv || f->rsrv->data != (uchar*)buf) ) SFMTXRETURN(f, (ssize_t)(-1)); f->mode &= ~SF_PEEK; if(f->mode&SF_PKRD) { /* read past peeked data */ char buf[16]; reg ssize_t r; for(w = n; w > 0; ) { if((r = w) > sizeof(buf)) r = sizeof(buf); if((r = read(f->file,buf,r)) <= 0) { n -= w; break; } else w -= r; } f->mode &= ~SF_PKRD; f->endb = f->data + n; f->here += n; } if((f->mode&SF_READ) && f->proc) f->next += n; } s = begs = (uchar*)buf; for(;; f->mode &= ~SF_LOCK) { /* check stream mode */ if(SFMODE(f,local) != SF_WRITE && _sfmode(f,SF_WRITE,local) < 0 ) { w = s > begs ? s-begs : -1; SFMTXRETURN(f,w); } SFLOCK(f,local); w = f->endb - f->next; if(s == f->next) /* after sfreserve */ { if(w > (ssize_t)n) w = (ssize_t)n; f->next = (s += w); n -= w; break; } /* attempt to create space in buffer */ if(w == 0 || ((f->flags&SF_WHOLE) && w < (ssize_t)n) ) { if(f->flags&SF_STRING) /* extend buffer */ { (void)SFWR(f, s, n-w, f->disc); if((w = f->endb - f->next) < (ssize_t)n) { if(!(f->flags&SF_STRING)) /* maybe sftmp */ { if(f->next > f->data) goto fls_buf; } else if(w == 0) break; } } else if(f->next > f->data) { fls_buf: (void)SFFLSBUF(f, -1); if((w = f->endb - f->next) < (ssize_t)n && (f->flags&SF_WHOLE) && f->next > f->data ) break; } } if(!(f->flags&SF_STRING) && f->next == f->data && ((f->flags&SF_WHOLE) || SFDIRECT(f,n)) ) { /* bypass buffering */ if((w = SFWR(f,s,n,f->disc)) <= 0 ) break; } else { if(w > (ssize_t)n) w = (ssize_t)n; if(w <= 0) /* no forward progress possible */ break; memcpy(f->next, s, w); f->next += w; } s += w; if((n -= w) <= 0) break; } /* always flush buffer for share streams */ if(f->extent < 0 && (f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) ) (void)SFFLSBUF(f,-1); /* check to see if buffer should be flushed */ else if(n == 0 && (f->flags&SF_LINE) && !(f->flags&SF_STRING)) { if((ssize_t)(n = f->next-f->data) > (w = s-begs)) n = w; if(n > 0 && n < HIFORLINE) { for(next = f->next-1; n > 0; --n, --next) { if(*next == '\n') { n = HIFORLINE; break; } } } if(n >= HIFORLINE) (void)SFFLSBUF(f,-1); } SFOPEN(f,local); w = s-begs; SFMTXRETURN(f,w); } ->extent < 0 && (f->flags&SF_SHARE) && !(f->flags&SF_PUBLIC) ) (void)SFFLSBUF(f,-1); /* check to see if buffer should be flushed */ else if(n == 0 && (f->flags&SF_LINE) && !(f->flags&SF_STRING)) { if((ssize_t)(n = f->next-f->data) > (w = s-begs)) n = w; if(n > 0 && n < HIFORLINE) { for(next = f->next-1; n > 0; --n, --next) { if(*next == '\n') { n = HIFORLINE; break; } } } if(n >= HIFORLINE) (void)SFFLSBUF(f,-1); } SFOPEN(f,local); w = s-begs; SFMTXRETURN(f,src/lib/sfio/sfraise.c000644 151361 151361 00000002002 07432261525 014625 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Invoke event handlers for a stream ** ** Written by Kiem-Phong Vo. */ #if __STD_C int sfraise(Sfio_t* f, int type, Void_t* data) #else int sfraise(f, type, data) Sfio_t* f; /* stream */ int type; /* type of event */ Void_t* data; /* associated data */ #endif { reg Sfdisc_t *disc, *next, *d; reg int local, rv; SFMTXSTART(f, -1); GETLOCAL(f,local); if(!SFKILLED(f) && !(local && (type == SF_NEW || type == SF_CLOSING || type == SF_FINAL || type == SF_ATEXIT)) && SFMODE(f,local) != (f->mode&SF_RDWR) && _sfmode(f,0,local) < 0) SFMTXRETURN(f, -1); SFLOCK(f,local); for(disc = f->disc; disc; ) { next = disc->disc; if(disc->exceptf) { SFOPEN(f,0); if((rv = (*disc->exceptf)(f,type,data,disc)) != 0 ) SFMTXRETURN(f, rv); SFLOCK(f,0); } if((disc = next) ) { /* make sure that "next" hasn't been popped */ for(d = f->disc; d; d = d->disc) if(d == disc) break; if(!d) disc = f->disc; } } SFOPEN(f,local); SFMTXRETURN(f, 0); } SFMODE(f,local) != (f->mode&SF_RDWR) && _sfmode(f,0,local) < 0) SFMTXRETURN(f, -1); SFLOCK(f,local); for(disc = f->disc; disc; ) { next = disc->disc; if(disc->exceptf) { SFOPEN(f,0); if((rv = (*disc->exceptf)(f,type,data,disc)) != 0 ) SFMTXRETURN(f, rv); SFLOCK(f,0); } if((disc = next) ) { /* make sure that "next" hasn't been popped */ for(d = f->disc; d; d = d->disc) if(d == disc) break; if(!d) disc = f->disc; } } SFOPEN(f,local); SFMTXRETURN(f, 0); src/lib/sfio/NOTICE000644 151361 151361 0000000000007317131241 014561 1NOTICEustar00kpvkpv000000 000000 src/lib/sfio/sfio_t.h000644 151361 151361 00000007073 07432261523 014474 0ustar00kpvkpv000000 000000 #ifndef _SFIO_T_H #define _SFIO_T_H 1 /* This header file is for library writers who need to know certain ** internal info concerning the full Sfio_t structure. Including this ** file means that you agree to track closely with sfio development ** in case its internal architecture is changed. ** ** Written by Kiem-Phong Vo */ /* the parts of Sfio_t private to sfio functions */ #define _SFIO_PRIVATE \ Sfoff_t extent; /* current file size */ \ Sfoff_t here; /* current physical location */ \ unsigned char getr; /* the last sfgetr separator */ \ unsigned char tiny[1];/* for unbuffered read stream */ \ unsigned short bits; /* private flags */ \ unsigned int mode; /* current io mode */ \ struct _sfdisc_s* disc; /* discipline */ \ struct _sfpool_s* pool; /* the pool containing this */ \ struct _sfrsrv_s* rsrv; /* reserved buffer */ \ struct _sfproc_s* proc; /* coprocess id, etc. */ \ Void_t* mutex; /* mutex for thread-safety */ \ Void_t* stdio; /* stdio FILE if any */ \ Sfoff_t lpos; /* last seek position */ \ size_t iosz; /* prefer size for I/O */ \ Void_t* fill[2];/* modest expansion */ #include "sfio.h" /* mode bit to indicate that the structure hasn't been initialized */ #define SF_INIT 0000004 /* short-hand for common stream types */ #define SF_RDWR (SF_READ|SF_WRITE) #define SF_RDSTR (SF_READ|SF_STRING) #define SF_WRSTR (SF_WRITE|SF_STRING) #define SF_RDWRSTR (SF_RDWR|SF_STRING) /* for static initialization of an Sfio_t structure */ #define SFNEW(data,size,file,type,disc,mutex) \ { (unsigned char*)(data), /* next */ \ (unsigned char*)(data), /* endw */ \ (unsigned char*)(data), /* endr */ \ (unsigned char*)(data), /* endb */ \ (Sfio_t*)0, /* push */ \ (unsigned short)((type)&SF_FLAGS), /* flags */ \ (short)(file), /* file */ \ (unsigned char*)(data), /* data */ \ (ssize_t)(size), /* size */ \ (ssize_t)(-1), /* val */ \ (Sfoff_t)0, /* extent */ \ (Sfoff_t)0, /* here */ \ 0, /* getr */ \ {0}, /* tiny */ \ 0, /* bits */ \ (unsigned int)(((type)&(SF_RDWR))|SF_INIT), /* mode */ \ (struct _sfdisc_s*)(disc), /* disc */ \ (struct _sfpool_s*)0, /* pool */ \ (struct _sfrsrv_s*)0, /* rsrv */ \ (struct _sfproc_s*)0, /* proc */ \ (mutex), /* mutex */ \ (Void_t*)0, /* stdio */ \ (Sfoff_t)0, /* lpos */ \ (size_t)0 /* iosz */ \ } /* function to clear an Sfio_t structure */ #define SFCLEAR(f,mtx) \ ( (f)->next = (unsigned char*)0, /* next */ \ (f)->endw = (unsigned char*)0, /* endw */ \ (f)->endr = (unsigned char*)0, /* endr */ \ (f)->endb = (unsigned char*)0, /* endb */ \ (f)->push = (Sfio_t*)0, /* push */ \ (f)->flags = (unsigned short)0, /* flags */ \ (f)->file = -1, /* file */ \ (f)->data = (unsigned char*)0, /* data */ \ (f)->size = (ssize_t)(-1), /* size */ \ (f)->val = (ssize_t)(-1), /* val */ \ (f)->extent = (Sfoff_t)(-1), /* extent */ \ (f)->here = (Sfoff_t)0, /* here */ \ (f)->getr = 0, /* getr */ \ (f)->tiny[0] = 0, /* tiny */ \ (f)->bits = 0, /* bits */ \ (f)->mode = 0, /* mode */ \ (f)->disc = (struct _sfdisc_s*)0, /* disc */ \ (f)->pool = (struct _sfpool_s*)0, /* pool */ \ (f)->rsrv = (struct _sfrsrv_s*)0, /* rsrv */ \ (f)->proc = (struct _sfproc_s*)0, /* proc */ \ (f)->mutex = (mtx), /* mutex */ \ (f)->stdio = (Void_t*)0, /* stdio */ \ (f)->lpos = (Sfoff_t)0, /* lpos */ \ (f)->iosz = (size_t)0 /* iosz */ \ ) #endif /* _SFIO_T_H */ (f)->tiny[0] = 0, /* tiny */ \ (f)->bits = 0, /* bits */ \ (f)->mode = 0, /* mode */ \ (f)->disc = (struct _sfdisc_s*)0, /* disc */ \ (f)->pool = (struct _sfpool_s*)0, /* pool */ \ (f)->rsrv = (struct _sfrsrv_s*)0, /* rsrv */ \ (f)->proc = (struct _sfproc_s*)0, /* proc */ \ (f)->mutex = (mtx), /* mutex */ \ (f)->stdio = (Void_t*)0, /* stdio */ \ (f)->lpos = (Sfoff_t)0, /* lpos */ \ (f)->iosrc/lib/sfio/sfio_s.h000644 151361 151361 00000001445 07432261523 014470 0ustar00kpvkpv000000 000000 #ifndef _SFIO_S_H #define _SFIO_S_H 1 /* * sfio file structure used by sfio and the stdio source compatibility library */ #if defined(_SFIO_H) && _SFIO_VERSION < 20020214L #define _data data #define _endb endb #define _next next #endif struct _sfio_s { unsigned char* _next; /* next position to read/write from */ unsigned char* _endw; /* end of write buffer */ unsigned char* _endr; /* end of read buffer */ unsigned char* _endb; /* end of buffer */ struct _sfio_s* _push; /* the stream that was pushed on */ unsigned short _flags; /* type of stream */ short _file; /* file descriptor */ unsigned char* _data; /* base of data buffer */ ssize_t _size; /* buffer size */ ssize_t _val; /* values or string lengths */ #ifdef _SFIO_PRIVATE _SFIO_PRIVATE #endif }; #endif sition to read/write from */ unsigned char* _endw; /* end of write buffer */ unsigned char* _endr; /* end of read buffer */ unsigned char* _endb; /* end of buffer */ struct _sfio_s* _push; /* the stream that wsrc/lib/sfio/sfvscanf.c000644 151361 151361 00000057075 07451656164 015036 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* The main engine for reading formatted data ** ** Written by Kiem-Phong Vo. */ #define MAXWIDTH (int)(((uint)~0)>>1) /* max amount to scan */ /* refresh stream buffer - taking care of unseekable/share streams too */ #if __STD_C static void _sfbuf(Sfio_t* f, int* peek) #else static void _sfbuf(f, peek) Sfio_t* f; int* peek; #endif { if(f->next >= f->endb) { if(*peek) /* try peeking for a share stream if possible */ { f->mode |= SF_RV; if(SFFILBUF(f,-1) > 0) { f->mode |= SF_PEEK; return; } *peek = 0; /* can't peek, back to normal reads */ } (void)SFFILBUF(f,-1); } } /* buffer used during scanning of a double value or a multi-byte character. the fields mirror certain local variables in sfvscanf. */ typedef struct _scan_s { int error; /* get set by _sfdscan if no value specified */ int inp; /* last input character read */ int width; /* field width */ Sfio_t *f; /* stream being scanned */ uchar *d, *endd, *data; /* local buffering system */ int peek; /* != 0 if unseekable/share stream */ int n_input;/* number of input bytes processed */ } Scan_t; /* ds != 0 for scanning double values */ #define SCinit(sc,ds) ((sc)->inp = (sc)->error = -1, (sc)->f = f, \ ((sc)->width = (ds) ? width : -1), \ (sc)->d = d, (sc)->endd = endd, (sc)->data = data, \ (sc)->peek = peek, (sc)->n_input = n_input) #define SCend(sc,ds) (inp = (sc)->inp, f = (sc)->f, \ (width = (ds) ? (sc)->width : width), \ d = (sc)->d, endd = (sc)->endd, data = (sc)->data, \ peek = (sc)->peek, n_input = (sc)->n_input) #if __STD_C static int _scgetc(void* arg) #else static int _scgetc(arg) void* arg; #endif { Scan_t *sc = (Scan_t*)arg; /* if width >= 0, do not allow to exceed width number of bytes */ if(sc->width == 0) return (sc->inp = -2); if(sc->d >= sc->endd) /* refresh local buffer */ { sc->n_input += sc->d - sc->data; if(sc->peek) SFREAD(sc->f, sc->data, sc->d - sc->data); else sc->f->next = sc->d; _sfbuf(sc->f, &sc->peek); sc->data = sc->d = sc->f->next; sc->endd = sc->f->endb; if(sc->d >= sc->endd) return (sc->inp = -2); } if((sc->width -= 1) >= 0) /* from _sfdscan */ return (sc->inp = (int)(*sc->d++)); else return ((int)(*sc->d++)); } /* structure to match characters in a character class */ typedef struct _accept_s { char ok[SF_MAXCHAR]; int yes; char *form, *endf; #if _has_multibyte wchar_t wc; #endif } Accept_t; #if __STD_C static char* _sfsetclass(const char* form, Accept_t* ac, int flags) #else static char* _sfsetclass(form, ac, flags) char* form; /* format string */ Accept_t* ac; /* values of accepted characters */ int flags; /* SFFMT_LONG for wchar_t */ #endif { int c, endc, n; #if _has_multibyte SFMBDCL(mbs) #endif if(*form == '^') /* complementing this set */ { ac->yes = 0; form += 1; } else ac->yes = 1; for(c = 0; c <= SF_MAXCHAR; ++c) ac->ok[c] = !ac->yes; if(*form == ']' || *form == '-') /* special first char */ { ac->ok[*form] = ac->yes; form += 1; } ac->form = (char*)form; if(flags&SFFMT_LONG) SFMBCLR(&mbs); for(n = 1; *form != ']'; form += n) { if((c = *((uchar*)form)) == 0) return NIL(char*); if(*(form+1) == '-') { endc = *((uchar*)(form+2)); #if _has_multibyte if(c >= 128 || endc >= 128 ) /* range must be ascii */ goto one_char; #endif for(; c <= endc; ++c) ac->ok[c] = ac->yes; n = 3; } else { one_char: #if _has_multibyte /* true multi-byte chars must be checked differently */ if((flags&SFFMT_LONG) && (n = (int)SFMBLEN(form,&mbs)) <= 0) return NIL(char*); if(n == 1) #endif ac->ok[c] = ac->yes; } } ac->endf = (char*)form; return (char*)(form+1); } #if _has_multibyte #if __STD_C static int _sfwaccept(wchar_t wc, Accept_t* ac) #else static int _sfwaccept(wc, ac) wchar_t wc; Accept_t* ac; #endif { int endc, c, n; wchar_t fwc; char *form = ac->form; SFMBDCL(mbs) SFMBCLR(&mbs); for(n = 1; *form != ']'; form += n) { if((c = *((uchar*)form)) == 0) return 0; if(*(form+1) == '-') { endc = *((uchar*)(form+2)); if(c >= 128 || endc >= 128 ) /* range must be ascii */ goto one_char; n = 3; } else { one_char: if((n = mbrtowc(&fwc, form, ac->endf-form, &mbs)) > 1 && wc == fwc ) return ac->yes; } } return !ac->yes; } #if _has_multibyte == 1 #define SFgetwc(sc,wc,fmt,ac,mbs) _sfgetwc(sc,wc,fmt,ac,(Void_t*)(mbs)) #else #define SFgetwc(sc,wc,fmt,ac,mbs) _sfgetwc(sc,wc,fmt,ac,NIL(Void_t*)) #endif #if __STD_C static int _sfgetwc(Scan_t* sc, wchar_t* wc, int fmt, Accept_t* ac, Void_t *mbs) #else static int _sfgetwc(sc, wc, fmt, ac, mbs) Scan_t* sc; /* the scanning handle */ wchar_t* wc; /* to return a scanned wchar_t */ int fmt; /* %s, %c, %[ */ Accept_t* ac; /* accept handle for %[ */ Void_t* mbs; /* multibyte parsing state */ #endif { int n; char b[16]; /* assuming that MB_CUR_MAX <= 16! */ size_t rv; /* shift left data so that there will be more room to back up on error. this won't help streams with small buffers - c'est la vie! */ if(sc->d > sc->f->data && (n = sc->endd - sc->d) > 0 && n < MB_CUR_MAX) { memcpy(sc->f->data, sc->d, n); if(sc->f->endr == sc->f->endb) sc->f->endr = sc->f->data+n; if(sc->f->endw == sc->f->endb) sc->f->endw = sc->f->data+n; sc->f->endb = sc->f->data+n; sc->d = sc->data = sc->f->data; sc->endd = sc->f->endb; if(!mbs) sc->f->endb = sc->endd; /* stop cc's "unused mbs" warning */ } for(n = 0; n < MB_CUR_MAX; ) { b[n++] = _scgetc((Void_t*)sc); if((rv = mbrtowc(wc, b, n, (mbstate_t*)mbs)) == (size_t)(-2)) continue; /* incomplete multi-byte char */ else if(rv == (size_t)(-1)) goto no_match; /* malformed multi-byte char */ else /* multi-byte char converted successfully */ { if(fmt == 'c') return 1; else if(fmt == 's') { if(n > 1 || (n == 1 && !isspace(b[0]) ) ) return 1; else goto no_match; } else if(fmt == '[') { if((n == 1 && ac->ok[b[0]]) || (n > 1 && _sfwaccept(*wc,ac)) ) return 1; else goto no_match; } else /* if(fmt == '1') match a single wchar_t */ { if(*wc == ac->wc) return 1; else goto no_match; } } } no_match: /* this unget is lossy on a stream with small buffer */ if((sc->d -= n) < sc->data) sc->d = sc->data; return 0; } #endif /*_has_multibyte*/ #if __STD_C int sfvscanf(Sfio_t* f, reg const char* form, va_list args) #else int sfvscanf(f,form,args) Sfio_t* f; /* file to be scanned */ reg char* form; /* scanning format */ va_list args; #endif { reg int inp, shift, base, width; ssize_t size; int fmt, flags, dot, n_assign, v, n, n_input; char *sp; Accept_t acc; Argv_t argv; Sffmt_t *ft; Fmt_t *fm, *fmstk; Fmtpos_t* fp; char *oform; va_list oargs; int argp, argn; int decimal = 0, thousand = 0; #if _has_multibyte wchar_t wc; SFMBDCL(fmbs) SFMBDCL(mbs) #endif Void_t* value; /* location to assign scanned value */ char* t_str; ssize_t n_str; /* local buffering system */ Scan_t scd; uchar *d, *endd, *data; int peek; #define SFbuf(f) (_sfbuf(f,&peek), (data = d = f->next), (endd = f->endb) ) #define SFlen(f) (d - data) #define SFinit(f) ((peek = f->extent < 0 && (f->flags&SF_SHARE)), SFbuf(f) ) #define SFend(f) ((n_input += SFlen(f)), \ (peek ? SFREAD(f,(Void_t*)data,SFlen(f)) : ((f->next = d),0)) ) #define SFgetc(f,c) ((c) = (d < endd || (SFend(f), SFbuf(f), d < endd)) ? \ (int)(*d++) : -1 ) #define SFungetc(f,c) (d -= 1) SFCVINIT(); /* initialize conversion tables */ SFMTXSTART(f,-1); if(!form || f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0) SFMTXRETURN(f, -1); SFLOCK(f,0); SFinit(f); /* initialize local buffering system */ n_assign = n_input = 0; inp = -1; fmstk = NIL(Fmt_t*); ft = NIL(Sffmt_t*); fp = NIL(Fmtpos_t*); argn = -1; oform = (char*)form; va_copy(oargs,args); SFSETLOCALE(&decimal, &thousand); loop_fmt: SFMBCLR(&fmbs); while((fmt = *form++)) { if(fmt != '%') { if(isspace(fmt)) { if(fmt != '\n' || !(f->flags&SF_LINE)) fmt = -1; for(;;) { if(SFgetc(f,inp) < 0 || inp == fmt) goto loop_fmt; else if(!isspace(inp)) { SFungetc(f,inp); goto loop_fmt; } } } else { match_1: #if _has_multibyte if((n = (int)mbrtowc(&wc,form-1,MB_CUR_MAX,&fmbs)) <= 0) goto pop_fmt; if(n > 1) { acc.wc = wc; SCinit(&scd,0); SFMBCLR(&mbs); v = SFgetwc(&scd, &wc, '1', &acc, &mbs); SCend(&scd,0); if(v == 0) goto pop_fmt; form += n-1; } else #endif if(SFgetc(f,inp) != fmt) { if(inp < 0) goto done; SFungetc(f,inp); goto pop_fmt; } } continue; } if(*form == '%') { form += 1; goto match_1; } if(*form == '\0') goto pop_fmt; if(*form == '*') { flags = SFFMT_SKIP; form += 1; } else flags = 0; /* matching some pattern */ base = 10; size = -1; width = dot = 0; t_str = NIL(char*); n_str = 0; value = NIL(Void_t*); argp = -1; loop_flags: /* LOOP FOR FLAGS, WIDTH, BASE, TYPE */ switch((fmt = *form++) ) { case LEFTP : /* get the type which is enclosed in balanced () */ t_str = (char*)form; for(v = 1;;) { switch(*form++) { case 0 : /* not balanceable, retract */ form = t_str; t_str = NIL(char*); n_str = 0; goto loop_flags; case LEFTP : /* increasing nested level */ v += 1; continue; case RIGHTP : /* decreasing nested level */ if((v -= 1) != 0) continue; if(*t_str != '*' ) n_str = (form-1) - t_str; else { t_str = (*_Sffmtintf)(t_str+1,&n); if(*t_str == '$') { if(!fp && !(fp = (*_Sffmtposf) (f,oform,oargs,1)) ) goto pop_fmt; n = FP_SET(n,argn); } else n = FP_SET(-1,argn); if(fp) { t_str = fp[n].argv.s; n_str = fp[n].ft.size; } else if(ft && ft->extf ) { FMTSET(ft, form,args, LEFTP, 0, 0, 0,0,0, NIL(char*),0); n = (*ft->extf) (f,(Void_t*)&argv,ft); if(n < 0) goto pop_fmt; if(!(ft->flags&SFFMT_VALUE) ) goto t_arg; if((t_str = argv.s) && (n_str = (int)ft->size) < 0) n_str = strlen(t_str); } else { t_arg: if((t_str = va_arg(args,char*)) ) n_str = strlen(t_str); } } goto loop_flags; } } case '#' : /* alternative format */ flags |= SFFMT_ALTER; goto loop_flags; case '.' : /* width & base */ dot += 1; if(isdigit(*form)) { fmt = *form++; goto dot_size; } else if(*form == '*') { form = (*_Sffmtintf)(form+1,&n); if(*form == '$') { form += 1; if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,1)) ) goto pop_fmt; n = FP_SET(n,argn); } else n = FP_SET(-1,argn); if(fp) v = fp[n].argv.i; else if(ft && ft->extf ) { FMTSET(ft, form,args, '.',dot, 0, 0,0,0, NIL(char*), 0); if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0) goto pop_fmt; if(ft->flags&SFFMT_VALUE) v = argv.i; else v = (dot <= 2) ? va_arg(args,int) : 0; } else v = (dot <= 2) ? va_arg(args,int) : 0; if(v < 0) v = 0; goto dot_set; } else goto loop_flags; case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : dot_size : for(v = fmt-'0'; isdigit(*form); ++form) v = v*10 + (*form - '0'); if(*form == '$') { form += 1; if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,1)) ) goto pop_fmt; argp = v-1; goto loop_flags; } dot_set : if(dot == 0 || dot == 1) width = v; else if(dot == 2) base = v; goto loop_flags; case 'I' : /* object size */ size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG; if(isdigit(*form)) { for(size = 0, n = *form; isdigit(n); n = *++form) size = size*10 + (n - '0'); } else if(*form == '*') { form = (*_Sffmtintf)(form+1,&n); if(*form == '$') { form += 1; if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,1))) goto pop_fmt; n = FP_SET(n,argn); } else n = FP_SET(-1,argn); if(fp) /* use position list */ size = fp[n].argv.i; else if(ft && ft->extf ) { FMTSET(ft, form,args, 'I',sizeof(int), 0, 0,0,0, NIL(char*), 0); if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0) goto pop_fmt; if(ft->flags&SFFMT_VALUE) size = argv.i; else size = va_arg(args,int); } else size = va_arg(args,int); } goto loop_flags; case 'l' : size = -1; flags &= ~SFFMT_TYPES; if(*form == 'l') { form += 1; flags |= SFFMT_LLONG; } else flags |= SFFMT_LONG; goto loop_flags; case 'h' : size = -1; flags &= ~SFFMT_TYPES; if(*form == 'h') { form += 1; flags |= SFFMT_SSHORT; } else flags |= SFFMT_SHORT; goto loop_flags; case 'L' : size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_LDOUBLE; goto loop_flags; case 'j' : size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_JFLAG; goto loop_flags; case 'z' : size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_ZFLAG; goto loop_flags; case 't' : size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_TFLAG; goto loop_flags; case QUOTE : if(thousand > 0) flags |= SFFMT_THOUSAND; goto loop_flags; } /* set object size for scalars */ if(flags & SFFMT_TYPES) { if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n') { if(flags&SFFMT_LONG) size = sizeof(long); else if(flags&SFFMT_SHORT) size = sizeof(short); else if(flags&SFFMT_SSHORT) size = sizeof(char); else if(flags&SFFMT_TFLAG) size = sizeof(ptrdiff_t); else if(flags&SFFMT_ZFLAG) size = sizeof(size_t); else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) ) size = sizeof(Sflong_t); else if(flags&SFFMT_IFLAG) { if(size <= 0 || size == sizeof(Sflong_t)*CHAR_BIT ) size = sizeof(Sflong_t); } else if(size < 0) size = sizeof(int); } else if(_Sftype[fmt]&SFFMT_FLOAT) { if(flags&(SFFMT_LONG|SFFMT_LLONG)) size = sizeof(double); else if(flags&SFFMT_LDOUBLE) size = sizeof(Sfdouble_t); else if(flags&SFFMT_IFLAG) { if(size <= 0) size = sizeof(Sfdouble_t); } else if(size < 0) size = sizeof(float); } else if(_Sftype[fmt]&SFFMT_CHAR) { #if _has_multibyte if((flags&SFFMT_LONG) || fmt == 'C') { size = sizeof(wchar_t) > sizeof(int) ? sizeof(wchar_t) : sizeof(int); } else #endif if(size < 0) size = sizeof(int); } } argp = FP_SET(argp,argn); if(fp) { if(!(fp[argp].ft.flags&SFFMT_SKIP) ) { n_assign += 1; value = fp[argp].argv.vp; size = fp[argp].ft.size; if(ft && ft->extf && fp[argp].ft.fmt != fp[argp].fmt) fmt = fp[argp].ft.fmt; } else flags |= SFFMT_SKIP; } else if(ft && ft->extf) { FMTSET(ft, form,args, fmt, size,flags, width,0,base, t_str,n_str); SFend(f); SFOPEN(f,0); v = (*ft->extf)(f, (Void_t*)&argv, ft); SFLOCK(f,0); SFbuf(f); if(v < 0) goto pop_fmt; else if(v > 0) /* extf comsumed v input bytes */ { n_input += v; if(!(ft->flags&SFFMT_SKIP) ) n_assign += 1; continue; } else /* if(v == 0): extf did not use input stream */ { FMTGET(ft, form,args, fmt, size, flags, width,n,base); if((ft->flags&SFFMT_VALUE) && !(ft->flags&SFFMT_SKIP) ) value = argv.vp; } } if(_Sftype[fmt] == 0) /* unknown pattern */ goto pop_fmt; /* get the address to assign value */ if(!value && !(flags&SFFMT_SKIP) ) value = va_arg(args,Void_t*); if(fmt == '!') { if(!fp) fp = (*_Sffmtposf)(f,oform,oargs,1); else goto pop_fmt; if(!(argv.ft = va_arg(args,Sffmt_t*)) ) continue; if(!argv.ft->form && ft ) /* change extension functions */ { if(ft->eventf && (*ft->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0) continue; fmstk->ft = ft = argv.ft; } else /* stack a new environment */ { if(!(fm = (Fmt_t*)malloc(sizeof(Fmt_t))) ) goto done; ft = fm->ft = argv.ft; if(ft->form) { fm->form = (char*)form; SFMBCPY(&fm->mbs,&fmbs); va_copy(fm->args,args); fm->oform = oform; va_copy(fm->oargs,oargs); fm->argn = argn; fm->fp = fp; form = ft->form; SFMBCLR(ft->mbs); va_copy(args,ft->args); argn = -1; fp = NIL(Fmtpos_t*); oform = (char*)form; va_copy(oargs,args); } else fm->form = NIL(char*); fm->eventf = ft->eventf; fm->next = fmstk; fmstk = fm; } continue; } if(fmt == 'n') /* return length of consumed input */ { #if !_ast_intmax_long if(size == sizeof(Sflong_t) ) *((Sflong_t*)value) = (Sflong_t)(n_input+SFlen(f)); else #endif if(size == sizeof(long) ) *((long*)value) = (long)(n_input+SFlen(f)); else if(size == sizeof(short) ) *((short*)value) = (short)(n_input+SFlen(f)); else if(size == sizeof(uchar)) *((uchar*)value) = (uchar)(n_input+SFlen(f)); else *((int*)value) = (int)(n_input+SFlen(f)); continue; } /* if get here, start scanning input */ if(width == 0) width = fmt == 'c' ? 1 : MAXWIDTH; /* define the first input character */ if(fmt == 'c' || fmt == '[' || fmt == 'C' ) SFgetc(f,inp); else { do { SFgetc(f,inp); } while(isspace(inp)); /* skip starting blanks */ } if(inp < 0) goto done; if(_Sftype[fmt] == SFFMT_FLOAT) { SFungetc(f,inp); SCinit(&scd,1); argv.ld = _sfdscan((Void_t*)(&scd), _scgetc); SCend(&scd,1); if(scd.error >= 0) { if(inp >= 0) SFungetc(f, inp); goto pop_fmt; } if(value) { #if !_ast_fltmax_double if(size == sizeof(Sfdouble_t)) *((Sfdouble_t*)value) = argv.ld; else #endif if(size == sizeof(double)) *((double*)value) = (double)argv.ld; else *((float*)value) = (float)argv.ld; n_assign += 1; } } else if(_Sftype[fmt] == SFFMT_UINT || fmt == 'p') { if(inp == '-') { SFungetc(f,inp); goto pop_fmt; } else goto int_cvt; } else if(_Sftype[fmt] == SFFMT_INT) { int_cvt: if(inp == '-' || inp == '+') { if(inp == '-') flags |= SFFMT_MINUS; while(--width > 0 && SFgetc(f,inp) >= 0) if(!isspace(inp)) break; } if(inp < 0) goto done; if(fmt == 'o') base = 8; else if(fmt == 'x' || fmt == 'X' || fmt == 'p') base = 16; else if(fmt == 'i' && inp == '0') /* self-described data */ { base = 8; if(width > 1) /* peek to see if it's a base-16 */ { if(SFgetc(f,inp) >= 0) { if(inp == 'x' || inp == 'X') base = 16; SFungetc(f,inp); } inp = '0'; } } /* now convert */ argv.lu = 0; if(base == 16) { sp = (char*)_Sfcv36; shift = 4; if(sp[inp] >= 16) { SFungetc(f,inp); goto pop_fmt; } if(inp == '0' && --width > 0) { /* skip leading 0x or 0X */ if(SFgetc(f,inp) >= 0 && (inp == 'x' || inp == 'X') && --width > 0) SFgetc(f,inp); } if(inp >= 0 && sp[inp] < 16) goto base_shift; } else if(base == 10) { for(n = v = 0;; ) { /* fast base 10 conversion */ #define TEN(x) (((x) << 3) + ((x) << 1) ) if (inp >= '0' && inp <= '9') { argv.lu = TEN(argv.lu) + (inp-'0'); n += 1; } else if(inp == thousand) { if((v && n != 3) || (!v && n > 3) ) break; v = 1; n = 0; } else break; if((width -= 1) <= 0 || SFgetc(f,inp) < 0) break; } if (!n && !v) { SFungetc(f,inp); goto pop_fmt; } if(fmt == 'i' && inp == '#' && !(flags&SFFMT_ALTER) ) { base = (int)argv.lu; if(base < 2 || base > SF_RADIX) goto pop_fmt; argv.lu = 0; sp = (char*)(base <= 36 ? _Sfcv36 : _Sfcv64); if(--width > 0 && SFgetc(f,inp) >= 0 && sp[inp] < base) goto base_conv; } } else { /* other bases */ sp = (char*)(base <= 36 ? _Sfcv36 : _Sfcv64); if(base < 2 || base > SF_RADIX || sp[inp] >= base) { SFungetc(f,inp); goto pop_fmt; } base_conv: /* check for power of 2 conversions */ if((base & ~(base-1)) == base) { if(base < 8) shift = base < 4 ? 1 : 2; else if(base < 32) shift = base < 16 ? 3 : 4; else shift = base < 64 ? 5 : 6; base_shift: do { argv.lu = (argv.lu << shift) + sp[inp]; } while(--width > 0 && SFgetc(f,inp) >= 0 && sp[inp] < base); } else { do { argv.lu = (argv.lu * base) + sp[inp]; } while(--width > 0 && SFgetc(f,inp) >= 0 && sp[inp] < base); } } if(flags&SFFMT_MINUS) argv.ll = -argv.ll; if(value) { n_assign += 1; if(fmt == 'p') #if _more_void_int *((Void_t**)value) = (Void_t*)((ulong)argv.lu); #else *((Void_t**)value) = (Void_t*)((uint)argv.lu); #endif #if !_ast_intmax_long else if(size == sizeof(Sflong_t)) *((Sflong_t*)value) = argv.ll; #endif else if(size == sizeof(long)) { if(fmt == 'd' || fmt == 'i') *((long*)value) = (long)argv.ll; else *((ulong*)value) = (ulong)argv.lu; } else if(size == sizeof(short)) { if(fmt == 'd' || fmt == 'i') *((short*)value) = (short)argv.ll; else *((ushort*)value) = (ushort)argv.lu; } else if(size == sizeof(char) ) { if(fmt == 'd' || fmt == 'i') *((char*)value) = (char)argv.ll; else *((uchar*)value) = (uchar)argv.lu; } else { if(fmt == 'd' || fmt == 'i') *((int*)value) = (int)argv.ll; else *((uint*)value) = (uint)argv.lu; } } } else if(fmt == 'C' || fmt == 'S') { fmt = fmt == 'C' ? 'c' : 's'; flags = (flags & ~SFFMT_TYPES) | SFFMT_LONG; goto do_string; } else if(fmt == 's' || fmt == 'c' || fmt == '[' ) { do_string: if(value) { if(size < 0) size = MAXWIDTH; if(fmt != 'c') size -= 1; #if _has_multibyte if(flags&SFFMT_LONG) argv.ws = (wchar_t*)value; else #endif argv.s = (char*)value; } else size = 0; if(fmt == '[' && !(form = _sfsetclass(form,&acc,flags)) ) { SFungetc(f,inp); goto pop_fmt; } n = 0; /* count number of scanned characters */ #if _has_multibyte if(flags&SFFMT_LONG) { SFungetc(f,inp); SCinit(&scd,0); SFMBCLR(&mbs); for(; width > 0; --width) { if(SFgetwc(&scd,&wc,fmt,&acc,&mbs) == 0) break; if((n += 1) <= size) *argv.ws++ = wc; } SCend(&scd,0); } else #endif if(fmt == 's') { do { if(isspace(inp)) break; if((n += 1) <= size) *argv.s++ = inp; } while(--width > 0 && SFgetc(f,inp) >= 0); } else if(fmt == 'c') { do { if((n += 1) <= size) *argv.s++ = inp; } while(--width > 0 && SFgetc(f,inp) >= 0); } else /* if(fmt == '[') */ { do { if(!acc.ok[inp]) { if(n > 0 || (flags&SFFMT_ALTER) ) break; else { SFungetc(f,inp); goto pop_fmt; } } if((n += 1) <= size) *argv.s++ = inp; } while(--width > 0 && SFgetc(f,inp) >= 0); } if(value && (n > 0 || fmt == '[') ) { n_assign += 1; if(fmt != 'c' && size >= 0) { #if _has_multibyte if(flags&SFFMT_LONG) *argv.ws = 0; else #endif *argv.s = 0; } } } if(width > 0 && inp >= 0) SFungetc(f,inp); } pop_fmt: if(fp) { free(fp); fp = NIL(Fmtpos_t*); } while((fm = fmstk) ) /* pop the format stack and continue */ { if(fm->eventf) { if(!form || !form[0]) (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),ft); else if((*fm->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0) goto loop_fmt; } fmstk = fm->next; if((form = fm->form) ) { SFMBCPY(&fmbs,&fm->mbs); va_copy(args, fm->args); oform = fm->oform; va_copy(oargs,fm->oargs); argn = fm->argn; fp = fm->fp; } ft = fm->ft; free(fm); if(form && form[0]) goto loop_fmt; } done: if(fp) free(fp); while((fm = fmstk) ) { if(fm->eventf) (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),fm->ft); fmstk = fm->next; free(fm); } SFend(f); SFOPEN(f,0); if(n_assign == 0 && inp < 0) n_assign = -1; SFMTXRETURN(f,n_assign); } = fm->next; if((form = fm->form) ) { SFMBCPY(&fmbs,&fm->mbs); va_copy(args, fm->args); oform = fm->oform; va_copy(oargs,fm->oargs); argn = fm->argn; fp = fm->fp; } ft = fm->ft; free(fm); if(form && form[0]) goto loop_fmt; } done: if(fp) free(fp); while((fm = fmstk) ) { if(fm->eventf) (*fm->eventf)(f,SF_FINAL,NIL(Void_t*),fm->ft); fmstk = fm->next; free(fm); } SFend(f); SFOPEN(f,0); if(n_assign ==src/lib/sfio/sfmode.c000644 151361 151361 00000026076 07476551005 014472 0ustar00kpvkpv000000 000000 #include "sfhdr.h" static char* Version = "\n@(#)sfio (AT&T Labs - kpv) 2002-05-31\0\n"; /* Functions to set a given stream to some desired mode ** ** Written by Kiem-Phong Vo. ** ** Modifications: ** 06/27/1990 (first version) ** 01/06/1991 ** 07/08/1991 ** 06/18/1992 ** 02/02/1993 ** 05/25/1993 ** 02/07/1994 ** 05/21/1996 ** 08/01/1997 ** 08/01/1998 (extended formatting) ** 09/09/1999 (thread-safe) ** 02/01/2001 (adaptive buffering) ** 05/31/2002 (multi-byte handling in sfvprintf/vscanf) */ /* the below is for protecting the application from SIGPIPE */ #if _PACKAGE_ast #include #include #define Sfsignal_f Sig_handler_t #else #include typedef void(* Sfsignal_f)_ARG_((int)); #endif static int _Sfsigp = 0; /* # of streams needing SIGPIPE protection */ /* done at exiting time */ #if __STD_C static void _sfcleanup(void) #else static void _sfcleanup() #endif { reg Sfpool_t* p; reg Sfio_t* f; reg int n; reg int pool; f = (Sfio_t*)Version; /* shut compiler warning */ /* set this so that no more buffering is allowed for write streams */ _Sfexiting = 1001; sfsync(NIL(Sfio_t*)); for(p = &_Sfpool; p; p = p->next) { for(n = 0; n < p->n_sf; ++n) { if(!(f = p->sf[n]) || SFFROZEN(f) ) continue; SFLOCK(f,0); SFMTXLOCK(f); /* let application know that we are leaving */ (void)SFRAISE(f, SF_ATEXIT, NIL(Void_t*)); if(f->flags&SF_STRING) continue; /* from now on, write streams are unbuffered */ pool = f->mode&SF_POOL; f->mode &= ~SF_POOL; if((f->flags&SF_WRITE) && !(f->mode&SF_WRITE)) (void)_sfmode(f,SF_WRITE,1); if(((f->bits&SF_MMAP) && f->data) || ((f->mode&SF_WRITE) && f->next == f->data) ) (void)SFSETBUF(f,NIL(Void_t*),0); f->mode |= pool; SFMTXUNLOCK(f); SFOPEN(f,0); } } } /* put into discrete pool */ #if __STD_C int _sfsetpool(Sfio_t* f) #else int _sfsetpool(f) Sfio_t* f; #endif { reg Sfpool_t* p; reg Sfio_t** array; reg int n, rv; if(!_Sfcleanup) { _Sfcleanup = _sfcleanup; (void)atexit(_sfcleanup); } if(!(p = f->pool) ) p = f->pool = &_Sfpool; POOLMTXSTART(p); rv = -1; if(p->n_sf >= p->s_sf) { if(p->s_sf == 0) /* initialize pool array */ { p->s_sf = sizeof(p->array)/sizeof(p->array[0]); p->sf = p->array; } else /* allocate a larger array */ { n = (p->sf != p->array ? p->s_sf : (p->s_sf/4 + 1)*4) + 4; if(!(array = (Sfio_t**)malloc(n*sizeof(Sfio_t*))) ) goto done; /* move old array to new one */ memcpy((Void_t*)array,(Void_t*)p->sf,p->n_sf*sizeof(Sfio_t*)); if(p->sf != p->array) free((Void_t*)p->sf); p->sf = array; p->s_sf = n; } } /* always add at end of array because if this was done during some sort of walk thru all streams, we'll want the new stream to be seen. */ p->sf[p->n_sf++] = f; rv = 0; done: POOLMTXRETURN(p, rv); } /* create an auxiliary buffer for sfgetr/sfreserve/sfputr */ #if __STD_C Sfrsrv_t* _sfrsrv(reg Sfio_t* f, reg ssize_t size) #else Sfrsrv_t* _sfrsrv(f,size) reg Sfio_t* f; reg ssize_t size; #endif { Sfrsrv_t *rsrv, *rs; /* make buffer if nothing yet */ size = ((size + SF_GRAIN-1)/SF_GRAIN)*SF_GRAIN; if(!(rsrv = f->rsrv) || size > rsrv->size) { if(!(rs = (Sfrsrv_t*)malloc(size+sizeof(Sfrsrv_t)))) size = -1; else { if(rsrv) { if(rsrv->slen > 0) memcpy(rs,rsrv,sizeof(Sfrsrv_t)+rsrv->slen); free(rsrv); } f->rsrv = rsrv = rs; rsrv->size = size; rsrv->slen = 0; } } if(rsrv && size > 0) rsrv->slen = 0; return size >= 0 ? rsrv : NIL(Sfrsrv_t*); } #ifdef SIGPIPE #if __STD_C static void ignoresig(int sig) #else static void ignoresig(sig) int sig; #endif { signal(sig, ignoresig); } #endif #if __STD_C int _sfpopen(reg Sfio_t* f, int fd, int pid, int stdio) #else int _sfpopen(f, fd, pid, stdio) reg Sfio_t* f; int fd; int pid; int stdio; /* stdio popen() does not reset SIGPIPE handler */ #endif { reg Sfproc_t* p; if(f->proc) return 0; if(!(p = f->proc = (Sfproc_t*)malloc(sizeof(Sfproc_t))) ) return -1; p->pid = pid; p->size = p->ndata = 0; p->rdata = NIL(uchar*); p->file = fd; p->sigp = (!stdio && pid >= 0 && (f->flags&SF_WRITE)) ? 1 : 0; #ifdef SIGPIPE /* protect from broken pipe signal */ if(p->sigp) { Sfsignal_f handler; vtmtxlock(_Sfmutex); if((handler = signal(SIGPIPE, ignoresig)) != SIG_DFL && handler != ignoresig) signal(SIGPIPE, handler); /* honor user handler */ _Sfsigp += 1; vtmtxunlock(_Sfmutex); } #endif return 0; } #if __STD_C int _sfpclose(reg Sfio_t* f) #else int _sfpclose(f) reg Sfio_t* f; /* stream to close */ #endif { Sfproc_t* p; int pid, status; if(!(p = f->proc)) return -1; f->proc = NIL(Sfproc_t*); if(p->rdata) free(p->rdata); if(p->pid < 0) status = 0; else { /* close the associated stream */ if(p->file >= 0) CLOSE(p->file); /* wait for process termination */ #if _PACKAGE_ast sigcritical(1); #endif while ((pid = waitpid(p->pid,&status,0)) == -1 && errno == EINTR) ; if(pid < 0) status = -1; #if _PACKAGE_ast sigcritical(0); #endif #ifdef SIGPIPE vtmtxlock(_Sfmutex); if(p->sigp && (_Sfsigp -= 1) <= 0) { Sfsignal_f handler; if((handler = signal(SIGPIPE,SIG_DFL)) != SIG_DFL && handler != ignoresig) signal(SIGPIPE,handler); /* honor user handler */ _Sfsigp = 0; } vtmtxunlock(_Sfmutex); #endif } free(p); return status; } #if __STD_C static int _sfpmode(Sfio_t* f, int type) #else static int _sfpmode(f,type) Sfio_t* f; int type; #endif { Sfproc_t* p; if(!(p = f->proc) ) return -1; if(type == SF_WRITE) { /* save unread data */ p->ndata = f->endb-f->next; if(p->ndata > p->size) { if(p->rdata) free((char*)p->rdata); if((p->rdata = (uchar*)malloc(p->ndata)) ) p->size = p->ndata; else { p->size = 0; return -1; } } if(p->ndata > 0) memcpy((Void_t*)p->rdata,(Void_t*)f->next,p->ndata); f->endb = f->data; } else { /* restore read data */ if(p->ndata > f->size) /* may lose data!!! */ p->ndata = f->size; if(p->ndata > 0) { memcpy((Void_t*)f->data,(Void_t*)p->rdata,p->ndata); f->endb = f->data+p->ndata; p->ndata = 0; } } /* switch file descriptor */ if(p->pid >= 0) { type = f->file; f->file = p->file; p->file = type; } return 0; } #if __STD_C int _sfmode(reg Sfio_t* f, reg int wanted, reg int local) #else int _sfmode(f, wanted, local) reg Sfio_t* f; /* change r/w mode and sync file pointer for this stream */ reg int wanted; /* desired mode */ reg int local; /* a local call */ #endif { reg int n; Sfoff_t addr; reg int rv = 0; SFONCE(); /* initialize mutexes */ if((!local && SFFROZEN(f)) || (!(f->flags&SF_STRING) && f->file < 0)) { if(local || !f->disc || !f->disc->exceptf) { local = 1; goto err_notify; } for(;;) { if((rv = (*f->disc->exceptf)(f,SF_LOCKED,0,f->disc)) < 0) return rv; if((!local && SFFROZEN(f)) || (!(f->flags&SF_STRING) && f->file < 0) ) { if(rv == 0) { local = 1; goto err_notify; } else continue; } else break; } } if(f->mode&SF_GETR) { f->mode &= ~SF_GETR; #ifdef MAP_TYPE if((f->bits&SF_MMAP) && (f->tiny[0] += 1) >= (4*SF_NMAP) ) { /* turn off mmap to avoid page faulting */ sfsetbuf(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND); f->tiny[0] = 0; } else #endif if(f->getr) { f->next[-1] = f->getr; f->getr = 0; } } if(f->mode&SF_STDIO) /* synchronizing with stdio pointers */ (*_Sfstdsync)(f); if(f->disc == _Sfudisc && wanted == SF_WRITE && sfclose((*_Sfstack)(f,NIL(Sfio_t*))) < 0 ) { local = 1; goto err_notify; } if(f->mode&SF_POOL) { /* move to head of pool */ if(f == f->pool->sf[0] || (*_Sfpmove)(f,0) < 0 ) { local = 1; goto err_notify; } f->mode &= ~SF_POOL; } SFLOCK(f,local); /* buffer initialization */ wanted &= SF_RDWR; if(f->mode&SF_INIT) { if(!f->pool && _sfsetpool(f) < 0) { rv = -1; goto done; } if(wanted == 0) goto done; if(wanted != (int)(f->mode&SF_RDWR) && !(f->flags&wanted) ) goto err_notify; if((f->flags&SF_STRING) && f->size >= 0 && f->data) { f->mode &= ~SF_INIT; f->extent = ((f->flags&SF_READ) || (f->bits&SF_BOTH)) ? f->size : 0; f->here = 0; f->endb = f->data + f->size; f->next = f->endr = f->endw = f->data; if(f->mode&SF_READ) f->endr = f->endb; else f->endw = f->endb; } else { n = f->flags; (void)SFSETBUF(f,f->data,f->size); f->flags |= (n&SF_MALLOC); } } if(wanted == (int)SFMODE(f,1)) goto done; switch(SFMODE(f,1)) { case SF_WRITE: /* switching to SF_READ */ if(wanted == 0 || wanted == SF_WRITE) break; if(!(f->flags&SF_READ) ) goto err_notify; else if(f->flags&SF_STRING) { SFSTRSIZE(f); f->endb = f->data+f->extent; f->mode = SF_READ; break; } /* reset buffer */ if(f->next > f->data && SFFLSBUF(f,-1) < 0) goto err_notify; if(f->size == 0) { /* unbuffered */ f->data = f->tiny; f->size = sizeof(f->tiny); } f->next = f->endr = f->endw = f->endb = f->data; f->mode = SF_READ|SF_LOCK; /* restore saved read data for coprocess */ if(f->proc && _sfpmode(f,wanted) < 0) goto err_notify; break; case (SF_READ|SF_SYNCED): /* a previously sync-ed read stream */ if(wanted != SF_WRITE) { /* just reset the pointers */ f->mode = SF_READ|SF_LOCK; /* see if must go with new physical location */ if((f->flags&(SF_SHARE|SF_PUBLIC)) == (SF_SHARE|SF_PUBLIC) && (addr = SFSK(f,0,SEEK_CUR,f->disc)) != f->here) { #ifdef MAP_TYPE if((f->bits&SF_MMAP) && f->data) { SFMUNMAP(f,f->data,f->endb-f->data); f->data = NIL(uchar*); } #endif f->endb = f->endr = f->endw = f->next = f->data; f->here = addr; } else { addr = f->here + (f->endb - f->next); if(SFSK(f,addr,SEEK_SET,f->disc) < 0) goto err_notify; f->here = addr; } break; } /* fall thru */ case SF_READ: /* switching to SF_WRITE */ if(wanted != SF_WRITE) break; else if(!(f->flags&SF_WRITE)) goto err_notify; else if(f->flags&SF_STRING) { f->endb = f->data+f->size; f->mode = SF_WRITE|SF_LOCK; break; } /* save unread data before switching mode */ if(f->proc && _sfpmode(f,wanted) < 0) goto err_notify; /* reset buffer and seek pointer */ if(!(f->mode&SF_SYNCED) ) { n = f->endb - f->next; if(f->extent >= 0 && (n > 0 || (f->data && (f->bits&SF_MMAP))) ) { /* reset file pointer */ addr = f->here - n; if(SFSK(f,addr,SEEK_SET,f->disc) < 0) goto err_notify; f->here = addr; } } f->mode = SF_WRITE|SF_LOCK; #ifdef MAP_TYPE if(f->bits&SF_MMAP) { if(f->data) SFMUNMAP(f,f->data,f->endb-f->data); (void)SFSETBUF(f,(Void_t*)f->tiny,(size_t)SF_UNBOUND); } #endif if(f->data == f->tiny) { f->endb = f->data = f->next = NIL(uchar*); f->size = 0; } else f->endb = (f->next = f->data) + f->size; break; default: /* unknown case */ err_notify: if((wanted &= SF_RDWR) == 0 && (wanted = f->flags&SF_RDWR) == SF_RDWR) wanted = SF_READ; /* set errno for operations that access wrong stream type */ if(wanted != (f->mode&SF_RDWR) && f->file >= 0) errno = EBADF; if(_Sfnotify) /* notify application of the error */ (*_Sfnotify)(f,wanted,f->file); rv = -1; break; } done: SFOPEN(f,local); return rv; } IL(uchar*); f->size = 0; } else f->endb = (f->next = f->data) + f->size; break; default: /* unknown case */ err_notify: if((wanted &= SF_RDWR) == 0 && (wanted = f->flags&SF_RDWR) == SF_RDWR) wanted = SF_READ; /* set errno for operations that access wrong stream type */ if(wanted != (f->mode&SF_RDWR) && f->file >= 0) errno = EBADF; if(_Sfnotify) /* notify application of the error */ (*_Sfnotify)(f,wanted,f->file); src/lib/sfio/sfpool.c000644 151361 151361 00000015317 07432261524 014507 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Management of pools of streams. ** If pf is not nil, f is pooled with pf and f becomes current; ** otherwise, f is isolated from its pool. flag can be one of ** 0 or SF_SHARE. ** ** Written by Kiem-Phong Vo. */ /* Note that we do not free the space for a pool once it is allocated. ** This is to prevent memory faults in calls such as sfsync(NULL) that walk the pool ** link list and during such walks may free up streams&pools. Free pools will be ** reused in newpool(). */ #if __STD_C static int delpool(reg Sfpool_t* p) #else static int delpool(p) reg Sfpool_t* p; #endif { POOLMTXSTART(p); if(p->s_sf && p->sf != p->array) free((Void_t*)p->sf); p->mode = SF_AVAIL; POOLMTXRETURN(p,0); } #if __STD_C static Sfpool_t* newpool(reg int mode) #else static Sfpool_t* newpool(mode) reg int mode; #endif { reg Sfpool_t *p, *last = &_Sfpool; /* look to see if there is a free pool */ for(last = &_Sfpool, p = last->next; p; last = p, p = p->next) { if(p->mode == SF_AVAIL ) { p->mode = 0; break; } } if(!p) { POOLMTXLOCK(last); if(!(p = (Sfpool_t*) malloc(sizeof(Sfpool_t))) ) { POOLMTXUNLOCK(last); return NIL(Sfpool_t*); } vtmtxopen(&p->mutex, VT_INIT); /* initialize mutex */ p->mode = 0; p->n_sf = 0; p->next = NIL(Sfpool_t*); last->next = p; POOLMTXUNLOCK(last); } POOLMTXSTART(p); p->mode = mode&SF_SHARE; p->s_sf = sizeof(p->array)/sizeof(p->array[0]); p->sf = p->array; POOLMTXRETURN(p,p); } /* move a stream to head */ #if __STD_C static int _sfphead(Sfpool_t* p, Sfio_t* f, int n) #else static int _sfphead(p, f, n) Sfpool_t* p; /* the pool */ Sfio_t* f; /* the stream */ int n; /* current position in pool */ #endif { reg Sfio_t* head; reg ssize_t k, w, v; reg int rv; POOLMTXSTART(p); if(n == 0) POOLMTXRETURN(p,0); head = p->sf[0]; if(SFFROZEN(head) ) POOLMTXRETURN(p,-1); SFLOCK(head,0); rv = -1; if(!(p->mode&SF_SHARE) ) { if(SFSYNC(head) < 0) goto done; } else /* shared pool, data can be moved among streams */ { if(SFMODE(head,1) != SF_WRITE && _sfmode(head,SF_WRITE,1) < 0) goto done; /**/ASSERT((f->mode&(SF_WRITE|SF_POOL)) == (SF_WRITE|SF_POOL) ); /**/ASSERT(f->next == f->data); v = head->next - head->data; /* pending data */ if((k = v - (f->endb-f->data)) <= 0) k = 0; else /* try to write out amount exceeding f's capacity */ { if((w = SFWR(head,head->data,k,head->disc)) == k) v -= k; else /* write failed, recover buffer then quit */ { if(w > 0) { v -= w; memcpy(head->data,(head->data+w),v); } head->next = head->data+v; goto done; } } /* move data from head to f */ if((head->data+k) != f->data ) memcpy(f->data,(head->data+k),v); f->next = f->data+v; } f->mode &= ~SF_POOL; head->mode |= SF_POOL; head->next = head->endr = head->endw = head->data; p->sf[n] = head; p->sf[0] = f; rv = 0; done: head->mode &= ~SF_LOCK; /* partially unlock because it's no longer head */ POOLMTXRETURN(p,rv); } /* delete a stream from its pool */ #if __STD_C static int _sfpdelete(Sfpool_t* p, Sfio_t* f, int n) #else static int _sfpdelete(p, f, n) Sfpool_t* p; /* the pool */ Sfio_t* f; /* the stream */ int n; /* position in pool */ #endif { POOLMTXSTART(p); p->n_sf -= 1; for(; n < p->n_sf; ++n) p->sf[n] = p->sf[n+1]; f->pool = NIL(Sfpool_t*); f->mode &= ~SF_POOL; if(p->n_sf == 0 || p == &_Sfpool) { if(p != &_Sfpool) delpool(p); goto done; } /* !_Sfpool, make sure head stream is an open stream */ for(n = 0; n < p->n_sf; ++n) if(!SFFROZEN(p->sf[n])) break; if(n < p->n_sf && n > 0) { f = p->sf[n]; p->sf[n] = p->sf[0]; p->sf[0] = f; } /* head stream has SF_POOL off */ f = p->sf[0]; f->mode &= ~SF_POOL; if(!SFFROZEN(f)) _SFOPEN(f); /* if only one stream left, delete pool */ if(p->n_sf == 1 ) { _sfpdelete(p,f,0); _sfsetpool(f); } done: POOLMTXRETURN(p,0); } #if __STD_C static int _sfpmove(reg Sfio_t* f, reg int type) #else static int _sfpmove(f,type) reg Sfio_t* f; reg int type; /* <0 : deleting, 0: move-to-front, >0: inserting */ #endif { reg Sfpool_t* p; reg int n; if(type > 0) return _sfsetpool(f); else { if(!(p = f->pool) ) return -1; for(n = p->n_sf-1; n >= 0; --n) if(p->sf[n] == f) break; if(n < 0) return -1; return type == 0 ? _sfphead(p,f,n) : _sfpdelete(p,f,n); } } #if __STD_C Sfio_t* sfpool(reg Sfio_t* f, reg Sfio_t* pf, reg int mode) #else Sfio_t* sfpool(f,pf,mode) reg Sfio_t* f; reg Sfio_t* pf; reg int mode; #endif { reg Sfpool_t* p; reg Sfio_t* rv; _Sfpmove = _sfpmove; if(!f) /* return head of pool of pf regardless of lock states */ { if(!pf) return NIL(Sfio_t*); else if(!pf->pool || pf->pool == &_Sfpool) return pf; else return pf->pool->sf[0]; } if(f) /* check for permissions */ { SFMTXLOCK(f); if((f->mode&SF_RDWR) != f->mode && _sfmode(f,0,0) < 0) { SFMTXUNLOCK(f); return NIL(Sfio_t*); } if(f->disc == _Sfudisc) (void)sfclose((*_Sfstack)(f,NIL(Sfio_t*))); } if(pf) { SFMTXLOCK(pf); if((pf->mode&SF_RDWR) != pf->mode && _sfmode(pf,0,0) < 0) { if(f) SFMTXUNLOCK(f); SFMTXUNLOCK(pf); return NIL(Sfio_t*); } if(pf->disc == _Sfudisc) (void)sfclose((*_Sfstack)(pf,NIL(Sfio_t*))); } /* f already in the same pool with pf */ if(f == pf || (pf && f->pool == pf->pool && f->pool != &_Sfpool) ) { if(f) SFMTXUNLOCK(f); if(pf) SFMTXUNLOCK(pf); return pf; } /* lock streams before internal manipulations */ rv = NIL(Sfio_t*); SFLOCK(f,0); if(pf) SFLOCK(pf,0); if(!pf) /* deleting f from its current pool */ { if(!(p = f->pool) || p == &_Sfpool || _sfpmove(f,-1) < 0 || _sfsetpool(f) < 0) goto done; if((p = f->pool) == &_Sfpool || p->n_sf <= 0) rv = f; else rv = p->sf[0]; /* return head of pool */ goto done; } if(pf->pool && pf->pool != &_Sfpool) /* always use current mode */ mode = pf->pool->mode; if(mode&SF_SHARE) /* can only have write streams */ { if(SFMODE(f,1) != SF_WRITE && _sfmode(f,SF_WRITE,1) < 0) goto done; if(SFMODE(pf,1) != SF_WRITE && _sfmode(pf,SF_WRITE,1) < 0) goto done; if(f->next > f->data && SFSYNC(f) < 0) /* start f clean */ goto done; } if(_sfpmove(f,-1) < 0) /* isolate f from current pool */ goto done; if(!(p = pf->pool) || p == &_Sfpool) /* making a new pool */ { if(!(p = newpool(mode)) ) goto done; if(_sfpmove(pf,-1) < 0) /* isolate pf from its current pool */ goto done; pf->pool = p; p->sf[0] = pf; p->n_sf += 1; } f->pool = p; /* add f to pf's pool */ if(_sfsetpool(f) < 0) goto done; /**/ASSERT(p->sf[0] == pf && p->sf[p->n_sf-1] == f); SFOPEN(pf,0); SFOPEN(f,0); if(_sfpmove(f,0) < 0) /* make f head of pool */ goto done; rv = pf; done: if(f) { SFOPEN(f,0); SFMTXUNLOCK(f); } if(pf) { SFOPEN(pf,0); SFMTXUNLOCK(pf); } return rv; } !(p = newpool(mode)) ) goto done; if(_sfpmove(pf,-1) < 0) /* isolate pf from its current pool */ goto done; pf->pool = p; p->sf[0] = pf; p->n_sf += 1; } f->pool = p; /* add f to pf's pool */ if(_sfsetpool(f) < 0) goto done; /**/ASSERT(p->sf[0] == pf && p->sf[p->n_sf-1] == f); SFOPEsrc/lib/sfio/sfpoll.c000644 151361 151361 00000011465 07432516301 014500 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Poll a set of streams to see if any is available for I/O. ** Ready streams are moved to front of array but retain the ** same relative order. ** ** Written by Kiem-Phong Vo. */ #if __STD_C int sfpoll(Sfio_t** fa, reg int n, int tm) #else int sfpoll(fa, n, tm) Sfio_t** fa; /* array of streams to poll */ reg int n; /* number of streams in array */ int tm; /* time in millisecs for select/poll */ #endif { reg int r, c, m, np; reg Sfio_t* f; reg Sfdisc_t* d; reg int *status, *check; if(n <= 0 || !fa) return -1; if(!(status = (int*)malloc(2*n*sizeof(int))) ) return -1; check = status+n; /* streams that need polling */ /* check the auxilliary file descriptor to see if polling needed */ #define CHKAUXFD(f) ((f->mode&SF_WRITE) && f->proc && f->proc->file >= 0 && \ f->proc->file != f->file && f->proc->rdata == 0 ) /* check the main file descriptor to see if polling needed */ #define POLLRD(f) ((f->mode&SF_READ) && f->next == f->endb ) #define POLLWR(f) ((f->mode&SF_WRITE) && f->next > f->data ) #define CHKMAINFD(f) (POLLRD(f) || POLLWR(f)) for(r = c = 0; r < n; ++r) /* compute streams that must be checked */ { f = fa[r]; status[r] = 0; /* check accessibility */ m = f->mode&SF_RDWR; if((int)f->mode != m && _sfmode(f,m,0) < 0) continue; if((f->flags&SF_READ) && !POLLRD(f) && !CHKAUXFD(f) ) status[r] |= SF_READ; if((f->flags&SF_WRITE) && (!POLLWR(f) || (f->mode&SF_READ)) ) status[r] |= SF_WRITE; if((f->flags&SF_RDWR) == status[r]) continue; /* has discipline, ask its opinion */ if((d = f->disc) && d->exceptf) { if((m = (*d->exceptf)(f,SF_DPOLL,&tm,d)) < 0) continue; else if(m > 0) { status[r] = m&SF_RDWR; continue; } } if(f->extent < 0) /* unseekable stream, must poll/select */ check[c++] = r; else /* seekable streams are always ready */ { if(f->flags&SF_READ) status[r] |= SF_READ; if(f->flags&SF_WRITE) status[r] |= SF_WRITE; } } np = -1; #if _lib_poll if(c > 0) { struct pollfd* fds; /* construct the poll array */ for(m = 0, r = 0; r < c; ++r, ++m) { f = fa[check[r]]; if(CHKMAINFD(f) && CHKAUXFD(f)) m += 1; } if(!(fds = (struct pollfd*)malloc(m*sizeof(struct pollfd))) ) return -1; for(m = 0, r = 0; r < c; ++r, ++m) { f = fa[check[r]]; if(CHKAUXFD(f) ) { fds[m].fd = f->proc->file; fds[m].events = POLLIN; fds[m].revents = 0; if(!CHKMAINFD(f)) continue; else m += 1; } fds[m].fd = f->file; fds[m].events = fds[m].revents = 0; if((f->flags&SF_READ) && POLLRD(f) ) fds[m].events |= POLLIN; if((f->flags&SF_WRITE) && POLLWR(f) ) fds[m].events |= POLLOUT; } while((np = SFPOLL(fds,m,tm)) < 0 ) { if(errno == EINTR || errno == EAGAIN) errno = 0; else break; } if(np > 0) /* poll succeeded */ np = c; for(m = 0, r = 0; r < np; ++r, ++m) { f = fa[check[r]]; if(CHKAUXFD(f)) { if(fds[m].revents & POLLIN) status[check[r]] |= SF_READ; if(!CHKMAINFD(f)) continue; else m += 1; } if((f->flags&SF_READ) && POLLRD(f) && (fds[m].revents&POLLIN) ) status[check[r]] |= SF_READ; if((f->flags&SF_WRITE) && POLLWR(f) && (fds[m].revents&POLLOUT)) status[check[r]] |= SF_WRITE; } free((Void_t*)fds); } #endif /*_lib_poll*/ #if _lib_select if(np < 0 && c > 0) { fd_set rd, wr; struct timeval tmb, *tmp; FD_ZERO(&rd); FD_ZERO(&wr); m = 0; for(r = 0; r < c; ++r) { f = fa[check[r]]; if(CHKAUXFD(f) ) { if(f->proc->file > m) m = f->proc->file; FD_SET(f->proc->file, &rd); if(!CHKMAINFD(f)) continue; } if(f->file > m) m = f->file; if((f->flags&SF_READ) && POLLRD(f)) FD_SET(f->file,&rd); if((f->flags&SF_WRITE) && POLLWR(f)) FD_SET(f->file,&wr); } if(tm < 0) tmp = NIL(struct timeval*); else { tmp = &tmb; tmb.tv_sec = tm/SECOND; tmb.tv_usec = (tm%SECOND)*SECOND; } while((np = select(m+1,&rd,&wr,NIL(fd_set*),tmp)) < 0 ) { if(errno == EINTR) errno = 0; else break; } if(np > 0) np = c; for(r = 0; r < np; ++r) { f = fa[check[r]]; if(CHKAUXFD(f)) { if(FD_ISSET(f->proc->file, &rd)) status[check[r]] |= SF_READ; if(!CHKMAINFD(f)) continue; } if(((f->flags&SF_READ) && POLLRD(f) && FD_ISSET(f->file,&rd)) ) status[check[r]] |= SF_READ; if(((f->flags&SF_WRITE) && POLLWR(f) && FD_ISSET(f->file,&wr)) ) status[check[r]] |= SF_WRITE; } } #endif /*_lib_select*/ /* announce readiness */ for(c = 0; c < n; ++c) if(status[c] != 0 && (d = fa[c]->disc) && d->exceptf) (*d->exceptf)(fa[c],SF_READY,(Void_t*)status[c],d); /* move ready streams to the front */ for(r = c = 0; c < n; ++c) { if(status[c] == 0) continue; fa[c]->val = (ssize_t)status[c]; if(c > r) { f = fa[r]; fa[r] = fa[c]; fa[c] = f; } r += 1; } free((Void_t*)status); return r; } WR(f) && FD_ISSET(f->file,&wr)) ) status[check[r]] |= SF_WRITE; } } #endif /*_lib_select*/ /* announce readiness */ for(c = 0; c < n; ++c) if(status[c] != 0 && (d = fa[c]->disc) && d->exceptfsrc/lib/sfio/sfmove.c000644 151361 151361 00000013324 07432261524 014500 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Move data from one stream to another. ** This code is written so that it'll work even in the presence ** of stacking streams, pool, and discipline. ** If you must change it, be gentle. ** ** Written by Kiem-Phong Vo. */ #define MAX_SSIZE ((ssize_t)((~((size_t)0)) >> 1)) #if __STD_C Sfoff_t sfmove(Sfio_t* fr, Sfio_t* fw, Sfoff_t n, reg int rc) #else Sfoff_t sfmove(fr,fw,n,rc) Sfio_t* fr; /* moving data from this stream */ Sfio_t* fw; /* moving data to this stream */ Sfoff_t n; /* number of bytes/records to move. <0 for unbounded move */ reg int rc; /* record separator */ #endif { reg uchar *cp, *next; reg ssize_t r, w; reg uchar *endb; reg int direct; Sfoff_t n_move; uchar *rbuf = NIL(uchar*); ssize_t rsize = 0; SFMTXSTART(fr, (Sfoff_t)0); if(fw) SFMTXLOCK(fw); for(n_move = 0; n != 0; ) { /* get the streams into the right mode */ if(fr->mode != SF_READ && _sfmode(fr,SF_READ,0) < 0) goto done; SFLOCK(fr,0); /* flush the write buffer as necessary to make room */ if(fw) { if(fw->mode != SF_WRITE && _sfmode(fw,SF_WRITE,0) < 0 ) break; SFLOCK(fw,0); if(fw->next >= fw->endb || (fw->next > fw->data && fr->extent < 0 && (fw->extent < 0 || (fw->flags&SF_SHARE)) ) ) if(SFFLSBUF(fw,-1) < 0 ) break; } /* about to move all, set map to a large amount */ if(n < 0 && (fr->bits&SF_MMAP) && !(fr->bits&SF_MVSIZE) ) { SFMVSET(fr); if(rc < 0) /* data will be accessed sequentially */ fr->bits |= SF_SEQUENTIAL; } /* try reading a block of data */ direct = 0; if((r = fr->endb - (next = fr->next)) <= 0) { /* amount of data remained to be read */ if((w = n > MAX_SSIZE ? MAX_SSIZE : (ssize_t)n) < 0) { if(fr->extent < 0) w = fr->data == fr->tiny ? SF_GRAIN : fr->size; else if((fr->extent-fr->here) > SF_NMAP*SF_PAGE) w = SF_NMAP*SF_PAGE; else w = (ssize_t)(fr->extent-fr->here); } /* use a decent buffer for data transfer but make sure that if we overread, the left over can be retrieved */ if(!(fr->flags&SF_STRING) && !(fr->bits&SF_MMAP) && (n < 0 || fr->extent >= 0) ) { reg ssize_t maxw = 4*(_Sfpage > 0 ? _Sfpage : SF_PAGE); /* direct transfer to a seekable write stream */ if(fw && fw->extent >= 0 && w <= (fw->endb-fw->next) ) { w = fw->endb - (next = fw->next); direct = SF_WRITE; } else if(w > fr->size && maxw > fr->size) { /* making our own buffer */ if(w >= maxw) w = maxw; else w = ((w+fr->size-1)/fr->size)*fr->size; if(rsize <= 0 && (rbuf = (uchar*)malloc(w)) ) rsize = w; if(rbuf) { next = rbuf; w = rsize; direct = SF_STRING; } } } if(!direct) { /* make sure we don't read too far ahead */ if(n > 0 && fr->extent < 0 && (fr->flags&SF_SHARE) ) { if(rc >= 0) { /* try peeking a large buffer */ fr->mode |= SF_RV; if((r = SFFILBUF(fr,-1)) > 0) goto done_filbuf; else if(n > 1 && !fr->disc) { r = sfpkrd(fr->file, (Void_t*)fr->data, fr->size, rc, -1, (int)(-n) ); if(r <= 0) goto one_r; fr->next = fr->data; fr->endb = fr->endr = fr->next+r; goto done_filbuf; } else /* get a single record */ {one_r: fr->getr = rc; fr->mode |= SF_RC; r = -1; } } else if((Sfoff_t)(r = fr->size) > n) r = (ssize_t)n; } else r = -1; if((r = SFFILBUF(fr,r)) <= 0) break; done_filbuf: next = fr->next; } else { /* actual amount to be read */ if(rc < 0 && n > 0 && n < w) w = (ssize_t)n; if((r = SFRD(fr,next,w,fr->disc)) > 0) fr->next = fr->endb = fr->endr = fr->data; else if(r == 0) break; /* eof */ else goto again; /* popped stack */ } } /* compute the extent of data to be moved */ endb = next+r; if(rc < 0) { if(n > 0) { if(r > n) r = (ssize_t)n; n -= r; } n_move += r; cp = next+r; } else { /* count records */ reg int rdwr = (fr->flags&SF_MALLOC) || (fr->bits&(SF_BOTH|SF_MMAP)); if(rdwr) { w = endb[-1]; endb[-1] = rc; } else w = 0; for(cp = next; cp < endb; ) { /* find the line extent */ if(rdwr) while(*cp++ != rc) ; else while(r-- && *cp++ != rc) ; if(cp < endb || w == rc) { n_move += 1; if(n > 0 && (n -= 1) == 0) break; } } if(rdwr) endb[-1] = w; r = cp-next; if(fr->mode&SF_PKRD) { /* advance the read point by proper amount */ fr->mode &= ~SF_PKRD; (void)read(fr->file,(Void_t*)next,r); fr->here += r; if(!direct) fr->endb = cp; else endb = cp; } } if(!direct) fr->next += r; else if((w = endb-cp) > 0) { /* move left-over to read stream */ if(w > fr->size) w = fr->size; memcpy((Void_t*)fr->data,(Void_t*)cp,w); fr->endb = fr->data+w; if((w = endb - (cp+w)) > 0) (void)SFSK(fr,(Sfoff_t)(-w),SEEK_CUR,fr->disc); } if(fw) { if(direct == SF_WRITE) fw->next += r; else if(r <= (fw->endb-fw->next) ) { memcpy((Void_t*)fw->next,(Void_t*)next,r); fw->next += r; } else if((w = SFWRITE(fw,(Void_t*)next,r)) != r) { /* a write error happened */ if(w > 0) { r -= w; if(rc < 0) n_move -= r; } if(fr->extent >= 0) (void)SFSEEK(fr,(Sfoff_t)(-r),1); break; } } again: SFOPEN(fr,0); if(fw) SFOPEN(fw,0); } done: if(n < 0 && (fr->bits&SF_MMAP) && (fr->bits&SF_MVSIZE)) { /* back to normal access mode */ SFMVUNSET(fr); if((fr->bits&SF_SEQUENTIAL) && (fr->data)) SFMMSEQOFF(fr,fr->data,fr->endb-fr->data); fr->bits &= ~SF_SEQUENTIAL; } if(rbuf) free(rbuf); SFOPEN(fr,0); if(fw) { SFOPEN(fw,0); SFMTXUNLOCK(fw); } SFMTXRETURN(fr, n_move); } move -= r; } if(fr->extent >= 0) (void)SFSEEK(fr,(Sfoff_t)(-r),1); break; } } again: SFOPEN(fr,0); if(fw) SFOPEN(fw,0); } done: if(n < 0 && (fr->bits&SF_MMAP) && (fr->bits&SF_MVSIZE)) { /* back to normal access mode */ SFMVUNSET(fr); if((fr->bits&SF_SEQUENTIAL)src/lib/sfio/Stdio_b/vsnprintf.c000644 151361 151361 00000000773 07432261704 016621 0ustar00kpvkpv000000 000000 #include "sfstdio.h" /* Internal printf engine to write to a string buffer ** Written by Kiem-Phong Vo */ #if __STD_C int vsnprintf(char* s, int n, const char* form, va_list args) #else int vsnprintf(s,n,form,args) reg char* s; reg int n; reg char* form; va_list args; #endif { return (s && form) ? sfvsprintf(s,n,form,args) : -1; } #if _lib___vsnprintf && !done_lib___vsnprintf && !defined(vsnprintf) #define done_lib___vsnprintf 1 #define vsnprintf __vsnprintf #include "vsnprintf.c" #endif h@src/lib/sfio/Stdio_b/snprintf.c000644 151361 151361 00000001222 07432261703 016420 0ustar00kpvkpv000000 000000 #include "sfstdio.h" /* Format a string with given buffer size. ** Written by Kiem-Phong Vo */ #if __STD_C int snprintf(char* s, int n, const char* form, ...) #else int snprintf(va_alist) va_dcl #endif { va_list args; reg int rv; #if __STD_C va_start(args,form); #else reg char* s; reg int n; reg char* form; va_start(args); s = va_arg(args,char*); n = va_arg(args,int); form = va_arg(args,char*); #endif rv = (s && form) ? sfvsprintf(s,n,form,args) : -1; va_end(args); return rv; } #if _lib___snprintf && !done_lib___snprintf && !defined(snprintf) #define done_lib___snprintf 1 #define snprintf __snprintf #include "snprintf.c" #endif har* form, ...) #else int snprintf(va_alist) va_dcl #endif { va_list args; reg int rv; #if __STD_C va_start(args,form); #else reg char* s; reg int n; reg char* form; va_start(args); s = va_arg(args,char*); n = va_arg(args,int); form = va_arg(args,char*); #endif rv = (s && form) ? sfvsprintf(s,n,form,args) : -1; va_end(args); return rv; } #if _lisrc/lib/sfio/Stdio_b/fdopen.c000644 151361 151361 00000001057 07432261677 016050 0ustar00kpvkpv000000 000000 #include "sfstdio.h" /* Opening a stream given a file descriptor. ** Written by Kiem-Phong Vo */ #if __STD_C FILE* fdopen(int fd, const char* mode) #else FILE* fdopen(fd,mode) int fd; char* mode; #endif { reg Sfio_t* sf; reg FILE* f; int flags, uflag; if((flags = _sftype(mode,NIL(int*),&uflag)) == 0) return NIL(FILE*); if(!uflag) flags |= SF_MTSAFE; if(!(sf = sfnew(NIL(Sfio_t*), NIL(Void_t*), (size_t)SF_UNBOUND, fd, flags))) return NIL(FILE*); if(!(f = _stdstream(sf, NIL(FILE*)))) { sfclose(sf); return NIL(FILE*); } return(f); } a file descriptor. ** Written by Kiem-Phong Vo */ #if __STD_C FILE* fdopen(int fd, const char* mode) #else FILE* fdopen(fd,mode) int fd; char* mode; #endif { reg Sfio_t* sf; reg FILE* f; int flags, uflag; if((flags = _sftype(mode,NIL(int*),&uflag)) == 0) return NIL(FILE*); if(!uflag) flags |= SF_MTSAFE; if(!(sf = sfnew(NIL(Sfio_t*), NIL(Void_t*), (size_t)SF_UNBOUND, fd, flags))) return NIL(FILE*); if(!(f = _stdstream(sf, NIL(FILE*)))) { sfclosrc/lib/sfio/Stdio_b/fopen.c000644 151361 151361 00000000713 07432261700 015665 0ustar00kpvkpv000000 000000 #include "sfstdio.h" /* Opening a stream ** Written by Kiem-Phong Vo */ #if __STD_C FILE* fopen(char* name,const char* mode) #else FILE* fopen(name,mode) char* name; char* mode; #endif { reg FILE* f; reg Sfio_t* sf; if(!(sf = sfopen(NIL(Sfio_t*), name, mode)) ) f = NIL(FILE*); else if(!(f = _stdstream(sf, NIL(FILE*)))) sfclose(sf); else { int uflag; _sftype(mode, NIL(int*), &uflag); if(!uflag) sf->flags |= SF_MTSAFE; } return(f); } V=Jg%flags |= SF_MTSAFE; } return(f); } %next) if(f->offset < fp->offset) break; if(last) { f->next = last->next; last->next = f; } else { f->next = head; head = f; } return head; } #if __STD_C int fldprint(int size, char* name, char* type) #else int fldprint(size,name,type) int size; char* name; char* type; #endif { if(type) printf("\t%s\t%s;\n",type,name); else if(size == sizeof(char)) printf("\tchar\t%s;\n",name); else if(size == sizeof(short)) printf("\tshort\t%s;\n",name); else if(size == sizeof(int)) printf("\tint\t%s;\n",name); else printf("\tlong\t%s;\n",name); return 0; } int main() { int pos, gap, s; Field_t *list, *f; Field_t field[64]; /* construct the order list of the fields of interest */ list = NIL(Field_t*); f = field; #ifdef std_cnt /* old-stdio _cnt */ f->offset = Offsetof(std_cnt); f->size = Sizeof(std_cnt); f->type = STD_CNT; f->next = NIL(Field_t*); list = fldinsert(list,f); f += 1; #endif #ifdef std_r /* BSD-stdio _r (read count) */ f->offset = Offsetof(std_r); f->size = Sizeof(std_r); f->type = STD_R; f->next = NIL(Field_t*); list = fldinsert(list,f); f += 1; #endif #ifdef std_w /* BSD-stdio _w (write count) */ f->offset = Offsetof(std_w); f->size = Sizeof(std_w); f->type = STD_W; f->next = NIL(Field_t*); list = fldinsert(list,f); f += 1; #endif #ifdef std_ptr /* old-stdio _ptr */ f->offset = Offsetof(std_ptr); f->size = Sizeof(std_ptr); f->type = STD_PTR; f->next = NIL(Field_t*); list = fldinsert(list,f); f += 1; #endif #ifdef std_p /* BSD-stdio _p */ f->offset = Offsetof(std_p); f->size = Sizeof(std_p); f->type = STD_PTR; f->next = NIL(Field_t*); list = fldinsert(list,f); f += 1; #endif #ifdef std_readptr /* Linux-stdio _IO_read_ptr */ f->offset = Offsetof(std_readptr); f->size = Sizeof(std_readptr); f->type = STD_READPTR; f->next = NIL(Field_t*); list = fldinsert(list,f); f += 1; #endif #ifdef std_readend /* Linux-stdio _IO_read_end */ f->offset = Offsetof(std_readend); f->size = Sizeof(std_readend); f->type = STD_READEND; f->next = NIL(Field_t*); list = fldinsert(list,f); f += 1; #endif #ifdef std_writeptr /* Linux-stdio _IO_write_ptr */ f->offset = Offsetof(std_writeptr); f->size = Sizeof(std_writeptr); f->type = STD_WRITEPTR; f->next = NIL(Field_t*); list = fldinsert(list,f); f += 1; #endif #ifdef std_writeend /* Linux-stdio _IO_write_end */ f->offset = Offsetof(std_writeend); f->size = Sizeof(std_writeend); f->type = STD_WRITEEND; f->next = NIL(Field_t*); list = fldinsert(list,f); f += 1; #endif #ifdef std_flag /* old-stdio _flag */ f->offset = Offsetof(std_flag); f->size = Sizeof(std_flag); f->type = STD_FLAG; f->next = NIL(Field_t*); list = fldinsert(list,f); f += 1; #endif #ifdef std_file /* old/BSD-stdio _file */ f->offset = Offsetof(std_file); f->size = Sizeof(std_file); f->type = STD_FILE; f->next = NIL(Field_t*); list = fldinsert(list,f); f += 1; #endif /* output standard protection */ printf("#ifndef _SFSTDIO_H\n"); printf("#define _SFSTDIO_H\t1\n\n"); printf("#include \"no_stdio.h\"\n\n"); printf("extern int\t_Stdstream;\n\n"); printf("extern int\t_Stdextern;\n\n"); #if defined(NAME_iob) || _msft_iob #if !_msft_iob if(strcmp(NAME_iob,"_iob") != 0) printf("#define _iob %s\n",NAME_iob); #endif printf("#define _do_iob 1\n\n"); #endif #ifdef NAME_sf if(strcmp(NAME_sf,"_sf") != 0) printf("#define _sf %s\n",NAME_sf); printf("#define _do_sf 1\n\n"); #endif #ifdef NAME_filbuf if(strcmp(NAME_filbuf,"_filbuf") != 0 ) printf("#define _filbuf %s\n",NAME_filbuf); if(__STD_C) printf("#define FILBUF(f) int _filbuf(FILE* f)\n"); else printf("#define FILBUF(f) int _filbuf(f) FILE* f;\n"); printf("#define _do_filbuf 1\n\n"); #endif #ifdef NAME_flsbuf if(strcmp(NAME_flsbuf,"_flsbuf") != 0) printf("#define _flsbuf %s\n",NAME_flsbuf); if(__STD_C) printf("#define FLSBUF(c,f) int _flsbuf(int c, FILE* f)\n"); else printf("#define FLSBUF(c,f) int _flsbuf(c,f) int c; FILE* f;\n"); printf("#define _do_flsbuf 1\n\n"); #endif #ifdef NAME_uflow if(strcmp(NAME_uflow,"_uflow") != 0 ) printf("#define _uflow %s\n",NAME_uflow); if(__STD_C) printf("#define FILBUF(f) int _uflow(FILE* f)\n"); else printf("#define FILBUF(f) int _uflow(f) FILE* f;\n"); printf("#define _do_uflow 1\n\n"); #endif #ifdef NAME_overflow if(strcmp(NAME_overflow,"_overflow") != 0) printf("#define _overflow %s\n",NAME_overflow); if(__STD_C) printf("#define FLSBUF(c,f) int _overflow(FILE* f, int c)\n"); else printf("#define FLSBUF(c,f) int _overflow(f,c) FILE* f; int c;\n"); printf("#define _do_overflow 1\n\n"); #endif #ifdef NAME_srget if(strcmp(NAME_srget,"_srget") != 0 ) printf("#define _srget %s\n",NAME_srget); if(__STD_C) printf("#define FILBUF(f) int _srget(FILE* f)\n"); else printf("#define FILBUF(f) int _srget(f) FILE* f;\n"); printf("#define _do_srget 1\n\n"); #endif #ifdef NAME_swbuf if(strcmp(NAME_swbuf,"_swbuf") != 0) printf("#define _swbuf %s\n",NAME_swbuf); if(__STD_C) printf("#define FLSBUF(c,f) int _swbuf(int c, FILE* f)\n"); else printf("#define FLSBUF(c,f) int _swbuf(c,f) int c; FILE* f;\n"); printf("#define _do_swbuf 1\n\n"); #endif #if _pragma_weak printf("#if _in_doprnt\n"); printf("#pragma weak _doprnt = __doprnt\n"); printf("#define _doprnt __doprnt\n"); printf("#endif\n\n"); printf("#if _in_doscan\n"); printf("#pragma weak _doscan = __doscan\n"); printf("#define _doscan __doscan\n"); printf("#endif\n\n"); #ifdef NAME_iob printf("#if _in_stdextern\n"); printf("#pragma weak %s = _%s\n",NAME_iob,NAME_iob); printf("#define %s _%s\n",NAME_iob,NAME_iob); printf("#endif\n\n"); #endif #ifdef NAME_filbuf printf("#if _in_filbuf\n"); printf("#pragma weak %s = _%s\n",NAME_filbuf,NAME_filbuf); printf("#define %s _%s\n",NAME_filbuf,NAME_filbuf); printf("#endif\n\n"); #endif #ifdef NAME_flsbuf printf("#if _in_flsbuf\n"); printf("#pragma weak %s = _%s\n",NAME_flsbuf,NAME_flsbuf); printf("#define %s _%s\n",NAME_flsbuf,NAME_flsbuf); printf("#endif\n\n"); #endif #ifdef NAME_uflow printf("#if _do_filbuf\n"); /* not a bug! */ printf("#pragma weak %s = _%s\n",NAME_uflow,NAME_uflow); printf("#define %s _%s\n",NAME_uflow,NAME_uflow); printf("#endif\n\n"); #endif #ifdef NAME_overflow printf("#if _do_flsbuf\n"); /* not a bug! */ printf("#pragma weak %s = _%s\n",NAME_overflow,NAME_overflow); printf("#define %s _%s\n",NAME_overflow,NAME_overflow); printf("#endif\n\n"); #endif #ifdef NAME_srget printf("#if _do_filbuf\n"); /* not a bug! */ printf("#pragma weak %s = _%s\n",NAME_srget,NAME_srget); printf("#define %s _%s\n",NAME_srget,NAME_srget); printf("#endif\n\n"); #endif #ifdef NAME_swbuf printf("#if _do_flsbuf\n"); /* not a bug! */ printf("#pragma weak %s = _%s\n",NAME_swbuf,NAME_swbuf); printf("#define %s _%s\n",NAME_swbuf,NAME_swbuf); printf("#endif\n\n"); #endif #endif/*_pragma_weak*/ #ifdef _NFILE #define N_FILE _NFILE #else #ifdef FOPEN_MAX #define N_FILE FOPEN_MAX #else #define N_FILE 3 #endif #endif printf("#define _NFILE %d\n\n", N_FILE); printf("/* preventing FILE to be defined in silly places */\n"); printf("#define\t_FILE_DEFINED\t1\t/* Windows */\n"); printf("#define\t_FILEDEFED\t1\t/* SUNOS5.8 */\n\n"); printf("#undef\tFILE\n"); printf("typedef struct _std_s\tFILE;\n\n"); /* now get what we need from sfio */ printf("#include\t\"sfhdr.h\"\n"); printf("#include\t\"FEATURE/stdio\"\n\n"); #ifdef _siz_fpos_t if(_siz_fpos_t == sizeof(short)) printf("#define stdfpos_t short\n"); else if(_siz_fpos_t == sizeof(int)) printf("#define stdfpos_t int\n"); #if _typ_long_long else if(_siz_fpos_t == sizeof(long long)) printf("#define stdfpos_t long long\n"); #endif else #endif /*_siz_fpos_t*/ printf("#define stdfpos_t long\n"); printf("\n"); #ifdef _siz_off_t if(_siz_off_t == sizeof(short)) printf("#define stdoff_t short\n"); else if(_siz_off_t == sizeof(int)) printf("#define stdoff_t int\n"); #if _typ_long_long else if(_siz_off_t == sizeof(long long)) printf("#define stdoff_t long long\n"); #endif else #endif /*_siz_off_t*/ printf("#define stdoff_t long\n"); printf("\n"); /* output FILE structure */ printf("\nstruct _std_s\n{\n"); gap = pos = 0; for(f = list; f; f = f->next) { if((s = f->offset - pos) > 0) /* fill the gap */ printf("\tuchar\tstd_gap%d[%d];\n",gap++,s); switch(f->type) { case STD_CNT : fldprint(f->size,"std_cnt",NIL(char*)); break; case STD_R : fldprint(f->size,"std_r",NIL(char*)); break; case STD_W : fldprint(f->size,"std_w",NIL(char*)); break; case STD_PTR : fldprint(f->size,"std_ptr","uchar*"); break; case STD_FLAG : fldprint(f->size,"std_flag",NIL(char*)); break; case STD_FILE : fldprint(f->size,"std_file",NIL(char*)); break; case STD_READPTR : fldprint(f->size,"std_readptr","uchar*"); break; case STD_READEND : fldprint(f->size,"std_readend","uchar*"); break; case STD_WRITEPTR : fldprint(f->size,"std_writeptr","uchar*"); break; case STD_WRITEEND : fldprint(f->size,"std_writeend","uchar*"); break; } pos = f->size+f->offset; } if((s = sizeof(FILE) - pos) > 0) /* last gap */ printf("\tuchar\tstd_gap%d[%d];\n",gap++,s); printf("};\n\n"); /* default values for a few typical stdio constants */ #ifndef BUFSIZ #define BUFSIZ 1024 #endif #ifndef _IOERR # ifdef _ERR # define _IOERR _ERR # else # ifdef _IO_ERR_SEEN # define _IOERR _IO_ERR_SEEN # else # ifdef __SERR # define _IOERR __SERR # else # define _IOERR 0 # endif # endif # endif #endif #ifndef _IOEOF # ifdef _EOF # define _IOEOF _EOF # else # ifdef _IO_EOF_SEEN # define _IOEOF _IO_EOF_SEEN # else # ifdef __SEOF # define _IOEOF __SEOF # else # define _IOEOF 0 # endif # endif # endif #endif #ifndef _IONBF # ifdef _UNBUF # define _IONBF _UNBUF # else # ifdef _IO_UNBUFFERED # define _IO_NBF _IO_UNBUFFERED # else # ifdef __SNBF # define _IONBF __SNBF # else # define _IONBF 0 # endif # endif # endif #endif #ifndef _IOLBF # ifdef _LINBUF # define _IOLBF _LINBUF # else # ifdef _IO_LINE_BUF # define _IOLBF _IO_LINE_BUF # else # ifdef __SLBF # define _IOLBF __SLBF # else # define _IOLBF 0 # endif # endif # endif #endif #ifndef _IOFBF # define _IOFBF 0 #endif printf("#define BUFSIZ\t\t%d\n",BUFSIZ); printf("#define _IOERR\t\t%#o\n",_IOERR); printf("#define _IOEOF\t\t%#o\n",_IOEOF); printf("#define _IONBF\t\t%#o\n",_IONBF); printf("#define _IOLBF\t\t%#o\n",_IOLBF); printf("#define _IOFBF\t\t%#o\n\n",_IOFBF); #ifdef std_flag printf("#define _seteof(fp)\t((fp)->std_flag |= _IOEOF)\n"); printf("#define _seterr(fp)\t((fp)->std_flag |= _IOERR)\n\n"); printf("#define _stdclrerr(fp)\t((fp)->std_flag &= ~(_IOEOF|_IOERR))\n"); printf("#define _stdseterr(fp,sp)\t((sfeof(sp) ? _seteof(fp) : 0), "); printf( "(sferror(sp) ? _seterr(fp) : 0) )\n\n" ); #else printf("#define _stdclrerr(fp)\t(0)\n"); printf("#define _stdseterr(fp,sp)\t(0)\n\n"); #endif printf("\n_BEGIN_EXTERNS_\n\n"); printf("#if _BLD_sfio && defined(__EXPORT__)\n"); printf("#define extern\t__EXPORT__\n"); printf("#endif\n"); #if defined(NAME_iob) || _msft_iob #define _have_streams 1 #if _msft_iob printf("\n#define _iob (__p__iob())\n"); printf("_CRTIMP extern FILE * __cdecl __p__iob(void);\n\n"); #else printf("\nextern FILE _iob[];\n"); #endif printf("#define stdin (&(_iob[0]))\n"); printf("#define stdout (&(_iob[1]))\n"); printf("#define stderr (&(_iob[2]))\n\n"); #endif #if defined(NAME_sf) && !_have_streams #define _have_streams 1 printf("\nextern FILE _sf[];\n"); printf("#define stdin (&(_sf[0]))\n"); printf("#define stdout (&(_sf[1]))\n"); printf("#define stderr (&(_sf[2]))\n\n"); #endif #if defined(NAME_swbuf) && defined(NAME_srget) && !_have_streams #define _have_streams 1 printf("\nextern FILE __sstdin, __sstdout, __sstderr;\n"); printf("#define stdin (&__sstdin)\n"); printf("#define stdout (&__sstdout)\n"); printf("#define stderr (&__sstderr)\n\n"); #endif /* Linux varieties */ #if SELF_stdin && !_have_streams #define _have_streams 1 printf("#define _do_self_stdin\t1\n"); printf("\nextern FILE *stdin, *stdout, *stderr;\n\n"); #endif #if AMPERSAND_IO_stdin && !_have_streams #define _have_streams 1 printf("#define _do_ampersand_stdin\t1\n"); printf("\nextern FILE _IO_stdin_, _IO_stdout_, _IO_stderr_;\n"); printf("#define stdin (&_IO_stdin_)\n"); printf("#define stdout (&_IO_stdout_)\n"); printf("#define stderr (&_IO_stderr_)\n\n"); #endif #if STAR_IO_stdin && !_have_streams #define _have_streams 1 printf("#define _do_star_stdin\t1\n"); printf("\nextern FILE *_IO_stdin_, *_IO_stdout_, *_IO_stderr_;\n"); printf("#define stdin _IO_stdin_\n"); printf("#define stdout _IO_stdout_\n"); printf("#define stderr _IO_stderr_\n\n"); #endif printf("extern void\t\t_sfunmap _ARG_((FILE*));\n"); printf("extern Sfio_t*\t\t_sfstream _ARG_((FILE*));\n"); printf("extern FILE*\t\t_stdstream _ARG_((Sfio_t*, FILE*));\n"); printf("extern char*\t\t_stdgets _ARG_((Sfio_t*,char*,int,int));\n"); printf("extern void\t\tclearerr _ARG_((FILE*));\n"); printf("extern int\t\t_doprnt _ARG_((const char*, va_list, FILE*));\n"); printf("extern int\t\t_doscan _ARG_((FILE*, const char*, va_list));\n"); printf("extern int\t\tfclose _ARG_((FILE*));\n"); printf("extern FILE*\t\tfdopen _ARG_((int, const char*));\n"); printf("extern int\t\tfeof _ARG_((FILE*));\n"); printf("extern int\t\tferror _ARG_((FILE*));\n"); printf("extern int\t\tfflush _ARG_((FILE*));\n"); printf("extern int\t\tfgetc _ARG_((FILE*));\n"); printf("extern char*\t\tfgets _ARG_((char*, int, FILE*));\n"); printf("extern int\t\t_filbuf _ARG_((FILE*));\n"); printf("extern int\t\t_uflow _ARG_((FILE*));\n"); printf("extern int\t\t_srget _ARG_((FILE*));\n"); printf("extern int\t\t_sgetc _ARG_((FILE*));\n"); printf("extern int\t\tfileno _ARG_((FILE*));\n"); printf("extern int\t\t_flsbuf _ARG_((int, FILE*));\n"); printf("extern int\t\t_overflow _ARG_((FILE*,int));\n"); printf("extern int\t\t_swbuf _ARG_((int,FILE*));\n"); printf("extern int\t\t_sputc _ARG_((int,FILE*));\n"); printf("extern void\t\t_cleanup _ARG_((void));\n"); printf("extern FILE*\t\tfopen _ARG_((char*, const char*));\n"); printf("extern int\t\tfprintf _ARG_((FILE*, const char* , ...));\n"); printf("extern int\t\tfputc _ARG_((int, FILE*));\n"); printf("extern int\t\tfputs _ARG_((const char*, FILE*));\n"); printf("extern size_t\t\tfread _ARG_((void*, size_t, size_t, FILE*));\n"); printf("extern FILE*\t\tfreopen _ARG_((char*, const char*, FILE*));\n"); printf("extern int\t\tfscanf _ARG_((FILE*, const char* , ...));\n"); printf("extern int\t\tfseek _ARG_((FILE*, long , int));\n"); printf("extern long\t\tftell _ARG_((FILE*));\n"); printf("extern int\t\tfgetpos _ARG_((FILE*,stdfpos_t*));\n"); printf("extern int\t\tfsetpos _ARG_((FILE*,stdfpos_t*));\n"); printf("extern int\t\tfpurge _ARG_((FILE*));\n"); printf("extern size_t\t\tfwrite _ARG_((const void*, size_t, size_t, FILE*));\n"); printf("extern int\t\tgetc _ARG_((FILE*));\n"); printf("extern int\t\tgetchar _ARG_((void));\n"); printf("extern char*\t\tgets _ARG_((char*));\n"); printf("extern int\t\tgetw _ARG_((FILE*));\n"); printf("extern int\t\tpclose _ARG_((FILE*));\n"); printf("extern FILE*\t\tpopen _ARG_((const char*, const char*));\n"); printf("extern int\t\tprintf _ARG_((const char* , ...));\n"); printf("extern int\t\tputc _ARG_((int, FILE*));\n"); printf("extern int\t\tputchar _ARG_((int));\n"); printf("extern int\t\tputs _ARG_((const char*));\n"); printf("extern int\t\tputw _ARG_((int, FILE*));\n"); printf("extern void\t\trewind _ARG_((FILE*));\n"); printf("extern int\t\tscanf _ARG_((const char* , ...));\n"); printf("extern void\t\tsetbuf _ARG_((FILE*, char*));\n"); printf("extern int\t\tsetbuffer _ARG_((FILE*, char*, size_t));\n"); printf("extern int\t\tsetlinebuf _ARG_((FILE*));\n"); printf("extern int\t\tsetvbuf _ARG_((FILE*,char*,int,size_t));\n"); printf("extern int\t\tsprintf _ARG_((char*, const char* , ...));\n"); printf("extern int\t\tsscanf _ARG_((const char*, const char* , ...));\n"); printf("extern FILE*\t\ttmpfile _ARG_((void));\n"); printf("extern int\t\tungetc _ARG_((int,FILE*));\n"); printf("extern int\t\tvfprintf _ARG_((FILE*, const char* , va_list));\n"); printf("extern int\t\tvfscanf _ARG_((FILE*, const char* , va_list));\n"); printf("extern int\t\tvprintf _ARG_((const char* , va_list));\n"); printf("extern int\t\tvscanf _ARG_((const char* , va_list));\n"); printf("extern int\t\tvsprintf _ARG_((char*, const char* , va_list));\n"); printf("extern int\t\tvsscanf _ARG_((char*, const char* , va_list));\n"); printf("extern void\t\tflockfile _ARG_((FILE*));\n"); printf("extern void\t\tfunlockfile _ARG_((FILE*));\n"); printf("extern int\t\tftrylockfile _ARG_((FILE*));\n"); printf("extern int\t\tsnprintf _ARG_((char*, int, const char*, ...));\n"); printf("extern int\t\tvsnprintf _ARG_((char*, int, const char*, va_list));\n"); printf("extern int\t\t__snprintf _ARG_((char*, int, const char*, ...));\n"); printf("extern int\t\t__vsnprintf _ARG_((char*, int, const char*, va_list));\n"); printf("\n_END_EXTERNS_\n"); printf("\n#endif /* _SFSTDIO_H */\n"); return 0; } f("extern void\t\tfunlockfile _ARG_((FILE*));\n"); printf("extern int\t\tftrylockfile _ARG_((FILE*));\n"); printf("extern int\t\tsnprintf _ARG_((char*, int, const char*, ...));\n"); printf("extern int\t\tvsnprintf _ARG_((char*, int, const char*, va_list));\n"); printf("extern int\t\t__snprintf _ARG_((char*, int, const char*, ...));\n"); src/lib/sfio/Stdio_b/no_stdio.h000644 151361 151361 00000002515 07432261702 016405 0ustar00kpvkpv000000 000000 #ifndef _NO_STDIO_H #define _NO_STDIO_H 1 /* While building the compatible stdio interface, we don't want ** to be included. Fortunately, these files tend to be protected by a single ** macro defined at the top of each file to prevent multiple inclusion. ** This header file defines the same macros here. ** ** Written by Kiem-Phong Vo. */ #ifndef __stdio_h__ #define __stdio_h__ 1 #endif #ifndef _stdio_h_ #define _stdio_h_ 1 #endif #ifndef _stdio_h #define _stdio_h 1 #endif #ifndef __h_stdio__ #define __h_stdio__ 1 #endif #ifndef _h_stdio_ #define _h_stdio_ 1 #endif #ifndef _h_stdio #define _h_stdio 1 #endif #ifndef __STDIO_H__ #define __STDIO_H__ 1 #endif #ifndef _STDIO_H_ #define _STDIO_H_ 1 #endif #ifndef _STDIO_H #define _STDIO_H 1 #endif #ifndef __H_STDIO__ #define __H_STDIO__ 1 #endif #ifndef _H_STDIO_ #define _H_STDIO_ 1 #endif #ifndef _H_STDIO #define _H_STDIO 1 #endif #ifndef _stdio_included #define _stdio_included 1 #endif #ifndef _included_stdio #define _included_stdio 1 #endif #ifndef _INCLUDED_STDIO #define _INCLUDED_STDIO 1 #endif #ifndef _STDIO_INCLUDED #define _STDIO_INCLUDED 1 #endif #ifndef _INC_STDIO #define _INC_STDIO 1 #endif #define _FILE_DEFINED 1 /* stop Windows from defining FILE */ #define _FILEDEFED 1 /* stop SUNOS5.8 ... */ #define __FILE_defined 1 /* stop Linux ... */ #endif/*_NO_STDIO_H*/ IO_ 1 #endif #ifndef _H_STDIO #define _H_STDIO 1 #endif #ifndef _stdio_included #define _stdio_included 1 #endif #ifndef _included_stdio #define _included_stdio 1 #endif #ifndef _src/lib/sfio/Stdio_b/ast54.sym000644 151361 151361 00000000500 07432261676 016112 0ustar00kpvkpv000000 000000 _Sfextern data _sfdlen _sffilbuf _sfflsbuf _sfllen _sfmode _sfputd _sfputl _sfputm _sfputu _sftype _stdgets sfclose sfclrlock sfmutex sfnew sfopen sfpopen sfpurge sfputr sfread sfseek sfset sfsetbuf sfsprintf sfsync sfstderr data sfstdin data sfstdout data sftmp sfungetc sfvprintf sfvscanf sfvsprintf sfvsscanf sfwrite NO_STDIO_H*/ IO_ 1 #endif #ifndef _H_STDIO #define _H_STDIO 1 #endif #ifndef _stdio_included #de ĵqAV=Jg%flags&(SF_LINE|SF_MTSAFE))) { /* fast access to buffer for putc benefit */ #if _FILE_writeptr f->std_writeptr = sf->next; f->std_writeend = sf->endb; #endif #if _FILE_readptr f->std_readptr = f->std_readend = NIL(uchar*); #endif #if _FILE_ptr || _FILE_p f->std_ptr = sf->next; #endif #if _FILE_cnt f->std_cnt = sf->endb - sf->next; #endif #if _FILE_w f->std_w = sf->endb - sf->next; #endif #if _FILE_r f->std_r = 0; #endif #if _FILE_writeptr || _FILE_cnt || _FILE_w /* internal protection against mixing of sfio/stdio */ sf->mode |= SF_STDIO; sf->endr = sf->endw = sf->data; #endif } return c; } eptr = sf->next; f->std_writeend = sf->endb; #endif #if _FILE_readptr f->std_readptr = f->std_readend = NIL(uchar*); #endif #if _FILE_ptr || _FILE_p f->std_ptr = sfsrc/lib/sfio/Stdio_b/filbuf.c000644 151361 151361 00000001604 07432261677 016042 0ustar00kpvkpv000000 000000 #define _in_filbuf 1 #include "sfstdio.h" /* Fill buffer. ** Written by Kiem-Phong Vo. */ FILBUF(f) { reg Sfio_t* sf; reg int rv; if(!(sf = _sfstream(f))) return -1; if((rv = sfgetc(sf)) < 0) _stdseterr(f,sf); else if(!(sf->flags&SF_MTSAFE) ) { #if _FILE_readptr /* Linux-stdio */ #if _under_flow && !_u_flow /* __underflow does not bump pointer */ f->std_readptr = sf->next-1; #else f->std_readptr = sf->next; #endif f->std_readend = sf->endb; #endif #if _FILE_writeptr f->std_writeptr = f->std_writeend = NIL(uchar*); #endif #if _FILE_ptr || _FILE_p /* old/BSD-stdio */ f->std_ptr = sf->next; #endif #if _FILE_cnt f->std_cnt = sf->endb - sf->next; #endif #if _FILE_r f->std_r = sf->endb - sf->next; #endif #if _FILE_w f->std_w = 0; #endif #if _FILE_readptr || _FILE_cnt || _FILE_r sf->mode |= SF_STDIO; sf->endr = sf->endw = sf->data; #endif } return(rv); } ext-1; #else f->std_readptr = sf->next; #endif f->std_readend = sf->endb; #endif #if _FILE_writeptr f->std_writeptr = src/lib/sfio/Stdio_b/stdstream.c000644 151361 151361 00000016064 07432261703 016575 0ustar00kpvkpv000000 000000 #include "sfstdio.h" int _Stdstream = 0; /* force loading this file */ /* Translation between sfio and stdio ** Written by Kiem-Phong Vo */ #if _FILE_readptr #define ISRDSYNC(f) (f->std_readptr == NIL(uchar*)) #else #define ISRDSYNC(f) (1) #endif #if _FILE_writeptr #define ISWRSYNC(f) (f->std_writeptr == NIL(uchar*)) #else #define ISWRSYNC(f) (1) #endif #if _FILE_cnt || _FILE_r || _FILE_w #define ISSYNC(f) (f->std_ptr == NIL(uchar*)) #else #define ISSYNC(f) (ISRDSYNC(f) && ISWRSYNC(f)) #endif typedef struct _stdmap_s Stdmap_t; struct _stdmap_s { FILE* f; /* the file */ Sfio_t* sf; /* its Sfio friend */ Stdmap_t* next; /* linked list */ }; #define STDMASK 255 #define STDINDEX(f) ((((ulong)(f))>>4) & STDMASK) #define SFSTREAM(f) (_Stdmap[STDINDEX(f)].f == f ? \ _Stdmap[STDINDEX(f)].sf : _sfstream(f) ) static Stdmap_t* _Stdmap[STDMASK+1]; /* the FILE -> Sfio_t mapping */ /* synchronizing sfio and stdio buffer pointers */ #if __STD_C static int _sfstdsync(Sfio_t* sf) #else static int _sfstdsync(sf) Sfio_t* sf; #endif { FILE* f; if(!sf || !(f = (FILE*)sf->stdio) ) return -1; SFMTXLOCK(sf); #if _FILE_readptr if(f->std_readptr >= sf->next && f->std_readptr <= sf->endb) sf->next = f->std_readptr; f->std_readptr = f->std_readend = NIL(uchar*); #endif #if _FILE_writeptr if(f->std_writeptr >= sf->next && f->std_writeptr <= sf->endb) sf->next = f->std_writeptr; f->std_writeptr = f->std_writeend = NIL(uchar*); #endif #if _FILE_cnt || _FILE_r || _FILE_w if(f->std_ptr >= sf->next && f->std_ptr <= sf->endb) sf->next = f->std_ptr; f->std_ptr = NIL(uchar*); #endif #if _FILE_cnt f->std_cnt = 0; #endif #if _FILE_r f->std_r = 0; #endif #if _FILE_w f->std_w = 0; #endif #if _FILE_readptr || _FILE_writeptr || _FILE_cnt || _FILE_w || _FILE_r if((sf->mode &= ~SF_STDIO) == SF_READ) sf->endr = sf->endb; else if(sf->mode == SF_WRITE && !(sf->flags&SF_LINE) ) sf->endw = sf->endb; #endif SFMTXUNLOCK(sf); return 0; } /* initialize a FILE stream using data from corresponding Sfio stream */ #if __STD_C static int _sfinit(FILE* f, Sfio_t* sf) #else static int _sfinit(f, sf) FILE* f; Sfio_t* sf; #endif { Stdmap_t* sm; int n; /* create the object mapping f to sf */ if(!(sm = (Stdmap_t*)malloc(sizeof(Stdmap_t))) ) return -1; sm->f = f; sm->sf = sf; n = STDINDEX(f); /* insert into hash table */ vtmtxlock(_Sfmutex); sm->next = _Stdmap[n]; _Stdmap[n] = sm; vtmtxunlock(_Sfmutex); /* initialize f and the map sf to f */ memclear(f,sizeof(FILE)); SFMTXLOCK(sf); #if _FILE_flag || _FILE_flags f->std_flag = ((sf->flags&SF_EOF) ? _IOEOF : 0) | ((sf->flags&SF_ERROR) ? _IOERR : 0); #endif #if _FILE_file || _FILE_fileno f->std_file = sffileno(sf); #endif sf->stdio = (Void_t*)f; SFMTXUNLOCK(sf); return 0; } /* initializing the mapping between standard streams */ #define STDINIT() (sfstdin->stdio ? 0 : _stdinit()) static int _stdinit() { SFONCE(); vtmtxlock(_Sfmutex); _Stdstream = _Stdextern = 1; if(!sfstdin->stdio) { _Sfstdsync = _sfstdsync; if(!(sfstdin->mode&SF_AVAIL)) _sfinit(stdin, sfstdin); if(!(sfstdout->mode&SF_AVAIL)) _sfinit(stdout, sfstdout); if(!(sfstderr->mode&SF_AVAIL)) _sfinit(stderr, sfstderr); } vtmtxunlock(_Sfmutex); return 0; } /* unmap a FILE stream */ #if __STD_C void _sfunmap(reg FILE* f) #else void _sfunmap(f) reg FILE* f; #endif { Stdmap_t *sm, *prev; reg int n; STDINIT(); if(!f) return; n = STDINDEX(f); prev = NIL(Stdmap_t*); vtmtxlock(_Sfmutex); for(sm = _Stdmap[n]; sm; prev = sm, sm = sm->next) { if(sm->f != f) continue; if(prev) prev->next = sm->next; else _Stdmap[n] = sm->next; free(sm); break; } vtmtxunlock(_Sfmutex); } /* map a FILE stream to a Sfio_t stream */ #if __STD_C Sfio_t* _sfstream(FILE* f) #else Sfio_t* _sfstream(f) FILE* f; #endif { Stdmap_t *sm, *prev; reg int n, flags; Sfpool_t *p; Sfio_t *sf = NIL(Sfio_t*); STDINIT(); if(!f) return NIL(Sfio_t*); vtmtxlock(_Sfmutex); for(prev = 0, sm = _Stdmap[n = STDINDEX(f)]; sm; prev = sm, sm = sm->next) if(sm->f == f) break; if(sm) { sf = sm->sf; if(prev) /* move-to-front */ { prev->next = sm->next; sm->next = _Stdmap[n]; _Stdmap[n] = sm; } } else { /* it is possible that f is really a Sfio_t* created by the source-compatibility package but is passed thru some other code that directly calls a Stdio function. We allow this by checking the list of known Sfio streams here. */ for(p = &_Sfpool; p && !sf; p = p->next) for(n = 0; n < p->n_sf && !sf; ++n) if(p->sf[n] == (Sfio_t*)f) sf = p->sf[n]; } vtmtxunlock(_Sfmutex); if(!sf) /* not much to do here */ return NIL(Sfio_t*); if(sm && !ISSYNC(f)) _sfstdsync(sf); if((sf->mode&SF_RDWR) != sf->mode) { flags = sf->flags; sf->flags |= SF_SHARE|SF_PUBLIC; n = _sfmode(sf,0,0); sf->flags = flags; if(n < 0) sfclrlock(sf); } if(sm) _stdclrerr(f); return sf; } /* map a Sfio_t stream to a FILE stream */ #if __STD_C FILE* _stdstream(Sfio_t* sf, FILE* f) #else FILE* _stdstream(sf, f) Sfio_t* sf; FILE* f; #endif { int did_malloc = 0; STDINIT(); if(!sf) return NIL(FILE*); if(!f) { if(sf == sfstdin) f = stdin; else if(sf == sfstdout) f = stdout; else if(sf == sfstderr) f = stderr; else if(!(f = (FILE*)malloc(sizeof(FILE))) ) return NIL(FILE*); else did_malloc = 1; } if(_sfinit(f, sf) < 0 && did_malloc) free(f); return f; } /* The following functions are never called from the application code. They are here to force loading of all compatibility functions so as to avoid name conflicts arising from local Stdio implementations. */ #define FORCE(f) ((void)__stdforce((Void_t*)f) ) #if __STD_C static Void_t* __stdforce(Void_t* fun) #else static Void_t* __stdforce(fun) Void_t* fun; #endif { return(fun); } void __stdiold() { FORCE(clearerr); FORCE(feof); FORCE(ferror); FORCE(fileno); FORCE(setbuf); FORCE(setbuffer); FORCE(setlinebuf); FORCE(setvbuf); FORCE(fclose); FORCE(fdopen); FORCE(fopen); FORCE(freopen); FORCE(popen); FORCE(pclose); FORCE(tmpfile); FORCE(fgetc); FORCE(getc); FORCE(getchar); FORCE(fgets); FORCE(gets); FORCE(getw); FORCE(fread); FORCE(fscanf); FORCE(scanf); FORCE(sscanf); FORCE(_doscan); FORCE(vfscanf); FORCE(vscanf); FORCE(vsscanf); FORCE(ungetc); #if _do_uflow FORCE(_uflow); #endif #if _do_filbuf FORCE(_filbuf); #endif #if _do_srget FORCE(_srget); #endif #if _do_sgetc FORCE(_sgetc); #endif FORCE(fputc); FORCE(putc); FORCE(putchar); FORCE(fputs); FORCE(puts); FORCE(putw); FORCE(fwrite); FORCE(fprintf); FORCE(printf); FORCE(sprintf); FORCE(_doprnt); FORCE(vfprintf); FORCE(vprintf); FORCE(vsprintf); FORCE(_cleanup); #if _do_overflow FORCE(_overflow); #endif #if _do_flsbuf FORCE(_flsbuf); #endif #if _do_swbuf FORCE(_swbuf); #endif #if _do_sputc FORCE(_sputc); #endif FORCE(fseek); FORCE(ftell); FORCE(rewind); FORCE(fflush); FORCE(fpurge); FORCE(fsetpos); FORCE(fgetpos); FORCE(flockfile); FORCE(ftrylockfile); FORCE(funlockfile); FORCE(snprintf); FORCE(vsnprintf); #if _lib___snprintf FORCE(__snprintf); #endif #if _lib___vsnprintf FORCE(__vsnprintf); #endif } rintf); FORCE(vsprintf); FORCE(_cleanup); #if _do_overflow FORCE(_overflow); #endif #if _do_flsbuf FORCE(_flsbuf); #endif #if _do_swbuf FORCE(_swbuf); #endif #if _do_sputc FORCE(_sputc); #endif FORCE(fseek); FORCE(ftell); FORCE(rewind); FORCE(fflush); FORCE(fpurge); FORCE(fsetpos); FORCE(fgetpos); FORCE(flockfile); FORCE(ftrylockfile); FORCE(funlockfile); FORCE(snprintf); FORCE(vsnprintf); #if _lib___snprintf FORCE(__snprintf); #endifsrc/lib/sfio/Stdio_b/stdextern.c000644 151361 151361 00000001721 07432261703 016601 0ustar00kpvkpv000000 000000 #define _in_stdextern 1 #include "sfstdio.h" int _Stdextern = 0; /* symbol to force loading of this file */ #if _native_iob #define _have_streams 1 #endif #if _do_iob && !_have_streams #define _have_streams 1 FILE _iob[_NFILE]; #endif #if _do_sf && !_have_streams /* BSDI2.0 */ FILE _sf[_NFILE]; #endif #if _do_swbuf && _do_srget && !_have_streams /*BSDI3.0*/ #define _have_streams 1 FILE __sstdin, __sstdout, __sstderr; #endif #if _do_self_stdin && !_have_streams /*Linux Redhat 6.0*/ #define _have_streams 1 FILE _Stdin_, *stdin = &_Stdin_; FILE _Stdout_, *stdout = &_Stdout_; FILE _Stderr_, *stderr = &_Stderr_; #endif #if _do_ampersand_stdin && !_have_streams /*Linux Redhat 5.2*/ #define _have_streams 1 FILE _IO_stdin_, _IO_stdout_, _IO_stderr_; #endif #if _do_star_stdin && !_have_streams /*Linux Redhat 5.2*/ #define _have_streams 1 FILE _Stdin_, *_IO_stdin = &_Stdin_; FILE _Stdout_, *_IO_stdout = &_Stdout_; FILE _Stderr_, *_IO_stderr = &_Stderr_; #endif reams /*Linux Redhat 6.0*/ #define _have_streamsrc/lib/sfio/Stdio_b/doscan.c000644 151361 151361 00000000707 07432261677 016045 0ustar00kpvkpv000000 000000 #define _in_doscan 1 #include "sfstdio.h" /* The internal scanf engine in older stdios. ** Written by Kiem-Phong Vo */ #if __STD_C int _doscan(FILE *f, const char* form, va_list args) #else int _doscan(f,form,args) FILE* f; char* form; /* format to use */ va_list args; /* arg list if argf == 0 */ #endif { reg int rv; reg Sfio_t* sf; if(!(sf = _sfstream(f))) return -1; if((rv = sfvscanf(sf,form,args)) <= 0) _stdseterr(f,sf); return rv; } V=Jg%/dev/null 2>&1'" 0 1 2 # Take cross-compiler name as an argument if test "$CC" != "" then C_C="$CC" else C_C="cc" fi if test "$1" = "" then CC="$C_C" else CC="$*" fi # initialize generated header file { echo '#include "ast_common.h"' echo '#include "FEATURE/sfio"' echo '#include "FEATURE/stdio"' } >sfstdhdr.h # Get full path name for stdio.h # make sure that the right stdio.h file will be included echo "#include " > kpv.xxx.c $CC -E kpv.xxx.c > kpv.xxx.cpp 2>/dev/null ed kpv.xxx.cpp >/dev/null 2>&1 <>sfstdhdr.h # determine the right names for the given objects for name in _iob _filbuf _flsbuf _uflow _overflow _sf _srget _swbuf _sgetc _sputc do { echo "#include " case $name in _iob) echo "kpvxxx: stdin;" ;; _filbuf) echo "kpvxxx: getc(stdin);" ;; _flsbuf) echo "kpvxxx: putc(0,stdout);" ;; _uflow) echo "kpvxxx: getc(stdin);" ;; _overflow) echo "kpvxxx: putc(0,stdout);" ;; _sf) echo "kpvxxx: stdin;" ;; _srget) echo "kpvxxx: getc(stdin);" ;; _swbuf) echo "kpvxxx: putc(0,stdout);" ;; esac } >kpv.xxx.c case $name in _iob) pat='_[a-z]*_*iob[a-zA-Z0-9_]*' ;; _filbuf) pat='__*fi[a-zA-Z0-9_]*buf[a-zA-Z0-9_]*' ;; _flsbuf) pat='__*fl[a-zA-Z0-9_]*buf[a-zA-Z0-9_]*' ;; _uflow) pat='__*u[a-z]*flow[a-zA-Z0-9_]*' ;; _overflow) pat='__*o[a-z]*flow[a-zA-Z0-9_]*' ;; _sf) pat='__*s[fF][a-zA-Z0-9_]*' ;; _srget) pat='__*sr[a-zA-Z0-9_]*' ;; _swbuf) pat='__*sw[a-zA-Z0-9_]*' ;; esac rm kpv.xxx.name >/dev/null 2>&1 $CC -E kpv.xxx.c > kpv.xxx.cpp 2>/dev/null grep kpvxxx kpv.xxx.cpp | grep "$pat" > kpv.xxx.name if test "`cat kpv.xxx.name`" = "" then echo "${name}_kpv" > kpv.xxx.name else ed kpv.xxx.name >/dev/null 2>&1 <>sfstdhdr.h done # Different Linuxes have different ways of defining stdin/stdout/stderr # We attempt to figure which is which here (08/16/1999). { echo "#include " echo "kpvxxx: stdin;" } > kpv.xxx.c cc -c -E kpv.xxx.c >kpv.xxx.cpp grep kpvxxx kpv.xxx.cpp > kpv.xxx.name p1='kpvxxx:[ ]*' p2='[ ]*;.*' ed kpv.xxx.name >/dev/null 2>&1 <>sfstdhdr.h { echo '#if _lib___srget && !defined(NAME_srget)' echo '#define NAME_srget "__srget"' echo '#undef _filbuf' echo '#define _filbuf __srget' echo '#endif' echo "" echo '#if _lib___swbuf && !defined(NAME_swbuf)' echo '#define NAME_swbuf "__swbuf"' echo '#undef _flsbuf' echo '#define _flsbuf __swbuf' echo '#endif' echo '#if _u_flow && !defined(NAME_uflow)' echo '#define NAME_uflow "__uflow"' echo '#undef _filbuf' echo '#define _filbuf __uflow' echo '#endif' echo '#if _under_flow && !_u_flow && !defined(NAME_uflow)' echo '#define NAME_uflow "__underflow"' echo '#undef _filbuf' echo '#define _filbuf __underflow' echo '#endif' echo "" echo '#if _lib___overflow && !defined(NAME_overflow)' echo '#define NAME_overflow "__overflow"' echo '#undef _flsbuf' echo '#define _flsbuf __overflow' echo '#endif' } >>sfstdhdr.h exit 0 low)' echo '#define NAME_uflow "__uflow"' echo '#undef _filbuf' echo '#define _filbuf __uflow' echo '#endif' echo '#if _under_flow && !_u_flow && !defined(NAME_uflow)' echo '#define NAME_uflow "__underflow"' echo '#undef _filbuf' echo '#define _filbuf __underflow' echo '#endif' echo "" echo '#if _lib___overflow && !defined(NAME_overflow)' echo '#define NAME_overflow src/lib/sfio/Stdio_b/setlinebuf.c000644 151361 151361 00000000374 07432261703 016724 0ustar00kpvkpv000000 000000 #include "sfstdio.h" /* Set line mode ** Written by Kiem-Phong Vo */ #if __STD_C int setlinebuf(reg FILE* f) #else int setlinebuf(f) reg FILE* f; #endif { reg Sfio_t* sf; if(!(sf = _sfstream(f))) return -1; sfset(sf,SF_LINE,1); return(0); } _flow && !_u_flow && !defined(NAME_uflow)' echo '#define NAME_uflow "__underflow"' echo '#undef _filbuf' echo '#define _filbuf __underflow' echo '#endif'  ĵqAV=Jg%= 0) return (esize == 0 ? 0 : rv/esize); else { _stdseterr(f,sf); return 0; } } #if _lib_fread_unlocked && !_done_fread_unlocked && !defined(fread) #define _done_fread_unlocked 1 #define fread fread_unlocked #include "fread.c" #undef fread #endif _t nelts, reg FILE* f) #else size_t fread(buf,esize,nelts,f) reg Void_t* buf; reg size_t esize; reg size_t nelts; reg FILE* f; #endif { reg Sfio_t* sf; reg ssize_t rv; if(!buf || !(sf = _sfstream(f))) return 0; if((rv = sfread(sf,buf,esize*nelts)) >= 0) return (esize == 0 ? 0 : rv/esize); else { _stdseterr(f,sf); return 0; } } #if _lib_fread_unlocked && !_done_fsrc/lib/sfio/Stdio_b/Makefile000644 151361 151361 00000004604 07432261676 016071 0ustar00kpvkpv000000 000000 # makefile for libstdio.a and libstdio-mt.a # # Written by Kiem-Phong Vo # Compiler and flags to use LIBTYPE= AR= ar CC= cc CXFLAGS= CCMODE= -O CCFLAGS= -I. -I.. $(CCMODE) $(LIBTYPE) $(CXFLAGS) BINDIR= ../../../bin HDRS= no_stdio.h MISC= Sfstdhdr.sh Sfstdio.c ast54.sym stdio.def SRCS= doprnt.c doscan.c fclose.c fdopen.c fflush.c fgetc.c fgets.c filbuf.c \ flsbuf.c fopen.c fprintf.c fputc.c fputs.c fread.c freopen.c fscanf.c \ fseek.c ftell.c fwrite.c getc.c getchar.c gets.c getw.c pclose.c popen.c \ printf.c putc.c putchar.c puts.c putw.c rewind.c scanf.c setbuf.c setbuffer.c \ setlinebuf.c setvbuf.c sprintf.c sscanf.c stdextern.c stdstream.c \ tmpfile.c ungetc.c vfprintf.c vfscanf.c vprintf.c vscanf.c vsprintf.c \ vsscanf.c fileno.c feof.c ferror.c clearerr.c fpurge.c fgetpos.c fsetpos.c \ cleanup.c vsnprintf.c snprintf.c flockfile.c ftrylockfile.c funlockfile.c OBJS= doprnt.o doscan.o fclose.o fdopen.o fflush.o fgetc.o fgets.o filbuf.o \ flsbuf.o fopen.o fprintf.o fputc.o fputs.o fread.o freopen.o fscanf.o \ fseek.o ftell.o fwrite.o getc.o getchar.o gets.o getw.o pclose.o popen.o \ printf.o putc.o putchar.o puts.o putw.o rewind.o scanf.o setbuf.o setbuffer.o \ setlinebuf.o setvbuf.o sprintf.o sscanf.o stdextern.o stdstream.o \ tmpfile.o ungetc.o vfprintf.o vfscanf.o vprintf.o vscanf.o vsprintf.o \ vsscanf.o fileno.o feof.o ferror.o clearerr.o fpurge.o fsetpos.o fgetpos.o \ cleanup.o vsnprintf.o snprintf.o flockfile.o ftrylockfile.o funlockfile.o .c.o: $(CC) -c $(CCFLAGS) $*.c libstdio.a: stdio_ut ../FEATURE/stdio sfstdio.h $(OBJS) $(AR) cr libstdio.a $(OBJS) -(ranlib libstdio.a; exit 0) >/dev/null 2>&1 stdio_ut: echo ""; echo "BUILDING UNI-THREADED libstdio.a"; libstdio-mt.a: stdio_mt ../FEATURE/stdio sfstdio.h $(OBJS) $(AR) cr libstdio-mt.a $(OBJS) -(ranlib libstdio-mt.a; exit 0) >/dev/null 2>&1 stdio_mt: echo ""; echo "BUILDING MULTI-THREADED libstdio-mt.a"; ../FEATURE/stdio: ../features/stdio cd ..; $(BINDIR)/iffe set cc $(CC) $(CCMODE) $(CXFLAGS) : run features/stdio sfstdio.h: Sfstdio.c Sfstdhdr.sh ./Sfstdhdr.sh $(CC) $(CCFLAGS) $(CC) $(CCFLAGS) Sfstdio.c -o Sfstdgen ./Sfstdgen > sfstdio.h -(rm Sfstdgen sfstdhdr.h $(OBJS) libstdio.a libstdio-mt.a; exit 0) >/dev/null 2>&1 3dupdate: cp Makefile $(MISC) $(HDRS) $(SRCS) ... clean: -(rm $(OBJS) Sfstdgen sfstdhdr.h; exit 0) >/dev/null 2>&1 -(rm libstdio.a libstdio-mt.a sfstdio.h; exit 0) >/dev/null 2>&1 ./FEATURE/stdio: ../features/stdio cd ..; $(BINDIR)/iffe set cc $(CC) $(CCMODE) $(CXFLAGS) : run features/stdio sfstdio.h:src/lib/sfio/Stdio_b/fseek.c000644 151361 151361 00000001601 07432261701 015651 0ustar00kpvkpv000000 000000 #include "sfstdio.h" /* Reposition stream IO pointer ** Written by Kiem-Phong Vo */ #ifndef lcloff_t #define lcloff_t long #endif #if __STD_C int fseek(FILE* f, lcloff_t offset, int whence) #else int fseek(f,offset,whence) reg FILE* f; reg lcloff_t offset; reg int whence; #endif { reg Sfio_t* sf; if(!(sf = _sfstream(f))) return -1; /* ready for either read or write */ #if _FILE_cnt f->std_cnt = 0; #endif #if _FILE_r f->std_r = 0; #endif #if _FILE_w f->std_w = 0; #endif #if _FILE_readptr f->std_readptr = f->std_readend = NIL(uchar*); #endif #if _FILE_writeptr f->std_writeptr = f->std_writeend = NIL(uchar*); #endif return sfseek(sf, (Sfoff_t)offset, whence|SF_SHARE) < (Sfoff_t)0 ? -1 : 0; } #if _lib_fseeko && !_done_fseeko && !defined(fseek) #define _done_fseeko 1 #undef lcloff_t #define lcloff_t stdoff_t #define fseek fseeko #include "fseek.c" #undef fseek #endif _FILE_cnt f->std_cnt = 0; #endif #if _FILE_r f->std_r = 0; #endif #if _FILE_w f->std_w = 0; #endif #if _FILE_readptr f->stsrc/lib/sfio/Stdio_b/fileno.c000644 151361 151361 00000000626 07432261677 016052 0ustar00kpvkpv000000 000000 #include "sfstdio.h" /* Return file number. ** Written by Kiem-Phong Vo. */ #if __STD_C int fileno(FILE* f) #else int fileno(f) FILE* f; #endif { reg Sfio_t* sf; if(!(sf = _sfstream(f))) return -1; return sffileno(sf); } #if _lib_fileno_unlocked && !_done_fileno_unlocked && !defined(fileno) #define _done_fileno_unlocked 1 #define fileno fileno_unlocked #include "fileno.c" #undef fileno #endif t = 0; #en ĵqAV=Jg%extent >= 0) (void)sfseek(sf, (Sfoff_t)0, SEEK_CUR|SF_PUBLIC); return (sfsync(sf) < 0 || sfpurge(sf) < 0) ? -1 : 0; } #if _lib_fflush_unlocked && !_done_fflush_unlocked && !defined(fflush) #define _done_fflush_unlocked 1 #define fflush fflush_unlocked #include "fflush.c" #undef fflush #endif Written by Kiem-Phong Vo. */ #if __STD_C int fflush(reg FILE* f) #else int fflush(f) reg FILE* f; #endif { reg Sfio_t* sf; if(!f) return sfsync(NIL(Sfio_t*)); if(!(sf = _sfstream(f))) return -1; if(sf->extent >= 0) (void)sfseek(sf, (Sfoff_t)0, SEEK_CUR|SF_PUBLIC); return (sfsync(sf) < 0 || sfpurge(sf) < 0) ? -1 : 0; } #if _lib_fflush_unlocked && !_done_fflush_unlocked src/lib/sfio/Stdio_b/freopen.c000644 151361 151361 00000001037 07432261700 016214 0ustar00kpvkpv000000 000000 #include "sfstdio.h" /* Reopening a stream ** Written by Kiem-Phong Vo */ #if __STD_C FILE* freopen(char*name, const char* mode, reg FILE* f) #else FILE* freopen(name,mode,f) reg char* name; reg char* mode; reg FILE* f; #endif { Sfio_t* sf; if(f && (sf = _sfstream(f)) ) _sfunmap(f); if(!(sf = sfopen(sf, name, mode)) ) return NIL(FILE*); else { int uflag; _sftype(mode, NIL(int*), &uflag); if(!uflag) sf->flags |= SF_MTSAFE; if(_stdstream(sf,f) != f) { sfclose(sf); return NIL(FILE*); } else return f; } } ing a stream ** Written by Kiem-Phong Vo */ #if __STD_C FILE* freopen(char*name, const char* mode, reg FILE* f) #else FILE* freopen(name,mode,f) reg char* name; reg char* mode; reg FILE* f; #endif { Sfio_t* sf; if(f && (sf = _sfstream(f)) ) _sfunmap(f); if(!(sf = sfopen(sf, name, mode)) ) return NIL(FILE*); else { int uflag; _sftype(mode, NIL(int*), &uflag); if(!uflag) sf->flags |= SF_MTSAFE; if(_stdstream(sf,f) != f) { sfclose(sf); return NIL(FILsrc/lib/sfio/Stdio_b/vfscanf.c000644 151361 151361 00000000672 07432261704 016214 0ustar00kpvkpv000000 000000 #include "sfstdio.h" /* Internal scanf engine ** Written by Kiem-Phong Vo */ #if __STD_C int vfscanf(FILE* f, const char* form, va_list args) #else int vfscanf(f,form,args) FILE* f; char* form; /* format to use */ va_list args; /* arg list if argf == 0 */ #endif { reg int rv; reg Sfio_t* sf; if(!form || !(sf = _sfstream(f))) return -1; if((rv = sfvscanf(sf,form,args)) <= 0) _stdseterr(f,sf); return rv; } AV=Jg%= 0 ? 0 : -1; } pos ? 0 : -1; } ((rv = sfvscanf(sf,form,args)) <= 0) _stdset ĵqAV=Jg%= 0 ? 0 : -1; } pos ? 0 : -1; } ((rv = sfvscanf(sf,form,args)) <= 0) _stdset ĵqAV=Jg%= 0) return (esize == 0 ? 0 : rv/esize); else { _stdseterr(f,sf); return 0; } } #if _lib_fwrite_unlocked && !_done_fwrite_unlocked && !defined(fwrite) #define _done_fwrite_unlocked 1 #define fwrite fwrite_unlocked #include "fwrite.c" #undef fwrite #endif nelts, reg FILE* f) #else size_t fwrite(buf,esize,nelts,f) reg Void_t* buf; reg size_t esize; reg size_t nelts; reg FILE* f; #endif { reg ssize_t rv; reg Sfio_t* sf; if(!(sf = _sfstream(f))) return 0; if((rv = sfwrite(sf,buf,esize*nelts)) >= 0) return (esize == 0 ? 0 : rv/esize); else { _stdseterr(f,sf); return 0; } } #if _lib_fwrite_unlocked && !src/lib/sfio/Stdio_b/clearerr.c000644 151361 151361 00000000705 07432261677 016373 0ustar00kpvkpv000000 000000 #include "sfstdio.h" /* Clear error status from a stream ** ** Written by Kiem-Phong Vo. */ #if __STD_C void clearerr(FILE* f) #else void clearerr(f) FILE* f; #endif { reg Sfio_t* sf; if(f && (sf = _sfstream(f)) ) { sfclrlock(sf); _stdclrerr(f); } } #if _lib_clearerr_unlocked && !_done_clearerr_unlocked && !defined(clearerr) #define _done_clearerr_unlocked 1 #define clearerr clearerr_unlocked #include "clearerr.c" #undef clearerr #endif V=Jg%flags |= SF_MTSAFE; return f; } ned(clearerr) #define _done_clearerr_unlocked 1 #define clearerr clearerr_unlocked #include  ĵqAV=Jg%= 0 && f != stdin && f != stdout && f != stderr) { _sfunmap(f); /* remove the FILE to Sfio_t map */ free(f); } return rv; } orm || !(sf = _sfstream(stdout))) retur ĵqAV=Jg% #ifndef NIL #define NIL(t) ((t)0) #endif #if __STD_C #include #else #include #endif _BEGIN_EXTERNS_ #if !_SFIO_H extern int sprintf _ARG_((char*, const char*, ...)); extern int vsprintf _ARG_((char*, const char*, va_list)); #endif extern int atexit _ARG_((void (*)(void))); extern void exit _ARG_((int)); extern size_t strlen _ARG_((const char*)); extern Void_t* malloc _ARG_((size_t)); extern char* getenv _ARG_((const char*)); extern int strncmp _ARG_((const char*, const char*, size_t)); extern int strcmp _ARG_((const char*, const char*)); extern int system _ARG_((const char*)); #if !_hdr_unistd extern int alarm _ARG_((int)); extern int sleep _ARG_((int)); extern int fork(); extern int wait _ARG_((int*)); extern int access _ARG_((const char*, int)); extern int write _ARG_((int, const void*, int)); extern int unlink _ARG_((const char*)); extern Void_t* sbrk _ARG_((int)); extern int getpid(); #endif extern void tsterror _ARG_((char*, ...)); extern void tstwarn _ARG_((char*, ...)); extern void tstsuccess _ARG_((char*, ...)); _END_EXTERNS_ static int Tstline; static char Tstfile[16][256]; #ifdef __LINE__ #define terror (Tstline=__LINE__),tsterror #else #define terror (Tstline=-1),tsterror #endif #ifdef __LINE__ #define twarn (Tstline=__LINE__),tstwarn #else #define twarn (Tstline=-1),tstwarn #endif #ifdef __LINE__ #define tsuccess (Tstline=__LINE__),tstsuccess #else #define tsuccess (Tstline=-1),tstsuccess #endif #define tmesg (Tstline=-1),tstwarn #ifdef DEBUG #ifdef __LINE__ #define TSTDEBUG(x) (Tstline=__LINE__),tstwarn x #else #define TSTDEBUG(x) (Tstline=-1),tstwarn x #endif #else #define TSTDEBUG(x) #endif #ifndef MAIN #if __STD_C #define MAIN() main(int argc, char** argv) #else #define MAIN() main(argc, argv) int argc; char** argv; #endif #endif /*MAIN*/ #ifndef TSTEXIT #define TSTEXIT(v) { tstcleanup(); exit(v); } #endif static void tstcleanup() { #ifdef DEBUG twarn("Temp files will not be removed"); #else int i; for(i = 0; i < sizeof(Tstfile)/sizeof(Tstfile[0]); ++i) if(Tstfile[i][0]) unlink(Tstfile[i]); #endif } #if __STD_C static void tstputmesg(int line, char* form, va_list args) #else static void tstputmesg(line, form, args) int line; char* form; va_list args; #endif { char *s, buf[1024]; int n; for(n = 0; n < sizeof(buf); ++n) buf[n] = 0; s = buf; if(line >= 0) { sprintf(s,"\tLine=%d: ", line); s += strlen(s); } vsprintf(s,form,args); if((n = strlen(buf)) > 0) { if(buf[n-1] != '\n') { buf[n] = '\n'; n += 1; } write(2,buf,n); } } #if __STD_C void tsterror(char* form, ...) #else void tsterror(va_alist) va_dcl #endif { char failform[1024]; va_list args; #if __STD_C va_start(args,form); #else char* form; va_start(args); form = va_arg(args,char*); #endif sprintf(failform, "Failure: %s", form); tstputmesg(Tstline,failform,args); va_end(args); tstcleanup(); exit(1); } #if __STD_C void tstsuccess(char* form, ...) #else void tstsuccess(va_alist) va_dcl #endif { va_list args; #if __STD_C va_start(args,form); #else char* form; va_start(args); form = va_arg(args,char*); #endif tstputmesg(Tstline,form,args); va_end(args); tstcleanup(); exit(0); } #if __STD_C void tstwarn(char* form, ...) #else void tstwarn(va_alist) va_dcl #endif { va_list args; #if __STD_C va_start(args,form); #else char* form; va_start(args); form = va_arg(args,char*); #endif tstputmesg(Tstline,form,args); va_end(args); } #if __STD_C static char* tstfile(int n) #else static char* tstfile(n) int n; #endif { static int Setatexit = 0; if(!Setatexit) { Setatexit = 1; atexit(tstcleanup); } if(n >= sizeof(Tstfile)/sizeof(Tstfile[0])) terror("Bad temporary file request:%d\n", n); if(!Tstfile[n][0]) { #ifdef DEBUG sprintf(Tstfile[n], "Tstfile.%c%c%c", '0'+n, '0'+n, '0'+n); #else static int pid; static char* tmp; if (!tmp) { if (!(tmp = (char*)getenv("TMPDIR")) || access(tmp, 0) != 0) tmp = "/tmp"; pid = (int)getpid() % 10000; } sprintf(Tstfile[n], "%s/sft.%c.%d", tmp, '0'+n, pid); #endif } return Tstfile[n]; } ; atexit(tstcleanup); } if(n >= sizeof(Tstfile)/sizeof(Tstfile[0])) terror("Bad temporary file request:%d\n", n); if(!Tstfile[n][0]) { #ifdef DEBUG sprintf(Tstfile[n], "Tstfile.%c%c%c", '0'+n, '0'+n, '0'+n); #else static int pid; static char* tmp; if (!tmp) { if (!(tmp = (char*)getenv("TMPDIR")) || access(tmp, 0) != 0) tmp = "/tmp"; pid = (int)getpid() % 10000; } sprintf(Tstfile[n], "%s/src/lib/sfio/Stdio_t/stdtest.h000644 151361 151361 00000000303 07437012076 016277 0ustar00kpvkpv000000 000000 #include "../FEATURE/sfio" #include "terror.h" #include #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif le[n][0]) { #ifdef DEBUG sprintf(Tstfile[n], "Tstfile.%c%c%c", '0'+n, '0'+n, '0'+n); #else static int pid; static char* tmp; if (!tmp) { if (!(tmp = (char*)getenv("TMPDIR")) || access(tmp, 0) != 0) tmp = "/ CPAV=>"lx<9i l<9i l@src/lib/sfio/Stdio_t/twrrd.c000644 151361 151361 00000001034 07235635475 015756 0ustar00kpvkpv000000 000000 #include "stdtest.h" MAIN() { int i; char wbuf[1023]; char rbuf[1023]; FILE *fp; for(i = 0; i < sizeof(wbuf); ++i) wbuf[i] = (i%26)+'a'; wbuf[sizeof(wbuf)-1] = '\0'; if(!(fp = fopen(tstfile(0), "w+")) ) terror("Opening temp file\n"); for(i = 0; i < 256; ++i) if(fwrite(wbuf,sizeof(wbuf),1,fp) != 1) terror("Writing\n"); fseek(fp,(long)0,0); for(i = 0; i < 256; ++i) { if(fread(rbuf,sizeof(rbuf),1,fp) != 1) terror("Reading\n"); if(strcmp(rbuf,wbuf) != 0) terror("Unmatched record\n"); } TSTEXIT(0); } ) { int i; char wbuf[1023]; char rbuf[1023]; FILE *fp; for(i = 0; i < sizeof(wbuf); ++i) wbuf[i] = (i%26)+'a'; wbuf[sizeof(wbuf)-1] = '\0'; if(!(fp = fopen(tstfile(0), "w+")) ) terror("Opening temp file\n"); for(i = 0; i < 256; ++i) if(fwrite(wbuf,sizeof(wbuf),1,fp) != 1) terror("Writing\n"); fseek(fp,(long)0,0); for(i = 0; i < 256; ++i) { if(fread(rbuf,sizeof(rbuf),1,fp) != 1) terror("Reading\n"); if(strcmp(rbuf,wbuf) != 0) terror("Unmatched recsrc/lib/sfio/Stdio_t/tputgetc.c000644 151361 151361 00000000567 07235635467 016466 0ustar00kpvkpv000000 000000 #include "stdtest.h" MAIN() { FILE *f; int i, c; if(!(f = fopen(tstfile(0), "w+")) ) terror("Can't open temp file\n"); for(i = 0; i < 10000; ++i) if(fputc((i%26)+'a', f) < 0) terror("Writing %c\n",(i%26)+'a'); fseek(f, 0L, 0); for(i = 0; i < 10000; ++i) if((c = fgetc(f)) != ((i%26)+'a')) terror("Input=%#o, Expect=%c\n",c,(i%26)+'a'); TSTEXIT(0); } 0; i < 256; ++i) { if(fread(rbuf,sizeof( CPAV=>"lx<9i l<9i l@src/lib/sfio/Stdio_t/tfseek.c000644 151361 151361 00000001336 07235635445 016077 0ustar00kpvkpv000000 000000 #include "stdtest.h" MAIN() { FILE *fp; int i, c, e; if(!(fp = fopen(tstfile(0), "w+")) ) terror("Can't open temp file\n"); for(i = 0; i < 256; ++i) if(putc(i, fp) < 0) terror("Bad putc\n"); for(i = 1; i < 255; ++i) { if(fseek(fp, (long)(-i), SEEK_END) < 0) terror("fseek seek_end failed\n"); if((c = getc(fp)) != (e = 256-i) ) terror("Bad getc: expect %d, get %d\n", e, c); if(fseek(fp, (long)(i), SEEK_SET) < 0) terror("fseek seek_set failed\n"); if((c = getc(fp)) != i) terror("Bad getc: expect %d, get %d\n", i, c); if(fseek(fp, (long)(-1), SEEK_CUR) < 0) terror("fseek seek_cur failed\n"); if((c = getc(fp)) != i ) terror("Bad getc: expect %d, get %d\n", i, c); } TSTEXIT(0); } 255; ++i) { if(fseek(fp, (long)(-i), SEEK_END) < 0) terror("fseek seek_end failed\n"); if((c = getc(fp)) != (e = 256-i) ) terror("Bad getc: expect %d, get %d\n", e, c); if(fseek(fp, (long)(i), SEEK_SET) < 0) terror("fseek seek_set failed\n"); if((c = getc(fp)) != i) tersrc/lib/sfio/Stdio_t/tmesg.h000644 151361 151361 00000001126 06777423467 015750 0ustar00kpvkpv000000 000000 #if __STD_C void t_error(char* form, ...) #else void t_error(va_alist) va_dcl #endif { char *s, buf[1024]; int n; va_list args; #if __STD_C va_start(args,form); #else char* form; va_start(args); form = va_arg(args,char*); #endif s = buf; memset(buf, 0, sizeof(buf)); #ifdef __LINE__ sprintf(s,"Line=%d: ", Sftline); s += strlen(s); #endif vsprintf(s,form,args); va_end(args); if((n = strlen(buf)) > 0) { #if _PACKAGE_ast if(buf[n-1] == '\n') buf[n-1] = ' '; #else if(buf[n-1] != '\n') { buf[n] = '\n'; n += 1; } #endif write(2,buf,n); } sftcleanup(); exit(1); } char *s, buf[1024]; int n; va_list args; #if __STD_C va_start(args,form); #else char* form; va_start(args); form = va_arg(args,char*); #endif s = buf; memset(buf, 0, sizeof(buf)); #ifdef __LINE__ sprintf(s,"Line=%d: ", Sftline); s += strlen(s); #endif vsprintf(s,form,args); va_end(args); if((n = strlen(buf)) > 0) { #if _PACKAGE_ast if(buf[n-1] == '\n') buf[n-1] = ' '; #else if(buf[n-1] != '\n') { src/lib/sfio/Stdio_t/tmtsafe.c000644 151361 151361 00000006327 07437012137 016255 0ustar00kpvkpv000000 000000 #include "stdtest.h" #include #define N_STR 1000 static FILE* F; static char Bigz[10*N_STR]; static char* Str[26] = { "aaaaaaaaa", "bbbbbbbbb", "ccccccccc", "ddddddddd", "eeeeeeeee", "fffffffff", "ggggggggg", "hhhhhhhhh", "iiiiiiiii", "jjjjjjjjj", "kkkkkkkkk", "lllllllll", "mmmmmmmmm", "nnnnnnnnn", "ooooooooo", "ppppppppp", "qqqqqqqqq", "rrrrrrrrr", "sssssssss", "ttttttttt", "uuuuuuuuu", "vvvvvvvvv", "wwwwwwwww", "xxxxxxxxx", "yyyyyyyyy", "zzzzzzzzz" }; #if _STD_C void* writesmall(void* arg) #else void* writesmall(arg) void* arg; #endif { int n; char buf[16]; strcpy(buf, Str[(int)arg]); buf[9] = '\n'; buf[10] = 0; for(n = 0; n < N_STR; ++n) { if(fputs(buf, F) != 10) terror("fputs failed"); } return arg; } #if _STD_C void* writebig(void* arg) #else void* writebig(arg) void* arg; #endif { int r = (rand()%3) + 1; sleep(r); if(fwrite(Bigz,1,sizeof(Bigz),F) != sizeof(Bigz)) terror("Writing bigz"); return arg; } MAIN() { #if vt_threaded int count[26]; char* s; int i, k, n; char buf[1024]; Vthread_t* thread[26]; /* make the big z string */ for(i = 0, s = Bigz; i < N_STR; ++i, s += 10) strcpy(s, "zzzzzzzzz\n"); tmesg("\tTesting thread-safety\n"); /* spin threads writing small chunks */ F = fopen(tstfile(0),"w+"); for(i = 0; i < 26; ++i) { if(!(thread[i] = vtopen(0,0)) ) terror("Creating thread %d", i); if(vtrun(thread[i], writesmall, (Void_t*)i) < 0) terror("Running thread %d", i); } for(i = 0; i < 26; ++i) { count[i] = 0; vtwait(thread[i]); } if(fseek(F,0L,SEEK_SET) != 0) terror("Rewinding"); for(n = 0;; ++n) { if(!(s = fgets(buf, sizeof(buf), F)) ) break; i = s[0] - 'a'; if(i < 0 || i >= 26 || strlen(s) != 10) terror("Bad data s='%s' n=%d", s, n); s[9] = 0; if(strcmp(s, Str[i]) != 0) terror("Bad str s='%s' i=%d Str[i]='%s' n=%d", s, i, Str[i], n); count[i] += 1; } for(i = 0; i < 26; ++i) if(count[i] != N_STR) terror("Bad count[%d] = %d", i, count[i]); /* spin threads with one writing a big chunk */ F = fopen(tstfile(0),"w+"); for(i = 0; i < 25; ++i) { if(!(thread[i] = vtopen(0,0))) terror("Creating thread %d", i); if(vtrun(thread[i],writesmall,(void*)i) < 0) terror("Running thread %d", i); } sleep(1); if(!(thread[i] = vtopen(0,0)) ) terror("Creating big thread z"); if(vtrun(thread[i],writebig,(void*)i) < 0) terror("Running big thread z"); for(i = 0; i < 26; ++i) { count[i] = 0; vtwait(thread[i]); } if(fseek(F,0L,SEEK_SET) != 0) terror("Rewinding"); for(n = 0; ; ++n) { if(!(s = fgets(buf, sizeof(buf), F)) ) break; i = s[0] - 'a'; if(i < 0 || i >= 26 || strlen(s) != 10) terror("Bad data s='%s' n=%d", s, n); s[9] = 0; if(strcmp(s, Str[i]) != 0) terror("Bad str s='%s' i=%d Str[i]='%s' n=%d", s, i, Str[i], n); count[i] += 1; if(i == 25) /* the 'z' */ { for(k = 1; k < N_STR; ++k, ++n) { if(!(s = fgets(buf, sizeof(buf), F)) ) terror("Premature eof n=%d", n); s[9] = 0; if(strcmp(s, Str[25]) != 0) terror("Bad str s='%s' n=%d", s, n); count[i] += 1; } } } for(i = 0; i < 26; ++i) if(count[i] != N_STR) terror("Bad count[%d] = %d", i, count[i]); #endif TSTEXIT(0); } s[9] = 0; if(strcmp(s, Str[i]) != 0) terror("Bad str s='%s' i=%d Str[i]='%s' n=%d", s, i, Str[i], n); count[i] += 1; if(i == 25) /* the 'z' */ { for(k = 1; k < N_STR; ++k, ++n) { if(!(s = fgets(buf, sizeof(buf), F)) ) terror("Premature eof n=%d", n); s[9] = 0; if(stsrc/lib/sfio/Stdio_t/tlocale.c000644 151361 151361 00000001700 07251334342 016222 0ustar00kpvkpv000000 000000 #include "stdtest.h" #if _lib_locale #include #endif MAIN() { #if _lib_locale char buf[128], cmp[128]; float d; int n, decimal, thousand; struct lconv* lv; setlocale(LC_ALL, "en"); if(!(lv = localeconv())) TSTEXIT(0); decimal = '.'; if(lv->decimal_point && lv->decimal_point[0]) decimal = lv->decimal_point[0]; thousand = 0; if(lv->thousands_sep && lv->thousands_sep[0]) thousand = lv->thousands_sep[0]; if(thousand) sprintf(cmp,"1%c000", thousand); else sprintf(cmp,"1000"); sprintf(buf, "%'d", 1000); if(strcmp(buf, cmp) != 0) terror("Bad printing"); if(thousand) sprintf(cmp, "1%c000%c10", thousand, decimal); else sprintf(cmp, "1000%c10", decimal); d = 0.; if((n = sscanf(cmp, "%'f", &d)) != 1) terror("Scan error %d", n); if(d < 1000.099 || d > 1000.101) terror("Bad scanning"); sprintf(buf, "%.2f", d); if(strcmp(buf, "1000.10") != 0) terror("Deep formatting error"); #endif TSTEXIT(0); } ousand) sprintf(cmp,"1%c000", thousand); else sprintf(cmp,"10src/lib/sfio/Stdio_t/treopen.c000644 151361 151361 00000000321 07416344551 016257 0ustar00kpvkpv000000 000000 #include "stdtest.h" MAIN() { FILE *fp; if(!(fp = freopen("/dev/null", "w", stdout)) ) terror("Can't reopen stdout\n"); if(fp != stdout) terror("Didn't get the right file pointer\n"); TSTEXIT(0); } = sscanf(cmp, "%'f", &d)) != 1) terror("Scan error %d", n); if(d < 1000.099 || d > 1000.101) terror("Bad scanning"); sprintf(buf, "%.2f", d); if(strcmp(buf, "1000.10") != 0) terror("Deep formatting  CPAV=>"lx<9i l<9i l@src/lib/sfio/Stdio_t/tlongjmp.c000644 151361 151361 00000002326 07235635455 016451 0ustar00kpvkpv000000 000000 #include "stdtest.h" #include #include /* this tests that stdio streams will not be locked even with longjmp */ jmp_buf Env; int Fd[2]; char Str[] = "Signal handler\n"; #if __STD_C void sighandler(int sig) #else void sighandler(sig) int sig; #endif { if(write(Fd[1], Str, strlen(Str)) != strlen(Str)) terror("Writing to pipe failed"); longjmp(Env,0); } MAIN() { FILE* f; char* s; char buf[128]; if(pipe(Fd) < 0) terror("Can't create pipe"); if(!(f = fdopen(Fd[0],"r"))) terror("Can't open read stream"); if(setjmp(Env) == 0) { /* set alarm handler */ tmesg("\tIf hung, send interrupt or quit signal\n"); signal(SIGALRM,sighandler); signal(SIGHUP,sighandler); signal(SIGQUIT,sighandler); alarm(2); /* we expect this to block on read */ fgets(buf,sizeof(buf),f); terror("fgets did not block!"); } else /* got back from longjmp() */ { #if _SFIO_H if((f->mode&SF_RDWR) == f->mode) terror("Stream should be locked"); #endif clearerr(f); /* make sure that stream is ok for IO */ /* this fgets should succeed */ if(!(s = fgets(buf,sizeof(buf),f)) ) terror("fgets returned NULL"); if(strcmp(s,Str) != 0) terror("fgets returned wrong data\n"); } TSTEXIT(0); } ighandler); alarm(2); /* we expect this to block on read */ fgets(buf,sizeof(buf),f); terror("fgets did not block!"); } else /* got back from longjmp() */ { #if _SFIO_H if((f->mode&SF_RDWR) == f->mode) terror("Stream should be locked"); #endif clearerr(f); /* make sure that strsrc/lib/sfio/Stdio_t/tlinux.c000644 151361 151361 00000000720 07235635451 016132 0ustar00kpvkpv000000 000000 #include "stdtest.h" #include MAIN() { struct tm* tmbufp; time_t l1, l2; FILE* f; char buf[1024]; if(!(f = fopen(tstfile(0),"w+")) ) terror("Open file to write"); /* these sometimes call rare Stdio functions such as fread_unlocked. Hopefully, iffe did catch these and built them. */ l2 = time(&l1); tmbufp = localtime(&l2); fprintf(f, "%ld %ld %p", l1, l2, tmbufp); fseek(f, 0L, 0); fread(buf, 1, sizeof(buf), f); TSTEXIT(0); } V=>"lx<9i l<9i l@src/lib/sfio/Stdio_t/runtest000755 151361 151361 00000005136 07001663561 016075 0ustar00kpvkpv000000 000000 ######################################################################### # Invocation arguments are: # # -v: verbose, print the compilation command # # -c: continue testing after a test fails # # -src: testing the source compatibility package # # -bin: testing the binary compatibility package (default) # # -native: test the native stdio # # -whatever_else: bad argument, will be ignored. # # tests: source of tests to be run. # # # # Below are a few example test runs: # # runtest: # # tests the uni-threaded binary compatibility package. # # runtest -src -mt -lpthread: # # tests the multi-threaded source compatibility package # # on a Linux/Irix/Solaris platform. # # runtest -mt -lcma: # # tests the multi-threaded binary compatibility package # # on a HPUX platform (-lcma defines the thread library). # # # # Written by Kiem-Phong Vo # ######################################################################### verbose=0 exit_on_fail=1 files="" LIBS="" HDRS="" DEFS="" XLIBS="" tsttype="binary" # test binary emulation by default envtype="ut" # test uni-threaded by default while test "$1" != "" do case $1 in -l*) XLIBS="$XLIBS $1"; ;; -v) verbose=1; ;; -c) exit_on_fail=0; ;; -src) tsttype="source"; ;; -bin) tsttype="binary"; ;; -native) tsttype="native"; ;; -mt) envtype="mt"; ;; -ut) envtype="ut"; ;; -*) echo "Hmm, unknown argument: $1"; ;; *) files="${files} $1"; ;; esac shift done if test "$CC" = ""; then CC="cc"; fi if test "$files" = "" then files="*.c" fi if test $tsttype = source then HDRS="-I../Stdio_s" if test $envtype = "mt" then DEFS="-Dvt_threaded=1"; LIBS="../libsfio-mt.a ../../vthread/libvthread.a" else DEFS="-Dvt_threaded=0" LIBS="../libsfio.a" fi elif test $tsttype = binary then HDRS="" if test $envtype = "mt" then DEFS="-Dvt_threaded=1"; LIBS="../Stdio_b/libstdio-mt.a ../libsfio-mt.a ../../vthread/libvthread.a" else DEFS="-Dvt_threaded=0" LIBS="../Stdio_b/libstdio.a ../libsfio.a" fi else HDRS="" if test $envtype = "mt" then DEFS="-Dvt_threaded=1"; LIBS="../../vthread/libvthread.a" else DEFS="-Dvt_threaded=0" LIBS="" fi fi LIBS="$LIBS $XLIBS" if test "$verbose" = 1 then echo "Compile: $CC -g -I. -I.. -I../../vthread $HDRS $DEFS whatever.c $LIBS -o t" fi for i in $files do echo "-- $i:" status="" if $CC -g -I. -I.. -I../../vthread $HDRS $DEFS $i $LIBS -o t then if ./t then rm t; status=Passed else status=Failed fi else status="Not compiled" fi echo " $status" if test "$status" != "Passed" then if test "$exit_on_fail" = "1"; then exit; fi fi done /libvthread.a" else DEFS="-Dvt_threaded=0" LIBS="" fi fi LIBS="$LIBS $XLIBS" if test "$verbose" = 1 then echo "Compile: $CC -g -I. -I.. -I../../vthread $HDRS $DEFS whatever.c $LIBS -o t" fi for i in $files do echo "-- $i:" status="" if $CC -g -I. -I.. -I../../vthread $HDRS $DEFS $i $LIBS -o t then if ./t then rm t; status=Passed else status=Failed fi else status="Not compiled" fi echo " $statusrc/lib/sfio/Stdio_s/stdgetc.c000644 151361 151361 00000000226 07432261634 016241 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" #undef getc #if __STD_C int getc(FILE* f) #else int getc(f) FILE* f; #endif { return f ? _std_getc(f) : -1; } i fi LIBS="$LIBS $XLIBS" if test "$verbose" = 1 then echo "Compile: $CC -g -I. -I.. -I../../vthread $HDRS $DEFS whatever.c $LIBS -o t" fi for i in $files do echo "-- $i:" status="" if $CC -g -I. -I.. -I../../vthread $HDRS $DEFS $i $LIBS -o t then if ./t t /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdputc.c000644 151361 151361 00000000251 07432261635 016271 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" #undef putc #if __STD_C int putc(int c, FILE* f) #else int putc(c, f) int c; FILE* f; #endif { return f ? _std_putc(c,f) : -1; } XLIBS" if test "$verbose" = 1 then echo "Compile: $CC -g -I. -I.. -I../../vthread $HDRS $DEFS whatever.c $LIBS -o t" fi for i in $files do echo "-- $i:" status="" if $CC -g -I. -I.. -I../../vthread $HDRS $DEFS $i $LIBS -o t then if ./t t /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdgetw.c000644 151361 151361 00000000277 07432261634 016273 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" #if __STD_C int _stdgetw(FILE* f) #else int _stdgetw(f) FILE* f; #endif { int w; return (f && sfread(f, &w, sizeof(int)) == sizeof(int)) ? w : -1; } ose" = 1 then echo "Compile: $CC -g -I. -I.. -I../../vthread $HDRS $DEFS whatever.c $LIBS -o t" fi for i in $files do echo "-- $i:" status="" if $CC -g -I. -I.. -I../../vthread $HDRS $DEFS $i $LIBS -o t then if ./t t /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdputw.c000644 151361 151361 00000000322 07432261635 016314 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" #if __STD_C int _stdputw(int w, FILE* f) #else int _stdputw(w, f) int w; FILE* f; #endif { if(!f) return -1; (void)sfwrite(f, &w, sizeof(int)); return sferror(f); } "Compile: $CC -g -I. -I.. -I../../vthread $HDRS $DEFS whatever.c $LIBS -o t" fi for i in $files do echo "-- $i:" status="" if $CC -g -I. -I.. -I../../vthread $HDRS $DEFS $i $LIBS -o t then if ./t t /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdgets.c000644 151361 151361 00000003013 07432261634 016256 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" /* Read a line into a buffer. ** ** Written by Kiem-Phong Vo. */ #if __STD_C char* _stdgets(reg Sfio_t* f, char* us, reg int n, int isgets) #else char* _stdgets(f,us,n,isgets) reg Sfio_t* f; /* stream to read from */ char* us; /* space to read into */ reg int n; /* max number of bytes to read */ int isgets; /* gets(), not fgets() */ #endif { reg int p; reg uchar *is, *ps; SFMTXSTART(f, NIL(char*)); if(n <= 0 || !us || (f->mode != SF_READ && _sfmode(f,SF_READ,0) < 0)) SFMTXRETURN(f, NIL(char*)); SFLOCK(f,0); n -= 1; is = (uchar*)us; while(n) { /* peek the read buffer for data */ if((p = f->endb - (ps = f->next)) <= 0 ) { f->getr = '\n'; f->mode |= SF_RC; if(SFRPEEK(f,ps,p) <= 0) break; } if(p > n) p = n; #if _lib_memccpy if((ps = (uchar*)memccpy((char*)is,(char*)ps,'\n',p)) != NIL(uchar*)) p = ps-is; is += p; ps = f->next+p; #else if(!(f->flags&(SF_BOTH|SF_MALLOC))) { while(p-- && (*is++ = *ps++) != '\n') ; p = ps-f->next; } else { reg int c = ps[p-1]; if(c != '\n') ps[p-1] = '\n'; while((*is++ = *ps++) != '\n') ; if(c != '\n') { f->next[p-1] = c; if((ps-f->next) >= p) is[-1] = c; } } #endif /* gobble up read data and continue */ f->next = ps; if(is[-1] == '\n') break; else if(n > 0) n -= p; } if((_Sfi = f->val = is - ((uchar*)us)) <= 0) us = NIL(char*); else if(isgets && is[-1] == '\n') is[-1] = '\0'; else *is = '\0'; SFOPEN(f,0); SFMTXRETURN(f, us); } next; } else { reg int c = ps[p-1]; if(c != '\n') ps[p-1] = '\n'; while((*is++ = *ps++) != '\n') ; if(c != '\n') { f->next[p-1] = c; if((ps-f->next) >= p) is[-1] = c; } } #endif /* gobble up read data and continue */ f->next = ps; if(is[-1] == '\n') break; else if(n > 0) n -= p; } if((_Sfi = f->val = is - ((uchar*)us)) <= 0) us = NIL(char*); else if(isgets && is[-1] == '\n') is[-1] = '\0'; else *is = '\0'; SFOPEN(f,0); SFMTXRETURNsrc/lib/sfio/Stdio_s/stdfflush.c000644 151361 151361 00000000407 07432261633 016606 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" #if __STD_C int _stdfflush(FILE* f) #else int _stdfflush(f) FILE* f; #endif { if(!f) return -1; if(f->extent >= 0) (void)sfseek(f, (Sfoff_t)0, SEEK_CUR|SF_PUBLIC); return (sfsync(f) < 0 || sfpurge(f) < 0) ? -1 : 0; } inue */ f->next = ps; if(is[-1] == '\n') break; else if(n > 0) n -= p; } if((_Sfi = f->val = is - ((uchar*)us)) <= 0) us = NIL(char*);  /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdio.h000644 151361 151361 00000027174 07432261634 015746 0ustar00kpvkpv000000 000000 #ifndef _SFSTDIO_H #define _SFSTDIO_H 1 /******************************************************************************** * This product contains certain software code or other information * * ("AT&T Software") proprietary to AT&T Corp. ("AT&T"). * * The AT&T Software is provided to you "AS IS". YOU ASSUME TOTAL * * RESPONSIBILITY AND RISK FOR USE OF THE AT&T SOFTWARE. * * AT&T DOES NOT MAKE, AND EXPRESSLY DISCLAIMS, ANY EXPRESS OR * * IMPLIED WARRANTIES OF ANY KIND WHATSOEVER, INCLUDING, * * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY OR * * FITNESS FOR A PARTICULAR PURPOSE, WARRANTIES OF TITLE OR * * NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS, * * ANY WARRANTIES ARISING BY USAGE OF TRADE, COURSE OF DEALING OR * * COURSE OF PERFORMANCE, OR ANY WARRANTY THAT THE AT&T SOFTWARE * * IS "ERROR FREE" OR WILL MEET YOUR REQUIREMENTS. * * * * All rights reserved. AT&T is a registered trademark of AT&T Corp. * ********************************************************************************/ #define BUFSIZ SF_BUFSIZE #undef FILE #define FILE Sfio_t #include #define _IOFBF 0 #define _IONBF 1 #define _IOLBF 2 #define L_ctermid 32 #define L_cuserid 32 #define P_tmpdir "/tmp/" #define L_tmpnam (sizeof(P_tmpdir)+32) #undef fpos_t #define fpos_t Sfoff_t #undef off_t #define off_t Sfoff_t _BEGIN_EXTERNS_ #if _BLD_sfio && defined(__EXPORT__) #define extern __EXPORT__ #endif #if !_BLD_sfio && defined(__IMPORT__) && defined(__EXPORT__) #define extern __IMPORT__ #endif extern char* ctermid _ARG_((char*)); extern char* cuserid _ARG_((char*)); extern char* tmpnam _ARG_((char*)); extern char* tempnam _ARG_((const char*, const char*)); #ifndef remove extern int remove _ARG_((const char*)); #endif extern void perror _ARG_((const char*)); extern Sfio_t* _stdfdopen _ARG_((int, const char*)); extern Sfio_t* _stdfopen _ARG_((const char*, const char*)); extern Sfio_t* _stdfreopen _ARG_((const char*, const char*, Sfio_t*)); extern Sfio_t* _stdpopen _ARG_((const char*, const char*)); extern Sfio_t* _stdtmpfile _ARG_((void)); extern int _stdprintf _ARG_((const char*, ...)); extern int _stdfprintf _ARG_((Sfio_t* f, const char*, ...)); extern int _stdsprintf _ARG_((char*, const char*, ...)); extern int _stdscanf _ARG_((const char*, ...)); extern int _stdfscanf _ARG_((Sfio_t* f, const char*, ...)); extern int _stdsetvbuf _ARG_((Sfio_t*, char*, int, size_t)); extern int _stdfputc _ARG_((int, Sfio_t*)); extern int _stdfgetc _ARG_((Sfio_t*)); extern int _stdputw _ARG_((int, Sfio_t*)); extern int _stdgetw _ARG_((Sfio_t*)); extern ssize_t _stdfwrite _ARG_((const Void_t*, size_t, size_t, Sfio_t*)); extern ssize_t _stdfread _ARG_((Void_t*, size_t, size_t, Sfio_t*)); extern char* _stdgets _ARG_((Sfio_t*, char*, int n, int isgets)); #undef extern _END_EXTERNS_ #define _STDSIZE(s) (sizeof(s) != sizeof(char*) ? sizeof(s) : BUFSIZ) #define printf _stdprintf #define fprintf _stdfprintf #define sprintf _stdsprintf #define snprintf sfsprintf #define vsnprintf sfvsprintf #define scanf _stdscanf #define fscanf _stdfscanf #define sscanf sfsscanf #define fdopen _stdfdopen #define fopen _stdfopen #define popen _stdpopen #define freopen _stdfreopen #define tmpfile _stdtmpfile #define setvbuf _stdsetvbuf #define putw _stdputw #define fputc _stdfputc #define fputc_unlocked _stdfputc #define fwrite _stdfwrite #define fwrite_unlocked _stdfwrite #define getw _stdgetw #define fgetc _stdfgetc #define fgetc_unlocked _stdfgetc #define fread _stdfread #define fread_unlocked _stdfread #define _std_fclose(f) sfclose(f) #define _std_pclose(f) sfclose(f) #define _std_flockfile(f) sfmutex((f), SFMTX_LOCK) #define _std_ftrylockfile(f) sfmutex((f), SFMTX_TRYLOCK) #define _std_funlockfile(f) sfmutex((f), SFMTX_UNLOCK) #define _std_putc(c,f) sfputc((f),(c)) #define _std_putchar(c) sfputc(sfstdout,(c)) #define _std_fputs(s,f) sfputr((f),(s),-1) #define _std_puts(s) sfputr(sfstdout,(s),'\n') #define _std_vprintf(fmt,a) sfvprintf(sfstdout,(fmt),(a)) #define _std_vfprintf(f,fmt,a) sfvprintf((f),(fmt),(a)) #define _std_doprnt(fmt,a,f) sfvprintf((f),(fmt),(a)) #define _std_vsprintf(s,fmt,a) sfvsprintf((s),_STDSIZE(s),(fmt),(a) ) #define _std_getc(f) sfgetc(f) #define _std_getchar() sfgetc(sfstdin) #define _std_ungetc(c,f) sfungetc((f),(c)) #define _std_fgets(s,n,f) _stdgets((f),(s),(n),0) #define _std_gets(s) _stdgets(sfstdin,(s),_STDSIZE(s),1) #define _std_vscanf(fmt,a) sfvscanf(sfstdin,(fmt),(a)) #define _std_vfscanf(f,fmt,a) sfvscanf((f),(fmt),(a)) #define _std_doscan(f,fmt,a) sfvscanf((f),(fmt),(a)) #define _std_vsscanf(s,fmt,a) sfvsscanf(s,(fmt),(a)) #define _std_fpurge(f) sfpurge(f) #define _std_fflush(f) _stdfflush(f) #define _std_rewind(f) (sfseek((f), (Sfoff_t)0, SEEK_SET|SF_SHARE), sfclrerr(f) ) #define _std_fseek(f,o,t) (sfseek((f), (Sfoff_t)(o), (t)|SF_SHARE) < 0 ? -1 : 0 ) #define _std_ftell(f) ((long)sfseek((f), (Sfoff_t)0, SEEK_CUR) ) #define _std_fgetpos(f,p) ((*(p) = _std_ftell(f)) >= 0 ? 0 : -1 ) #define _std_fsetpos(f,p) (sfseek((f), *(p), SEEK_SET|SF_SHARE) != *(p) ? -1 : 0 ) #define _std_fseeko(f,o,t) (sfseek((f), (Sfoff_t)(o), (t)|SF_SHARE) < 0 ? -1 : 0 ) #define _std_ftello(f) ((off_t)sfseek((f), (Sfoff_t)0, SEEK_CUR) ) #define _std_setbuf(f,b) (sfsetbuf((f),(b),(b) ? BUFSIZ : 0) ) #define _std_setbuffer(f,b,n) (sfsetbuf((f),(b),(n)) ? 0 : -1) #define _std_setlinebuf(f) sfset((f),SF_LINE,1) #define _std_fileno(f) sffileno(f) #define _std_feof(f) sfeof(f) #define _std_ferror(f) sferror(f) #define _std_clearerr(f) (sfclrlock(f), sfclrerr(f) ) #if defined(__INLINE__) && !_BLD_sfio __INLINE__ int fclose(FILE* f) { return _std_fclose(f); } __INLINE__ int pclose(FILE* f) { return _std_pclose(f); } __INLINE__ void flockfile(FILE* f) { (void) _std_flockfile(f); } __INLINE__ int ftrylockfile(FILE* f) { return _std_ftrylockfile(f); } __INLINE__ void funlockfile(FILE* f) { (void) _std_funlockfile(f); } __INLINE__ int putc(int c, FILE* f) { return _std_putc(c,f); } __INLINE__ int putc_unlocked(int c, FILE* f) { return _std_putc(c,f); } __INLINE__ int putchar(int c) { return _std_putchar(c); } __INLINE__ int putchar_unlocked(int c) { return _std_putchar(c); } __INLINE__ int fputs(const char* s, FILE* f) { return _std_fputs(s,f); } __INLINE__ int fputs_unlocked(const char* s, FILE* f) { return _std_fputs(s,f); } __INLINE__ int puts(const char* s) { return _std_puts(s); } __INLINE__ int puts_unlocked(const char* s) { return _std_puts(s); } __INLINE__ int vprintf(const char* fmt, va_list a) { return _std_vprintf(fmt,a); } __INLINE__ int vfprintf(Sfio_t* f, const char* fmt, va_list a) { return _std_vfprintf(f,fmt,a);} __INLINE__ int _doprnt(const char* fmt, va_list a, FILE* f) { return _std_doprnt(fmt,a,f); } __INLINE__ int vsprintf(char* s, const char* fmt, va_list a) { return _std_vsprintf(s,fmt,a);} __INLINE__ int getc(FILE* f) { return _std_getc(f); } __INLINE__ int getc_unlocked(FILE* f) { return _std_getc(f); } __INLINE__ int getchar(void) { return _std_getchar(); } __INLINE__ int getchar_unlocked(void) { return _std_getchar(); } __INLINE__ int ungetc(int c, FILE* f) { return _std_ungetc(c,f); } __INLINE__ char* fgets(char* s, int n, FILE* f) { return _std_fgets(s,n,f); } __INLINE__ char* fgets_unlocked(char* s, int n, FILE* f){ return _std_fgets(s,n,f); } __INLINE__ char* gets_unlocked(char* s) { return _std_gets(s); } __INLINE__ int vscanf(const char* fmt, va_list a) { return _std_vscanf(fmt,a); } __INLINE__ int vfscanf(Sfio_t* f, const char* fmt, va_list a) { return _std_vfscanf(f,fmt,a); } __INLINE__ int _doscan(Sfio_t* f, const char* fmt, va_list a) { return _std_doscan(f,fmt,a); } __INLINE__ int vsscanf(char* s, const char* fmt, va_list a) { return _std_vsscanf(s,fmt,a); } __INLINE__ int fpurge(FILE* f) { return _std_fpurge(f); } __INLINE__ int fflush(FILE* f) { return _std_fflush(f); } __INLINE__ int fflush_unlocked(FILE* f) { return _std_fflush(f); } __INLINE__ void rewind(FILE* f) { (void) _std_rewind(f); } __INLINE__ int fseek(FILE* f, long o, int t) { return _std_fseek(f,o,t); } __INLINE__ long ftell(FILE* f) { return _std_ftell(f); } __INLINE__ int fsetpos(FILE* f, fpos_t* pos) { return _std_fsetpos(f,pos); } __INLINE__ int fgetpos(FILE* f, fpos_t* pos) { return _std_fgetpos(f,pos); } __INLINE__ int fseeko(FILE* f, off_t o, int t) { return _std_fseeko(f,o,t); } __INLINE__ off_t ftello(FILE* f) { return _std_ftello(f); } __INLINE__ void setbuf(FILE* f, char* b) { (void) _std_setbuf(f,b); } __INLINE__ int setbuffer(FILE* f, char* b, int n) { return _std_setbuffer(f,b,n); } __INLINE__ int setlinebuf(FILE* f) { return _std_setlinebuf(f); } __INLINE__ int fileno(FILE* f) { return _std_fileno(f); } __INLINE__ int feof(FILE* f) { return _std_feof(f); } __INLINE__ int feof_unlocked(FILE* f) { return _std_feof(f); } __INLINE__ int ferror(FILE* f) { return _std_ferror(f); } __INLINE__ int ferror_unlocked(FILE* f) { return _std_ferror(f); } __INLINE__ void clearerr(FILE* f) { (void) _std_clearerr(f); } __INLINE__ void clearerr_unlocked(FILE* f) { (void) _std_clearerr(f); } #else #define fclose(f) ( _std_fclose(f) ) #define pclose(f) ( _std_pclose(f) ) #define flockfile(f) ( _std_flockfile(f) ) #define ftrylockfile(f) ( _std_ftrylockfile(f) ) #define funlockfile(f) ( _std_funlockfile(f) ) #define putc(c,f) ( _std_putc(c,f) ) #define putc_unlocked(c,f) ( _std_putc(c,f) ) #define putchar(c) ( _std_putchar(c) ) #define putchar_unlocked(c) ( _std_putchar(c) ) #define fputs(s,f) ( _std_fputs(s,f) ) #define fputs_unlocked(s,f) ( _std_fputs(s,f) ) #define puts(s) ( _std_puts(s) ) #define puts_unlocked (s) ( _std_puts(s) ) #define vprintf(fmt,a) ( _std_vprintf(fmt,a) ) #define vfprintf(f,fmt,a) ( _std_vfprintf(f,fmt,a) ) #define _doprnt(fmt,a,f) ( _std_doprnt(fmt,a,f) ) #define vsprintf(s,fmt,a) ( _std_vsprintf(s,fmt,a) ) #define getc(f) ( _std_getc(f) ) #define getc_unlocked(f) ( _std_getc(f) ) #define getchar() ( _std_getchar() ) #define getchar_unlocked() ( _std_getchar() ) #define ungetc(c,f) ( _std_ungetc(c,f) ) #define fgets(s,n,f) ( _std_fgets(s,n,f) ) #define fgets_unlocked(s,n,f) ( _std_fgets(s,n,f) ) #define gets(s) ( _std_gets(s) ) #define gets_unlocked(s) ( _std_gets(s) ) #define vscanf(fmt,a) ( _std_vscanf(fmt,a) ) #define vfscanf(f,fmt,a) ( _std_vfscanf(f,fmt,a) ) #define vsscanf(s,fmt,a) ( _std_vsscanf(s,fmt,a) ) #define fpurge(f) ( _std_fpurge(f) ) #define fflush(f) ( _std_fflush(f) ) #define fflush_unlocked(f) ( _std_fflush(f) ) #define rewind(f) ( (void)_std_rewind(f) ) #define fseek(f,o,t) ( _std_fseek(f,o,t) ) #define ftell(f) ( _std_ftell(f) ) #define fgetpos(f,pos) ( _std_fgetpos(f,pos) ) #define fsetpos(f,pos) ( _std_fsetpos(f,pos) ) #define fseeko(f,o,t) ( _std_fseeko(f,o,t) ) #define ftello(f) ( _std_ftello(f) ) #define setbuf(f,b) ( (void)_std_setbuf(f,b) ) #define setbuffer(f,b,n) ( _std_setbuffer(f,b,n) ) #define setlinebuf(f) ( _std_setlinebuf(f) ) #define fileno(f) ( _std_fileno(f) ) #define feof(f) ( _std_feof(f) ) #define feof_unlocked(f) ( _std_feof(f) ) #define ferror(f) ( _std_ferror(f) ) #define ferror_unlocked(f) ( _std_ferror(f) ) #define clearerr(f) ( (void)_std_clearerr(f) ) #define clearerr_unlocked(f) ( (void)_std_clearerr(f) ) #endif /* standard streams */ #ifdef SF_FILE_STRUCT #define sfstdin (&_Sfstdin) #define sfstdout (&_Sfstdout) #define sfstderr (&_Sfstderr) #endif #define stdin sfstdin #define stdout sfstdout #define stderr sfstderr #endif /* _SFSTDIO_H */ td_feof(f) ) #define feof_unlocked(f) ( _std_feof(f) ) #define ferror(f) ( _std_ferror(f) ) #define ferror_unlocked(f) ( _std_ferror(f) ) #define clearerr(f) ( (void)_std_clearerr(f) ) #define clearerr_unlocked(f) ( (void)_std_clearerr(f) ) #endif /* standard streams */ #ifdef SF_FILE_STRUCT #define sfstdin (&_Sfstdin) #define sfstdout (&_Sfstdout) #define sfssrc/lib/sfio/Stdio_s/Makefile000644 151361 151361 00000001541 07432261633 016100 0ustar00kpvkpv000000 000000 # makefile for stdio-source compatibility code # # Written by Kiem-Phong Vo # Compiler and flags to use LIBTYPE= AR= ar CC= cc CXFLAGS= CCMODE= -O CCFLAGS= -I. -I.. $(CCMODE) $(LIBTYPE) $(CXFLAGS) HDRS= stdio.h SRCS= stdfgetc.c stdfprintf.c stdfputc.c stdfscanf.c stdgetc.c stdgets.c \ stdgetw.c stdfdopen.c stdprintf.c stdputc.c stdputw.c stdscanf.c \ stdsprintf.c stdsetvbuf.c stdfopen.c stdfreopen.c stdpopen.c stdtmpfile.c \ stdfwrite.c stdfread.c stdfflush.c OBJS= stdfgetc.o stdfprintf.o stdfputc.o stdfscanf.o stdgetc.o stdgets.o \ stdgetw.o stdfdopen.o stdprintf.o stdputc.o stdputw.o stdscanf.o \ stdsprintf.o stdsetvbuf.o stdfopen.o stdfreopen.o stdpopen.o stdtmpfile.o \ stdfwrite.o stdfread.o stdfflush.o .c.o: $(CC) -c $(CCFLAGS) $*.c must: $(OBJS) 3dupdate: cp Makefile $(HDRS) $(SRCS) ... clean: -(rm $(OBJS); exit 0) >/dev/null 2>&1 \ stdsprintf.c stdsetvbuf.c stdfopen.c stdfreopen.c stdpopen.c stdtmpfile.c \ stdfwrite.c stdfread.c stdfflush.c OBJS= stdfgetc.o stdfprintf.o stdfputc.o ssrc/lib/sfio/Stdio_s/stdsetvbuf.c000644 151361 151361 00000001204 07432261635 016773 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" /* Stdio function setvbuf() ** ** Written by Kiem-Phong Vo. */ #if __STD_C int _stdsetvbuf(Sfio_t* f, char* buf, int type, size_t size) #else int _stdsetvbuf(f,buf,type,size) Sfio_t* f; char* buf; int type; size_t size; #endif { SFMTXSTART(f,-1); if(type == _IOLBF) { sfset(f,SF_LINE,1); } else if((f->flags&SF_STRING)) { SFMTXRETURN(f, -1); } else if(type == _IONBF) { sfsync(f); sfsetbuf(f,NIL(Void_t*),0); sfset(f,SF_LINE,0); } else if(type == _IOFBF) { if(size == 0) size = SF_BUFSIZE; sfsync(f); sfsetbuf(f,(Void_t*)buf,size); sfset(f,SF_LINE,0); } SFMTXRETURN(f, 0); } fio_t* f, char* buf, int type, size_t size) #else int _stdsetvbuf(f,buf,type,size) Sfio_t* f; char* buf; int type; size_t size; #endif { SFMTXSTART(f,-1); if(type == _IOLBF) { sfset(f,SF_LINE,1); } else if((f->flags&SF_STRING)) { SFMTXRETURN(f, -1); } else if(type == _IONBF) { sfsync(f); sfsetbuf(f,NIL(Void_t*),0); sfset(f,SF_LINE,0); } else if(type == _IOFBF) src/lib/sfio/Stdio_s/stdfdopen.c000644 151361 151361 00000000712 07432261633 016571 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Open a stream given a file descriptor. ** ** Written by Kiem-Phong Vo. */ #if __STD_C Sfio_t* _stdfdopen(reg int fd, reg const char* mode) #else Sfio_t* _stdfdopen(fd,mode) reg int fd; reg char* mode; #endif { int sflags, uflag; if(fd < 0 || !mode || (sflags = _sftype(mode,NIL(int*),&uflag)) == 0) return NIL(Sfio_t*); if(!uflag) sflags |= SF_MTSAFE; return sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND,fd,sflags); } V=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdfreopen.c000644 151361 151361 00000000620 07432261634 016753 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Open a stream given a file descriptor. ** ** Written by Kiem-Phong Vo. */ #if __STD_C Sfio_t* _stdfreopen(const char* file, const char* mode, Sfio_t* f) #else Sfio_t* _stdfreopen(file,mode,f) char* file; char* mode; Sfio_t* f; #endif { if((f = sfopen(f, file, mode)) ) { int uflag; _sftype(mode, NIL(int*), &uflag); if(!uflag) f->flags |= SF_MTSAFE; } return f; } IL(Sfio_t*),NIL( /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdfscanf.c000644 151361 151361 00000000770 07432261634 016563 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" /* Read formatted data from a stream ** ** Written by Kiem-Phong Vo. */ #if __STD_C int _stdfscanf(Sfio_t* f, const char* form, ...) #else int _stdfscanf(va_alist) va_dcl #endif { va_list args; reg int rv; #if __STD_C va_start(args,form); #else reg Sfio_t* f; reg char* form; /* scanning format */ va_start(args); f = va_arg(args,Sfio_t*); form = va_arg(args,char*); #endif rv = (f && form) ? sfvscanf(f,form,args) : -1; va_end(args); return rv; } Y?x@src/lib/sfio/Stdio_s/stdfprintf.c000644 151361 151361 00000000726 07432261634 016774 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" /* fprintf function ** ** Written by Kiem-Phong Vo. */ #if __STD_C int _stdfprintf(Sfio_t* f, const char *form, ...) #else int _stdfprintf(va_alist) va_dcl #endif { va_list args; reg int rv; #if __STD_C va_start(args,form); #else reg Sfio_t* f; reg char* form; va_start(args); f = va_arg(args,Sfio_t*); form = va_arg(args,char*); #endif rv = (f && form) ? sfvprintf(f,form,args) : -1; va_end(args); return rv; } V=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdprintf.c000644 151361 151361 00000000634 07432261635 016625 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" /* printf function ** ** Written by Kiem-Phong Vo. */ #if __STD_C int _stdprintf(const char *form, ...) #else int _stdprintf(va_alist) va_dcl #endif { va_list args; reg int rv; #if __STD_C va_start(args,form); #else reg char *form; va_start(args); form = va_arg(args,char*); #endif rv = form ? sfvprintf(sfstdout,form,args) : -1; va_end(args); return rv; } vpri /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdsprintf.c000644 151361 151361 00000000733 07432261635 017010 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" /* sprintf function ** ** Written by Kiem-Phong Vo. */ #if __STD_C int _stdsprintf(char* s, const char* form, ...) #else int _stdsprintf(va_alist) va_dcl #endif { va_list args; reg int rv; #if __STD_C va_start(args,form); #else reg char* s; reg char* form; va_start(args); s = va_arg(args,char*); form = va_arg(args,char*); #endif rv = (s && form) ? sfvsprintf(s,SF_BUFSIZE,form,args) : -1; va_end(args); return rv; } =Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdfread.c000644 151361 151361 00000000662 07432261634 016404 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" /* Read in a block of data ** ** Written by Kiem-Phong Vo. */ #if __STD_C ssize_t _stdfread(Void_t* buf, size_t esize, size_t nelts, Sfio_t* f) #else ssize_t _stdfread(buf, esize, nelts, f) Void_t* buf; size_t esize; size_t nelts; Sfio_t* f; #endif { ssize_t rv; if(!f || !buf) return -1; if((rv = sfread(f, buf, esize*nelts)) >= 0) return esize == 0 ? 0 : rv/esize; else return 0; } /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdfgetc.c000644 151361 151361 00000000221 07432261633 016401 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" #if __STD_C int _stdfgetc(FILE* f) #else int _stdfgetc(f) FILE* f; #endif { return f ? sfgetc(f) : -1; } size_t esize, size_t nelts, Sfio_t* f) #else ssize_t _stdfread(buf, esize, nelts, f) Void_t* buf; size_t esize; size_t nelts; Sfio_t* f; #endif { ssize_t rv; if(!f || !buf) return -1; if((rv = sfread(f, buf, esize*nelts)) >= 0) return esize == 0 ? 0 : rv/esize;  /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdfputc.c000644 151361 151361 00000000260 07432261634 016436 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" #undef putc #if __STD_C int _stdfputc(int c, FILE* f) #else int _stdfputc(c, f) int c; FILE* f; #endif { return f ? sfputc(f,c) : -1; } o_t* f) #else ssize_t _stdfread(buf, esize, nelts, f) Void_t* buf; size_t esize; size_t nelts; Sfio_t* f; #endif { ssize_t rv; if(!f || !buf) return -1; if((rv = sfread(f, buf, esize*nelts)) >= 0) return esize == 0 ? 0 : rv/esize;  /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdscanf.c000644 151361 151361 00000000676 07432261635 016423 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" /* Read formatted data from a stream ** ** Written by Kiem-Phong Vo. */ #if __STD_C int _stdscanf(const char* form, ...) #else int _stdscanf(va_alist) va_dcl #endif { va_list args; reg int rv; #if __STD_C va_start(args,form); #else reg char *form; /* scanning format */ va_start(args); form = va_arg(args,char*); #endif rv = form ? sfvscanf(sfstdin,form,args) : -1; va_end(args); return rv; } V=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdtmpfile.c000644 151361 151361 00000000260 07432261635 016756 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Open a temp stream. ** ** Written by Kiem-Phong Vo. */ Sfio_t* _stdtmpfile() { Sfio_t* f; if((f = sftmp(0)) ) f->flags |= SF_MTSAFE; return f; } canf(va_alist) va_dcl #endif { va_list args; reg int rv; #if __STD_C va_start(args,form); #else reg char *form; /* scanning format */ va_start(args); form = va_arg(args,char*); #endif rv = form ? sfvscanf(sfstdin,form,args) : -1; /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdfopen.c000644 151361 151361 00000000630 07432261633 016424 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Open a stream given a file descriptor. ** ** Written by Kiem-Phong Vo. */ #if __STD_C Sfio_t* _stdfopen(const char* file, reg const char* mode) #else Sfio_t* _stdfopen(file,mode) reg char* file; reg char* mode; #endif { Sfio_t* f; if((f = sfopen(NIL(Sfio_t*), file, mode)) ) { int uflag; _sftype(mode, NIL(int*), &uflag); if(!uflag) f->flags |= SF_MTSAFE; } return f; } s) : -1; /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdpopen.c000644 151361 151361 00000000632 07432261634 016441 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Open a stream given a file descriptor. ** ** Written by Kiem-Phong Vo. */ #if __STD_C Sfio_t* _stdpopen(const char* file, reg const char* mode) #else Sfio_t* _stdpopen(file,mode) reg char* file; reg char* mode; #endif { Sfio_t* f; if((f = sfpopen((Sfio_t*)(-1), file, mode)) ) { int uflag; _sftype(mode, NIL(int*), &uflag); if(!uflag) f->flags |= SF_MTSAFE; } return f; } : -1; /%AV=Jd@9RY?x9RY?x@src/lib/sfio/Stdio_s/stdfwrite.c000644 151361 151361 00000000711 07432261634 016616 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include "stdio.h" /* Write out a block of data ** ** Written by Kiem-Phong Vo. */ #if __STD_C ssize_t _stdfwrite(const Void_t* buf, size_t esize, size_t nelts, Sfio_t* f) #else ssize_t _stdfwrite(buf, esize, nelts, f) Void_t* buf; size_t esize; size_t nelts; Sfio_t* f; #endif { ssize_t rv; if(!f || !buf) return (ssize_t)(-1); if((rv = sfwrite(f, buf, esize*nelts)) > 0) return (esize == 0 ? 0 : rv/esize); else return 0; } V=Jd@9RY?x9RY?x@src/lib/sfio/features/sfio000644 151361 151361 00000026615 07432261457 015552 0ustar00kpvkpv000000 000000 ################################################################## # This file defines probes for local features that sfio requires. # Such probes are interpreted by the "iffe" language interpreter. # Results are stored in the FEATURE directory. # # Written by Kiem-Phong Vo ################################################################## hdr time sys time hdr stdarg hdr stdlib hdr wchar typ mbstate_t wchar.h lib mbrtowc lib wcrtomb lib mbtowc lib wctomb hdr string hdr math lib qfrexp lib qldexp hdr unistd hdr values hdr floatingpoint hdr float lib atexit lib onexit lib ftruncate lib ftruncate64 lib open64 lib close64 lib creat64 lib lseek64 lib stat64 lib fstat64 lib mmap64 lib munmap64 typ off64_t typ struct_stat64 compile{ #include #include main() { struct stat64 statb; } }end exit cleanup note{ stuck with standard _cleanup }end execute{ #include _BEGIN_EXTERNS_ extern void exit _ARG_((int)); extern void _exit _ARG_((int)); extern void _cleanup(); void _cleanup() { _exit(0); } _END_EXTERNS_ main() { printf("cleanup\n"); exit(1); } }end lib bcopy lib bzero lib memcpy lib memset lib memalign lib memchr note{ see if memchr is fast }end execute{ #include #include #include main() { struct tms stm1, etm1, stm2, etm2; register int i, p; register char *s, *ends; long t1, t2; char buf[128]; for(p = 0; p < 100; ++p) buf[p] = '0' + (p%10); buf[p++] = '\n'; buf[p] = 0; times(&stm1); for(i = 0; i < 100000; ++i) s = memchr(buf,'\n',p); times(&etm1); times(&stm2); for(i = 0; i < 100000; ++i) { ends = (s = buf) + p; while(*s != '\n') if((s += 1) == ends) break; } times(&etm2); t1 = (etm1.tms_utime - stm1.tms_utime) + (etm1.tms_stime - stm1.tms_stime); t2 = (etm2.tms_utime - stm2.tms_utime) + (etm2.tms_stime - stm2.tms_stime); return t1 < t2 ? 0 : 1; } }end lib memccpy note{ see if memccpy is fast }end execute{ #include #include #include main() { struct tms stm1, etm1, stm2, etm2; register int i, p; register char *s1, *s2; long t1, t2; char buf1[128], buf2[128]; for(i = 0; i < 100; ++i) buf1[i] = '0' + (i%10); buf1[i++] = '\n'; buf1[i] = 0; times(&stm1); for(i = 0; i < 100000; ++i) { p = 128; memccpy(buf2,buf1,'\n',p); } times(&etm1); times(&stm2); for(i = 0; i < 100000; ++i) { s1 = buf1; s2 = buf2; p = 128; while((*s2++ = *s1++) != '\n' && --p > 0) ; } times(&etm2); t1 = (etm1.tms_utime - stm1.tms_utime) + (etm1.tms_stime - stm1.tms_stime); t2 = (etm2.tms_utime - stm2.tms_utime) + (etm2.tms_stime - stm2.tms_stime); return t1 < t2 ? 0 : 1; } }end sys stat note{ stat() in default lib(s) }end link{ #if _STD_ #include #else #include #endif #include #include main() { struct stat st; fstat(0,&st); } }end hdr stat note{ stat() in default lib(s) }end link{ #if _STD_ #include #else #include #endif #include #include main() { struct stat st; fstat(0,&st); } }end ############################################################# # See if memory mapping is available and fast enough to use ############################################################# sys mman tst output{ #include #include #include _BEGIN_EXTERNS_ int creat _ARG_((char*, int)); int open _ARG_((char*, int)); int unlink _ARG_((char*)); int read _ARG_((int, char*, int)); _END_EXTERNS_ #define MAPSIZE (64*1024) #define BUFSIZE (MAPSIZE/8) #define WRITE (64) #define RUN (64) #define Failed(file) (unlink(file),1) #if _STD_ main(int argc, char** argv) #else main(argc,argv) int argc; char** argv; #endif { caddr_t mm; char *t, *f; int i, fd, k, run; char file[1024], buf[MAPSIZE]; struct tms stm, etm; clock_t rdtm, mmtm; /* create data file */ f = argv[0]; t = file; while (*t = *f++) t++; *t++ = '.'; *t++ = 'D'; *t = 0; if ((fd = creat(file,0666)) < 0) return 1; for (i = 0; i < sizeof(buf); ++i) buf[i] = '0' + (i%10); for (i = 0; i < WRITE; ++i) if (write(fd,buf,sizeof(buf)) != sizeof(buf)) return Failed(file); close(fd); /* read time */ times(&stm); for(run = 0; run < RUN; ++run) { if((fd = open(file, 0)) < 0) return Failed(file); for (i = 0; i < WRITE; ++i) { for(k = 0; k < MAPSIZE; k += BUFSIZE) if (read(fd,buf,BUFSIZE) != BUFSIZE) return Failed(file); } close(fd); } times(&etm); rdtm = (etm.tms_utime-stm.tms_utime) + (etm.tms_stime-stm.tms_stime); /* mmap time */ times(&stm); for(run = 0; run < RUN; ++run) { if ((fd = open(file,0)) < 0) return Failed(file); for(i = 0, mm = (caddr_t)0; i < WRITE; ++i) { if(mm) munmap(mm, MAPSIZE); mm = (caddr_t)mmap((caddr_t)0, MAPSIZE, (PROT_READ|PROT_WRITE), MAP_PRIVATE, fd, i*MAPSIZE ); if(mm == (caddr_t)(-1) || mm == (caddr_t)0) return Failed(file); /* the memcpy is < BUFSIZE to simulate the fact that functions like sfreserve/sfgetr do not do buffer copying. */ t = (char*)mm; for(k = 0; k < MAPSIZE; k += BUFSIZE, t += BUFSIZE) memcpy(buf,t,(3*BUFSIZE)/4); } close(fd); } times(&etm); mmtm = (etm.tms_utime-stm.tms_utime) + (etm.tms_stime-stm.tms_stime); unlink(file); if(4*mmtm <= 3*rdtm) /* mmap is great! */ printf("#define _mmap_worthy 2 \n"); else if(4*mmtm <= 5*rdtm) /* mmap is good */ printf("#define _mmap_worthy 1 \n"); return 0; } }end ################################################## # vfork and any associated header files ################################################## hdr vfork sys vfork lib vfork ################################################## # file control checks ################################################## hdr filio sys filio sys ioctl lib remove lib unlink lib waitpid lib getpagesize tmp rmfail note{ file not removable if still opened }end execute{ #include _BEGIN_EXTERNS_ extern int creat _ARG_((char*, int)); extern int unlink _ARG_((char*)); extern int write _ARG_((int, char*, int)); _END_EXTERNS_ main() { int fw, fr; char file[128]; sprintf(file,"/tmp/iffe%lu",(unsigned long)time(0)); if((fw = creat(file,0666)) < 0) return 0; if((fr = open(file,0)) < 0 ) return 0; if(unlink(file) < 0) return 0; if(write(fw,"0123456789",11) != 11 ) return 0; if(read(fr,file,11) != 11) return 0; if(strcmp(file,"0123456789") != 0) return 0; return 1; } }end more void_int note{ voidptr is larger than int }end execute{ main() { return sizeof(char*) > sizeof(int) ? 0 : 1; } }end more long_int note{ long is larger than int }end execute{ main() { return sizeof(long) > sizeof(int) ? 0 : 1; } }end ################################################################ # See if there is a preferred block size for a file system ################################################################ stat blksize note{ st_blksize is a field in struct stat }end compile{ #include #include main () { struct stat sb; sb.st_blksize = 0; return 0; } }end ################################################## # See if certain prototypes are required ################################################## proto open note{ open() has a vararg prototype }end compile{ #include #include #include #include _BEGIN_EXTERNS_ extern int open _ARG_((const char*,int,...)); _END_EXTERNS_ main() { open("file",0); open("file",0,1); } }end proto bcopy note{ bcopy() has prototype }end compile{ #include main() { char buf[128]; bcopy(buf, "abc", 3); } }end proto bzero note{ bzero() has prototype }end compile{ #include main() { char buf[128]; bzero(buf, 128); } }end lib poll_fd_1 note{ fd is first arg to poll() }end execute{ #include _BEGIN_EXTERNS_ extern int pipe _ARG_((int*)); _END_EXTERNS_ main() { int rw[2]; struct pollfd fd; if (pipe(rw) < 0) return 1; fd.fd = rw[0]; fd.events = POLLIN; fd.revents = 0; return poll(&fd, 1, 0) < 0; } }end lib poll_fd_2 note{ fd is second arg to poll() }end execute{ #include _BEGIN_EXTERNS_ extern int pipe _ARG_((int*)); _END_EXTERNS_ main() { int rw[2]; struct pollfd fd; if (pipe(rw) < 0) return 1; fd.fd = rw[0]; fd.events = POLLIN; fd.revents = 0; return poll(1, &fd, 0) < 0; } }end lib select note{ select() has standard 5 arg interface }end link{ #include #include #include main() { struct timeval tmb; fd_set rd; FD_ZERO(&rd); FD_SET(0,&rd); tmb.tv_sec = 0; tmb.tv_usec = 0; select(1,&rd,(fd_set*)0,(fd_set*)0,&tmb); return 0; } }end ################################################################ ## See if we can peek ahead in unseekable devices ################################################################ stream peek note{ ioctl(I_PEEK) works }end link{ #include #include main() { struct strpeek pbuf; pbuf.flags = 0; pbuf.ctlbuf.maxlen = pbuf.databuf.maxlen = pbuf.ctlbuf.len = pbuf.databuf.len = 0; pbuf.ctlbuf.buf = pbuf.databuf.buf = 0; ioctl(0,I_PEEK,&pbuf); return 0; } }end socket peek note{ recv(MSG_PEEK) works }end link{ #include #include main() { char buf[128]; recv(0,buf,sizeof(buf),MSG_PEEK); return 0; } }end ################################################################ ## See if register layout is ok for vax string operations ################################################################ vax asm note{ register layout ok for vax string operations }end execute{ main() { #ifndef vax return absurd = -1; #else register int r11, r10, r9, r8, r7, r6; r11 = r10 = r9 = r8 = r7 = r6 = -1; asm("clrw r11"); asm("clrw r10"); asm("clrw r9"); asm("clrw r8"); asm("clrw r7"); asm("clrw r6"); if(sizeof(int) != sizeof(char*) || r11 || r10 || r9 || r8 || r7 || r6 ) return -1; return 0; #endif } }end lib strtod note{ native strtod exists }end ################################################################ ## See if there is "locale" stuff for conditioning printf/scanf ################################################################ lib locale note{ Check for localeconv }end compile{ #include main() { struct lconv* lv = localeconv(); return 0; } }end r*) || r11 || r10 || r9 || r8 || r7 || r6 ) return -1; return 0; #esrc/lib/sfio/features/stdio000644 151361 151361 00000021154 07432261457 015725 0ustar00kpvkpv000000 000000 ################################################################ ## Need to hide certain names such as _doprnt, _doscan ################################################################ #pragma weak note{ compile system supports symbol transform }end link{ # main() { return _xyz(); } # #pragma weak _xyz = __xyz # #define _xyz __xyz # _xyz() { return 0; } #}end ################################################################ ## To emulate old-style stdio at binary level ################################################################ tst - output{ #include main() { printf("#define _siz_fpos_t %d\n", sizeof(fpos_t)); printf("#define _siz_off_t %d\n", sizeof(off_t)); exit(0); } }end FILE _cnt note{ field FILE.__cnt exists }end compile{ #include main() { return (stdin->__cnt == 0) ? 0 : -1; } }end FILE _ptr note{ field FILE.__ptr exists }end compile{ #include main() { return (stdin->__ptr == 0) ? 0 : -1; } }end FILE _file note{ field FILE.__file exists }end compile{ #include main() { return (stdin->__file == 0) ? 0 : -1; } }end FILE _flag note{ field FILE.__flag exists }end compile{ #include main() { return (stdin->__flag == 0) ? 0 : -1; } }end FILE cnt note{ field FILE._cnt exists }end compile{ #include main() { return (stdin->_cnt == 0) ? 0 : -1; } }end FILE ptr note{ field FILE._ptr exists }end compile{ #include main() { return (stdin->_ptr == 0) ? 0 : -1; } }end FILE file note{ field FILE._file exists }end compile{ #include main() { return (stdin->_file == 0) ? 0 : -1; } }end FILE flag note{ field FILE._flag exists }end compile{ #include main() { return (stdin->_flag == 0) ? 0 : -1; } }end FILE flags note{ field FILE._flags exists }end compile{ #include main() { return (stdin->_flags == 0) ? 0 : -1; } }end cat{ #if _FILE__cnt && ! _FILE_cnt #define _FILE_cnt 1 #define _cnt __cnt #endif #if _FILE__ptr && ! _FILE_ptr #define _FILE_ptr 1 #define _ptr __ptr #endif #if _FILE__flag && ! _FILE_flag #define _FILE_flag 1 #define _flag __flag #endif #if _FILE__file && ! _FILE_file #define _FILE_file 1 #define _file __file #endif }end ############################################################################ # To emulate Linux-stdio at binary level ############################################################################ FILE readptr note{ fields FILE._IO_read_ptr/end exist }end execute{ #include main() { if(sizeof(stdin->_IO_read_ptr) != sizeof(char*) ) return 1; if(sizeof(stdin->_IO_read_end) != sizeof(char*) ) return 1; return 0; } }end FILE writeptr note{ fields FILE._IO_write_ptr/end exist }end execute{ #include main() { if(sizeof(stdin->_IO_write_ptr) != sizeof(char*) ) return 1; if(sizeof(stdin->_IO_write_end) != sizeof(char*) ) return 1; return 0; } }end FILE flags note{ field FILE._flags exists }end compile{ #include main() { return stdin->_flags == 0 ? 1 : 0; } }end FILE fileno note{ field FILE._fileno exists }end compile{ #include main() { return stdin->_fileno == 0 ? 1 : 0; } }end u flow note{ uflow() does bump buffer }end execute{ #include #if _STD_ main(int argc, char** argv) #else main(argc,argv) int argc; char** argv; #endif { FILE* f; char file[BUFSIZ]; sprintf(file,"%s.D",argv[0]); if(!(f = fopen(file,"w+")) ) exit(1); unlink(file); setbuf(f,file); fputs("123456789",f); fseek(f,0L,0); if(__uflow(f) == EOF) exit(1); if(*f->_IO_read_ptr == '1') exit(1); else exit(0); } }end under flow note{ underflow() does not bump buffer }end execute{ #include #if _STD_ main(int argc, char** argv) #else main(argc,argv) int argc; char** argv; #endif { FILE* f; char file[BUFSIZ]; sprintf(file,"%s.D",argv[0]); if(!(f = fopen(file,"w+")) ) exit(1); unlink(file); setbuf(f,file); fputs("123456789",f); fseek(f,0L,0); if(__underflow(f) == EOF) exit(1); if(*f->_IO_read_ptr == '1') exit(0); else exit(1); } }end ###################################################################### # To emulate BSD-style stdio ###################################################################### FILE p note{ FILE._p field }end compile{ #include main() { return stdin->_p == 0 ? 0 : 1; } }end FILE r note{ FILE._r field }end compile{ #include main() { return stdin->_r == 0 ? 0 : 1; } }end FILE w note{ FILE._w field }end compile{ #include main() { return stdout->_w == 0 ? 0 : 1; } }end lib __swbuf lib __srget lib __uflow lib __underflow lib __overflow lib _IO_getc lib _IO_putc lib clearerr_unlocked lib feof_unlocked lib ferror_unlocked lib fflush_unlocked lib fgetc_unlocked lib fgets_unlocked lib fileno_unlocked lib fputc_unlocked lib fputs_unlocked lib fread_unlocked lib fwrite_unlocked lib getc_unlocked lib getchar_unlocked lib putc_unlocked lib putchar_unlocked lib __snprintf lib __vsnprintf lib fseeko lib ftello # detect microsoft dll declaration of _iob mac _iob stdio.h msft iob note{ microsoft's oddity }end compile{ #include #if _mac__iob _CRTIMP extern FILE * __cdecl __p__iob(void); FILE* foo() { return &(_iob[0]); } #else this should fail; #endif }end dat _iob,__iob stdio.h native iob note{ ok to use stdio's _iob }end compile{ #define _doprnt _____doprnt #define _doscan _____doscan #define fclose ____fclose #define fdopen ____fdopen #define fflush ____fflush #define fgetc ____fgetc #define fgets ____fgets #define _filbuf _____filbuf #define _flsbuf _____flsbuf #define _cleanup _____cleanup #define fopen ____fopen #define fprintf ____fprintf #define fputc ____fputc #define fputs ____fputs #define fread ____fread #define freopen ____freopen #define fscanf ____fscanf #define fseek ____fseek #define ftell ____ftell #define fgetpos ____fgetpos #define fsetpos ____fsetpos #define fpurge ____fpurge #define fwrite ____fwrite #define gets ____gets #define getw ____getw #define pclose ____pclose #define popen ____popen #define printf ____printf #define puts ____puts #define putw ____putw #define rewind ____rewind #define scanf ____scanf #define setbuf ____setbuf #define setbuffer ____setbuffer #define setlinebuf ____setlinebuf #define setvbuf ____setvbuf #define sprintf ____sprintf #define sscanf ____sscanf #define tmpfile ____tmpfile #define ungetc ____ungetc #define vfprintf ____vfprintf #define vfscanf ____vfscanf #define vprintf ____vprintf #define vscanf ____vscanf #define vsprintf ____vsprintf #define vsscanf ____vsscanf #define flockfile ____flockfile #define funlockfile ____funlockfile #define ftrylockfile ____ftrylockfile #include #undef IOB #if defined(_dat_iob) && !defined(IOB) #define IOB iob #endif #if defined(_dat__iob) && !defined(IOB) #define IOB _iob #endif #if defined(_dat___iob) && !defined(IOB) #define IOB __iob #endif static void* addr() { return((void*)IOB); } int main() { addr(); exit(0); } #undef _doprnt #undef _doscan #undef fclose #undef fdopen #undef fflush #undef fgetc #undef fgets #undef _filbuf #undef _flsbuf #undef _cleanup #undef fopen #undef fprintf #undef fputc #undef fputs #undef fread #undef freopen #undef fscanf #undef fseek #undef ftell #undef fgetpos #undef fsetpos #undef fpurge #undef fwrite #undef gets #undef getw #undef pclose #undef popen #undef printf #undef puts #undef putw #undef rewind #undef scanf #undef setbuf #undef setbuffer #undef setlinebuf #undef setvbuf #undef sprintf #undef sscanf #undef tmpfile #undef ungetc #undef vfprintf #undef vfscanf #undef vprintf #undef vscanf #undef vsprintf #undef vsscanf #undef flockfile #undef funlockfile #undef ftrylockfile void _doprnt() {} void _doscan() {} void fclose() {} void fdopen() {} void fflush() {} void fgetc() {} void fgets() {} void _filbuf() {} void _flsbuf() {} void _cleanup() {} void fopen() {} void fprintf() {} void fputc() {} void fputs() {} void fread() {} void freopen() {} void fscanf() {} void fseek() {} void ftell() {} void fgetpos() {} void fsetpos() {} void fpurge() {} void fwrite() {} void gets() {} void getw() {} void pclose() {} void popen() {} void printf() {} void puts() {} void putw() {} void rewind() {} void scanf() {} void setbuf() {} void setbuffer() {} void setlinebuf() {} void setvbuf() {} void sprintf() {} void sscanf() {} void tmpfile() {} void ungetc() {} void vfprintf() {} void vfscanf() {} void vprintf() {} void vscanf() {} void vsprintf() {} void vsscanf() {} void flockfile() {} void funlockfile() {} void ftrylockfile() {} }end void fwrite() {} void gets() {} void getw() {} void pclose() {} void popen() {} void printf() {} void puts() {} void putw() {} void rewind() {} void scanf() {} void setbuf() {} void setbuffer() {} void setlinebuf() {} void setvbuf() {} void sprintf() {} void sscanf() {} void tmpfile() {} void ungetc() {} void vfprintf() {} void vfscanf() {} void vprintf() {} void vscanf() {} voisrc/lib/sfio/features/iffeio000644 151361 151361 00000000117 07432261457 016040 0ustar00kpvkpv000000 000000 iff SFSTDIO cat{ #include "FEATURE/common" #include "FEATURE/stdio.lcl" }end /home/kpv/Software/src/lib/sfio/featuress{} void gets() {} void getw() {} void pclose() {} void popen() {} void printf() {} void puts() {} void putw() {} void rewind() {} void scanf() {} void setbuf() {} void setbuffer() {} void setlinebuf() {} void setvbuf() {} void sprintf() {} void sscanf() {} void tmpfile() {} v YB#AVs=Jg4<%l.<%l.@src/lib/sfio/features/float000644 151361 151361 00000032553 07436546025 015716 0ustar00kpvkpv000000 000000 hdr float,limits,math,values lib frexp,frexpl,ldexp,ldexpl ast mpy_overflow_fpe note{ fpe on mpy overflow }end noexecute{ main() { float f; float p; p = f = 1.0; do { p = f; f *= 2.0; } while (f != p); return 0; } }end ast div_underflow_fpe note{ fpe on div underflow }end noexecute{ main() { float f; float p; p = f = 1.0; do { p = f; f /= 2.0; } while (f != p); return 0; } }end macro{ #if _hdr_float #include #endif #if _hdr_limits #include #endif #if _hdr_math #include #endif #if _hdr_values #include #endif #if !defined(FLT_MIN_EXP) && defined(FMINEXP) #define FLT_MIN_EXP FMINEXP #endif #if !defined(FLT_MIN) && defined(MINFLOAT) #define FLT_MIN MINFLOAT #endif #if !defined(FLT_MAX_EXP) && defined(FMAXEXP) #define FLT_MAX_EXP FMAXEXP #endif #if !defined(FLT_MAX) && defined(MAXFLOAT) #define FLT_MAX MAXFLOAT #endif #if !defined(DBL_MIN_EXP) && defined(DMINEXP) #define DBL_MIN_EXP DMINEXP #endif #if !defined(DBL_MIN) && defined(MINDOUBLE) #define DBL_MIN MINDOUBLE #endif #if !defined(DBL_MAX_EXP) && defined(DMAXEXP) #define DBL_MAX_EXP DMAXEXP #endif #if !defined(DBL_MAX) && defined(MAXDOUBLE) #define DBL_MAX MAXDOUBLE #endif #if _hdr_float <<#if _hdr_float>> <<"#include ">> <<#endif>> #endif #if _hdr_math <<#if _hdr_math>> <<"#include ">> <<#endif>> #endif #ifdef FLT_DIG <<"#ifndef FLT_DIG">> <<"#define FLT_DIG">> FLT_DIG <<"#endif">> #endif #ifdef FLT_MAX <<"#ifndef FLT_MAX">> <<"#define FLT_MAX">> FLT_MAX <<"#endif">> #endif #ifdef FLT_MAX_10_EXP <<"#ifndef FLT_MAX_10_EXP">> <<"#define FLT_MAX_10_EXP">> FLT_MAX_10_EXP <<"#endif">> #endif #ifdef FLT_MAX_EXP <<"#ifndef FLT_MAX_EXP">> <<"#define FLT_MAX_EXP">> FLT_MAX_EXP <<"#endif">> #endif #ifdef FLT_MIN <<"#ifndef FLT_MIN">> <<"#define FLT_MIN">> FLT_MIN <<"#endif">> #endif #ifdef FLT_MIN_10_EXP <<"#ifndef FLT_MIN_10_EXP">> <<"#define FLT_MIN_10_EXP">> FLT_MIN_10_EXP <<"#endif">> #endif #ifdef FLT_MIN_EXP <<"#ifndef FLT_MIN_EXP">> <<"#define FLT_MIN_EXP">> FLT_MIN_EXP <<"#endif">> #endif #ifdef DBL_DIG <<"#ifndef DBL_DIG">> <<"#define DBL_DIG">> DBL_DIG <<"#endif">> #endif #ifdef DBL_MAX <<"#ifndef DBL_MAX">> <<"#define DBL_MAX">> DBL_MAX <<"#endif">> #endif #ifdef DBL_MAX_10_EXP <<"#ifndef DBL_MAX_10_EXP">> <<"#define DBL_MAX_10_EXP">> DBL_MAX_10_EXP <<"#endif">> #endif #ifdef DBL_MAX_EXP <<"#ifndef DBL_MAX_EXP">> <<"#define DBL_MAX_EXP">> DBL_MAX_EXP <<"#endif">> #endif #ifdef DBL_MIN <<"#ifndef DBL_MIN">> <<"#define DBL_MIN">> DBL_MIN <<"#endif">> #endif #ifdef DBL_MIN_10_EXP <<"#ifndef DBL_MIN_10_EXP">> <<"#define DBL_MIN_10_EXP">> DBL_MIN_10_EXP <<"#endif">> #endif #ifdef DBL_MIN_EXP <<"#ifndef DBL_MIN_EXP">> <<"#define DBL_MIN_EXP">> DBL_MIN_EXP <<"#endif">> #endif #ifdef LDBL_DIG <<"#ifndef LDBL_DIG">> <<"#define LDBL_DIG">> LDBL_DIG <<"#endif">> #endif #ifdef LDBL_MAX <<"#ifndef LDBL_MAX">> <<"#define LDBL_MAX">> LDBL_MAX <<"#endif">> #endif #ifdef LDBL_MAX_10_EXP <<"#ifndef LDBL_MAX_10_EXP">> <<"#define LDBL_MAX_10_EXP">> LDBL_MAX_10_EXP <<"#endif">> #endif #ifdef LDBL_MAX_EXP <<"#ifndef LDBL_MAX_EXP">> <<"#define LDBL_MAX_EXP">> LDBL_MAX_EXP <<"#endif">> #endif #ifdef LDBL_MIN <<"#ifndef LDBL_MIN">> <<"#define LDBL_MIN">> LDBL_MIN <<"#endif">> #endif #ifdef LDBL_MIN_10_EXP <<"#ifndef LDBL_MIN_10_EXP">> <<"#define LDBL_MIN_10_EXP">> LDBL_MIN_10_EXP <<"#endif">> #endif #ifdef LDBL_MIN_EXP <<"#ifndef LDBL_MIN_EXP">> <<"#define LDBL_MIN_EXP">> LDBL_MIN_EXP <<"#endif">> #endif }end tst - output{ #include "FEATURE/common" #if _hdr_float #include #endif #if _hdr_limits #include #endif #if _hdr_math #include #endif #if _hdr_values #include #endif #include #ifdef SIGFPE int caught = 0; #if _STD_ int catch(int sig) #else int catch(sig) int sig; #endif { signal(sig, SIG_IGN); caught++; return 0; } #endif main() { register int i; register int s; float f; float pf; float mf; float xf; double d; double pd; double md; #if _ast_fltmax_double char* fs = ""; char* ds = ""; #else _ast_fltmax_t l; _ast_fltmax_t pl; _ast_fltmax_t ml; char* fs = "F"; char* ds = ""; char* ls = "L"; #endif unsigned long u; unsigned _ast_intmax_t w; unsigned _ast_intmax_t pw; unsigned _ast_intmax_t x; unsigned short us; unsigned int ui; unsigned long ul; unsigned _ast_intmax_t uq; #ifdef SIGFPE signal(SIGFPE, catch); #endif printf("#include\t\"FEATURE/common\"\n"); printf("\n"); printf("\n"); us = 0; us = ~us; i = 0; while (us /= 10) i++; printf("#define USHRT_DIG %d\n", i); ui = 0; ui = ~ui; i = 0; while (ui /= 10) i++; printf("#define UINT_DIG %d\n", i); ul = 0; ul = ~ul; i = 0; while (ul /= 10) i++; printf("#define ULONG_DIG %d\n", i); if (sizeof(uq) > sizeof(ul)) { uq = 0; uq = ~uq; i = 0; while (uq /= 10) i++; printf("#define ULONGLONG_DIG %d\n", i); printf("#define UINTMAX_DIG ULONGLONG_DIG\n"); } else printf("#define UINTMAX_DIG ULONG_DIG\n"); printf("\n"); w = 1; do { pw = w; w *= 2; f = (_ast_intmax_t)w; x = (_ast_intmax_t)f; } while (w > pw && w == x); w = (pw - 1) + pw; u = ~0; if (u > w) u = w; printf("#define FLT_ULONG_MAX %lu.0F\n", u); if (sizeof(w) > sizeof(u)) { printf("#define FLT_ULONGLONG_MAX %llu.0F\n", w); printf("#define FLT_UINTMAX_MAX FLT_ULONGLONG_MAX\n"); } else printf("#define FLT_UINTMAX_MAX FLT_ULONG_MAX\n"); #ifdef FLT_DIG s = FLT_DIG; #else f = pf = 1.0; s = -1; do { s++; f *= 10.0; } while (f != (f + pf)); #endif #if defined(FLT_MIN) && defined(FLT_MIN_EXP) i = FLT_MIN_EXP; mf = FLT_MIN; #else i = 3; f = pf = 1.0; do { i--; mf = pf; pf = f; f /= 2.0; } while (f < pf); #ifdef FLT_MIN_EXP i = FLT_MIN_EXP; #endif #ifdef FLT_MIN mf = FLT_MIN; #endif #endif #ifndef FLT_DIG printf("#ifndef FLT_DIG\n"); printf("#define FLT_DIG %d\n", s); printf("#endif\n"); #endif #ifndef FLT_MIN printf("#ifndef FLT_MIN\n"); printf("#define FLT_MIN %.*E%s\n", s + 1, mf, fs); printf("#endif\n"); #endif #ifndef FLT_MIN_EXP printf("#ifndef FLT_MIN_EXP\n"); printf("#define FLT_MIN_EXP (%d)\n", i); printf("#endif\n"); #endif #if defined(FLT_MAX) && defined(FLT_MAX_EXP) i = FLT_MAX_EXP; f = FLT_MAX; #else i = -1; f = pf = 1.0; do { i++; mf = pf; pf = f; f *= 2.0; } while (f > pf); #ifdef FLT_MAX_EXP i = FLT_MAX_EXP; #endif #ifdef FLT_MAX f = FLT_MAX; #endif #endif #ifdef FLT_MAX_EXP i = FLT_MAX_EXP; #else f = 1; do { f *= 2.0; } while (mf == (mf + f)); f = (mf - f) * 2.0 + f; #endif xf = f; #ifndef FLT_MAX printf("#ifndef FLT_MAX\n"); printf("#define FLT_MAX %.*E%s\n", s + 1, f, fs); printf("#endif\n"); #endif #ifndef FLT_MAX_EXP printf("#ifndef FLT_MAX_EXP\n"); printf("#define FLT_MAX_EXP %d\n", i); printf("#endif\n"); #endif #ifdef FLT_MIN_10_EXP i = FLT_MIN_10_EXP; #else i = 2; f = 1.0; do { i--; pf = f; f /= 10.0; } while (f < pf); #endif #ifndef FLT_MIN_10_EXP printf("#ifndef FLT_MIN_10_EXP\n"); printf("#define FLT_MIN_10_EXP (%d)\n", i); printf("#endif\n"); #endif #ifdef FLT_MAX_10_EXP i = FLT_MAX_10_EXP; #else i = -2; f = 1.0; do { i++; pf = f; f *= 10.0; } while (f > pf); #endif #ifndef FLT_MAX_10_EXP printf("#ifndef FLT_MAX_10_EXP\n"); printf("#define FLT_MAX_10_EXP %d\n", i); printf("#endif\n"); #endif printf("\n"); w = 1; do { pw = w; w *= 2; d = (_ast_intmax_t)w; x = (_ast_intmax_t)d; } while (w > pw && w == x); w = (pw - 1) + pw; u = ~0; if (u > w) u = w; printf("#define DBL_ULONG_MAX %lu.0\n", u); if (sizeof(w) > sizeof(u)) { printf("#define DBL_ULONGLONG_MAX %llu.0\n", w); printf("#define DBL_UINTMAX_MAX DBL_ULONGLONG_MAX\n"); } else printf("#define DBL_UINTMAX_MAX DBL_ULONG_MAX\n"); #ifdef DBL_DIG s = DBL_DIG; #else d = pd = 1.0; s = -1; do { s++; d *= 10.0; } while (d != (d + pd)); #endif #if defined(DBL_MIN) && defined(DBL_MIN_EXP) i = DBL_MIN_EXP; md = DBL_MIN; #else i = 3; d = pd = 1.0; do { i--; md = pd; pd = d; d /= 2.0; } while (d < pd); #ifdef DBL_MIN_EXP i = DBL_MIN_EXP; #endif #ifdef DBL_MIN md = DBL_MIN; #endif #endif #ifndef DBL_DIG printf("#ifndef DBL_DIG\n"); printf("#define DBL_DIG %d\n", s); printf("#endif\n"); #endif #ifndef DBL_MIN printf("#ifndef DBL_MIN\n"); printf("#define DBL_MIN %.*E%s\n", s + 1, md, ds); printf("#endif\n"); #endif #ifndef DBL_MIN_EXP printf("#ifndef DBL_MIN_EXP\n"); printf("#define DBL_MIN_EXP (%d)\n", i); printf("#endif\n"); #endif #if defined(DBL_MAX) && defined(DBL_MAX_EXP) i = DBL_MAX_EXP; d = DBL_MAX; #else i = -1; d = pd = 1.0; do { i++; md = pd; pd = d; d *= 2.0; } while (d > pd); d = 1.0; do { d *= 2.0; } while (md == (md + d)); d = (md - d) * 2.0 + d; #ifdef DBL_MAX_EXP i = DBL_MAX_EXP; #endif #ifdef DBL_MAX d = DBL_MAX; #endif #endif #ifndef DBL_MAX printf("#ifndef DBL_MAX\n"); printf("#define DBL_MAX %.*E%s\n", s + 1, d, ds); printf("#endif\n"); #endif #ifndef DBL_MAX_EXP printf("#ifndef DBL_MAX_EXP\n"); printf("#define DBL_MAX_EXP %d\n", i); printf("#endif\n"); #endif #ifdef DBL_MIN_10_EXP i = DBL_MIN_10_EXP; #else i = 2; d = 1.0; do { i--; pd = d; d /= 10.0; } while (d < pd); #endif #ifndef DBL_MIN_10_EXP printf("#ifndef DBL_MIN_10_EXP\n"); printf("#define DBL_MIN_10_EXP (%d)\n", i); printf("#endif\n"); #endif #ifdef DBL_MAX_10_EXP i = DBL_MAX_10_EXP; #else i = -2; d = 1.0; do { i++; pd = d; d *= 10.0; } while (d > pd); #endif #ifndef DBL_MAX_10_EXP printf("#ifndef DBL_MAX_10_EXP\n"); printf("#define DBL_MAX_10_EXP %d\n", i); printf("#endif\n"); #endif #if !_ast_fltmax_double printf("\n"); w = 1; do { pw = w; w *= 2; l = (_ast_intmax_t)w; x = (_ast_intmax_t)l; } while (w > pw && w == x); w = (pw - 1) + pw; u = ~0; if (u > w) u = w; printf("#define LDBL_ULONG_MAX %lu.0L\n", u); if (sizeof(w) > sizeof(u)) { printf("#define LDBL_ULONGLONG_MAX %llu.0L\n", w); printf("#define LDBL_UINTMAX_MAX LDBL_ULONGLONG_MAX\n"); } else printf("#define LDBL_UINTMAX_MAX LDBL_ULONG_MAX\n"); #ifdef LDBL_DIG s = LDBL_DIG; #else l = pl = 1.0L; s = -1; do { s++; l *= 10.0L; } while (l != (l + pl)); #endif #if defined(LDBL_MIN) && defined(LDBL_MIN_EXP) i = LDBL_MIN_EXP; ml = LDBL_MIN; #else i = 3; l = pl = 1.0L; do { i--; ml = pl; pl = l; l /= 2.0L; } while (l < pl); #ifdef LDBL_MIN_EXP i = LDBL_MIN_EXP; #endif #ifdef LDBL_MIN ml = LDBL_MIN; #endif #endif #ifndef LDBL_DIG printf("#ifndef LDBL_DIG\n"); printf("#define LDBL_DIG %d\n", s); printf("#endif\n"); #endif #ifndef LDBL_MIN printf("#ifndef LDBL_MIN\n"); printf("#define LDBL_MIN %.*LE%s\n", s + 1, ml, ls); printf("#endif\n"); #endif #ifndef LDBL_MIN_EXP printf("#ifndef LDBL_MIN_EXP\n"); printf("#define LDBL_MIN_EXP (%d)\n", i); printf("#endif\n"); #endif #if defined(LDBL_MAX) && defined(LDBL_MAX_EXP) i = LDBL_MAX_EXP; l = LDBL_MAX; #else i = -1; l = pl = 1.0L; do { i++; ml = pl; pl = l; l *= 2.0L; } while (l > pl); l = 1.0L; do { l *= 2.0L; } while (ml == (ml + l)); l = (ml - l) * 2.0L + l; #ifdef LDBL_MAX_EXP i = LDBL_MAX_EXP; #endif #ifdef LDBL_MAX l = LDBL_MAX; #endif #endif #ifndef LDBL_MAX printf("#ifndef LDBL_MAX\n"); printf("#define LDBL_MAX %.*LE%s\n", s + 1, l, ls); printf("#endif\n"); #endif #ifndef LDBL_MAX_EXP printf("#ifndef LDBL_MAX_EXP\n"); printf("#define LDBL_MAX_EXP %d\n", i); printf("#endif\n"); #endif #ifdef LDBL_MIN_10_EXP i = LDBL_MIN_10_EXP; #else i = 2; l = 1.0L; do { i--; pl = l; l /= 10.0L; } while (l < pl); #endif #ifndef LDBL_MIN_10_EXP printf("#ifndef LDBL_MIN_10_EXP\n"); printf("#define LDBL_MIN_10_EXP (%d)\n", i); printf("#endif\n"); #endif #ifdef LDBL_MAX_10_EXP i = LDBL_MAX_10_EXP; #else i = -2; l = 1.0L; do { i++; pl = l; l *= 10.0L; } while (l > pl); #endif #ifndef LDBL_MAX_10_EXP printf("#ifndef LDBL_MAX_10_EXP\n"); printf("#define LDBL_MAX_10_EXP %d\n", i); printf("#endif\n"); #endif #endif #ifdef SIGFPE if (!caught) { f = xf; f *= 2; if (!f) caught = 1; } if (caught) printf("#define _ast_fltsig %d\n", SIGFPE); #endif printf("\n"); printf("_BEGIN_EXTERNS_\n"); #if !_lib_frexp printf("extern double frexp _ARG_((double, int*));\n"); #endif #if !_lib_frexpl printf("extern _ast_fltmax_t frexpl _ARG_((_ast_fltmax_t, int*));\n"); #endif #if !_lib_ldexp printf("extern double ldexp _ARG_((double, int));\n"); #endif #if !_lib_ldexpl printf("extern _ast_fltmax_t ldexpl _ARG_((_ast_fltmax_t, int));\n"); #endif printf("_END_EXTERNS_\n"); return 0; } }end tst - -DN=1 - -DN=2 output{ main() { #if N == 1 unsigned long long m; long double f = 123.456; m = f; if (!m || f == m) return 1; printf("#define _ast_flt_unsigned_max_t unsigned long long\n"); #else printf("#define _ast_flt_unsigned_max_t unsigned long\n"); #endif return 0; } }end xtern double ldexp _ARG_((double, int));\n"); #endif #if !_lib_ldexpl printf("extern _ast_fltmax_t ldexpl _ARG_((_ast_fltmax_t, int));\n"); #ensrc/lib/sfio/features/stdio_lcl000644 151361 151361 00000000012 07432261457 016545 0ustar00kpvkpv000000 000000 lcl stdio _k]D_k_o_/home/kpv/Software/src/lib/sfio/featuressong m; long double f = 123.456; m = f; if (!m || f == m) return 1; printf("#define _ast_flt_unsigned_max_t unsigned long long\n"); #else printf("#define _ast_flt_unsigned_max_t unsigned long\n"); #endif return 0; } }end xtern double ldexp _ARG_((double, int));\n"); #endi YB#AVs=Jg4<%l.<%l.@src/lib/sfio/features/sfinit.c000644 151361 151361 00000005255 07436552561 016327 0ustar00kpvkpv000000 000000 /* * generate sfio _Sftable static initializers */ #include "FEATURE/iffeio" #include "FEATURE/common" #include "FEATURE/float" main() { register int i; #if _ast_fltmax_double char* fs = ""; char* ds = ""; char* ls = ""; #else char* fs = "F"; char* ds = ""; char* ls = "L"; #endif #if __STD_C #define CONST "const" #else #define CONST "" #endif printf("\nstatic %s float sf_flt_pow10[] =\n{\n", CONST); for (i = 0; i <= FLT_MAX_10_EXP; i++) printf("\t1E%d%s,\n", i, fs); printf("};\n"); printf("\nstatic %s double sf_dbl_pow10[] =\n{\n", CONST); for (i = 0; i <= DBL_MAX_10_EXP; i++) printf("\t1E%d%s,\n", i, ds); printf("};\n"); #if !_ast_fltmax_double printf("\nstatic %s _ast_fltmax_t sf_ldbl_pow10[] =\n{\n", CONST); for (i = 0; i <= LDBL_MAX_10_EXP; i++) printf("\t1E%d%s,\n", i, ls); printf("};\n"); #endif printf("\nSftab_t _Sftable =\n{\n"); printf("\t{ 1E1%s, 1E2%s, 1E4%s, 1E8%s, 1E16%s, 1E32%s },\n", ls, ls, ls, ls, ls, ls); printf("\t{ 1E-1%s, 1E-2%s, 1E-4%s, 1E-8%s, 1E-16%s, 1E-32%s },\n", ls, ls, ls, ls, ls, ls); printf("\t{ '0','0', '0','1', '0','2', '0','3', '0','4',\n"); printf("\t '0','5', '0','6', '0','7', '0','8', '0','9',\n"); printf("\t '1','0', '1','1', '1','2', '1','3', '1','4',\n"); printf("\t '1','5', '1','6', '1','7', '1','8', '1','9',\n"); printf("\t '2','0', '2','1', '2','2', '2','3', '2','4',\n"); printf("\t '2','5', '2','6', '2','7', '2','8', '2','9',\n"); printf("\t '3','0', '3','1', '3','2', '3','3', '3','4',\n"); printf("\t '3','5', '3','6', '3','7', '3','8', '3','9',\n"); printf("\t '4','0', '4','1', '4','2', '4','3', '4','4',\n"); printf("\t '4','5', '4','6', '4','7', '4','8', '4','9',\n"); printf("\t '5','0', '5','1', '5','2', '5','3', '5','4',\n"); printf("\t '5','5', '5','6', '5','7', '5','8', '5','9',\n"); printf("\t '6','0', '6','1', '6','2', '6','3', '6','4',\n"); printf("\t '6','5', '6','6', '6','7', '6','8', '6','9',\n"); printf("\t '7','0', '7','1', '7','2', '7','3', '7','4',\n"); printf("\t '7','5', '7','6', '7','7', '7','8', '7','9',\n"); printf("\t '8','0', '8','1', '8','2', '8','3', '8','4',\n"); printf("\t '8','5', '8','6', '8','7', '8','8', '8','9',\n"); printf("\t '9','0', '9','1', '9','2', '9','3', '9','4',\n"); printf("\t '9','5', '9','6', '9','7', '9','8', '9','9',\n"); printf("\t},\n"); printf("\t\"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_\",\n"); printf("\tsfcvinit, 0,\n"); printf("\tsffmtpos,\n"); printf("\tsffmtint,\n"); printf("\t(float*)&sf_flt_pow10[0],\n"); printf("\t(double*)&sf_dbl_pow10[0],\n"); #if _ast_fltmax_double printf("\t0,\n"); #else printf("\t(_ast_fltmax_t*)&sf_ldbl_pow10[0],\n"); #endif printf("};\n"); return 0; } '9','1', '9','2', '9','3', '9','4',\n"); printf("\t '9','5', '9','6', '9','7', '9','8', '9','9',\n"); printf("\t},\n"); printf("\t\"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_\",\n"); printf("\tsfcvinit, 0,\n"); printf("\tsffmtpos,\n"); printf("\tsffmtint,\n"); printf("\t(float*)&sf_flt_pow10[0],\n"); printsrc/lib/sfio/features/common000644 151361 151361 00000021637 07432510164 016071 0ustar00kpvkpv000000 000000 iff AST_COMMON hdr pthread,stddef,types,stdlib sys types typ long.double,size_t,ssize_t,ptrdiff_t mac SF_APPEND,SF_CLOSE sys/stat.h sys/socket.h dll import note{ Microsoft import/export nonsense }end execute{ __declspec(dllimport) int foo; main() { return foo == 5 ? 0 : 1; } int bar = 5; int* _imp__foo = &bar; }end std proto note{ standard C prototypes ok }end compile{ extern int foo(int, int); bar() { foo(1, 1); } }end tst ptr_void note{ standard C void* ok }end compile{ extern void* foo(); void* bar() { return foo(); } }end cat{ /* disable non-standard linux/gnu inlines */ #ifdef __GNUC__ # undef __OPTIMIZE_SIZE__ # define __OPTIMIZE_SIZE__ 1 #endif /* __STD_C indicates that the language is ANSI-C or C++ */ #if !defined(__STD_C) && __STDC__ # define __STD_C 1 #endif #if !defined(__STD_C) && (__cplusplus || c_plusplus) # define __STD_C 1 #endif #if !defined(__STD_C) && _std_proto # define __STD_C 1 #endif #if !defined(__STD_C) # define __STD_C 0 #endif /* extern symbols must be protected against C++ name mangling */ #ifndef _BEGIN_EXTERNS_ # if __cplusplus || c_plusplus # define _BEGIN_EXTERNS_ extern "C" { # define _END_EXTERNS_ } # else # define _BEGIN_EXTERNS_ # define _END_EXTERNS_ # endif #endif /* _ARG_ simplifies function prototyping among flavors of C */ #ifndef _ARG_ # if __STD_C # define _ARG_(x) x # else # define _ARG_(x) () # endif #endif /* _NIL_ simplifies defining nil pointers to a given type */ #ifndef _NIL_ # define _NIL_(x) ((x)0) #endif /* __INLINE__ is the inline keyword */ #if !defined(__INLINE__) && defined(__cplusplus) # define __INLINE__ inline #endif #if !defined(__INLINE__) && defined(_WIN32) && !defined(__GNUC__) # define __INLINE__ __inline #endif /* Void_t is defined so that Void_t* can address any type */ #ifndef Void_t # if __STD_C # define Void_t void # else # define Void_t char # endif #endif /* dynamic linked library external scope handling */ #ifdef __DYNAMIC__ # undef __DYNAMIC__ # ifndef _DLL # define _DLL # endif #endif #if _dll_import # if _BLD_STATIC && !_BLD_DLL # undef _DLL # else # if !_UWIN && !defined(_DLL) # define _DLL 1 # endif # endif # if !defined(__EXPORT__) && _BLD_DLL # define __EXPORT__ __declspec(dllexport) # endif # if !defined(__IMPORT__) && ( _BLD_DLL || _DLL ) # define __IMPORT__ __declspec(dllimport) # endif # if _BLD_DLL && _UWIN # define __DYNAMIC__(v) (_ast_getdll()->_ast_ ## v) # endif #endif #if !defined(_astimport) # if defined(__IMPORT__) && _DLL # define _astimport __IMPORT__ # else # define _astimport extern # endif #endif #if _dll_import && !_BLD_DLL # ifdef __STDC__ # define __EXTERN__(T,obj) extern T obj; T* _imp__ ## obj = &obj # define __DEFINE__(T,obj,val) T obj = val; T* _imp__ ## obj = &obj # else # define __EXTERN__(T,obj) extern T obj; T* _imp__/**/obj = &obj # define __DEFINE__(T,obj,val) T obj = val; T* _imp__/**/obj = &obj # endif #else # define __EXTERN__(T,obj) extern T obj # define __DEFINE__(T,obj,val) T obj = val #endif }end tst _ast_LL note{ LL numeric suffix supported }end compile{ int i = 1LL; }end tst - -DN=0 - -DN=1 - -DN=2 - -DN=3 - -DN=4 - -DN=5 - -DN=6 - -DN=7 - -DN=8 output{ #define _BYTESEX_H #include #if N == 0 #define _ast_int8_t long #define _ast_int8_str "long" #endif #if N == 1 #define _ast_int8_t __int64 #define _ast_int8_str "__int64" #endif #if N == 2 #define _ast_int8_t long long #define _ast_int8_str "long long" #endif #if N == 3 #define _ast_int8_t __int64_t #define _ast_int8_str "__int64_t" #endif #if N == 4 #define _ast_int8_t _int64_t #define _ast_int8_str "_int64_t" #endif #if N == 5 #define _ast_int8_t int64_t #define _ast_int8_str "int64_t" #endif #if N == 6 #define _ast_int8_t _int64 #define _ast_int8_str "_int64" #endif #if N == 7 #define _ast_int8_t int64 #define _ast_int8_str "int64" #endif #define elementsof(x) (sizeof(x)/sizeof(x[0])) static char i_char = 1; static short i_short = 1; static int i_int = 1; static long i_long = 1L; #ifdef _ast_int8_t #if _ast_LL static _ast_int8_t i_long_long = 1LL; static unsigned _ast_int8_t u_long_long = 18446744073709551615LLU; #else static _ast_int8_t i_long_long = 1; static unsigned _ast_int8_t u_long_long = 18446744073709551615; #endif #endif static struct { char* name; int size; char* swap; } int_type[] = { "char", sizeof(char), (char*)&i_char, "short", sizeof(short), (char*)&i_short, "int", sizeof(int), (char*)&i_int, "long", sizeof(long), (char*)&i_long, #ifdef _ast_int8_t _ast_int8_str, sizeof(_ast_int8_t), (char*)&i_long_long, #endif }; static struct { char* name; int size; } flt_type[] = { "float", sizeof(float), "double", sizeof(double), #ifdef _typ_long_double "long double", sizeof(long double), #endif }; static int int_size[] = { 1, 2, 4, 8 }; main() { register int t; register int s; register int m = 1; register int b = 1; register int w = 0; #ifdef _ast_int8_t if (int_type[elementsof(int_type)-1].size <= 4) return 1; #endif for (s = 0; s < elementsof(int_size); s++) { for (t = 0; t < elementsof(int_type) && int_type[t].size < int_size[s]; t++); if (t < elementsof(int_type)) { m = int_size[s]; printf("#define _ast_int%d_t %s\n", m, int_type[t].name); if (m > 1) { if (*int_type[t].swap) w |= b; b <<= 1; } } } printf("#define _ast_intmax_t _ast_int%d_t\n", m); if (m == sizeof(long)) printf("#define _ast_intmax_long 1\n"); printf("#define _ast_intswap %d\n", w); printf("\n"); for (t = 0; t < elementsof(flt_type); t++) { while (t < elementsof(flt_type) && flt_type[t].size == flt_type[t + 1].size) t++; m = flt_type[t].size; printf("#define _ast_flt%d_t %s\n", flt_type[t].size, flt_type[t].name); } printf("#define _ast_fltmax_t _ast_flt%d_t\n", m); if (m == sizeof(double)) printf("#define _ast_fltmax_double 1\n"); return 0; } }end tst - -DTRY=1 - -DTRY=1 -Dvoid=char - -DTRY=2 - -DTRY=3 - -DTRY=4 output{ #define printf ______printf #ifdef __STDC__ #include #else #include #endif #undef printf static va_list ap; main() { #if TRY == 4 printf("\n#ifndef va_listref\n"); printf("#define va_listref(p) (&(p))\t"); printf("/* pass va_list to varargs function */\n"); printf("#define va_listval(p) (*(p))\t"); printf("/* retrieve va_list from va_arg(ap,va_listarg) */\n"); printf("#define va_listarg va_list*\t"); printf("/* va_arg() va_list type */\n"); #else #if TRY == 1 *ap++; #endif /*TRY == 1*/ #if TRY == 2 *ap; #endif /*TRY == 2*/ #if TRY == 3 ap++; #endif /*TRY == 3*/ printf("\n#ifndef va_listref\n"); printf("#define va_listref(p) (p)\t"); printf("/* pass va_list to varargs function */\n"); if (sizeof(va_list) > sizeof(void*)) printf("#define va_listval(p) (*(p))\t"); else printf("#define va_listval(p) (p)\t"); printf("/* retrieve va_list from va_arg(ap,va_listarg) */\n"); #if TRY == 2 printf("#define va_listarg va_list*\t"); #else printf("#define va_listarg va_list\t"); #endif /*TRY == 2*/ printf("/* va_arg() va_list type */\n"); #endif /*TRY == 4*/ #if defined(_WIN32) || !defined(va_copy) #if defined(__va_copy) printf("#define va_copy(to,fr) __va_copy(to,fr)\t"); printf("/* copy va_list fr -> to */\n"); #else #if TRY == 2 printf("#define va_copy(to,fr) memcpy(to,fr,sizeof(va_list))\t"); printf("/* copy va_list fr -> to */\n"); #else printf("#define va_copy(to,fr) ((to)=(fr))\t"); printf("/* copy va_list fr -> to */\n"); #endif #endif #endif printf("#undef _ast_va_list\n"); printf("#ifdef va_start\n"); printf("#define _ast_va_list va_list\n"); printf("#else\n"); #if TRY == 1 || TRY == 2 printf("#define _ast_va_list void*\t"); #else #if TRY == 3 if (sizeof(va_list) == sizeof(long)) printf("#define _ast_va_list long\t"); else if (sizeof(va_list) == sizeof(short)) printf("#define _ast_va_list short\t"); else printf("#define _ast_va_list int\t"); #else #if defined(_M_ALPHA) && defined(_VA_LIST_DEFINED) printf("#ifndef _VA_LIST_DEFINED\n"); printf("#define _VA_LIST_DEFINED\n"); printf("typedef struct { char *a0; int offset; } va_list;\n"); printf("#endif\n"); printf("#define _ast_va_list va_list\t"); #else printf("typedef struct { char fill[%d]; } _ast_va_list_s;\n", sizeof(va_list)); printf("#define _ast_va_list _ast_va_list_s\t"); #endif #endif #endif printf("/* va_list that avoids #include */\n"); printf("#endif\n"); printf("#endif\n"); return 0; } }end cat{ #ifndef _AST_STD_H # if __STD_C && _hdr_stddef # include # endif # if _sys_types # include # endif #endif #if !_typ_size_t # define _typ_size_t 1 typedef int size_t; #endif #if !_typ_ssize_t # define _typ_ssize_t 1 typedef int ssize_t; #endif #if !_typ_ptrdiff_t # define _typ_ptrdiff_t 1 typedef int ptrdiff_t; #endif }end dif #endif #endif printf("/* va_list that avoids #include */\n"); printf("#endif\n"); prisrc/lib/sfio/Sfio_t/tpopen.c000644 151361 151361 00000001777 07235635536 015753 0ustar00kpvkpv000000 000000 #include "sftest.h" #include MAIN() { Sfio_t *f; char *s, *endos, *os = "one\ntwo\nthree\n"; int n; void(* handler)_ARG_((int)); if(argc > 1) { sfmove(sfstdin,sfstdout,(Sfoff_t)(-1),-1); return 0; } if(!(f = sfpopen((Sfio_t*)0, sfprints("%s -p > %s", argv[0], tstfile(0)), "w"))) terror("Opening for write\n"); if(sfwrite(f,os,strlen(os)) != (ssize_t)strlen(os)) terror("Writing\n"); #ifdef SIGPIPE if((handler = signal(SIGPIPE,SIG_DFL)) == SIG_DFL) terror("Wrong signal handler\n"); if((handler = signal(SIGPIPE,handler)) != SIG_DFL) terror("Weird signal handling"); #endif sfclose(f); if(!(f = sfpopen((Sfio_t*)0, sfprints("%s -p < %s", argv[0], tstfile(0)), "r"))) terror("Opening for read\n"); sleep(1); endos = os + strlen(os); while(s = sfgetr(f,'\n',0)) { n = sfvalue(f); if(strncmp(s,os,n) != 0) { s[n-1] = os[n-1] = 0; terror("Input=%s, Expect=%s\n",s,os); } os += n; } if(os != endos) terror("Does not match all data, left=%s\n",os); TSTEXIT(0); } \src/lib/sfio/Sfio_t/topen.c000644 151361 151361 00000001540 07411272067 015547 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t* f; Sfio_t sf; if(sfopen(sfstdout,"abc","s") != sfstdout) terror("Bad reopening of sfstdout\n"); if(sfopen(sfstdin,"123","s") != sfstdin) terror("Bad reopening of sfstdin\n"); sfclose(sfstdin); if(!(f = sfopen(NIL(Sfio_t*),"123","s")) ) terror("Opening a stream\n"); sfclose(f); if(sfopen(f,"123","s") != NIL(Sfio_t*)) terror("can't reopen a closed stream!\n"); if(sfnew(&sf,NIL(char*),(size_t)SF_UNBOUND,0,SF_EOF|SF_READ) != &sf) terror("Did not open sf\n"); sfset(&sf,SF_STATIC,1); if(sfclose(&sf) < 0 || !(sfset(&sf,0,0)&SF_STATIC)) terror("Did not close sf\n"); /* test for exclusive opens */ unlink(tstfile(0)); if(!(f = sfopen(NIL(Sfio_t*),tstfile(0),"wx") ) ) terror("sfopen failed\n"); if((f = sfopen(f,tstfile(0),"wx") ) ) terror("sfopen should not succeed here\n"); TSTEXIT(0); } ") != NIL(Sfio_t*)) terror("can't reopen a closed stream!\n"); if(sfnew(&sf,NIL(char*),(size_t)SF_UNBOUND,0,SF_EOF|SF_READ) != &sf) terror("Did not open ssrc/lib/sfio/Sfio_t/tflags.c000644 151361 151361 00000003461 07235635535 015715 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t* f; if(!(f = sfopen(NIL(Sfio_t*),"ab","sr")) ) terror("Can't open stream\n"); if(sfeof(f) || sferror(f)) terror("Can't be eof or error yet\n"); if(sfgetc(f) != 'a') terror("Got wrong data\n"); if(sfeof(f) || sferror(f)) terror("Can't be eof or error yet2\n"); if(sfgetc(f) != 'b') terror("Got wrong data2\n"); if(sfeof(f) || sferror(f)) terror("Can't be eof or error yet3\n"); if(sfgetc(f) >= 0) terror("Got wrong data2\n"); if(!sfeof(f)) terror("Should be eof now\n"); if(sfseek(f,(Sfoff_t)(-1),2) != 1) terror("Seek error\n"); if(sfeof(f)) terror("Shouldn't be eof any more\n"); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "w+")) ) terror("Can't open stream2\n"); if(sfeof(f) || sferror(f)) terror("Can't be eof or error yet2\n"); if(sfwrite(f,"ab",2) != 2) terror("Can't write data\n"); if(sfseek(f,(Sfoff_t)0,0) != 0) terror("Can't seek back\n"); if(sfgetc(f) != 'a') terror("Got wrong data3\n"); if(sfeof(f) || sferror(f)) terror("Can't be eof or error yet4\n"); if(sfgetc(f) != 'b') terror("Got wrong data4\n"); if(sfeof(f) || sferror(f)) terror("Can't be eof or error yet5\n"); if(sfgetc(f) >= 0) terror("Got wrong data5\n"); if(!sfeof(f)) terror("Should be eof now2\n"); if(sfseek(f,(Sfoff_t)(-1),2) != 1) terror("Seek error2\n"); if(sfeof(f)) terror("Shouldn't be eof any more2\n"); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0),"w+")) ) terror("Reopening %s\n", tstfile(0)); sfwrite(f,"1234567890",10); sfseek(f,(Sfoff_t)0,0); if(sfopen(sfstdout, tstfile(1), "w") != sfstdout) terror("Opening %s\n", tstfile(1)); if(sfmove(f,sfstdout,(Sfoff_t)(-1),-1) != 10) terror("sfmove failed\n"); if(!sfeof(f)) terror("f should be eof\n"); if(sferror(sfstdout)) terror("sfstdout should not be in error\n"); TSTEXIT(0); } rror2\n"); if(sfeof(f)) terror("Shouldn't be eof any more2\n"); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0),"w+")) ) terror("Reopening %s\n", tstfile(0)); sfwrite(f,"1234567890",10); sfseek(f,(Sfoff_t)src/lib/sfio/Sfio_t/tstack.c000644 151361 151361 00000010733 07411272067 015717 0ustar00kpvkpv000000 000000 #include "sftest.h" static Sfio_t* Fclose; #if __STD_C int exceptf(Sfio_t*f, int type, Void_t* data, Sfdisc_t* disc) #else int exceptf(f, type, data, disc) Sfio_t* f; int type; Void_t* data; Sfdisc_t* disc; #endif { if(type == SF_CLOSING || type == SF_FINAL) { if(f != Fclose) return -1; if(type == SF_CLOSING && (f->mode&SF_RDWR) != f->mode) terror("Stream should be open\n"); return 0; } if((f->mode&SF_RDWR) != f->mode ) terror("Stream mode should be accessible in exceptf\n"); return 0; } #if __STD_C ssize_t readf(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t readf(f, buf, n, disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { if((f->mode&SF_RDWR) == f->mode ) terror("Stream mode should be inaccessible in readf\n"); return 0; } #if __STD_C ssize_t writef(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t writef(f, buf, n, disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { if((f->mode&SF_RDWR) == f->mode ) terror("Stream mode should be inaccessible in writef\n"); return 0; } Sfdisc_t Disc = { readf, writef, NIL(Sfseek_f), exceptf, 0 }; MAIN() { Sfio_t *f1, *f2, *f3, *f; char *s, *s1, *s2, *s3, *s4, str[1024], *ss; int n; int fd[2]; if(!(f1 = sfopen(NIL(Sfio_t*), tstfile(0),"w+")) ) terror("Opening file1\n"); if(!(f2 = sfopen(NIL(Sfio_t*), tstfile(0),"w+")) ) terror("Opening file2\n"); Fclose = f2; sfdisc(f1,&Disc); sfdisc(f2,&Disc); sfstack(f1,f2); if((n = sfgetc(f1)) >= 0 || !sfeof(f1)) terror("There should be no data n=%d\n",n); if(sfstacked(f1)) terror("There should be no stack\n"); Fclose = f1; if(sfclose(f1) < 0) terror("Can't close f1\n"); tstcleanup(); s1 = "1234567890"; s2 = "abcdefghijklmnopqrstuvwxyz"; s3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; s4 = "!@#$%^&*()_-+={}[]~`':;?/><,|"; if(!(f1 = sfopen((Sfio_t*)0,s1,"s")) || !(f2 = sfopen((Sfio_t*)0,s2,"s")) || !(f3 = sfopen((Sfio_t*)0,s3,"s"))) terror("Opening strings\n"); sfdisc(sfstdin,&Disc); sfclose(sfstdin); if(sffileno(sfstdin) != 0) terror("Bad fd for stdin\n"); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0),"w+")) ) terror("Opening file\n"); if(sfwrite(f,"0123456789",10) != 10) terror("Write file\n"); if(sfseek(f,(Sfoff_t)0,0) != 0) terror("Seek file\n"); if(sfstack(sfstdin,f) != sfstdin) terror("Stacking on stdin2\n"); if(sfopen(sfstdout,"/dev/null","w") != sfstdout) terror("Opening sfstdout\n"); if(sfmove(sfstdin,sfstdout,(Sfoff_t)SF_UNBOUND,-1) != 10 || !sfeof(sfstdin) || sferror(sfstdout)) terror("Bad sfmove\n"); tstcleanup(); if(!(f = sftmp(0))) terror("Opening temp file\n"); if(sfputr(f,s4,-1) != (ssize_t)strlen(s4)) terror("Writing s4\n"); sfseek(f,(Sfoff_t)0,0); if(sfstack(f,f3) != f) terror("Stacking s3\n"); if(sfstack(f,f2) != f) terror("Stacking s2\n"); if(sfstack(f,f1) != f) terror("Stacking s1\n"); sfsprintf(str,sizeof(str),"%s%s%s%s",s1,s2,s3,s4); if((ss = sfgetr(f,'\n',1)) ) terror("There shouldn't have been any new-line\n"); else { if(!(ss = sfgetr(f,'\n',-1)) ) terror("Reading streams\n"); ss[sfvalue(f)] = 0; } if(strcmp(ss,str) != 0) terror("Expect=%s\n",str); if(!(f1 = sfopen((Sfio_t*)0,s1,"s")) || !(f2 = sfopen((Sfio_t*)0,s2,"s")) || !(f3 = sfopen((Sfio_t*)0,s3,"s"))) terror("Opening strings2\n"); sfseek(f,(Sfoff_t)0,0); if(sfstack(f,f3) != f || sfstack(f,f2) != f || sfstack(f,f1) != f) terror("Stacking streams2\n"); if(!(s = sfreserve(f,SF_UNBOUND,0)) || s != s1) terror("Sfpeek1\n"); if(!(s = sfreserve(f,SF_UNBOUND,0)) || s != s2) terror("Sfpeek2\n"); if(!(s = sfreserve(f,SF_UNBOUND,0)) || s != s3) terror("Sfpeek3\n"); if(!(s = sfreserve(f,SF_UNBOUND,0)) || strncmp(s,s4,strlen(s4)) != 0) terror("Sfpeek4\n"); /* test to see if hidden read data still accessible */ if(pipe(fd) < 0) terror("Can't create pipe"); if(!(f1 = sfnew(0, NIL(Void_t*), (size_t)SF_UNBOUND, fd[0], SF_READ|SF_WRITE)) ) terror("Can't create stream"); if(write(fd[1],"0123",4) != 4) terror("Can't write to pipe"); if(sfgetc(f1) != '0') terror("sfgetc failed"); /* hack to create hidden reserved buffer */ f1->_file = fd[1]; if(sfwrite(f1,"4",1) != 1) terror("Can't write to stream"); sfsync(f1); f1->_file = fd[0]; close(fd[1]); /* now stack stream */ if(!(f2 = sfopen(0, "abcd\n", "s"))) terror("Can't open string stream"); sfstack(f2,f1); if(!(s = sfgetr(f2, '\n', 1)) ) terror("sfgetr failed"); if(strcmp(s, "1234abcd") != 0) terror("sfgetr got wrong data"); TSTEXIT(0); } n't write to pipe"); if(sfgetc(f1) !src/lib/sfio/Sfio_t/tscanf.c000644 151361 151361 00000010525 07235635536 015713 0ustar00kpvkpv000000 000000 #include "sftest.h" #if _hdr_values #include #endif #if _hdr_math #include #endif #if _hdr_float #include #endif #if defined(MAXDOUBLE) #define MAXD MAXDOUBLE #endif #if !defined(MAXD) && defined(DBL_MAX) #define MAXD DBL_MAX #endif #if !defined(MAXD) #define MAXD (double)(~((unsigned long)0)) #endif MAIN() { char str[8], c[4], cl[8]; int i, j, k, n; float f; double d; char* s; Void_t* vp; Sfio_t* sf; str[0] = 'x'; str[1] = 0; n = sfsscanf("123","%[a-z]%d",str,&i); if(n != 0) terror("Bad %%[ scanning1"); n = sfsscanf("123","%#[a-z]%d",str,&i); if(n != 2 || str[0] != 0 || i != 123) terror("Bad %%[ scanning2"); str[0] = str[1] = str[2] = str[3] = str[4] = str[5] = str[6] = str[7] = 'x'; c[0] = c[1] = c[2] = c[3] = 'x'; cl[0] = cl[1] = cl[2] = cl[3] = cl[4] = cl[5] = cl[6] = cl[7] = 'x'; i = -1; if(sfsscanf("123456789","%.*.*d",4,10,&i) != 1) terror("Bad %%d scanning\n"); if(i != 1234) terror("Got wrong value\n"); i = -1; if(sfsscanf("0","%i",&i) != 1 || i != 0) terror("Bad %%i scanning1\n"); i = -1; if(sfsscanf("0x","%1i%c",&i,c) != 2 || i != 0 || c[0] != 'x') terror("Bad %%i scanning2\n"); i = -1; if(sfsscanf("0x1","%i",&i) != 1 || i != 1) terror("Bad %%i scanning3\n"); i = -1; if(sfsscanf("07","%i",&i) != 1 || i != 7) terror("Bad %%i scanning4\n"); i = -1; if(sfsscanf("08","%i%i",&i,&j) != 2 || i != 0 || j != 8) terror("Bad %%i scanning5\n"); sfsscanf("1234567890","%4I*s%2I*c%4I*[0-9]",4,str,2,c,6,cl); if(strcmp(str,"123") != 0) terror("Bad s\n"); if(str[4] != 'x') terror("str overwritten\n"); if(strncmp(c,"56",2) != 0) terror("Bad c\n"); if(c[2] != 'x') terror("c overwritten\n"); if(strcmp(cl,"7890") != 0) terror("Bad class\n"); if(cl[5] != 'x') terror("cl overwritten\n"); if(sfsscanf("123 ab","%*d") != 0) terror("Bad return value\n"); if(sfsscanf("123abcA","%[0-9]%[a-z]%[0-9]",str,c,cl) != 2 || strcmp(str,"123") != 0 || strcmp(c,"abc") != 0) terror("Bad character class scanning\n"); if(sfsscanf("123 456 ","%d %d%n",&i,&j,&n) != 2) terror("Bad integer scanning\n"); if(i != 123 || j != 456 || n != 7) terror("Bad return values\n"); if(sfsscanf("1 2","%d %d%n",&i,&j,&n) != 2) terror("Bad scanning2\n"); if(i != 1 || j != 2 || n != 3) terror("Bad return values 2\n"); if(sfsscanf("1234 1","%2d %d%n",&i,&j,&n) != 2) terror("Bad scanning3\n"); if(i != 12 || j != 34 || n != 4) terror("Bad return values 3\n"); if(sfsscanf("011234 1","%3i%1d%1d%n",&i,&j,&k,&n) != 3) terror("Bad scanning4\n"); if(i != 9 || j != 2 || k != 3 || n != 5) terror("Bad return values 4\n"); if(sfsscanf("4 6","%f %lf",&f, &d) != 2) terror("Bad scanning5\n"); if(f != 4 || d != 6) terror("Bad return values f=%f d=%f\n", f, d); s = ".1234 .1234"; if(sfsscanf(s,"%f %lf",&f, &d) != 2) terror("Bad scanning6\n"); if(f <= .1233 || f >= .1235 || d <= .1233 || d >= .1235) terror("Bad return values: f=%.4f d=%.4lf\n",f,d); /* test for scanning max double value */ s = sfprints("%.14le",MAXD); if(!s || s[0] < '0' || s[0] > '9') terror("sfprints failed\n"); for(i = 0; s[i]; ++i) if(s[i] == 'e') break; if(s[i-1] > '0' && s[i-1] <= '9') s[i-1] -= 1; sfsscanf(s,"%le",&d); if(d > MAXD || d < MAXD/2) terror("sfscanf of MAXDOUBLE failed\n"); if(!(sf = sftmp(8*1024)) ) terror("Opening temp file\n"); for(k = 2; k <= 64; ++k) { sfseek(sf,(Sfoff_t)0,0); for(i = 0; i < 1000; ++i) sfprintf(sf,"%#..*d\n",k,i); sfseek(sf,(Sfoff_t)0,0); for(i = 0; i < 1000; ++i) { if(sfscanf(sf,"%i",&j) != 1) terror("Scanf failed\n"); if(i != j) terror("Wrong scanned value\n"); } } /* test %p */ s = sfprints("%p", sf); sfsscanf(s, "%p", &vp); if(vp != (Void_t*)sf) terror("Wrong pointer scan\n"); if(sfsscanf("2#1001","%i",&i) != 1 || i != 9) terror("Bad %%i scanning\n"); if(sfsscanf("2#1001","%#i%c",&i,c) != 2 || i != 2 || c[0] != '#') terror("Bad %%#i scanning\n"); n = -1; if(sfsscanf("12345","%d%n",&k,&n) != 1 || k != 12345 || n != 5) terror("Bad scanning results"); n = -1; if(sfsscanf("12345","%d %n",&k,&n) != 1 || k != 12345 || n != 5) terror("Bad scanning results"); n = -1; if(sfsscanf("12345 ","%d%n",&k,&n) != 1 || k != 12345 || n != 5) terror("Bad scanning results"); n = -1; if(sfsscanf("12345 ","%d %n",&k,&n) != 1 || k != 12345 || n != 6) terror("Bad scanning results"); TSTEXIT(0); } || i != 2 || c[0] != '#') terror("Bad %%#i scanning\n"); n = -1; if(sfsscanf("12345","%d%n",&k,&n) != 1 || k != 12345 || n != 5) terror("Bad scanning results"); n src/lib/sfio/Sfio_t/tshare.c000644 151361 151361 00000001367 07235635536 015727 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { char buf[1024], *s; Sfio_t* f; f = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND,-1,SF_WRITE|SF_STRING); sfsetbuf(sfstdout,buf,sizeof(buf)); sfsetbuf(sfstderr,buf,sizeof(buf)); sfset(sfstdout,SF_SHARE,0); sfset(sfstderr,SF_SHARE,0); if(!sfpool(sfstdout,f,SF_SHARE) || !sfpool(sfstderr,f,SF_SHARE) ) terror("Pooling\n"); if(sfputr(sfstdout,"01234",-1) != 5) terror("Writing to stderr\n"); if(sfputr(sfstderr,"56789",-1) != 5) terror("Writing to stdout\n"); if(sfputc(f,'\0') < 0) terror("Writing to string stream\n"); sfseek(f,(Sfoff_t)0,0); if(!(s = sfreserve(f,SF_UNBOUND,1)) ) terror("Peeking\n"); sfwrite(f,s,0); if(strcmp(s,"0123456789") != 0) terror("Data is wrong\n"); TSTEXIT(0); } sfset(sfstderr,SF_SHARE,0); if(!sfpool(sfstdout,f,SF_SHARE) || !sfpool(sfstderr,f,SF_SHARE) ) terror("Pooling\n"); if(sfputr(sfstdout,"01234",-1) != 5) terror("Writing to stderr\n"); if(sfputr(sfstderr,"56789",-1) != 5) terror("Writing to stdout\n"); src/lib/sfio/Sfio_t/talarm.c000644 151361 151361 00000002531 07235635535 015712 0ustar00kpvkpv000000 000000 #include "sftest.h" #include #define HANDLER "Handler" char Buf[16]; int Except; #if __STD_C void alrmhandler(int sig) #else void alrmhandler(sig) int sig; #endif { strcpy(Buf,HANDLER); signal(sig,alrmhandler); } #if __STD_C exceptf(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) #else exceptf(f, type, data, disc) Sfio_t* f; int type; Void_t* data; Sfdisc_t* disc; #endif { if(type == SF_ATEXIT) return 0; if(type != SF_READ) terror("Bad Io type\n"); if(errno != EINTR) terror("Bad exception\n"); Except = 1; return -1; } Sfdisc_t Disc = {NIL(Sfread_f), NIL(Sfwrite_f), NIL(Sfseek_f), exceptf}; MAIN() { int fd[2]; if(pipe(fd) < 0) terror("Can't make pipe\n"); if(sfnew(sfstdin,NIL(Void_t*),(size_t)SF_UNBOUND,fd[0],SF_READ) != sfstdin) terror("Can't renew stdin\n"); sfdisc(sfstdin,&Disc); sfset(sfstdin,SF_SHARE,1); signal(SIGALRM,alrmhandler); alarm(2); if(sfreserve(sfstdin,1,1)) terror("Unexpected data\n"); if(strcmp(Buf,HANDLER) != 0) terror("Handler wasn't called\n"); if(!Except) terror("Exception handler wasn't called1\n"); Buf[0] = 0; Except = 0; signal(SIGALRM,alrmhandler); alarm(2); if(sfgetr(sfstdin,'\n',0)) terror("Unexpected data2\n"); if(strcmp(Buf,HANDLER) != 0) terror("Handler wasn't called2\n"); if(!Except) terror("Exception handler wasn't called2\n"); TSTEXIT(0); } SHARE,1); signal(SIGALRM,alrmhandler); alarm(2); if(sfreserve(sfstdin,1,1)) terror("Unexpected data\n"); if(strcmp(Buf,HANDLER) != 0) terror("Handler wasn't csrc/lib/sfio/Sfio_t/tnoseek.c000644 151361 151361 00000002176 07235635536 016110 0ustar00kpvkpv000000 000000 #include "sftest.h" char* buffer; size_t size; size_t count; #if __STD_C Sfoff_t discseek(Sfio_t* f, Sfoff_t offset, int type, Sfdisc_t* disc) #else Sfoff_t discseek(f,offset,type,disc) Sfio_t* f; Sfoff_t offset; int type; Sfdisc_t* disc; #endif { return 0; } #if __STD_C ssize_t discwrite(Sfio_t* f, const Void_t* s, size_t n, Sfdisc_t* disc) #else ssize_t discwrite(f,s,n,disc) Sfio_t* f; Void_t* s; size_t n; Sfdisc_t* disc; #endif { buffer = (char*)s; size = n; count += 1; return n; } Sfdisc_t seekable = { (Sfread_f)0, discwrite, discseek, (Sfexcept_f)0 }; MAIN() { char buf[1024]; sfsetbuf(sfstdout,buf,sizeof(buf)); sfset(sfstdout,SF_LINE,0); if(sfdisc(sfstdout,&seekable) != &seekable) terror("Can't set discipline\n"); if(sfseek(sfstdout,(Sfoff_t)0,0) < 0) terror("Sfstdout should be seekable\n"); if(sfwrite(sfstdout,"123\n",4) != 4) terror("Can't write\n"); if(sfwrite(sfstdout,"123\n",4) != 4) terror("Can't write\n"); if(sfdisc(sfstdout,NIL(Sfdisc_t*)) != &seekable) terror("Can't pop discipline\n"); if(buffer != buf || size != 8 || count != 1) terror("Wrong calls to write\n"); TSTEXIT(0); } f)); sfset(sfstdout,SF_LINE,0); if(sfdisc(sfstdout,&seekable) != &seekable) terror("Can't set discipline\n"); if(sfseek(sfstdout,(Sfoff_t)0,0) < 0) terror("Sfstdout should be seekable\n"); if(sfwrite(sfstdout,"123\n",4) != 4) terror("Can't write\n"); if(sfwrite(sfstdout,"123\n",4) != 4) terror("Can't write\n"); if(sfdisc(sfstdout,NIL(Sfdisc_t*)) != &seekable) terror(src/lib/sfio/Sfio_t/tmpread.c000644 151361 151361 00000002100 07327057605 016054 0ustar00kpvkpv000000 000000 #include "sftest.h" /* This test checks to see if sfread() will always fill the buffer ** from a piped-stream correctly even if the other end of the pipe ** is writing odd amounts of bytes. */ #define RBUF 16 #define ITER 1024 main() { Sfio_t *fr; int p[2]; char wbuf[1023], rbuf[RBUF*1023], *s; int i, r, n; if(pipe(p) < 0 ) terror("Making pipe for communication"); if(!(fr = sfnew(0, 0, (size_t)SF_UNBOUND, p[0], SF_READ)) ) terror("Making read stream"); for(i = 0; i < sizeof(wbuf); ++i) wbuf[i] = (i%10) + '0'; switch(fork()) { case -1 : terror("fork() failed"); case 0 : for(i = 0; i < RBUF*ITER; ++i) if(write(p[1], wbuf, sizeof(wbuf)) != sizeof(wbuf)) terror("Write to pipe failed i=%d", i); break; default: for(i = 0; i < ITER; ++i) { if(sfread(fr, rbuf, sizeof(rbuf)) != sizeof(rbuf)) terror("Read from pipe failed i=%d", i); for(r = 0, s = rbuf; r < RBUF; r += 1, s += n) for(n = 0; n < sizeof(wbuf); ++n) if(s[n] != (n%10)+'0') terror("Bad data i=%d n=%d", i, n); } break; } TSTEXIT(0); } or("fork() failed"); case 0 : for(i = 0; i < RBUF*ITER; ++i) if(write(p[1], wbuf, sizeof(wbuf)) != sizeof(wbuf)) terror("Write to pipe failed i=%d", i); break; default: for(i = 0; i < ITER; ++i) { if(sfread(fr, rbuf, sizeof(rbuf)) != sizeof(rbuf)) terror("Read from pipe failed i=%d", i); for(r = 0, s = rbuf; r < RBUF; r += 1, s += n) for(n = 0; n < sizeof(wbuf); ++n) if(s[n] != (n%10)+'0') terrorsrc/lib/sfio/Sfio_t/tappend.c000644 151361 151361 00000003356 07235635535 016073 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t *f1, *f2; char* s; Sfoff_t p; char buf[1024]; int r, w; if(!(f1 = sfopen(NIL(Sfio_t*), tstfile(0), "w")) ) terror("Can't open f1\n"); if(!(f1 = sfopen(f1, tstfile(0), "a+")) ) terror("Can't open f1\n"); if(!(f2 = sfopen(NIL(Sfio_t*), tstfile(0), "a+")) ) terror("Can't open f2\n"); if(sfwrite(f1,"012345678\n",10) != 10 || sfsync(f1) < 0) terror("Writing to f1\n"); if((p = sftell(f1)) != 10) terror("Bad sftell1 %ld\n",p); if(sfwrite(f2,"abcdefghi\n",10) != 10 || sfsync(f2) < 0) terror("Writing to f2\n"); if((p = sftell(f2)) != 20) terror("Bad sftell2\n"); if((p = sfseek(f1,(Sfoff_t)0,0)) != 0) terror("Bad seek\n"); if(!(s = sfgetr(f1,'\n',1)) ) terror("Bad getr1\n"); if(strcmp(s,"012345678") != 0) terror("Bad input1\n"); if((p = sftell(f1)) != 10) terror("Bad sftell3\n"); if(sfwrite(f1,"012345678\n",10) != 10 || sfsync(f1) < 0) terror("Writing to f1\n"); if((p = sftell(f1)) != 30) terror("Bad sftell4\n"); if((p = sfseek(f2,(Sfoff_t)10,0)) != 10) terror("Bad seek\n"); if(!(s = sfgetr(f2,'\n',1)) ) terror("Bad getr2\n"); if(strcmp(s,"abcdefghi") != 0) terror("Bad input2\n"); if(!(s = sfgetr(f2,'\n',1)) ) terror("Bad getr3\n"); if(strcmp(s,"012345678") != 0) terror("Bad input3\n"); if(!(f1 = sfopen(f1, tstfile(0), "w")) ) terror("Can't open file to write\n"); for(r = 0; r < 1024; ++r) buf[r] = 'a'; if((w = sfwrite(f1,buf,1024)) != 1024) terror("writing w=%d\n", w); if(!(f1 = sfopen(f1, tstfile(0), "a")) ) terror("Can't open file to append\n"); sfseek(f1,(Sfoff_t)0,0); if((w = sfwrite(f1,buf,64)) != 64) terror("writing w=%d\n", w); if((r = (int)sftell(f1)) != (1024+64) ) terror("seek position wrong s=%d\n", r); TSTEXIT(0); } 5678") != 0) terror("Bad input3\n"); if(!(f1 = sfopen(f1, tstfile(0), "w")) ) terror("Can't open file to write\n"); for(r = 0; r < 1024; ++r) buf[r] = 'a'; if((w = sfwrite(f1,buf,1024)) != 1024) terror("writing w=%d\n", w); if(!(f1 = sfopen(f1, tstfile(0), "a")src/lib/sfio/Sfio_t/tungetc.c000644 151361 151361 00000003321 07235635536 016102 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t *f; char *str, *alpha, *s; char buf[128]; int n; str = "0123456789"; alpha = "abcdefghijklmnop"; if(!(f = sfopen((Sfio_t*)0,alpha,"s"))) terror("Opening stream\n"); for(n = 9; n >= 0; --n) if(sfungetc(f,n+'0') != n+'0') terror("Ungetc\n"); if(!(s = sfreserve(f,-1,0)) || sfvalue(f) != 10) terror("Peek stream1\n"); if(strncmp(s,str,10) != 0) terror("Bad data1\n"); if(!(s = sfreserve(f,-1,0)) || sfvalue(f) != (ssize_t)strlen(alpha)) terror("Peek stream2\n"); if(strncmp(s,alpha,strlen(alpha)) != 0) terror("Bad data2\n"); sfseek(f,(Sfoff_t)0,0); for(n = 9; n >= 0; --n) if(sfungetc(f,n+'0') != n+'0') terror("Ungetc2\n"); if(sfgetc(f) != '0') terror("Sfgetc\n"); sfseek(f,(Sfoff_t)0,0); if(!(s = sfreserve(f,-1,0)) || sfvalue(f) != (ssize_t)strlen(alpha)) terror("Peek stream3\n"); if(strncmp(s,alpha,strlen(alpha)) != 0) terror("Bad data2\n"); sfseek(f,(Sfoff_t)0,0); if(sfungetc(f,'0') != '0') terror("Ungetc3\n"); strcpy(buf,"0123456789\n"); if(!(f = sfopen(f,buf,"s+")) ) terror("Reopening string\n"); if(sfungetc(f,'\n') != '\n') terror("Can't unget new-line2\n"); if(sfungetc(f,'d') != 'd') terror("Can't unget d\n"); if(sfungetc(f,'c') != 'c') terror("Can't unget c\n"); if(sfungetc(f,'\n') != '\n') terror("Can't unget new-line\n"); if(sfungetc(f,'b') != 'b') terror("Can't unget b\n"); if(sfungetc(f,'a') != 'a') terror("Can't unget a\n"); if(!(s = sfgetr(f,'\n',1)) || strcmp(s,"ab") != 0) terror("Did not get ab\n"); if(!(s = sfgetr(f,'\n',1)) || strcmp(s,"cd") != 0) terror("Did not get cd\n"); if(!(s = sfgetr(f,'\n',1)) || strcmp(s,"0123456789") != 0) terror("Did not get 0123456789\n"); TSTEXIT(0); } sfungetc(f,'c') != 'c') terror("Can't unget c\n"); if(sfungetc(f,'\n') != '\n') terror("Can't unget new-line\n"); if(sfungetc(f,'b') != 'b') terror("Can't unget b\n"); if(sfungetc(f,'a') != 'a') terror("Can't unget a\n"); if(!(s = sfgetr(f,'\n',1)) || strcmp(s,"ab") != 0) terror("Did notsrc/lib/sfio/Sfio_t/texcept.c000644 151361 151361 00000006031 07411272066 016075 0ustar00kpvkpv000000 000000 #include "sftest.h" static int Type; #if __STD_C static int except(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) #else static int except(f, type, data, disc) Sfio_t* f; int type; Void_t* data; Sfdisc_t* disc; #endif { switch(type) { case SF_WRITE : return 0; case SF_CLOSING: if(Type == SF_CLOSING) return 0; case SF_SYNC: if(Type == SF_CLOSING) return 0; } Type = type; return -1; } #if __STD_C static int except2(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) #else static int except2(f, type, data, disc) Sfio_t* f; int type; Void_t* data; Sfdisc_t* disc; #endif { return 0; } #if __STD_C static int except3(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) #else static int except3(f, type, data, disc) Sfio_t* f; int type; Void_t* data; Sfdisc_t* disc; #endif { if(type == SF_LOCKED) { Type = type; return -1; } return 0; } #if __STD_C static ssize_t readfunc(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else static ssize_t readfunc(f, buf, n, disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { if(sfgetc(f) >= 0) terror("Can't access stream here!"); return 0; } static Sfdisc_t Disc, Disc2; MAIN() { Sfio_t* f; char buf[1024]; char rbuf[4*1024]; off_t o; int i; if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "w")) ) terror("Can't open file\n"); sfset(f,SF_IOCHECK,1); Disc.exceptf = except; if(!sfdisc(f,&Disc) ) terror("Pushing discipline failed\n"); sfdisc(f,&Disc); if(Type != SF_DPUSH) terror("Did not get push event\n"); sfdisc(f,NIL(Sfdisc_t*)); if(Type != SF_DPOP) terror("Did not get pop event\n"); sfwrite(f,"123",3); sfsync(f); if(Type != SF_SYNC) terror("Did not get sync event\n"); sfwrite(f,"123",3); sfpurge(f); if(Type != SF_PURGE) terror("Did not get purge event\n"); sfclose(f); if(Type != SF_CLOSING) terror("Did not get close event\n"); sfclose(f); if(Type != SF_FINAL) terror("Did not get final event\n"); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "r")) ) terror("Can't open file\n"); Disc2.readf = readfunc; Disc2.exceptf = except3; sfdisc(f,&Disc2); if(sfgetc(f) >= 0) terror("There should be no data here\n"); if(Type != SF_LOCKED) terror("Did not get lock event\n"); /* test to see if sfclose() preserves seek location */ if(!(f = sftmp(0)) ) terror("Can't create temp file\n"); sfsetbuf(f,buf,sizeof(buf)); for(i = 0; i < sizeof(rbuf); ++i) rbuf[i] = i; sfwrite(f,rbuf,sizeof(rbuf)); sfset(f,SF_WRITE,0); Disc.exceptf = except2; sfdisc(f,&Disc); sfseek(f,(Sfoff_t)0,0); if(sfread(f,rbuf,4) != 4) terror("reading 4 bytes\n"); for(i = 0; i < 4; ++i) if(rbuf[i] != i) terror("wrong 4 bytes\n"); sfsync(f); if((o = lseek(sffileno(f), (off_t)0, SEEK_CUR)) != 4) terror("Wrong seek location %lld\n", (Sfoff_t)o); if((i = dup(sffileno(f))) < 0) terror("Can't dup file descriptor\n"); if((o = lseek(i, (off_t)0, SEEK_CUR)) != 4) terror("Wrong seek location %lld\n", (Sfoff_t)o); sfclose(f); if((o = lseek(i, (off_t)0, SEEK_CUR)) != 4) terror("Wrong seek location %lld\n", (Sfoff_t)o); TSTEXIT(0); } reading 4 bytes\n"); for(i = 0; i < 4; ++i) if(rbuf[i] != i) terror("wrong 4 bytes\n"); sfsync(f); if((o = lseek(sffileno(f), (off_t)0, SEEK_CUR)) != 4) terror("Wrong seek location %lld\n", (Sfoff_t)o); if((i = dup(sffileno(f))) < 0) terror("Can't dup file descriptor\n"); if((o = lseek(i, (off_t)0, SEEK_CUR)) != 4) terror("Wrong seek location %lld\n", (Sfoff_t)o); sfclose(f); if((o = lseek(i, (off_t)0, SEEK_CUR)) != 4) terror("Wrong seek location %lld\n", (Sfosrc/lib/sfio/Sfio_t/terror.h000644 151361 151361 0000000000007477666274 023304 1src/lib/sfio/Stdio_t/terror.hustar00kpvkpv000000 000000 src/lib/sfio/Sfio_t/terrno.c000644 151361 151361 00000003524 07411272066 015736 0ustar00kpvkpv000000 000000 #include "sftest.h" /* errnos tested for xopen-compliance */ MAIN() { Sfio_t* fw; Sfio_t* fr; int fds[2]; int lseek_errno; int rv; if(!(fw = sfopen(NIL(Sfio_t*), tstfile(0), "w")) ) terror("Can't create temp file %s to write", tstfile(0)); if(!(fr = sfopen(NIL(Sfio_t*), tstfile(0), "r")) ) terror("Can't open temp file %s to read", tstfile(0)); sfseek(fr, (Sfoff_t)0, SEEK_END); if(sfgetc(fr) >= 0 || !sfeof(fr)) terror("Should have seen eof"); errno = 0; if((rv = sfwrite(fr, "a", 1)) == 1) terror("sfwrite returns %d, expecting 1", rv); if(errno != EBADF) twarn("Wrong errno %d after sfwrite(%d), expecting %d",errno,rv,EBADF); /* on some system (eg, apple), lseek does not set errno for this case */ errno = 0; lseek(sffileno(fw), (off_t)(-2), SEEK_SET); lseek_errno = errno; lseek(sffileno(fw), (off_t)0, SEEK_SET); errno = 0; if(sfseek(fw, (Sfoff_t)(-2), SEEK_SET) != (Sfoff_t)(-1) ) terror("sfseek should have failed"); if(errno != lseek_errno) twarn("Wrong errno %d after sfseek, expecting %d", errno, lseek_errno); errno = 0; if(sfseek(fw, (Sfoff_t)0, SEEK_SET|SEEK_CUR|SEEK_END) >= 0) terror("sfseek should not have succeeded"); if(errno != EINVAL) twarn("Wrong errno %d after sfseek, expecting %d", errno, EINVAL); if(pipe(fds) < 0) terror("Can't create pipes"); if(!(fw = sfnew(fw, NIL(Void_t*), (size_t)SF_UNBOUND, fds[1], SF_WRITE)) ) terror("Can't create stream for pipe"); errno = 0; if(sfseek(fw, (Sfoff_t)0, SEEK_SET) >= 0) terror("sfseek should have failed on a pipe"); if(errno != ESPIPE) twarn("Wrong errno %d after sfseek, expecting %d", ESPIPE); close(sffileno(fw)); errno = 0; if(sfseek(fw, (Sfoff_t)0, SEEK_END) >= 0) terror("sfseek should have failed on a closed file descriptor"); if(errno != EBADF) twarn("Wrong errno %d after sfseek, expecting %d", EBADF); TSTEXIT(0); } size_t)SF_UNBOUND, fds[1], SF_WRITE)) ) terror("Can't create stream for pipe"); errno = 0; if(sfseek(fw, (Sfoff_t)0, SEEK_SET) >= 0) terror("sfseek should have failesrc/lib/sfio/Sfio_t/twrrd.c000644 151361 151361 00000001205 07327060024 015554 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { int i; char wbuf[1023]; char rbuf[1023]; Sfio_t *fp; for(i = 0; i < sizeof(wbuf); ++i) wbuf[i] = (i%26)+'a'; wbuf[sizeof(wbuf)-1] = '\0'; if(!(fp = sftmp(0))) terror("Opening temp file\n"); for(i = 0; i < 256; ++i) if(sfwrite(fp,wbuf,sizeof(wbuf)) != sizeof(wbuf)) terror("Writing\n"); sfseek(fp,(Sfoff_t)0,0); sfset(fp,SF_WRITE,0); sfsetbuf(fp,NIL(char*),0); sfsetbuf(fp,NIL(char*),(size_t)SF_UNBOUND); for(i = 0; i < 256; ++i) { if(sfread(fp,rbuf,sizeof(rbuf)) != sizeof(rbuf)) terror("Reading\n"); if(strcmp(rbuf,wbuf) != 0) terror("Unmatched record\n"); } TSTEXIT(0); } = (i%26)+'a'; wbuf[sizeof(wbuf)-1] = '\0'; if(!(fp = sftmp(0))) terror("Opening temp file\n"); for(i = 0; i < 256; ++i) if(sfwrite(fp,wbuf,sizeof(wbuf)) != sizeof(wbuf)) terror("Writing\n"); sfseek(fp,(Sfoff_t)0,0); sfset(fp,SF_WRITE,0); sfsetbuf(fp,NIL(char*),0); sfsetbuf(fp,NIL(char*),(size_t)SF_UNBOUND); for(i = 0; i < 256; ++i) { if(sfread(fp,rbuf,sizesrc/lib/sfio/Sfio_t/tputgetm.c000644 151361 151361 00000000650 07433034314 016267 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { unsigned int i, r; Sfio_t *fp; if(!(fp = sftmp(8))) terror("Can't open temp file\n"); for(i = 10000; i <= 100000; i += 9) if(sfputm(fp, (Sfulong_t)i, (Sfulong_t)100000) < 0) terror("Writing %u\n",i); sfseek(fp,(Sfoff_t)0,0); for(i = 10000; i <= 100000; i += 9) if((r = (unsigned int)sfgetm(fp,(Sfulong_t)100000)) != i) terror("Input=%u, Expect=%u\n",r,i); TSTEXIT(0); } JAV=>:,`:,`@src/lib/sfio/Sfio_t/tputgetl.c000644 151361 151361 00000000553 07235635536 016305 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { int i, r; Sfio_t *fp; if(!(fp = sftmp(8))) terror("Can't open temp file\n"); for(i = -5448; i <= 5448; i += 101) if(sfputl(fp,(long)i) < 0) terror("Writing %d\n",i); sfseek(fp,(Sfoff_t)0,0); for(i = -5448; i <= 5448; i += 101) if((r = (int)sfgetl(fp)) != i) terror("Input=%d, Expect=%d\n",r,i); TSTEXIT(0); } = i) terror("Input=%u, Expect=%u\n",r,i); TSTEXI JAV=>:,`:,`@src/lib/sfio/Sfio_t/tputgetd.c000644 151361 151361 00000001303 07437047134 016262 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfdouble_t f, v; int i, flag; Sfio_t *fp; if(!(fp = sfopen(NIL(Sfio_t*), tstfile(0), "w+")) ) terror("Can't open temp file\n"); #define BEGV (Sfdouble_t)(1e-10) #define ENDV (Sfdouble_t)(1e-10 + 1) #define INCR (Sfdouble_t)(1e-3) for(f = BEGV; f < ENDV; f += INCR) if(sfputd(fp,f) < 0) terror("Writing %.12Lf\n",f); sfseek(fp,(Sfoff_t)0,0); for(flag = 0, f = BEGV, i = 0; f < ENDV; ++i, f += INCR) { if((v = sfgetd(fp)) == f) continue; if(v <= (f - 1e-10) || v >= (f + 1e-10) ) terror("Element=%d Input=%.12Lf, Expect=%.12Lf\n",i,v,f); else if(!flag) { twarn("Element=%d Input=%.12Lf, Expect=%.12Lf\n",i,v,f); flag = 1; } } TSTEXIT(0); } 10) #define ENDV (Sfdouble_t)(1e-10 + 1) #define INCR (Sfdouble_t)(1e-3) for(f = BEGV; f < ENDV; f += INCR) if(sfputd(fp,f) < 0) terror("Writing %.12Lf\n",f); sfseek(fp,(Sfoff_t)0,0); for(flag = 0, f = BEGV, i = 0; f < ENDV; ++i, f += INCR) { if((v = sfgetd(fp)) == f) continue; if(v <= (f - 1e-10) ||src/lib/sfio/Sfio_t/tputgetc.c000644 151361 151361 00000000560 07235635536 016272 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t *f; int i, c; if(!(f = sftmp(8))) terror("Can't open temp file\n"); for(i = 0; i < 10000; ++i) if(sfputc(f,(i%26)+'a') < 0) terror("Writing %c\n",(i%26)+'a'); sfseek(f,(Sfoff_t)0,0); for(i = 0; i < 10000; ++i) if((c = sfgetc(f)) != ((i%26)+'a')) terror("Input=%#o, Expect=%c\n",c,(i%26)+'a'); TSTEXIT(0); } k(fp,(Sfoff_t)0,0); for(flag = 0, f = BEGV, i = JAV=>:,`:,`@src/lib/sfio/Sfio_t/tputgetu.c000644 151361 151361 00000000567 07235635536 016323 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { unsigned int i, r; Sfio_t *fp; if(!(fp = sftmp(8))) terror("Can't open temp file\n"); for(i = 10000; i <= 100000; i += 9) if(sfputu(fp,i) < 0) terror("Writing %u\n",i); sfseek(fp,(Sfoff_t)0,0); for(i = 10000; i <= 100000; i += 9) if((r = (unsigned int)sfgetu(fp)) != i) terror("Input=%u, Expect=%u\n",r,i); TSTEXIT(0); } foff_t)0,0); for(flag = 0, f = BEGV, i = JAV=>:,`:,`@src/lib/sfio/Sfio_t/tputgetr.c000644 151361 151361 00000001410 07235635536 016304 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { char buf[100]; Sfio_t *fp; int i; char *s; if(!(fp = sftmp(8))) terror("Can't open temp file\n"); sfset(fp,SF_LINE,1); for(i = 0; i < 1000; ++i) { sfsprintf(buf,sizeof(buf),"Number: %d",i); if(sfputr(fp,buf,'\n') <= 0) terror("Writing %s\n",buf); } sfseek(fp,(Sfoff_t)0,0); for(i = 0; i < 1000; ++i) { sfsprintf(buf,sizeof(buf),"Number: %d",i); if(!(s = sfgetr(fp,'\n',1))) terror("Reading %s\n",buf); if(strcmp(s,buf) != 0) terror("Input=%s, Expect=%s\n",s,buf); } sfseek(fp,(Sfoff_t)0,0); s = sfgetr(fp,'\0',1); if(s) terror("Expecting a null string\n"); s = sfgetr(fp,'\0',-1); if(!s) terror("Expecting a non-null string\n"); if(sfvalue(fp) != sfsize(fp)) terror("Wrong size\n"); TSTEXIT(0); } terror("Writing %s\n",buf); } sfseek(fp,(Sfoff_t)0,0); for(i = 0; i < 1000; ++i) { sfsprintf(buf,sizeof(buf),"Number: %d",i); if(!(s = sfgetr(fp,'\n',1))) terror("Reading %s\n",buf); if(strcmp(s,buf) != 0) terror("Input=%s, Expectsrc/lib/sfio/Sfio_t/tmprdwr.c000644 151361 151361 00000006103 07411272066 016120 0ustar00kpvkpv000000 000000 #include "sftest.h" #define ITER 10 #define CNT 2000 typedef struct _mydisc_s { Sfdisc_t disc; int size; /* remaining size of readable data */ int send; /* channel to send size of a read */ int recv; /* channel to read amount of data */ } Mydisc_t; #if __STD_C ssize_t discread(Sfio_t* f, void* buf, size_t n, Sfdisc_t* disc) #else ssize_t discread(f, buf, n, disc) Sfio_t* f; void* buf; size_t n; Sfdisc_t* disc; #endif { Mydisc_t *dc = (Mydisc_t*)disc; int r; if(dc->size <= 0) { if((r = read(dc->recv, &dc->size, sizeof(int))) != sizeof(int) ) return 0; if(dc->size == 0) return 0; } if(n > dc->size) n = dc->size; if((r = read(sffileno(f), buf, n)) <= 0) terror("Bad reading of data from file r=%d n=%d", r, n); /**/TSTDEBUG(("Reader just read %d bytes", r)); dc->size -= r; if((n = write(dc->send, &r, sizeof(int))) != sizeof(int)) terror("Sending read size"); /**/TSTDEBUG(("Reader just told sender of a %d byte read",r)); return r; } #if __STD_C void writeprocess(int send, int recv, Sfio_t* f) #else void writeprocess(send, recv, f) int send; int recv; Sfio_t* f; #endif { char buf[11*CNT], *bp; int i, s, size, rv; for(s = 0, bp = buf; s < CNT; ++s) { for(i = 0; i < 10; ++i) *bp++ = '0' + i%10; *bp++ = '\0'; } for(i = 0; i < ITER; i++) { /* write out a buffer of data */ if((size = write(sffileno(f), buf, sizeof(buf))) != sizeof(buf)) terror("Bad write to file"); if(write(send, &size, sizeof(int)) != sizeof(int)) terror("Sending output size %d", size); /**/TSTDEBUG(("Writer just wrote %d bytes", size)); /* now wait until readprocess exhausts the data */ while(size > 0) { if((rv = read(recv, &s, sizeof(int))) != sizeof(int)) terror("Reading amount of consumed data, rv=%d", rv); /**/TSTDEBUG(("Writer was told of a %d byte read",s)); if(s <= 0 || s > size) terror("Reader just told a bad read size %d", s); size -= s; } } size = 0; if(write(send, &size, sizeof(int)) != sizeof(int)) terror("Sending eof signal"); } main() { Sfio_t *fw, *fr; Mydisc_t disc; int parent[2], child[2]; char buf[11]; int i, s, rv; if(pipe(parent) < 0 || pipe(child) < 0) terror("Making pipes for communications"); if(!(fw = sfopen(NIL(Sfio_t*), tstfile(0), "w")) ) terror("Creating temp file"); if(!(fr = sfopen(NIL(Sfio_t*), tstfile(0), "r")) ) terror("Opening temp file to read"); disc.disc.readf = discread; disc.disc.writef = 0; disc.disc.seekf = 0; disc.disc.exceptf = 0; disc.send = parent[1]; disc.recv = child[0]; disc.size = 0; sfdisc(fr, &disc.disc); switch(fork()) { case -1 : terror("fork() failed"); case 0 : close(child[0]); close(parent[1]); writeprocess(child[1], parent[0], fw); break; default: close(child[1]); close(parent[0]); for(i = 0, s = 0; i <= ITER*CNT; ++i) { if((rv = sfread(fr, buf, 11)) != 11) break; s += rv; if(strcmp(buf, "0123456789") != 0) terror("Bad data"); for(rv = 0; rv < 11; ++rv) buf[rv] = 1; } if(s != ITER*CNT*11) terror("Only read %d, expected %d", s, ITER*CNT*11); break; } TSTEXIT(0); } terror("fork() failed"); case 0 : close(child[0]); close(parent[1]); writeprocess(child[1], parent[0], fw); break; default: close(child[1]); close(parent[0]); for(i = 0, s = 0; i <= ITER*CNT; ++i) { if((rv = sfread(fr, buf, 11)) != 11) break; s += rv; if(strcmp(buf, "0123456789") != 0) terror("Bad data"); for(rv = 0; rv < 11; ++rv) buf[rv] = 1; } if(s != ITER*CNT*11) terror("Only resrc/lib/sfio/Sfio_t/tstatus.c000644 151361 151361 00000001174 07235635536 016144 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t* ip; Sfio_t* op; int n; if(!(ip = sfopen((Sfio_t*)0, "/dev/null", "r"))) terror("/dev/null read open\n"); if(!(op = sfopen((Sfio_t*)0, tstfile(0), "w"))) terror("Write open\n"); n = (int)sfmove(ip, op, SF_UNBOUND, -1); if(n) terror("move count %d != 0\n", n); if(!sfeof(ip)) terror("sfeof(ip) expected\n"); if(sfeof(op)) terror("sfeof(op) not expected\n"); if(sferror(ip)) terror("sferror(ip) not expected\n"); if(sferror(op)) terror("sferror(op) not expected\n"); if(sfclose(ip)) terror("sfclose(ip)\n"); if(sfclose(op)) terror("sfclose(op)\n"); TSTEXIT(0); } "/dev/null read open\n"); if(!(op = sfopen((Sfio_t*)0, tstfile(0), "w"))) terror("Write open\n"); n = (int)sfmove(ip, op, SF_UNBOUND, -1); if(n) terror("move count %d != 0\n", n); if(!sfeof(ip)) terror("sfeof(ip) expected\n"); if(sfeof(op)) terror("sfeof(op) not expected\n"); if(sferror(ip)) terror("sferror(ip) not expected\n"); if(sferror(op)) terror("sferror(op)src/lib/sfio/Sfio_t/trcrv.c000644 151361 151361 00000002000 07235635536 015562 0ustar00kpvkpv000000 000000 #include "sftest.h" #if __STD_C ssize_t myread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t myread(f, buf, n, disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { return sfrd(f,buf,n,disc); } Sfdisc_t Disc = {myread, NIL(Sfwrite_f), NIL(Sfseek_f), NIL(Sfexcept_f)}; MAIN() { int fd[2]; if(pipe(fd) < 0) terror("Can't open pipe\n"); if(sfnew(sfstdin,NIL(Void_t*),(size_t)SF_UNBOUND,fd[0],SF_READ) != sfstdin) terror("Can't initialize sfstdin\n"); sfset(sfstdin,SF_SHARE,1); sfdisc(sfstdin,&Disc); if(sfnew(sfstdout,NIL(Void_t*),0,fd[1],SF_WRITE) != sfstdout) terror("Can't initialize sfstdout\n"); sfputr(sfstdout,"111\n222\n333\n",-1); sfsync(sfstdout); if(strcmp(sfgetr(sfstdin,'\n',1),"111") != 0) terror("sfgetr failed1\n"); if(sfstdin->endb > sfstdin->next) terror("sfgetr reads too much1\n"); if(strcmp(sfgetr(sfstdin,'\n',1),"222") != 0) terror("sfgetr failed2\n"); if(sfstdin->endb > sfstdin->next) terror("sfgetr reads too much2\n"); TSTEXIT(0); } src/lib/sfio/Sfio_t/tsetfd.c000644 151361 151361 00000001405 07235635536 015723 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t *f; int fd; off_t sk; if(!(f = sfopen((Sfio_t*)0,tstfile(0),"w+"))) terror("Opening file\n"); fd = sffileno(f); if(sfsetfd(f,-1) != -1 || sffileno(f) != -1) terror("setfd1\n"); if(sfputc(f,'a') >= 0) terror("sfputc\n"); if(sfsetfd(f,fd) != fd) terror("setfd2\n"); if(sfwrite(f,"123456789\n",10) != 10) terror("sfwrite\n"); sfseek(f,(Sfoff_t)0,0); if(sfgetc(f) != '1') terror("sfgetc1\n"); if(sfsetfd(f,-1) != -1 || sffileno(f) != -1) terror("setfd2\n"); if((sk = lseek(fd, (off_t)0, 1)) != (off_t)1) terror("Bad seek address %lld\n", (Sfoff_t)sk ); if(sfgetc(f) >= 0) terror("sfgetc2\n"); if(sfsetfd(f,fd) != fd) terror("setfd2\n"); if(sfgetc(f) != '2') terror("sfgetc3\n"); TSTEXIT(0); } fputc\n"); if(sfsetfd(f,fd) != fd) terror("setfd2\n"); if(sfwrite(f,"123456789\n",10) != 10) terror("sfwrite\n"); sfseek(f,(Sfoff_t)0,0); if(sfgetc(f) != '1') terror("sfgetc1\n"); if(sfsetfd(f,-1) != -1 || sffileno(f) != -1) terror("ssrc/lib/sfio/Sfio_t/tlongdouble.c000644 151361 151361 00000001060 07235635535 016744 0ustar00kpvkpv000000 000000 #include "sftest.h" #if _typ_long_double #include #endif MAIN() { #if _typ_long_double long double ldval, ldmax; char *s, *str; ldmax = LDBL_MAX; if(!(s = sfprints("%Le",ldmax)) ) terror("sfprints failed1\n"); if(!(str = malloc(strlen(s)+1)) ) terror("Malloc failed\n"); strcpy(str,s); if(sfsscanf(str,"%Le",&ldval) != 1) terror("sfsscanf failed\n"); if(!(s = sfprints("%Le",ldval)) ) terror("sfprints failed2\n"); if(strcmp(s,str) != 0) terror("Bad conversion, expecting %s and getting %s\n",str,s); #endif TSTEXIT(0); } de #endif MAIN() { #if _typ_long_double long double ldval, ldmax; char *s, *str; ldmax = LDBL_MAX; if(!(s = sfprints("%Le",ldmax)) ) terror("sfprints failed1\n"); if(!(str = malloc(strlen(s)+1)) ) terror("Malloc failed\n"); strcpy(str,s); if(sfsscanf(str,"%Le",&ldval) != 1) terror("sfsscanf failed\n"); if(!(s = sfprints("%Le",ldval)) ) terror("sfprints failed2\n"); if(strcmp(s,str) != 0) terror("Bad conversion, expecting %s asrc/lib/sfio/Sfio_t/ttmp.c000644 151361 151361 00000006514 07501443756 015421 0ustar00kpvkpv000000 000000 #include "sftest.h" static int Count = 0; static Sfdisc_t Disc; static char Rec[] = "0"; #if __STD_C void count(Sfio_t* f, int type, int fd) #else void count(f, type, fd) Sfio_t* f; int type; int fd; #endif { if(fd >= 0) Count += 1; } MAIN() { Sfio_t* f; char* s; ssize_t siz; Sfoff_t pos; Sfoff_t nxt; int pid; char buf[1024*1024]; /* test to see if transforming to file is ok with sfwrite */ memset(buf,1,sizeof(buf)); if(!(f = sftmp(1024)) ) terror("sftmp failed\n"); if((siz = sfwrite(f,buf,sizeof(buf))) != sizeof(buf)) terror("sfwrite failed with siz=%d",siz); /* ast ed does this */ if (!(f = sftmp(SF_BUFSIZE))) terror("sftmp\n"); if (pos = sfseek(f, (Sfoff_t)0, SEEK_CUR)) terror("top offset %I*d expected 0\n", sizeof(pos), pos); if ((siz = sfputr(f, Rec, 0)) != sizeof(Rec)) terror("put record size %I*d expected %d\n", sizeof(siz), siz, sizeof(Rec)); if ((nxt = sfseek(f, (Sfoff_t)0, SEEK_CUR)) != (pos + siz)) terror("put record size %I*d offset %I*d expected %I*d\n", sizeof(siz), siz, sizeof(nxt), nxt, sizeof(nxt), nxt + sizeof(Rec)); if ((pos = sfseek(f, (Sfoff_t)SF_BUFSIZE, SEEK_CUR)) != (nxt + SF_BUFSIZE)) terror("skip block size %d offset %I*d expected %I*d\n", SF_BUFSIZE, sizeof(nxt), nxt, sizeof(nxt), nxt + SF_BUFSIZE); sfclose(f); /* let two run concurrently */ if((pid = fork()) < 0) return 0; f = sftmp((size_t)SF_UNBOUND); sfputr(f,"1234",'\n'); /* write a string into it */ sfseek(f,(Sfoff_t)0,0); /* get back so we can read the string */ s = sfreserve(f,-1,0); if(sfvalue(f) != 5) terror("Get n=%d, expect n=5\n", sfvalue(f)); sfseek(f,(Sfoff_t)10,1); /* seek to extend buffer */ if(s = sfreserve(f,-1,0)) terror("Get n=%d, expect n=0\n", sfvalue(f)); sfset(f,SF_READ,0); /* turn off read mode so stream is write only */ sfseek(f,(Sfoff_t)(-10),1); /* back 10 places to get space to write */ if(!(s = sfreserve(f,-1,1)) || sfwrite(f,s,0) != 0) terror("Get n=%d, expect n > 0\n", sfvalue(f)); strcpy(s,"5678\n"); sfset(f,SF_READ,1); sfseek(f,(Sfoff_t)0,0); /* read 1234\n5678\n */ if(!(s = sfreserve(f,-1,1)) || sfread(f,s,0) != 0) terror("Get n=%d, expect n > 0\n", sfvalue(f)); if(strncmp(s,"1234\n5678\n",10) != 0) terror("Get wrong string\n"); sfclose(f); sfnotify(count); if(!(f = sftmp(0)) ) terror("sftmp\n"); if(Count != 1) terror("wrong count 1, count=%d\n", Count); sfclose(f); if(Count != 2) terror("wrong count 2 count=%d\n", Count); if(!(f = sftmp(8)) ) terror("sftmp\n"); if(Count != 2) terror("wrong count 2.2 count=%d\n", Count); sfdisc(f,&Disc); if(Count != 3) terror("wrong count 3 count=%d\n", Count); sfclose(f); if(Count != 4) terror("wrong count 4 count=%d\n", Count); if(!(f = sftmp(8)) ) terror("sftmp\n"); if(Count != 4) terror("wrong count 4.2 count=%d\n", Count); sfwrite(f,"0123456789",10); if(Count != 5) terror("wrong count 5 count=%d\n", Count); sfclose(f); if(Count != 6) terror("wrong count 6 count=%d\n", Count); if(!(f = sftmp(1024)) ) terror("sftmp\n"); sfwrite(f,"1234567890",10); sfseek(f,(Sfoff_t)0,0); if(sfsize(f) != 10) terror("Wrong size\n"); sfdisc(f,SF_POPDISC); if(sfsize(f) != 10) terror("Wrong size\n"); s = sfreserve(f,-1,0); if(sfvalue(f) != 10 || strncmp(s,"1234567890",10) != 0) terror("did not create correct real file\n"); if(pid != 0) wait(&pid); TSTEXIT(0); } terror("wrong count 5 count=%d\n", Count); sfclose(f); if(Count != 6) terror("wrong count 6 count=%d\n", Count); if(!(f = sftmp(1024)) ) terror("sftmp\n"); sfwrite(f,"1src/lib/sfio/Sfio_t/tstdio.c000644 151361 151361 00000005243 07235635536 015744 0ustar00kpvkpv000000 000000 #if _PACKAGE_ast #include "sftest.h" #include #else #include "sftest.h" #include "../Stdio_s/stdio.h" #endif /* test compliance of certain stdio behaviors */ MAIN() { FILE *f, *f2; long s1, s2; int i, k, fd; char buf[128*1024], rbuf[1024], *sp; if(argc > 1) { if(sfwrite(sfstdout,argv[1],strlen(argv[1])) != strlen(argv[1])) terror("Can't write to stdout"); sfsync(sfstdout); return 0; } /* test for shared streams and seek behavior */ if(!(f = fopen(tstfile(0),"w+")) ) terror("Opening file to read&write"); /* change stdout to a dup of fileno(f) */ fd = dup(1); close(1); dup(fileno(f)); /* write something to the dup file descriptor */ system(sfprints("%s 0123456789", argv[0])); /* change stdout back */ close(1); dup(fd); close(fd); /* this fseek should reset the stream back to where we can read */ fseek(f, 0L, SEEK_SET); /* see if data is any good */ fread(buf, sizeof(buf), 1, f); for(i = 0; i < 10; ++i) if(buf[i] != '0'+i) terror("Bad data0"); /* construct a bunch of lines and out put to f */ sp = buf; for(k = 0; k < sizeof(buf)/10; ++k) { for(i = 0; i < 9; ++i) *sp++ = '0' + i; *sp++ = '\n'; } /* write out a bunch of thing */ fseek(f, 0L, SEEK_SET); if(fwrite(buf, sizeof(buf), 1, f) != 1) terror("Writing data"); if((fd = dup(fileno(f))) < 0) terror("Can't dup file descriptor"); if(!(f2 = fdopen(fd, "r")) ) terror("Can't create stream"); /* read a few bytes from this dup stream */ fseek(f2, 0L, SEEK_SET); rbuf[0] = 0; if(fread(rbuf, 1, 7, f2) != 7) terror("Bad read\n"); for(i = 0; i < 7; ++i) if(rbuf[i] != '0'+i) terror("Bad data1"); if((s2 = ftell(f2)) != 7) terror("Bad tell location in f2"); /* now seek way off on f */ fseek(f, 1005L, SEEK_SET); rbuf[0] = 0; fread(rbuf, 5, 1, f); for(i = 5; i < 9; ++i) if(rbuf[i-5] != '0'+i) terror("Bad data2"); if(rbuf[i-5] != '\n') terror("Bad data: did not get new-line"); if((s1 = ftell(f)) != 1010) terror("Bad location in f: s1=%lld", (Sflong_t)s1); fseek(f, 0L, SEEK_CUR); /* switch mode so we can write */ if(fputc('x',f) < 0) terror("fputc failed"); if(fflush(f) < 0) terror("fflush failed"); if((s1 = ftell(f)) != 1011) terror("Bad location in f: s1=%lld", (Sflong_t)s1); fseek(f, -1L, SEEK_CUR); /* set the seek location in the file descriptor */ fflush(f2); /* assuming POSIX conformance and to set seek location to 1010 */ if((s2 = ftell(f2)) != 1010) terror("Bad location in f2: s2=%lld", (Sflong_t)s2); fread(rbuf, 10, 1, f2); if(rbuf[0] != 'x') terror("Didn't get x"); for(i = 1; i < 9; ++i) if(rbuf[i] != '0'+i) terror("Bad data3"); if(rbuf[i] != '\n') terror("Did not get new-line"); TSTEXIT(0); } ) terror("Bad location in f: s1=%lld", (Sflong_t)s1); fseek(f, -1L, SEEK_CUR); /* set the seek location in the file descriptor */ fflush(f2); /* assuming POSIX conformance and to set seek location to 1010 */ if((s2 = ftell(f2)) != 1010) terror("Bad location in f2: s2=%lld", (Sflong_t)s2); fread(rbuf, 10, 1, f2); if(rbuf[0] != 'x') tersrc/lib/sfio/Sfio_t/tbadargs.c000644 151361 151361 00000003117 07235635535 016222 0ustar00kpvkpv000000 000000 #include "sftest.h" #include int Code_line = 30; /* line number of CALL(sfclose(0)) */ #if defined(__LINE__) #define CALL(x) ((Code_line = __LINE__), (x)) #else #define CALL(x) ((Code_line += 1),(x)) #endif #if __STD_C void handler(int sig) #else void handler(sig) int sig; #endif { terror("Bad argument handling on code line %d", Code_line); } MAIN() { signal(SIGILL,handler); signal(SIGBUS,handler); signal(SIGSEGV,handler); CALL(sfclose(0)); CALL(sfclrlock(0)); CALL(sfopen(0,0,0)); CALL(sfdisc(0,0)); CALL(_sffilbuf(0,0)); CALL(_sfflsbuf(0,0)); CALL(sfgetd(0)); CALL(sfgetl(0)); CALL(sfgetm(0,0)); CALL(sfgetr(0,0,0)); CALL(sfgetu(0)); CALL(sfmove(0,0,0,0)); CALL(sfmutex(0,0)); CALL(sfnew(0,0,0,0,0)); CALL(sfnputc(0,0,0)); CALL(sfopen(0,0,0)); CALL(sfpoll(0,0,0)); CALL(sfpool(0,0,0)); CALL(sfpopen(0,0,0)); CALL(sfprintf(0,0)); CALL(sfvsprintf(0,0,0,0)); CALL(sfsprintf(0,0,0)); CALL(sfprints(0)); CALL(sfpurge(0)); CALL(sfputd(0,0)); CALL(sfputl(0,0)); CALL(sfputm(0,0,0)); CALL(sfputr(0,0,0)); CALL(sfputu(0,0)); CALL(sfraise(0,0,0)); CALL(sfrd(0,0,0,0)); CALL(sfread(0,0,0)); CALL(sfreserve(0,0,0)); CALL(sfresize(0,0)); CALL(sfscanf(0,0)); CALL(sfvsscanf(0,0,0)); CALL(sfsscanf(0,0)); CALL(sfseek(0,0,0)); CALL(sfset(0,0,0)); CALL(sfsetbuf(0,0,0)); CALL(sfsetfd(0,0)); CALL(sfsize(0)); CALL(sfsk(0, 0, 0, 0)); CALL(sfstack(0, 0)); CALL(sfswap(0, 0)); CALL(sfsync(0)); CALL(sftell(0)); CALL(sftmp(0)); CALL(sfungetc(0,0)); CALL(sfvprintf(0,0,0)); CALL(sfvscanf(0,0,0)); CALL(sfwr(0,0,0,0)); CALL(sfwrite(0,0,0)); TSTEXIT(0); } sfrd(0,0,0,0)); CALL(sfread(0,0,0)); CALL(sfreserve(0,0,0)); CALL(sfresize(0,0)); CALL(sfscanf(0,0)); CALL(sfvsscanf(0,0,0)); CALL(sfsscanf(0,0)); CALL(sfseek(0,0,0)); CALL(sfset(0,0,0)); CALL(sfsetbuf(0,0,0)); CALL(sfsetfd(0,0)); CALL(sfsize(0)); CALL(sfsk(0, 0, 0, 0)); CALL(sfstack(0, 0)); CALL(sfswap(0, 0)); CALL(sfsync(0)); CALL(sftell(0)); CALL(sftmp(0)); CALL(sfungetc(0,0)); CALL(sfvprintf(0,0,0)); CALL(src/lib/sfio/Sfio_t/tsetbuf.c000644 151361 151361 00000003553 07235635536 016114 0ustar00kpvkpv000000 000000 #include "sftest.h" #ifdef SF_APPEND #undef SF_APPEND #endif #if _hdr_stat #include #endif #if _sys_stat #include #endif Sfdisc_t Disc; MAIN() { int n, fd; Sfio_t *f; char *s, buf[1024]; int fdv[100]; buf[0] = 0; sfsetbuf(sfstdout,buf,sizeof(buf)); if(!sfstdout->pool) terror("No pool\n"); sfdisc(sfstdout,&Disc); sfset(sfstdout,SF_SHARE,0); sfputr(sfstdout,"123456789",0); if(strcmp(buf,"123456789") != 0) terror("Setting own buffer for stdout\n"); if(sfpurge(sfstdout) < 0) terror("Purging sfstdout\n"); if((fd = creat(tstfile(0),0666)) < 0) terror("Creating file\n"); if(write(fd,buf,sizeof(buf)) != sizeof(buf)) terror("Writing to file\n"); if(lseek(fd, (off_t)0, 0) < 0) terror("Seeking back to origin\n"); if(!(f = sfnew((Sfio_t*)0,buf,sizeof(buf),fd,SF_WRITE))) terror("Making stream\n"); if(!(s = sfreserve(f,SF_UNBOUND,1)) || s != buf) terror("sfreserve1 returns the wrong pointer\n"); sfwrite(f,s,0); #define NEXTFD 12 if((fd+NEXTFD) < (sizeof(fdv)/sizeof(fdv[0])) ) { struct stat st; int i; for(i = 0; i < fd+NEXTFD; ++i) fdv[i] = fstat(i,&st); } if((n = sfsetfd(f,fd+NEXTFD)) != fd+NEXTFD) terror("Try to set file descriptor to %d but get %d\n",fd+NEXTFD,n); if((fd+NEXTFD) < (sizeof(fdv)/sizeof(fdv[0])) ) { struct stat st; int i; for(i = 0; i < fd+NEXTFD; ++i) if(i != fd && fdv[i] != fstat(i,&st)) terror("Fd %d changes status after sfsetfd %d->%d\n", i, fd, fd+NEXTFD); } if(!(s = sfreserve(f,SF_UNBOUND,1)) || s != buf) terror("sfreserve2 returns the wrong pointer\n"); sfwrite(f,s,0); if(sfsetbuf(f,NIL(Void_t*),(size_t)SF_UNBOUND) != buf) terror("sfsetbuf didnot returns last buffer\n"); sfsetbuf(f,buf,sizeof(buf)); if(sfreserve(f,SF_UNBOUND,1) != buf || sfvalue(f) != sizeof(buf) ) terror("sfreserve3 returns the wrong value\n"); sfwrite(f,s,0); TSTEXIT(0); } = fstat(i,&st)) terror("Fd %d changes status after sfsetfd %d->%d\n", i, fd, fd+NEXTFD); } if(!(s = sfreserve(f,SF_UNBOUND,1)) || s != busrc/lib/sfio/Sfio_t/treserve.c000644 151361 151361 00000017165 07235635536 016303 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { int i, n, k; Sfoff_t o; char buf[1024], *s; char bigbuf[1024*8]; int fd[2]; Sfio_t* f; if(!(f = sfopen(0, tstfile(0), "w")) ) terror("Opening file to write"); if(sfwrite(f,"0123456789",10) != 10 || sfwrite(f,"abcde",5) != 5) terror("Writing data"); if(!(f = sfopen(f, tstfile(0), "r")) ) terror("Opening file to read"); if(!(s = (char*)sfreserve(f,10,0)) ) terror("sfreserve failed"); if(strncmp(s,"0123456789",10) != 0) terror("Did not get correct data"); if((s = (char*)sfreserve(f,10,0)) ) terror("sfreserve should not have succeeded"); if(sfvalue(f) != 5) terror("sfreserve should have left the right unread record length"); if(!(s = (char*)sfreserve(f,0,SF_LASTR)) ) terror("sfreserve should have returned last unread record"); if(strncmp(s,"abcde",5) != 0) terror("Record has wrong data"); sfclose(f); sfsetbuf(sfstdout,buf,sizeof(buf)); sfset(sfstdout,SF_SHARE|SF_PUBLIC,0); if((s = (char*)sfreserve(sfstdout,0,0)) != buf) terror("Wrong buffer\n"); if((n = sfwrite(sfstdout,"foobar",6)) != 6) terror("Write failed\n"); if((char*)sfreserve(sfstdout,0,0) != s+6) terror("Wrong reserved pointer\n"); sfpurge(sfstdout); if(sfopen(sfstdout, tstfile(0),"w") != sfstdout) terror("Opening file\n"); sfsetbuf(sfstdout,NIL(char*),0); if(!(s = sfreserve(sfstdout,0,1)) ) terror("Could not lock stdout\n"); if(sfputc(sfstdout,'1') >= 0) terror("stdout wasn't locked\n"); if(sfwrite(sfstdout,s,0) != 0) terror("stdout can't be unlocked\n"); sfsetbuf(sfstdout,NIL(char*),sizeof(buf)/2); for(i = 0; i < sizeof(buf); ++i) buf[i] = (i%26) + 'a'; n = 0; for(i = 0; i < 33; ++i) { if(!(s = sfreserve(sfstdout,sizeof(buf),1)) ) terror("Can't reserve write buffer\n"); memcpy(s,buf,sizeof(buf)); if(sfwrite(sfstdout,s,sizeof(buf)) != sizeof(buf) ) terror("Writing to file\n"); else n += sizeof(buf); } sfsync(sfstdout); if(sfopen(sfstdin, tstfile(0),"r") != sfstdin) terror("Opening file2\n"); sfsetbuf(sfstdin,NIL(char*),8*sizeof(buf)); if(sfsize(sfstdin) != n) terror("Wrong size for file\n"); i = 0; for(;;) { if(!(s = sfreserve(sfstdin,16*sizeof(buf),0)) ) break; else i += 16*sizeof(buf); } if(sfvalue(sfstdin) > 0) i += sfvalue(sfstdin); if(i != n) terror("Did not read data\n"); if(sfseek(sfstdin,(Sfoff_t)0,0) != 0) terror("sfseek failed0\n"); sfsetbuf(sfstdin,bigbuf,sizeof(bigbuf)); i = 0; for(;;) { if(!(s = sfreserve(sfstdin,16*sizeof(buf),0)) ) break; else i += 16*sizeof(buf); } if(sfvalue(sfstdin) > 0) i += sfvalue(sfstdin); if(i != n) terror("Did not read data2\n"); sfsetbuf(sfstdin,NIL(Void_t*),(size_t)SF_UNBOUND); if(sfopen(sfstdout, tstfile(0), "w") != sfstdout) terror("Can't open to write\n"); for(i = 0; i < 32; ++i) { for(k = 0; k < sizeof(bigbuf); ++k) bigbuf[k] = '0' + (k+i)%10; if(sfwrite(sfstdout,bigbuf,sizeof(bigbuf)) != sizeof(bigbuf)) terror("Writing to %s\n", tstfile(0)); } sfclose(sfstdout); if(sfopen(sfstdin, tstfile(0), "r") != sfstdin) terror("Opening to read\n"); sfsetbuf(sfstdin,NIL(Void_t*),8*1024); if(!(s = sfreserve(sfstdin,16*sizeof(bigbuf),0)) ) terror("sfreserve failed\n"); for(i = 0; i < 16; ++i) { for(k = 0; k < sizeof(bigbuf); ++k) if(*s++ != ('0' + (k+i)%10)) terror("Wrong data i=%d k=%d\n",i,k); } if((o = sfseek(sfstdin,-15*((Sfoff_t)sizeof(bigbuf)),1)) != sizeof(bigbuf)) terror("sfseek failed o=%lld\n", (Sflong_t)o); if(sfread(sfstdin,bigbuf,sizeof(bigbuf)) != sizeof(bigbuf) ) terror("sfread failed\n"); s = bigbuf; for(i = 1; i < 2; ++i) { for(k = 0; k < sizeof(bigbuf); ++k) if(*s++ != ('0' + (k+i)%10)) terror("Wrong data2 i=%d k=%d\n",i,k); } if(!(s = sfreserve(sfstdin,16*sizeof(bigbuf),1)) ) { sfsetbuf(sfstdin,NIL(Void_t*),16*sizeof(bigbuf)); if(!(s = sfreserve(sfstdin,16*sizeof(bigbuf),1)) ) terror("sfreserve failed2\n"); } sfread(sfstdin,s,0); #ifdef MAP_TYPE if(sfreserve(sfstdin,0,0) != s) terror("Reserve pointer changed?\n"); #endif for(i = 2; i < 17; ++i) { for(k = 0; k < sizeof(bigbuf); ++k) if(*s++ != ('0' + (k+i)%10)) terror("Wrong data3 i=%d k=%d\n",i,k); } if(sfopen(sfstdout, tstfile(0),"w") != sfstdout) terror("Opening for write\n"); for(i = 0; i < 100; ++i) bigbuf[i] = 'a'; for(i = 0; i < 101; ++i) if(sfwrite(sfstdout,bigbuf,100) != 100) terror("Bad write to file\n"); sfsync(sfstdout); if(sfopen(sfstdin, tstfile(0),"r") != sfstdin) terror("Opening for read\n"); sfsetbuf(sfstdin,buf,1024); sfset(sfstdin,SF_SHARE,0); for(i = 0; i < 10; ++i) if(!sfreserve(sfstdin,500,0) ) terror("Can't reserve from file\n"); for(i = 0; i < 5; ++i) if(sfwrite(sfstdout,bigbuf,100) != 100) terror("Bad write to file2\n"); sfsync(sfstdout); n = 5000; while(sfreserve(sfstdin,500,0)) n += 500; if(n+sfvalue(sfstdin) != sfsize(sfstdout)) terror("Wrong reserve size from file\n"); tstcleanup(); fd[0] = fd[1] = -1; if(pipe(fd) < 0 || fd[0] < 0 || fd[1] < 0) terror("Can't make pipe\n"); if(write(fd[1],"abcdefghijklmnopqrstuvwxyz\n0123456789",37) != 37) terror("Can't write to pipe\n"); close(fd[1]); sfclose(sfstdin); if(sfnew(sfstdin,NIL(Void_t*),(size_t)SF_UNBOUND,fd[0],SF_READ) != sfstdin) terror("Can't creat pipe stream\n"); if(!(s = sfgetr(sfstdin,'\n',1) ) || strcmp(s,"abcdefghijklmnopqrstuvwxyz") != 0) terror("Get wrong string\n"); if((s = sfreserve(sfstdin,16,1)) ) terror("There should not be enough data for this\n"); if(!(s = sfreserve(sfstdin,10,0)) ) terror("Fail to reserve remainder of stream\n"); if(strncmp(s,"0123456789",10) != 0) terror("Reserved data was corrupted\n"); for(i = 0; i < 18; i += 6) { if(!(f = sftmp(i)) ) terror("Can't open tempfile\n"); sfset(f,SF_READ,0); for(k = 0; k < 10; ++k) if(sfputc(f,'0'+k) != '0'+k) terror("Write %c to temp file\n", '0'+k); if(!sfreserve(f,0,-1) ) terror("No write buffer?\n"); if(i < 10 && (sfset(f,0,0)&SF_STRING) ) terror("No file created\n"); sfset(f,SF_READ,1); sfseek(f,(Sfoff_t)0,0); if(sfgetc(f) != '0') terror("Getting the 0\n"); if(!(s = sfreserve(f,0,-1)) || sfvalue(f) != 9 || strncmp(s,"123456789",9) != 0) terror("Read reserved failed\n"); if(sfgetc(f) != '1') terror("Getting the 1\n"); sfclose(f); } if(!(f = sftmp(0)) ) terror("Can't open file\n"); for(i = 0; i < sizeof(bigbuf); ++i) bigbuf[i] = (i%10) + '0'; if(sfwrite(f,bigbuf,1000) != 1000) terror("Writing to file\n"); sfsetbuf(f,buf,100); sfseek(f,(Sfoff_t)0,0); if(!(s = sfreserve(f,-1,1)) ) terror("sfreserve failed at bottom1\n"); if(sfvalue(f) != 100) terror("Expecting1 100 bytes, get only %d\n",sfvalue(f)); if(strncmp(s,bigbuf,100) != 0) terror("Wrong data at bottom\n"); sfread(f,s,95); if(!(s = sfreserve(f,6,1)) ) terror("sfreserve failed at bottom2\n"); if(sfvalue(f) != 100) terror("Expecting2 100 bytes, get only %d\n",sfvalue(f)); if(strncmp(s,bigbuf+5,100) != 0) terror("Wrong data at bottom2\n"); sfread(f,s,5); for(i = 1; i < 10; ++i) { if(!(s = sfreserve(f,-96,1)) ) terror("sfreserve failed at bottom loop\n"); if(sfvalue(f) != 100) terror("Expecting3 100 bytes, get only %d\n",sfvalue(f)); if(strncmp(s,bigbuf,100) != 0) terror("Wrong data at bottom loop\n"); sfread(f,s,100); } sfseek(f,(Sfoff_t)0,0); for(i = 0; i < 16; ++i) sfwrite(f,bigbuf,sizeof(bigbuf)); sfseek(f,(Sfoff_t)0,0); sfset(f,SF_WRITE,0); sfsetbuf(f,NIL(Void_t*),4096); if(!(s = sfreserve(f,-1,1)) ) terror("sfreserve failed 11\n"); if((n = sfvalue(f)) < 4096) terror("sfvalue is wrong\n"); if(sfread(f,s,n-16) != n-16) terror("sfread failed\n"); if(!(s = sfreserve(f,-7,1)) ) terror("sfreserve failed 12\n"); if(sfvalue(f) < 16 ) terror("hmm\n"); TSTEXIT(0); } ttom loop\n"); sfread(f,s,100); } sfseek(f,(Sfoff_t)0,0); for(i = 0; i < 16; ++i) sfwrite(f,bigbuf,sizeof(bigbuf)); sfseek(f,(Sfoff_t)0,0); sfset(f,SF_WRITE,0); sfsetbuf(f,NIL(Void_t*),4096); if(!(s = sfreserve(f,-1,1)) ) terror("sfreserve failed 11\n"); if((n = sfvalue(f)) < 4096) terror("sfvalue is wrong\n"); if(sfread(f,s,n-16) != n-16) terror("sfread failed\n"); if(!(src/lib/sfio/Sfio_t/tleak.c000644 151361 151361 00000001136 07235635535 015532 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfoff_t m; if(sfopen(sfstdout, tstfile(0), "w") != sfstdout) terror("Can't open %s to write\n", tstfile(0)); if(sfputr(sfstdout,"012345678\n",-1) != 10) terror("Can't write to %s\n", tstfile(0)); if(sfopen(sfstdout, tstfile(1),"w") != sfstdout) terror("Can't open %s to write\n", tstfile(1)); if(sfopen(sfstdin, tstfile(0), "r") != sfstdin) terror("Can't open %s to read\n", tstfile(0)); if((m = sfmove(sfstdin,sfstdout, (Sfoff_t)SF_UNBOUND, -1)) != 10) terror("Moving data from %s to %s m=%lld\n", tstfile(0), tstfile(1), (Sflong_t)m); TSTEXIT(0); } terror("Can't open %s to write\n", tstfile(0)); if(sfputr(sfstdout,"012345678\n",-1) != 10) terror("Can't write to %s\n", tstfile(0)); if(sfopen(sfstdout, tstfile(1),"w") != sfstdout) terror("Can't open %s to write\n", tstfile(1)); if(sfopen(sfstdin, tstfile(0), "r") != sfstdin) terror("Can't open %s to read\n", tstfile(0)); if((m = sfmove(sfstdin,sfstdout, (Sfoff_t)SF_UNBOUND, -1)) != 10) terror("src/lib/sfio/Sfio_t/tseek.c000644 151361 151361 00000007031 07235635536 015546 0ustar00kpvkpv000000 000000 #include "sftest.h" static int Bufcount = 0; #if __STD_C ssize_t readbuf(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t readbuf(f,buf,n,disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { Bufcount += 1; return sfrd(f,buf,n,disc); } Sfdisc_t Disc = {readbuf, (Sfwrite_f)0, (Sfseek_f)0, (Sfexcept_f)0, (Sfdisc_t*)0}; MAIN() { Sfio_t *f, *sf; char *ss, *s; int n, i; char zero[SF_BUFSIZE*2]; char buf[SF_BUFSIZE], little[512]; Sfoff_t one, two; s = "123456789\n"; n = strlen(s); if(!(f = sfopen((Sfio_t*)0, tstfile(0),"w"))) terror("Opening file to write\n"); for(i = 0; i < 1000; ++i) if(sfwrite(f,s,n) != n) terror("Writing data\n"); if(!(f = sfopen(f, tstfile(0),"r"))) terror("Opening file to read\n"); if(sfseek(f,(Sfoff_t)128,0) != (Sfoff_t)128) terror("Bad seek to 128\n"); if(sfseek(f,(Sfoff_t)0,1) != (Sfoff_t)128) terror("Bad seek(0,1) to 128\n"); if(sfseek(f,(Sfoff_t)0,2) != (i*n)) terror("Bad file length\n"); if(sftell(f) != (i*n)) terror("sftell\n"); for(; i > 0; --i) { sfseek(f,(Sfoff_t)(-i*n),2); if(!(ss = sfgetr(f,'\n',1))) terror("sfgetr\n"); if(strncmp(ss,s,sfvalue(f)-1) != 0) terror("Expect=%s\n",s); } if(!(f = sfopen(f,tstfile(0),"w")) ) terror("Open to write\n"); for(n = sizeof(zero)-1; n >= 0; --n) zero[n] = 0; if(sfwrite(f,zero,sizeof(zero)) != sizeof(zero)) terror("Writing data\n"); one = sfseek(f,(Sfoff_t)0,2); two = (Sfoff_t)lseek(sffileno(f), (off_t)0, 2); if(one != two) terror("seeking1\n"); if(sfseek(f,(Sfoff_t)(-1),2) != (Sfoff_t)lseek(sffileno(f), (off_t)(-1), 2)) terror("seeking2\n"); if(!(f = sfopen(f,tstfile(0),"w"))) terror("Open to write2\n"); for(n = 0; n < sizeof(buf); n++) buf[n] = n; for(n = 0; n < 256; n++) if(sfwrite(f,buf,sizeof(buf)) != sizeof(buf)) terror("Writing data 2\n"); if(!(f = sfopen(f,tstfile(0),"r"))) terror("Open to read2\n"); if(sfgetc(f) != 0 && sfgetc(f) != 1) terror("Get first 2 bytes\n"); if(sfseek(f,(Sfoff_t)(128*sizeof(buf)),0) != (Sfoff_t)128*sizeof(buf) ) terror("Seeking \n"); for(n = 0; n < 128; ++n) if(sfread(f,buf,sizeof(buf)) != sizeof(buf)) terror("Reading data\n"); if(!(f = sfopen(f,tstfile(0),"r"))) terror("Open to read3\n"); sfsetbuf(f,little,sizeof(little)); if(sfread(f, buf, 10) != 10) terror("sfread failed\n"); if(sftell(f) != (Sfoff_t)10) terror("sftell failed\n"); if(sfseek(f, (Sfoff_t)10, SEEK_CUR|SF_PUBLIC) != (Sfoff_t)20) terror("sfseek failed\n"); sfseek(f, (Sfoff_t)0, SEEK_SET); if(!(sf = sfnew((Sfio_t*)0, little, sizeof(little), sffileno(f), SF_READ)) ) terror("sfnew failed\n"); if(sfread(f, buf, 10) != 10) terror("sfread failed2\n"); if(sftell(f) != 10) terror("sftell failed2\n"); if(sfseek(sf, (Sfoff_t)4000, SEEK_SET) != (Sfoff_t)4000) terror("sfseek failed on sf\n"); sfsync(sf); if(sfseek(f, (Sfoff_t)10, SEEK_CUR|SF_PUBLIC) != (Sfoff_t)4010) terror("sfseek public failed\n"); /* test to see if the buffering algorithm does the right thing */ if(!(f = sfopen(NIL(Sfio_t*),tstfile(0),"w")) ) terror("Opening test file to write"); for(i = 0; i < 8192; ++i) if(sfputr(f,"123456789",'\n') != 10) terror("writing test data"); if(!(f = sfopen(f,tstfile(0),"r")) ) terror("Opening test file to read"); sfdisc(f,&Disc); sfsetbuf(f,NIL(Void_t*),8192); for(i = 0; i < 8192; ++i) { sfseek(f, (Sfoff_t)(i*10), 0); if(!(s = sfgetr(f, '\n', SF_STRING)) ) terror("Reading data"); if(strcmp(s,"123456789") != 0) terror("Bad data"); } if(Bufcount != 10) terror("Bad buffer filling count"); TSTEXIT(0); } ng test file to write"); for(i = 0; i < 8192; ++i) if(sfputr(f,"123456789",'\n') != 10) terror("writing test data"); if(!(f = sfopen(f,tstfile(0),"r")) ) terror("Opening test file to read"); sfdisc(f,&Disc); sfsetbuf(f,NIL(Void_t*),8192); for(i = 0; i < 8192; ++i) { sfseek(f, (Sfoff_t)(i*10), 0); if(!(s = sfgetr(f, '\n', SF_STRING)) ) terror("Reading data"); if(strcmp(s,"123456789") != 0) terror("Bad data"); } if(Bufcount != 10) terror("Bad buffer filling src/lib/sfio/Sfio_t/ttell.c000644 151361 151361 00000005737 07241770617 015567 0ustar00kpvkpv000000 000000 #include "sftest.h" #if __STD_C static ssize_t discread(Sfio_t* f, void* buf, size_t n, Sfdisc_t* disc) #else static ssize_t discread(f, buf, n, disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { return sfrd(f, buf, n, disc); } #if __STD_C static ssize_t discwrite(Sfio_t* f, const void* buf, size_t n, Sfdisc_t* disc) #else static ssize_t discwrite(f, buf, n, disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { return sfwr(f, buf, n, disc); } #if __STD_C static Sfoff_t discseek(Sfio_t* f, Sfoff_t offset, int type, Sfdisc_t* disc) #else static ssize_t discseek(f, offset, type, disc) Sfio_t* f; Sfoff_t offset; int type; Sfdisc_t* disc; #endif { return (Sfoff_t)(-1); /* pretend that stream is unseekable */ } Sfdisc_t Disc1 = { discread, discwrite }; Sfdisc_t Disc2 = { discread, discwrite }; Sfdisc_t Disc3 = { discread, discwrite }; MAIN() { Sfio_t* f; char* s; int i; if(argc > 1) { /* coprocess only */ while((s = sfgetr(sfstdin,'\n',0)) ) sfwrite(sfstdout,s,sfvalue(sfstdin)); TSTEXIT(0); } if(!(f = sfpopen(NIL(Sfio_t*),sfprints("%s -p",argv[0]),"r+")) ) terror("Open coprocess\n"); if(sfwrite(f,"123\n",4) != 4) terror("Write coprocess\n"); if(sftell(f) != 4) terror("sftell1\n"); if(!(s = sfreserve(f,4,0)) || strncmp(s,"123\n",4) != 0 ) terror("Read coprocess\n"); if(sftell(f) != 8) terror("sftell2\n"); sfset(f,SF_SHARE,1); if(sfwrite(f,"123\n",4) != 4) terror("Write coprocess2\n"); if(sftell(f) != 12) terror("sftell 3\n"); if(!(s = sfreserve(f,4,0)) || strncmp(s,"123\n",4) != 0 ) terror("Read coprocess2\n"); if(sftell(f) != 16) terror("sftell 4\n"); sfclose(f); /* the below tests to see if stream position is correct when multiple disciplines are put on a stream. */ if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "w"))) terror("Opening file to write"); sfdisc(f,&Disc1); sfdisc(f,&Disc2); sfdisc(f,&Disc3); for(i = 0; i < 100; ++i) { if(sfputr(f, "123456789", '\n') != 10) terror("Can't write out strings"); sfsync(f); if(sftell(f) != (Sfoff_t)((i+1)*10) ) terror("Wrong position"); } sfclose(f); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "r"))) terror("Opening file to read"); sfdisc(f,&Disc1); sfdisc(f,&Disc2); sfdisc(f,&Disc3); for(i = 0; i < 100; ++i) { if(!(s = sfgetr(f, '\n', 1)) ) terror("Can't read string"); if(strcmp(s,"123456789") != 0) terror("Wrong string"); if(sftell(f) != (Sfoff_t)((i+1)*10) ) terror("Wrong position"); } sfclose(f); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "r"))) terror("Opening file to read"); Disc1.seekf = discseek; sfdisc(f,&Disc1); Disc2.seekf = discseek; sfdisc(f,&Disc2); Disc3.seekf = discseek; sfdisc(f,&Disc3); for(i = 0; i < 100; ++i) { if(!(s = sfgetr(f, '\n', 1)) ) terror("Can't read string"); if(strcmp(s,"123456789") != 0) terror("Wrong string"); if(sftell(f) != (Sfoff_t)((i+1)*10) ) terror("Wrong position"); } sfclose(f); TSTEXIT(0); } terror("Wrong position"); } ssrc/lib/sfio/Sfio_t/sftest.h000644 151361 151361 00000000570 07204561053 015735 0ustar00kpvkpv000000 000000 #include "../FEATURE/sfio" #if _SFIO_H_ONLY #include #else #include #endif #if _hdr_unistd #include #endif #include #include "terror.h" #ifndef EINTR #define EINTR 4 #endif #ifndef EBADF #define EBADF 9 #endif #ifndef EAGAIN #define EAGAIN 11 #endif #ifndef ENOMEM #define ENOMEM 12 #endif #ifndef ESPIPE #define ESPIPE 29 #endif ; if(sftell(f) != (Sfoff_t)((i+1)*10)  JAV=>:,`:,`@src/lib/sfio/Sfio_t/tgetr.c000644 151361 151361 00000002316 07235635535 015560 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t* f; char* s; char* string = "111\n222\n333"; f = sfopen(NIL(Sfio_t*),string,"s"); if(!(s = sfgetr(f,'\n',SF_STRING|SF_LOCKR)) || strcmp(s,"111") != 0) terror("sfgetr failed1\n"); if(sfgetr(f,'\n',0) != NIL(char*)) terror("sfgetr should have failed because of locking\n"); sfread(f,s,1); if(!(s = sfgetr(f,'\n',SF_STRING)) || strcmp(s,"222") != 0) terror("sfgetr failed2\n"); if((s = sfgetr(f,'\n',0)) != NIL(char*)) terror("sfgetr should have failed because of partial record\n"); if(!(s = sfgetr(f,0,SF_LASTR)) ) terror("sfgetr should have succeeded getting partial record\n"); /* test type == -1 and type == 1 modes */ sfseek(f,(Sfoff_t)0,0); if(!(s = sfgetr(f,'\n',1)) || strcmp(s,"111") != 0) terror("sfgetr failed in compatible mode\n"); if(!(s = sfgetr(f,'\n',SF_STRING|SF_LOCKR)) || strcmp(s,"222") != 0) terror("sfgetr failed3\n"); if(sfgetr(f,'\n',1) ) terror("sfgetr should have failed due to locking\n"); sfread(f,s,0); if(sfgetr(f,'\n',1) ) terror("sfgetr should have failed because record is incomplete\n"); if(!(s = sfgetr(f,0,-1)) || strcmp(s,"333") != 0) terror("sfgetr failed in getting last partial record\n"); TSTEXIT(0); } = sfgetr(f,'\n',1)) || strcmp(s,"111") != 0) terror("sfgetr failed in compatible mode\n"); if(!(s = sfgetr(f,'\n',SF_STRING|SF_LOCKR)) || strcmp(s,"222") != 0) terror("sfgetr failed3\n"); if(sfgetr(f,'\n',1) ) terror("sfgetr should have failed due to locking\n"); sfread(f,s,0); if(sfgetr(f,'\nsrc/lib/sfio/Sfio_t/tmtsafe.c000644 151361 151361 00000010751 07432516257 016076 0ustar00kpvkpv000000 000000 #include "sftest.h" #include #include #define N_STR 1000 static Sfio_t* Sf; static char Bigz[10*N_STR]; static char* Str[26] = { "aaaaaaaaa", "bbbbbbbbb", "ccccccccc", "ddddddddd", "eeeeeeeee", "fffffffff", "ggggggggg", "hhhhhhhhh", "iiiiiiiii", "jjjjjjjjj", "kkkkkkkkk", "lllllllll", "mmmmmmmmm", "nnnnnnnnn", "ooooooooo", "ppppppppp", "qqqqqqqqq", "rrrrrrrrr", "sssssssss", "ttttttttt", "uuuuuuuuu", "vvvvvvvvv", "wwwwwwwww", "xxxxxxxxx", "yyyyyyyyy", "zzzzzzzzz" }; static int Inverted; /* failure means success */ #if _STD_C void* writesmall(void* arg) #else void* writesmall(arg) void* arg; #endif { char* s; int n; s = Str[(int)arg]; for(n = 0; n < N_STR; ++n) { if(sfputr(Sf, s, '\n') != 10) { if(Inverted) tsuccess("sfputr failed as expected"); else terror("sfputr failed"); } } return arg; } #if _STD_C void* writebig(void* arg) #else void* writebig(arg) void* arg; #endif { int r = (rand()%3) + 1; sleep(r); if(sfwrite(Sf,Bigz,sizeof(Bigz)) != sizeof(Bigz)) terror("Writing bigz"); return arg; } #if __STD_C void sighandler(int sig) #else void sighandler(sig) int sig; #endif { tmesg("\tSignal %d.\n", sig); TSTEXIT(0); } MAIN() { #if vt_threaded int count[26]; char* s; int i, k, n; Vthread_t* thread[26]; /* make the big z string */ for(i = 0, s = Bigz; i < N_STR; ++i, s += 10) strcpy(s, "zzzzzzzzz\n"); signal(SIGQUIT,sighandler); signal(SIGINT,sighandler); do_inverted: /* get back to here when trying to make things fail */ if(!Inverted) tmesg("\tTesting thread-safe streams.\n"); else tmesg("\tTesting unsafe streams: if hung, send INTR or QUIT.\n"); /* spin threads writing small chunks */ Sf = sfopen(NIL(Sfio_t*),tstfile(0), Inverted ? "w+" : "mw+"); for(i = 0; i < 26; ++i) { if(!(thread[i] = vtopen(0, 0)) ) terror("Creating thread handle[%d]", i); if(vtrun(thread[i], writesmall, (Void_t*)i) < 0) terror("Running thread [%d]", i); } for(i = 0; i < 26; ++i) { count[i] = 0; vtwait(thread[i]); } if(sfseek(Sf,(Sfoff_t)0,SEEK_SET) != (Sfoff_t)0) { if(Inverted) tsuccess("Rewinding failed as expected"); else terror("Rewinding"); } for(n = 0;; ++n) { if(!(s = sfgetr(Sf,'\n',1)) ) break; i = s[0] - 'a'; if(i < 0 || i >= 26 || sfvalue(Sf) != 10) { if(Inverted) tsuccess("Bad data as expected"); else terror("Bad data s='%s' n=%d", s, n); } if(strcmp(s, Str[i]) != 0) { if(Inverted) tsuccess("Bad str as expected"); else terror("Bad str s='%s' i=%d Str[i]='%s' n=%d", s, i, Str[i], n); } count[i] += 1; } for(i = 0; i < 26; ++i) { if(count[i] != N_STR) { if(Inverted) tsuccess("Bad count as expected"); else terror("Bad count[%d] = %d", i, count[i]); } } /* spin threads with one writing a big chunk */ Sf = sfopen(Sf,tstfile(0), Inverted ? "w+" : "mw+"); for(i = 0; i < 25; ++i) { if(!(thread[i] = vtopen(0, 0)) ) terror("Creating thread %d", i); if(vtrun(thread[i], writesmall, (void*)i) < 0) terror("Running thread %d", i); } sleep(1); if(!(thread[i] = vtopen(0,0))) terror("Creating big thread z"); if(vtrun(thread[i],writebig,(void*)i) < 0) terror("Running big thread z"); for(i = 0; i < 26; ++i) { count[i] = 0; vtwait(thread[i]); } if(sfseek(Sf,(Sfoff_t)0,SEEK_SET) != (Sfoff_t)0) { if(Inverted) tsuccess("Rewinding failed as expected"); else terror("Rewinding"); } for(n = 0; ; ++n) { if(!(s = sfgetr(Sf,'\n',1)) ) break; i = s[0] - 'a'; if(i < 0 || i >= 26 || sfvalue(Sf) != 10) { if(Inverted) tsuccess("Bad data as expected"); else terror("Bad data s='%s' n=%d", s, n); } if(strcmp(s, Str[i]) != 0) { if(Inverted) tsuccess("Bad str as expected"); else terror("Bad str s='%s' i=%d Str[i]='%s' n=%d", s, i, Str[i], n); } count[i] += 1; if(i == 25) /* the 'z' */ { for(k = 1; k < N_STR; ++k, ++n) { if(!(s = sfgetr(Sf,'\n',1)) ) { if(Inverted) tsuccess("Premature eof as expected"); else terror("Premature eof n=%d", n); } if(strcmp(s, Str[25]) != 0) { if(Inverted) tsuccess("Bad str as expected"); else terror("Bad str s='%s' n=%d", s, n); } count[i] += 1; } } } for(i = 0; i < 26; ++i) { if(count[i] != N_STR) { if(Inverted) tsuccess("Bad count as expected"); else terror("Bad count[%d] = %d", i, count[i]); } } if(!Inverted) { Inverted = 1; goto do_inverted; } else tmesg("\tUnsafe streams work ok on this platform!\n"); #endif TSTEXIT(0); } "Premature eof n=%d", nsrc/lib/sfio/Sfio_t/tlocale.c000644 151361 151361 00000002033 07251336006 016037 0ustar00kpvkpv000000 000000 #include "sftest.h" #if _lib_locale #include #endif MAIN() { #if _lib_locale char buf[128], cmp[128]; float d; int n, decimal, thousand; struct lconv* lv; setlocale(LC_ALL, ""); if(!(lv = localeconv())) TSTEXIT(0); decimal = '.'; if(lv->decimal_point && lv->decimal_point[0]) decimal = lv->decimal_point[0]; thousand = 0; if(lv->thousands_sep && lv->thousands_sep[0]) thousand = lv->thousands_sep[0]; if(thousand) sfsprintf(cmp, sizeof(cmp), "1%c000", thousand); else sfsprintf(cmp, sizeof(cmp), "1000"); sfsprintf(buf, sizeof(buf), "%'d", 1000); if(strcmp(buf, cmp) != 0) terror("Bad printing"); if(thousand) sfsprintf(cmp, sizeof(cmp), "1%c000%c10", thousand, decimal); else sfsprintf(cmp, sizeof(cmp), "1000%c10", decimal); d = 0.; if((n = sfsscanf(cmp, "%'f", &d)) != 1) terror("Scan error %d", n); if(d < 1000.099 || d > 1000.101) terror("Bad scanning"); sfsprintf(buf, sizeof(buf), "%.2f", d); if(strcmp(buf, "1000.10") != 0) terror("Deep formatting error"); #endif TSTEXIT(0); } 1000"); sfsprintf(buf, sizeof(buf), "%'d", 1000); if(strcmp(buf, cmp) != 0) terror("Bad printing"); if(thousand) sfsprintf(cmp, sizeof(cmp), "1%c000%c10", thousand, decimal); else sfsprintf(cmp, sizeof(cmp), "1000%c10", decimal); d = 0.; if((n = sfsscanf(cmp, "%'f", &d)) != 1) terror("Scan error %d", n); if(d < 1000.099 || d > 1000.101) terror("Bad scanning"); sfsprintf(buf, sizeof(buf), "%.2f", d); if(strcmp(buf, "1000.10") != 0) terror("Deep formatting errorsrc/lib/sfio/Sfio_t/tswap.c000644 151361 151361 00000001446 07235635536 015575 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t* f1; Sfio_t* f2; char* s; if(!(f1 = sfopen(NIL(Sfio_t*), tstfile(0),"w+")) ) terror("Can't open file\n"); if(sfwrite(f1,"0123456789\n",11) != 11) terror("Can't write to file\n"); sfclose(sfstdin); if(sfswap(f1,sfstdin) != sfstdin) terror("Can't swap with sfstdin\n"); sfseek(sfstdin,(Sfoff_t)0,0); if(!(s = sfgetr(sfstdin,'\n',1)) ) terror("sfgetr failed\n"); if(strcmp(s,"0123456789") != 0) terror("Get wrong data\n"); if(!(f1 = sfswap(sfstdin,NIL(Sfio_t*))) ) terror("Failed swapping to NULL\n"); if(!sfstack(sfstdout,f1) ) terror("Failed stacking f1\n"); if(!(f2 = sfopen(NIL(Sfio_t*), tstfile(0), "r")) ) terror("Can't open for read\n"); if(sfswap(f1,f2) != NIL(Sfio_t*) ) terror("sfswap should have failed\n"); TSTEXIT(0); } 't swap with sfstdin\n"); sfseek(sfstdin,(Sfoff_t)0,0); if(!(s = sfgetr(sfstdin,'\n',1)) ) terror("sfgetr failed\n"); if(strcmp(s,"0123456789") != 0) terror("Get wrong data\n"); if(!(f1 = sfswap(sfstdin,NIL(Sfsrc/lib/sfio/Sfio_t/tpipemove.c000644 151361 151361 00000001644 07235635536 016447 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { int fd[2]; Sfio_t *fr, *fw; char *s; int n, w; if(pipe(fd) < 0) terror("Can't open pipe\n"); if(!(fr = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND,fd[0],SF_READ)) || !(fw = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND,fd[1],SF_WRITE)) ) terror("Can't open pipe streams\n"); sfset(fr,SF_SHARE,1); if(sfopen(sfstdout,tstfile(0),"w") != sfstdout) terror("Can't open for write\n"); if(sfopen(sfstdin,tstfile(0),"r") != sfstdin) terror("Can't open for read\n"); for(n = 0; n < 100; ++n) if((w = sfwrite(fw,"123456789\n",10)) != 10) terror("Writing to pipe w=%d\n",w); if((n = (int)sfmove(fr,sfstdout,(Sfoff_t)100,'\n')) != 100) terror("sfmove failed n=%d\n", n); sfclose(sfstdout); for(n = 0; n < 100; ++n) { if(!(s = sfgetr(sfstdin,'\n',1)) ) terror("Can't read data\n"); if(strcmp(s,"123456789") != 0) terror("Wrong data\n"); } TSTEXIT(0); } t open for write\n"); if(sfopen(sfstdin,tstfile(0),"r") != sfstdin) terror("Can't open fosrc/lib/sfio/Sfio_t/tprintf.c000644 151361 151361 00000026426 07432503332 016115 0ustar00kpvkpv000000 000000 #include "sftest.h" typedef struct _coord_ { int x; int y; } Coord_t; Coord_t Coord; #if __STD_C coordprint(Sfio_t* f, Void_t* v, Sffmt_t* fe) #else coordprint(f, v, fe) Sfio_t* f; Void_t* v; Sffmt_t* fe; #endif { char type[128]; Coord_t* cp; char* s; if(fe->fmt != 'c') return -1; cp = va_arg(fe->args,Coord_t*); memcpy(type,fe->t_str,fe->n_str); type[fe->n_str] = 0; s = *((char**)v) = sfprints(type,cp->x,cp->y); fe->fmt = 's'; fe->size = strlen(s); fe->flags |= SFFMT_VALUE; return 0; } int OXcount; #if __STD_C OXprint(Sfio_t* f, Void_t* v, Sffmt_t* fe) #else OXprint(f, v, fe) Sfio_t* f; Void_t* v; Sffmt_t* fe; #endif { OXcount += 1; switch(fe->fmt) { case 'd' : *((int*)v) = 10; fe->flags |= SFFMT_VALUE; return 0; case 'O' : fe->fmt = 'o'; *((int*)v) = 11; fe->flags |= SFFMT_VALUE; return 0; case 'X' : fe->fmt = 'x'; *((int*)v) = 12; fe->flags |= SFFMT_VALUE; return 0; } return 0; } #if __STD_C abprint(Sfio_t* f, Void_t* v, Sffmt_t* fe) #else abprint(f, v, fe) Sfio_t* f; Void_t* v; Sffmt_t* fe; #endif { switch(fe->fmt) { case 'a' : fe->fmt = 'u'; return 0; case 'b' : fe->fmt = 'd'; return 0; case 'y' : /* test return value of extension function */ fe->size = 10; fe->fmt = 's'; return 0; case 'Y' : /* terminate format processing */ default : return -1; } } #if __STD_C intarg(Sfio_t* f, Void_t* val, Sffmt_t* fe) #else intarg(f, val, fe) Sfio_t* f; Void_t* val; Sffmt_t* fe; #endif { static int i = 1; *((int*)val) = i++; fe->flags |= SFFMT_VALUE; return 0; } #if __STD_C shortarg(Sfio_t* f, Void_t* val, Sffmt_t* fe) #else shortarg(f, val, fe) Sfio_t* f; Void_t* val; Sffmt_t* fe; #endif { static short i = -2; *((short*)val) = i++; fe->size = sizeof(short); fe->flags |= SFFMT_VALUE; return 0; } #if __STD_C transarg(Sfio_t* f, Void_t* val, Sffmt_t* fe) #else transarg(f, val, fe) Sfio_t* f; Void_t* val; Sffmt_t* fe; #endif { switch(fe->fmt) { case 'D' : fe->fmt = 'd'; return 0; case 'O' : fe->fmt = 'o'; return 0; case 'F' : fe->fmt = 'f'; return 0; case 'S' : fe->fmt = 's'; return 0; case 'C' : fe->fmt = 'c'; return 0; default : return -1; } } #if __STD_C void stkprint(char* buf, int n, char* form, ...) #else void stkprint(buf,n,form,va_alist) char* buf; int n; char* form; va_dcl #endif { va_list args; Sffmt_t fe; #if __STD_C va_start(args,form); #else va_start(args); #endif fe.form = form; va_copy(fe.args,args); fe.extf = NIL(Sffmtext_f); fe.eventf = NIL(Sffmtevent_f); sfsprintf(buf,n,"%! %d %d",&fe,3,4); va_end(args); } MAIN() { char buf1[1024], buf2[1024], *list[4], *s; double x=0.0051; int i, j; long k; Sffmt_t fe; Sfio_t* f; f = sfopen(NIL(Sfio_t*), tstfile(0), "w+"); sfsetbuf(f,buf1,10); sfprintf(f,"%40s\n","0123456789"); sfsprintf(buf2,sizeof(buf2),"%40s","0123456789"); sfseek(f,(Sfoff_t)0,0); if(!(s = sfgetr(f,'\n',1)) ) terror("Failed getting string\n"); if(strcmp(s,buf2) != 0) terror("Failed formatting %%s\n"); sfsprintf(buf1,sizeof(buf1),"%4d %4o %4x", 10, 11, 11); sfsprintf(buf2,sizeof(buf2),"%2$4d %1$4o %1$4x", 11, 10); if(strcmp(buf1,buf2) != 0) terror("Failed testing $position\n"); sfsprintf(buf1,sizeof(buf1),"%d %1$d %.*d %1$d", 10, 5, 300); sfsprintf(buf2,sizeof(buf2),"%d %1$d %3$.*2$d %1$d", 10, 5, 300); if(strcmp(buf1,buf2) != 0) terror("Failed testing $position with precision\n"); fe.version = SFIO_VERSION; fe.form = NIL(char*); fe.extf = OXprint; fe.eventf = NIL(Sffmtevent_f); sfsprintf(buf1,sizeof(buf1),"%4d %4o %4x %4o %4x", 10, 11, 12, 11, 10); sfsprintf(buf2,sizeof(buf2),"%!%2$4d %3$4O %4$4X %3$4O %2$4x", &fe); if(strcmp(buf1,buf2) != 0) terror("Failed testing $position2\n"); if(OXcount != 3) terror("Failed OXprint called wrong number of times %d\n",OXcount); sfsprintf(buf1,sizeof(buf1),"%6.2f",x); if(strcmp(buf1," 0.01") != 0) terror("%%f rounding wrong\n"); fe.version = SFIO_VERSION; fe.form = NIL(char*); fe.extf = abprint; fe.eventf = NIL(Sffmtevent_f); sfsprintf(buf1,sizeof(buf1),"%%sX%%d%..4u %..4d9876543210",-1,-1); sfsprintf(buf2,sizeof(buf2),"%!%%sX%%d%..4a %..4b%y%Yxxx", &fe, -1, -1, "9876543210yyyy" ); if(strcmp(buf1,buf2) != 0) terror("%%!: Extension function failed1\n"); fe.form = NIL(char*); fe.extf = intarg; sfsprintf(buf1,sizeof(buf1),"%d %d%",1,2); sfsprintf(buf2,sizeof(buf2),"%!%d %d%",&fe); if(strcmp(buf1,buf2) != 0) terror("%%!: Extension function failed2\n"); fe.form = NIL(char*); sfsprintf(buf1,sizeof(buf1),"%d %d%%",3,4); sfsprintf(buf2,sizeof(buf2),"%!%d %d%%",&fe); if(strcmp(buf1,buf2) != 0) terror("%%!: Extension function failed3\n"); fe.form = NIL(char*); fe.extf = shortarg; sfsprintf(buf1,sizeof(buf1),"%hu %ho %hi %hu %ho %hd", -2, -1, 0, 1, 2, 3); sfsprintf(buf2,sizeof(buf2),"%!%u %o %i %u %o %d",&fe); if(strcmp(buf1,buf2) != 0) terror("%%!: Extension function failed4\n"); /* test extf translation */ fe.form = NIL(char*); fe.extf = transarg; sfsprintf(buf1,sizeof(buf1),"%d %o %f %s %c", -1, -1, -1., "s", 'c'); sfsprintf(buf2,sizeof(buf2),"%!%D %O %F %S %C",&fe, -1, -1, -1., "s", 'c'); if(strcmp(buf1,buf2) != 0) terror("%%!: Extension function failed5\n"); k = 1234567890; sfsprintf(buf1,sizeof(buf1),"%I*d",sizeof(k),k); if(strcmp(buf1,"1234567890") != 0) terror("%%I*d failed\n"); Coord.x = 5; Coord.y = 7; sfsprintf(buf1,sizeof(buf1),"%d %d",Coord.x,Coord.y); fe.form = NIL(char*); fe.extf = coordprint; sfsprintf(buf2,sizeof(buf2),"%!%(%d %d)c",&fe,&Coord); if(strcmp(buf1,buf2) != 0) terror("%%()c `%s' != `%s'\n", buf1, buf2); sfsprintf(buf1,sizeof(buf1),"%d %d %d %d",1,2,3,4); stkprint(buf2,sizeof(buf2),"%d %d",1,2); if(strcmp(buf1,buf2) != 0) terror("%%!: Stack function failed\n"); sfsprintf(buf1,sizeof(buf1),"% +G",-1.2345); sfsprintf(buf2,sizeof(buf2),"-1.2345"); if(strcmp(buf1,buf2) != 0) terror("Failed %% +G test\n"); if(sizeof(int) == 4 && sizeof(short) == 2) { char* s = sfprints("%hx",0xffffffff); if(!s || strcmp(s,"ffff") != 0) terror("Failed %%hx test\n"); s = sfprints("%I2x",0xffffffff); if(!s || strcmp(s,"ffff") != 0) terror("Failed %%I2x test\n"); } if(sizeof(int) == 4 && sizeof(char) == 1) { char* s = sfprints("%hhx",0xffffffff); if(!s || strcmp(s,"ff") != 0) terror("Failed %%hhx test\n"); s = sfprints("%I1x",0xffffffff); if(!s || strcmp(s,"ff") != 0) terror("Failed %%I1x test\n"); } sfsprintf(buf1,sizeof(buf1),"%#..16d",-0xabc); if(strcmp(buf1,"-16#abc") != 0) terror("Failed %%..16d test\n"); sfsprintf(buf1,sizeof(buf1),"%#..16lu",(long)0xc2c01576); if(strcmp(buf1,"16#c2c01576") != 0) terror("Failed %%..16u test\n"); sfsprintf(buf1,sizeof(buf1),"%0#4o",077); if(strcmp(buf1,"0077") != 0) terror("Failed %%0#4o test\n"); sfsprintf(buf1,sizeof(buf1),"%0#4x",0xc); if(strcmp(buf1,"0x000c") != 0) terror("Failed %%0#4x test\n"); sfsprintf(buf1,sizeof(buf1),"%c%c%c",'a','b','c'); if(strcmp(buf1,"abc") != 0) terror("Failed %%c test\n"); sfsprintf(buf1,sizeof(buf1),"%.4c",'a'); if(strcmp(buf1,"aaaa") != 0) terror("Failed %%.4c test\n"); sfsprintf(buf1,sizeof(buf1),"%hd%c%hd%ld",(short)1,'1',(short)1,1L); if(strcmp(buf1,"1111") != 0) terror("Failed %%hd test\n"); sfsprintf(buf1,sizeof(buf1),"%10.5E",(double)0.0000625); if(strcmp(buf1,"6.25000E-05") != 0) terror("Failed %%E test\n"); sfsprintf(buf1,sizeof(buf1),"%10.5f",(double)0.0000625); if(strcmp(buf1," 0.00006") != 0) terror("Failed %%f test\n"); sfsprintf(buf1,sizeof(buf1),"%10.5G",(double)0.0000625); if(strcmp(buf1," 6.25E-05") != 0) terror("Failed %%G test\n"); list[0] = "0"; list[1] = "1"; list[2] = "2"; list[3] = 0; sfsprintf(buf1,sizeof(buf1),"%..*s", ',', list); if(strcmp(buf1,"0,1,2") != 0) terror("Failed %%..*s test\n"); sfsprintf(buf1,sizeof(buf1),"%.2.*c", ',', "012"); if(strcmp(buf1,"00,11,22") != 0) terror("Failed %%..*c test\n"); sfsprintf(buf1,sizeof(buf1),"A%.0dB", 0); if(strcmp(buf1,"AB") != 0) terror("Failed precision+0 test\n"); sfsprintf(buf1,sizeof(buf1),"A%.0dB", 1); if(strcmp(buf1,"A1B") != 0) terror("Failed precision+1 test\n"); sfsprintf(buf1,sizeof(buf1),"A%4.0dB", 12345); if(strcmp(buf1,"A12345B") != 0) terror("Failed exceeding width test\n"); sfsprintf(buf1,sizeof(buf1),"A%3dB",33); if(strcmp(buf1,"A 33B") != 0) terror("Failed justification test\n"); sfsprintf(buf1,sizeof(buf1),"A%04dB",-1); if(strcmp(buf1,"A-001B") != 0) terror("Failed zero filling test\n"); sfsprintf(buf1,sizeof(buf1),"A%+04dB",1); if(strcmp(buf1,"A+001B") != 0) terror("Failed signed and zero-filled test\n"); sfsprintf(buf1,sizeof(buf1),"A% .0dB", -1); if(strcmp(buf1,"A-1B") != 0) terror("Failed blank and precision test\n"); sfsprintf(buf1,sizeof(buf1),"A%+ .0dB", 1); if(strcmp(buf1,"A+1B") != 0) terror("Failed +,blank and precision test\n"); sfsprintf(buf1,sizeof(buf1),"A%010.2fB", 1.2); if(strcmp(buf1,"A0000001.20B") != 0) terror("Failed floating point and zero-filled test\n"); sfsprintf(buf1,sizeof(buf1),"A%-010.2fB", 1.2); if(strcmp(buf1,"A1.20 B") != 0) terror("Failed floating point and left justification test\n"); sfsprintf(buf1,sizeof(buf1),"A%-#XB", 0xab); if(strcmp(buf1,"A0XABB") != 0) terror("Failed %%-#X conversion test\n"); #if !_ast_intmax_long { Sflong_t ll; char buf[128]; char* s = sfprints("%#..16llu",~((Sflong_t)0)); sfsscanf(s,"%lli", &ll); if(ll != (~((Sflong_t)0)) ) terror("Failed inverting printf/scanf Sflong_t\n"); s = sfprints("%#..18lld",~((Sflong_t)0)); sfsscanf(s,"%lli", &ll); if(ll != (~((Sflong_t)0)) ) terror("Failed inverting printf/scanf Sflong_t\n"); s = sfprints("%#..lli",~((Sflong_t)0)); sfsscanf(s,"%lli", &ll); if(ll != (~((Sflong_t)0)) ) terror("Failed inverting printf/scanf Sflong_t\n"); sfsprintf(buf,sizeof(buf), "%llu", (~((Sflong_t)0)/2) ); s = sfprints("%Iu", (~((Sflong_t)0)/2) ); if(strcmp(buf,s) != 0) terror("Failed conversion with I flag\n"); if(sizeof(Sflong_t)*8 == 64) { s = sfprints("%I64u",(~((Sflong_t)0)/2) ); if(strcmp(buf,s) != 0) terror("Failed conversion with I64 flag\n"); } } #endif i = (int)(~(~((unsigned int)0) >> 1)); s = sfprints("%d",i); j = atoi(s); if(i != j) terror("Failed converting highbit\n"); for(i = -10000; i < 10000; i += 123) { s = sfprints("%d",i); j = atoi(s); if(j != i) terror("Failed integer conversion\n"); } /* test I flag for strings */ { char *ls[3]; ls[0] = "0123456789"; ls[1] = "abcdefghij"; ls[2] = 0; s = sfprints("%I5..*s", 0, ls); if(strcmp(s, "01234abcde") != 0) terror("Failed I flag with %%s\n"); } /* test justification */ sfsprintf(buf1,sizeof(buf1),"%-10.5s","abcdefghij"); sfsprintf(buf2,sizeof(buf2),"%*.5s",-10,"abcdefghij"); if(strcmp(buf1,buf2) != 0) terror("Left-justification is wrong\n"); sfsprintf(buf1,sizeof(buf1),"%10.5s","abcdefghij"); sfsprintf(buf2,sizeof(buf2),"%*.5s",10,"abcdefghij"); if(strcmp(buf1,buf2) != 0) terror("Justification is wrong\n"); /* testing x/open compliant with respect to precision */ sfsprintf(buf1, sizeof(buf1), "%.d %.hi %.lo %.f %.e %.g %.g %.g %.g %.g %.s %.d %.hi %.lo|", 1345, 1234, 1234567890, 321.7654321, 321.7654321, -0.01, 0.01, 1e-5, 1.4, -1.4, "test-string", 0, 0, 0L); if(strcmp(buf1,"1345 1234 11145401322 322 3e+02 -0.01 0.01 1e-05 1 -1 |") ) terror("Precision not set to zero as required after a dot"); TSTEXIT(0); } strcmp(buf1,buf2) != 0) terror("Justification is wrong\n"); /* testing x/open compliant with respect to precision */ sfsprintf(buf1, sizeof(buf1), "%.d %.hi %.lo %.f %.e %.g %.g %.g %.g %.g %.s %.d %.hi %.lo|", 1345, 1234, src/lib/sfio/Sfio_t/talign.c000644 151361 151361 00000002035 07235635535 015707 0ustar00kpvkpv000000 000000 #include "sftest.h" static ssize_t Read; static int Count; #if __STD_C ssize_t readf(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t readf(f,buf,n,disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { Count += 1; Read += (n = sfrd(f,buf,n,disc)); return n; } Sfdisc_t Disc = {readf, (Sfwrite_f)0, (Sfseek_f)0, (Sfexcept_f)0, (Sfdisc_t*)0}; MAIN() { Sfio_t* f; int i; char* s; char buf[1024], rbuf[128*1024]; if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "w")) ) terror("Opening to write\n"); for(i = 0; i < sizeof(buf); ++i) buf[i] = 'a' + (i%26); for(i = 0; i < 1024; ++i) if(sfwrite(f,buf,sizeof(buf)) != sizeof(buf) ) terror("Write error\n"); sfclose(f); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "r")) ) terror("Opening to read\n"); sfsetbuf(f,rbuf,sizeof(rbuf)); sfdisc(f,&Disc); for(i = 0;; i += 64) { sfseek(f,(Sfoff_t)i,0); if(!(s = sfreserve(f,619,1)) ) break; sfread(f,s,64); } if(Read != 1024*sizeof(buf) ) terror("Count=%d Read=%d\n", Count, Read); TSTEXIT(0); } = 0; i < sizeof(buf); ++i) buf[i] = 'a' + (i%26); for(i = 0; i < 1024; ++i) if(sfwrite(f,buf,sizeof(buf)) != sizeof(buf) ) terror("Write error\n"); sfclose(f); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "r")) ) terror("Opening to read\n"); sfsetbuf(f,rbuf,sizeof(rbuf)); sfdisc(f,&Disc); for(i = 0;; i += 64) { sfseek(f,(Sfoff_t)i,0); if(!(s = sfreserve(f,619,1)) ) break; sfread(f,s,64); } if(Read != 1024*sizeof(buf) ) terror("Count=%d Read=%d\n", Csrc/lib/sfio/Sfio_t/tsync.c000644 151361 151361 00000010234 07235635536 015572 0ustar00kpvkpv000000 000000 #include "sftest.h" /* this tests to see if SF_SYNC is raised at the right time */ static int Count = 0; #if __STD_C static except(Sfio_t* f, int type, Void_t* arg, Sfdisc_t* disc) #else static except(f, type, arg, disc) Sfio_t* f; int type; Void_t* arg; Sfdisc_t* disc; #endif { if(type == SF_SYNC && (int)arg == 1) Count += 1; return 0; } Sfdisc_t Disc = { NIL(Sfread_f), NIL(Sfwrite_f), NIL(Sfseek_f), except }; /* this tests to see if data is written correctly */ typedef struct _mydisc_s { Sfdisc_t disc; int sync; } Mydisc_t; #if __STD_C int event(Sfio_t* f, int type, Void_t* arg, Sfdisc_t* disc) #else int event(f,type,arg,disc) Sfio_t* f; int type; Void_t* arg; Sfdisc_t* disc; #endif { if(type == SF_SYNC) ((Mydisc_t*)disc)->sync = (int)arg; return 0; } #if __STD_C ssize_t newline(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t newline(f,buf,n,disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { size_t i; char* s = (char*)buf; if(((Mydisc_t*)disc)->sync) /* for synchronization, write everything */ i = n; else /* only write entire lines */ { for(i = n; i > 0; --i) if(s[i-1] == '\n') break; if(i <= 0) return 0; } return sfwr(f,buf,i,disc); } Mydisc_t Mydisc = {{(Sfread_f)0, newline, (Sfseek_f)0, event, (Sfdisc_t*)0}, 0}; MAIN() { int p1[2], p2[2]; int n, dupf2; Sfoff_t off; char buf[1024], *s; Sfio_t *f, *f1, *f2; /* redirect stdout to a pipe */ if(pipe(p1) < 0 || close(1) < 0 || dup(p1[1]) != 1) terror("Creating pipe1\n"); /* redirect stdin to a pipe with some input */ close(0); if(pipe(p2) < 0) terror("Creating a pipe2\n"); if(write(p2[1],"foo\n",4) != 4) terror("Writing to pipe\n"); close(p2[1]); sfsetbuf(sfstdout,buf,sizeof(buf)); if(sfset(sfstdout,0,0)&SF_LINE) terror("Line mode on unexpectedly\n"); sfset(sfstdout,SF_SHARE,0); if(sfeof(sfstdin) ) terror("Premature eof\n"); if(sferror(sfstdout) ) terror("Weird error1\n"); if((off = sfmove(sfstdin,sfstdout,(Sfoff_t)SF_UNBOUND,-1)) != 4) terror("Wrong # of bytes %lld\n", off); if(!sfeof(sfstdin) ) terror("Should be eof\n"); if(sferror(sfstdout) ) terror("Weird error2\n"); if(sfpurge(sfstdout) < 0) terror("Purging stdout\n"); if(!(f1 = sfopen(NIL(Sfio_t*), tstfile(0), "w")) ) terror("Opening file to write\n"); if(!(f2 = sfopen(NIL(Sfio_t*), tstfile(0),"r")) ) terror("Opening file to read\n"); sfset(f1,SF_IOCHECK,1); sfdisc(f1,&Disc); sfsetbuf(f1,NIL(char*),4); if(Count != 1) terror("No sfsync call?"); Count = 0; sfputc(f1,'1'); sfputc(f1,'2'); sfputc(f1,'3'); sfputc(f1,'4'); sfputc(f1,'5'); sfputc(f1,'6'); if((n = sfread(f2,buf,sizeof(buf))) != 4) terror("Did not get all data n=%d\n", n); if(Count != 0) terror("Should not have seen SF_SYNC yet\n"); sfsync(NIL(Sfio_t*)); if(Count != 1) terror("Should have seen SF_SYNC\n"); sfputc(f1,'7'); sfputc(f1,'8'); sfsync(f1); if(Count != 2) terror("Bad SF_SYNC count=%d, expecting 2\n", Count); sfsync(f1); if(Count != 3) terror("Bad SF_SYNC count=%d, expecting 3\n", Count); sfdisc(f1,NIL(Sfdisc_t*)); if(Count != 3) terror("Bad SF_SYNC count=%d, expecting 3\n", Count); sfseek(f2,(Sfoff_t)0,0); sfgetc(f2); if((off = sftell(f2)) != 1) terror("Wrong sfseek location %lld\n", off); sfsync(0); if((off = (Sfoff_t)lseek(sffileno(f2), (off_t)0, 1)) != 1) terror("Wrong lseek location %lld\n", off); dupf2 = dup(sffileno(f2)); sfclose(f2); if((off = (Sfoff_t)lseek(dupf2, (off_t)0, 1)) != 1) terror("Wrong lseek location %lld\n", off); /* test to see if data is written correctly */ if(!(f = sfopen(NIL(Sfio_t*), tstfile(0),"w+"))) terror("Creating temp file\n"); sfdisc(f, &Mydisc.disc); sfsetbuf(f, NIL(Void_t*), 95); sfset(f, SF_IOCHECK, 1); for(n = 0; n < 10; ++n) if(sfwrite(f, "0123456789\n", 11) != 11) terror("Bad sfwrite call"); if(sfwrite(f, "abcdefgh", 8) != 8) terror("Bad sfwrite call 2"); if(sfsync(f) != 0) terror("Bad sfsync call"); if(sfseek(f,(Sfoff_t)0,0) != (Sfoff_t)0) terror("Bad sfseek call"); for(n = 0; n < 10; ++n) { if(!(s = sfgetr(f, '\n', SF_STRING)) ) terror("Bad sfgetr call"); if(strcmp(s, "0123456789") != 0) terror("Bad read data"); } TSTEXIT(0); } Void_t*), 95); sfset(f, SF_IOCHECK, 1); for(n = 0; n < 10; ++n) if(sfwrite(f, "0123456789\n", 11) != 11) terror("Bad sfwrite call"); if(sfwrite(f, "abcdefgh", 8) != 8) terror("Bad sfwrite call 2"); if(sfsync(f) != 0) terror("Bad sfsync call"); if(sfseek(f,(Sfoff_t)0,0) != (Sfoff_t)0) terror("Bad sfseek call"); for(n = 0; n < 10; ++nsrc/lib/sfio/Sfio_t/tpipe.c000644 151361 151361 00000005665 07235635536 015567 0ustar00kpvkpv000000 000000 #include "sftest.h" #include #if __STD_C void alrmf(int sig) #else void alrmf(sig) int sig; #endif { terror("Blocking somewhere until alarm went off\n"); } MAIN() { int fd[2]; Sfio_t *fr, *fw; char *s; int i, j, n; char buf[1024]; if(sfnew(sfstdout,buf,sizeof(buf),SF_UNBOUND,SF_STRING|SF_WRITE) != sfstdout) terror("Reopen sfstdout\n"); if(pipe(fd) < 0) terror("Can't open pipe\n"); if(!(fr = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND,fd[0],SF_READ)) || !(fw = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND,fd[1],SF_WRITE)) ) terror("Can't open stream\n"); signal(SIGALRM,alrmf); sfwrite(fw,"0123456789",10); alarm(4); if(sfread(fr,buf,10) != 10) terror("Can't read data from pipe\n"); sfwrite(fw,"0123456789",10); if(sfmove(fr,fw,(Sfoff_t)10,-1) != 10) terror("sfmove failed\n"); alarm(0); sfpurge(fw); sfclose(fw); sfpurge(fr); sfclose(fr); if(pipe(fd) < 0) terror("Can't open pipe2\n"); if(!(fr = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND,fd[0],SF_READ)) || !(fw = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND,fd[1],SF_WRITE)) ) terror("Can't open stream\n"); sfset(fr,SF_SHARE|SF_LINE,1); sfset(fw,SF_SHARE,1); if(sfwrite(fw,"1\n2\n3\n",6) != 6) terror("sfwrite failed0\n"); i = j = -1; if(sfscanf(fr,"%d%d\n%n",&i,&j,&n) != 2 || i != 1 || j != 2 || n != 4) terror("sfscanf failed0\n"); if(sfscanf(fr,"%d\n%n",&i,&n) != 1 || i != 3 || n != 2) terror("sfscanf failed1\n"); if(sfwrite(fw,"123\n",4) != 4) terror("sfwrite failed\n"); if(!(s = sfreserve(fr,4,0)) ) terror("sfreserve failed\n"); sfputr(fw,"abc",'\n'); if(sfmove(fr,fw,(Sfoff_t)1,'\n') != 1) terror("sfmove failed\n"); if(!(s = sfgetr(fr,'\n',1)) || strcmp(s,"abc") != 0) terror("sfgetr failed\n"); if(sfwrite(fw,"111\n222\n333\n444\n",16) != 16) terror("Bad write to pipe\n"); if(!(s = sfgetr(fr,'\n',1)) ) terror("sfgetr failed\n"); if(strcmp(s,"111") != 0) terror("sfgetr got wrong string\n"); if(sfmove(fr,sfstdout,(Sfoff_t)2,'\n') != 2) terror("sfmove failed2\n"); sfputc(sfstdout,0); if(strcmp("222\n333\n",buf) != 0) terror("sfmove got wrong data\n"); if(sfmove(fr,NIL(Sfio_t*),(Sfoff_t)1,'\n') != 1) terror("sfmove failed\n"); if(sfwrite(fw,"0123456789",11) != 11) terror("Bad write to pipe2\n"); if(!(s = sfreserve(fr,11,0)) ) terror("Bad peek size %d, expect 11\n",sfvalue(fr)); if(strncmp(s,"0123456789",10) != 0) terror("Bad peek str %s\n",s); /* test for handling pipe error */ if(pipe(fd) < 0) terror("Can't create pipe"); close(fd[0]); if(!(fw = sfnew(NIL(Sfio_t*),NIL(Void_t*),sizeof(buf),fd[1],SF_WRITE)) ) terror("Can't open stream"); signal(SIGPIPE,SIG_IGN); /* avoid dying by sigpipe */ for(i = 0; i < sizeof(buf); ++i) buf[i] = 'a'; buf[sizeof(buf)-1] = 0; for(i = 0; i < 3; ++i) { signal(SIGALRM,alrmf); /* do this to avoid infinite loop */ alarm(4); sfprintf(fw, "%s\n", buf); /* this should not block */ alarm(0); } TSTEXIT(0); } r handling pipe error */ if(pipe(fd) < 0) terror("Can't create pipe"); src/lib/sfio/Sfio_t/tdisc.c000644 151361 151361 00000010573 07235635535 015545 0ustar00kpvkpv000000 000000 #include "sftest.h" #if __STD_C ssize_t upper(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t upper(f,buf,n,disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { size_t i; char* s = (char*)buf; if(sfgetc(f) >= 0) terror("Stream should be locked\n"); if((n = sfrd(f,buf,n,disc)) <= 0) return n; for(i = 0; i < n; ++i) if(s[i] >= 'a' && s[i] <= 'z') s[i] = (s[i]-'a') + 'A'; return n; } #if __STD_C ssize_t wupper(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t wupper(f,buf,n,disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { size_t i; char* s = (char*)buf; if(sfputc(f,0) >= 0) terror("Stream should be locked2\n"); for(i = 0; i < n; ++i) if(s[i] >= 'a' && s[i] <= 'z') s[i] = (s[i]-'a') + 'A'; return sfwr(f,buf,n,disc); } #if __STD_C ssize_t lower(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t lower(f,buf,n,disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { size_t i; char* s = (char*)buf; if(sfgetc(f) >= 0) terror("Stream should be locked\n"); if((n = sfrd(f,buf,n,disc)) <= 0) return n; for(i = 0; i < n; ++i) if(s[i] >= 'A' && s[i] <= 'Z') s[i] = (s[i]-'A') + 'a'; return n; } #if __STD_C ssize_t once(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t once(f,buf,n,disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { static int called = 0; if(!called) { called = 1; strcpy(buf,"123456"); return 6; } else { terror("Discipline is called twice\n"); return -1; } } static char External[128], *Enext = External; #if __STD_C ssize_t external(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t external(f,buf,n,disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { memcpy(Enext,buf,n); Enext += n; return n; } Sfdisc_t Wdisc = {(Sfread_f)0, wupper, (Sfseek_f)0, (Sfexcept_f)0, (Sfdisc_t*)0}; Sfdisc_t Udisc = {upper, wupper, (Sfseek_f)0, (Sfexcept_f)0, (Sfdisc_t*)0}; Sfdisc_t Ldisc = {lower, (Sfwrite_f)0, (Sfseek_f)0, (Sfexcept_f)0, (Sfdisc_t*)0}; Sfdisc_t Odisc = {once, (Sfwrite_f)0, (Sfseek_f)0, (Sfexcept_f)0, (Sfdisc_t*)0}; Sfdisc_t Edisc = {(Sfread_f)0, external, (Sfseek_f)0, (Sfexcept_f)0, (Sfdisc_t*)0}; MAIN() { Sfio_t *f, *fs; char *l, *u, *s; int n, r; int flags; char buf[1024], low[64], up[64]; sfsetbuf(sfstdin,buf,sizeof(buf)); flags = sfset(sfstdin,0,0); sfdisc(sfstdin,&Ldisc); if(sfset(sfstdin,0,0) != flags) terror("Flags changed after discipline setting\n"); l = low; strcpy(l, "abcdefghijklmnopqrstuvwxyz"); u = up; strcpy(u, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); n = strlen(l); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0),"w+"))) terror("Creating temp file\n"); if((r = sfwrite(f,l,n)) != n) terror("Writing data %d\n",r); sfsync(f); sfseek(f,(Sfoff_t)0,0); sfdisc(f,&Udisc); if(!(s = sfreserve(f,n,0)) ) terror("Reading string1\n"); if(strncmp(s,u,n) != 0) { s[n-1] = 0; terror("Input1=%s, Expect=%s\n",s,u); } sfseek(f,(Sfoff_t)0,0); sfdisc(f,&Ldisc); if(!(s = sfreserve(f,n,0)) ) terror("Reading string2\n"); if(strncmp(s,l,n) != 0) { s[n-1] = 0; terror("Input2=%s, Expect=%s\n",s,l); } if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "w+")) ) terror("Opening file\n"); sfdisc(f,&Wdisc); if(sfputr(f,low,'\n') < 0) terror("Writing data\n"); if(sfseek(f,(Sfoff_t)0,0) != 0) terror("Seeking\n"); if(!(s = sfgetr(f,'\n',1))) terror("sfgetr\n"); if(strcmp(s,up) != 0) terror("Bad data\n"); /* read-once discipline */ if(!(f = sfopen(NIL(Sfio_t*), tstfile(0),"r")) ) terror("Opening file\n"); sfdisc(f,&Odisc); if(!(s = sfreserve(f,SF_UNBOUND,1)) ) terror("Sfreserve failed1\n"); if(sfvalue(f) != 6) terror("Wrong reserved length1\n"); sfread(f,s,3); if(!(fs = sfopen(NIL(Sfio_t*),"abcdef","s")) ) terror("String open failed\n"); sfstack(f,fs); if(!(s = sfreserve(f,SF_UNBOUND,1)) ) terror("Sfreserve failed2\n"); if(sfvalue(f) != 6) terror("Wrong reserved length2\n"); sfread(f,s,6); if(!(s = sfreserve(f,SF_UNBOUND,1)) ) terror("sfreserve failed 3\n"); if(sfvalue(f) != 3) terror("Wrong reserved length3\n"); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0),"w")) ) terror("Opening file to write\n"); sfdisc(f,&Edisc); if(sfwrite(f, "one", 3) != 3) terror("Bad sfwrite\n"); if(sfwr(f, "two", 4, NIL(Sfdisc_t*)) != 4) terror("Bad sfwr\n"); if(strcmp(External,"onetwo") != 0) terror("Bad call of sfwr\n"); TSTEXIT(0); } ) != 6) terror("Wrong reserved length2\n"); sfread(f,s,6); if(!(s = sfreserve(f,SF_UNBOUND,1)) ) terror("sfreserve failed 3\n"src/lib/sfio/Sfio_t/tpopenrw.c000644 151361 151361 00000002365 07235635536 016316 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t* f; char buf[1024], *s; int n; #ifdef DEBUG Sfio_t* logf = sfopen(0,"LOG","a"); sfsetbuf(logf,NIL(Void_t*),0); #endif if(argc > 1) { /* coprocess only */ while((s = sfreserve(sfstdin,-1,0)) ) { #ifdef DEBUG sfwrite(logf, s, sfvalue(sfstdin)); #endif sfwrite(sfstdout, s, sfvalue(sfstdin)); } return 0; } /* make coprocess */ if(!(f = sfpopen(NIL(Sfio_t*), sfprints("%s -p",argv[0]), "r+"))) terror("Opening for read/write\n"); for(n = 0; n < 10; ++n) { sfsprintf(buf,sizeof(buf),"Line %d",n); sfputr(f,buf,'\n'); if(!(s = sfgetr(f,'\n',1))) terror("Did not read back line\n"); if(strcmp(s,buf) != 0) terror("Input=%s, Expect=%s\n",s,buf); } if(sfputr(f,"123456789",'\n') != 10) terror("Bad write"); if(sfread(f,buf,3) != 3) terror("Did not get data back\n"); if(strncmp(s,"123",3) != 0) terror("Wrong data\n"); if(sfwrite(f,"aaa",3) != 3 || sfputc(f,'\n') != '\n') terror("Fail on write\n"); if(!(s = sfgetr(f,'\n',1)) ) terror("Should have gotten 456789\n"); if(strcmp(s,"456789") != 0) terror("Wrong data2\n"); if(!(s = sfgetr(f,'\n',1)) ) terror("Should have gotten aaa\n"); if(strcmp(s,"aaa") != 0) terror("Wrong data3\n"); sfclose(f); TSTEXIT(0); } ) terror("Bad write"); if(sfread(f,buf,3) != 3) terror("Did not get data back\n"); if(strncmp(s,"123",3) != 0) terror("Wrong data\n"); if(sfwrite(f,"aaa",3) != 3 || sfputc(f,'\n') != '\n') terror("Fail on write\n"); if(!(s = sfgetr(f,'\n',1)) ) terrosrc/lib/sfio/Sfio_t/tsize.c000644 151361 151361 00000006562 07235635536 015601 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t *f, *f2; char* s; int i, n; char buf[16*1024]; if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "w+") ) ) terror("Can't open file\n"); if(sfnputc(f,'a',1000) != 1000) terror("Writing\n"); if(sfseek(f,(Sfoff_t)0,0) != 0) terror("Seeking\n"); if((n = (int)sfsize(f)) != 1000) terror("Wrong size %d\n", n); if(!(f2 = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND, sffileno(f),SF_WRITE)) ) terror("Can't open stream\n"); if(sfseek(f2,(Sfoff_t)1999,0) != (Sfoff_t)1999) terror("Seeking2\n"); sfputc(f2,'b'); sfsync(f2); if((n = (int)sfsize(f2)) != 2000) terror("Wrong size2 %d\n", n); if((n = (int)sfsize(f)) != 1000) terror("Wrong size3 %d\n", n); sfputc(f,'a'); sfset(f,SF_SHARE,1); if((n = (int)sfsize(f)) != 2000) terror("Wrong size4 %d\n", n); if(!(f = sfopen(f,NIL(char*),"srw")) ) terror("Can't open string stream\n"); sfwrite(f,"0123456789",10); if(sfsize(f) != 10) terror("String size is wrong1\n"); sfseek(f,(Sfoff_t)19,0); if(sfsize(f) != 10) terror("String size is wrong2\n"); sfputc(f,'a'); if(sfsize(f) != 20) terror("String size is wrong3\n"); sfseek(f,(Sfoff_t)0,0); if(sfsize(f) != 20) terror("String size is wrong4\n"); sfseek(f,(Sfoff_t)0,0); if(!(s = sfreserve(f,SF_UNBOUND,1)) && sfvalue(f) != 20) terror("String size is wrong5\n"); sfread(f,s,5); if(sfsize(f) != 20) terror("String size is wrong6\n"); sfwrite(f,"01234567890123456789",20); if(sfsize(f) != 25) terror("String size is wrong7\n"); strcpy(buf,"0123456789"); if(!(f = sfopen(f,buf,"s+")) ) terror("Can't open string stream2\n"); if(sfset(f,0,0)&SF_MALLOC) terror("SF_MALLOC should not have been set\n"); if(sfsize(f) != 10) terror("String size is wrong8\n"); sfread(f,buf,5); if((n = (int)sfwrite(f,"0123456789",10)) != 5) terror("Write wrong amount %d\n", n); if(sfsize(f) != 10) terror("String size is wrong9\n"); if(!(f = sfopen(f, tstfile(0),"w") ) ) terror("Reopening file1\n"); for(i = 0; i < 10000; ++i) if(sfputc(f,'0'+(i%10)) != '0'+(i%10) ) terror("sfputc failed\n"); if(!(f = sfopen(f, tstfile(0),"r+") ) ) terror("Reopening file2\n"); if(sfsize(f) != 10000) terror("Bad size of file1\n"); sfsetbuf(f,buf,1024); for(i = 0; i < 20; ++i) if(!sfreserve(f,100,0)) terror("Reserve failed\n"); s = buf+1024; for(i = 0; i < 20; ++i) s[i] = '0' + i%10; sfseek(f,(Sfoff_t)(10000-10),0); if(sfwrite(f,s,20) != 20) terror("Write failed\n"); if(sfsize(f) != 10010) terror("Bad size of file2\n"); sfseek(f,(Sfoff_t)0,0); for(i = 0; i < 10; ++i) { if(!(s = sfreserve(f,1001,0)) ) terror("Reserve failed2\n"); if(s[0] != '0'+i) terror("Bad data1\n"); } for(n = 0; n < 1001; ++n) if(s[n] != ((n+i-1)%10 + '0') ) terror("Bad data\n"); /* test to see if a string stream extends ok during writes */ s = malloc(5); f = sfnew((Sfio_t*)0, (void*)s, 5, -1, SF_STRING|SF_READ|SF_WRITE|SF_MALLOC); if(!f) terror("Can't create string stream\n"); if(sfwrite(f,"01",2) != 2) terror("Bad write to string stream\n"); if(sfwrite(f,"2345678",7) != 7) terror("Bad write to string stream2\n"); if(sfputc(f,0) != 0) terror("sfputc failed\n"); if(sfseek(f, (Sfoff_t)0, 0) != 0) terror("sfseek failed\n"); if((n = (int)sfread(f, buf, 100)) != 10) terror("sfread gets wrong amount of data %d\n", n); if(strcmp(buf, "012345678") != 0) terror("Get wrong data\n"); TSTEXIT(0); } AD|SF_WRITE|SF_MALLOC); if(!f) terror("Can't create string stream\n"); if(sfwrite(f,"01",2) != 2) terror("Bad write to string stream\n")src/lib/sfio/Sfio_t/tmprocess.c000644 151361 151361 00000005500 07411272067 016441 0ustar00kpvkpv000000 000000 #include "sftest.h" /* Test to see if multiple writers to the same file create ** a consistent set of records. */ #define N_PROC 3 #define N_REC 1000 #define B_SIZE 1024 #if __STD_C static ssize_t inspect(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) #else static ssize_t inspect(f, buf, n, disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { int w, k; char* s; Sfio_t* sf; if(*((char*)buf + n-1) != '\n') terror("Not writing a whole record\n"); sf = sfnew(NIL(Sfio_t*),(Void_t*)buf,n,-1,SF_STRING|SF_READ); while((s = sfgetr(sf,'\n',0)) ) { w = sfvalue(sf)-1; if(s[0] != s[w-1]-1) terror("Bad record\n"); k = (s[2]-'0')*10 + (s[3]-'0'); if(k != w) terror("Expect %d, get %d\n",k,w); } sfclose(sf); if((w = write(sffileno(f),buf,n)) != (int)n) terror("Write %d returns %d\n",n,w); return w; } static Sfdisc_t Disc[N_PROC]; MAIN() { ssize_t size[N_PROC][N_REC]; int count[N_PROC]; char record[N_PROC][128], *s; int i, r, n; Sfio_t* f; Sfio_t* fa[N_PROC]; char buf[N_PROC][B_SIZE], b[N_PROC][128]; unsigned long u; /* create pseudo-random record sizes */ u = 1; for(i = 0; i < N_PROC; ++i) for(r = 0; r < N_REC; ++r) { u = u * 0x63c63cd9L + 0x9c39c33dL; size[i][r] = (ssize_t)(u%63) + 16; } /* records for different processes */ for(i = 0; i < N_PROC; ++i) for(r = 0; r < 128; ++r) record[i][r] = '0' + 2*i; /* create file */ if(!(f = sfopen(NIL(Sfio_t*),tstfile(0),"w+")) ) terror("Opening temporary file %s\n", tstfile(0)); for(i = 0; i < N_PROC; ++i) { fa[i] = sfopen(NIL(Sfio_t*), tstfile(0), "a"); sfsetbuf(fa[i], (Void_t*)buf[i], sizeof(buf[i])); sfset(fa[i], SF_WHOLE, 1); Disc[i].writef = inspect; sfdisc(fa[i], &Disc[i]); } /* fork processes */ for(i = 0; i < N_PROC; ++i) { switch(fork() ) { case -1: terror("Creating process %d\n", i); case 0 : for(r = 0; r < N_REC; ++r) { n = size[i][r]; s = b[i]; memcpy(s,record[i],n-1); s[1] = '('; s[2] = ((n-1)/10) + '0'; s[3] = ((n-1)%10) + '0'; s[4] = ')'; s[n-2] = s[0] + 1; s[n-1] = '\n'; sfwrite(fa[i],s,n); } sfsync(fa[i]); return 0; } } for(i = 0; i < N_PROC; ++i) { wait(&r); count[i] = 0; } n = 0; while((s = sfgetr(f,'\n',0)) ) { n += 1; if((i = s[0] - '0') < 0 || (i%2) != 0 || (i /= 2) >= N_PROC ) terror("%d: Wrong record type\n", n); r = sfvalue(f); if(s[r-2] != s[0]+1) terror("%d: process%d, number=%d\n", n, i, count[i]); for(r -= 3; r > 4; --r) if(s[r] != s[0]) terror("%d: process%d, count=%d\n", n, i, count[i]); if(sfvalue(f) != size[i][count[i]]) terror("%d: process%d number=%d expected size=%d read size=%d\n", n, i, count[i], size[i][count[i]], sfvalue(f)); count[i] += 1; } for(i = 0; i < N_PROC; ++i) if(count[i] != N_REC) terror("Bad count%d %d\n", i, count[i]); TSTEXIT(0); } d type\n", n); r = sfvalue(f); if(s[r-2] != s[0]+1) terror("%d: process%d, number=%d\n", n, i, count[i]); for(r -= 3; r > 4; --r) if(s[r] != s[0]) terror("%d: process%d, countsrc/lib/sfio/Sfio_t/tpublic.c000644 151361 151361 00000006236 07327057743 016103 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t* f; Sfio_t* g; char* s; char buf[1024]; int n, i; if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "w")) ) terror("Can't open file to write\n"); sfputr(f,"1111",'\n'); sfputr(f,"2222",'\n'); sfputr(f,"3333",'\n'); sfputr(f,"4444",'\n'); if(!(f = sfopen(f, tstfile(0), "r")) ) terror("Can't open file to read1\n"); if(!(g = sfnew(NIL(Sfio_t*), NIL(Void_t*),(size_t)SF_UNBOUND,dup(sffileno(f)),SF_READ)) ) terror("Can't open file to read2\n"); sfset(f,SF_SHARE|SF_PUBLIC,1); sfset(g,SF_SHARE|SF_PUBLIC,1); if(!(s = sfgetr(f,'\n',1)) || strcmp(s,"1111") != 0) terror("Wrong data1\n"); sfsync(f); if(!(s = sfgetr(g,'\n',1)) || strcmp(s,"2222") != 0) terror("Wrong data2\n"); sfsync(g); if(!(s = sfgetr(f,'\n',1)) || strcmp(s,"3333") != 0) terror("Wrong data3\n"); sfsync(f); if(!(s = sfgetr(g,'\n',1)) || strcmp(s,"4444") != 0) terror("Wrong data4\n"); sfsync(g); sfclose(f); sfclose(g); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "r+")) ) terror("Can't open file to write2\n"); if(!(g = sfnew(NIL(Sfio_t*), NIL(Void_t*),(size_t)SF_UNBOUND,dup(sffileno(f)),SF_READ)) ) terror("Can't open file to read3\n"); sfset(f,SF_SHARE|SF_PUBLIC,1); sfset(g,SF_SHARE|SF_PUBLIC,1); if(sfputr(f,"1111",'\n') <= 0) terror("bad write1\n"); sfsync(f); if(!(s = sfgetr(g,'\n',1)) || strcmp(s,"2222") != 0) terror("Wrong data5\n"); sfsync(g); if(sfputr(f,"3333",'\n') <= 0) terror("bad write2\n"); sfsync(f); if(!(s = sfgetr(g,'\n',1)) || strcmp(s,"4444") != 0) terror("Wrong data6\n"); sfsync(g); if(!(f = sfopen(f, tstfile(0), "w")) ) terror("Can't open file to write3\n"); for(i = 0; i < sizeof(buf); ++i) buf[i] = 0; for(i = 0; i < 256; ++i) if(sfwrite(f,buf,sizeof(buf)) != sizeof(buf)) terror("Writing buffer0\n"); for(i = 0; i < sizeof(buf); ++i) buf[i] = 1; for(i = 0; i < 256; ++i) if(sfwrite(f,buf,sizeof(buf)) != sizeof(buf)) terror("Writing buffer1\n"); if(!(f = sfopen(f, tstfile(0), "r")) ) terror("Can't open file to read3\n"); sfset(f,SF_SHARE|SF_PUBLIC,1); for(n = 0; n < 256; ++n) { if(!(s = sfreserve(f,sizeof(buf),0)) ) terror("Can't reserve buffer1\n"); for(i = 0; i < sizeof(buf); ++i) if(s[i] != 0) terror("Bad data1\n"); } for(n = 0; n < 256; ++n) { if(!(s = sfreserve(f,sizeof(buf),0)) ) terror("Can't reserve buffer2\n"); for(i = 0; i < sizeof(buf); ++i) if(s[i] != 1) terror("Bad data2\n"); } if((s = sfreserve(f,1,0)) ) terror("Reading beyond eof\n"); if(!(f = sfopen(f, tstfile(0), "w")) ) terror("Can't open to write\n"); if(sfwrite(f,"aaa\nbbb\nccc\n",12) != 12) terror("Can't write\n"); sfclose(f); if(sfopen(sfstdin,tstfile(0),"r") != sfstdin) terror("Can't open file as sfstdin\n"); if((n = (int)sfmove(sfstdin,NIL(Sfio_t*),(Sfoff_t)SF_UNBOUND,'\n')) != 3) terror("sfmove wrong number of lines %d\n",n); if(sfseek(sfstdin,(Sfoff_t)0,0) != 0) terror("Can't seek back to 0\n"); if((n = (int)sfmove(sfstdin,NIL(Sfio_t*),(Sfoff_t)2,'\n')) != 2) terror("sfmove2 wrong number of lines %d\n",n); if((n = (int)sfmove(sfstdin,NIL(Sfio_t*),(Sfoff_t)SF_UNBOUND,'\n')) != 1) terror("sfmove3 wrong number of lines %d\n",n); TSTEXIT(0); } ) != sfstdin) terror("Can't open file as sfstdin\n"); if((n = (int)sfmove(sfstdin,NIL(Sfio_t*),(Sfoff_t)SF_UNBOUND,'\n')) != 3) terror("sfmove wrong number of lines %d\n",n); if(sfseek(sfstdin,(Sfoff_t)0,0) != 0) terror("Can't seek back to 0\n"); if((n = (int)sfmove(sfstdin,NIL(Sfio_t*),(Sfoff_t)2,'\n')) != 2) terror("sfmove2 wrong number ofsrc/lib/sfio/Sfio_t/tmmap2read.c000644 151361 151361 00000002226 07235635535 016467 0ustar00kpvkpv000000 000000 #define _SFIO_H_ONLY 1 #include "sftest.h" /* This test causes mmap() to fail so that read() must be used. On a system such as BSDI, malloc uses mmap() so if mmap() fails, not much else will work. In such a case, we make this test automatically success. */ static int Success = 1; #if __STD_C void* mmap(void* addr, size_t size, int x, int y, int z, Sfoff_t offset) #else void* mmap() #endif { if(Success) TSTEXIT(0); return (void*)(-1); } MAIN() { Sfio_t* f; char buf[1024], buf2[1024], *data; int n, r; /* test to see if malloc() winds up calling mmap() */ if(!(data = (char*)malloc(8*1024)) ) terror("Malloc failed\n"); free(data); Success = 0; /* our real work */ if(!(f = sfopen(NIL(Sfio_t*), tstfile(0),"w")) ) terror("Can't open to write\n"); for(n = 0; n < sizeof(buf); ++n) buf[n] = '0' + (n%10); for(n = 0; n < 10; ++n) sfwrite(f,buf,sizeof(buf)); if(!(f = sfopen(f, tstfile(0),"r")) ) terror("Can't open to read\n"); for(n = 0; n < 10; ++n) { if((r = sfread(f,buf2,sizeof(buf))) != sizeof(buf)) terror("Bad read size=%d\n",r); if(strncmp(buf,buf2,sizeof(buf)) != 0) terror("Get wrong data\n"); } TSTEXIT(0); } ss = 0; /* our real work */ if(!(f = sfopen(NIL(Sfio_t*), tstfile(0),"w")) ) terror("Can't open to write\n"); for(n = 0; n < sizeof(buf); ++n) buf[n] = '0' + (n%10); for(n = 0; n < 10; ++n) sfwrite(f,buf,sizeof(buf)); if(!(f = sfopen(f, tstfile(0),"r")) ) terror("Can't open to read\n"); for(n = 0; n < 10; ++n) { if((r = sfread(f,buf2,sizeofsrc/lib/sfio/Sfio_t/tpkrd.c000644 151361 151361 00000001530 07235635536 015555 0ustar00kpvkpv000000 000000 #include "sftest.h" #include static int Fd[2]; #if __STD_C void alarmhandler(int sig) #else void alarmhandler(sig) int sig; #endif { if(write(Fd[1],"01234\n56789\n",12) != 12) terror("Writing to pipe\n"); } MAIN() { char* s; char buf[1024]; if(pipe(Fd) < 0) terror("Can't make pipe\n"); if(sfnew(sfstdin,NIL(Void_t*),(size_t)SF_UNBOUND,Fd[0],SF_READ) != sfstdin) terror("Can't renew stdin\n"); sfset(sfstdin,SF_SHARE,1); if(sfpkrd(Fd[0],(Void_t*)buf,10,-1,1000,1) >= 0) terror("There isn't any data yet\n"); signal(SIGALRM,alarmhandler); alarm(2); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"01234") != 0) terror("Expecting 01234\n"); if(sfstdin->next < sfstdin->endb) terror("Sfgetr read too much\n"); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"56789") != 0) terror("Expecting 56789\n"); TSTEXIT(0); } ize_t)SF_UNBOUND,Fd[0],SF_READ) != sfstdin) terror("Can't renew stdin\n"); sfset(sfstdin,SF_SHARE,1); if(sfpkrd(Fd[0],(Void_t*)buf,10,-1,1000,1) >= 0) terror("Thsrc/lib/sfio/Sfio_t/tstkpk.c000644 151361 151361 00000001712 07235635536 015753 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t* f; char buf[1024]; char* s; int fd[2]; close(0); if(pipe(fd) < 0 || fd[0] != 0) terror("Making pipe\n"); strcpy(buf,"1234567890"); if(!(f = sfopen(NIL(Sfio_t*),buf,"s"))) terror("Opening string stream\n"); if(!sfstack(f,sfstdin)) terror("Stacking\n"); if(write(fd[1],"ab",2) != 2) terror("Writing ab to pipe\n"); if(!(s = sfreserve(f,SF_UNBOUND,1)) || sfvalue(f) != 2) terror("Peeking size1 = %d but should be 2\n", sfvalue(f)); sfread(f,s,0); if(strncmp(s,"ab",2) != 0) terror("Wrong data1\n"); if(write(fd[1],"cd",2) != 2) terror("Writing cd to pipe\n"); close(fd[1]); if(!(s = sfreserve(f,4,0)) ) terror("Peeking size2 = %d but should be 4\n", sfvalue(f)); if(strncmp(s,"abcd",4) != 0) terror("Wrong data2\n"); if(!(s = sfreserve(f,10,0)) ) terror("Peeking size3 = %d but should be 10\n", sfvalue(f)); if(strncmp(s,"1234567890",10) != 0) terror("Wrong data3\n"); TSTEXIT(0); } %d but should be 2\n", sfvalue(f)); sfread(f,s,0); src/lib/sfio/Sfio_t/tnotify.c000644 151361 151361 00000001724 07244644345 016130 0ustar00kpvkpv000000 000000 #include "sftest.h" static int Type; #if __STD_C static void notify(Sfio_t* f, int type, int fd) #else static void notify(f, type, fd) Sfio_t* f; int type; int fd; #endif { switch(Type = type) { case SF_NEW: case SF_CLOSING: case SF_SETFD: case SF_READ: case SF_WRITE: return; default: terror("Unexpected nofity-type: %d\n",type); } } MAIN() { Sfio_t* f; int fd; sfnotify(notify); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "w")) && Type != SF_NEW) terror("Notify did not announce SF_NEW event\n"); fd = sffileno(f); close(fd+5); if(sfsetfd(f,fd+5) != fd+5 || Type != SF_SETFD) terror("Notify did not announce SF_SETFD event\n"); if(sfclose(f) < 0 || Type != SF_CLOSING) terror("Notify did not announce SF_CLOSING event\n"); if(sfputc(sfstdin,'a') >= 0 || Type != SF_WRITE) terror("Notify did not announce SF_WRITE event\n"); if(sfgetc(sfstdout) >= 0 || Type != SF_READ) terror("Notify did not announce SF_READ event\n"); TSTEXIT(0); } EW) terror("Notify did not announce SF_NEWsrc/lib/sfio/Sfio_t/tstring.c000644 151361 151361 00000004637 07235635536 016136 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t *f; int n; char *s, *os, *endos; char buf[8192]; os = "123\n456\n789\n"; if(!(f = sfopen((Sfio_t*)0,os,"s"))) terror("Opening string\n"); endos = os + strlen(os); while((s = sfgetr(f,'\n',0)) ) { if(s != os) terror("Did not get string\n"); os += sfvalue(f); } if(os != endos) terror("Did not match everything\n"); if(sfgetc(f) >= 0 || !sfeof(f)) terror("Stream should have exhausted\n"); if(!(f = sfopen(f,(char*)0,"s+"))) terror("Opening string for r/w\n"); for(n = 0; n < 26; ++n) if((sfputc(f,'a'+n)) != 'a'+n) terror("Output\n"); if(sfgetc(f) >= 0) terror("Read a non-existent byte\n"); sfseek(f,(Sfoff_t)0,0); if(!(s = sfreserve(f,26,0)) ) terror("Didnot get the right amount of data\n"); for(n = 0; n < 26; ++n) if((sfputc(f,'a'+n)) != 'a'+n) terror("Output2\n"); sfseek(f,(Sfoff_t)2,0); if(!(s = sfreserve(f,50,0)) ) terror("Didnot get the right amount of data2\n"); if(!(f = sfopen(f,(char*)0,"s+"))) terror("Opening string for r/w\n"); sfset(f,SF_READ,0); sfseek(f,(Sfoff_t)0,0); if(!(s = sfreserve(f,SF_UNBOUND,1)) || (n = sfvalue(f)) <= 0 || sfwrite(f,s,0) != 0) terror("Buffer size should be positive\n"); sfseek(f,(Sfoff_t)(n+8192),0); sfseek(f,(Sfoff_t)0,0); if(!(s = sfreserve(f,SF_UNBOUND,1)) || sfvalue(f) != (n+8192) || sfwrite(f,s,0) != 0) terror("Bad buffer size\n"); if(!(f = sfopen(f,(char*)0,"s+"))) terror("Opening string for r/w\n"); if(sfwrite(f,buf,sizeof(buf)) != sizeof(buf)) terror("Can't write large buffer\n"); if(!(f = sfopen((Sfio_t*)0,(char*)0,"s+"))) terror("Opening string for r/w\n"); sfset(f,SF_READ,0); for(n = 0; n < 16*1024; ++n) { if((n%1024) == 0) { Sfoff_t a = sfseek(f,(Sfoff_t)1024,1); sfputc(f,'a'); sfseek(f,(Sfoff_t)(-1025),1); } sfputc(f,'a'); } sfseek(f,(Sfoff_t)0,0); if(!(s = sfreserve(f,SF_UNBOUND,1)) || sfvalue(f) != n+1024 || sfwrite(f,s,0) != 0) terror("Wrong buffer size\n"); while(n-- > 0) if(*s++ != 'a') terror("Wrong data\n"); if(!(f = sfopen((Sfio_t*)0,(char*)0,"s+"))) terror("Opening r/w string\n"); for(n = 0; n < 10; n++) sfputc(f,'a'+n); sfputc(f,'\n'); sfseek(f,(Sfoff_t)0,0); for(n = 0; n <= 11 ; ++n) if(sfgetc(f) != 'a'+n) break; if(n != 10) terror("Get too many\n"); if(sfgetc(f) >= 0) terror("Reading non-existent data\n"); if(!sfeof(f)) terror("Didn't get eof\n"); TSTEXIT(0); } | sfwrite(f,s,0) != 0) terror("Wrong buffer size\n"); while(n-- > 0) if(*s++ != 'a') src/lib/sfio/Sfio_t/ttmpfile.c000644 151361 151361 00000002223 07235635536 016255 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t* f; if(!(f = sftmp(1025))) terror("Can't open temp file\n"); if(sffileno(f) >= 0) terror("Attempt to create file detected\n"); if(sfputc(f,0) < 0) terror("Can't write to temp file\n"); if(sffileno(f) >= 0) terror("Attempt to create file detected\n"); if(sfclose(f) < 0) terror("Can't close temp file\n"); if(sffileno(f) >= 0) terror("Attempt to create file detected\n"); if(!(f = sftmp(8))) terror("Can't open temp file\n"); if(sffileno(f) >= 0) terror("Attempt to create file detected\n"); sfdisc(f,NIL(Sfdisc_t*)); if(sffileno(f) < 0) terror("Real file wasn't created\n"); if(sfclose(f) < 0) terror("Can't close temp file\n"); if(!(f = sftmp(8))) terror("Can't open temp file\n"); if(sffileno(f) >= 0) terror("Attempt to create file detected\n"); if(sfseek(f, (Sfoff_t)8, SEEK_SET) < 0) terror("Can't seek on temp file\n"); if(sffileno(f) >= 0) terror("Attempt to create file detected\n"); if(sfputc(f,0) < 0) terror("Can't write to temp file\n"); if(sffileno(f) < 0) terror("Real file wasn't created\n"); if(sfclose(f) < 0) terror("Can't close temp file\n"); TSTEXIT(0); } 0) terror("Can't close temp file\n"); if(!(f = sftmp(8))) terror("Can't open temp file\n"); if(sffileno(f) >= 0) terror("Attempt to create file detected\n"); if(sfseek(f, (Sfoff_t)8, SEEK_SET) < 0) terror("Can't seek on temp file\n"); if(sffileno(f) >= 0) terror("Attempt to create file detected\n"); if(sfputc(f,0) < 0) terror("Can't write to tesrc/lib/sfio/Sfio_t/tmwrite.c000644 151361 151361 00000003463 07235635536 016133 0ustar00kpvkpv000000 000000 #include "sftest.h" /* see if multiple writers do create a consistent set of records. */ #define N_WRITER 3 #define N_RECORD 10000 static long vrandom() { #define LOWBITS ((~((unsigned long)0)) >> 1) static unsigned long hash = 0xdeadbeef; return (hash = hash*0xbadbeef + 0xdeadbeef)&LOWBITS; } MAIN() { ssize_t size[N_WRITER][N_RECORD]; int count[N_WRITER]; char record[N_WRITER][128], *s; Sfio_t* fw[N_WRITER]; Sfio_t* fr; int i, r, done; /* create random record sizes */ for(i = 0; i < N_WRITER; ++i) for(r = 0; r < N_RECORD; ++r) size[i][r] = (ssize_t)(vrandom()%64) + 2; /* records for different processes */ for(i = 0; i < N_WRITER; ++i) for(r = 0; r < 128; ++r) record[i][r] = '0'+i; /* create file */ fr = sfopen(NIL(Sfio_t*),tstfile(0),"w+"); /* create records */ for(i = 0; i < N_WRITER; ++i) { fw[i] = sfopen(NIL(Sfio_t*),tstfile(0),"a"); count[i] = 0; } for(done = 0; done < N_WRITER; ) { i = (int)(vrandom()%N_WRITER); if(count[i] < N_RECORD) { r = size[i][count[i]]; if(!(s = sfreserve(fw[i],r,1)) || sfvalue(fw[i]) < r ) terror("sfreserve fails in process %d\n", i); memcpy(s,record[i],r-1); s[r-1] = '\n'; sfwrite(fw[i],s,r); if((count[i] += 1) == N_RECORD) { done += 1; sfclose(fw[i]); } } } for(i = 0; i < N_WRITER; ++i) count[i] = 0; while((s = sfgetr(fr,'\n',0)) ) { if((i = s[0] - '0') < 0 || i >= N_WRITER) terror("Wrong record type\n"); for(r = sfvalue(fr)-2; r > 0; --r) if(s[r] != s[0]) terror("Bad record%d, count=%d\n", i, count[i]); if(sfvalue(fr) != size[i][count[i]]) terror("Record%d count=%d size=%d sfvalue=%d\n", i, count[i], size[i][count[i]], sfvalue(fr)); count[i] += 1; } for(i = 0; i < N_WRITER; ++i) if(count[i] != N_RECORD) terror("Bad count%d %d\n", i, count[i]); TSTEXIT(0); } = 0; while((s = sfgetr(fr,'\n',0)) ) { if((i = s[0] - '0') < 0 || i >= N_WRITER) terror("Wrong record type\n"); for(r = sfvalue(fr)-2; r > 0; --r) if(s[r] != s[0]) terror("Bad record%d, cosrc/lib/sfio/Sfio_t/tresize.c000644 151361 151361 00000004122 07235635536 016116 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t* f; char buf[8*1024]; int i; Sfoff_t s; /* test file resizing */ #if _lib_ftruncate if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "w")) ) terror("Can't open file %s", tstfile(0)); for(i = 0; i < sizeof(buf); ++i) buf[i] = '1'; for(i = 0; i < 1024; ++i) if(sfwrite(f, buf, sizeof(buf)) != sizeof(buf) ) terror("Can't write data"); if(sfclose(f) < 0) terror("Can't sync/close file"); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "r+")) ) terror("Can't open file %s again", tstfile(0)); if(sfsize(f) != (s = 1024*sizeof(buf)) ) terror("Bad file size"); if(sfresize(f, s + sizeof(buf)) < 0) terror("Can't resize file"); if(sfsize(f) != s+sizeof(buf)) terror("Bad file size"); sfseek(f, s, 0); if(sfread(f,buf,sizeof(buf)) != sizeof(buf)) terror("Can't read data"); for(i = 0; i < sizeof(buf); ++i) if(buf[i] != 0) terror("Bad data"); sfclose(f); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "r+")) ) terror("Can't open file %s again", tstfile(0)); if(sfsize(f) != s+sizeof(buf)) terror("Bad file size"); if(sfresize(f, s) < 0) terror("Can't resize file"); sfclose(f); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "r+")) ) terror("Can't open file %s again", tstfile(0)); if(sfsize(f) != s) terror("Bad file size"); #endif /* test resizing string stream */ if(!(f = sfopen(NIL(Sfio_t*), NIL(char*), "rws")) ) terror("Can't open string stream"); for(i = 0; i < sizeof(buf); ++i) buf[i] = '1'; for(i = 0; i < 1024; ++i) if(sfwrite(f, buf, sizeof(buf)) != sizeof(buf) ) terror("Can't write data"); if(sfsize(f) != (s = 1024*sizeof(buf)) ) terror("Bad stream size"); if(sfresize(f, s + sizeof(buf)) < 0) terror("Can't resize stream"); if(sfsize(f) != s+sizeof(buf)) terror("Bad stream size"); if(sfseek(f, s, 0) != s) terror("seek failed"); if(sfread(f,buf,sizeof(buf)) != sizeof(buf)) terror("Can't read data"); for(i = 0; i < sizeof(buf); ++i) if(buf[i] != 0) terror("Bad data"); if(sfresize(f, s) < 0) terror("Can't resize stream"); if(sfsize(f) != s) terror("Bad stream size"); TSTEXIT(0); } s = 1024*sizeof(buf)) ) terror("Bad stream size"); if(sfresize(f, s + sizeof(buf)) < 0) terror("Can't resize stream"); if(sfsize(f) != s+sizeof(buf)) terror("Bad stream size"); if(sfseek(f, s, 0) != s) terror("seek failed"); if(sfread(f,buf,sizeof(buf)) != sizeof(buf)) terror("Can't read data"); for(i = 0; i < sizeof(buf); ++i) if(buf[i] != 0) terror("Bad data"); if(sfresize(f, s) < 0) terror("Can't src/lib/sfio/Sfio_t/runtest000755 151361 151361 00000003773 07103372262 015716 0ustar00kpvkpv000000 000000 ######################################################################### # Invocation arguments are: # # -lLIBRARY: a library to be linked with, e.g., -lpthread # # -ut: testing the uni-threaded libsfio.a (default) # # -mt: testing the multi-threaded libsfio-mt.a # # -v: verbose, print the compilation command # # -c: continue testing after a test fails # # -whatever_else: bad argument, will be ignored. # # tests: test cases to be run. If no test specified, # # all tests will be run. # # # # Below are a few example test runs: # # runtest: # # tests the uni-threaded library. # # runtest -mt: # # tests the multi-threaded library on a BSD platform. # # runtest -mt -lpthread: # # tests the multi-threaded library on a # # Linux/Irix/Solaris platform. # # runtest -mt -lcma: # # tests the multi-threaded library on a HPUX platform. # # The argument -lcma defines the thread library. # # # # Written by Kiem-Phong Vo # ######################################################################### verbose=0 exit_on_fail=1 files="" LIBS="../libsfio.a" HDRS="-I../Stdio_s -I.." DEFS="-Dvt_threaded=0" XLIBS="" while test "$1" != "" do case $1 in -l*) XLIBS="$XLIBS $1"; ;; -v) verbose=1; ;; -c) exit_on_fail=0; ;; -ut) LIBS="../libsfio.a"; DEFS="-Dvt_threaded=0"; ;; -mt) LIBS="../libsfio-mt.a ../../vthread/libvthread.a"; DEFS="-Dvt_threaded=1"; ;; -*) echo "Hmm, unknown argument: $1"; ;; *) files="${files} $1"; ;; esac shift done if test "$CC" = ""; then CC="cc"; fi if test "$files" = "" then files="*.c" fi LIBS="$LIBS $XLIBS" if test "$verbose" = 1 then echo "Compiler invocation: $CC -g $DEFS $HDRS xxx.c $LIBS -o ./t" fi for i in $files do echo "-- $i:" status="" if $CC -g $DEFS $HDRS $i $LIBS -o ./t then if ./t then rm ./t; status=Passed else status=Failed fi else status="Not compiled" fi echo " $status" if test "$status" != "Passed" then if test "$exit_on_fail" = "1"; then exit; fi fi done sac src/lib/sfio/Sfio_t/tmultiple.c000644 151361 151361 00000005072 07235635536 016455 0ustar00kpvkpv000000 000000 #include "sftest.h" /* Test multiple processes reading/writing from same file ** descriptor. */ MAIN() { char* s; if(argc > 1) { if(strcmp(argv[1],"-r") == 0) /* doing sfgetr */ { if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line2") != 0) terror("Coprocess getr did not get Line2\n"); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line3") != 0) terror("Coprocess getr did not get Line3\n"); } else /* doing sfmove */ { Sfio_t* f = sfopen(NIL(Sfio_t*),NIL(char*),"swr"); if(!f) terror("Can't open string stream\n"); if(sfmove(sfstdin,f,(Sfoff_t)2,'\n') != 2) terror("Coprocess sfmove failed\n"); sfseek(f,(Sfoff_t)0,0); if(!(s = sfgetr(f,'\n',1)) || strcmp(s,"Line2") != 0) terror("Coprocess move did not get Line2\n"); if(!(s = sfgetr(f,'\n',1)) || strcmp(s,"Line3") != 0) terror("Coprocess move did not get Line3\n"); } TSTEXIT(0); } if(sfopen(sfstdout, tstfile(0), "w") != sfstdout ) terror("Opening file\n"); if(sfputr(sfstdout,"Line1",'\n') < 0 || sfputr(sfstdout,"Line2",'\n') < 0 || sfputr(sfstdout,"Line3",'\n') < 0 || sfputr(sfstdout,"Line4",'\n') < 0) terror("Writing data\n"); sfopen(sfstdout,"/dev/null","w"); /* testing coprocess calling sfgetr */ if(sfopen(sfstdin, tstfile(0),"r") != sfstdin) terror("Opening to read\n"); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line1") != 0) terror("Did not get Line1 for sfgetr\n"); sfsync(sfstdin); system(sfprints("%s -r",argv[0])); sfseek(sfstdin, (Sfoff_t)lseek(sffileno(sfstdin), (off_t)0, 1), 0); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line4") != 0) terror("Did not get Line4 for sfgetr\n"); /* testing coprocess calling sfmove */ if(sfopen(sfstdin, tstfile(0), "r") != sfstdin) terror("Opening to read\n"); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line1") != 0) terror("Did not get Line1 for sfmove\n"); sfsync(sfstdin); system(sfprints("%s -m",argv[0])); sfseek(sfstdin, (Sfoff_t)lseek(sffileno(sfstdin), (off_t)0, 1), 0); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line4") != 0) terror("Did not get Line4 for sfmove\n"); /* testing the head program */ #ifdef HEAD if(sfopen(sfstdin, tstfile(0), "r") != sfstdin) terror("Opening to read\n"); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line1") != 0) terror("Did not get Line1 for head\n"); sfsync(sfstdin); system("head -2 > /dev/null"); /* for testing the head program */ sfseek(sfstdin, (Sfoff_t)lseek(sffileno(sfstdin), (off_t)0, 1), 0); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line4") != 0) terror("Did not get Line4 for head\n"); #endif TSTEXIT(0); } "); /* testing the head program */ #ifdef HEAD if(sfopen(sfstdin, tstfile(0), "r") != sfstdin) terror("Opening to read\n"); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line1") != 0) terror("Did not get Line1 for head\n"); sfsync(sfstdin); system("head -2 > /dev/null"); /* for testing the head program */ sfseek(sfstdin, (Sfoff_t)lseek(sffileno(sfstdin), (off_t)0, 1), 0); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line4") != 0) terrosrc/lib/sfio/Sfio_t/tatexit.c000644 151361 151361 00000001575 07235635535 016123 0ustar00kpvkpv000000 000000 #include "sftest.h" /* test to see if files created in atexit functions work ok */ void ae() { Sfio_t* f = sfopen(NIL(Sfio_t*), tstfile(0), "w"); if(!f) terror("Can't create file"); if(sfwrite(f,"1234\n",5) != 5) terror("Can't write to file"); } #if __STD_C main(int argc, char** argv) #else main(argc, argv) int argc; char** argv; #endif { Sfio_t* f; if(argc <= 1) /* atexit function registered after some sfio access */ { if(!(f = sfopen(NIL(Sfio_t*), tstfile(1), "w")) ) terror("Can't create file"); if(sfwrite(f,"1234\n",5) != 5) terror("Can't write to file"); atexit(ae); system(sfprints("%s 1",argv[0])); } else /* atexit function registered before some sfio access */ { atexit(ae); if(!(f = sfopen(NIL(Sfio_t*), tstfile(1), "w")) ) terror("Can't create file"); if(sfwrite(f,"1234\n",5) != 5) terror("Can't write to file"); } TSTEXIT(0); } /* atexit function registered after some sfio access */ { if(!(f = sfopen(NIL(Sfio_t*), tstfile(1), "w")) ) terror("Can't creatsrc/lib/sfio/Sfio_t/tmode.c000644 151361 151361 00000002617 07235635536 015550 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t *f; if(argc > 1) { if(sfopen(sfstdin,argv[1],"r") != sfstdin) terror("Can't reopen stdin"); sfmove(sfstdin,sfstdout,(Sfoff_t)(-1),-1); return 0; } if(!(f = sfopen((Sfio_t*)0,tstfile(0),"w"))) terror("Opening to write\n"); if(sfputc(f,'a') != 'a') terror("sfputc\n"); if(sfgetc(f) >= 0) terror("sfgetc\n"); if(!(f = sfopen(f,tstfile(0),"r"))) terror("Opening to read\n"); if(sfgetc(f) != 'a') terror("sfgetc2\n"); if(sfputc(f,'b') >= 0) terror("sfputc2\n"); if(!(f = sfopen(f,tstfile(0),"r+"))) terror("Opening to read/write\n"); if(sfgetc(f) != 'a') terror("sfgetc3\n"); if(sfputc(f,'b') != 'b') terror("sfputc3\n"); if(sfclose(f) < 0) terror("sfclose\n"); if(!(f = sfpopen(NIL(Sfio_t*),sfprints("%s %s", argv[0], tstfile(0)),"r"))) terror("sfpopen\n"); if(sfgetc(f) != 'a') terror("sfgetc4\n"); if(sfgetc(f) != 'b') terror("sfgetc5\n"); if(sfgetc(f) >= 0) terror("sfgetc6\n"); if(!(f = sfopen(f,tstfile(0),"w")) ) terror("sfopen\n"); if(sfputc(f,'a') != 'a') terror("sfputc1\n"); sfsetfd(f,-1); if(sfputc(f,'b') >= 0) terror("sfputc2\n"); if(sfclose(f) < 0) terror("sfclose\n"); if(!(f = sfopen(NIL(Sfio_t*),tstfile(0),"a+")) ) terror("sfopen2\n"); sfset(f,SF_READ,0); if(!sfreserve(f,0,-1) ) terror("Failed on buffer getting\n"); if(sfvalue(f) <= 0) terror("There is no buffer?\n"); TSTEXIT(0); } terror("sfgetc5\n"); if(sfgetc(f) >= 0) terror("sfgetc6\n"); if(!(f = sfopen(f,tstfile(0),"w")) ) terror("src/lib/sfio/Sfio_t/twhole.c000644 151361 151361 00000002303 07411272067 015722 0ustar00kpvkpv000000 000000 #include "sftest.h" static int Count; static int Size; #if __STD_C ssize_t writef(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t writef(f,buf,n,disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { Count += 1; if((n % Size) != 0) terror("Wrong record size\n"); return write(sffileno(f),buf,n); } Sfdisc_t Disc = {(Sfread_f)0, writef, (Sfseek_f)0, (Sfexcept_f)0, (Sfdisc_t*)0}; MAIN() { Sfio_t* f; char buf[550]; int i; char* s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; Count = 0; Size = 52; if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "w")) ) terror("Opening to write\n"); sfsetbuf(f,buf,sizeof(buf)); sfset(f,SF_WHOLE,1); sfdisc(f,&Disc); for(i = 0; i < 100; ++i) if(sfwrite(f,s,52) != 52) terror("sfwrite failed\n"); sfclose(f); if(Count != 10) terror("Wrong number of writes1\n"); Count = 0; Size = 53; if(!(f = sfopen(NIL(Sfio_t*), tstfile(0),"w")) ) terror("Opening to write\n"); sfsetbuf(f,buf,sizeof(buf)); sfset(f,SF_WHOLE,1); sfdisc(f,&Disc); for(i = 0; i < 100; ++i) if(sfputr(f,s,'\n') != 53) terror("sfputr failed\n"); sfclose(f); if(Count != 10) terror("Wrong number of writes2\n"); TSTEXIT(0); } &Disc); for(i = 0; i < 100; ++i) if(sfwrite(f,s,52) != 52) terror("sfwrite failed\n"); sfclose(f); if(Count != 10) terror("Wrong number of writes1\n"); Count = 0; Size = 53; if(!(f = sfopen(NIL(Sfio_t*), tstfile(0),"w")) ) terror("Opening to write\n"); sfsetbuf(f,buf,sizeof(buf)); sfset(f,SF_WHOLsrc/lib/sfio/Sfio_t/thole.c000644 151361 151361 00000002062 07235635535 015544 0ustar00kpvkpv000000 000000 #include "sftest.h" /* Test for /dev/null and hole-preserving code */ MAIN() { Sfio_t* null; Sfio_t* f; int k, n; static char buf[256*1024], b[256*1024]; if(!(null = sfopen(NIL(Sfio_t*),"/dev/null","w")) ) terror("Opening /dev/null"); sfsetbuf(null,NIL(char*),(size_t)SF_UNBOUND); if(!(f = sfopen(NIL(Sfio_t*), tstfile(0), "w+")) ) terror("Creating %s", tstfile(0)); sfwrite(f,"1234",4); sfseek(f,(Sfoff_t)1,0); sfsync(f); sfsetfd(null,-1); sfsetfd(null,sffileno(f)); sfsync(null); sfseek(f,(Sfoff_t)0,0); if(sfread(f,buf,4) != 4 || strncmp(buf,"1234",4) != 0) terror("Bad data"); for(k = 0; k < sizeof(buf); ++k) buf[k] = 1; for(k = sizeof(buf)/4; k < sizeof(buf)/2; ++k) /* make a big hole */ buf[k] = 0; if(!(f = sfopen(f, tstfile(0), "w+")) ) terror("Creating %s", tstfile(0)); n = sizeof(buf)-127; if(sfwrite(f,buf,n) != n) terror("Writing large buffer"); sfseek(f,(Sfoff_t)0,0); if(sfread(f,b,n) != n) terror("Reading large buffer"); for(k = 0; k < n; ++k) if(b[k] != buf[k]) terror("Bad data"); TSTEXIT(0); } strncmp(buf,"1234",4) != 0) terror("Bad data"); for(k = 0; k < sizeof(buf); ++k) buf[k] = 1; for(k = sizeof(buf)/4; k < sizeof(buf)/2; ++k) /* make a big hole */ buf[k] = 0; if(!(f = sfopen(f, tstfile(0), "w+")) ) terror("Creating %s", tstfile(0)); n = sizeof(buf)-127; if(sfwrite(f,buf,n) != n) terror("Writing large buffer"); sfseek(f,(Sfoff_t)0,0); if(sfread(f,b,n) != n) terror("Reading large buffer"); for(k = 0; k < n; ++k) if(b[k] src/lib/sfio/Sfio_t/tpoll.c000644 151361 151361 00000004255 07411271726 015563 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { Sfio_t *f, *str, *fr, *fw, *sf[2]; int c; char *s; int fd[2]; if(argc > 1) { while((s = sfgetr(sfstdin, '\n', 1)) ) { sfputr(sfstdout, s, '\n'); sfsync(sfstdout); } exit(0); } if(!(str = sfopen(NIL(Sfio_t*),"abc","s")) ) terror("Opening string stream\n"); if(pipe(fd) < 0) terror("pipe failed\n"); if(!(fr = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND, fd[0],SF_READ)) ) terror("Opening read pipe stream\n"); if(!(fw = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND, fd[1],SF_WRITE)) ) terror("Opening write pipe stream\n"); sf[0] = fr; sf[1] = str; if((c = sfpoll(sf,2,0)) != 1 || sf[0] != str) terror("Only str should be available c=%d\n",c); sf[0] = fr; if(sfpoll(sf,1,0) != 0 ) terror("Pipe stream should not be ready\n"); sfputc(fw,'a'); sfsync(fw); sf[0] = fr; if(sfpoll(sf,1,0) != 1 ) terror("Pipe read should be ready\n"); if((c = sfgetc(fr)) != 'a') terror("Didn't get back right data\n"); sf[0] = fr; sf[1] = str; if(sfpoll(sf,2,0) != 1 || sf[0] != str) terror("Only str should be available2\n"); sf[0] = fw; sf[1] = str; if(sfpoll(sf,2,0) != 2) terror("Both str&pipe write should be available\n"); if(pipe(fd) < 0) terror("Can't create pipe\n"); if(!(fr = sfnew(fr,NIL(Void_t*),(size_t)SF_UNBOUND,fd[0],SF_READ)) ) terror("Can't create stream\n"); if(write(fd[1],"0123456789",10) != 10) terror("Can't write to pipe\n"); if(sfpoll(&fr,1,1000) != 1) terror("Data should be available\n"); s = sfprints("%s 1", argv[0]); if(!(f = sfpopen(0, s, "w+")) ) terror("Can't create read/write process"); if(sfwrite(f, "abc\n",4) != 4) terror("Writing to pipe"); if(sfpoll(&f, 1, 0) != 1) terror("Poll should succeed\n"); if(sfvalue(f)&SF_READ) terror("Read should not be ready\n"); if(!(sfvalue(f)&SF_WRITE) ) terror("Write should be ready\n"); if(sfsync(f) < 0) terror("Bad sync"); if(sfpoll(&f, 1, 1000) != 1) terror("Poll should succeed2\n"); if(!(sfvalue(f)&SF_READ) ) terror("Read should be ready\n"); if(!(sfvalue(f)&SF_WRITE) ) terror("Write should be ready\n"); if(!(s = sfgetr(f,'\n',1)) || strcmp(s, "abc") != 0) terror("Bad read"); TSTEXIT(0); } (&f, 1, 0) != 1) terror("Poll should succeed\n"); if(sfvalue(f)&SF_READ) terror("Read should not be ready\n"); if(!(sfvalue(f)&SF_WRITE) ) terror("Write should be ready\n"); if(sfsync(f) < 0) terror("Bad sync"); if(sfpoll(&f, 1, 1000) != 1) terror("Poll should succeed2\n"); if(!(sfvalue(f)&SF_READ) ) terror("Read shouldsrc/lib/sfio/Sfio_t/tpool.c000644 151361 151361 00000007700 07235635536 015573 0ustar00kpvkpv000000 000000 #include "sftest.h" static char Serial[128], *S = Serial; #if __STD_C ssize_t writef(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) #else ssize_t writef(f, buf, n, disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { memcpy((Void_t*)S,buf,n); S += n; return n; } Sfdisc_t Serialdc = {NIL(Sfread_f), writef, NIL(Sfseek_f), NIL(Sfexcept_f) }; MAIN() { int i, n, on; char *s, *os, *s1, *s2, *s3; char poolbuf[1024]; Sfio_t *f1, *f2, *f3, *f4; if(!(f1 = sfopen((Sfio_t*)0,tstfile(0),"w+")) || !(f2 = sfopen((Sfio_t*)0,tstfile(1),"w")) || !(f3 = sfopen((Sfio_t*)0,tstfile(2),"w"))) terror("Opening files\n"); if(!(f4 = sfopen((Sfio_t*)0,tstfile(0),"r+")) ) terror("Opening file to read\n"); sfungetc(f1,'a'); sfungetc(f4,'b'); sfpool(f1,f4,0); sfungetc(f1,'a'); sfpool(f1,NIL(Sfio_t*),0); sfsetbuf(f2,poolbuf,sizeof(poolbuf)); sfsetbuf(f3,poolbuf,sizeof(poolbuf)); if(!sfpool(f2,f3,0) ) terror("Setting pool\n"); os = "1234567890\n"; on = strlen(os); for(i = 0; i < 100; ++i) if(sfputr(f1,os,-1) < 0) terror("Writing data\n"); sfseek(f1,(Sfoff_t)0,0); for(i = 0; i < 100; ++i) { if(!(s = sfgetr(f1,'\n',0)) || (n = sfvalue(f1)) != on) terror("Reading data\n"); if(sfwrite(f2,s,n) != n) terror("Writing1\n"); if(sfwrite(f3,s,n) != n) terror("Writing2\n"); } /* see if data matches */ if(!(f1 = sfopen(f1, tstfile(0), "r")) || !(f2 = sfopen(f2, tstfile(1), "r")) || !(f3 = sfopen(f3, tstfile(2), "r")) ) terror("sfopen for file comparison\n"); if(sfsize(f1) != sfsize(f2) || sfsize(f2) != sfsize(f3)) terror("Files don't match sizes"); n = (int)sfsize(f1); if(!(s1 = sfreserve(f1,n,0)) || !(s2 = sfreserve(f2,n,0)) || !(s3 = sfreserve(f3,n,0)) ) terror("Fail reserving data"); if(memcmp(s1,s2,n) != 0 || memcmp(s2,s3,n) != 0) terror("Data do not match"); sfclose(f1); sfclose(f2); sfclose(f3); f1 = sfstdout; f2 = sfstderr; sfdisc(sfstdout,&Serialdc); sfdisc(sfstderr,&Serialdc); sfset(sfstdout,SF_LINE,0); sfset(sfstderr,SF_LINE,0); if(sfpool(sfstdout,sfstderr,0) != sfstderr ) terror("sfpool1\n"); sfputc(sfstdout,'1'); sfputc(sfstderr,'2'); sfputc(sfstdout,'3'); sfputc(sfstderr,'4'); sfsync(sfstderr); if(strcmp(Serial,"1234") != 0) terror("Pool not serializing output\n"); sfdisc(sfstdout,NIL(Sfdisc_t*)); sfdisc(sfstderr,NIL(Sfdisc_t*)); sfclose(sfstdout); if(!(f1 = sfopen((Sfio_t*)0,tstfile(0),"r"))) terror("sfopen\n"); if(!sfpool(f1,sfstderr,0) ) terror("sfpool2\n"); if(!(f1 = sfopen(NIL(Sfio_t*), tstfile(0), "w+")) || !(f2 = sfopen(NIL(Sfio_t*), tstfile(1), "w+")) || !(f3 = sfopen(NIL(Sfio_t*), tstfile(2), "w+")) ) terror("sfopen3\n"); if(sfpool(f1,f2,SF_SHARE) != f2 || sfpool(f3,f2,SF_SHARE) != f2 ) terror("sfpool3\n"); if(sfputc(f3,'x') < 0) terror("sfputc to f3\n"); if(sfputc(f2,'y') < 0) terror("sfputc to f2\n"); if(sfputc(f1,'z') < 0) terror("sfputc to f1\n"); if(sfseek(f1,(Sfoff_t)0,0) != 0) terror("sfseek failed on f1\n"); if(!(s = sfreserve(f1,3,1)) || sfvalue(f1) != 3) terror("sfreserve failed on f1\n"); if(memcmp(s,"xyz",3) != 0) terror("Wrong data\n"); if((os = sfreserve(f2,-1,0)) ) terror("sfreserve should have failed on f2\n"); if(sfpool(NIL(Sfio_t*),f2,0) != f1) terror("Didn't get right pool head for f2\n"); if(sfread(f1,s,3) != 3) terror("Wrong read on f1\n"); if(!sfpool(f3,NIL(Sfio_t*),0) ) terror("sfpool to delete f3\n"); if(sfpool(f1,NIL(Sfio_t*),0) != f1 ) terror("sfpool to delete f1\n"); if(!(f1 = sfopen(NIL(Sfio_t*), tstfile(0), "w+")) || !(f2 = sfopen(NIL(Sfio_t*), tstfile(1), "w")) ) terror("sfopen4\n"); sfputc(f1,'a'); sfputc(f1,'b'); sfputc(f1,'c'); sfset(f1,SF_WRITE,0); /* off write mode */ if(sfpool(f1,f2,SF_SHARE) ) terror("sfpool should fail pooling read+write streams\n"); if(sfseek(f1,(Sfoff_t)0,0) != (Sfoff_t)0) terror("sfseek failed\n"); if(!(s = sfreserve(f1,3,1)) || memcmp(s,"abc",3) != 0) terror("Can't get data from f1\n"); TSTEXIT(0); } delete f1\n"); if(!(f1 = sfopen(NIL(Sfio_t*), tstfile(0), "w+"src/lib/sfio/Sfio_t/tclose.c000644 151361 151361 00000006057 07235635535 015732 0ustar00kpvkpv000000 000000 #include "sftest.h" #include static int Write_error = 0; #if __STD_C static int except(Sfio_t* f, int type, Void_t* obj, Sfdisc_t* disc) #else static int except(f, type, obj, disc) Sfio_t* f; int type; Void_t* obj; Sfdisc_t* disc; #endif { if(type == SF_WRITE) Write_error = 1; return 0; } static Sfdisc_t Wdisc = {NIL(Sfread_f), NIL(Sfwrite_f), NIL(Sfseek_f), except}; MAIN() { int fd[2]; Sfio_t *r, *w; char* s; void(* handler)_ARG_((int)); #define N_STR 10 if(argc > 1) /* to act as a coprocess that read/write ten lines */ { int i, n, rv; n = atoi(argv[1]); for(i = 0; i < n; ++i) { if(!(s = sfgetr(sfstdin,'\n',1)) ) terror("Failed to read from stdin"); if((rv = sfputr(sfstdout, s, '\n')) != sfvalue(sfstdin)) terror("Failed to write rv=%d stdin=%d", rv, sfvalue(sfstdin)); } sfsync(sfstdout); TSTEXIT(0); } signal(SIGPIPE,SIG_IGN); if(pipe(fd) < 0) terror("Opening pipes\n"); if(!(w = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND, fd[1],SF_WRITE)) ) terror("Opening write stream\n"); if(!(r = sfnew(NIL(Sfio_t*),NIL(Void_t*),(size_t)SF_UNBOUND, fd[0],SF_READ)) ) terror("Opening read stream\n"); sfdisc(w,&Wdisc); if(sfputr(w,"abc",'\n') != 4) terror("sfputr failed\n"); if(!(s = sfgetr(r,'\n',1)) || strcmp(s,"abc") != 0) terror("sfgetr failed\n"); if(sfclose(r) < 0) terror("sfclose failed closing read stream\n"); if(sfputr(w,"def",'\n') != 4) terror("sfputr failed2\n"); if(Write_error) terror("Write exception should not have been raised\n"); if(sfclose(w) >= 0) terror("sfclose should have failed closing write stream\n"); if(!Write_error) terror("Write exception did not get raised\n"); signal(SIGPIPE,SIG_DFL); if((w = sfpopen(NIL(Sfio_t*), sfprints("%s %d", argv[0], N_STR), "w+")) ) { int i; if((handler = signal(SIGPIPE,SIG_IGN)) == SIG_DFL || handler == SIG_IGN) terror("Bad signal handler for SIGPIPE\n"); signal(SIGPIPE,handler); Write_error = 0; sfdisc(w,&Wdisc); for(i = 0; i < N_STR*10; ++i) if(sfputr(w, "abc",'\n') != 4) terror("Writing to coprocess1\n"); sfsync(w); sfset(w,SF_READ,1); i = sffileno(w); sfset(w,SF_WRITE,1); if (i != sffileno(w)) close(sffileno(w)); for(i = 0; i < N_STR; ++i) if(!(s = sfgetr(w,'\n',1)) || strcmp(s,"abc") != 0) terror("Reading coprocess [%s]\n", s); if((s = sfgetr(w,'\n',1)) ) terror("sfgetr should have failed\n"); if(sfputr(w, "abc",'\n') != 4) terror("Writing to coprocess2\n"); if(Write_error) terror("Write exception should not have been raised yet\n"); if(sfclose(w) < 0) terror("sfclose should have returned an exit status\n"); if(!Write_error) terror("Write exception should have been raised\n"); } if(signal(SIGPIPE,SIG_DFL) != SIG_DFL) terror("SIGPIPE handler should have been SIG_DFL\n"); /* test for stdio signal handling behavior */ w = sfpopen((Sfio_t*)(-1), sfprints("%s %d 2>/dev/null",argv[0],N_STR), "w+"); if(w && (handler = signal(SIGPIPE,SIG_DFL)) != SIG_DFL) terror("SIGPIPE handler should have been SIG_DFL\n"); TSTEXIT(0); } if(sfclose(w) < 0) terror("sfclose should have returned an exit status\n"); if(!Write_error) terror("Write exception should have been raised\n"); } if(signal(SIGPIPE,SIG_DFL) != SIG_DFL) terror("SIGPIPE handler should have been SIG_DFL\n"); /* test for stdio signal handling behavior */ w = sfpopen((Sfio_t*)(-1), sfprints("%s %d 2>/dev/null",argv[0],N_STR), "w+"); if(w && (handler = signal(SIGPIPE,SIG_DFL)) != SIG_DFL) terror("SIGPIPE handlersrc/lib/sfio/Sfio_t/tmove.c000644 151361 151361 00000002703 07235635536 015566 0ustar00kpvkpv000000 000000 #include "sftest.h" MAIN() { char *s = "1234567890\n"; Sfoff_t n, i; Sfio_t *f; char buf[1024]; char* addr; if(sfopen(sfstdout,tstfile(0),"w+") != sfstdout) terror("Opening output file\n"); for(i = 0; i < 10000; ++i) if(sfputr(sfstdout,s,-1) < 0) terror("Writing data\n"); if(!(f = sfopen((Sfio_t*)0,tstfile(1),"w"))) terror("Opening output file \n"); sfseek(sfstdout,(Sfoff_t)0,0); if((n = sfmove(sfstdout,f,(Sfoff_t)SF_UNBOUND,'\n')) != i) terror("Move %d lines, Expect %d\n",n,i); sfseek(sfstdout,(Sfoff_t)0,0); sfseek(f,(Sfoff_t)0,0); sfsetbuf(sfstdout,buf,sizeof(buf)); if((n = sfmove(sfstdout,f,(Sfoff_t)SF_UNBOUND,'\n')) != i) terror("Move %d lines, Expect %d\n",n,i); sfopen(sfstdin,tstfile(0),"r"); sfopen(sfstdout,tstfile(1),"w"); sfmove(sfstdin,sfstdout,(Sfoff_t)SF_UNBOUND,-1); if(!sfeof(sfstdin)) terror("Sfstdin is not eof\n"); if(sferror(sfstdin)) terror("Sfstdin is in error\n"); if(sferror(sfstdout)) terror("Sfstdout is in error\n"); sfseek(sfstdin,(Sfoff_t)0,0); sfseek(sfstdout,(Sfoff_t)0,0); sfsetbuf(sfstdin,buf,sizeof(buf)); addr = (char*)sbrk(0); sfmove(sfstdin,sfstdout,(Sfoff_t)((unsigned long)(~0L)>>1),-1); if((ssize_t)((char*)sbrk(0)-addr) > 256*1024) terror("Too much space allocated in sfmove\n"); if(!sfeof(sfstdin)) terror("Sfstdin is not eof2\n"); if(sferror(sfstdin)) terror("Sfstdin is in error2\n"); if(sferror(sfstdout)) terror("Sfstdout is in error2\n"); TSTEXIT(0); } terror("Sfstdout is in error\n"); sfseek(sfstdin,(Sfoff_t)0src/lib/sfio/Sfio_f/_sfputu.c000644 151361 151361 00000000257 06777405327 016110 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfputu #if __STD_C int sfputu(reg Sfio_t* f, Sfulong_t u) #else int sfputu(f,u) reg Sfio_t* f; reg Sfulong_t u; #endif { return __sf_putu(f,u); } )((char*)sbrk(0)-addr) > 256*1024) terror("Too much space allocated in sfmove\n"); if(!sfeof(sfstdin)) terror("Sfstdin is not eof2\n"); if(sferror(sfstdin)) terror("Sfstdin is in error2\n"); if(sferror(sfstdout)) terror("SfstdoutAV=Q5LH=Q|=Q|@src/lib/sfio/Sfio_f/_sfputl.c000644 151361 151361 00000000255 06777405327 016075 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfputl #if __STD_C int sfputl(reg Sfio_t* f, Sflong_t l) #else int sfputl(f,l) reg Sfio_t* f; reg Sflong_t l; #endif { return __sf_putl(f,l); } } )((char*)sbrk(0)-addr) > 256*1024) terror("Too much space allocated in sfmove\n"); if(!sfeof(sfstdin)) terror("Sfstdin is not eof2\n"); if(sferror(sfstdin)) terror("Sfstdin is in error2\n"); if(sferror(sfstdout)) terror("SfstdoutÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sfputm.c000644 151361 151361 00000000321 07037160134 016050 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfputm #if __STD_C int sfputm(reg Sfio_t* f, Sfulong_t u, Sfulong_t m) #else int sfputm(f,u,m) reg Sfio_t* f; reg Sfulong_t u; reg Sfulong_t m; #endif { return __sf_putm(f,u,m); } terror("Too much space allocated in sfmove\n"); if(!sfeof(sfstdin)) terror("Sfstdin is not eof2\n"); if(sferror(sfstdin)) terror("Sfstdin is in error2\n"); if(sferror(sfstdout)) terror("SfstdoutÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sfputd.c000644 151361 151361 00000000261 06777405327 016062 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfputd #if __STD_C int sfputd(reg Sfio_t* f, Sfdouble_t d) #else int sfputd(f,d) reg Sfio_t* f; reg Sfdouble_t d; #endif { return __sf_putd(f,d); } f { return __sf_putm(f,u,m); } terror("Too much space allocated in sfmove\n"); if(!sfeof(sfstdin)) terror("Sfstdin is not eof2\n"); if(sferror(sfstdin)) terror("Sfstdin is in error2\n"); if(sferror(sfstdout)) terror("SfstdoutÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sfgetc.c000644 151361 151361 00000000215 06777405326 016026 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfgetc #if __STD_C int sfgetc(reg Sfio_t* f) #else int sfgetc(f) reg Sfio_t* f; #endif { return __sf_getc(f); } #endif { return __sf_putd(f,d); } f { return __sf_putm(f,u,m); } terror("Too much space allocated in sfmove\n"); if(!sfeof(sfstdin)) terror("Sfstdin is not eof2\n"); if(sferror(sfstdin)) terror("Sfstdin is in error2\n"); if(sferror(sfstdout)) terror("SfstdoutÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sfputc.c000644 151361 151361 00000000250 06777405327 016057 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfputc #if __STD_C int sfputc(reg Sfio_t* f, reg int c) #else int sfputc(f,c) reg Sfio_t* f; reg int c; #endif { return __sf_putc(f,c); } (f,d); } f { return __sf_putm(f,u,m); } terror("Too much space allocated in sfmove\n"); if(!sfeof(sfstdin)) terror("Sfstdin is not eof2\n"); if(sferror(sfstdin)) terror("Sfstdin is in error2\n"); if(sferror(sfstdout)) terror("SfstdoutÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sfvalue.c000644 151361 151361 00000000231 06777405327 016217 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfvalue #if __STD_C ssize_t sfvalue(reg Sfio_t* f) #else ssize_t sfvalue(f) reg Sfio_t* f; #endif { return __sf_value(f); } f_putc(f,c); } (f,d); } f { return __sf_putm(f,u,m); } terror("Too much space allocated in sfmove\n"); if(!sfeof(sfstdin)) terror("Sfstdin is not eof2\n"); if(sferror(sfstdin)) terror("Sfstdin is in error2\n"); if(sferror(sfstdout)) terror("SfstdoutÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/Makefile000644 151361 151361 00000001312 07411266634 015700 0ustar00kpvkpv000000 000000 # makefile for true function versions of macro functions # # Written by Kiem-Phong Vo # Compiler and flags to use LIBTYPE= AR= ar CC= cc CXFLAGS= CCMODE= -O CCFLAGS= -I. -I.. $(CCMODE) $(LIBTYPE) $(CXFLAGS) HDRS= SRCS= _sfclrerr.c _sfdlen.c _sfeof.c _sferror.c _sffileno.c _sfgetc.c \ _sfllen.c _sfputc.c _sfputd.c _sfputl.c _sfputu.c _sfputm.c \ _sfslen.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfdlen.o _sfeof.o _sferror.o _sffileno.o _sfgetc.o \ _sfllen.o _sfputc.o _sfputd.o _sfputl.o _sfputu.o _sfputm.o \ _sfslen.o _sfstacked.o _sfulen.o _sfvalue.o .c.o: $(CC) -c $(CCFLAGS) $*.c must: $(OBJS) 3dupdate: cp Makefile $(HDRS) $(SRCS) ... clean: -(rm $(OBJS); exit 0) >/dev/null 2>&1 LAGS) HDRS= SRCS= _sfclrerr.c _sfdlen.c _sfeof.c _sferror.c _sffileno.c _sfgetc.c \ _sfllen.c _sfputc.c _sfputd.c _sfputl.c _sfputu.c _sfputm.c \ _sfslen.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfdlen.o _sfeof.o _sferror.o _sffileno.o _sfgetc.o \ _sfllen.o _sfputc.o _sfputd.o _sfputl.o _sfpsrc/lib/sfio/Sfio_f/_sfeof.c000644 151361 151361 00000000211 06777405326 015651 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfeof #if __STD_C int sfeof(reg Sfio_t* f) #else int sfeof(f) reg Sfio_t* f; #endif { return __sf_eof(f); } HDRS) $(SRCS) ... clean: -(rm $(OBJS); exit 0) >/dev/null 2>&1 LAGS) HDRS= SRCS= _sfclrerr.c _sfdlen.c _sfeof.c _sferror.c _sffileno.c _sfgetc.c \ _sfllen.c _sfputc.c _sfputd.c _sfputl.c _sfputu.c _sfputm.c \ _sfslen.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sfllen.c000644 151361 151361 00000000217 06777405327 016041 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfllen #if __STD_C int sfllen(reg Sflong_t v) #else int sfllen(v) reg Sflong_t v; #endif { return __sf_llen(v); } $(SRCS) ... clean: -(rm $(OBJS); exit 0) >/dev/null 2>&1 LAGS) HDRS= SRCS= _sfclrerr.c _sfdlen.c _sfeof.c _sferror.c _sffileno.c _sfgetc.c \ _sfllen.c _sfputc.c _sfputd.c _sfputl.c _sfputu.c _sfputm.c \ _sfslen.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sfdlen.c000644 151361 151361 00000000223 06777405326 016025 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfdlen #if __STD_C int sfdlen(reg Sfdouble_t v) #else int sfdlen(v) reg Sfdouble_t v; #endif { return __sf_dlen(v); } CS) ... clean: -(rm $(OBJS); exit 0) >/dev/null 2>&1 LAGS) HDRS= SRCS= _sfclrerr.c _sfdlen.c _sfeof.c _sferror.c _sffileno.c _sfgetc.c \ _sfllen.c _sfputc.c _sfputd.c _sfputl.c _sfputu.c _sfputm.c \ _sfslen.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sfulen.c000644 151361 151361 00000000221 06777405327 016045 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfulen #if __STD_C int sfulen(reg Sfulong_t v) #else int sfulen(v) reg Sfulong_t v; #endif { return __sf_ulen(v); } } CS) ... clean: -(rm $(OBJS); exit 0) >/dev/null 2>&1 LAGS) HDRS= SRCS= _sfclrerr.c _sfdlen.c _sfeof.c _sferror.c _sffileno.c _sfgetc.c \ _sfllen.c _sfputc.c _sfputd.c _sfputl.c _sfputu.c _sfputm.c \ _sfslen.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sfslen.c000644 151361 151361 00000000173 06777405327 016051 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfslen #if __STD_C ssize_t sfslen(void) #else ssize_t sfslen() #endif { return __sf_slen(); } eturn __sf_ulen(v); } } CS) ... clean: -(rm $(OBJS); exit 0) >/dev/null 2>&1 LAGS) HDRS= SRCS= _sfclrerr.c _sfdlen.c _sfeof.c _sferror.c _sffileno.c _sfgetc.c \ _sfllen.c _sfputc.c _sfputd.c _sfputl.c _sfputu.c _sfputm.c \ _sfslen.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sfclrerr.c000644 151361 151361 00000000225 06777405326 016376 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfclrerr #if __STD_C int sfclrerr(reg Sfio_t* f) #else int sfclrerr(f) reg Sfio_t* f; #endif { return __sf_clrerr(f); } ) ... clean: -(rm $(OBJS); exit 0) >/dev/null 2>&1 LAGS) HDRS= SRCS= _sfclrerr.c _sfdlen.c _sfeof.c _sferror.c _sffileno.c _sfgetc.c \ _sfllen.c _sfputc.c _sfputd.c _sfputl.c _sfputu.c _sfputm.c \ _sfslen.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sffileno.c000644 151361 151361 00000000225 06777405326 016361 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sffileno #if __STD_C int sffileno(reg Sfio_t* f) #else int sffileno(f) reg Sfio_t* f; #endif { return __sf_fileno(f); } ) ... clean: -(rm $(OBJS); exit 0) >/dev/null 2>&1 LAGS) HDRS= SRCS= _sfclrerr.c _sfdlen.c _sfeof.c _sferror.c _sffileno.c _sfgetc.c \ _sfllen.c _sfputc.c _sfputd.c _sfputl.c _sfputu.c _sfputm.c \ _sfslen.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sfstacked.c000644 151361 151361 00000000231 06777405327 016521 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sfstacked #if __STD_C int sfstacked(reg Sfio_t* f) #else int sfstacked(f) reg Sfio_t* f; #endif { return __sf_stacked(f); } . clean: -(rm $(OBJS); exit 0) >/dev/null 2>&1 LAGS) HDRS= SRCS= _sfclrerr.c _sfdlen.c _sfeof.c _sferror.c _sffileno.c _sfgetc.c \ _sfllen.c _sfputc.c _sfputd.c _sfputl.c _sfputu.c _sfputm.c \ _sfslen.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_f/_sferror.c000644 151361 151361 00000000221 06777405326 016232 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #undef sferror #if __STD_C int sferror(reg Sfio_t* f) #else int sferror(f) reg Sfio_t* f; #endif { return __sf_error(f); } d(f); } . clean: -(rm $(OBJS); exit 0) >/dev/null 2>&1 LAGS) HDRS= SRCS= _sfclrerr.c _sfdlen.c _sfeof.c _sferror.c _sffileno.c _sfgetc.c \ _sfllen.c _sfputc.c _sfputd.c _sfputl.c _sfputu.c _sfputm.c \ _sfslen.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfÓAV=Jc#>8|3oH8|3oH@src/lib/sfio/Sfio_rm/sfecvt.c000644 151361 151361 00000000545 06307437524 016077 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #if __STD_C char* sfecvt(double dval, int n_digit, int* decpt, int* sign) #else char* sfecvt(dval,n_digit,decpt,sign) double dval; /* value to convert */ int n_digit; /* number of digits wanted */ int* decpt; /* to return decimal point */ int* sign; /* to return sign */ #endif { return _sfcvt(&dval,n_digit,decpt,sign,F_EFORMAT); } n.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfAV=Q=Q|=Q|@src/lib/sfio/Sfio_rm/sffcvt.c000644 151361 151361 00000000535 06777405100 016073 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #if __STD_C char *sffcvt(double dval, int n_digit, int* decpt, int* sign) #else char *sffcvt(dval,n_digit,decpt,sign) double dval; /* value to convert */ int n_digit; /* number of digits wanted */ int* decpt; /* to return decimal point */ int* sign; /* to return sign */ #endif { return _sfcvt(&dval,n_digit,decpt,sign,0); } MAT); } n.c _sfstacked.c _sfulen.c _sfvalue.c OBJS= _sfclrerr.o _sfD#AVb=>Fhmode&SF_INIT) (void)_sfmode(f,0,0); if((f->flags&SF_RDWRSTR) == SF_RDWRSTR) { SFSTRSIZE(f); n = (f->data+f->here) - f->next; } else n = f->endb - f->next; if(!bp) return n; else if(n > 0) /* size == 0 */ { *bp = (Void_t*)f->next; return 0; } /* else fall down and fill buffer */ } if(!(mode = f->flags&SF_READ) ) mode = SF_WRITE; if((int)f->mode != mode && _sfmode(f,mode,0) < 0) return -1; *bp = sfreserve(f, sz <= 0 ? 0 : sz > f->size ? f->size : sz, 0); if(*bp && sz >= 0) return sz; if((n = sfvalue(f)) > 0) { *bp = (Void_t*)f->next; if(sz < 0) { f->mode |= SF_PEEK; f->endr = f->endw = f->data; } else { if(sz > n) sz = n; f->next += sz; } } return (sz >= 0 && n >= sz) ? sz : n; } next; return 0; } /* else fall down and fill buffer */ } if(!(mode = f->flags&SF_READ) ) mode = SF_WRITE; if((int)f->mode != mode && _sfmode(f,mode,0) < 0) return -1; *bp = sfreserve(f, sz <= 0 ? 0 : sz > f->size ? f->size : sz, 0); src/lib/sfio/Sfio_rm/sfstrtof.h000644 151361 151361 00000016571 07432261526 016467 0ustar00kpvkpv000000 000000 /* * AT&T Labs Research * Glenn Fowler & Phong Vo * * common header and implementation for * * strtof strtod strtold _sfscand * * define these macros to instantiate an implementation: * * S2F_function the function name * S2F_static 1 if S2F_function is static * S2F_type 0:float 1:double 2:long.double * S2F_scan 1 for alternate interface with these arguments: * void* handle * int (*getchar)(void* handle) * exactly one extra (*getchar)() is done, i.e., * the caller must do the pushback */ #include "sfhdr.h" #include "FEATURE/float" #if S2F_type == 2 && _ast_fltmax_double #undef S2F_type #define S2F_type 1 #endif #if S2F_type == 0 #define S2F_number float #define S2F_ldexp ldexp #define S2F_pow10 _Sffpow10 #define S2F_huge _Sffhuge #define S2F_min (FLT_MIN) #define S2F_max (FLT_MAX) #define S2F_exp_10_min (FLT_MIN_10_EXP) #define S2F_exp_10_max (FLT_MAX_10_EXP) #define S2F_exp_2_min (FLT_MIN_EXP) #define S2F_exp_2_max (FLT_MAX_EXP) #endif #if S2F_type == 1 #define S2F_number double #define S2F_ldexp ldexp #define S2F_pow10 _Sfdpow10 #define S2F_huge _Sfdhuge #define S2F_min (DBL_MIN) #define S2F_max (DBL_MAX) #define S2F_exp_10_min (DBL_MIN_10_EXP) #define S2F_exp_10_max (DBL_MAX_10_EXP) #define S2F_exp_2_min (DBL_MIN_EXP) #define S2F_exp_2_max (DBL_MAX_EXP) #endif #if S2F_type == 2 #define S2F_number long double #define S2F_ldexp ldexpl #define S2F_pow10 _Sflpow10 #define S2F_huge _Sflhuge #define S2F_min (LDBL_MIN) #define S2F_max (LDBL_MAX) #define S2F_exp_10_min (LDBL_MIN_10_EXP) #define S2F_exp_10_max (LDBL_MAX_10_EXP) #define S2F_exp_2_min (LDBL_MIN_EXP) #define S2F_exp_2_max (LDBL_MAX_EXP) #endif #if -S2F_exp_10_min < S2F_exp_10_max #define S2F_exp_10_abs (-S2F_exp_10_min) #else #define S2F_exp_10_abs S2F_exp_10_max #endif #define S2F_batch _ast_flt_unsigned_max_t #if S2F_scan typedef int (*S2F_get_f)_ARG_((void*)); #define ERR(e) #define GET(p) (*get)(p) #define PUT(p) #define SET(p,t) #else #define ERR(e) (errno=(e)) #define GET(p) (*p++) #define PUT(p) (end?(*end=(char*)p-1):(char*)0) #define SET(p,t) (t=p) #endif typedef struct S2F_part_s { S2F_batch batch; int digits; } S2F_part_t; #ifndef ERANGE #define ERANGE EINVAL #endif #if S2F_static static #else #if defined(__EXPORT__) #define extern __EXPORT__ #endif extern #undef extern #endif S2F_number #if S2F_scan #if __STD_C S2F_function(void* s, S2F_get_f get) #else S2F_function(s, get) void* s; S2F_get_f get; #endif #else #if __STD_C S2F_function(const char* str, char** end) #else S2F_function(str, end) char* str; char** end; #endif #endif { #if !S2F_scan register unsigned char* s = (unsigned char*)str; unsigned char* t; #endif register S2F_batch n; register int c; register int digits; register int m; register unsigned char* cv; int negative; int enegative; int fraction; int decimal = 0; int thousand = 0; int part = 0; S2F_number v; S2F_number p; S2F_part_t parts[16]; /* * radix char and thousands separator are locale specific */ SFSETLOCALE(&decimal, &thousand); SFCVINIT(); /* * skip initial blanks */ do c = GET(s); while (isspace(c)); SET(s, t); /* * get the sign */ if ((negative = (c == '-')) || c == '+') c = GET(s); /* * drop leading 0's */ digits = 0; fraction = -1; if (c == '0') { c = GET(s); if (c == 'x' || c == 'X') { /* * hex floating point -- easy */ cv = _Sfcv36; v = 0; for (;;) { c = GET(s); if ((part = cv[c]) < 16) { digits++; v *= 16; v += part; } else if (c == decimal) { decimal = -1; fraction = digits; } else break; } m = 0; if (c == 'p' || c == 'P') { c = GET(s); if ((enegative = c == '-') || c == '+') c = GET(s); while (c >= '0' && c <= '9') { m = (m << 3) + (m << 1) + (c - '0'); c = GET(s); } if (enegative) m = -m; } /* * consume the optional suffix */ switch (c) { case 'f': case 'F': case 'l': case 'L': c = GET(s); break; } PUT(s); if (v == 0) return v; if (fraction >= 0) m -= 4 * (digits - fraction); if (m < S2F_exp_2_min) { if ((m -= S2F_exp_2_min) < S2F_exp_2_min) { ERR(ERANGE); return 0; } v = S2F_ldexp(v, S2F_exp_2_min); } else if (m > S2F_exp_2_max) { ERR(ERANGE); return negative ? -S2F_huge : S2F_huge; } v = S2F_ldexp(v, m); goto check; } while (c == '0') c = GET(s); } else if (c == decimal) { decimal = -1; fraction = 0; for (;;) { c = GET(s); if (c != '0') break; digits++; } } else if (c == 'i' || c == 'I') { if ((c = GET(s)) != 'n' && c != 'N' || (c = GET(s)) != 'f' && c != 'F') { PUT(t); return 0; } c = GET(s); SET(s, t); if (((c) == 'i' || c == 'I') && ((c = GET(s)) == 'n' || c == 'N') && ((c = GET(s)) == 'i' || c == 'I') && ((c = GET(s)) == 't' || c == 'T') && ((c = GET(s)) == 'y' || c == 'Y')) { c = GET(s); SET(s, t); } PUT(t); return negative ? -S2F_huge : S2F_huge; } else if (c == 'n' || c == 'N') { if ((c = GET(s)) != 'a' && c != 'A' || (c = GET(s)) != 'n' && c != 'N') { PUT(t); return 0; } do c = GET(s); while (c && !isspace(c)); PUT(s); return negative ? -S2F_huge : S2F_huge; } else if (c < '1' || c > '9') { PUT(t); #if S2F_scan /* KPV: this returns an indicator that no number was specified */ *((int*)s) = 1; #endif return 0; } /* * consume the integral and fractional parts */ n = 0; m = 0; for (;;) { if (c >= '0' && c <= '9') { digits++; n = (n << 3) + (n << 1) + (c - '0'); if (n >= ((~((S2F_batch)0)) / 10) && part < sizeof(parts)/sizeof(parts[0]) ) { parts[part].batch = n; n = 0; parts[part].digits = digits; part++; } } else if (m && (digits - m) != 3) break; else if (c == decimal) { decimal = -1; m = 0; fraction = digits; } else if (c != thousand) break; else if (!(m = digits)) break; c = GET(s); } /* * don't forget the last part */ if (n && part < sizeof(parts)/sizeof(parts[0]) ) { parts[part].batch = n; parts[part].digits = digits; part++; } /* * consume the exponent */ if (fraction >= 0) digits = fraction; if (c == 'e' || c == 'E') { c = GET(s); if ((enegative = (c == '-')) || c == '+') c = GET(s); n = 0; while (c >= '0' && c <= '9') { n = (n << 3) + (n << 1) + (c - '0'); c = GET(s); } if (enegative) digits -= n; else digits += n; } /* * consume the optional suffix */ switch (c) { case 'f': case 'F': case 'l': case 'L': c = GET(s); break; } PUT(s); /* * adjust for at most one multiply per part * and at most one divide overall */ if (!part) return 0; else if ((m = parts[part-1].digits - digits) > 0) digits += m; else m = 0; /* * combine the parts */ v = 0; while (part--) { p = parts[part].batch; c = digits - parts[part].digits; if (c > S2F_exp_10_max) { ERR(ERANGE); v = S2F_huge; break; } if (c > 0) p *= S2F_pow10[c]; v += p; } if (m) { while (m > S2F_exp_10_max) { m -= S2F_exp_10_max; v /= S2F_pow10[S2F_exp_10_max]; } v /= S2F_pow10[m]; } /* * check the range */ check: if (v < S2F_min) { ERR(ERANGE); v = 0; } else if (v > S2F_max) { ERR(ERANGE); v = S2F_huge; } /* * done */ return negative ? -v : v; } p = parts[part].batch; c = digits - parts[part].digits; if (c > S2F_exp_10_max) { ERR(ERANGE); v = S2F_huge; break; src/lib/sfio/Sfio_rm/sfstrtod.c000644 151361 151361 00000004724 07432261526 016455 0ustar00kpvkpv000000 000000 #include "sfhdr.h" /* Convert a Sfdouble_t value represented in an ASCII format into ** the internal Sfdouble_t representation. This code is not aware ** of the alternative decimal/thousand characters. It is assumed ** that whoever calls it should have done the necessary massaging. ** ** Written by Kiem-Phong Vo. */ #define BATCH (2*sizeof(int)) /* accumulate this many digits at a time */ #define IPART 0 /* doing integer part */ #define FPART 1 /* doing fractional part */ #define EPART 2 /* doing exponent part */ #if __STD_C static Sfdouble_t sfpow10(reg int n) #else static Sfdouble_t sfpow10(n) reg int n; #endif { Sfdouble_t dval; switch(n) { case -3: return .001; case -2: return .01; case -1: return .1; case 0: return 1.; case 1: return 10.; case 2: return 100.; case 3: return 1000.; } if(n < 0) { dval = .0001; for(n += 4; n < 0; n += 1) dval /= 10.; } else { dval = 10000.; for(n -= 4; n > 0; n -= 1) dval *= 10.; } return dval; } #if __STD_C Sfdouble_t _sfstrtod(reg const char* s, char** retp) #else Sfdouble_t _sfstrtod(s,retp) reg char* s; /* string to convert */ char** retp; /* to return the remainder of string */ #endif { reg int n, c, m; reg int mode, fexp, sign, expsign; Sfdouble_t dval; /* skip initial blanks */ while(isspace(*s)) ++s; /* get the sign */ if((sign = (*s == '-')) || *s == '+') s += 1; mode = IPART; fexp = expsign = 0; dval = 0.; while(*s) { /* accumulate a handful of the digits */ for(m = BATCH, n = 0; m > 0; --m, ++s) { /* get and process a char */ c = *s; if(isdigit(c)) n = 10*n + (c - '0'); else break; } /* number of digits accumulated */ m = BATCH-m; if(mode == IPART) { /* doing the integer part */ if(dval == 0.) dval = (Sfdouble_t)n; else dval = dval*sfpow10(m) + (Sfdouble_t)n; } else if(mode == FPART) { /* doing the fractional part */ fexp -= m; if(n > 0) dval += n*sfpow10(fexp); } else if(n) { /* doing the exponent part */ if(expsign) n = -n; dval *= sfpow10(n); } if(!c) break; if(m < BATCH) { /* detected a non-digit */ if(c == '.') { /* start the fractional part or no match */ if(mode != IPART) break; mode = FPART; s += 1; } else if(c == 'e' || c == 'E') { if(mode == EPART) break; mode = EPART; c = *++s; if((expsign = (c == '-')) || c == '+') s += 1; } else break; } } if(retp) *retp = (char*)s; return sign ? -dval : dval; } nt part */ if(expsign) n = -n; dvasrc/lib/sfio/Sfio_dc/sfdcslow.c000644 151361 151361 00000001647 06777405343 016412 0ustar00kpvkpv000000 000000 #include "sfdchdr.h" /* Make a stream op return immediately on interrupts. ** This is useful on slow streams (hence the name). ** ** Written by Glenn Fowler (03/18/1998). */ #if __STD_C static int slowexcept(Sfio_t* f, int type, Void_t* v, Sfdisc_t* disc) #else static int slowexcept(f, type, v, disc) Sfio_t* f; int type; Void_t* v; Sfdisc_t* disc; #endif { NOTUSED(f); NOTUSED(v); NOTUSED(disc); switch (type) { case SF_FINAL: case SF_DPOP: free(disc); break; case SF_READ: case SF_WRITE: if (errno == EINTR) return(-1); break; } return(0); } #if __STD_C int sfdcslow(Sfio_t* f) #else int sfdcslow(f) Sfio_t* f; #endif { Sfdisc_t* disc; if(!(disc = (Sfdisc_t*)malloc(sizeof(Sfdisc_t))) ) return(-1); disc->readf = NIL(Sfread_f); disc->writef = NIL(Sfwrite_f); disc->seekf = NIL(Sfseek_f); disc->exceptf = slowexcept; if(sfdisc(f,disc) != disc) { free(disc); return(-1); } return(0); } { case SF_FINAL: case SF_DPOP: free(disc); break; case SF_READ: case SF_WRITE: src/lib/sfio/Sfio_dc/sfdcfilter.c000644 151361 151361 00000007410 06777405343 016705 0ustar00kpvkpv000000 000000 #include "sfdchdr.h" /* Discipline to invoke UNIX processes as data filters. ** These processes must be able to fit in pipelines. ** ** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998. */ #if !defined(FNDELAY) && defined(O_NDELAY) #define FNDELAY O_NDELAY #endif typedef struct _filter_s { Sfdisc_t disc; /* discipline structure */ Sfio_t* filter; /* the filter stream */ char raw[1024]; /* raw data buffer */ char* next; /* remainder of data unwritten to pipe */ char* endb; /* end of data */ } Filter_t; /* read data from the filter */ #if __STD_C static ssize_t filterread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else static ssize_t filterread(f, buf, n, disc) Sfio_t* f; /* stream reading from */ Void_t* buf; /* buffer to read into */ size_t n; /* number of bytes requested */ Sfdisc_t* disc; /* discipline */ #endif { Filter_t* fi; ssize_t r, w; fi = (Filter_t*)disc; for(;;) { if(!fi->next) fi->next = fi->endb = fi->raw; else { /* try to get data from filter, if any */ errno = 0; if((r = sfread(fi->filter,buf,n)) > 0) return r; if(errno != EWOULDBLOCK) return 0; } /* get some raw data to stuff down the pipe */ if(fi->next >= fi->endb) { if((r = sfrd(f,fi->raw,sizeof(fi->raw),disc)) > 0) { fi->next = fi->raw; fi->endb = fi->raw+r; } else { /* eof, close write end of pipes */ sfset(fi->filter,SF_READ,0); close(sffileno(fi->filter)); sfset(fi->filter,SF_READ,1); } } if((w = fi->endb - fi->next) > 0) { errno = 0; if((w = sfwrite(fi->filter,fi->next,w)) > 0) fi->next += w; else if(errno != EWOULDBLOCK) return 0; /* pipe is full, sleep for a while, then continue */ else sleep(1); } } } #if __STD_C static ssize_t filterwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) #else static ssize_t filterwrite(f, buf, n, disc) Sfio_t* f; /* stream reading from */ Void_t* buf; /* buffer to read into */ size_t n; /* number of bytes requested */ Sfdisc_t* disc; /* discipline */ #endif { return -1; } /* for the duration of this discipline, the stream is unseekable */ #if __STD_C static Sfoff_t filterseek(Sfio_t* f, Sfoff_t addr, int offset, Sfdisc_t* disc) #else static Sfoff_t filterseek(f, addr, offset, disc) Sfio_t* f; Sfoff_t addr; int offset; Sfdisc_t* disc; #endif { f = NIL(Sfio_t*); addr = 0; offset = 0; disc = NIL(Sfdisc_t*); return (Sfoff_t)(-1); } /* on close, remove the discipline */ #if __STD_C static filterexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) #else static filterexcept(f,type,data,disc) Sfio_t* f; int type; Void_t* data; Sfdisc_t* disc; #endif { if(type == SF_FINAL || type == SF_DPOP) { sfclose(((Filter_t*)disc)->filter); free(disc); } return 0; } #if __STD_C int sfdcfilter(Sfio_t* f, const char* cmd) #else int sfdcfilter(f, cmd) Sfio_t* f; /* stream to filter data */ char* cmd; /* program to run as a filter */ #endif { reg Filter_t* fi; reg Sfio_t* filter; /* open filter for read&write */ if(!(filter = sfpopen(NIL(Sfio_t*),cmd,"r+")) ) return -1; /* unbuffered so that write data will get to the pipe right away */ sfsetbuf(filter,NIL(Void_t*),0); /* make the write descriptor nonblocking */ sfset(filter,SF_READ,0); fcntl(sffileno(filter),F_SETFL,FNDELAY); sfset(filter,SF_READ,1); /* same for the read descriptor */ sfset(filter,SF_WRITE,0); fcntl(sffileno(filter),F_SETFL,FNDELAY); sfset(filter,SF_WRITE,1); if(!(fi = (Filter_t*)malloc(sizeof(Filter_t))) ) { sfclose(filter); return -1; } fi->disc.readf = filterread; fi->disc.writef = filterwrite; fi->disc.seekf = filterseek; fi->disc.exceptf = filterexcept; fi->filter = filter; fi->next = fi->endb = NIL(char*); if(sfdisc(f,(Sfdisc_t*)fi) != (Sfdisc_t*)fi) { sfclose(filter); free(fi); return -1; } return 0; } /* same for the read descriptor */ sfset(filter,SF_WRITE,0); fcntl(sffileno(filter),F_SETFL,FNDELAY); sfset(filter,SF_WRITE,1); if(!(fi = (Filter_t*)malloc(sizeof(Filter_t))) ) { sfclose(filter); return -1; } fi->disc.readf = filterreadsrc/lib/sfio/Sfio_dc/sfdcdos.c000644 151361 151361 00000016370 06777405343 016212 0ustar00kpvkpv000000 000000 #include "sfdchdr.h" /* Discipline to turn \r\n into \n. ** This is useful to deal with DOS text files. ** ** Written by David Korn (03/18/1998). */ #define MINMAP 8 #define CHUNK 1024 struct map { off_t logical; off_t physical; }; typedef struct _dosdisc { Sfdisc_t disc; struct map *maptable; int mapsize; int maptop; off_t lhere; off_t llast; off_t lmax; off_t pmax; off_t phere; off_t plast; off_t begin; int skip; void *buff; char last; char extra; int bsize; } Dosdisc_t; #if __STD_C static void addmapping(register Dosdisc_t *dp) #else static void addmapping(dp) register Dosdisc_t *dp; #endif { register int n; if((n=dp->maptop++)>=dp->mapsize) { dp->mapsize *= 2; if(!(dp->maptable=(struct map*)realloc((void*)dp->maptable,(dp->mapsize+1)*sizeof(struct map)))) { dp->maptop--; dp->mapsize *= 2; return; } } dp->maptable[n].physical = dp->phere; dp->maptable[n].logical = dp->lhere; dp->maptable[dp->maptop].logical=0; } #if __STD_C static struct map *getmapping(Dosdisc_t *dp, off_t offset, register int whence) #else static struct map *getmapping(dp, offset, whence) Dosdisc_t *dp; off_t offset; register int whence; #endif { register struct map *mp; static struct map dummy; if(offset <= dp->begin) { dummy.logical = dummy.physical = offset; return(&dummy); } if(!(mp=dp->maptable)) { dummy.logical = dp->begin; dummy.physical = dummy.logical+1; return(&dummy); } while((++mp)->logical && (whence==SEEK_CUR?mp->physical:mp->logical) <= offset); return(mp-1); } #if __STD_C static ssize_t dos_read(Sfio_t *iop, void *buff, size_t size, Sfdisc_t* disc) #else static ssize_t dos_read(iop, buff, size, disc) Sfio_t *iop; void *buff; size_t size; Sfdisc_t* disc; #endif { register Dosdisc_t *dp = (Dosdisc_t*)disc; register char *cp = (char*)buff, *first, *cpmax; register int n, count, m; if(dp->extra) { dp->extra=0; *cp = dp->last; return(1); } while(1) { if((n = sfrd(iop,buff,size,disc)) <= 0) return(n); dp->plast=dp->phere; dp->phere +=n; dp->llast = dp->lhere; cpmax = cp+n-1; if(dp->last=='\r' && *cp!='\n') { /* should insert a '\r' */ ; } dp->last = *cpmax; if(n>1) break; if(dp->last!='\r') { dp->lhere++; return(1); } } if(dp->last=='\r') n--; else if(dp->last!='\n' || cpmax[-1]!='\r') *cpmax = '\r'; dp->lhere += n; while(1) { while(*cp++ != '\r'); if(cp > cpmax || *cp=='\n') break; } dp->skip = cp-1 - (char*)buff; /* if not \r\n in buffer, just return */ if((count = cpmax+1-cp) <=0) { *cpmax = dp->last; if(!dp->maptable) dp->begin +=n; dp->skip++; count=0; goto done; } if(!dp->maptable) { dp->begin += cp - (char*)buff-1; if(dp->maptable=(struct map*)malloc((MINMAP+1)*sizeof(struct map))) { dp->mapsize = MINMAP; dp->maptable[0].logical= dp->begin; dp->maptable[0].physical = dp->maptable[0].logical+1; dp->maptable[1].logical=0; dp->maptop = 1; } } /* save original discipline inside buffer */ if(count>dp->bsize) { if(dp->bsize==0) dp->buff = malloc(count); else dp->buff = realloc(dp->buff,count); dp->bsize = count; if(!dp->buff) return(-1); } memcpy(dp->buff, cp, count); count=1; while(1) { first=cp; if(cp==cpmax) cp++; else while(*cp++ != '\r'); if(cp<=cpmax && *cp!='\n') continue; if((m=(cp-first)-1) >0) memcpy(first-count, first, m); if(cp > cpmax) break; count++; } cpmax[-count] = dp->last; dp->lhere -= count; done: if(dp->lhere>dp->lmax) { dp->lmax = dp->lhere; dp->pmax = dp->phere; if(dp->maptable && dp->lmax > dp->maptable[dp->maptop-1].logical+CHUNK) addmapping(dp); } return(n-count); } /* * returns the current offset * must be in the current buffer * if is SEEK_CUR, physical offset converted to logical offset * otherwise, logical offset is converted to physical offset */ #if __STD_C static off_t cur_offset(Dosdisc_t *dp, off_t offset,Sfio_t *iop,register int whence) #else static off_t cur_offset(dp, offset, iop, whence) Dosdisc_t *dp; off_t offset; Sfio_t *iop; register int whence; #endif { register off_t n,m=0; register char *cp; if(whence==SEEK_CUR) { whence= -1; n = offset - dp->plast; iop->next = iop->data + n; offset = dp->llast; } else { whence = 1; n = offset - dp->llast; offset = dp->plast; } offset +=n; if((n -= dp->skip) > 0) { m=whence; cp = (char*)dp->buff; while(n--) { if(*cp++=='\r' && *cp=='\n') { m += whence; if(whence>0) n++; } } } if(whence<0) iop->next += m; return(offset+m); } #if __STD_C static Sfoff_t dos_seek(Sfio_t *iop, Sfoff_t offset, register int whence, Sfdisc_t* disc) #else static Sfoff_t dos_seek(iop, offset, whence, disc) Sfio_t *iop; Sfoff_t offset; register int whence; Sfdisc_t* disc; #endif { register Dosdisc_t *dp = (Dosdisc_t*)disc; struct map dummy, *mp=0; off_t physical; register int n,size; retry: switch(whence) { case SEEK_CUR: offset = sfsk(iop, (off_t)0,SEEK_CUR,disc); if(offset<=dp->begin) return(offset); /* check for seek outside buffer */ if(offset==dp->phere) return(dp->lhere); else if(offset==dp->plast) return(dp->llast); else if(offsetplast || offset>dp->phere) mp = getmapping(dp,offset,whence); break; case SEEK_SET: /* check for seek outside buffer */ if(offsetllast || offset > dp->lhere) mp = getmapping(dp,offset,whence); break; case SEEK_END: if(!dp->maptable) return(sfsk(iop,offset,SEEK_END,disc)); mp = &dummy; mp->physical = dp->plast; mp->logical = dp->llast; break; } if(sfsetbuf(iop,(char*)iop,0)) size = sfslen(); else size = iop->endb-iop->data; if(mp) { sfsk(iop,mp->physical,SEEK_SET,disc); dp->phere = mp->physical; dp->lhere = mp->logical; if((*disc->readf)(iop,iop->data,size,disc)<0) return(-1); } while(1) { if(whence==SEEK_CUR && dp->phere>=offset) break; if(whence==SEEK_SET && dp->lhere>=offset) break; n=(*disc->readf)(iop,iop->data,size,disc); if(n < 0) return(-1); if(n==0) { if(whence==SEEK_END && offset<0) { offset = dp->lhere; whence=SEEK_SET; goto retry; } break; } } if(whence==SEEK_END) offset += dp->lhere; else { physical = cur_offset(dp,offset,iop,whence); if(whence==SEEK_SET) { sfsk(iop, physical ,SEEK_SET,disc); dp->phere = physical; dp->lhere = offset; } else offset = physical; } return(offset); } #if __STD_C static int dos_except(Sfio_t *iop, int type, void *arg, Sfdisc_t *disc) #else static int dos_except(iop, type, arg, disc) Sfio_t *iop; int type; void *arg; Sfdisc_t *disc; #endif { register Dosdisc_t *dp = (Dosdisc_t*)disc; if(type==SF_DPOP || type==SF_FINAL) { if(dp->bsize>0) free((void*)dp->buff); if(dp->mapsize) free((void*)dp->maptable); free((void*)disc); } return(0); } #if __STD_C int sfdcdos(Sfio_t *f) #else int sfdcdos(f) Sfio_t *f; #endif { Dosdisc_t *dos; /* this is a readonly discipline */ if(sfset(f,0,0)&SF_WRITE) return(-1); if(!(dos = (Dosdisc_t*)malloc(sizeof(Dosdisc_t))) ) return -1; memset(dos,'\0',sizeof(Dosdisc_t)); dos->disc.readf = dos_read; dos->disc.writef = NIL(Sfwrite_f); dos->disc.seekf = dos_seek; dos->disc.exceptf = dos_except; if(sfdisc(f,(Sfdisc_t*)dos) != (Sfdisc_t*)dos) { free(dos); return -1; } return(0); } return(0); } #if __STD_C int sfdcdos(Sfio_t *f) #else int sfdcdos(f) Sfio_t *f; #endif { Dosdisc_t *dos; /* this is a readonly discipline */ if(sfset(f,0,0)&SF_WRITE) return(-1); if(!(dos = (Dosdisc_t*)malloc(sizeof(Dosdisc_t))) ) return -1; memset(dossrc/lib/sfio/Sfio_dc/sfdcdio.c000644 151361 151361 00000007536 06777405343 016204 0ustar00kpvkpv000000 000000 #include "sfdchdr.h" /* Discipline to turn on direct IO capability. ** This currently only works for XFS on SGI's. ** ** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998. */ typedef struct _direct_s { Sfdisc_t disc; /* Sfio discipline */ int cntl; /* file control flags */ #ifdef FDIRECT struct dioattr dio; /* direct IO params */ #endif } Direct_t; /* convert a pointer to an int */ #define P2I(p) (Sfulong_t)((char*)(p) - (char*)0) #if __STD_C static ssize_t diordwr(Sfio_t* f, Void_t* buf, size_t n, Direct_t* di, int type) #else static ssize_t diordwr(f, buf, n, di, type) Sfio_t* f; Void_t* buf; size_t n; Direct_t* di; int type; #endif { size_t rw, done; ssize_t rv; done = 0; /* amount processed by direct IO */ #if FDIRECT if((P2I(buf)%di->dio.d_mem) == 0 && (f->here%di->dio.d_miniosz) == 0 && n >= di->dio.d_miniosz ) { /* direct IO ok, make sure we're in the right mode */ if(!(di->cntl & FDIRECT) ) { di->cntl |= FDIRECT; (void)fcntl(f->file, F_SETFL, di->cntl); } for(rw = (n/di->dio.d_miniosz)*di->dio.d_miniosz;; ) { size_t io; if((io = rw) > di->dio.d_maxiosz ) io = di->dio.d_maxiosz; if(type == SF_READ) rv = read(f->file,buf,io); else rv = write(f->file,buf,io); if(rv > 0) { rw -= rv; done += rv; buf = (Void_t*)((char*)buf + rv); } if(rv < io || rw < di->dio.d_miniosz) break; } } if(done < n && (di->cntl & FDIRECT) ) { /* turn off directIO for remaining IO operation */ di->cntl &= ~FDIRECT; (void)fcntl(f->file, F_SETFL, di->cntl); } #endif /*FDIRECT*/ if((rw = n-done) > 0 && (rv = type == SF_READ ? read(f->file,buf,rw) : write(f->file,buf,rw)) > 0 ) done += rv; return done ? done : rv; } #if __STD_C static ssize_t dioread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else static ssize_t dioread(f, buf, n, disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { return diordwr(f, buf, n, (Direct_t*)disc, SF_READ); } #if __STD_C static ssize_t diowrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) #else static ssize_t diowrite(f, buf, n, disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { return diordwr(f, (Void_t*)buf, n, (Direct_t*)disc, SF_WRITE); } #if __STD_C static dioexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) #else static dioexcept(f,type,data,disc) Sfio_t* f; int type; Void_t* data; Sfdisc_t* disc; #endif { Direct_t* di = (Direct_t*)disc; if(type == SF_FINAL || type == SF_DPOP) { #ifdef FDIRECT if(di->cntl&FDIRECT) { di->cntl &= ~FDIRECT; (void)fcntl(f->file,F_SETFL,di->cntl); } #endif free(disc); } return 0; } #if __STD_C int sfdcdio(Sfio_t* f, size_t bufsize) #else int sfdcdio(f, bufsize) Sfio_t* f; size_t bufsize; #endif { #ifndef FDIRECT return -1; #else int cntl; struct dioattr dio; Void_t* buf; Direct_t* di; if(f->extent < 0 || (f->flags&SF_STRING)) return -1; if((cntl = fcntl(f->file,F_GETFL,0)) < 0) return -1; if(!(cntl&FDIRECT) ) { cntl |= FDIRECT; if(fcntl(f->file,F_SETFL,cntl) < 0) return -1; } if(fcntl(f->file,F_DIOINFO,&dio) < 0) goto no_direct; if(bufsize > 0) bufsize = (bufsize/dio.d_miniosz)*dio.d_miniosz; if(bufsize <= 0) bufsize = dio.d_miniosz*64; if(bufsize > dio.d_maxiosz) bufsize = dio.d_maxiosz; if(!(di = (Direct_t*)malloc(sizeof(Direct_t))) ) goto no_direct; if(!(buf = (Void_t*)memalign(dio.d_mem,bufsize)) ) { free(di); goto no_direct; } sfsetbuf(f,buf,bufsize); if(sfsetbuf(f,buf,0) == buf) sfset(f,SF_MALLOC,1); else { free(buf); free(di); goto no_direct; } di->disc.readf = dioread; di->disc.writef = diowrite; di->disc.seekf = NIL(Sfseek_f); di->disc.exceptf = dioexcept; di->cntl = cntl; di->dio = dio; if(sfdisc(f,(Sfdisc_t*)di) != (Sfdisc_t*)di) { free(di); no_direct: cntl &= ~FDIRECT; (void)fcntl(f->file,F_SETFL,cntl); return -1; } return 0; #endif /*FDIRECT*/ } fsize)) ) { free(di); goto no_direct; } sfsetbuf(f,buf,bufsize); if(sfsetbuf(f,buf,0) == buf) sfset(f,SF_MALLOC,1); else { free(buf); free(di); gotsrc/lib/sfio/Sfio_dc/sfdctee.c000644 151361 151361 00000003440 06777405343 016174 0ustar00kpvkpv000000 000000 #include "sfdchdr.h" /* A discipline to tee the output to a stream to another stream. ** This is similar to what the "tee" program does. As implemented ** this discipline only works with file streams. ** ** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998. */ /* the discipline structure for tee-ing */ typedef struct _tee_s { Sfdisc_t disc; /* the sfio discipline structure */ Sfio_t* tee; /* the stream to tee to */ int status; /* if tee stream is still ok */ } Tee_t; /* write to the teed stream. */ #if __STD_C static ssize_t teewrite(Sfio_t* f, const Void_t* buf, size_t size, Sfdisc_t* disc) #else static ssize_t teewrite(f,buf,size,disc) Sfio_t* f; /* the stream being written to */ Void_t* buf; /* the buffer of data being output */ size_t size; /* the data size */ Sfdisc_t* disc; /* the tee discipline */ #endif { reg Tee_t* te = (Tee_t*)disc; /* tee data if still ok */ if(te->status == 0 && sfwrite(te->tee,buf,size) != (ssize_t)size) te->status = -1; /* do the actual write */ return sfwr(f,buf,size,disc); } /* on close, remove the discipline */ #if __STD_C static teeexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) #else static teeexcept(f,type,data,disc) Sfio_t* f; int type; Void_t* data; Sfdisc_t* disc; #endif { if(type == SF_FINAL || type == SF_DPOP) free(disc); return 0; } #if __STD_C int sfdctee(Sfio_t* f, Sfio_t* tee) #else int sfdctee(f, tee) Sfio_t* f; /* stream to tee from */ Sfio_t* tee; /* stream to tee to */ #endif { reg Tee_t* te; if(!(te = (Tee_t*)malloc(sizeof(Tee_t))) ) return -1; te->disc.readf = NIL(Sfread_f); te->disc.seekf = NIL(Sfseek_f); te->disc.writef = teewrite; te->disc.exceptf = teeexcept; te->tee = tee; te->status = 0; if(sfdisc(f,(Sfdisc_t*)te) != (Sfdisc_t*)te) { free(te); return -1; } return 0; } OP) free(disc); return 0; } #if __STD_C int sfdctee(Sfio_t* f, Sfio_t* tee) #else int sfdctee(f, tee) Sfio_t* f; /* stream to tee from */ Sfio_t* tee; /* stream to tee to */ #endif { reg Tee_t* te; if(!(te = (Tee_t*)src/lib/sfio/Sfio_dc/sfdcseekable.c000644 151361 151361 00000006300 06777405343 017170 0ustar00kpvkpv000000 000000 #include "sfdchdr.h" /* Discipline to make an unseekable read stream seekable ** ** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998. */ typedef struct _skable_s { Sfdisc_t disc; /* sfio discipline */ Sfio_t* shadow; /* to shadow data */ int eof; /* if eof has been reached */ } Seek_t; #if __STD_C static ssize_t skwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) #else static ssize_t skwrite(f, buf, n, disc) Sfio_t* f; /* stream involved */ Void_t* buf; /* buffer to read into */ size_t n; /* number of bytes to read */ Sfdisc_t* disc; /* discipline */ #endif { return (ssize_t)(-1); } #if __STD_C static ssize_t skread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else static ssize_t skread(f, buf, n, disc) Sfio_t* f; /* stream involved */ Void_t* buf; /* buffer to read into */ size_t n; /* number of bytes to read */ Sfdisc_t* disc; /* discipline */ #endif { Seek_t* sk; Sfio_t* sf; Sfoff_t addr, extent; ssize_t r, w; sk = (Seek_t*)disc; sf = sk->shadow; if(sk->eof) return sfread(sf,buf,n); addr = sfseek(sf,(Sfoff_t)0,1); extent = sfsize(sf); if(addr+n <= extent) return sfread(sf,buf,n); if((r = (ssize_t)(extent-addr)) > 0) { if((w = sfread(sf,buf,r)) != r) return w; buf = (char*)buf + r; n -= r; } /* do a raw read */ if((w = sfrd(f,buf,n,disc)) <= 0) { sk->eof = 1; w = 0; } else if(sfwrite(sf,buf,w) != w) sk->eof = 1; return r+w; } #if __STD_C static Sfoff_t skseek(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc) #else static Sfoff_t skseek(f, addr, type, disc) Sfio_t* f; Sfoff_t addr; int type; Sfdisc_t* disc; #endif { Sfoff_t extent; Seek_t* sk; Sfio_t* sf; char buf[SF_BUFSIZE]; ssize_t r, w; if(type < 0 || type > 2) return (Sfoff_t)(-1); sk = (Seek_t*)disc; sf = sk->shadow; extent = sfseek(sf,(Sfoff_t)0,2); if(type == 1) addr += sftell(sf); else if(type == 2) addr += extent; if(addr < 0) return (Sfoff_t)(-1); else if(addr > extent) { if(sk->eof) return (Sfoff_t)(-1); /* read enough to reach the seek point */ while(addr > extent) { if(addr > extent+sizeof(buf) ) w = sizeof(buf); else w = (int)(addr-extent); if((r = sfrd(f,buf,w,disc)) <= 0) w = r-1; else if((w = sfwrite(sf,buf,r)) > 0) extent += r; if(w != r) { sk->eof = 1; break; } } if(addr > extent) return (Sfoff_t)(-1); } return sfseek(sf,addr,0); } /* on close, remove the discipline */ #if __STD_C static skexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) #else static skexcept(f,type,data,disc) Sfio_t* f; int type; Void_t* data; Sfdisc_t* disc; #endif { if(type == SF_FINAL || type == SF_DPOP) { sfclose(((Seek_t*)disc)->shadow); free(disc); } return 0; } #if __STD_C int sfdcseekable(Sfio_t* f) #else int sfdcseekable(f) Sfio_t* f; #endif { reg Seek_t* sk; /* see if already seekable */ if(sfseek(f,(Sfoff_t)0,1) >= 0) return 0; if(!(sk = (Seek_t*)malloc(sizeof(Seek_t))) ) return -1; sk->disc.readf = skread; sk->disc.writef = skwrite; sk->disc.seekf = skseek; sk->disc.exceptf = skexcept; sk->shadow = sftmp(SF_BUFSIZE); sk->eof = 0; if(sfdisc(f, (Sfdisc_t*)sk) != (Sfdisc_t*)sk) { sfclose(sk->shadow); free(sk); return -1; } return 0; } #if __STD_C int sfdcseekable(Sfio_t* f) #else int sfdcseekable(f) Sfio_t* f; #endif { reg Seek_t* sk; /* see if already seekable */ if(sfseek(f,(Sfoff_t)0,1) >= 0) return 0; if(!(sk = (Seek_t*)malloc(sizeof(Seek_t))) ) return -1; sk->disc.readf = skread; sk->disc.writef = skwrite; sk->disc.seekf = skseek;src/lib/sfio/Sfio_dc/Makefile000644 151361 151361 00000001121 07432234530 016030 0ustar00kpvkpv000000 000000 # makefile for discipline functions # # Written by Kiem-Phong Vo # Compiler and flags to use LIBTYPE= CXFLAGS= CCMODE= -O CCFLAGS= -I. -I.. $(CCMODE) $(LIBTYPE) $(CXFLAGS) AR= ar CC= cc # sfdisc HDRS= sfdchdr.h sfdisc.h SRCS= sfdcdio.c sfdcdos.c sfdcfilter.c sfdclzw.c sfdcseekable.c sfdcslow.c \ sfdcsubstream.c sfdctee.c sfdcunion.c OBJS= sfdcdio.o sfdcdos.o sfdcfilter.o sfdclzw.o sfdcseekable.o sfdcslow.o \ sfdcsubstream.o sfdctee.o sfdcunion.o .c.o: $(CC) -c $(CCFLAGS) $*.c must: $(OBJS) 3dupdate: cp Makefile $(HDRS) $(SRCS) ... clean: -(rm $(OBJS); exit 0) >/dev/null 2>&1 flags to use LIBTYPE= CXFLAGS= CCMODE= -O CCFLAGS= -I. -I.. $(CCMODE) $(LIBTYPE) $(CXFLAGS) AR= ar CC= cc # sfdisc HDRS= sfdchdr.h sfdisc.h SRCS= sfdcdio.c sfdcdos.c sfdcfilter.c sfdclzw.c sfdcseekable.c sfdcslow.c \ sfdcsubstream.c sfdctee.c sfdcunion.c OBJS= sfdcdio.o sfdcdos.o sfdcfilter.o sfdclzw.o sfdcseekable.o sfdcslow.o \ sfdcsubstream.o sfdctee.o sfdcunion.o .c.o: $(CC) -c $(CCFLAGS) $*.c must: $(OBJS) 3dupdate:src/lib/sfio/Sfio_dc/sfdcsubstream.c000644 151361 151361 00000007246 06777405343 017434 0ustar00kpvkpv000000 000000 #include "sfdchdr.h" /* Discipline to treat a contiguous segment of a stream as a stream ** in its own right. The hard part in all this is to allow multiple ** segments of the stream to be used as substreams at the same time. ** ** Written by David G. Korn and Kiem-Phong Vo (03/18/1998) */ typedef struct _subfile_s { Sfdisc_t disc; /* sfio discipline */ Sfio_t* parent; /* parent stream */ Sfoff_t offset; /* starting offset */ Sfoff_t extent; /* size wanted */ Sfoff_t here; /* current seek location */ } Subfile_t; #if __STD_C static ssize_t streamio(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc, int type) #else static ssize_t streamio(f, buf, n, disc, type) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; int type; #endif { reg Subfile_t *su; reg Sfoff_t here, parent; reg ssize_t io; su = (Subfile_t*)disc; /* read just what we need */ if(su->extent >= 0 && (ssize_t)n > (io = (ssize_t)(su->extent - su->here)) ) n = io; if(n <= 0) return n; /* save current location in parent stream */ parent = sfseek(su->parent,(Sfoff_t)0,1); /* read data */ here = su->here + su->offset; if(sfseek(su->parent,here,0) != here) io = 0; else { if(type == SF_WRITE) io = sfwrite(su->parent,buf,n); else io = sfread(su->parent,buf,n); if(io > 0) su->here += io; } /* restore parent current position */ sfseek(su->parent,parent,0); return io; } #if __STD_C static ssize_t streamwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) #else static ssize_t streamwrite(f, buf, n, disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { return streamio(f,(Void_t*)buf,n,disc,SF_WRITE); } #if __STD_C static ssize_t streamread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else static ssize_t streamread(f, buf, n, disc) Sfio_t* f; Void_t* buf; size_t n; Sfdisc_t* disc; #endif { return streamio(f,buf,n,disc,SF_READ); } #if __STD_C static Sfoff_t streamseek(Sfio_t* f, Sfoff_t pos, int type, Sfdisc_t* disc) #else static Sfoff_t streamseek(f, pos, type, disc) Sfio_t* f; Sfoff_t pos; int type; Sfdisc_t* disc; #endif { reg Subfile_t* su; reg Sfoff_t here, parent; su = (Subfile_t*)disc; switch(type) { case 0: here = 0; break; case 1: here = su->here; break; case 2: if(su->extent >= 0) here = su->extent; else { parent = sfseek(su->parent,(Sfoff_t)0,1); if((here = sfseek(su->parent,(Sfoff_t)0,2)) < 0) return -1; else here -= su->offset; sfseek(su->parent,parent,0); } break; default: return -1; } pos += here; if(pos < 0 || (su->extent >= 0 && pos >= su->extent)) return -1; return (su->here = pos); } #if __STD_C static streamexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) #else static streamexcept(f, type, data, disc) Sfio_t* f; int type; Void_t* data; Sfdisc_t* disc; #endif { if(type == SF_FINAL || type == SF_DPOP) free(disc); return 0; } #if __STD_C int sfdcsubstream(Sfio_t* f, Sfio_t* parent, Sfoff_t offset, Sfoff_t extent) #else int sfdcsubstream(f, parent, offset, extent) Sfio_t* f; /* stream */ Sfio_t* parent; /* parent stream */ Sfoff_t offset; /* offset in parent stream */ Sfoff_t extent; /* desired size */ #endif { reg Subfile_t* su; reg Sfoff_t here; /* establish that we can seek to offset */ if((here = sfseek(parent,(Sfoff_t)0,1)) < 0 || sfseek(parent,offset,0) < 0) return -1; else sfseek(parent,here,0); if(!(su = (Subfile_t*)malloc(sizeof(Subfile_t))) ) return -1; su->disc.readf = streamread; su->disc.writef = streamwrite; su->disc.seekf = streamseek; su->disc.exceptf = streamexcept; su->parent = parent; su->offset = offset; su->extent = extent; if(sfdisc(f, (Sfdisc_t*)su) != (Sfdisc_t*)su) { free(su); return -1; } return 0; } /* establish that we can seek to offset */ if((here = sfseek(parent,(Sfoff_t)0,1)) < 0 || sfseek(parent,offset,0) < 0) return -1; else sfseek(parent,here,0); if(!(su = (Subfile_t*)malloc(sizeof(Subfile_t))) ) return -1; su->disc.readf = streamread; su->disc.writef = streamwrite; su->disc.seekf = streamseek; su->disc.exceptf = streasrc/lib/sfio/Sfio_dc/sfdisc.h000644 151361 151361 00000001054 06777405343 016036 0ustar00kpvkpv000000 000000 #ifndef _SFDISC_H #define _SFDISC_H 1 #include _BEGIN_EXTERNS_ /* functions to create disciplines */ extern int sfdcdio _ARG_((Sfio_t*, size_t)); extern int sfdcdos _ARG_((Sfio_t*)); extern int sfdcfilter _ARG_((Sfio_t*, const char*)); extern int sfdclzw _ARG_((Sfio_t*)); extern int sfdcseekable _ARG_((Sfio_t*)); extern int sfdcslow _ARG_((Sfio_t*)); extern int sfdcsubstream _ARG_((Sfio_t*, Sfio_t*, Sfoff_t, Sfoff_t)); extern int sfdctee _ARG_((Sfio_t*, Sfio_t*)); extern int sfdcunion _ARG_((Sfio_t*, Sfio_t**, int)); _END_EXTERNS_ #endif ude _BEGIN_EXTERNS_ /* functions to create disciplines */ extern int sfdcdio _ARG_((Sfio_t*, size_t)); extern int sfdcdos _ARG_((Sfio_t*)); extern int sfdcfilter _ARG_((Sfio_t*, const char*)); extern int sfdclzw _ARG_((Sfio_t*)); extern int sfdcseekable _ARG_((Sfio_t*)); extern int sfdcslow _ARG_((Sfio_t*)); extern int sfdcsubstream _ARG_((Sfio_t*, Sfio_t*, Sfoff_t, Sfoff_t)); extern int sfdctee _ARG_((Sfio_t*, Sfio_t*)); extern int sfdcunion _ARG_((Sfiosrc/lib/sfio/Sfio_dc/sfdclzw.c000644 151361 151361 00000023151 06777405343 016234 0ustar00kpvkpv000000 000000 #include "sfdchdr.h" /* * compress.c - File compression ala IEEE Computer, June 1984. * * Authors: Spencer W. Thomas (decvax!utah-cs!thomas) * Jim McKie (decvax!mcvax!jim) * Steve Davies (decvax!vax135!petsd!peora!srd) * Ken Turkowski (decvax!decwrl!turtlevax!ken) * James A. Woods (decvax!ihnp4!ames!jaw) * Joe Orost (decvax!vax135!petsd!joe) * * July, 1992, Jim Arnold * Modified uncompress code to work as a discipline under sfio. * Didn't need compression code and deleted it. * * Kiem-Phong Vo (03/18/1998) * Small interface modifications to conform with other disciplines. */ /***************************************************************** * Algorithm from "A Technique for High Performance Data Compression", * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19. * * Algorithm: * Modified Lempel-Ziv method (LZW). Basically finds common * substrings and replaces them with a variable size code. This is * deterministic, and can be done on the fly. Thus, the decompression * procedure needs no input table, but tracks the way the table was built. */ #ifndef LZWBITS # define LZWBITS 16 #endif #define INIT_BITS 9 /* initial number of bits/code */ /* Defines for third byte of header. * Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is * a fourth header byte (for expansion). If the BLOCK_MASK is set, * the CODE_CLEAR is disabled. Instead of flushing all the codes, * they are simply overwritten. */ #define BIT_MASK 0x1f #define BLOCK_MASK 0x80 /* The next two codes should not be changed lightly, as they must not * lie within the contiguous general code space. */ #define CODE_FIRST 257 /* first free entry */ #define CODE_CLEAR 256 /* table clear output code */ #define MAXCODE(n_bits) ((1 << (n_bits)) - 1) /* A code_int must hold 2**LZWBITS non-negative values, and also -1 */ #if LZWBITS > 15 typedef long int code_int; #else typedef int code_int; #endif typedef unsigned char char_type; typedef struct { Sfdisc_t disc; int init; int n_bits; /* number of bits/code */ int maxbits; /* user settable max # bits/code */ int block_compress; code_int maxcode; /* maximum code, given n_bits */ code_int maxmaxcode; /* should NEVER generate this code */ code_int free_ent; /* first unused entry */ int clear_flg; int finchar; char_type* stackp; code_int code; code_int oldcode; code_int incode; int gc_offset; /* getcode() */ int gc_size; /* getcode() */ char_type* gc_buf; /* getcode() */ char_type* io_ptr; char_type* io_end; char io_buf[LZWBITS + 8192]; char_type de_stack[8000]; char_type tab_suffix [1 << LZWBITS]; unsigned short tab_prefix [1 << LZWBITS]; } LZW_Disc; static char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; #if __STD_C static int peek(Sfio_t* f, char_type** bufp, int count, reg LZW_Disc* disc) #else static int peek(f, bufp, count, disc) Sfio_t* f; char_type** bufp; int count; reg LZW_Disc* disc; #endif { reg int io_sz, j; if (count <= 0) return count; if (count > LZWBITS) return -1; if ((io_sz = disc->io_end - disc->io_ptr) < count) { memcpy(disc->io_buf + LZWBITS - io_sz, disc->io_ptr, io_sz); disc->io_ptr = (char_type *)disc->io_buf + LZWBITS - io_sz; j = sfrd(f, disc->io_buf + LZWBITS, sizeof disc->io_buf - LZWBITS, (Sfdisc_t *)disc); if (j < 0) j = 0; io_sz += j; disc->io_end = disc->io_ptr + io_sz; } *bufp = disc->io_ptr; if (io_sz < count) count = io_sz; disc->io_ptr += count; return count; } /***************************************************************** * TAG( getcode ) * * Read one code from the standard input. If EOF, return -1. * Inputs: * stdin * Outputs: * code or -1 is returned. */ #if __STD_C static code_int getcode(Sfio_t* f, LZW_Disc* disc) #else static code_int getcode(f, disc) Sfio_t* f; LZW_Disc* disc; #endif { reg code_int code; reg int r_off, bits; reg char_type *bp; if ( disc->clear_flg > 0 || disc->gc_offset >= disc->gc_size || disc->free_ent > disc->maxcode ) { /* * If the next entry will be too big for the current code * size, then we must increase the size. This implies reading * a new buffer full, too. */ if ( disc->free_ent > disc->maxcode ) { if (++disc->n_bits > disc->maxbits) return -1; if ( disc->n_bits == disc->maxbits ) disc->maxcode = disc->maxmaxcode; else disc->maxcode = MAXCODE(disc->n_bits); } if ( disc->clear_flg > 0) { disc->maxcode = MAXCODE (disc->n_bits = INIT_BITS); disc->clear_flg = 0; } disc->gc_size = peek(f, &disc->gc_buf, disc->n_bits, disc); if ( disc->gc_size <= 0 ) return -1; /* end of file */ disc->gc_offset = 0; /* Round size down to integral number of codes */ disc->gc_size = (disc->gc_size << 3) - (disc->n_bits - 1); } bp = disc->gc_buf; r_off = disc->gc_offset; bits = disc->n_bits; /* * Get to the first byte. */ bp += (r_off >> 3); r_off &= 7; /* Get first part (low order bits) */ code = (*bp++ >> r_off); bits -= (8 - r_off); r_off = 8 - r_off; /* now, offset into code word */ /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ if ( bits >= 8 ) { code |= *bp++ << r_off; r_off += 8; bits -= 8; } /* high order bits. */ code |= (*bp & rmask[bits]) << r_off; disc->gc_offset += disc->n_bits; return code; } #if __STD_C static int lzwExcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) #else static int lzwExcept(f, type, data, disc) Sfio_t* f; int type; Void_t* data; Sfdisc_t* disc; #endif { if(type == SF_FINAL || type == SF_DPOP) free(disc); return 0; } /* * Uncompress. This routine adapts to the codes in the * file building the "string" table on-the-fly; requiring no table to * be stored in the compressed file. The tables used herein are shared * with those of the compress() routine. See the definitions above. */ #if __STD_C ssize_t lzwRead(Sfio_t* f, Void_t* iobuf, size_t iocnt, Sfdisc_t* sfdisc) #else ssize_t lzwRead(f, iobuf, iocnt, sfdisc) Sfio_t* f; Void_t* iobuf; size_t iocnt; Sfdisc_t* sfdisc; #endif { LZW_Disc *disc = (LZW_Disc *)sfdisc; reg char_type *stackp; reg code_int code; char *ioend = (char*)iobuf + iocnt; register char *ioptr = iobuf; #define END_REGS {disc->code=code;disc->stackp=stackp;} #define BEGIN_REGS {code=disc->code;stackp=disc->stackp;} BEGIN_REGS if (disc->init <= 0) { char_type *p; if (disc->init < 0) return disc->init; if (iocnt <= 0) return iocnt; /* Check the magic number */ if (peek(f, &p, 3, disc) != 3 || *p++ != (char_type)0x1f || *p++ != (char_type)0x9d) return disc->init = -1; disc->maxbits = *p; /* set -b from file */ disc->block_compress = disc->maxbits & BLOCK_MASK; disc->maxbits &= BIT_MASK; disc->maxmaxcode = 1 << disc->maxbits; if(disc->maxbits > LZWBITS) return disc->init = -1; disc->init = 1; /* * As above, initialize the first 256 entries in the table. */ disc->maxcode = MAXCODE(disc->n_bits = INIT_BITS); for ( code = 255; code >= 0; code-- ) { disc->tab_prefix[code] = 0; disc->tab_suffix[code] = (char_type)code; } disc->free_ent = ((disc->block_compress) ? CODE_FIRST : 256 ); stackp = disc->de_stack; disc->finchar = disc->oldcode = getcode(f, disc); if(disc->oldcode == -1) /* EOF already? */ { END_REGS return 0; /* Get out of here */ } *ioptr++ = (char)disc->finchar; if ((code = getcode(f, disc)) < 0) { END_REGS return 1; } } do { if (stackp <= disc->de_stack) { if ( (code == CODE_CLEAR) && disc->block_compress ) { for ( code = 255; code >= 0; code-- ) disc->tab_prefix[code] = 0; disc->clear_flg = 1; disc->free_ent = CODE_FIRST - 1; if ( (code = getcode (f, disc)) == -1 ) break; } else if (code < 0) break; disc->incode = code; /* * Special case for KwKwK string. */ if ( code >= disc->free_ent ) { *stackp++ = disc->finchar; code = disc->oldcode; } /* * Generate output characters in reverse order */ while ( code >= 256 ) { *stackp++ = disc->tab_suffix[code]; code = disc->tab_prefix[code]; } *stackp++ = disc->finchar = disc->tab_suffix[code]; } /* * And put them out in forward order */ do { if (ioptr >= ioend) { END_REGS return iocnt; } *ioptr++ = *--stackp; }while ( stackp > disc->de_stack ); /* * Generate the new entry. */ if ( (code=disc->free_ent) < disc->maxmaxcode ) { disc->tab_prefix[code] = (unsigned short)disc->oldcode; disc->tab_suffix[code] = disc->finchar; disc->free_ent = code+1; } /* * Remember previous code. */ disc->oldcode = disc->incode; } while ((code = getcode(f, disc)) >= 0); END_REGS return ioptr - (char*)iobuf; } #if __STD_C static Sfoff_t lzwSeek(Sfio_t* f, Sfoff_t offset, int whence, Sfdisc_t* disc) #else static Sfoff_t lzwSeek(f, offset, whence, disc) Sfio_t* f; Sfoff_t offset; int whence; Sfdisc_t* disc; #endif { return (Sfoff_t)(-1); } #if __STD_C static ssize_t lzwWrite(Sfio_t* f, const Void_t* buf, size_t count, Sfdisc_t* disc) #else static ssize_t lzwWrite(f, buf, count, disc) Sfio_t* f; Void_t* buf; size_t count; Sfdisc_t* disc; #endif { return (ssize_t)(-1); } #if __STD_C int sfdclzw(Sfio_t* f) #else int sfdclzw(f) Sfio_t* f; #endif { LZW_Disc* lz; if (!(lz = (LZW_Disc *)malloc(sizeof(LZW_Disc))) ) return -1; lz->disc.readf = lzwRead; lz->disc.writef = lzwWrite; lz->disc.seekf = lzwSeek; lz->disc.exceptf = lzwExcept; lz->init = 0; lz->clear_flg = 0; lz->gc_offset = 0; lz->gc_size = 0; lz->io_ptr = (char_type *)lz->io_buf + LZWBITS; lz->io_end = (char_type *)lz->io_buf + LZWBITS; if(sfdisc(f, (Sfdisc_t*)lz) != (Sfdisc_t*)lz) { free(lz); return -1; } return 0; } zw(Sfio_t* f) #else int sfdclzw(f) Sfio_t* f; #endif { LZW_Disc* lz; if (!(lz = (LZW_Disc *)malloc(sizeof(LZW_Disc))) ) return -1; lz->disc.readf = lzwRead; lz->disc.writef = lzwWrite; lz->disc.seekf = lzwSeek; lz->disc.exceptf = lzwExcept; lz->init = 0; lz->clear_flg = 0; lz->gc_offset = 0; lz->gc_size = 0; lz->io_ptr = (char_type *)lz->io_buf + LZWBITS; lz->io_end = (char_type *)lz->io_bsrc/lib/sfio/Sfio_dc/sfdcunion.c000644 151361 151361 00000006737 07476550276 016566 0ustar00kpvkpv000000 000000 #include "sfdchdr.h" /* Make a sequence of streams act like a single stream. ** This is for reading only. ** ** Written by Kiem-Phong Vo, kpv@research.att.com, 03/18/1998. */ #define UNSEEKABLE 1 typedef struct _file_s { Sfio_t* f; /* the stream */ Sfoff_t lower; /* its lowest end */ } File_t; typedef struct _union_s { Sfdisc_t disc; /* discipline structure */ short type; /* type of streams */ short c; /* current stream */ short n; /* number of streams */ Sfoff_t here; /* current location */ File_t f[1]; /* array of streams */ } Union_t; #if __STD_C static ssize_t unwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc) #else static ssize_t unwrite(f, buf, n, disc) Sfio_t* f; /* stream involved */ Void_t* buf; /* buffer to read into */ size_t n; /* number of bytes to read */ Sfdisc_t* disc; /* discipline */ #endif { return -1; } #if __STD_C static ssize_t unread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc) #else static ssize_t unread(f, buf, n, disc) Sfio_t* f; /* stream involved */ Void_t* buf; /* buffer to read into */ size_t n; /* number of bytes to read */ Sfdisc_t* disc; /* discipline */ #endif { reg Union_t* un; reg ssize_t r, m; un = (Union_t*)disc; m = n; f = un->f[un->c].f; while(1) { if((r = sfread(f,buf,m)) < 0 || (r == 0 && un->c == un->n-1) ) break; m -= r; un->here += r; if(m == 0) break; buf = (char*)buf + r; if(sfeof(f) && un->c < un->n-1) f = un->f[un->c += 1].f; } return n-m; } #if __STD_C static Sfoff_t unseek(Sfio_t* f, Sfoff_t addr, int type, Sfdisc_t* disc) #else static Sfoff_t unseek(f, addr, type, disc) Sfio_t* f; Sfoff_t addr; int type; Sfdisc_t* disc; #endif { reg Union_t* un; reg int i; reg Sfoff_t extent, s; un = (Union_t*)disc; if(un->type&UNSEEKABLE) return (Sfoff_t)(-1); if(type == 2) { extent = 0; for(i = 0; i < un->n; ++i) extent += (sfsize(un->f[i].f) - un->f[i].lower); addr += extent; } else if(type == 1) addr += un->here; if(addr < 0) return (Sfoff_t)(-1); /* find the stream where the addr could be in */ extent = 0; for(i = 0; i < un->n-1; ++i) { s = sfsize(un->f[i].f) - un->f[i].lower; if(addr < extent + s) break; extent += s; } s = (addr-extent) + un->f[i].lower; if(sfseek(un->f[i].f,s,0) != s) return (Sfoff_t)(-1); un->c = i; un->here = addr; for(i += 1; i < un->n; ++i) sfseek(un->f[i].f,un->f[i].lower,0); return addr; } /* on close, remove the discipline */ #if __STD_C static unexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc) #else static unexcept(f,type,data,disc) Sfio_t* f; int type; Void_t* data; Sfdisc_t* disc; #endif { if(type == SF_FINAL || type == SF_DPOP) free(disc); return 0; } #if __STD_C int sfdcunion(Sfio_t* f, Sfio_t** array, int n) #else int sfdcunion(f, array, n) Sfio_t* f; Sfio_t** array; int n; #endif { reg Union_t* un; reg int i; if(n <= 0) return -1; if(!(un = (Union_t*)malloc(sizeof(Union_t)+(n-1)*sizeof(File_t))) ) return -1; un->disc.readf = unread; un->disc.writef = unwrite; un->disc.seekf = unseek; un->disc.exceptf = unexcept; un->type = 0; un->c = 0; un->n = n; un->here = 0; for(i = 0; i < n; ++i) { un->f[i].f = array[i]; if(!(un->type&UNSEEKABLE)) { un->f[i].lower = sfseek(array[i],(Sfoff_t)0,1); if(un->f[i].lower < 0) un->type |= UNSEEKABLE; } } if(sfdisc(f,(Sfdisc_t*)un) != (Sfdisc_t*)un) { free(un); return -1; } return 0; } t*)malloc(sizeof(Union_t)+(n-1)*ssrc/lib/sfio/Sfio_dc/sfdchdr.h000644 151361 151361 00000000047 06777405343 016201 0ustar00kpvkpv000000 000000 #include "sfhdr.h" #include _o_/home/kpv/Software/src/lib/sfio/Sfio_dccexceptf = unexcept; un->type = 0; un->c = 0; un->n = n; un->here = 0; for(i = 0; i < n; ++i) { un->f[i].f = array[i]; if(!(un->type&UNSEEKABLE)) { un->f[i].lower = sfseek(array[i],(Sfoff_t)0,1); if(un->f[i].lower < 0) un->type |= UNSEEKABLE; } } if(sfdisc(f,(Sfdisc_t*)un'AV=Jd .77H@src/lib/vthread/vtmtxclose.c000644 151361 151361 00000000703 07002245007 016072 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Free a mutex. ** ** Written by Kiem-Phong Vo. */ #if __STD_C int vtmtxclose(Vtmutex_t* mtx) #else int vtmtxclose(mtx) Vtmutex_t* mtx; #endif { #if !vt_threaded return -1; #else if(!mtx) return -1; if(vtmtxclrlock(mtx) < 0) return -1; #if _WIN32 DeleteCriticalSection(&mtx->lock); #else pthread_mutex_destroy(&mtx->lock); #endif /*_WIN32*/ if(mtx->state&VT_FREE) free(mtx); return 0; #endif /*vt_threaded*/ } V=Q!8=o5=o5@src/lib/vthread/vtopen.c000644 151361 151361 00000003543 07211001200 015165 0ustar00kpvkpv000000 000000 #include "vthdr.h" static char* Version = "\n@(#)vthread (AT&T Labs - kpv) 2000-12-01\0\n"; /* Open a thread handle ** ** Written by Kiem-Phong Vo */ #if __STD_C Vthread_t* vtopen(Vthread_t* vt, int flags) #else Vthread_t* vtopen(vt, flags) Vthread_t* vt; int flags; #endif { #if !vt_threaded return NIL(Vthread_t*); #else Vthread_t* v; int s, slot, myvt; VTONCE(); v = (Vthread_t*)Version; /* shut compiler warning */ vtmtxlock(_Vtmutex); myvt = 0; if(vt) { /* if there is a running thread, wait for its termination */ for(slot = 0; slot < _Vtnlist; ++slot) if(_Vtlist[slot] == vt) break; if(slot < _Vtnlist && (vt->state&VT_RUNNING) ) { vtmtxunlock(_Vtmutex); if(vtwait(vt) < 0) return NIL(Vthread_t*); vtmtxlock(_Vtmutex); } if(slot == _Vtnlist) goto find_slot; } else { find_slot: for(slot = 0; slot < _Vtnlist; ++slot) if(_Vtlist[slot] == NIL(Vthread_t*)) break; } /* create a slot for this new thread if necessary */ if(slot >= _Vtnlist) { Vthread_t** list; #define INCR 8 if(!(list = (Vthread_t**)malloc((slot+INCR)*sizeof(Vthread_t*))) ) { vtmtxunlock(_Vtmutex); return NIL(Vthread_t*); } if(_Vtnlist > 0) { memcpy(list,_Vtlist,_Vtnlist*sizeof(Vthread_t*)); free(_Vtlist); } _Vtlist = list; _Vtnlist += INCR; for(s = slot; s < _Vtnlist; ++s) list[s] = NIL(Vthread_t*); } if(!(v = vt) ) { if(!(v = (Vthread_t*)malloc(sizeof(Vthread_t))) ) { vtmtxunlock(_Vtmutex); return NIL(Vthread_t*); } flags |= VT_INIT|VT_FREE; myvt = 1; } if(flags&VT_INIT) { v->state = (flags&VT_FREE); v->stack = 0; v->error = 0; v->exit = NIL(Void_t*); #if !_WIN32 if(pthread_attr_init(&v->attrs) != 0) { if(myvt) free(v); vtmtxunlock(_Vtmutex); return NIL(Vthread_t*); } #endif } _Vtlist[slot] = v; vtmtxunlock(_Vtmutex); return v; #endif /*vt_threaded*/ } } if(!(v = vt) ) { if(!(v = (Vthread_t*)malloc(sizeof(Vthread_t))) ) { vtmtxunlock(_Vtmutex); return NIL(Vthread_t*); } flags |= VT_INIT|VT_FREE;src/lib/vthread/vtwait.c000644 151361 151361 00000001242 07075143564 015216 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Wait for a thread to end ** ** Written by Kiem-Phong Vo */ #if __STD_C int vtwait(Vthread_t* vt) #else int vtwait(vt) Vthread_t* vt; #endif { #if !vt_threaded return -1; #else int rv; if(!vt) return -1; if(!(vt->state&VT_RUNNING) ) { vt->error = 0; return -1; } #if _WIN32 if((rv = WaitForSingleObject(vt->self, INFINITE)) == 0xffffffff) vt->error = GetLastError(); else { vt->exit = (Void_t*)rv; rv = 0; CloseHandle(vt->self); } #else if((rv = pthread_join(vt->self, &vt->exit)) != 0) vt->error = rv; #endif if(rv == 0) vt->state = (vt->state & ~VT_RUNNING) | VT_WAITED; return rv ? -1 : 0; #endif /*vt_threaded*/ } f { #if !vt_threaded return -1; #else int rv; if(!vt) return -1; if(!(vt->state&VT_RUNNING) ) { vt->error = 0; return -1; } #if _WIN32 if((rv = WaitForSingleObject(vt->self, INFINITE)) == 0xffffffff) vt->error = GetLastError(); else { vt->exit = (Void_t*)rv; rv = 0; CloseHandle(vt->self); } #else if((rv = pthread_join(vt->sesrc/lib/vthread/vtmtxclrlock.c000644 151361 151361 00000003130 07002243623 016415 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Clear all locks on a mutex. ** ** Written by Kiem-Phong Vo. */ #if __STD_C int vtmtxclrlock(Vtmutex_t* mtx) #else int vtmtxclrlock(mtx) Vtmutex_t* mtx; #endif { #if !vt_threaded return -1; #else int rv; if(!mtx ) return -1; #if _WIN32 #define _did_clrlock 1 EnterCriticalSection(&mtx->lock); for(; mtx->count > 0; mtx->count -= 1) LeaveCriticalSection(&mtx->lock); mtx->count = 0; LeaveCriticalSection(&mtx->lock); return rv=0; #endif /*_WIN32*/ #if !_did_clrlock && _mtx_recursive #define _did_clrlock 1 if((rv = pthread_mutex_lock(&mtx->lock)) == MTXLOCK_OK ) { for(; mtx->count > 0; mtx->count -= 1) pthread_mutex_unlock(&mtx->lock); mtx->count = 0; pthread_mutex_unlock(&mtx->lock); return 0; } else { mtx->error = rv; return -1; } #endif #if !_did_clrlock && _mtx_errorcheck && !_hpux_pthread #define _did_clrlock 1 if((rv = pthread_mutex_lock(&mtx->lock)) == MTXLOCK_OK ) { mtx->count = 0; mtx->owner = pthread_self(); pthread_mutex_unlock(&mtx->lock); return 0; } else if(rv == EDEADLK && pthread_equal(pthread_self(), mtx->owner) ) { mtx->count = 0; pthread_mutex_unlock(&mtx->lock); return 0; } else { mtx->error = rv; return -1; } #endif #if !_did_clrlock if((rv = pthread_mutex_trylock(&mtx->lock)) == MTXTRYLOCK_OK ) { mtx->count = 0; mtx->owner = pthread_self(); pthread_mutex_unlock(&mtx->lock); return 0; } else if(MTXBUSY(rv) && pthread_equal(pthread_self(), mtx->owner) ) { mtx->count = 0; pthread_mutex_unlock(&mtx->lock); return 0; } else { mtx->error = rv; return -1; } #endif #endif /*vt_threaded*/ } tx->count = 0; pthread_mutex_unlock(&mtx->lock); return 0; } else { mtx->error = rv; return -1; } #endif #if !_did_clrlock if((rv = pthread_mutex_trylock(&mtx->lock)) == MTXTRYLOCK_OK ) { mtx->count = 0; mtx->owner = pthread_self(); pthread_mutex_unlock(&mtx->lock); return 0; } else if(MTXBUSY(rv) && pthread_equal(pthread_self(), mtx->owner) ) { mtx->count = 0; pthread_mutex_unlock(&mtx->lock); src/lib/vthread/vtextern.c000644 151361 151361 00000000116 07002227232 015537 0ustar00kpvkpv000000 000000 #include "vthdr.h" Vtextern_t _Vtextern; Vtonce_t _Vtonce = VTONCE_INITDATA; /home/kpv/Software/src/lib/vthreaddx_unlock(&mtx->lock); return 0; } else { mtx->error = rv; return -1; } #endif #if !_did_clrlock if((rv = pthread_mutex_trylock(&mtx->lock)) == MTXTRYLOCK_OK ) { mtx->count = 0; mtx->owner = pthread_self(); pthread_mutex_unlock(&mtx->lock); return 0; } else if(MTXBUSY(rv) && pthre'AV=?*;< 3P;< 3P@src/lib/vthread/vthread.h000644 151361 151361 0000000000007432261527 021370 1src/lib/sfio/vthread.hustar00kpvkpv000000 000000 src/lib/vthread/vtrun.c000644 151361 151361 00000001176 07075143412 015054 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Run a thread ** ** Written by Kiem-Phong Vo */ #if __STD_C int vtrun(Vthread_t* vt, Void_t* (*startf)(Void_t*), Void_t* arg) #else int vtrun(vt, startf, arg) Vthread_t* vt; Void_t* (*startf)(); Void_t* arg; #endif { #if !vt_threaded return -1; #else #if _WIN32 vt->self = CreateThread(0, (DWORD)vt->stack, (LPTHREAD_START_ROUTINE)startf, (LPVOID)arg, 0, &vt->id); vt->error = vt->self ? 0 : EPERM; #else vt->error = pthread_create(&vt->self, ATTR(vt->attrs), startf, arg); vt->id = vt->self; #endif if(!vt->error) vt->state |= VT_RUNNING; return vt->error ? -1 : 0; #endif /*vt_threaded*/ } Void_t*), Void_t* arg) #else int vtrun(vt, startf, arg) Vthread_t* vt; Void_t* (*startf)(); Void_t* arg; #endif { #if !vt_threaded return -1; #else #if _WIN32 vt->self = CreateThread(0, (DWORD)vt->stack, (LPTHREAD_START_ROUTINE)startf, (LPVOID)arg, 0, &vt->id); vt->error = vt->self ? 0 : EPERM; #else vt->error = pthread_create(&vt->self, ATTR(vt->attrs), startf, arg); src/lib/vthread/vtset.c000644 151361 151361 00000001061 07210770031 015026 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Set attributes of a thread ** ** Written by Kiem-Phong Vo */ #if __STD_C int vtset(Vthread_t* vt, int type, Void_t* val) #else int vtset(vt, type, val) Vthread_t* vt; int type; Void_t* val; #endif { #if !vt_threaded return -1; #else int rv; if(!vt) return -1; if(type == VT_STACK) { vt->stack = (size_t)val; #if _WIN32 rv = 0; #else if((rv = pthread_attr_setstacksize(&vt->attrs, (size_t)val)) != 0) vt->error = rv; #endif } else { vt->error = EINVAL; rv = -1; } return rv ? -1 : 0; #endif /*vt_threaded*/ } ** ** Written by Kiem-Phong Vo */ #if __STD_C int vtset(Vthread_t* vt, int type, Void_t* val) #else int vtset(vt, type, val) Vthread_t* vt; int type; Void_t* val; #endif { #if !vt_threaded return -1; #else int rv; if(!vt) return -1; if(type == VT_STACK) { vt->stack = (size_t)val; #if _WIN32 rv = 0; #else if((rv = pthread_attr_setstacksize(&vt->attrs, (size_t)val)) != 0) vt->error = rv; #endif } else { vt->error = EINVAL; rv = -1; }src/lib/vthread/vtmtxtrylock.c000644 151361 151361 00000002037 07002243644 016463 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Try to lock a mutex. ** ** Written by Kiem-Phong Vo. */ #if __STD_C int vtmtxtrylock(Vtmutex_t* mtx) #else int vtmtxtrylock(mtx) Vtmutex_t* mtx; #endif { #if !vt_threaded return -1; #else int rv; if(!mtx) return -1; #if _WIN32 #define _did_trylock 1 if(_Vttrylockf && (*_Vttrylockf)(&mtx->lock) ) { if(mtx->count <= 0) mtx->count = 1; else mtx->count += 1; return rv=0; } else { mtx->error = EBUSY; return -1; } #endif /*_WIN32*/ #if !_did_trylock && _mtx_recursive #define _did_trylock 1 if((rv = pthread_mutex_trylock(&mtx->lock)) == MTXTRYLOCK_OK) { if(mtx->count <= 0) mtx->count = 1; else mtx->count += 1; return 0; } else { mtx->error = rv; return -1; } #endif #if !_did_trylock if((rv = pthread_mutex_trylock(&mtx->lock)) == MTXTRYLOCK_OK) { mtx->count = 1; mtx->owner = pthread_self(); return 0; } else if(MTXBUSY(rv) && pthread_equal(pthread_self(), mtx->owner) ) { mtx->count += 1; return 0; } else { mtx->error = rv; return -1; } #endif #endif /*vt_threaded*/ } v = pthread_mutex_trylock(&mtx->lock)) == MTXTRYLOCK_OK) { if(mtx->count <= 0) mtx->count = 1; else mtx->count += 1; return 0; } else { mtx->error = rv; return -1; } #endif #if !_did_trylock if((rv = pthread_mutex_trylock(&mtx->lock)) == MTXTRYLOCK_OK) { mtx->count = 1; mtx->owner = pthread_self(); return 0; } else if(MTXBUSY(rv) && pthread_equal(pthread_self(), mtx->owner) ) { mtx->count += 1; return 0; } else { mtx->error = rv; return -1; } #esrc/lib/vthread/README000644 151361 151361 00000001522 07317134360 014406 0ustar00kpvkpv000000 000000 This directory contains the source code for the Vthread library. Despite the promise of the Posix pthread interface, multi-threading is still a haphazard as far as portable programming is concerned. For this reason, Vthread provides a set of functions for portable threads including mutex handling. Vthread is known to run on all known Unix flavors including Linux, BSD, Irix, HPUX, Solaris, etc. and all known Window versions. DIRECTORY HIERARCHY: . : source code for Vthread ./features: source code for generating configuration parameters. ./Vthread_t: regression tests. SOFTWARE CONSTRUCTION: To build the library, type: make -f Makefile install CORRESPONDENCE: Comments, etc. should be sent to: Phong Vo AT&T Labs - Research 180 Park Avenue Florham Park, NJ 07932 e-mail: kpv@research.att.com ix flavors including Linux, BSD, Irix, HPUX, Solaris, etc. and all known Window versions. DIRECTORY HIERARCHY: . : source code for Vthread ./features: source code for gensrc/lib/vthread/Makefile000644 151361 151361 00000002322 07254205553 015170 0ustar00kpvkpv000000 000000 # libvthread.a makefile # Written by Kiem-Phong Vo INCDIR= ../../../include LIBDIR= ../../../lib BINDIR= ../../../bin CXFLAGS= CCMODE= -O CCFLAGS= $(CCMODE) -I. $(CXFLAGS) CC=cc HDRS= vthread.h vthdr.h SRCS= vtclose.c vtextern.c vtkill.c vtmtxclose.c vtmtxclrlock.c \ vtmtxlock.c vtmtxopen.c vtmtxtrylock.c vtmtxunlock.c \ vtonce.c vtopen.c vtrun.c vtself.c vtset.c vtwait.c OBJS= vtclose.o vtextern.o vtkill.o vtmtxclose.o vtmtxclrlock.o \ vtmtxlock.o vtmtxopen.o vtmtxtrylock.o vtmtxunlock.o \ vtonce.o vtopen.o vtrun.o vtself.o vtset.o vtwait.o .c.o : $(CC) -c $(CCFLAGS) $*.c %.o : %.c $(CC) -c $(CCFLAGS) $*.c all: install libvthread.a : ast_common.h FEATURE/vthread $(OBJS) ar cr libvthread.a $(OBJS) -(ranlib libvthread.a; exit 0) >/dev/null 2>&1 ast_common.h : features/common $(BINDIR)/iffe - set cc $(CC) $(CCMODE) $(CXFLAGS) : \ run features/common > ast_common.h FEATURE/vthread : features/vthread $(BINDIR)/iffe set cc $(CC) $(CCMODE) $(CXFLAGS) : run features/vthread install : libvthread.a cp vthread.h ast_common.h $(INCDIR); cp libvthread.a $(LIBDIR); -(ranlib $(LIBDIR)/libvthread.a; exit 0) >/dev/null 2>&1 clean : -(rm ast_common.h $(OBJS) libvthread.a FEATURE/*; exit 0) >/dev/null 2>&1 (ranlib libvthread.a; exit 0) >/dev/null 2>&1 ast_common.h : features/common $(BINDIR)/iffe - set cc $(CC) $(CCMODE) $(CXFLAGS) : \ run features/common > ast_common.h FEATURE/vthread : features/vthread $(BINDIR)/iffe set cc $(CC) $(CCMODE) $(CXFLAGS) : run features/vthread install : libvthread.src/lib/vthread/vtself.c000644 151361 151361 00000000750 07002240435 015167 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Identify self ** ** Written by Kiem-Phong Vo */ Vthread_t* vtself() { #if !vt_threaded return NIL(Vthread_t*); #else Vthread_t* vt; _vtid_t id; int t; #if _WIN32 #define IDEQUAL(id1,id2) (id1 == id2) id = GetCurrentThreadId(); #else #define IDEQUAL(id1,id2) pthread_equal(id1,id2) id = pthread_self(); #endif for(t = 0; t < _Vtnlist; ++t) if((vt = _Vtlist[t]) && IDEQUAL(id, vt->id) ) return vt; return NIL(Vthread_t*); #endif /*vt_threaded*/ } *;< 3P;< 3P@src/lib/vthread/vtmtxopen.c000644 151361 151361 00000003126 07002651610 015731 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Create or initialize a mutex. ** ** Written by Kiem-Phong Vo. */ /* this get done once per process */ void _vtonce() { #if vt_threaded #if _WIN32 char sys_dir[MAX_PATH]; int n; HANDLE hm; /* get the win32 TryEnterCriticalSection function */ n = GetSystemDirectory(sys_dir, sizeof(sys_dir)); sys_dir[n++] = '\\'; strcpy(&sys_dir[n], "kernel32"); if((hm = GetModuleHandle(sys_dir)) ) _Vttrylockf = (Vttrylock_f)GetProcAddress(hm,"TryEnterCriticalSection"); #endif _Vtinit = 1; /* initialize the global mutex that we use internally */ vtmtxopen(_Vtmutex, VT_INIT); #endif } #if __STD_C Vtmutex_t* vtmtxopen(Vtmutex_t* mtx, int flags) #else Vtmutex_t* vtmtxopen(mtx, flags) Vtmutex_t* mtx; int flags; #endif { #if !vt_threaded return NIL(Vtmutex_t*); #else Vtmutex_t* m; VTONCE(); if(!(m = mtx)) { if(!(m = (Vtmutex_t*)malloc(sizeof(Vtmutex_t))) ) return NIL(Vtmutex_t*); flags = VT_INIT|VT_FREE; } if(flags & VT_INIT) { m->count = 0; m->error = 0; m->state = 0; #if _WIN32 #define _did_init 1 InitializeCriticalSection(&m->lock); m->owner = 0; #endif /*_WIN32*/ #if !_did_init && defined(MTXTYPE) #define _did_init 1 { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, MTXTYPE); pthread_mutex_init(&m->lock, ATTR(attr)); pthread_mutexattr_destroy(&attr); m->owner = pthread_self(); } #endif #if !_did_init /*BSD or Solaris*/ pthread_mutex_init(&m->lock, NIL(pthread_mutexattr_t*)); m->owner = pthread_self(); #endif } m->state |= (flags&VT_FREE); return m; #endif /*vt_threaded*/ } ndif /*_WIN32*/ #if !_did_init && defined(MTXTYPE) #define _did_init 1 { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, MTXTYPE); pthread_mutex_init(&m->lock, ATTR(attr)); pthread_mutexattr_destroy(&attr); m->owner = pthread_self(); } #endif #if !_did_init /*BSD or Solaris*/ pthread_mutex_init(&m->lock, NIL(pthread_mutexattr_t*)); m->owner = pthread_ssrc/lib/vthread/vtmtxunlock.c000644 151361 151361 00000003421 07002243651 016263 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Unlock a mutex. ** ** Written by Kiem-Phong Vo. */ #if __STD_C int vtmtxunlock(Vtmutex_t* mtx) #else int vtmtxunlock(mtx) Vtmutex_t* mtx; #endif { #if !vt_threaded return -1; #else int rv; if(!mtx ) return -1; #if _WIN32 #define _did_unlock 1 EnterCriticalSection(&mtx->lock); if(mtx->count <= 0) { mtx->error = EINVAL; rv = -1; } else { rv = 0; mtx->count -= 1; LeaveCriticalSection(&mtx->lock); } LeaveCriticalSection(&mtx->lock); return rv; #endif /*_WIN32*/ #if !_did_unlock && _mtx_recursive #define _did_unlock 1 if((rv = pthread_mutex_lock(&mtx->lock)) == MTXLOCK_OK) { if(mtx->count <= 0) { mtx->error = EPERM; rv = -1; } else { mtx->count -= 1; pthread_mutex_unlock(&mtx->lock); rv = 0; } pthread_mutex_unlock(&mtx->lock); return rv; } else { mtx->error = EPERM; return -1; } #endif #if !_did_unlock && _mtx_errorcheck #define _did_unlock 1 if((rv = pthread_mutex_lock(&mtx->lock)) == MTXLOCK_OK) { mtx->count = 0; mtx->owner = pthread_self(); pthread_mutex_unlock(&mtx->lock); return 0; } else if(rv == EDEADLK && pthread_equal(pthread_self(), mtx->owner) ) { if((mtx->count -= 1) > 0) return 0; else { mtx->count = 0; pthread_mutex_unlock(&mtx->lock); return 0; } } else { mtx->error = EPERM; return -1; } #endif #if !_did_unlock /* bsd, solaris */ if((rv = pthread_mutex_trylock(&mtx->lock)) == MTXTRYLOCK_OK) { mtx->count = 0; mtx->owner = pthread_self(); pthread_mutex_unlock(&mtx->lock); return 0; } else if(MTXBUSY(rv) && pthread_equal(pthread_self(), mtx->owner) ) { if((mtx->count -= 1) > 0) return 0; else { mtx->count = 0; pthread_mutex_unlock(&mtx->lock); return 0; } } else { mtx->error = EPERM; return -1; } #endif #endif /*vt_threaded*/ } >error = EPERM; return -1; } #endif #if !_did_unlock /* bsd, solaris */ if((rv = pthread_mutex_trylock(&mtx->lock)) == MTXTRYLOCK_OK) { mtx->count = 0; mtx->owner = pthread_self(); pthread_mutex_unlock(&mtx->lock); return 0; }src/lib/vthread/vtclose.c000644 151361 151361 00000001251 07210760071 015344 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Deleting a thread ** ** Written by Kiem-Phong Vo */ #if __STD_C int vtclose(Vthread_t* vt) #else int vtclose(vt) Vthread_t* vt; #endif { #if !vt_threaded return -1; #else int s; if(!vt ) return -1; vtmtxlock(_Vtmutex); for(s = 0; s < _Vtnlist; ++s) if(_Vtlist[s] == vt) break; if(s == _Vtnlist) { vt->error = EINVAL; vtmtxunlock(_Vtmutex); return -1; } else if((vt->state&VT_RUNNING) && vtwait(vt) < 0) { vtmtxunlock(_Vtmutex); return -1; } _Vtlist[s] = NIL(Vthread_t*); #if !_WIN32 pthread_attr_destroy(&vt->attrs); #endif if(vt->state & VT_FREE) free(vt); vtmtxunlock(_Vtmutex); return 0; #endif /*vt_threaded*/ } threaded return -1; #else int s; if(!vt ) return -1; vtmtxlock(_Vtmutex); for(s = 0; s < _Vtnlist; ++s) if(_Vtlist[s] == vt) break; if(s == _Vtnlist) { vt->error = EINVAL; vtmtxunlock(_Vtmutex); return -1; } else if((vt->state&VT_RUNNING) && vtwait(vt) < 0) { vtmtxunlock(_Vtmutex); return -1; } _Vtlist[s] = NIL(src/lib/vthread/vthdr.h000644 151361 151361 00000010260 07253761524 015034 0ustar00kpvkpv000000 000000 #ifndef _VTHDR_H #define _VTHDR_H 1 #include #include "FEATURE/vthread" #if !vt_threaded /* for creating sub functions */ #undef vtopen #undef vtclose #undef vtkill #undef vtwait #undef vtrun #undef vtset #undef vtonce #undef vtmtxopen #undef vtmtxclose #undef vtmtxlock #undef vtmtxtrylock #undef vtmtxunlock #undef vtmtxclrlock #undef vtstatus #undef vterror #undef vtmtxerror #undef vtonceerror #endif /*!vt_threaded*/ #ifndef NIL #define NIL(t) ((t)0) #endif #if _num_PTHREAD_MUTEX_ERRORCHECK #define _mtx_errorcheck 1 #endif #if _num_PTHREAD_MUTEX_RECURSIVE #define _mtx_recursive 1 #endif /* Linux */ #if _num_PTHREAD_MUTEX_ERRORCHECK_NP && !_mtx_errorcheck #define PTHREAD_MUTEX_ERRORCHECK PTHREAD_MUTEX_ERRORCHECK_NP #define _mtx_errorcheck 1 #endif #if defined(PTHREAD_MUTEX_ERRORCHECK_NP) && !_mtx_errorcheck #define PTHREAD_MUTEX_ERRORCHECK PTHREAD_MUTEX_ERRORCHECK_NP #define _mtx_errorcheck 1 #endif #if _num_PTHREAD_MUTEX_RECURSIVE_NP && !_mtx_recursive #define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP #define _mtx_recursive 1 #endif #if defined(PTHREAD_MUTEX_ERRORCHECK_NP) && !_mtx_recursive #define PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP #define _mtx_recursive 1 #endif /* pre-HPUX 11 strangeness */ #if !_lib_pthread_attr_init && _num_MUTEX_NONRECURSIVE_NP #define _hpux_weirdness 1 #endif #if _num_MUTEX_NONRECURSIVE_NP && !_mtx_errorcheck #define PTHREAD_MUTEX_ERRORCHECK MUTEX_NONRECURSIVE_NP #define _mtx_errorcheck 1 #endif #if defined(MUTEX_NONRECURSIVE_NP) && !_mtx_errorcheck #define PTHREAD_MUTEX_ERRORCHECK MUTEX_NONRECURSIVE_NP #define _mtx_errorcheck 1 #endif #if _num_MUTEX_RECURSIVE_NP && !_mtx_recursive #define PTHREAD_MUTEX_RECURSIVE MUTEX_RECURSIVE_NP #define _mtx_recursive 1 #endif #if defined(MUTEX_RECURSIVE_NP) && !_mtx_recursive #define PTHREAD_MUTEX_RECURSIVE MUTEX_RECURSIVE_NP #define _mtx_recursive 1 #endif #if !_lib_pthread_mutexattr_init && _lib_pthread_mutexattr_create #define pthread_mutexattr_init pthread_mutexattr_create #endif #if !_lib_pthread_mutexattr_destroy && _lib_pthread_mutexattr_delete #define pthread_mutexattr_destroy pthread_mutexattr_delete #endif #if !_lib_pthread_attr_init && _lib_pthread_attr_create #define pthread_attr_init pthread_attr_create #endif #if !_lib_pthread_attr_destroy && _lib_pthread_attr_delete #define pthread_attr_destroy pthread_attr_delete #endif /* define pthread_mutexattr_settype() based on detected alternatives */ #if !_lib_pthread_mutexattr_settype #if _lib_pthread_mutexattr_setkind_np #undef pthread_mutexattr_setkind #undef _lib_pthread_mutexattr_setkind #define pthread_mutexattr_setkind pthread_mutexattr_setkind_np #define _lib_pthread_mutexattr_setkind 1 #endif #if _lib_pthread_mutexattr_setkind #undef pthread_mutexattr_settype #define pthread_mutexattr_settype pthread_mutexattr_setkind #define _lib_pthread_mutexattr_settype 1 #endif #endif /*!_lib_pthread_mutexattr_settype*/ /* because of irix and hpux quirks, we'll bias toward mtx_errorcheck */ #if _mtx_errorcheck && _mtx_recursive #undef _mtx_recursive #endif #if _mtx_errorcheck #define MTXTYPE PTHREAD_MUTEX_ERRORCHECK #endif #if _mtx_recursive #define MTXTYPE PTHREAD_MUTEX_RECURSIVE #endif /* deal with pre-hpux11's lapse of judgement! */ #if _hpux_weirdness #define MTXTRYLOCK_OK 1 #define MTXLOCK_OK 0 #define MTXUNLOCK_OK 0 #define MTXBUSY(rv) (rv == 0) #define ATTR(attr) (attr) #else #define MTXTRYLOCK_OK 0 #define MTXLOCK_OK 0 #define MTXUNLOCK_OK 0 #define MTXBUSY(rv) (rv == EBUSY) #define ATTR(attr) (&attr) #endif /* variables local to library */ typedef struct _vtextern_s Vtextern_t; typedef int (*Vttrylock_f) _ARG_((_vtmtx_t*)); struct _vtextern_s { Vtmutex_t vt_mutex; Vthread_t** vt_list; int vt_nlist; Vttrylock_f vt_trylockf; int vt_init; }; #define _Vtmutex (&_Vtextern.vt_mutex) #define _Vtlist _Vtextern.vt_list #define _Vtnlist _Vtextern.vt_nlist #define _Vttrylockf _Vtextern.vt_trylockf #define _Vtinit _Vtextern.vt_init #define VTONCE() (_Vtinit ? 0 : vtonce(&_Vtonce, _vtonce) ) _BEGIN_EXTERNS_ extern Vtextern_t _Vtextern; extern void _vtonce(); extern Vtonce_t _Vtonce; extern Void_t* malloc _ARG_((size_t)); extern void free _ARG_((Void_t*)); _END_EXTERNS_ #endif /*_VTHDR_H*/ vt_nlist; Vttrylock_f vt_trylockf; int vt_init; }; #define _Vtmutex (&_Vtextern.vt_mutex) #define _Vtlist _Vtextern.vt_list #define _Vtnlist _Vtextern.vt_nlist #define _Vttrylockf _Vtextern.vt_trylockf #define _Vtinit _Vtextern.vt_init #define VTONCE() (_Vtinit ? 0 : vtonce(&_Vtonce, _vtonce) ) _BEGIN_EXTERNS_ extern Vtextern_src/lib/vthread/vtmtxlock.c000644 151361 151361 00000002647 07002243632 015730 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Lock a mutex. ** ** Written by Kiem-Phong Vo. */ #if __STD_C int vtmtxlock(Vtmutex_t* mtx) #else int vtmtxlock(mtx) Vtmutex_t* mtx; #endif { #if !vt_threaded return -1; #else int rv; if(!mtx ) return -1; #if _WIN32 #define _did_lock 1 EnterCriticalSection(&mtx->lock); if(mtx->count <= 0) mtx->count = 1; else mtx->count += 1; return rv=0; #endif #if !_did_lock && _mtx_recursive #define _did_lock 1 if((rv = pthread_mutex_lock(&mtx->lock)) == MTXLOCK_OK) { if(mtx->count <= 0) mtx->count = 1; else mtx->count += 1; return 0; } else { mtx->error = rv; return -1; } #endif #if !_did_lock && _mtx_errorcheck && !_hpux_pthread #define _did_lock 1 if((rv = pthread_mutex_lock(&mtx->lock)) == MTXLOCK_OK) { mtx->count = 1; mtx->owner = pthread_self(); return 0; } else if(rv == EDEADLK && pthread_equal(pthread_self(), mtx->owner)) { mtx->count += 1; return 0; } else { mtx->error = rv; return -1; } #endif #if !_did_lock /* hpux,solaris,bsd */ if((rv = pthread_mutex_trylock(&mtx->lock)) == MTXTRYLOCK_OK) { mtx->count = 1; mtx->owner = pthread_self(); return 0; } else if(MTXBUSY(rv) && pthread_equal(pthread_self(), mtx->owner) ) { mtx->count += 1; return 0; } else if((rv = pthread_mutex_lock(&mtx->lock)) == MTXLOCK_OK) { mtx->count = 1; mtx->owner = pthread_self(); return 0; } else { mtx->error = rv; return -1; } #endif #endif /*vt_threaded*/ } tx->error = rv; return -1; } #endif #if !_did_lock /* hpux,solaris,bsd */ if((rv = psrc/lib/vthread/vtkill.c000644 151361 151361 00000001106 07253762235 015204 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Deleting a thread ** ** Written by Kiem-Phong Vo */ #if __STD_C int vtkill(Vthread_t* vt) #else int vtkill(vt) Vthread_t* vt; #endif { #if !vt_threaded return -1; #else int rv; if(!vt) return -1; if(!(vt->state&VT_RUNNING) ) { vt->error = 0; return -1; } #if _WIN32 if((rv = TerminateThread(vt->self, 0)) == FALSE) { vt->error = GetLastError(); rv = -1; } else rv = 0; #else if((rv = pthread_cancel(vt->self)) != 0) { vt->error = rv; rv = -1; } #endif if(rv == 0) vt->state &= ~VT_RUNNING; return rv; #endif /*!vt_threaded*/ } o */ #if __STD_C int vtkill(Vthread_t* vt) #else int vtkill(vt) Vthread_t* vt; #endif { #if !vt_threaded return -1; #else int rv; if(!vt) return -1; if(!(vt->state&VT_RUNNING) ) { vt->error = 0; return -1; } #if _WIN32 if((rv = TerminateThread(vt->self, 0)) == FALSE) { vt->error = GetLastError(); rv = -1; } else rv = 0; #else if((rv = pthread_cancel(vt->self)) != 0) { vt->error = rv; rv = -1; } #endif if(rv == 0src/lib/vthread/vtonce.c000644 151361 151361 00000001231 07002243000 015144 0ustar00kpvkpv000000 000000 #include "vthdr.h" /* Execute some set of actions exactly once ** ** Written by Kiem-Phong Vo */ #if __STD_C int vtonce(Vtonce_t* once, void(*func)() ) #else int vtonce(once, func) Vtonce_t* once; void (*func)(); #endif { #if !vt_threaded return -1; #else int rv; if(!func) { once->error = EINVAL; return -1; } if(once->done) return 0; #if _WIN32 if(InterlockedIncrement(&once->once) == 1) { (*func)(); once->done = 1; } else { once->once = 2; while(!once->done) Sleep(1); } rv = 0; #else if((rv = pthread_once(&once->once, func)) != 0) once->error = rv; else once->done = 1; #endif return rv ? -1 : 0; #endif /*vt_threaded*/ } ) #else int vtonce(once, func) Vtonce_t* once; void (*func)(); #endif { #if !vt_threaded return -1; #else int rv; if(!func) { once->error = EINVAL; return -1; } if(once->done) return 0; #if _WIN32 if(InterlockedIncrement(&once->once) == 1) { (*func)(); once->done = 1; } else { once->once = 2; while(!once->done) Sleep(1); } rv = 0;src/lib/vthread/NOTICE000644 151361 151361 0000000000007317131241 015256 1NOTICEustar00kpvkpv000000 000000 src/lib/vthread/Vthread_t/terror.h000644 151361 151361 0000000000007477666274 024476 1src/lib/sfio/Stdio_t/terror.hustar00kpvkpv000000 000000 src/lib/vthread/Vthread_t/tmutex.c000644 151361 151361 00000003525 07211001052 017125 0ustar00kpvkpv000000 000000 #include "vttest.h" #define NITEMS 100 #define NTHREADS 16 int Buf[NTHREADS*NITEMS]; int Count; Vtmutex_t Mutex; int Inverted; #if __STD_C void* stuff(void* arg) #else void* stuff(arg) void* arg; #endif { int n; if(!Inverted && vtmtxlock(&Mutex) < 0) terror("Can't lock mutex"); for(n = 0; n < NITEMS; ++n) { Buf[Count++] = (int)arg; #if _WIN32 Sleep(1); /* give up thread control */ #endif } if(!Inverted && vtmtxunlock(&Mutex) < 0) terror("Can't unlock mutex"); return NIL(Void_t*); } main() { Vthread_t* vt[NTHREADS]; int i, count[NTHREADS]; if(vtmtxopen(&Mutex, VT_INIT) != &Mutex) terror("Can't create mutex"); do_inverted: if(Inverted) tmesg("\tTesting non-locking threads\n"); else tmesg("\tTesting locking threads\n"); /* prepare buffer */ for(i = 0; i < NTHREADS*NITEMS; ++i) Buf[i] = -1; Count = 0; for(i = 0; i < NTHREADS; ++i) { if(!(vt[i] = vtopen(0,0)) ) terror("Can't create thread handle"); if(vtrun(vt[i], stuff, (Void_t*)i) < 0) terror("Can't run thread %d", i); } for(i = 0; i < NTHREADS; ++i) if(vtwait(vt[i]) < 0) terror("Wait failed"); if(Count != NTHREADS*NITEMS) { if(!Inverted) terror("Wrong Count"); else tsuccess("Wrong Count as expected."); } for(i = 0; i < NTHREADS; ++i) count[i] = 0; for(i = 0; i < NTHREADS*NITEMS; i += NITEMS) { int k; count[Buf[i]] += 1; for(k = 1; k < NITEMS; ++k) { if(Buf[k+i] != Buf[i]) { if(!Inverted) terror("Buffer messed up"); else tsuccess("Buffer messed up as expected."); } } } for(i = 0; i < NTHREADS; ++i) { if(count[i] != 1 ) { if(!Inverted) terror("Count wrong"); else tsuccess("Count wrong as expected."); } } if(!Inverted) { tmesg("\t\tLocking threads work fine."); Inverted = 1; goto do_inverted; } else tmesg("\t\tNon-locking threads also work - weird but ok!\n"); return 0; } += 1; for(k = 1; k < NITEMS; ++k) { if(Buf[k+i] != Buf[i]) { if(!Inverted) terror("Buffer messed up"); else tsuccess("Buffer messed up as expected."); }src/lib/vthread/Vthread_t/vttest.h000644 151361 151361 00000000051 07002244041 017131 0ustar00kpvkpv000000 000000 #include "terror.h" #include _o_/home/kpv/Software/src/lib/vthread/Vthread_ttunt wrong as expected."); } } if(!Inverted) { tmesg("\t\tLocking threads work fine."); Inverted = 1; goto do_inverted; } else tmesg("\t\tNon-locking threads also work - weird but ok!\n"); return 0; } += 1; for(k = 1; k < NITEMS; ++k) { if(Buf[k+i] != Buf[i]) { if(!Inv AVL=?08 dX8 dX@src/lib/vthread/Vthread_t/runtest000755 151361 151361 00000002504 07002350521 017067 0ustar00kpvkpv000000 000000 ######################################################################### # Invocation arguments are: # # -lLIBRARY: a library to be linked with, e.g., -lpthread # # -v: verbose, print the compilation command # # -c: continue testing after a test fails # # -whatever_else: bad argument, will be ignored. # # tests: test cases to be run. If no test specified, # # all tests will be run. # # # # Written by Kiem-Phong Vo # ######################################################################### verbose=0 exit_on_fail=1 files="" LIBS="../libvthread.a" HDRS="" DEFS="-Dvt_threaded=1" XLIBS="" while test "$1" != "" do case $1 in -l*) XLIBS="$XLIBS $1"; ;; -v) verbose=1; ;; -c) exit_on_fail=0; ;; -*) echo "Hmm, unknown argument: $1"; ;; *) files="${files} $1"; ;; esac shift done if test "$CC" = ""; then CC="cc"; fi if test "$files" = "" then files="*.c" fi LIBS="$LIBS $XLIBS" if test "$verbose" = 1 then echo "Compiler invocation: $CC -g $DEFS -I. -I.. $HDRS xxx.c $LIBS -o ./t" fi for i in $files do echo "-- $i:" status="" if $CC -g $DEFS -I. -I.. $HDRS $i $LIBS -o ./t then if ./t then rm ./t; status=Passed else status=Failed fi else status="Not compiled" fi echo " $status" if test "$status" != "Passed" then if test "$exit_on_fail" = "1"; then exit; fi fi done f test "$CC" = ""; then CC="cc"; fi if test "$files" = "" then files="*.c" fi LIBS="$LIBS $XLIBS" if test "$verbose" = 1 then echo "Compiler invocation: $CC -g $DEFS -I. -I.. $HDRS xxxsrc/lib/vthread/features/vthread000644 151361 151361 00000001364 07210776733 016740 0ustar00kpvkpv000000 000000 hdr pthread lib pthread_mutexattr_settype -lpthread lib pthread_mutexattr_setkind -lpthread lib pthread_mutexattr_setkind_np -lpthread num PTHREAD_MUTEX_RECURSIVE pthread.h num PTHREAD_MUTEX_RECURSIVE_NP pthread.h num MUTEX_RECURSIVE_NP pthread.h num PTHREAD_MUTEX_ERRORCHECK pthread.h num PTHREAD_MUTEX_ERRORCHECK_NP pthread.h num MUTEX_NONRECURSIVE_NP pthread.h lib pthread_mutexattr_setkind -lcma lib pthread_mutexattr_setkind_np -lcma lib pthread_mutexattr_init pthread.h -lpthread lib pthread_mutexattr_destroy pthread.h -lpthread lib pthread_mutexattr_create -lcma lib pthread_mutexattr_delete -lcma lib pthread_attr_init pthread.h -lpthread lib pthread_attr_destroy pthread.h -lpthread lib pthread_attr_create -lcma lib pthread_attr_delete -lcma .h num PTHREAD_MUTEX_ERRORCHECK pthread.h num PTHREAD_MUTEX_ERRORCHECK_NP pthread.h num MUTEX_NONRECURSIVE_NP pthread.h lib pthread_mutexattr_setkind -lcma lib pthread_mutexattr_setkind_np -lcma lib pthread_mutexattr_init pthread.h -lpthread lib pthread_mutexattr_desrc/lib/vthread/features/common000644 151361 151361 0000000000007432510164 024030 1src/lib/sfio/features/commonustar00kpvkpv000000 000000