diff options
Diffstat (limited to 'src/lib/libast/man')
59 files changed, 12835 insertions, 0 deletions
diff --git a/src/lib/libast/man/LIBAST.3 b/src/lib/libast/man/LIBAST.3 new file mode 100644 index 0000000..380ebde --- /dev/null +++ b/src/lib/libast/man/LIBAST.3 @@ -0,0 +1,98 @@ +.fp 5 CW +.de Af +.if \\$2 .nr ;G \\$1 +.ie !\\$3 \{\ +\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" +\} +.. +.de aF +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" +.ft \\n(;G +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH LIBAST 3 +.UC 4 +.SH NAME +libast \- introduction to the ast library +.SH DESCRIPTION +This section describes the +.I AST +(AT&T Software Technology) library functions of the +.B libast +library. +.B libast +serves three major purposes. +First, it presents (a subset of) POSIX/ANSI standard headers and interfaces on +non-compliant systems. +Second, it provides a portable base of routines that implement concepts +common to all UNIX system variants. +Finally, it is a forum for +modern implementations of features present (or lacking) +in the standard C libraries. +Features better provided by separate libraries are omitted from +.BR libast . +For example, most terminal driver interface issues are left for +special purpose libraries such as +.IR curses (3). +.PP +The +.B libast +related header files are installed in the directories +.LR include/ast . +Routines that do not advertize their own headers are prototyped in +.LR <ast.h> . +.L <ast.h> +is ANSI, K&R and C++ compatible and includes or defines the equivalent of +.LR <limits.h> , +.LR <stddef.h> , +.LR <stdlib.h> , +.LR <sys/types.h> , +.L <string.h> +and +.LR <unistd.h> . +Other libraries that depend on +.B libast +may also have headers installed in the +.L include/ast +directories. +.SH FILES +.nf +include/ast the \fBast\fP package header directory +lib/libast.a the \fBlibast\fP library +lib/libast-g.a the \fBlibast\fP library compiled for debugging +lib/libast-pg.a the \fBlibast\fP library compiled for profiling +lib/libast.so.4.0 the \fBlibast\fP shared library +.fi +.SH "SEE ALSO" +intro(3), +intro(2), +cc(1) +.SH CAVEATS +The library documentation is still under construction. +Yes, some of it has been in this state for 20 years. +Thank goodness our commands self-document. diff --git a/src/lib/libast/man/aso.3 b/src/lib/libast/man/aso.3 new file mode 100644 index 0000000..0e41d30 --- /dev/null +++ b/src/lib/libast/man/aso.3 @@ -0,0 +1,355 @@ +.fp 5 CW +.TH LIBASO 3 +.SH NAME +\fBASO\fP \- Atomic Scalar Operations +.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 <aso.h> +.Ce +.Ss "TYPES" +.Cs +typedef int (*Asoerror_f)(int, const char*); +typedef void* (*Asoinit_f)(void*, const char*); +typedef ssize_t (*Asolock_f)(void*, ssize_t, void volatile*); + +typedef struct Asodisc_s +{ + uint32_t version; + unsigned int hung; + Asoerror_f errorf; +} Asodisc_t; + +typedef struct Asometh_s +{ + const char* name; + int type; + Asoinit_f initf; + Asolock_f lockf; + const char* details; +} Asometh_t; +.Ce +.Ss "OPERATIONS" +.Cs +uint8_t asocas8(uint8_t volatile*, int, int); +uint8_t asoget8(uint8_t volatile*); +uint8_t asoinc8(uint8_t volatile*); +uint8_t asodec8(uint8_t volatile*); + +uint16_t asocas16(uint16_t volatile*, uint16_t, uint16_t); +uint16_t asoget16(uint16_t volatile*); +uint16_t asoinc16(uint16_t volatile*); +uint16_t asodec16(uint16_t volatile*); + +uint32_t asocas32(uint32_t volatile*, uint32_t, uint32_t); +uint32_t asoget32(uint32_t volatile*); +uint32_t asoinc32(uint32_t volatile*); +uint32_t asodec32(uint32_t volatile*); + +uint64_t asocas64(uint64_t volatile*, uint64_t, uint64_t); +uint64_t asoget64(uint64_t volatile*); +uint64_t asoinc64(uint64_t volatile*); +uint64_t asodec64(uint64_t volatile*); + +unsigned char asocaschar(unsigned char volatile*, int, int); +unsigned char asogetchar(unsigned char volatile*); +unsigned char asoincchar(unsigned char volatile*); +unsigned char asodecchar(unsigned char volatile*); + +unsigned short asocasshort(unsigned short volatile*, unsigned short, unsigned short); +unsigned short asogetshort(unsigned short volatile*); +unsigned short asoincshort(unsigned short volatile*); +unsigned short asodecshort(unsigned short volatile*); + +unsigned int asocasint(unsigned int volatile*, unsigned int, unsigned int); +unsigned int asogetint(unsigned int volatile*); +unsigned int asoincint(unsigned int volatile*); +unsigned int asodecint(unsigned int volatile*); + +unsigned long asocaslong(unsigned long volatile*, unsigned long, unsigned long); +unsigned long asogetlong(unsigned long volatile*); +unsigned long asoinclong(unsigned long volatile*); +unsigned long asodeclong(unsigned long volatile*); + +size_t asocassize(size_t volatile*, size_t, size_t); +size_t asogetsize(size_t volatile*); +size_t asoincsize(size_t volatile*); +size_t asodecsize(size_t volatile*); + +void* asocasptr(void volatile*, void*, void*); +void* asogetptr(void volatile*); + +void ASODISC(Asodisc_t*, Asoerror_f); +Asometh_t* asometh(int, void*); +int asoinit(const char*, Asometh_t*, Asodisc_t*); +int asolock(unsigned int volatile*, unsigned int, int); +int asoloop(uintmax_t); +int asorelax(long); +.Ce +.SH DESCRIPTION +.PP +\fIASO\fP provides functions to perform atomic scalar operations. +The functions on the type \f5uint32_t\fP will be fully described below. +Other functions work similarly on their respective types. +Some of the functions may be macros that call other functions. +64 bit operations are provided if the compiler supports 64 bit integers and/or pointers. +.PP +.Ss "TYPES" +.PP +\f5uint8_t, uint16_t, uint32_t, uint64_t\fP + +These are \fIunsigned integer\fP types of different sizes in bits. +For example, \f5uint32_t\fP represents the type of unsigned integer with 32 bits or 4 bytes. +.PP +.Ss "OPERATIONS" +.PP +.Ss " uint32_t asoget32(uint32_t* from);" +This function returns the value \f5*from\fP. +.PP +.Ss " uint32_t asoinc32(uint32_t* dest);" +.Ss " uint32_t asodec32(uint32_t* dest);" +These functions increment \f5*dest\fP by 1 and decrement \f5*dest\fP by 1 in an atomic step. +The return value is the old value in \f5*dest\fP. + +Consider an example where two concurrent threads/processes call \f5asoinc32()\fP +on the same \f5dest\fP with values, say \fIv1\fP and \fIv2\fP. +The eventual value in \f5dest\fP +will be as if \f5*dest += 2\fP was performed in a single-threaded execution. + +That should be constrasted with a situation where, instead of \f5asoinc32()\fP or \f5asodec32()\fP, +only normal increment (++) or decrement (--) were used. +Then, the end result could be either \f5*dest += 1\fP or \f5*dest += 2\fP, +depending on states of the hardware cache and process scheduling. +.PP +.Ss " uint32_t asocas32(uint32_t* dest, uint32_t tstval, uint32_t newval);" +This function provides the atomic \fIcompare-and-swap\fP operation. +If the current content of \f5dest\fP is equal to \f5tstval\fP then it will be set to \f5newval\fP. +If multiple threads/processes are performing the same operations only one will succeed with a +return value of \f5tstval\fP. +The return value is the old value in \f5*dest\fP. +.PP +.Ss " void asorelax(long nsec)" +This function causes the calling process or thread to briefly pause +for \f5nsec\fP nanoseconds. +It is useful to implement tight loops that occasionally yield control. +.PP +.Ss " int asolock(unsigned int* lock, unsigned int key, int type)" +This function uses \f5key\fP, a non-zero unsigned integer, to lock or unlock the \f5lock\fP. +It returns \f50\fP on success and \f5-1\fP on failure. +The argument \f5type\fP can take one of the following values: +.Tp +\f5ASO_UNLOCK\fP: +This unlocks the lock if it was locked with \f5key\fP. It is an error to try +unlocking a lock of a different key. +.Tp +\f5ASO_TRYLOCK\fP: +This makes a single attempt to use the given \f5key\fP to acquire a lock. +An error will result if the lock is already locked with a different key. +.Tp +\f5ASO_LOCK\fP: +This is a regular locking call. If the lock is locked with a different key, +this call will wait until the lock is open, then lock it with the given \f5key\fP. +.Tp +\f5ASO_SPINLOCK\fP: +Regardless of what key is currently locking the lock, +this call will always wait until the lock is open, then lock it with the given \f5key\fP. +Note that, if the lock is already locked with \f5key\fP, this call can result +in a deadlock unless that lock can be opened by some other mechanism, e.g., +by a different process or thread. +.PP +.Ss " int asoloop(uintmax_t iteration);" +This function is used to implement spin locks that periodically relinquish the processor: +.Cs +uintmax_t iteration; +iteration = 0; +for (;;) { + /* test resource with an aso*() call */ + if (asoloop(++iteration)) + /* an error occurred */; +} +.Ce +The value of \f5iteration\fP should be \f51\fP (\fInot\fP \f50\fP) for the first loop iteration. +\f50\fP is returned on success, \f5-1\fP on failure. +If \f5iteration mod 4\fP is \f50\fP then \f5asorelax(1)\fP is called to temporarily relinquish +the processor. +If \f5Asodisc_t.hung != 0\fP and \f5Asodisc_t.errorf != 0\fP and +\f5iteration mod (2**Asodisc_t.hung-1)\fP is \f50\fP, +then \f5Asodisc_t.errorf\fP is called with type \f5ASO_HUNG\fP +and \f5-1\fP is returned. +.PP +.Ss "DISCIPLINE" +.PP +The Asodisc_t discipline structure allows the caller to modify default behavior. +The \fIASO\fP discipline is global for all threads and forked children of the current process. +The discipline is set and modified by the \f5asoinit()\fP function, described below. +The structure members are: +.Tp +\f5uint32_t version;\fP +This must be set to \f5ASO_VERSION\fP by the caller and is used by the implementation to detect +release differences between the caller and the implementation. +The version is integer of the form \fIYYYYMMDD\fP where \fIYYYY\fP is the release year, \fIMM\fP +is the release month, and \fIDD\fP is the release day of month. +This allows the implementation to be forwards and backwards binary compatible with all releases. +.Tp +\f5unsigned int hung;\fP +An error occurs if \f5asoloop\fP() is called \f52**Asometh_t.hung\fP times without gaining access to the loop resource. +The default value \f50\fP disables the test. +.Tp +\f5Asoerror_f errorf;\fP +\f5int (*errorf)(int type, const char* mesg);\fP +If \f5errorf\fP != \f50\fP then it is called for each \fIASO\fP fatal library condition. +\f5type\fP may be one of: \f5ASO_METHOD\fP - a method error; \f5ASO_HUNG\fP - \f5asoloop\fP() was called +\f52**Asometh_t.hung\fP times with no access to the loop resource. +\f5mesg\fP is a 0-terminated messsage description. +.Ss " void ASODISC(Asodisc_t* disc, Asoerror_f errorf);" +.PP +This function-like-macro initializes \f5disc->version = ASO_VERSION\fP, \f5disc->errorf = errorf\fP, +and the remaining \f5disc\fP members to \f50\fP. +.PP +.Ss "METHODS" +.PP +Several atomic locking methods are implemented for atomic operations +not supported by \fIintrinsic\fP functions or assembly instructions. +Methods are controlled by the \f5asometh()\fP and \f5asoinit()\fP +functions, described below. +The \fIASO\fP method is global for all threads and forked children of the current process. +A given method may have multiple types. +The methods types are: +.Tp +\f5ASO_INTRINSIC\fP: +Some hardware platforms provide machine instructions to implement these operations directly. +In that case, if a local compiler permits, calls to these \fIintrinsic\fP functions +may be translated directly into their corresponding machine instructions. +When necessary the implementation can use only the intrinsic \fIcompare-and-swap\fP +function on the largest integer type to emulate all other \fIASO\fP operations. +The \f5ASO_INTRINSIC\fP method type is the default when supported by the compiler. +It may be used for single-process single-thread, multi-thread, and +multi-process applications. +When supported by the hardware / compiler, the library provides the "\fBintrinsic\fP" method with type +\f5ASO_INTRINSIC|ASO_PROCESS|ASO_THREAD|ASO_SIGNAL\fP. +.Tp +\f5ASO_SIGNAL\fP: +This method type is suitable only for single-process single-thread applications. +It can be used to provide locking between asyncronous \fBsignal\fP(2) handlers +and the main program. +The library provides the "\fBsignal\fP" method with type \f5ASO_SIGNAL\fP. +This is the default method type when \f5ASO_INTRINSIC\fP is not supported. +.Tp +\f5ASO_THREAD\fP: +This method type is suitable for single-process single-thread, and multi-thread applications. +It typically requires thread library support, and since the default \f5aso\fP library +is not linked with a thread library, no \f5ASO_THREAD\fP method is provided by default. +Threaded applications must link with \fB-ltaso\fP (before \fB-laso\fP or \fB-last\fP) +in order to access \f5ASO_THREAD\fP methods. +The \fB-ltaso\fP library provides the "\fBspin\fP" (using \fBpthread_spin_lock\fP(3)) and +"\fBmutex"\fP (using \fBpthread_mutex_lock\fP(3)) methods with type \f5ASO_THREAD|ASO_SIGNAL\fP. +.Tp +\f5ASO_PROCESS\fP: +This method type is suitable for single-process single-thread, and multi-process applications. +Some \f5ASO_PROCESS\fP methods may also be suitable for multi-thread applications (if they have the \f5ASO_THREAD\fP type.) +These methods are typically and noticably \fIslow\fP, up to 2 orders of magnitude slower than +\f5ASO_INTRINSIC\fP for some applications. +They are provided as a last resort when other methods are not available. +The library provides the "\fBsemaphore\fP" method with type \f5ASO_PROCESS|ASO_THREAD|ASO_SIGNAL\fP +and the "\fBfcntl\fP" method with type \f5ASO_PROCESS|ASO_SIGNAL\fP. + +.Ss " Asometh_t* asometh(int type, void* data);" +This function looks up methods by type or name. +If type is \f50\fP and \f5data\fP is \f50\fP then the current method is returned; a valid method +will always be returned for this call. +If type is \f50\fP then \f5data\fP is treated as a \f50\fP-terminated string method name; +\f50\fP is returned if no matching method is found. +The pseudo-type \f5ASO_NEXT\fP generates the list of all methods in successive calls: +.Cs +Asometh_t* meth; +meth = 0; +while (meth = asometh(ASO_NEXT, meth)) + /* examine meth->... */ +.Ce +Otherwise if \f5type\fP is not \f50\fP and not \f5ASO_NEXT\fP it is treated as a combination of the ordered types +\f5ASO_THREAD\fP, \f5ASO_SIGNAL\fP, \f5ASO_INTRINSIC\fP, \f5ASO_PROCESS\fP: +the first method with \f5(meth->type & type) != 0\fP is returned; +\f50\fP is returned if no matching method is found. + +Method names are treated as a name, optionally followed by a list of +\fB,\fP\fIname\fP=\fIvalue\fP details, and optionally ending with \fB,\fP\fIpathname\fP. +The \fBsemaphore\fP method uses \fBsize\fP=\fInumber\fP to specify +the number of semaphores and hashes \fIpathname\fP to determine the semaphore IPC key. +The \fBfcntl\fP method uses \fBsize\fP=\fInumber\fP to specify +the number of 1 byte file locks and uses \fIpathname\fP as the +file to lock using \f5fcntl(F_SETLCK[W])\fP. + +.Ss " int asoinit(const char* details, Asometh_t* meth, Asodisc_t* disc);" +This function sets the global discipline to \f5disc\fP, +closes the current method (releasing its resources), +temporarily instantiates the default method +(either \f5ASO_INTRINSIC\fP if available or \f5AS_SIGNAL\fP otherwise), +and initializes \f5meth\fP and instantiates it as the new method. +If \f5disc\fP is \f50\fP the the global discpline is not modified. +If \f5meth\fP is \f50\fP or \f5meth->lockf\fP is \f50\fP and \f5(meth->type & ASO_INTRINSIC) != 0\fP +then \f5-1\fP is returned and the current method is not changed. +If an error occurs instantiating \f5meth\fP then the current method is +set to the default and \f5-1\fP is returned. +Otherwise \f50\fP is returned on success. + +Method resources are released by the next \f5asometh()\fP call, +or by an \fIASO\fP cleanup function called via \f5atexit\fP(2). +System global method resources are released on last use; +this includes removing semaphore keys or +physical files that may be used by some methods. +In some cases \fIASO\fP maintains reference counts within +the resource to determine last use. + +An application requiring a specific method must check the default method before +using any \fIASO\fP operations. For example, a threaded application would +do something like this: +.Cs +void* data = 0 /* \fIor\fP a method name string with optional details */ +Asometh_t* meth; +if (data || !(asometh(0, 0)->type & (ASO_INTRINSIC|ASO_THREAD))) { + if (!(meth = asometh(ASO_INTRINSIC|ASO_THREAD, data))) + /* error -- suitable method not found */; + else if (asoinit(meth, 0, 0, ASO_VERSION)) + /* error -- method initialization error */; +} +/* ready for \fIASO\fP operaions */ +.Ce +A multi-process application would check for \f5(ASO_INTRINSIC|ASO_PROCESS)\fP +instead of \f5(ASO_INTRINSIC|ASO_THREAD)\fP. + +.PP +.SH IMPLEMENTATION NOTES +Unlike other \fIAST\fP library discipline/method functions which can instantiate +multiple discpline/method handles within a single process, the \fIASO\fP +library allows only one discipline and method to be set at a time, with the additional +restriction that it may only be set by the main and only thread of the calling process. +For this reason there is no open/close interface with an instantation handle; +instead the global discipline/method is simply initialized by \f5asoinit()\fP. + +\f5ASO_THREAD\fP and \f5ASO_PROCESS\fP methods rely on the \f5Asometh_t.lockf()\fP +being sufficiently "heavy" to flush the calling thread/process memory cache +so the subsequent \fIASO\fP operation operates on the physical memory location +instead of the cached location. There is currently no other portable mechanism +that guarantees this other than the \f5ASO_INTRINSIC\fP method. + +.PP +.SH AUTHOR +Kiem-Phong Vo, Adam Edgar, and Glenn Fowler diff --git a/src/lib/libast/man/ast.3 b/src/lib/libast/man/ast.3 new file mode 100644 index 0000000..8055be9 --- /dev/null +++ b/src/lib/libast/man/ast.3 @@ -0,0 +1,283 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH AST 3 +.SH NAME +ast \- miscellaneous libast support +.SH SYNOPSIS +.EX +#include <ast.h> + +char* astconf(const char* \fIname\fP, const char* \fIpath\fP, const char* \fIvalue\fP); +Ast_confdisc_t astconfdisc(Ast_confdisc_t new_notify); +void astconflist(Sfio_t* stream, const char* path, int flags); +off_t astcopy(int \fIrfd\fP, int \fIwfd\fP, off_t \fIn\fP); +int astquery(int \fIfd\fP, const char* \fIformat\fP , ...); +.EE +.SH DESCRIPTION +.L astconf +is a string interface to the +.IR confstr (2), +.IR pathconf (2), +and +.IR sysconf (2) +calls. +If +.I value +is +.L 0 +then the configuration parameter value for +.I name +is returned. +Some +.I name +configuration parameters may consult the +.I path +argument. +In this case if +.I path +is +.L 0 +then +\f5"/"\fP +is used. +Otherwise if +.I path +is not +.L 0 +then it must exist. +The string return value for +.I name +remains unchanged until the next +.L astconf +call on +.IR name . +If +.I value +is +.L 0 +then a valid string is always returned; +\f5""\fP +is returned if +.I name +has no configuration value. +This simplifies the programming interface: +.EX +if (!strcmp(astconf("PATH_RESOLVE", NiL, NiL), "logical")) + /* the logical way ... */ +.EE +If +.I value +is not +.L 0 +then the configuration parameter value for +.I name +is set to +.IR value . +.L 0 +is returned if the value cannot be set. +The paradigm is: +.EX +universe = astconf("UNIVERSE", 0, "att"); +\|.\|.\|. +astconf("UNIVERSE", 0, universe); +.EE +The settable configuration names are: +.TP +.L FS_3D +.L 1 +if +.IR 3d (1) +viewpathing is enabled, +.L 0 +otherwise. +This is an alternative to the +.IR fs3d (3) +interface. +.TP +.L PATH_RESOLVE +.L logical +if symbolic links are followed during file tree traversal, +.L physical +if symbolic links are not followed during file tree traversal, +and +.L metaphysical +if symbolic links are followed at the top level during file tree traversal. +These correspond to the generic +.LR \-L , +.LR \-P , +and +.L \-H +command options. +.TP +.L UNIVERSE +.L ucb +for +.I Berkeley +style and +.L att +otherwise. +This configuration parameter controls the +.I universe +setting on machines that support it (e.g., Pyramid). +.L UNIVERSE +also controls the behavior of some commands like +.IR cat (1) +and +.IR echo (1). +.PP +User defined +.I name +values may also be set and queried, but these should probably have +some form of vendor prefix to avoid being stomped by future standards. +.PP +.L astconfdisc +registers a discipline function +.EX +int (*notify)(const char* \fIname\fP, const char* \fIpath\fP, const char* \fIvalue\fP); +.EE +that is called just before the configuration parameter +.I name +is set to +.I value +relative to +.IR path . +If +.I notify +returns +.L 0 +then the configuration parameter value is not changed. +.PP +.L astconflist +lists the current configuration names and values of +.IR stream . +If +.I path +is +.L 0 +then \f5"/"\fP is used where appropriate. +If +.I flags +is +.L 0 +or +.L R_OK|W_OK +then all configuration parameters are listed. +.L R_OK +lists the readonly configuration parameters and +.L W_OK +lists the settable configuration parameters. +.L X_OK +lists the settable configuration parameters in a form that can be +snarfed for input to the +.IR getconf (1) +command. +.PP +.L astcopy +efficiently copies up to +.I n +bytes from the file descriptor +.I rfd +to the file descriptor +.IR wfd . +The actual number of bytes copied is returned; \-1 is returned on error. +If +.I n +is 0 then an optimal number of bytes (with respect to both +.I rfd +and +.IR wfd ) +is copied. +.PP +If possible +.IR mmap (2) +is used to do the transfer. +Some implementations may bypass user buffer copies usually required by the +.IR read (2)- write (2) +paradigm. +.PP +.L astquery +outputs an +.IR sfprintf (3) +prompt specified by +.I "format, .\|.\|." +to the controlling terminal and reads a response from the controlling terminal. +Offirmative response returns +.LR 0 , +.L EOF +or quit response returns +.LR \-1 , +otherwise +.L 1 +is returned. +If +.I quit +is greater than +.L 0 +then +.I exit(quit) +is called on a quit response. +The responses will eventually be locale specific. +.PP +.L astwinsize +returns the number of rows in +.I *rows +and the number of columns +.I *col +for the terminal file descriptor +.IR fd . +If the number of rows or columns cannot be determined or if +.I fd +is not a terminal then +.I *rows +and +.I *cols +are set to +.LR 0 . +If +.I ioctl (2) +methods fail then the environment variable +.L LINES +is used to set +.I *rows +and the environment variable +.L COLUMNS +is used to set +.IR *cols . +.SH "SEE ALSO" +getconf(1), confstr(2), mmap(2), pathconf(2), read(2), sysconf(2), write(2) diff --git a/src/lib/libast/man/astsa.3 b/src/lib/libast/man/astsa.3 new file mode 100644 index 0000000..5b588a8 --- /dev/null +++ b/src/lib/libast/man/astsa.3 @@ -0,0 +1,161 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.PP +.. +.de Tp +.fl +.ne 3 +.TP +.. +.de Ss +.fl +.ne 3 +.SS "\\$1" +.. +.ta 1.0i 2.0i 3.0i 4.0i 5.0i +.TH ASTSA 3 +.SH NAME +astsa \- standalone libast support +.SH SYNOPSIS +.EX +#include <ast.h> +#include <ccode.h> +#include <error.h> +#include <option.h> +#include <stk.h> +.EE +.SH DESCRIPTION +.B astsa +is a standalone subset of +.BR ast (3) +that requires only +.BR cdt (3) +and +.BR sfio (3). +.PP +.B <ast.h> +includes +.BR <ast_common.h> , +.B <stdarg.h> +or +.BR <varargs.h> , +.BR <sfio.h> , +.BR <limits.h> , +and +.B <limits.h> +and +.B <unistd.h> +if supported by the local system. +.PP +The macros and functions provided by +.B <ast.h> +are described below. +The other headers are described in +.BR ccode (3), +.BR error (3), +.BR optget (3), +and +.BR stk (3). +.SH MACROS +.Ss "size_t elementsof(\fIx\fP)" +Evaluates to the number of elements in the array variable +.IR x . +.Ss "\fItype\fP* newof(void* old, \fItype\fP, size_t \fIelements\fP, size_t \fIextra\fP)" +Equivalent to (\fItype\fP*)realloc((char*)\fIold\fP,sizeof(\fItype\fP)*\fIelements\fP+\fIextra\fP) +if \fIold\fP!=0 and +(\fItype\fP*)calloc(1,sizeof(\fItype\fP)*\fIelements\fP+\fIextra\fP) +otherwise. +.Ss "\fItype\fP* oldof(void* old, \fItype\fP, size_t \fIelements\fP, size_t \fIextra\fP)" +Equivalent to (\fItype\fP*)realloc((char*)\fIold\fP,sizeof(\fItype\fP)*\fIelements\fP+\fIextra\fP) +if \fIold\fP!=0 and +(\fItype\fP*)malloc(1,sizeof(\fItype\fP)*\fIelements\fP+\fIextra\fP) +otherwise. +.Ss "size_t roundof(\fIx\fP,\fIy\fP)" +Evaluates to \fIx\fP rounded up to the next power of 2 boundary \fIy\fP. +.Ss "int ssizeof(\fIx\fP)" +Equivalent to (int)sizeof(\fIx\fP). +.Ss "int streq(\fIa\fP,\fIb\fP)" +Equivalent to (*(\fIa\fP)==*(\fIb\fP)&&strcmp(\fIa\fP,\fIb\fP)==0). +.Ss "int strneq(\fIa\fP,\fIb\fP,\fIn\fP)" +Equivalent to (*(\fIa\fP)==*(\fIb\fP)&&strncmp(\fIa\fP,\fIb\fP,\fIn\fP)==0). +.SH FUNCTIONS +.Ss "void astwinsize(int \fIfd\fP, int* \fIplines\fP, int* \fIpcolumns\fP)" +If \fIplines\fP!=0 then *\fIplines\fP is set to the number of lines on the +tty device corresponding to \fIfd\fP. +If \fIpcolumns\fP!=0 then *\fIpcolumns\fP is set to the number of columns +on the tty device corresponding to \fIfd\fP. +The default if \fIfd\fP is not a terminal device, or if \fIfd\fP queries fail, +is 24 lines and 80 columns. +.Ss "char* fmterror(int \fIerrno\fP)" +Returns the error message text corresponding to the +.BR errno (3) +\fIerrno\fP. +.Ss "char* strerror(int \fIerrno\fP)" +Equivalent to fmterror(\fIerrno\fP). +.Ss "int strgrpmatch(const char* \fIstring\fP, const char* \fIpattern\fP, int* \fIsub\fP, int \fInsub\fP, int \fIflags\fP)" +Matches the null terminated \fIstring\fP against the null terminated +.BR ksh (1) +augmented \fIpattern\fP. +If \fIsub\fP!=0 then \fIsub\fP[2*\fIi\fP] is set to the start offset and \fIsub\fP[2*\fIi\fP+1] is set +to the end offset of the \fIi\fP-th parenthesized subexpression. +\fInsub\fP is 1/2 the number of elements in \fIsub\fP. +\fIflags\fP controls the matching: +.Tp +\f5STR_MAXIMAL\fP: +Maximal match. +The default is minimal (first) match. +.Tp +\f5STR_LEFT\fP: +Implicit left anchor. +.Tp +\f5STR_RIGHT\fP: +Implicit right anchor. +.Tp +\f5STR_ICASE\fP: +Ignore case. +.Tp +\f5STR_GROUP\fP: +(|&) inside [@|*|+{n,m}](...) only. +.Ss "int strmatch(const char* \fIstring\fP, const char* \fIpattern\fP, int* \fIsub\fP, int \fInsub\fP, int \fIflags\fP)" +Equivalent to strgrpmatch(\fIstring\fP,\fIpattern\fP,0,0,STR_MAXIMAL|STR_LEFT|STR_RIGHT). +.SH "SEE ALSO" +.BR ast (3), +.BR ccode (3), +.BR cdt (3), +.BR error (3), +.BR malloc (3), +.BR option (3), +.BR sfio (3), +.BR stk (3) diff --git a/src/lib/libast/man/cdt.3 b/src/lib/libast/man/cdt.3 new file mode 100644 index 0000000..46bfe13 --- /dev/null +++ b/src/lib/libast/man/cdt.3 @@ -0,0 +1,617 @@ +.fp 5 CW +.TH LIBCDT 3 +.SH NAME +\fBCdt\fR \- container data types +.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 <cdt.h> +.Ce +.Ss "DICTIONARY TYPES" +.Cs +Void_t*; +Dt_t; +Dtdisc_t; +Dtmethod_t; +Dtlink_t; +Dtstat_t; +.Ce +.Ss "DICTIONARY CONTROL" +.Cs +Dt_t* dtopen(const Dtdisc_t* disc, const Dtmethod_t* meth); +int dtclose(Dt_t* dt); +void dtclear(dt); +Dtdisc_t* dtdisc(Dt_t* dt, const Dtdisc_t* disc, int type); +Dtmethod_t* dtmethod(Dt_t* dt, const Dtmethod_t* meth); +Dt_t* dtview(Dt_t* dt, Dt_t* view); +int dtcustomize(Dt_t* dt, int type, Void_t* arg); +int dtoptimize(Dt_t* dt); +int dtshare(Dt_t* dt, int type); +int dtlock(Dt_t* dt, unsigned int key, int type); +.Ce +.Ss "STORAGE METHODS" +.Cs +Dtmethod_t* Dtset; +Dtmethod_t* Dtbag; +Dtmethod_t* Dtrhset; +Dtmethod_t* Dtrhbag; +Dtmethod_t* Dtoset; +Dtmethod_t* Dtobag; +Dtmethod_t* Dtlist; +Dtmethod_t* Dtstack; +Dtmethod_t* Dtqueue; +Dtmethod_t* Dtdeque; +.Ce +.Ss "DISCIPLINE" +.Cs +#define DTOFFSET(struct_s,member) +#define DTDISC(disc,key,size,link,makef,freef,comparf,hashf,memoryf,eventf) +typedef Void_t* (*Dtmake_f)(Dt_t*, Void_t*, Dtdisc_t*); +typedef void (*Dtfree_f)(Dt_t*, Void_t*, Dtdisc_t*); +typedef int (*Dtcompar_f)(Dt_t*, Void_t*, Void_t*, Dtdisc_t*); +typedef unsigned int (*Dthash_f)(Dt_t*, Void_t*, Dtdisc_t*); +typedef Void_t* (*Dtmemory_f)(Dt_t*, Void_t*, size_t, Dtdisc_t*); +typedef int (*Dtevent_f)(Dt_t*, int, Void_t*, Dtdisc_t*); +.Ce +.Ss "OBJECT OPERATIONS" +.Cs +Void_t* dtinsert(Dt_t* dt, Void_t* obj); +Void_t* dtappend(Dt_t* dt, Void_t* obj); +Void_t* dtdelete(Dt_t* dt, Void_t* obj); +Void_t* dtattach(Dt_t* dt, Void_t* obj); +Void_t* dtdetach(Dt_t* dt, Void_t* obj); +Void_t* dtsearch(Dt_t* dt, Void_t* obj); +Void_t* dtmatch(Dt_t* dt, Void_t* key); +Void_t* dtfirst(Dt_t* dt); +Void_t* dtnext(Dt_t* dt, Void_t* obj); +Void_t* dtlast(Dt_t* dt); +Void_t* dtprev(Dt_t* dt, Void_t* obj); +Void_t* dtleast(Dt_t* dt, Void_t* obj); +Void_t* dtmost(Dt_t* dt, Void_t* obj); +int dtwalk(Dt_t* dt, int (*userf)(Dt_t*, Void_t*, Void_t*), Void_t*); +Dtlink_t* dtflatten(Dt_t* dt); +Dtlink_t* dtlink(Dt_t* dt, Dtlink_t* link); +Void_t* dtobj(Dt_t* dt, Dtlink_t* link); +Dtlink_t* dtextract(Dt_t* dt); +Dtlink_t* dtrestore(Dt_t* dt, Dtlink_t* link); +.Ce +.Ss "DICTIONARY STATUS" +.Cs +Dt_t* dtvnext(Dt_t* dt); +ssize_t dtvcount(Dt_t* dt); +Dt_t* dtvhere(Dt_t* dt); +ssize_t dtsize(Dt_t* dt); +ssize_t dtstat(Dt_t* dt, Dtstat_t* st); +.Ce +.Ss "HASH FUNCTIONS" +.Cs +unsigned int dtstrhash(unsigned int h, char* str, int n); +unsigned int dtcharhash(unsigned int h, unsigned char c); +.Ce +.SH DESCRIPTION +.PP +\fICdt\fP manages run-time dictionaries using standard container data types: +unordered set/multiset, ordered set/multiset, list, stack, and queue. +.PP +.Ss "DICTIONARY TYPES" +.PP +.Ss " Void_t*" +This type is used to pass objects between \fICdt\fP and application code. +\f5Void_t\fP is defined as \f5void\fP for ANSI-C and C++ +and \f5char\fP for older C compilation environments. +.PP +.Ss " Dt_t" +This is the type of a dictionary handle. +.PP +.Ss " Dtdisc_t" +This defines the type of a discipline structure which define the lay-out of +an object and functions to compare, hash, make, delete objects, etc. (see \f5dtdisc()\fP). +.PP +.Ss " Dtmethod_t" +This defines the type of a container method. +.PP +.Ss " Dtlink_t" +This is the type of a dictionary object holder (see \f5dtdisc()\fP.) +.PP +.Ss " Dtstat_t" +This is the type of a structure to return dictionary statistics (see \f5dtstat()\fP.) +.PP +.Ss "DICTIONARY CONTROL" +.PP +.Ss " Dt_t* dtopen(const Dtdisc_t* disc, const Dtmethod_t* meth)" +This creates a new dictionary. +\f5disc\fP is a discipline structure to describe object format. +\f5meth\fP specifies a manipulation method. +\f5dtopen()\fP returns the new dictionary or \f5NULL\fP on error. +See also the events \f5DT_OPEN\fP and \f5DT_ENDOPEN\fP below. +.PP +.Ss " int dtclose(Dt_t* dt)" +This deletes \f5dt\fP and its objects. +Note that \f5dtclose()\fP fails if \f5dt\fP is being viewed by +some other dictionaries (see \f5dtview()\fP). +\f5dtclose()\fP returns \f50\fP on success and \f5-1\fP on error. +See also the events \f5DT_CLOSE\fP and \f5DT_ENDCLOSE\fP below. +.PP +.Ss " void dtclear(Dt_t* dt)" +This deletes all objects in \f5dt\fP without closing \f5dt\fP. +.PP +.Ss " Dtdisc_t* dtdisc(Dt_t* dt, const Dtdisc_t* disc, int type)" +If \f5disc\fP is \f5NULL\fP, \f5dtdisc()\fP returns the current discipline. +Otherwise, it changes the discipline of \f5dt\fP to \f5disc\fP. +Objects may be rehashed, reordered, or removed as appropriate. +\f5type\fP can be any bit combination of \f5DT_SAMECMP\fP and \f5DT_SAMEHASH\fP. +\f5DT_SAMECMP\fP means that objects will compare exactly the same as before +thus obviating the need for reordering or removing new duplicates. +\f5DT_SAMEHASH\fP means that hash values of objects remain the same +thus obviating the need to rehash. +\f5dtdisc()\fP returns the previous discipline on success +and \f5NULL\fP on error. +.PP +.Ss " Dtmethod_t dtmethod(Dt_t* dt, const Dtmethod_t* meth)" +If \f5meth\fP is \f5NULL\fP, \f5dtmethod()\fP returns the current method. +Otherwise, it changes the storage method of \f5dt\fP to \f5meth\fP. +Objects may be rehashed, reordered, or removed as appropriate. +\f5dtmethod()\fP returns the previous method or \f5NULL\fP on error. +.PP +.Ss " Dt_t* dtview(Dt_t* dt, Dt_t* view)" +A viewpath allows a search or walk starting from a dictionary to continue to another. +\f5dtview()\fP first terminates any current view from \f5dt\fP to another dictionary. +Then, if \f5view\fP is \f5NULL\fP, \f5dtview\fP returns the terminated view dictionary. +If \f5view\fP is not \f5NULL\fP, a viewpath from \f5dt\fP to \f5view\fP is established. +\f5dtview()\fP returns \f5dt\fP on success and \f5NULL\fP on error. +.PP +It is an error to have dictionaries on a viewpath with different storage methods. +In addition, dictionaries on the same view path should +treat objects in a consistent manner with respect to comparison or hashing. +If not, undefined behaviors may result. +.PP +.Ss " int dtcustomize(Dt_t* dt, int type, Void_t* arg)" +This customizes a storage method. The \f5type\fP argument +indicates the type of customization and \f5arg\fP gives additional +information for the operation. Here are the types: +.Tp +\f5DT_SHARE\fP: +This turns on/off the share mode for a dictionary. +Concurrent accesses of a dictionary not in share mode +may exhibit undefined behaviors including memory segmentation. + +Share mode allows multiple accessors, threads or processes, to access objects. +Such objects could be in the same directory in the case of threads or shared +memory in the case of processes. +.Tp +\f5DT_OPTIMIZE\fP: +This causes the underlying method to optimize its internal +data structure. For example, the splay tree underlying \f5Dtoset\fP +would be balanced. +.PP +.Ss " int dtoptimize(Dt_t* dt)" +This is a short-hand for invoking \f5dtcustomize()\fP with the \f5DT_OPTIMIZE\fP event. +.PP +.Ss " int dtshare(Dt_t* dt, int type)" +This turns on or off share mode for dictionary \f5dt\fP depending on whether \f5type\fP +is positive or non-positive. It returns -1 on failure. +.PP +.Ss " int dtlock(Dt_t* dt, unsigned int key, int type)" +This globally locks/unlocks a dictionary using the given \f5key\fP. +It returns 0 on success and -1 on failure. +The value of \f5key\fP must not be 0. +The argument \f5type\fP is used as follows: +.Tp +\f5type < 0\fP: +Unlock the dictionary if it was locked with \f5key\fP. +An error will result if the dictionary was locked with a different key. +.Tp +\f5type == 0\fP: +Attempt to lock the dictionary with \f5key\fP if it is unlocked. +An error will result if the dictionary was already locked with a different key. +.Tp +\f5type > 0\fP: +Attempt to lock the dictionary with \f5key\fP. +If the dictionary is already locked with a different key, +the call will loop and wait until the lock is open to lock it. + +.PP +.Ss "STORAGE METHODS" +.PP +Storage methods are of type \f5Dtmethod_t*\fP. +\fICdt\fP supports the following methods: +.PP +.Ss " Dtoset" +.Ss " Dtobag" +Objects are ordered by comparisons. +\f5Dtoset\fP keeps unique objects. +\f5Dtobag\fP allows repeatable objects. +.PP +.Ss " Dtset" +.Ss " Dtbag" +Objects are unordered. +\f5Dtset\fP keeps unique objects. +\f5Dtbag\fP allows repeatable objects. +The underlying data structure is a hash table with chaining to handle collisions. +.PP +.Ss " Dtrhset" +.Ss " Dtrhbag" +These methods are like \f5Dtset\fP and \f5Dtbag\fP but are based on +a recursive hashing data structure that allows table extension without +object relocation. The data structure also supports lock-free +concurrent search operations for share dictionaries. +.PP +.Ss " Dtlist" +Objects are kept in a list. +\fIA current object\fP is always defined to be either the head of +the list or an object resulting from a recent search or insert operation. +The call \f5dtinsert()\fP will insert a new object +in front of such a current object +while the call \f5dtappend()\fP will append in back of it. +.PP +.Ss " Dtdeque" +Objects are kept in a deque. This is similar to \f5Dtlist\fP +except that objects are always inserted at the front and appended at the tail +of the list. +.PP +.Ss " Dtstack" +Objects are kept in a stack, i.e., in reverse order of insertion. +Thus, the last object inserted is at stack top +and will be the first to be deleted. +.PP +.Ss " Dtqueue" +Objects are kept in a queue, i.e., in order of insertion. +Thus, the first object inserted is at queue head +and will be the first to be deleted. +.PP +.Ss "DISCIPLINE" +.PP +Object format and associated management functions are +defined in the type \f5Dtdisc_t\fP: +.Cs + typedef struct + { ssize_t key, size; + ssize_t link; + Dtmake_f makef; + Dtfree_f freef; + Dtcompar_f comparf; + Dthash_f hashf; + Dtmemory_f memoryf; + Dtevent_f eventf; + } Dtdisc_t; +.Ce +.Ss " ssize_t key, size" +Each object \f5obj\fP is identified by a key used for object comparison or hashing. +\f5key\fP should be non-negative and defines an offset into \f5obj\fP. +If \f5size\fP is negative, the key is a null-terminated +string with starting address \f5*(Void_t**)((char*)obj+key)\fP. +If \f5size\fP is zero, the key is a null-terminated string with starting address +\f5(Void_t*)((char*)obj+key)\fP. +Finally, if \f5size\fP is positive, the key is a byte array of length \f5size\fP +starting at \f5(Void_t*)((char*)obj+key)\fP. +.PP +.Ss " ssize_t link" +Let \f5obj\fP be an object to be inserted into \f5dt\fP. +If \f5link\fP is negative, an object holder of type \f5Dtlink_t\fP +will be allocated to hold \f5obj\fP. +Otherwise, \f5obj\fP should have +a \f5Dtlink_t\fP structure embedded \f5link\fP bytes into it, +i.e., at address \f5(Dtlink_t*)((char*)obj+link)\fP. +.PP +.Ss " Void_t* (*makef)(Dt_t* dt, Void_t* obj, Dtdisc_t* disc)" +If \f5makef\fP is not \f5NULL\fP, +\f5dtinsert(dt,obj)\fP or \f5dtappend()\fP will call it +to make a copy of \f5obj\fP suitable for insertion into \f5dt\fP. +If \f5makef\fP is \f5NULL\fP, \f5obj\fP itself will be inserted into \f5dt\fP. +.PP +.Ss " void (*freef)(Dt_t* dt, Void_t* obj, Dtdisc_t* disc)" +If not \f5NULL\fP, +\f5freef\fP is used to destroy data associated with \f5obj\fP. +.PP +.Ss "int (*comparf)(Dt_t* dt, Void_t* key1, Void_t* key2, Dtdisc_t* disc)" +If not \f5NULL\fP, \f5comparf\fP is used to compare two keys. +Its return value should be \f5<0\fP, \f5=0\fP, or \f5>0\fP to indicate +whether \f5key1\fP is smaller, equal to, or larger than \f5key2\fP. +All three values are significant for method \f5Dtoset\fP and \f5Dtobag\fP. +For other methods, a zero value +indicates equality and a non-zero value indicates inequality. +If \f5(*comparf)()\fP is \f5NULL\fP, an internal function is used +to compare the keys as defined by the \f5Dtdisc_t.size\fP field. +.PP +.Ss " unsigned int (*hashf)(Dt_t* dt, Void_t* key, Dtdisc_t* disc)" +If not \f5NULL\fP, +\f5hashf\fP is used to compute the hash value of \f5key\fP. +It is required that keys compared equal will also have same hash values. +If \f5hashf\fP is \f5NULL\fP, an internal function is used to hash +the key as defined by the \f5Dtdisc_t.size\fP field. +.PP +.Ss " Void_t* (*memoryf)(Dt_t* dt, Void_t* addr, size_t size, Dtdisc_t* disc)" +If not \f5NULL\fP, \f5memoryf\fP is used to allocate and free memory. +When \f5addr\fP is \f5NULL\fP, a memory segment of size \f5size\fP is requested. +If \f5addr\fP is not \f5NULL\fP and \f5size\fP is zero, \f5addr\fP is to be freed. +If \f5addr\fP is not \f5NULL\fP and \f5size\fP is positive, +\f5addr\fP is to be resized to the given size. +If \f5memoryf\fP is \f5NULL\fP, \fImalloc(3)\fP is used. +.PP +.Ss " int (*eventf)(Dt_t* dt, int type, Void_t* data, Dtdisc_t* disc)" +If not \f5NULL\fP, \f5eventf\fP announces various events. +Each event may have particular handling of the return values from \f5eventf\fP. +But a negative return value typically means failure. +Following are the events: +.Tp +\f5DT_OPEN\fP: +This event is raised at the start of the process to open a new dictionary. +The argument \f5data\fP will be a pointer to an object of type \f5Void_t*\fP +initialized to \f5NULL\fP before the call. The return value of \f5eventf()\fP +is significant as follows: + +On a negative return value, \f5dtopen()\fP will return failure. + +On a zero return value, \f5eventf()\fP may set \f5*(Void_t**)data\fP to some non-\f5NULL\fP +value to indicate that the dictionary structure itself should be allocated +along with the \f5Dtdisc_t.data\fP section. +Otherwise, it will be allocated separately with \f5malloc(3)\fP. + +On a positive return value, the dictionary is being reconstructed +based on existing states of some previous dictionary. +In this case, \f5eventf()\fP should set \f5*(Void_t**)data\fP to point to +the field \f5Dt_t.data\fP of the corresponding previous dictionary (see \f5DT_CLOSE\fP below). +If the handle of the previous dictionary was created as discussed above +in the case of the zero return value, it will be exactly restored. +Otherwise, a new handle will be allocated with \f5malloc()\fP. +The ability to create different dictionaries sharing the same set of objects +allows for managing objects in shared and/or persistent memory. +.Tp +\f5DT_ENDOPEN\fP: +This event is raised at the end of the process to open a dictionary. +The return value of \f5eventf()\fP will be ignored. +.Tp +\f5DT_CLOSE\fP: +This event is raised at the start of the process to close dictionary \f5dt\fP. +The return value of \f5eventf\fP is significant as follows: + +On a negative return value, \f5dtclose()\fP will return failure. + +On a zero return value, all dictionary objects will be deleted and +and all associated memory will be freed. + +On a positive return value, allocated objects and memory will be kept intact. +This means that \f5dt->data\fP remains intact and can be reused in some future +dictionary (see \f5DT_OPEN\fP above). +Note, however, that \f5dt\fP itself would still be freed if it was allocated with \f5malloc(3)\fP. +.Tp +\f5DT_ENDCLOSE\fP: +This event is raised at the end of the process to close a dictionary. +The return value of \f5eventf()\fP will be ignored. +.Tp +\f5DT_DISC\fP: +The discipline of \f5dt\fP is being changed to a new one given in +\f5(Dtdisc_t*)data\fP. +.Tp +\f5DT_METH\fP: +The method of \f5dt\fP is being changed to a new one given in +\f5(Dtmethod_t*)data\fP. +.Tp +\f5DT_HASHSIZE\fP: +This event is applicable to +the methods \f5Dtset\fP, \f5Dtbag\fP, \f5Dtrhset\fP and \f5Dtrhbag\fP. +It is typically issued when the respective internal data structure of +a method is about to be initialized. +If the return value of the event handling function is positive, +\f5*(ssize_t*)data\fP is examined for further action; +else, it is ignored. +A positive return value means that the event function wishes to suggest a table size. +It does that by setting \f5*(ssize_t*)data\fP to the desired size. +Then, the actual table size will be the maximum of the absolute value +of \f5*(ssize_t*)data\fP and some predefined value set by the method. +In addition, if \f5*(ssize_t*)data\fP was negative, +the \f5Dtset\fP and \f5Dtbag\fP methods will never resize the hash table. +.Tp +\f5DT_ERROR\fP: +This event announces an error that occurred during some operations. +The argument \f5(char*)data\fP is a null-terminated string describing the error. +.PP +.Ss "#define DTOFFSET(struct_s,member)" +This macro function computes the offset of \f5member\fP from the start +of structure \f5struct_s\fP. It is useful for getting the offset of +a \f5Dtlink_t\fP embedded inside an object. +.PP +.Ss "#define DTDISC(disc,key,size,link,makef,freef,comparf,hashf,memoryf,eventf)" +This macro function initializes the discipline pointed to by \f5disc\fP +with the given values. +.PP +.Ss "OBJECT OPERATIONS" +.PP +.Ss " Void_t* dtinsert(Dt_t* dt, Void_t* obj)" +.Ss " Void_t* dtappend(Dt_t* dt, Void_t* obj)" +These functions add an object prototyped by \f5obj\fP into \f5dt\fP. +\f5dtinsert()\fP and \f5dtappend()\fP perform the same function +for all methods except for \f5Dtlist\fP (see \f5Dtlist\fP for details). +If there is an existing object in \f5dt\fP matching \f5obj\fP +and the storage method is \f5Dtset\fP, \f5Dtrhset\fP or \f5Dtoset\fP, +\f5dtinsert()\fP and \f5dtappend()\fP will simply return the matching object. +Otherwise, a new object is inserted according to the method in use. +See \f5Dtdisc_t.makef\fP for object construction. +The new object or a matching object as noted will be returned on success +while \f5NULL\fP is returned on error. +.PP +.Ss " Void_t* dtdelete(Dt_t* dt, Void_t* obj)" +If \f5obj\fP is \f5NULL\fP, methods \f5Dtstack\fP and \f5Dtqueue\fP +delete respectively stack top or queue head while other methods do nothing. +If \f5obj\fP is not \f5NULL\fP, an object matching \f5obj\fP is deleted. +See \f5Dtdisc_t.freef\fP for object destruction. +\f5dtdelete()\fP returns the deleted object (even if it was deallocated) +or \f5NULL\fP on error. +.PP +.Ss " Void_t* dtattach(Dt_t* dt, Void_t* obj)" +This function is similar to \f5dtinsert()\fP but \f5obj\fP itself +will be inserted into \f5dt\fP even if a discipline +function \f5makef\fP is defined. +.PP +.Ss " Void_t* dtdetach(Dt_t* dt, Void_t* obj)" +This function is similar to \f5dtdelete()\fP but the object to be deleted +from \f5dt\fP will not be freed (via the discipline \f5freef\fP function). +.PP +.Ss " Void_t* dtsearch(Dt_t* dt, Void_t* obj)" +.Ss " Void_t* dtmatch(Dt_t* dt, Void_t* key)" +These functions find an object matching \f5obj\fP or \f5key\fP either from \f5dt\fP or +from some dictionary accessible from \f5dt\fP via a viewpath (see \f5dtview()\fP.) +\f5dtsearch()\fP and \f5dtmatch()\fP return the matching object or +\f5NULL\fP on failure. +.PP +.Ss " Void_t* dtfirst(Dt_t* dt)" +.Ss " Void_t* dtnext(Dt_t* dt, Void_t* obj)" +\f5dtfirst()\fP returns the first object in \f5dt\fP. +\f5dtnext()\fP returns the object that follows an object matching \f5obj\fP. +Objects are ordered based on the storage method in use. +For \f5Dtoset\fP and \f5Dtobag\fP, objects are ordered by object comparisons. +For \f5Dtstack\fP, objects are ordered in reverse order of insertion. +For \f5Dtqueue\fP, objects are ordered in order of insertion. +For \f5Dtlist\fP, objects are ordered by list position. +For \f5Dtset\fP, \f5Dtbag\fP, \f5Dtrhset\fP and \f5Dtrhbag\fP, +objects are ordered by some internal order defined at the time when these +functions are called. + +Objects in a dictionary or a viewpath can be walked using +a \f5for(;;)\fP loop as below. +.Cs + for(obj = dtfirst(dt); obj; obj = dtnext(dt,obj)) +.Ce +.PP +.Ss " Void_t* dtlast(Dt_t* dt)" +.Ss " Void_t* dtprev(Dt_t* dt, Void_t* obj)" +\f5dtlast()\fP and \f5dtprev()\fP are like \f5dtfirst()\fP and \f5dtnext()\fP +but work in reverse order. +For \f5Dtset\fP, \f5Dtbag\fP, \f5Dtrhset\fP and \f5Dtrhbag\fP, +both reverse and forward orders are the same. +Note that dictionaries on a viewpath are still walked in the order +of the viewpath. +.PP +.Ss " Void_t* dtleast(Dt_t* dt, Void_t* obj)" +.Ss " Void_t* dtmost(Dt_t* dt, Void_t* obj)" +\f5dtleast()\fP returns the smallest object greater or equal to \f5obj\fP. +\f5dtmost()\fP returns the largest object smaller or equal to \f5obj\fP. +Again, object ordering depends on the storage method in use. +For example, with \f5Dtoset\fP and \f5Dtobag\fP, the ordering of objects +is well-defined and it is possible to call \f5dtleast()\fP or \f5dtmost()\fP +on an object not in the dictionary and still get a meaningful result. +On the other hand, with \f5Dtset\fP or \f5Dtrhset\fP, such a call will +essentially be the same as \f5dtsearch()\fP because without matching +an object, it cannot be determined what comes before or after. +.PP +.Ss " dtwalk(Dt_t* dt, int (*userf)(Dt_t*, Void_t*, Void_t*), Void_t* data)" +This function calls \f5(*userf)(walk,obj,data)\fP on each object in \f5dt\fP and +other dictionaries viewable from it. +\f5walk\fP is the dictionary containing \f5obj\fP. +If \f5userf()\fP returns a \f5<0\fP value, +\f5dtwalk()\fP terminates and returns the same value. +\f5dtwalk()\fP returns \f50\fP on completion. +.PP +.Ss " Dtlink_t* dtflatten(Dt_t* dt)" +.Ss " Dtlink_t* dtlink(Dt_t* dt, Dtlink_t* link)" +.Ss " Void_t* dtobj(Dt_t* dt, Dtlink_t* link)" +Using \f5dtfirst()/dtnext()\fP or \f5dtlast()/dtprev()\fP +to walk a single dictionary can incur significant cost due to function calls. +For efficient walking of a single directory (i.e., no viewpathing), +\f5dtflatten()\fP and \f5dtlink()\fP can be used. +Objects in \f5dt\fP are made into a linked list and walked as follows: +.Cs + for(link = dtflatten(dt); link; link = dtlink(dt,link) ) +.Ce +.PP +Note that \f5dtflatten()\fP returns a list of type \f5Dtlink_t*\fP, +not \f5Void_t*\fP. That is, it returns a dictionary holder pointer, +not a user object pointer +(although both are the same if the discipline field \f5link\fP is zero.) +The macro function \f5dtlink()\fP +returns the dictionary holder object following \f5link\fP. +The macro function \f5dtobj(dt,link)\fP +returns the user object associated with \f5link\fP, +Beware that the flattened object list is unflattened on any +dictionary operations other than \f5dtlink()\fP. +.PP +.Ss " Dtlink_t* dtextract(Dt_t* dt)" +.Ss " Dtlink_t* dtrestore(Dt_t* dt, Dtlink_t* list)" +\f5dtextract()\fP extracts the list of objects from \f5dt\fP and makes it appear empty. +\f5dtrestore()\fP repopulates \f5dt\fP with +a list of objects previously obtained via \f5dtextract()\fP. +It is important that the same discipline and method are in use at both +extraction and restoration. Otherwise, undefined behaviors may result. +These functions return \f5NULL\fP on error. + +.PP +.Ss "DICTIONARY INFORMATION" +.PP +.Ss " Dt_t* dtvnext(Dt_t* dt)" +This returns the dictionary that \f5dt\fP is viewing, if any. +.Ss " ssize_t dtvcount(Dt_t* dt)" +This returns the number of dictionaries that view \f5dt\fP. +.Ss " Dt_t* dtvhere(Dt_t* dt)" +This returns the dictionary \f5v\fP viewable from \f5dt\fP +where an object was found from the most recent search or walk operation. +.Ss " ssize_t dtsize(Dt_t* dt)" +This function returns the number of objects stored in \f5dt\fP. +.PP +.Ss " ssize_t dtstat(Dt_t *dt, Dtstat_t* st)" +This function reports dictionary statistics. +It returns the number of objects stored in \f5dt\fP. +.PP +\f5Dtstat_t\fP contains the below fields: +.Tp +\f5int meth\fP: +This returns the method used for the dictionary, e.g., \f5DT_SET\fP, \f5DT_OSET\fP, etc. +.Tp +\f5ssize_t size\fP: +This has the number of objects in the dictionary. +.Tp +\f5ssize_t mlev\fP: +This returns the maximum number of levels in the data structure used for object storage, i.e., +the binary tree or the recursive hash table. +For a hash table with chaining (i.e., \f5Dtset\fP and \f5Dtbag\fP), +it gives the length of the longest chain. +.Tp +\f5ssize_t lsize[]\fP: +This gives the object counts at each level. +For a hash table with chaining (i.e., \f5Dtset\fP and \f5Dtbag\fP), +a level is defined as objects at that position in their chains. +Since chains can be arbitrarily long, the report is limited +to objects at a level less than \f5DT_MAXSIZE\fP. +.Tp +\f5ssize_t tsize[]\fP: +For a hash table using a trie structure, this counts the number of +sub-tables at each level. For example, \f5tsize[0]\fP should be 1 +only for this hash table type. +.PP +.Ss "HASH FUNCTIONS" +.PP +.Ss " unsigned int dtcharhash(unsigned int h, char c)" +.Ss " unsigned int dtstrhash(unsigned int h, char* str, int n)" +These functions compute hash values from bytes or strings. +\f5dtcharhash()\fP computes a new hash value from byte \f5c\fP and seed value \f5h\fP. +\f5dtstrhash()\fP computes a new hash value from string \f5str\fP and seed value \f5h\fP. +If \f5n\fP is positive, \f5str\fP is a byte array of length \f5n\fP; +otherwise, \f5str\fP is a null-terminated string. +.PP +.SH IMPLEMENTATION NOTES +\f5Dtlist\fP, \f5Dtstack\fP and \f5Dtqueue\fP are based on doubly linked list. +\f5Dtoset\fP and \f5Dtobag\fP are based on top-down splay trees. +\f5Dtset\fP and \f5Dtbag\fP are based on hash tables with +move-to-front collision chains. +\f5Dtrhset\fP and \f5Dtrhbag\fP are based on a recursive hashing data structure +that avoids table resizing. +.PP +.SH AUTHOR +Kiem-Phong Vo, kpv@research.att.com diff --git a/src/lib/libast/man/chr.3 b/src/lib/libast/man/chr.3 new file mode 100644 index 0000000..8d57648 --- /dev/null +++ b/src/lib/libast/man/chr.3 @@ -0,0 +1,126 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH CHR 3 +.SH NAME +chr \- character constant conversion routines +.SH SYNOPSIS +.EX +#include <ast.h> + +int chresc(const char* \fIs\fP, char** \fIe\fP); +int chrtoi(const char* \fIs\fP); +.EE +.SH DESCRIPTION +.L chresc +converts and returns the next character constant in the 0-terminated string +.IR s . +If +.I e +is not 0 then +.I *e +is set to point to the next character in +.I s +on return. +0 is returned and +.I e +is not modified when the end of +.I s +is reached. +.PP +.L chrtoi +converts the 0-terminated string +.I s +to an +.I int +and returns the value. +The characters in +.I s +are converted in order from the left and shifted into the +.I int +value until up to the number of characters in an +.I int +is reached. +This operation is inherently machine-dependent, +but at least its defined in one place. +.PP +The following +.B \e +escape sequences are recognized: +.TP +.RI \e ooo +The character represented by the octal code +.IR ooo . +.TP +.RI \ex xx +The character represented by the hex code +.IR xx . +.TP +.L \ea +Alert (bell). +.TP +.L \eb +Backspace. +.TP +.L \ef +Formfeed. +.TP +.L \en +Newline. +.TP +.L \er +Carriage return. +.TP +.L \et +Horizontal tab. +.TP +.L \ev +Vertical tab. +.TP +.L \eE +ESC (escape). +.TP +.L \e\e +Backslash. +.PP +Other characters following +.B \e +are undefined (although for backwards compatibility they +translate to themselves). +.SH "SEE ALSO" +str(3) diff --git a/src/lib/libast/man/compat.3 b/src/lib/libast/man/compat.3 new file mode 100644 index 0000000..eb5e8a7 --- /dev/null +++ b/src/lib/libast/man/compat.3 @@ -0,0 +1,103 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH COMPATIBILITY 3 +.SH NAME +compatibility \- ast library compatibility routines +.SH SYNOPSIS +.EX +#include <ast.h> + +int atexit(void(*)(void)); +char* confstr(int); +int dup2(int, int); +long fpathconf(int, int); +int getgroups(int, int*); +char* getwd(char*); +int killpg(int, int); +int link(const char*, const char*); +int lstat(const char*, struct stat*); +int memcmp(const char*, const char*, unsigned int); +char* memcpy(char*, const char*, int); +char* memset(char*, char, int); +int mkdir(const char*, mode_t); +int mkfifo(const char*, mode_t); +int mknod(const char*, mode_t); +char* mktemp(char*); +int mount(const char*, const char*, int); +long pathconf(const char*, int); +int perror(const char*); +FILE* popen(const char*, const char*); +int readlink(const char*, char*, int); +int remove(const char*); +int rename(const char*, const char*); +int rmdir(const char*); +int setpgid(pid_t, pid_t); +int sigmask(int); +int sigsetmask(long); +int sigunblock(int); +char* strchr(const char*, int); +char* strrchr(const char*, int); +double strtod(const char*, char**); +long strtol(const char*, char**, int); +int symlink(const char*, const char*); +long sysconf(int); +int system(const char*); +char* tmpnam(char*); +int unlink(const char*); +int vfork(void); +int waitpid(pid_t, int*, int); +.EE +.SH DESCRIPTION +These routines are described in the ANSI C, POSIX, BSD and System V manual +sections 2 and 3. +The interfaces are preserved and present in all libast implementations. +Where conflicts exist the POSIX syntax and semantics are implied. +The appropriate error value is returned and +.I errno +is set to +.L EINVAL +when emulation is either too expensive or not possible. +.SH CAVEATS +If you +.L "#undef foo" +and then call +.L foo +you may end up with the local implementation of +.LR foo , +and then you get what you payed for. diff --git a/src/lib/libast/man/error.3 b/src/lib/libast/man/error.3 new file mode 100644 index 0000000..df47d34 --- /dev/null +++ b/src/lib/libast/man/error.3 @@ -0,0 +1,283 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH ERROR 3 +.SH NAME +error \- error and debug trace message formatter +.SH SYNOPSIS +.EX +#include <error.h> + +Error_info_t error_info; + +void error(int \fIlevel\fP, ...); +void errorv(const char* \fIlibrary\fP, int \fIlevel\fP, va_alist \fIargs\fP); +void liberror(const char* \fIlibrary\fP, int \fIlevel\fP, ...); + +#include <debug.h> + +debug(\fIstatement\fP) +message((int \fIlevel\fP, ...)) +libmessage((const char* \fIlibrary\fI, int \fIlevel\fP, ...)) +.EE +.SH DESCRIPTION +.L error +is the error and debug trace message formatter. +.I level +is the severity level. +Messages with +.I "level < error_info.trace" +are suppressed. +.I error_info.trace +is initially +.LR 0 . +The remaining arguments are passed on to +.LR printf . +A +.I newline +is appended to the message text, so none should appear in the +.L printf +format. +If +.I error_info.id +is not +.L 0 +then messages with +.I "level > 0" +are prefixed by +.IR error_info.id: . +.PP +Before the message text is output to standard error +it is passed to the function +.LR "char* ERROR_translate(const char* \fItext\fP, int \fIflag\fP)" . +By default +.L ERROR_translate +returns the +.L text +argument, but on some systems it may do language translation via lookup +on the original source text. +.RL ( error +calls +.L ERROR_translate +with a 0 +.L flag +argument). +.PP +.I level +may be one of: +.TP +.B <0 +Negative values are for debug tracing. +Debug messages are prefixed with +.BI debug level. +If +.I "errno != error_info.last_errno" +then +.I error_info.last_errno +is set to +.I errno +and the error text for errno is appended to the message. +.TP +.B "ERROR_INFO [0]" +Information only; no prefixes are added to the message. +.TP +.B "ERROR_WARNING [1]" +.L "warning:" +is added after +.L error_info.id +and +.I error_info.warnings +is incremented. +.TP +.I "ERROR_ERROR [2]" +(soft error) +.I error_info.errors +is incremented. +.TP +.B ">= ERROR_FATAL [3]" +(hard error) +.I error_info.errors +is incremented and +.L exit(\fIlevel\fP\-2) +is called after the message is emitted. +.TP +.B "ERROR_PANIC [77]" +(unrecoverable internal error) +.L "panic:" +is added after +.IR error_info.id . +.PP +The following may be inclusive-or'd into +.I level +for alternate behavior: +.TP +.L ERROR_SYSTEM +The error text for +.I errno +is appended to the message. +.TP +.L ERROR_OUTPUT +The next argument is the file descriptor where the error message +should be emitted. +.TP +.L ERROR_SOURCE +Then next two arguments are a file name and line number that are added +to the message after +.IR error_info.id . +.TP +.L ERROR_USAGE +A usage message is emitted. +.TP +.L ERROR_PROMPT +The trailing +.I newline +is suppressed. +.TP +.L ERROR_NOID +The +.I error_info.id +prefix is suppressed. +.TP +.L ERROR_LIBRARY +The message is from a library routine. +.SH ENVIRONMENT +The elements of the global struct +.I error_info +control error output and actions. +Parts of +.I error_info +can be initialized from the +.L ERROR_OPTIONS +environment variable. +.L ERROR_OPTIONS +contains space separated +.IR name [ =value ] +options, described below. +.TP +.I "int core" +If +.I "error_info.core != 0" +then +.I "level >= error_info.core" +generates a core dump. +Initialized by +.EX +ERROR_OPTIONS="core=\fIlevel\fP" +.EE +where +.I level +can be a number or one of +.LR error , +.LR fatal , +or +.LR panic . +.I error_info.core +is a handy way to get a stack trace at the exact point of error. +.TP +.I "int error_info.trace" +If +.I "error_info.trace != 0" +and +.I "level < error_info.trace" +then the error message text is suppressed. +.L exit() +may still be called if appropriate for +.IR level . +Initialized by +.EX +ERROR_OPTIONS="trace=\fIlevel\fP" +.EE +where +.I error_info.trace +is set to the negative of +.IR level . +.PP +Library error messages, suppressed by default, are enabled by +.EX +ERROR_OPTIONS="library" +.EE +The system +.I errno +message text can be forced for each message by +.EX +ERROR_OPTIONS="system" +.EE +.SH "EXTENDED DESCRIPTION" +.L "<debug.h>" +provides debugging message macros when +.L DEBUG +or +.L _TRACE_ +are defined +.RL ( _TRACE_ +is defined by +.I makerules +when +.L CCFLAGS +contains +.LR \-g ). +All of the macros expand to nothing when both +.L DEBUG +and +.L _TRACE_ +are not defined. +Otherwise +.L debug +expands its arg and +.L libmessage +and +.L message +call +.L liberror +and +.L error +respectively if +.IR "error_info.trace<0" . +Notice that +.L libmessage +and +.L message +are macro hacks that require double parentheses ((...)) around the +arguments. +.SH EXAMPLE +To enable debugging message level -3, library messages, and system +.I errno +text for all commands: +.EX +export ERROR_OPTIONS="trace=3 library system" +.EE diff --git a/src/lib/libast/man/find.3 b/src/lib/libast/man/find.3 new file mode 100644 index 0000000..a14ceae --- /dev/null +++ b/src/lib/libast/man/find.3 @@ -0,0 +1,89 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH FIND 3 +.SH NAME +find \- fastfind algorithm interface +.SH SYNOPSIS +.EX +#include <find.h> + +void* findopen(const char* \fIpattern\fP); +char* findnext(void* \fIhandle\fP); +void findclose(void* \fIhandle\fP); +.EE +.SH DESCRIPTION +These routines access the data generated by the +.I fastfind +algorithm. +The data itself is generated by a standalone program that is run daily +via +.I cron +or +.IR at . +.PP +.L findopen +returns a handle to a +.I fastfind +stream for the +.I ksh +file pattern +.IR pattern . +.L findnext +returns the next pathname that matches the pattern specified by +.IR handle . +.L findnext +returns +.L 0 +when no more pathnames match the pattern. +Finally, +.L findclose +closes the +.I fastfind +stream for +.IR handle . +.SH BUGS +These rotuines are only as good as the +.I fastfind +information which is in the system administration domain. +.SH "SEE ALSO" +tw(1), +find(1), +strmatch(3) +.br +James A. Woods, \fIFast Find Algorithm\fP, Usenix ;login:, February/March, 1983, p. 8 diff --git a/src/lib/libast/man/fmt.3 b/src/lib/libast/man/fmt.3 new file mode 100644 index 0000000..dbe1aab --- /dev/null +++ b/src/lib/libast/man/fmt.3 @@ -0,0 +1,213 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH FMT 3 +.SH NAME +fmt \- string formatting routines +.SH SYNOPSIS +.EX +#include <ast.h> +#include <ls.h> + +char* fmtbase(long \fInumber\fP, int \fIbase\fP, int \fIprefix\fP); +char* fmtdev(struct stat* \fIst\fP); +char* fmtelapsed(unsigned long \fIcount\fP, int \fIpersec\fP) +char* fmterror(int \fIerrno\fP); +char* fmtesc(const char* \fIstring\fP); +char* fmtfs(struct stat* \fIst\fP); +char* fmtgid(int \fIgid\fP); +char* fmtmatch(const char* \fIre\fP); +char* fmtmode(int \fImode\fP, int \fIexternal\fP); +char* fmtperm(int \fIperm\fP); +char* fmtre(const char* \fIpattern\fP); +char* fmtsignal(int \fIsig\fP); +char* fmttime(const char* \fIformat\fP, time_t \fItm\fP); +char* fmtuid(int \fIuid\fP); +.EE +.SH DESCRIPTION +These routines return a pointer to a formatted string for various numeric +and string entities. +Some routines may cache information to speed up the next call. +Most of the routines return a pointer to a private buffer, the +contents of which are overwritten on the next call to that routine. +Most +.L fmt +routines have a corresponding +.L str +routine that converts in the other direction. +There is nothing spectacular about this collection other than that +it provides a single place where the exact format is spelled out. +.PP +.L fmtbase +formats a base +.I base +representation for +.IR number . +If +.I "prefix != 0" +then the base prefix is included in the formatted string. +If +.I "number == 0" +or +.I "base == 0" +then the output is signed base 10. +.PP +.L fmtdev +returns the device handle name specified by the +.L stat +structure +.IR st . +This is the device information displayed by +.IR "ls \-l" . +.PP +.L fmtelapsed +formats the elapsed time for +.I (count/persec) +seconds. +The two largest time units are used, limiting the return value length +to at most 6 characters. +The units are: +.RS +.TP +.B s +seconds +.TP +.B m +minutes +.TP +.B h +hours +.TP +.B days +.TP +.B weeks +.TP +.B M +months +.TP +.B Y +years +.TP +.B S +scores +.RE +.PP +.L fmterror +returns the system error message text for the error number +.IR errno . +.PP +.L fmtesc +formats non-ASCII characters in +.I string +into C-style +.B \e +sequences. +These sequences are understood by +.L chresc +and +.LR chrtoi . +.PP +.L fmtfs +returns the file system type name corresponding to the +.L stat +structure +.IR st . +.PP +.L fmtgid +returns the group name for +.IR gid . +.PP +.L fmtmatch +returns the +.L strmatch +equivalent pattern for the regular expression pattern +.IR re . +0 is returned for invalid +.IR re . +.PP +.L fmtmode +returns the +.I "ls \-l" +mode string for the file mode bits in +.IR mode . +If +.I "external != 0" +then +.I mode +is +.IR modecanon (3) +canonical. +.PP +.L fmtperm +returns the +.I chmod +permission string for the permission bits in +.IR perm . +.PP +.L fmtre +returns the regular expression +equivalent pattern for the +.L strmatch +pattern +.IR pattern . +0 is returned for invalid +.IR pattern . +.PP +.L fmtsignal +returns the signal name, sans +.LR SIG , +for the signal number +.IR sig . +If +.I "sig < 0" +then the description text for +.I \-sig +is returned. +.PP +.L fmttime +returns the results of +.I "tmfmt(buf,sizeof(buf),format,tm)" +in the private buffer +.IR buf . +.PP +.L fmtuid +returns the user name for +.IR uid . +.SH "SEE ALSO" +modecanon(3), +str(3) diff --git a/src/lib/libast/man/fmtls.3 b/src/lib/libast/man/fmtls.3 new file mode 100644 index 0000000..50d872b --- /dev/null +++ b/src/lib/libast/man/fmtls.3 @@ -0,0 +1,143 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRLS 3 +.SH NAME +fmtls \- format file information in buffer +.SH SYNOPSIS +.EX +#include <ls.h> + +char* fmtls(char* \fIbuf\fP, char* \fIname\fP, struct stat* \fIst\fP, char* \fIinfo\fP, char* \fIlink\fP, int \fIflags\fP); +.EE +.SH DESCRIPTION +.L fmtls +formats +.IR ls (1) +style file information into the buffer +.IR buf . +A pointer to the trailing 0 in +.I buf +is returned. +.I name +is the file name. +.I st +is a pointer to the +.B "struct stat +status information for +.I name +obtained from one of the +.IR stat (2) +routines. +.I info +is an additional string that will appear before +.I name +in +.I buf +and +.I link +is the name of the related hard or soft link file. +Both +.I info +and +.I link +may be 0. +.I flags +controls the format style and may be a combination of the following: +.PP +.TP +.B LS_ATIME +Use +.I st->st_atime +rather than +.I st->st_mtime +for +.BR LS_LONG . +.TP +.B LS_CTIME +Use +.I st->st_mtime +rather than +.I st->st_mtime +for +.BR LS_LONG . +.TP +.B LS_BLOCKS +List the number of blocks. +.TP +.B LS_INUMBER +List the file serial number (inode number). +.TP +.B LS_LONG +List the file mode, link count, user and group name, +size or major/minor device number, and date along with the +file name. +.TP +.B LS_MARK +The file name is appended with +.L / +for directories, +.L @ +for symbolic links, +and +.L * +for executable files. +.TP +.B LS_NOGROUP +Omit the group name from +.BR LS_LONG . +.TP +.B LS_NOUSER +Omit the user name from +.BR LS_LONG . +.PP +The user and group fields are each +.B LS_W_NAME +characters wide, +the +.B LS_INUMBER +field is +.B LS_W_INUMBER +characters wide, +and the +.B LS_BLOCKS +field is +.B LS_W_BLOCKS +characters wide. +.SH "SEE ALSO" +ls(1), stat(2), strmode(3) diff --git a/src/lib/libast/man/fs3d.3 b/src/lib/libast/man/fs3d.3 new file mode 100644 index 0000000..7dfd448 --- /dev/null +++ b/src/lib/libast/man/fs3d.3 @@ -0,0 +1,92 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH FS3D 3 +.SH NAME +fs3d \- 3D (nDFS) on/off switch +.SH SYNOPSIS +.EX +#include <fs3d.h> + +int fs3d(int \fIop\fP); +.EE +.SH DESCRIPTION +.L fs3d +controls and queries the +.B 3D +file system +.RB (aka nDFS ) +enable state. +.L 0 +is returned if the current process cannot mount +.B 3D +files. +.I op +may be one of: +.TP +.B FS3D_TEST +Returns +.L "FS3D_ON [1]" +if +.B 3D +is enabled, +.L "FS3D_OFF [0]" +otherwise. +.TP +.B FS3D_ON +Enables +.B 3D +and returns the previous +.L 3D +state (either +.B FS3D_ON +or +.BR FS3D_OFF ). +.TP +\fBFS3D_LIMIT(\fIlimit\fB)\fR +Sets the viewpath level limit to +.IR limit . +The previous limit is returned. +.TP +.B FS3D_INIT +Re-initialize the +.B 3D +tables. +Used for debugging. +.SH "SEE ALSO" +3D(1) diff --git a/src/lib/libast/man/ftwalk.3 b/src/lib/libast/man/ftwalk.3 new file mode 100644 index 0000000..f339ab7 --- /dev/null +++ b/src/lib/libast/man/ftwalk.3 @@ -0,0 +1,235 @@ +.fp 5 CW +.TH FTWALK 3 +.SH NAME +\fBftwalk\fR \- file tree walker +.SH SYNOPSIS +.ta .75i 1.5i 2.25i 3i 3.75i 4.5i 5.25i 6i +.PP +.nf +\f5 +#include <ftwalk.h> + +int ftwalk(char* path, int (*userf)(struct FTW* ftw), int options, + int (*comparf)(struct FTW* ftw1, struct FTW* ftw2)); + + +int ftwflags(void); +\fR +.fi +.SH DESCRIPTION +.PP +\fIFtwalk\fR traverses a directory hierarchy using depth-first search. +Upon visiting each file or directory in the hierarchy, it calls +the user function \fIuserf\fP to process that file or directory. +On a directory object, \fIuserf\fR may be called twice, once in preorder +and once in postorder. +On a terminal object such as a file or an unreadable directory, +\fIuserf\fP is called only once. +Cycles due to hard links or symbolic links are detected +to avoid infinite loops. +.PP +\fIPath\fR is the starting point of the search. +It may be an absolute path name or a path name relative to +the current directory. +If \fIpath\fR is a null pointer or points to an empty string, it is treated +as if it points to the current (dot) directory. +.PP +\fIOptions\fR consists of zero or more of the following bits: +.IP +FTW_CHILDREN: +This implies preorder calls to \fIuserf\fR on directory objects. +On such a call to \fIuserf\fR, +the field \fIftw->link\fR (below) points to a link list of +the children of the respective directory. +Upon returning from \fIuserf\fP, +if the field \fIftw->status\fR of any child object +is set to FTW_SKIP (below), that child is pruned from the search. +.IP +FTW_DELAY: When \fBFTW_CHILDREN\fP is turned on, +the fields \fIftw->statb\fP (\fIstruct stat\fP) of children objects +remain undefined until these objects are visited. +.IP +FTW_DOT: Do not use \fIchdir\fR(2) during the traversal. +Normally \fIchdir\fR is used so that +the base name of the object about to be processed can be used +in accessing its data. +This can enhance \fIftwalk\fR efficiency but certain program effects +such as core dumps may be generated in unexpected places +or may not even be generated at all. +Whenever \fIchdir\fR generates an error, if possible, +the current directory is restored to the starting directory +(see FTW_NAME and FTW_PATH). +.IP +FTW_MULTIPLE: The \fIpath\fP argument is treated as a \fIchar**\fP +pointer to a null-terminated array of path names. +All hierarchies rooted at these paths will be searched +.IP +FTW_POST: Calls to the user function are issued only in postorder. +That is, \fIuserf\fP is called on a directory only after its descendants have +been processed. +The absence of this bit indicates that calls to the user functions +are issued in preorder. That is, \fIuserf\fP is +called on a directory before its descendants are processed. +.IP +FTW_PHYSICAL: Use \fIlstat\fR(2) instead of \fIstat\fR(2) to get +file status and allow detection of symbolic links. +In addition, if each component +of the absolute path to the starting object has search permission, +the absolute path is used for early detection of cycles. +.IP +FTW_META|FTW_PHYSICAL: Use \fIstat\fR(2) for top level file status and +\fIlstat\fR(2) for all other files. +Used to implement the POSIX +.B \-H +option for commands like +.IR ls . +.IP +FTW_TWICE: Calls to the user function are issued in both preorder and postorder +for directory objects. +.IP +FTW_USER: The first of 6 user defined option bits. +These bits are ignored by \fIftwalk\fP. +.PP +\fIUserf\fR is a user supplied function that is +called upon different visits of an object. +If the return value of \fIuserf\fR is non-zero, +\fIftwalk\fR returns immediately with the same value. +The \fIuserf\fP prototype is: +.PP +.nf + int userf(struct FTW* ftw) +.fi +.PP +\fBstruct FTW\fP contains at least the following elements: +.PP +.nf + struct FTW* link; /* link list of children */ + struct FTW* parent; /* parent object on the search path */ + union + { + long number; /* local number */ + void* pointer; /* local pointer */ + } local; /* user defined */ + struct stat statb; /* stat buffer of this object */ + char* path; /* full pathname */ + short pathlen; /* strlen(path) */ + unsigned short info; /* type of object */ + unsigned short status; /* status of object */ + short level; /* depth of object on the search path */ + short namelen; /* strlen(name) */ + char name[]; /* file name of object */ +.fi +.PP +The \fIlink\fR field is normally NULL. +If the option FTW_CHILDREN was turned on, +it points to the start of the list of children +of the directory being visited in preorder. +Finally, if the directory being visited causes a cycle, +\fIlink\fR points to the object on the search path that is +identical to this directory. Note that if FTW_PHYSICAL was turned on, +this may point to a directory that is an ancestor of the starting +object. +.PP +The \fIparent\fR field points to the parent object +on the search path. For convenience, a parent object is also supplied for +the starting object. +In this case, except for the \fIlocal\fR field which is initialized +to 0 and the \fIlevel\fR field which contains a negative number, +the rest of the structure may be undefined. +.PP +The \fIinfo\fR field indicates the type of the object +being visited and the type of the visit. The types are: +.IP +FTW_D: A directory being visited in preorder, i.e., +none of its children has been visited by the search. +.IP +FTW_DNX: A directory being visited in preorder that does not have +search permission. +.IP +FTW_DP: A directory being visited in postorder, i.e., all of its +descendants have been completely processed. +.IP +FTW_DC: A directory that causes cycles. This is a terminal object. +.IP +FTW_DNR: A directory that cannot be opened for reading. This is a terminal object. +.IP +FTW_F: An ordinary file. +.IP +FTW_SL: A symbolic link. +Unless FTW_FOLLOW (below) is issued by the user function, +this object is terminal. +.IP +FTW_NS: \fIStat\fR failed on this object. +The stat buffer \fIstatb\fR is undefined. +This object is terminal. +.PP +The \fIstatus\fR field of \fIstruct FTW\fR is used to communicate information +between \fIftwalk\fR and \fIuserf\fR. On calls to \fIuserf\fR, it has one of +two values: +.IP +FTW_NAME: The name of the object as defined in \fIftw->name\fR should be used for +accessing its file information. This is because \fIchdir\fR(2) has been used +to set the current directory to a suitable place (see FTW_CHDIR). +.IP +FTW_PATH: The argument \fIpath\fR of \fIuserf\fR should be used +for accessing the file information of the object. +.PP +Upon returning, \fIuserf\fR may set the \fIstatus\fR field +to one of the following values: +.IP +FTW_AGAIN: If this is a directory object being visited in postorder, +it will be processed \fIagain\fR as if it had not been visited. +.IP +FTW_NOPOST: If this is a directory object being visited in preorder, +the user function will not be called on its postorder visit. +.IP +FTW_SKIP: This object and its descendants are pruned from the search. +.IP +FTW_FOLLOW: If this object is a symbolic link, +follow the link to its physical counterpart. +.PP +\fIComparf\fR, if not NULL, is a pointer to a function +used to define a search ordering for children of a directory. +If FTW_CHILDREN is turned on, the ordering of the children of +a directory is done before the preorder call to \fIuserf\fR on that directory. +Therefore, in that case, \fIftw->link\fR will point to the smallest child. +.PP +The \fIcomparf\fP prototype is: +.PP +.nf + int comparf(struct FTW* ftw1, struct FTW* ftw2) +.fi +.PP +\fIComparf\fR should return a value <0, 0, or >0 to indicate whether +\fIftw1\fR is considered smaller, equal, or larger than \fIftw2\fR. +.PP +\fIFtwalk\fR normally returns 0. +On hard errors such as running out of memory, it returns -1. +\fIFtwalk\fR may also return other values as discussed with respect +to \fIuserf\fR. +.PP +\fIFtwflags\fR returns a combination of \fB0, FTW_META, FTW_PHYSICAL\fR +according to the +preferences specified by +\fBastconf("PATH_RESOLVE",0,0)\fR: +.TP +.B logical +0 +.TP +.B metaphysical +.B "FTW_META|FTW_PHYSICAL" +.TP +.B physical +.B FTW_PHYSICAL +.SH HISTORY +\fIFtwalk\fR performs similar functions as that of +the routine \fIftw\fR provided in System V. +However, it is more general than \fIftw\fR +and suitable for use as a base in implementing +popular tools such as \fIls, find, tar, du,\fR and \fIrm\fR. +\fIFtwalk\fR also handles symbolic links and hard links gracefully. +.SH AUTHORS +Phong Vo, Glenn Fowler, Dave Korn +.SH SEE ALSO +find(1), rm(1), du(1), ls(1), tar(1), stat(2), symlink(2), +astfeature(3), ftw(3), pathcd(3) diff --git a/src/lib/libast/man/getcwd.3 b/src/lib/libast/man/getcwd.3 new file mode 100644 index 0000000..3403296 --- /dev/null +++ b/src/lib/libast/man/getcwd.3 @@ -0,0 +1,67 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH GETCWD 3 +.SH NAME +getcwd \- return absolute path to current directory +.SH SYNOPSIS +.EX +#include <ast.h> + +char* getcwd(char* \fIbuf\fP, size_t \fIlen\fP); +.EE +.SH DESCRIPTION +.L getcwd +copies the absolute path name of the current directory info into +.I buf +of length +.IR len . +The return path may be longer than +.LR PATH_MAX . +If +.I "buff == 0" +then space is allocated via +.IR malloc (3) +and +.I len +extra characters are reserved after the generated path name. +A pointer to the path name is returned, +.L 0 +on error. +.SH "SEE ALSO" +pathcd(3) diff --git a/src/lib/libast/man/hash.3 b/src/lib/libast/man/hash.3 new file mode 100644 index 0000000..162d62d --- /dev/null +++ b/src/lib/libast/man/hash.3 @@ -0,0 +1,644 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH HASH 3 +.SH NAME +hash \- hash table support (obsolete: use \fBcdt\fP instead) +.SH SYNOPSIS +.L "#include <hash.h>" +.SH DESCRIPTION +The +.I hash +routines manipulate collections of dynamic, scoped hash tables. +.PP +A hash table provides an association between a +.I key +and its +.IR value . +A +.I key +is a sequence of +.L char +elements and a +.I value +is a user supplied pointer to the value. +Each hash table has a dynamic number of slots, +each pointing to the head of a forward linked +.IR "collision chain" . +.PP +Hashing occurs as follows: +a +.I "hash function" +takes a +.I key +as an argument and returns a non-negative index. +The index modulo the table size produces a +slot that points to a +.IR "collision chain" . +The collision chain is sequentially searched until a match is found for +.IR key . +The hash tables are automatically resized as new entries are added. +.PP +Each hash table has one key type. +The default key type is a pointer to a null-terminated string. +The alternate key type is a pointer to a fixed length byte buffer, +declared for a given table by the +.L hashalloc() +function described below. +.PP +Hash table information is partitioned into two parts for efficient scoping. +The +.I root +part contains fixed information that is shared among a set of related +hash tables. +The remaining information is maintained on a per-table basis. +.PP +These basic types are defined in the header file +.B hash.h +(alternate names are listed in parenthesis): +.TP +.L "Hash_table_t (HASHTABLE)" +The per-table information. +The readonly public elements are: +.RS +.TP +.L "int buckets" +The number of table entries. +.TP +.L "char* name" +The hash table name. +.TP +.L "root" +The root information. +The public elements are: +.RS +.TP +.L "int root->accesses" +The number of lookups. +.TP +.L "int root->collisions" +The number of lookup collisions. +.RE +.TP +.L "Hash_table_t* scope" +The table that this scope covers, +.L NULL +if the table is not a scope. +.TP +.L "int size" +The current hash table size. +.RE +.TP +.L "Hash_bucket_t (HASHBUCKET)" +A collision chain hash bucket. +The public structure elements are: +.RS +.TP +.L "char* hashname(Hash_bucket_t*)" +Returns a pointer to the hash bucket key given the bucket pointer. +.TP +.L "char* value" +The value associated with the key. +.RE +.TP +.L "Hash_header_t (HASHHEADER)" +The hash bucket header that must be the first element in all user defined +buckets. +.L HASH_VALUE +may not be used with user defined buckets. +.TP +.L "Hash_position_t (HASHPOSITION)" +Stores the hash table position for +.LR hashscan . +The public elements are: +.RS +.TP +.L "Hash_bucket_t* bucket" +The current hash bucket pointer. +.RE +.PP +The routines are: +.TP +.L "Hash_table_t* hashalloc(Hash_table_t* ref, int op, ...)" +Creates a new hash table and returns a pointer to the table. +.IR malloc (3) +is used to allocate space for the table. +.L NULL +is returned if the table cannot be created. +.L ref +is a pointer to a reference hash table that provides +default values for unspecified information. +The new hash table and +.L ref +share the same root information. +If +.L ref +is +.L NULL +then new root information is created for the new table. +The remaining arguments appear in +.I op-arg +pairs, followed by a final +.L 0 +argument. +The +.I op-arg +pairs are: +.RS +.TP +.L "HASH_alloc, (char(*)()) alloc" +.L alloc +is a function that is called to process +.L Hash_bucket_t +.L value +assignments. +The single argument is +.L "char* value" +and the processed +.L char* +value is returned. +.TP +.L "HASH_clear, int flags" +.L flags +are the +.L ref +flags to be cleared in the new hash table. +See +.L HASH_set +below. +.TP +.L "HASH_compare, (int(*)()) compare" +Specifies an alternate +.I key +comparison function. +The arguments and return value for +.L compare +are the same as for +.IR strncmp (3) +if +.L HASH_namesize +is specified and +.IR strcmp (3) +otherwise. +The first argument is the +.I key +from the current hash bucket on the +.I "collision chain" +and the second argument is the user supplied +.IR key . +.TP +.L "HASH_free, (int(*)()) free" +.L free +is a function that is called when a hash bucket is freed. +If +.L HASH_BUCKET +was set in +.L hashalloc +then the hash bucket pointer is passed, otherwise the bucket +.L value +pointer is passed. +.TP +.L "HASH_hash, (int(*)()) hash" +Specifies an alternate +.I key +hash function. +A +.L char* +key argument (and, if +.L HASH_namesize +is specified, an +.L int +key size argument) is passed to +.LR hash . +The return value must be a non-negative +.LR int . +.TP +.L "HASH_meanchain, int meanchain" +Specifies the mean collision chain length. +The hash table is automatically resized when this value is exceeded. +The default mean chain length is 2. +.TP +.L "HASH_name, char* name" +Associates +.L name +with the hash table. +Used by +.LR hashdump) . +.TP +.L "HASH_namesize, int namesize" +The fixed size in bytes for +.I keys +in the table. +If +.L namesize +is 0 (the default) then the +.I keys +are interpreted as null-terminated strings. +.TP +.L "HASH_set, int flags" +Changes the hash table flags by +.IR or ing +in +.LR flags . +The flags, which may be +.IR or ed +together, are: +.RS +.TP +.L HASH_ALLOCATE +Keys for new hash table entries are to be copied to data areas obtained from +.IR malloc (3). +.TP +.L HASH_FIXED +Fixes the hash table size, disabling any automatic table resizing. +.TP +.L HASH_SCOPE +The new hash table is a scope that is to be pushed on top of +.LR ref . +.L ref +must be +.RL non- NULL . +.RE +.TP +.L "HASH_va_list, va_list ap" +.L ap +is a +.L va_list +variable argument list pointer +(see +.LR <stdarg.h> ). +.RE +.TP +.L "Hash_table_t* hashfree(Hash_table_t* tab)" +The hash table +.L tab +is freed. +The scope covered table pointer is returned, +.L NULL +if +.L tab +is not a scope. +.TP +.L "char* hashlook(Hash_table_t* tab, char* name, int flags, char* value)" +Operates on the key +.L name +in the hash table +.L tab +according to +.L flags +and +.LR value . +A +.L Hash_bucket_t +pointer is returned unless otherwise noted. +There are three basic lookup operations: +.RS +.TP +.L HASH_CREATE +.L name +is entered into the top level scope if it does not already exist. +If +.L name +also appears in a lower scope and +.L HASH_ALLOC +is set for the table then the new bucket will share the +.L name +field value with the lower scope. +.TP +.L HASH_DELETE +.L name +is deleted from the top level scope if it exists. +.L NULL +is returned. +.TP +.L HASH_LOOKUP +The scopes are searched in order from top to bottom for +.L name . +The bucket pointer for the first occurrence is returned. +.L NULL +is returned if +.L name +is not found. +.RE +The basic operations may be qualified by the following +(the qualifiers are restricted to the basic operations in +the parenthesized list): +.RS +.TP +.L "HASH_BUCKET (HASH_CREATE,HASH_DELETE,HASH_LOOKUP)" +.L name +is a pointer to a bucket that has already been entered into the table. +.TP +.L "HASH_FIXED (HASH_CREATE)" +.L value +is taken to be the size of the hash bucket to be created for +.L name +in the top level scope. +The minimum bucket size is silently restricted to +.LR sizeof(Hash_header_t) . +.TP +.L "HASH_INSTALL (HASH_CREATE)" +.L name +is a pointer to a bucket that has not been entered into the table. +.TP +.L "HASH_NOSCOPE (HASH_LOOKUP)" +The lookup is restricted to the top level scope. +.TP +.L "HASH_OPAQUE (HASH_CREATE,HASH_DELETE)" +Sets +.L (HASH_CREATE) +or clears +.L (HASH_DELETE) +the +.I opaque +property for the bucket. +An opaque bucket is not visible in lower scopes. +.TP +.L "HASH_SCOPE (HASH_CREATE,HASH_DELETE)" +All scopes are searched for the bucket. +If the bucket is not found for +.L HASH_CREATE +then a new bucket is created in the lowest scope. +.TP +.L "HASH_VALUE (HASH_CREATE,HASH_LOOKUP)" +For +.L HASH_CREATE +the bucket +.L value +field is set to +.L value +and the bucket +.L name +value is returned. +For +.L HASH_LOOKUP +the bucket +.L value +field is returned, +.L NULL +if the bucket is not found. +.RE +If +.L name +.L NULL +then the name from the most recent +.L hashlook() +is used, avoiding recomputation of some internal parameters. +.TP +.L "char* hashget(Hash_table_t* tab, char* name)" +Returns the value +associated with the key +.L name +in the hash table +.LR tab . +If +.L name +is +.L NULL +then the name from the most recent +.L hashget() +is used, avoiding recomputation of some internal parameters. +.L NULL +is returned if +.L name +is not in the table. +All scope covered tables are searched. +.TP +.L "Hash_bucket_t* hashlast(Hash_table_t* tab)" +Returns a pointer to the most recent hash bucket for +.LR tab . +The value is set by +.LR hashlook() , +.L hashscan() +and +.LR hashwalk() . +.TP +.L "char* hashput(Hash_table_t* tab, char* name, char* value)" +Set the value of the key +.L name +to +.L value +in the top level scope of the hash table +.LR tab . +.L name +is entered into the top level scope if necessary. +The (possibly re-allocated) key name pointer is returned +(see +.LR HASH_ALLOCATE ). +If +.L name +is 0 then the most recent lookup +.L name +to +.L hashlook() +or +.L hashget() +is used. +This eliminates a re-hash and re-lookup of +.LR name . +.TP +.L "int hashwalk(Hash_table_t* tab, int flags, (int(*)()) walker, char* handle)" +The function +.L walker +is applied to each entry (not covered by a scope starting at +.LR tab ) +in the hash table +.LR tab . +If +.L flags +is +.L HASH_NOSCOPE +then only the top level hash table is used, otherwise the walk includes +all scope covered tables. +.L walker +is called with +.L char* +.I key +as the first argument, +.L char* +.I value +as the second argument, and +.L char* +.I handle +as the third argument. +.I handle +may be +.LR 0 . +The walk terminates after the last entry or when +.L walker +returns a negative value. +The return value of the last call to +.L walker +is returned. +Only one walk may be active within a collection of scoped tables. +.TP +.L "Hash_position_t* hashscan(Hash_table_t* tab, int flags)" +Returns a +.L Hash_position_t +pointer for a sequential scan on the hash table +.LR tab . +If +.L flags +is +.L HASH_NOSCOPE +then only the top level hash table is used, otherwise the scan includes +all scope covered tables. +Only one scan may be active within a collection of scoped tables. +.L hashdone() +must be called to terminate the scan. +.L 0 +is returned on error. +.TP +.L "Hash_bucket_t* hashnext(Hash_position_t* pos)" +Returnes a pointer to the next bucket in the sequential scan set up by +.L hashscan() +on +.LR pos . +If no elements remain then +.L 0 +is returned. +.TP +.L "void hashdone(Hash_position_t* pos)" +Completes a scan initiated by +.L hashscan() +on +.LR pos . +.TP +.L "int hashset(Hash_table_t* tab, int flags)" +Sets the flags for the hash table +.L tab +by +.IR or ing +in +.LR flags . +Only +.L HASH_ALLOCATE +and +.L HASH_FIXED +may be set. +.TP +.L "int hashclear(Hash_table_t* tab, int flags)" +Clears the flags for the hash table +.L tab +by masking out +.LR flags . +Only +.L HASH_ALLOCATE +and +.L HASH_FIXED +may be cleared. +.TP +.L "void hashdump(Hash_table_t* tab, int flags)" +Dumps hash table accounting info to standard error. +If +.L tab +is +.L NULL +then all allocated hash tables are dumped, otherwise only information on +.L tab +is dumped. +If +.L flags +is +.L HASH_BUCKET +then the hash bucket +.I key-value +pairs for each collision chain are also dumped. +.TP +.L "void hashsize(Hash_table_t* tab, int size)" +Changes the size of the hash table +.L tab +to +.L size +where +.L size +must be a power of 2. +Explicit calls to this routine are not necessary as hash tables +are automatically resized. +.TP +.L "int strhash(char* name)" +Hashes the null terminated character string +.L name +using a linear congruent pseudo-random number generator algorithm +and returns a non-negative +.L int +hash value. +.TP +.L "int memhash(char* buf, int siz)" +Hashes the buffer +.L buf +of +.L siz +bytes using a linear congruent pseudo-random number generator algorithm +and returns a non-negative +.L int +hash value. +.TP +.L "long strsum(char* name, long sum)" +Returns a running 31-bit checksum of the string +.L name +where +.L sum +is +.L 0 +on the first call and +the return value from a previous +.L memsum +or +.L strsum +call otherwise. +The checksum value is consistent across all implementations. +.TP +.L "long memsum(char* buf, int siz, long sum)" +Returns a running 31-bit checksum of buffer +.L buf +of +.L siz +bytes where +.L sum +is +.L 0 +on the first call and +the return value from a previous +.L memsum +or +.L strsum +call otherwise. +The checksum value is consistent across all implementations. +.SH "SEE ALSO" +sum(1) diff --git a/src/lib/libast/man/iblocks.3 b/src/lib/libast/man/iblocks.3 new file mode 100644 index 0000000..0c615f8 --- /dev/null +++ b/src/lib/libast/man/iblocks.3 @@ -0,0 +1,62 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH IBLOCKS 3 +.SH NAME +iblocks \- compute number file blocks used +.SH SYNOPSIS +.EX +#include <ls.h> + +long _iblocks(struct stat* \fIst\fP); +.EE +.SH DESCRIPTION +.L _iblocks +returns the number of blocks used by the file whose +.IR stat (2) +information is pointed to by +.IR st . +The count includes both data and indirect blocks. +.PP +This routine is used by +.B <ls.h> +on system without the +.LI "struct stat" st_blocks +field. +.SH "SEE ALSO" +ls(1), stat(2) diff --git a/src/lib/libast/man/int.3 b/src/lib/libast/man/int.3 new file mode 100644 index 0000000..8d457c0 --- /dev/null +++ b/src/lib/libast/man/int.3 @@ -0,0 +1,68 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH INT 3 +.SH NAME +int \- integral type macros +.SH SYNOPSIS +.EX +#include <int.h> +.EE +.SH DESCRIPTION +This header defines macros for the local integral types. +.LR int_1 , +.LR int_2 +and +.L int_4 +are always defined to integral types with a size of +1, 2 and 4 bytes respectively. +The macros +.LI int_ n +where +.I n +is a power of 2 greater than 4 are defined if the type is supported. +.L int_max +is defined to be the largest support integral type. +.L int_swap +is the +.IR swap (3) +operation that converts a local +.L int +to canonical big-endian representation. +.SH "SEE ALSO" +swap(3) diff --git a/src/lib/libast/man/ip6.3 b/src/lib/libast/man/ip6.3 new file mode 100644 index 0000000..1dadb05 --- /dev/null +++ b/src/lib/libast/man/ip6.3 @@ -0,0 +1,85 @@ +.fp 5 B +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH IP6 3 +.SH NAME +ip6 \- IP V6 address support +.SH SYNOPSIS +.EX +#include <ip6.h> + +char* fmtip6(unsigned char* addr, int bits); +int strtoip6(const char* str, char** end, unsigned char* addr, unsigned char* bits); +.EE + +.SH DESCRIPTION +.L fmtip6() +formats the IPV6 address +.L addr +with optional prefix bits +.L bits +(0 if not a prefix) into a thread-specific 0-terminated temporary buffer and returns a pointer +to the formatted value. + +.PP +.L strtoip6() +converts a formatted IPV6 address from the 0-terminated string +.L str +into a host order IPV6 address in +.L addr +which must be a buffer of at least +.L IP6ADDR +bytes. +If +.L bits +is not 0 then an optional +.BI / bits +(prefix size in bits) is parsed and +.L *bits +is set to the number of prefix bits. +If +.L end +is not 0 then +.L *end +will point to the first unparsed character in +.L str +on return. +0 is returned on success, -1 on failure. + +.SH "SEE ALSO" +dss(1) diff --git a/src/lib/libast/man/magic.3 b/src/lib/libast/man/magic.3 new file mode 100644 index 0000000..e8bf0e3 --- /dev/null +++ b/src/lib/libast/man/magic.3 @@ -0,0 +1,493 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH MAGIC 3 +.SH NAME +magic \- magic file interface +.SH SYNOPSIS +.EX +#include <magic.h> + +Magic_t +{ + unsigned long flags; +}; + +Magic_t* magicopen(unsigned long \fIflags\fP); +void magicclose(Magic_t* \fImagic\fP); + +int magicload(Magic_t* \fImagic\fP, const char* \fIpath\fP, unsigned long \fIflags\fP); +int magiclist(Magic_t* \fImagic\fP, Sfio_t* \fIsp\fP); + +char* magictype(Magic_t* \fImagic\fP, const char* \fIpath\fP, struct stat* \fIst\fP); +.EE +.SH DESCRIPTION +These routines provide an interface to the +.IR file (1) +command magic file. +.L magicopen +returns a magic session handle that is passed to all of the other routines. +.I flags +may be +.TP +.L MAGIC_MIME +Return the MIME type string rather than the magic file description. +.TP +.L MAGIC_PHYSICAL +Don't follow symbolic links. +.TP +.L MAGIC_STAT +The stat structure +.I st +passed to +.I magictype +will contain valid +.I stat (2) +information. +See +.L magictype +below. +.TP +.L MAGIC_VERBOSE +Enable verbose error messages. +.PP +.L magicclose +closes the magic session. +.PP +.L magicload +loads the magic file named by +.I path +into the magic session. +.I flags +are the same as with +.LR magicopen . +More than one magic file can be loaded into a session; +the files are searched in load order. +If +.I path +is +.L 0 +then the default magic file is loaded. +.PP +.L magiclist +lists the magic file contents on the +.IR sfio (3) +stream +.IR sp . +This is used for debugging magic entries. +.PP +.L magictype +returns the type string for +.I path +with optional +.IR stat (2) +information +.IR st . +If +.I "st == 0" +then +.L magictype +calls +.L stat +on a private stat buffer, +else if +.L magicopen +was called with the +.L MAGIC_STAT +flag then +.I st +is assumed to contain valid stat information, otherwise +.L magictype +calls +.L stat +on +.IR st . +.L magictype +always returns a non-null string. +If errors are encounterd on +.I path +then the return value will contain information on those errors, e.g., +.LR "cannot stat" . +.SH FORMAT +The magic file format is a backwards compatible extension of an +ancient System V file implementation. +However, with the extended format it is possible to write a single +magic file that works on all platforms. +Most of the net magic files floating around work with +.LR magic , +but they usually double up on +.I le +and +.I be +entries that are automatically handled by +.LR magic . +.PP +A magic file entry describes a procedure for determining a single file type +based on the file pathname, +.I stat (2) +information, and the file data. +An entry is a sequence of lines, each line being a record of +.I space +separated fields. +The general record format is: +.EX +[op]offset type [mask]expression description [mimetype] +.EE +.L # +in the first column introduces a comment. +The first record in an entry contains no +.LR op ; +the remaining records for an entry contain an +.LR op . +Integer constants are as in C: +.L 0x* +or +.L 0X* +for hexadecimal, +.L 0* +for octal and decimal otherwise. +.PP +The +.L op +field may be one of: +.TP +.L + +The previous records must match but the current record is optional. +.L > +is an old-style synonym for +.LR + . +.TP +.L & +The previous and current records must match. +.TP +.L { +Starts a nesting block that is terminated by +.LR } . +A nesting block pushes a new context for the +.L + +and +.L & +ops. +The +.L { +and +.L } +records have no other fields. +.TP +\fIid\f5{\fR +A function declaration and call for the single character identifier +.IR id . +The function return is a nesting block end record +.LR } . +Function may be redefined. +Functions have no arguments or return value. +.TP +\fIid\f5()\fR +A call to the function +.IR id . +.PP +The +.L offset +field is either the offset into the data upon which the current entry operates +or a file metadata identifier. +Offsets are either integer constants or offset expressions. +An offset expression is contained in (...) and is a combination of +integral arithmetic operators and the +.L @ +indirection operator. +Indirections take the form +.LI @ integer +where integer is the data offset for the indirection value. +The size of the indirection value is taken either from one of the suffixes +.LR B (byte, 1 char), +.LR H (short, 2 chars), +.LR L (long, 4 chars), +pr +.LR Q (quead, 8 chars), +or from the +.L type +field. +Valid file metadata identifiers are: +.TP +.L atime +The string representation of +.LR stat.st_atime . +.TP +.L blocks +.LR stat.st_blocks . +.TP +.L ctime +The string representation of +.LR stat.st_ctime . +.TP +.L fstype +The string representation of +.LR stat.st_fstype . +.TP +.L gid +The string representation of +.LR stat.st_gid . +.TP +The +.L stat.st_mode +file mode bits in +.IR modecanon (3) +canonical representation (i.e., the good old octal values). +.TP +.L mtime +The string representation of +.LR stat.st_mtime . +.TP +.L nlink +.LR stat.st_nlink . +.TP +.L size +.LR stat.st_size . +.TP +.L name +The file path name sans directory. +.TP +.L uid +The string representation of +.LR stat.st_uid . +.PP +The +.L type +field specifies the type of the data at +.LR offset . +Integral types may be prefixed by +.L le +or +.L be +for specifying exact little-endian or big-endian representation, +but the internal algorithm automatically loops through the +standard representations to find integral matches, +so representation prefixes are rarely used. +However, this looping may cause some magic entry conflicts; use the +.L le +or +.L be +prefix in these cases. +Only one representation is used for all the records in an entry. +Valid types are: +.TP +.L byte +A 1 byte integer. +.TP +.L short +A 2 byte integer. +.TP +.L long +A 4 byte integer. +.TP +.L quad +An 8 byte integer. +Tests on this type may fail is the local compiler does not support +an 8 byte integral type and the corresponding value overflows 4 bytes. +.TP +.L date +The data at +.L offset +is interpreted as a 4 byte seconds-since-the-epoch date and +converted to a string. +.TP +.L edit +The +.L expression +field is an +.IR ed (1) +style substitution expression +\fIdel old del new del \fP [ \fI flags \fP ] +where the substituted value is made available to the +.L description +field +.L %s +format. +In addition to the +.I flags +supported by +.IR ed (3) +are +.L l +that converts the substituted value to lower case and +.L u +that converts the substituted value to upper case. +If +.I old +does not match the string data at +.L offset +then the entry record fails. +.TP +.L match +.L expression +field is a +.IR strmatch (3) +pattern that is matched against the string data at +.LR offset . +.TP +.L string +The +.L expression +field is a string that is compared with the string data at +.LR offset . +.PP +The optional +.L mask +field takes the form +.LI & number +where +.I number +is +.I anded +with the integral value at +.L offset +before the +.L expression +is applied. +.PP +The contents of the expression field depends on the +.LR type . +String type expression are described in the +.L type +field entries above. +.L * +means any value and applies to all types. +Integral +.L type +expression take the form [\fIoperator\fP] \fIoperand\P where +.I operand +is compared with the data value at +.L offset +using +.IR operator . +.I operator +may be one of +.LR < . +.LR <= , +.LR == , +.LR >= +or +.LR > . +.I operator +defaults to +.L == +if omitted. +.I operand +may be an integral constant or one of the following builtin function calls: +.TP +.L magic() +A recursive call to the magic algorithm starting with the data at +.LR offset . +.TP +\f5loop(\fIfunction\fP,\fIoffset\fP,\fIincrement\fP)\fR +Call +.I function +starting at +.I offset +and increment +.I offset +by +.I increment +after each iteration. +Iteration continues until the description text does not change. +.PP +The +.L description +field is the most important because it is this field that is presented +to the outside world. +When constructing description +fields one must be very careful to follow the style layed out in the +magic file, lest yet another layer of inconsistency creep into the system. +The description for each matching record in an entry are concatenated +to form the complete magic type. +If the previous matching description in the current entry does not end with +.I space +and the current description is not empty and does not start with +.I comma , +.I dot +or +.I backspace +then a +.I space +is placed between the descriptions +(most optional descriptions start with +.IR comma .) +The data value at +.L offset +can be referenced in the description using +.L %s +for the string types and +.L %ld +or +.L %lu +for the integral types. +.PP +The +.L mimetype +field specifies the MIME type, usually in the form +.IR a / b . +.SH FILES +.L ../lib/file/magic +located on +.L $PATH +.SH EXAMPLES +.EX +0 long 0x020c0108 hp s200 executable, pure +o{ ++36 long >0 , not stripped ++4 short >0 , version %ld +} + +0 long 0x020c0107 hp s200 executable +o() + +0 long 0x020c010b hp s200 executable, demand-load +o() +.EE +The function +.LR o() , +shared by 3 entries, +determines if the executable is stripped and also extracts the version number. +.EX +0 long 0407 bsd 386 executable +&mode long &0111!=0 ++16 long >0 , not stripped +.EE +This entry requires that the file also has execute permission. +.SH "SEE ALSO" +file(1), mime(4), tw(1), modecanon(3) diff --git a/src/lib/libast/man/mem.3 b/src/lib/libast/man/mem.3 new file mode 100644 index 0000000..70da0db --- /dev/null +++ b/src/lib/libast/man/mem.3 @@ -0,0 +1,98 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH MEM 3 +.SH NAME +mem \- fixed string routines +.SH SYNOPSIS +.EX +#include <ast.h> + +void mematoe(void* \fIout\fP, const void* \fIin\fP, size_t \fIn\fP); +void* memdup(const void* \fIbuf\fP, size_t \fIn\fP) +void memetoa(void* \fIout\fP, const void* \fIin\fP, size_t \fIn\fP); +void* memzero(void* \fIbuf\fP, size_t \fIn\fP); +.EE +.SH DESCRIPTION +.L mematoe +converts +.I n +ASCII characters in +.I in +to EBCDIC characters in +.IR out . +.I in +and +.I out +may be the same. +.PP +.L memdup +copies the +.I n +byte buffer +.I buf +to a new location provided by +.IR malloc (3) +and returns a pointer to the new copy. +0 is returned if +.IR malloc (3) +fails. +.PP +.L memetoa +converts +.I n +EBCDIC characters in +.I in +to ASCII characters in +.IR out . +.I in +and +.I out +may be the same. +.PP +.L memzero +sets the first +.I n +bytes in +.I buf +to +.IR 0 . +.SH "SEE ALSO" +Proposed Bell Laboratories ASCII/EBCDIC standard, April 16, 1979. +.br +str(3), vmalloc(3) diff --git a/src/lib/libast/man/mime.3 b/src/lib/libast/man/mime.3 new file mode 100644 index 0000000..f540b2e --- /dev/null +++ b/src/lib/libast/man/mime.3 @@ -0,0 +1,117 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH MIME 3 +.SH NAME +mime \- mime/mailcap interface +.SH SYNOPSIS +.EX +#include <mime.h> + +Mime_t +{ + unsigned long flags; +}; + +Mime_t* mimeopen(unsigned long \fIflags\fP); +void mimeclose(Mime_t* \fImime\fP); + +int mimeload(Mime_t* \fImime\fP, const char* \fIpath\fP, unsigned long \fIflags\fP); +int mimelist(Mime_t* \fImime\fP, Sfio_t* \fIsp\fP, const char* \fIpattern\fP); + +char* mimeview(Mime_t* \fImime\fP, const char* \fIview\fP, const char* \fIname\fP, const char* \fItype\fP, const char* \fIopts\fP); +int mimeset(Mime_t* \fImime\fP, char* \fIline\fP, unsigned long \fIflags\fP); +.EE +.SH DESCRIPTION +These routines provide an interface to the MIME type database. +.L mimeopen +returns a mime session handle that is passed to all of the other routines. +The +.I flags +argument is currently unused. +.PP +.L mimeclose +closes the mime session. +.PP +.L mimeload +loads the mime file named by +.I path +into the mime session. +.I flags +may be one of: +.TP +.L MIME_LIST +The +.I path +argument is a +.B : +separated list of pathnames, each of which is loaded. +Non-existent files are ignored +.L MIME_LIST +set. +.TP +.L MIME_REPLACE +Replace existing entries by new entries with the same type. +Otherwise original entries take precedence. +.PP +More than one mime file can be loaded into a session; +the files are searched in load order. +If +.I path +is +.L 0 +then the default mime file is loaded. +.PP +.L mimelist +lists the mime file contents on the +.IR sfio (3) +stream +.IR sp . +This is used for debugging mime entries. +.PP +.L mimetype +returns the type string for +.IR path . +.L mimetype +always returns a non-null string. +If errors are encounterd on +.I path +then the return value will be +.LR "error" . +.SH "SEE ALSO" +file(1), mime(4) diff --git a/src/lib/libast/man/modecanon.3 b/src/lib/libast/man/modecanon.3 new file mode 100644 index 0000000..4a5d128 --- /dev/null +++ b/src/lib/libast/man/modecanon.3 @@ -0,0 +1,104 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH MODECANON 3 +.SH NAME +modecanon \- canonical file mode representation +.SH SYNOPSIS +#include <modex.h> + +int modei(int \fIexternal\fP); +int modex(int \fIinternal\fP); +.EE +.SH DESCRIPTION +POSIX threw out the file type bit macros and replaced them with +function-like macros that test file type. +This is bad in many ways, the worst of which is that it provides +no way for a user program to synthesize file types in the mode bits. +.IR pax (1), +.IR tar (1) +and +.IR cpio (1) +are examples of user programs that must convert between the internal mode +representation and a private external representation. +These routines provide a canonical external representation +with macros to access and synthesize the bits in the external +representation. +.PP +.L modei +takes an external mode representation +.I external +and returns the equivalent internal representation. +.PP +.L modex +takes an internal mode representation +.I internal +and returns the equivalent external representation. +.PP +The traditional bit access macro (\f5S_\fP prefix changes to \f5X_\fP) are: +.L X_IFMT , +.L X_IFSOCK , +.L X_IFLNK , +.L X_IFCTG , +.L X_IFREG , +.L X_IFBLK , +.L X_IFDIR , +.L X_IFCHR , +.L X_IFIFO , +.L X_IPERM , +.L X_ISUID , +.L X_ISGID , +.L X_ISVTX , +.L X_IRUSR , +.L X_IWUSR , +.L X_IXUSR , +.L X_IRGRP , +.L X_IWGRP , +.L X_IXGRP , +.L X_IROTH , +.L X_IWOTH , +.L X_IXOTH , +.L X_IRWXU , +.L X_IRWXG +and +.L X_IRWXO . +.LI X_ITYPE( mode ) +returns the type bits for +.IR mode . +.SH "SEE ALSO" +pax(1), stat(2) diff --git a/src/lib/libast/man/optget.3 b/src/lib/libast/man/optget.3 new file mode 100644 index 0000000..90afcb8 --- /dev/null +++ b/src/lib/libast/man/optget.3 @@ -0,0 +1,68 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH OPTGET 3 +.SH NAME +optget \- option parse assist +.SH SYNOPSIS +.EX +#include <option.h> + +Opt_t +{ +}; + +Optdisc_t +{ + unsigned long version; + unsigned long flags; + char* catalog; + Optinfo_f infof; +}; + +Opt_t opt_info; + +void optinit(Optdisc_t* \fIdisc\fP, Error_f \fIerrorf\fP); +int optget(char** \fIargv\fP, const char* \fIusage\fP); +int optstr(const char* \fIstring\fP, const char* \fIusage\fP); +int optjoin(char** \fIargv\fP, ... [int (*\fIoptfun\fP)(char** \fIargv\fP, int \fIlast\fP)]); +char* optusage(const char* \fIopts\fP); +int optesc(Sfio_t* \fIsp\fP, const char* \fIstring\fP, int \fIflags\fP); +.EE +.SH DESCRIPTION +.SH "SEE ALSO" diff --git a/src/lib/libast/man/path.3 b/src/lib/libast/man/path.3 new file mode 100644 index 0000000..8721888 --- /dev/null +++ b/src/lib/libast/man/path.3 @@ -0,0 +1,391 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH PATH 3 +.SH NAME +path \- file path routines +.SH SYNOPSIS +.EX +#include <ast.h> + +char* pathaccess(char* \fIpath\fP, const char* \fIdirs\fP, const char* \fIa\fP, const char* \fIb\fP, int \fImode\fP); +char* pathbin(void); +char* pathcanon(char* \fIpath\fP, int \fIflags\fP); +char* pathcat(char* \fIpath\fP, const char* \fIdirs\fP, int \fIsep\fP, const char* \fIa\fP, const char* \fIb\fP); +char* pathcd(char* \fIpath\fP, const char* \fIhome\fP); +int pathcheck(const char* \fIpackage\fP, const char* \fItool\fP, Pathcheck_t* \fIpc\fP); +int pathgetlink(const char* \fIname\fP, char* \fIbuf\fP, int \fIsiz\fP); +char* pathkey(char* \fIkey\fP, char* \fIattr\fP, const char* \fIlang\fP, const char* \fIpath\fP); +char* pathnext(char* \fIpath\fP, char* \fIextra\fP, long* \fIvisits\fP); +char* pathpath(char* \fIpath\fP, const char* \fIp\fP, const char* \fIa\fP, int \fImode\fP); +char* pathprobe(char* \fIpath\fP, char* \fIattr\fP, const char* \fIlang\fP, const char* \fItool\fP, const char* \fIproc\fP, int \fIop\fP); +char* pathrepl(char* \fIpath\fP, const char* \fImatch\fP, const char* \fIreplace\fP); +int pathsetlink(const char* \fItext\fP, char* \fIname\fP); +char* pathshell(void); +int pathstat(const char* \fIpath\fP, struct stat* \fIst\fP); +char* pathtemp(char* \fIpath\fP, const char* \fIdir\fP, const char* \fIpfx\fP); +.EE +.SH DESCRIPTION +These routines operate on file path names. +Path buffers are assumed to be of size +.LR PATH_MAX . +.L <ast.h> +always defines +.LR PATH_MAX , +even if it indeterminant on the local system. +Yes, this was probably a bad choice, but it was made about 10 years ago. +We will probably move to a <stk.h> based implementation. +.PP +.L pathaccess +constructs a path in +.L path +to the file +.L a/b +with access +.L mode +using the +.L : +separated directories in +.IR dirs . +Both +.I a +and +.I b +may be +.LR 0 . +.L mode +is the inclusive-or of: +.TP +.L F_OK +File exists. +.TP +.L R_OK +Read permission on file. +.TP +.L W_OK +Write permission on file. +.TP +.L X_OK +Execute permission on file. +.TP +.L PATH_REGULAR +A regular file. +.TP +.L PATH_ABSOLUTE +Generated path name is rooted at +.LR / . +.I path +is returned, 0 on error. +.PP +.L pathbin +returns a pointer to the +.L : +separated list of directories to search for executable commands. +The +.L PATH +environment variable is first consulted. +If not defined then +.L confstr(_CS_PATH,...) +is used. +A valid string is always returned. +.PP +.L pathcanon +canonicalizes the path +.I path +in place. +A pointer to the trailing 0 in the canonicalized path is returned. +A canonical path has: +redundant +.L . +and +.L / +removed; +.L .. +moved to the front; +.L /.. +preserved for super root hacks; +.L ... +resolved if +.IR fs3d (3) +is enabled. +.I flags is the inclusive-or of: +.TP +.L PATH_DOTDOT +Each +.L .. +is checked for access. +.TP +.L PATH_EXISTS +Path must exist at each component. +.TP +.L PATH_PHYSICAL +Symbolic links are resolved at each component. +.PP +0 is returned on error. +If an error occurs and either of +.L PATH_DOTDOT +or +.L PATH_EXISTS +is set then +.I path +will contain the components following the failure point. +.PP +.L pathcat +concatenates the first +.I sep +separated path component in +.I dirs +with the path components +.I a +and +.I b +into +.LR path . +The path is constructed in +.I path +by separating each path component with +.IR / . +Both +.I a +and +.I b +may be +.LR 0 . +A pointer to the next +.I sep +separated component in +.I dirs +is returned, +.L 0 +when there are no more components. +.L pathcat +is used by +.LR pathaccess . +.PP +.L pathcd +sets the current working directory to +.I path +via +.IR chdir (2). +If +.I path +is longer than +.L PATH_MAX +then it is split up into a sequence of relative paths and +.I chdir +is called on each of these. +For any given system, if you got to a directory, then +.L pathcd +can get you back, modulo permission and link changes. +.PP +.L pathcheck +is a stub for license libraries. +See +.IR license (3). +.PP +.L pathgetlink +returns the 0-terminated symbolic link text for +.I path +in the buffer +.I bu +of size +.IR siz . +The link text length is returned on success, \-1 on error. +Weird +.I universe (1) +interactions with dynamic symbolic links are handled +by converting non-standard dynamic link text to +.LI .../$( UNIVERSE )/... +.L pathsetsymlink +converts in the other direction. +.PP +.L pathkey +generates in +.I key +a 14 character lookup key (plus terminating 0) for the language +.I lang +processor in +.IR path . +A poihter to the key is returned, 0 on error. +If +.I "key == 0" +then space is allocated via +.IR malloc (3). +Key specific attribute +.I name=value +pairs are copied into +.I attr +if +.IR "attr != 0" . +.PP +.L pathpath +constructs in +.I path +a path to +.I p +with +.IR access (2) +mode +.I mode +using the directories from +.LR pathbin() . +If \fIa != 0\fP then +.IR a , +.IR argv [0] +(if available via +.IR optget (3)), +and the +.L _ +environment variable (set by +.IR ksh (1) ) +are used for related root searching. +If +.I p +also contains a +.L / +then +.I ../p +is searched for. +.PP +.L pathprobe +generates in +.I path +the full path name of the +.I tool +specific +.IR probe (1) +information file for the +.I lang +langauge processor +.IR proc . +If +.I "path == 0" +then space is allocated via +.IR malloc (3). +Probe attribute +.I name=value +pairs are copied into +.I attr +if +.IR "attr != 0" . +.I op +may be one of: +.TP +.B \-1 +return the path name with no access checks or generation +.TP +.B 0 +message emitted information must be generated via +.IR probe (1) +.TP +.B 1 +no message emitted information must be probed via +.IR probe (1) +.PP +0 is returned if the information does not exist and cannot be generated. +.PP +.L pathrepl +does an in-place replacement of the first occurrence of +.I /match/ +with +.I /replace/ +in +.IR path . +.PP +.L pathsetlink +creates a symbolic link +.I text +in the path +.IR name . +See +.L pathgetlink +above for weird +.IR universe (1) +interactions hidden by this routine. +.PP +.L pathshell +returns a pointer to the pathname for the shell for the current process. +The +.L SHELL +environment variable is first consulted, but is rejected under suspicious +ownership/setuid conditions of if it seems to point to +.IR csh (1) ; +otherwise +.L confstr(_CS_SHELL,...) +is used. +A valid string is always returned. +.PP +.L pathstat +first tries +.LI stat( path,st ) +and if that fails it tries +.LI lstat( path,st ). +The +.L stat +or +.L lstat +return value is returned. +.PP +.L pathtemp +generates in +.I path +a temporary file path name of the form +.I dir/pfx<pid>.<suf> +where the length of +.IR pfx , +if !=0, is limited to 5, the length of +.I <pid> +(the base 64 representation of the current process id) +is limited to 3, and +.I <suf> +(an internally generated suffix that avoid file confilicts) +is limited to 3. +The generated path name conforms to the classic UNIX 14 char and the DOS +.LR 8.3 +limitations. +Both +.I dir +and +.I pfx +may be +.LR 0 . +.IR access (2) +is used to avoid file conflicts but the generated path name is not created, +so you could lose in a race. +.SH "SEE ALSO" +3d(1), access(2), confstr(3), fs3d(3), lstat(2), stat(2) diff --git a/src/lib/libast/man/preroot.3 b/src/lib/libast/man/preroot.3 new file mode 100644 index 0000000..025fc22 --- /dev/null +++ b/src/lib/libast/man/preroot.3 @@ -0,0 +1,151 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH PREROOT 3 +.SH NAME +preroot \- preroot support +.SH SYNOPSIS +.EX +#include <preroot.h> + +char* getpreroot(char* \fIpath\fP, char* \fIcmd\fP); +int ispreroot(char* \fIdir\fP); +int realopen(char* \fIpath\fP, int \fImode\fP, int \fIperm\fP); +void setpreroot(char** \fIargv\fP, char* \fIdir\fP); +.EE +.SH DESCRIPTION +The +.I preroot +routines manipulate the process preroot. +.I preroot +is a kernel supported per-process two level viewpath. +All pathnames rooted at +.L / +are first searched for in the process preroot directory +and then in the system root directory. +Setting the process preroot is a priveleged operation controlled by the +.IR /etc/preroot (1) +command. +.PP +.L <preroot.h> +defines the symbol +.B FS_PREROOT +for those systems that support preroot. +The following routines are valid only when +.B FS_PREROOT +is defined: +.TP +.L getpreroot +returns a pointer to the absolute pathname of the preroot directory +for the executable +.IR cmd . +The result is placed in +.IR path . +If +.I path +is +.B 0 +then +.IR malloc (3) +is used to allocate the pathname space. +.B 0 +is returned if +.I cmd +has no preroot or if an error was encountered. +In this case +.I errno +is set to indicate the error. +.TP +.L ispreroot +Non-zero is returned if +.I dir +is the current process preroot. +If +.I dir +is +.B 0 +then non-zero is returned if the current process has a preroot. +.TP +.L realopen +temporarily disables the process preroot and does an +.IR open (3) +relative to the system root directory. +The return value from +.I open +is returned. +If there is no preroot then +.I realopen +is equivalent to +.IR open . +.TP +.L setpreroot +calls +.IR execvp (3) +as +.L "execvp(a\fIrgv\fP[0],\fIargv\fP)" +with the process preroot set to +.IR dir . +.I argv +must be a +.BR 0 -terminated +argument array. +If +.I argv +is +.B 0 +then the value of +.I opt_argv +from +.IR optget (3) +is used. +.L setpreroot +returns immediately if +.I dir +is already the process preroot. +.SH "SEE ALSO" +/etc/preroot(1) +.SH BUGS +Preroot semantics should be preserved when reading directories. +The +.I ast +.IR directory (3) +routines do this. +.IR 3d (1) +viewpathing does +.I preroot +the right way. diff --git a/src/lib/libast/man/proc.3 b/src/lib/libast/man/proc.3 new file mode 100644 index 0000000..64c1a6e --- /dev/null +++ b/src/lib/libast/man/proc.3 @@ -0,0 +1,319 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH PROC 3 +.SH NAME +proc \- process control routines +.SH SYNOPSIS +.EX +#include <proc.h> + +Proc_t* procopen(const char* \fIcommand\fP, char** \fIargv\fP, char** \fIenvv\fP, long* \fIopv\fP, long \fIflags\fP); +int procfree(Proc_t* \fIproc\fP); +int procclose(Proc_t* \fIproc\fP); +int procrun(const char* \fIcommand\fP, char** \fIargv\fP); +.EE +.SH DESCRIPTION +These routines provide a portable interface to process creation and execution. +They work on systems with +.IR fork (2) +and +.IR exec (2) +as well as on systems with only +.IR spawnve (2) +or +.IR spanwveg (3). +.PP +.L procopen +runs +.I command +with arguments +.IR argv , +environment modifications in +.IR envv , +file descriptor, signal and process group operations in +.I opv +and flags in +.IR flags . +.PP +.I command +is searched for using the +.L PATH +environment variable from the calling environment. +If +.I command +is +.L 0 +then the current shell is used (see +.IR pathshell (3)). +If +.I envv +is not +.L 0 +then it is a +.L 0 +terminated vector of +\fIname\fP[=\fIvalue\fP] +strings that are added to the +.I command +environment using +.IR setenviron (3). +If +.I name +appears in the parent environment then its value is replaced with the new +.IR value . +If +.RI = value +is omitted then +.I name +is removed from the child environment. +The +.L _ +environment variable is set to contain the pathname for +.I command +and will appear at the top of the child environment. +.PP +If +.I opv +is not +.L 0 +then it is a 0 terminaled vector of operations to perform. +In the following +.I context +is a combination of +.L PROC_FD_CHILD +and +.L PROC_FD_PARENT +for the child and parent process context respectively. +Valid operations are: +.TP +\f5PROC_FD_CLOSE(\fIfd\fP,\fIcontext\fP)\fR +The file descriptor +.I fd +is closed in +.IR context . +.TP +\f5PROC_FD_DUP(\fIfrom\fP,\fIto\fP,\fIcontext\fP)\fR +The file descriptor +.I from +is +.IR dup (2)'d +into the file descriptor +.I to +in +.IR context . +.TP +\f5PROC_SIG_DFL(\fIsig\fP)\fR +The signal handler for +.I sig +is set to +.L SIG_DFL +in the child context. +.TP +\f5PROC_SIG_IGN(\fIsig\fP)\fR +The signal handler for +.I sig +is set to +.L SIG_IGN +in the child context. +.TP +\f5PROC_SYS_PGRP(\fIpgid\fP)\fR +The child process group is set to +.IR pgid . +.I pgid +may have the following values: +.TP +.L <0 +The child process becomes a session leader. +.TP +.L 0 +The child process is in the parent process group. +.TP +.L 1 +The child process becomes a process group leader. +.TP +.L >1 +The child process joins the process group +.IR pgid . +.TP +\f5PROC_SYS_UMASK(\fImask\fP)\fR +The child process group file creation mask is set to +.IR mask . +.PP +.I flags +is the inclusive-or of the following: +.TP +.L PROC_ARGMOD +.I "argv[-1]" +and +.I "argv[0]" +may be modified. +This is an optimization that avoids an environment vector +.I realloc(3) +when +.I command +is a shell script. +.TP +.L PROC_BACKGROUND +Standard shell +.L & +setup is done for the child process. +.TP +.L PROC_CLEANUP +Parent process redirection file discriptors are closed on error. +.TP +.L PROC_DAEMON +Standard daemon setup is done for the child process. +.TP +.L PROC_ENVCLEAR +The child environment is cleared before +.I envv +is added. +.TP +.L PROC_GID +The child effective group id is set to the real group id. +.TP +.L PROC_IGNORE +Parent pipe errors are ignored. +.TP +.L PROC_OVERLAY +The current process is overlayed by +.I command +if possible +(i.e., the +.IR fork (2) +call is omitted). +.TP +.L PROC_PARANOID +Paranoid: +.I command +is searched using the default standard +.LR PATH ; +the child environment variable +.L PATH +is set to the default standard; +the +.L PROC_GID +and +.L PROC_UID +modes are set; +only +.L /bin/sh +is used to execute +.I command +if it is a shell script. +.TP +.L PROC_PRIVELEGED +If the effective user id is +.L 0 +then the child real user id is set to +.L 0 +and the child real group id is set to the effective group id. +.TP +.L PROC_READ +.I proc.rfd +is connected to +.IR command 's +standard output. +.TP +.L PROC_SESSION +The child process becomes a session group leader. +(Equivalent to the +.I opv +entry +.LR PROC_SYS_PGRP(-1) .) +.TP +.L PROC_UID +The child effective user id is set to the real user id. +.TP +.L PROC_WRITE +.I proc.wfd +is connected to +.IR commands 's +standard input. +.PP +The return value is a pointer to a structure with the following members: +.TP +.L "pid_t \fIpid\fP" +The child process id. +.TP +.L "pid_t \fIpgrp\fP" +The child process group. +.TP +.L "int \fIrfd\fP" +A read file descriptor connected to +.IR command 's +standard output. +.TP +.L "int \fIwfd\fP" +A write file descriptor connected to +.IR command 's +standard input. +.PP +If an error occurs then +.L 0 +is returned. +.PP +.L procclose +waits for the process +.I proc +to complete and then closes the command stream +.IR proc . +The command exit status is returned. +.L -1 +is returned if the child portion of +.L procopen +failed. +.PP +.L procfree +frees the process stream without waiting for +.I command +to complete. +Presumably some other mechanism will be used to wait for +.IR proc.pid . +.PP +.L procrun +combines +.L procopen +and +.L procclose +with the flags +.L PROC_GID|PROC_UID +and returns the command exit status. +.SH "SEE ALSO" +popen(3), sfpopen(3), spawnveg(3), system(3) diff --git a/src/lib/libast/man/re.3 b/src/lib/libast/man/re.3 new file mode 100644 index 0000000..2e1010e --- /dev/null +++ b/src/lib/libast/man/re.3 @@ -0,0 +1,214 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH RE 3 +.SH NAME +recomp, reexec, ressub, refree, reerror \(mi regular expression library +.SH SYNOPSIS +.EX +#include <re.h> + +Re_program_t* recomp(char* \fIpattern\fP, int \fIflags\fP); +int reexec(Re_program_t* \fIre\fP, char* \fIsource\fP); +void ressub(Re_program_t* \fIre\fP, Sfio_t* \fIsp\fP, char* \fIold\fP, char* \fInew\fP, int \fIflags\fP); +void reerror(char* \fImessage\fP); +void refree(Re_program_t* \fIre\fP); +.EE +.SH DESCRIPTION +.L recomp +compiles a regular expression in +.I pattern +and returns a pointer to the compiled regular expression. +The space is allocated by +.IR malloc (3) +and may be released by +.LR refree . +Regular expressions are as in +.IR egrep (1) +except that newlines are treated as ordinary +characters and +.L $ +matches the end of a null-terminated string. +.I flags +may be +.L RE_EDSTYLE +which specifies +.IR ed (1) +style special characters, +.LR \e( , +.LR \e) , +.LR \e? , +.L \e+ +and +.L \e| +for the +.IR egrep (1) +.LR ( , +.LR ) , +.LR ? , +.L + +and +.LR | , +respectively. +.PP +.L reexec +matches the null-terminated +.I source +string against the compiled regular expression +.I re +from a previous call to +.LR recomp . +If it matches, +.L reexec +returns a non-zero value. +If +.I flags +is +.L RE_MATCH +then the array +.I re\->match +is filled with character pointers to the substrings of +.I source +that correspond to the +parenthesized subexpressions of +.IR pattern : +.I re\->match[i].sp +points to the beginning and +.I re\->match[i].ep +points just beyond +the end of substring +.IR i . +(Subexpression +.I i +begins at the +.IR i th +matched left parenthesis, counting from 1.) +Pointers in +.I re\->match[0] +pick out the substring that corresponds to +the entire regular expression. +Unused elements of +.I re\->match +are filled with zeros. +Matches involving +.LR * , +.LR + , +and +.L ? +are extended as far as possible. +A maximum of 9 subexpressions will be matched. +The structure of elements of +.I re\->match +is: +.nf +.ta 8n + typedef struct + { + char* sp; + char* ep; + } rematch; +.fi +.LP +.L ressub +places in the +.IR sfio (3) +stream +.I sp +a substitution instance of +.I old +to +.I new +in +.I source +in the context of the last +.L reexec +performed on +.IR re\->match . +Each instance of +.LI \e n , +where +.I n +is a digit, is replaced by the +string delimited by +.LI re\->match[ n ].sp +and +.LI re\->match[ n ].ep . +Each instance of +.L & +is replaced by the string delimited by +.I re\->match[0].sp +and +.IR re\->match[0].ep . +If +.L RE_ALL +is set in +.I flags +then all occurrences of +.I old +are replaced by +.IR new . +If +.L RE_LOWER +.RL [ RE_UPPER ] +is set in +.I flags +then +.I old +is converted to lower [upper] case. +.LP +.L reerror, +called whenever an error is detected in +.L recomp, +.L reexec, +or +.L ressub, +writes the string +.I msg +on the standard error file and exits. +.L reerror +may be replaced to perform +special error processing. +.SH DIAGNOSTICS +.L recomp +returns 0 for an invalid expression or other failure. +.L reexec +returns 1 if +.I source +is accepted, 0 otherwise. +.SH "SEE ALSO" +ed(1), grep(1), expr(1) diff --git a/src/lib/libast/man/regex.3 b/src/lib/libast/man/regex.3 new file mode 100644 index 0000000..7c15d21 --- /dev/null +++ b/src/lib/libast/man/regex.3 @@ -0,0 +1,163 @@ +.fp 5 B +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH REGEX 3 +.SH NAME +regex \- regular expression interface +.SH SYNOPSIS +.EX +#include <regex.h> + +int regcomp(regex_t* \fIre\fP, const char* \fIregex\fP, int \fIcflags\fP); +int regexec(const regex_t* \fIre\fP, const char* \fIstring\fP, size_t \fInmatch\fP, regmatch_t \fIpmatch\fP[], int \fIeflags\fP); +size_t regerror(int \fIcode\fP, const regex_t* \fIre\fP, char* \fIerrbuf\fP, size_t \fIerrbuf_size\fP); +void regfree(regex_t* \fIre\fP); + +regclass_t regclass(const char* \fIstr\fP, char** \fIend\fP); +int regaddclass(const char* \fIname\fP, regclass_t \fIclassf\fP); +int regcollate(const char* \fIstr\fP, char** \fIend\fP, char* \fIbuf\fP, int \fIsize\fP); + +int regcomb(regex_t* \fIre_1\fP, regex_t* \fIre_2\fP); +size_t regdecomp(regex_t* \fIre\fP, regflags_t \fIflags\fP, char* \fIbuf\fP, size_t \fIsize\fP); +int regdup(regex_t* \fIre_old\fP, regex_t* \fIre_new\fP); +regstat_t* regstat(const regex_t* \fIre\fP); + +regex_t* regcache(const char* \fIpattern\fP, regflags_t \fIflags\fP, int* \fIpcode\fP); + +int regncomp(regex_t* \fIre\fP, const char* \fIpattern\fP, size_t \fIsize\fP, regflags_t \fIflags\fP); +int regnexec(const regex_t* \fIre\fP, const char* \fIsubject\fP, size_t \fIsize\fP, size_t \fInmatch\fP, regmatch_t* \fImatch\fP, regflags_t \fIflags\fP); +int regrecord(const regex_t* \fIre\fP); +int regrexec(const regex_t* \fIre\fP, const char* \fIbuf\fP, size_t \fIsize\fP, size_t \fInmatch\fP, regmatch_t* \fImatch\fP, regflags_t \fIflags\fP, int \fIsep\fP, void* \fIhandle\fP, regrecord_t \fIrecordf\fP); +void regfatal(regex_t* \fIre\fP, int \fIlevel\fP, int \fIcode\fP); +void regfatalpat(regex_t* \fIre\fP, int \fIlevel\fP, int \fIcode\fP, const char* \fIpattern\fP); + +int regsubcomp(regex_t* \fIre\fP, const char* \fIstr\fP, const regflags_t* \fImap\fP, int \fIminmatch\fP, regflags_t \fIflags\fP); +int regsubexec(const regex_t* \fIre\fP, const char* \fIsubject\fP, size_t \fInmatch\fP, regmatch_t* match); +int regsubflags(regex_t* \fIre\fP, const char* \fIstr\fP, char** \fIend\fP, int \fIdelim\fP, const regflags_t* \fImap\fP, int* \fIpm\fP, regflags_t* \fIpf\fP); +void regsubfree(regex_t* \fIre\fP); +.EE + +.SH DESCRIPTION +.LR regcomp() , +.LR regexec() , +.LR regerror() , +and +.L regfree() +are the POSIX regular expression functions. +The remaining functions are +.B ast +extensions. +.B ast +also provides +.I flags +extensions to the +.LR regcomp() , +.LR regexec() +functions and +.I code +extensions to the +.L regerror() +function. + +.PP +.L regcache() +maintains a cache of compiled regular expressions for patterns of size +255 bytes or less. +The initial cache size is 8. +.L pattern +and +.L flags +are passed to +.L regcomp() +with an +.L re +pointer maintained by +.LR regcache() . +.LR pcode , +if not 0, points to the return value of the +.L regcomp() +call. +If the +.L regcomp() +call fails, +.L regcache() +returns 0 and +.L pcode +will point to the non-zero error code. +Do not call +.L regfree() +on the +.L re +returned by +.LR regcache() . +Both +.L pattern +and +.L flags +are used to match entries in the cache. +When the cache is full the least recently used +.L re +is freed (via +.LR regfree() ) +to make space for the new pattern. +Any +.L re +previously returned by +.L regcache() +may be freed (invalidated) on the next call to +.LR regcache() . +If +.L pattern +is longer that 255 bytes then it is still passed on to +.LR regcomp() , +but it will not be cached. +If +.L pattern +is 0 then the cache is flushed. +In addition, if the integer value of +.L flags +is greater than the current cache size, the cache size is increased +to that integer value. +0 is always returned when +.L pattern +is 0; +.L pcode +will point to a non-zero value on error. + +.SH "SEE ALSO" +strmatch(3) diff --git a/src/lib/libast/man/setenviron.3 b/src/lib/libast/man/setenviron.3 new file mode 100644 index 0000000..818f7fc --- /dev/null +++ b/src/lib/libast/man/setenviron.3 @@ -0,0 +1,79 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH LIBAST 3 +.SH NAME +setenviron \- set environment value +.SH SYNOPSIS +.EX +#include <ast.h> + +char* setenviron(const char* \fIkey\fP); +.EE +.SH DESCRIPTION +.L setenviron +controls environment +.I name=value +pairs. +.L setenviron("\fIname=value\fP") +adds +.I name +to the environment and returns a pointer to a +.IR strdup (3) +copy of +.IR name=value . +.L setenviron("\fIname\fP") +removes +.I name +from the environment and returns the empty string. +.L setenviron(0) +reserves a few slots in an internal array and is usually called by +a parent process that expects many children. +0 is returned on error. +.L setenviron +preserves the +.IR ksh (1) +convention of +.L _ +as the first environment variable name. +.SH "SEE ALSO" +env(1), exec(2) +.SH BUGS +POSIX will eventually settle on an interface. +It has already picked a few of the names we did in .2 drafts. +This is about the third name change for ours. diff --git a/src/lib/libast/man/sfdisc.3 b/src/lib/libast/man/sfdisc.3 new file mode 100644 index 0000000..f0ce5b0 --- /dev/null +++ b/src/lib/libast/man/sfdisc.3 @@ -0,0 +1,118 @@ +.fp 5 CW +.TH SFDISC 3 "16 June 1993" +.SH NAME +\fBsfdisc\fR \- \fBsfio\fP disciplines +.SH SYNOPSIS +.de Tp +.fl +.ne 2 +.TP +.. +.de Ss +.fl +.ne 2 +.SS "\\$1" +.. +.ta 1.0i 2.0i 3.0i 4.0i 5.0i +.nf +.ft 5 +#include <sfdisc.h> + +extern Sfdisc_t* dcnewskable(Sfio_t* f); +extern int dcdelskable(Sfdisc_t* disc); + +extern Sfdisc_t* dcnewtee(Sfio_t* tee); +extern int dcdeltee(Sfdisc_t* disc); + +extern Sfdisc_t* dcnewfilter(char* cmd); +extern int dcdelfilter(Sfdisc_t* disc); + +extern Sfdisc_t* dcnewsubstream(Sfio_t* f, long offset, long extent); +extern int dcdelsubstream(Sfdisc_t* disc); + +extern Sfdisc_t* dcnewlzw(void); +extern int dcdellzw(Sfdisc_t* disc); + +extern Sfdisc_t* dcnewunion(Sfio_t** flist, int n); +extern int dcdelunion(Sfdisc_t* disc); +.ft 1 +.fi +.SH DESCRIPTION +.PP +I/O disciplines are used to extend the data processing power of +\fIsfio\fP streams. The convention for using the disciplines +in this package is to use the call \f5dcnewXXX()\fP to create +a discipline of the type \f5XXX\fP and to use \f5dcdelXXX()\fP +to destroy it. +A discipline is enable by inserting it into the desired +stream using the \f5sfdisc()\fP call. A discipline can be used on only +one stream. It is unsafe to share a discipline on two or more streams +since the discipline may maintain states between successive IO calls. +For multiple uses, \f5dcnewXXX()\fP should be used +to create a distinct discipline for each stream. +Each discipline structure is equipped with an exception handler +that causes self-destruction when the associated stream is closed. +.PP +.Ss " Sfdisc_t* dcnewskable(Sfio_t* f);" +.Ss " int dcdelskable(Sfdisc_t* disc);" +\f5dcnewskable()\fP creates a discipline that when inserted +on the stream \f5f\fP will ensure that \f5f\fP is seekable. +If \f5f\fP is originally unseekable, data will be shadowed +in a temporary file stream to allow seekability. +\f5dcnewskable()\fP returns the discipline on success and \f5NULL\fP on failure. + +.Ss " Sfdisc_t* dcnewtee(Sfio_t* tee);" +.Ss " int dcdeltee(Sfdisc_t* disc);" +\f5dcnewtee()\fP creates a discipline that +when inserted into a stream \f5f\fP will duplicate to the stream \f5tee\fP +any data written to \f5f\fP. +\f5dcnewtee()\fP returns the discipline on success and \f5NULL\fP on failure. + +.Ss " Sfdisc_t* dcnewfilter(char* cmd);" +.Ss " int dcdelfilter(Sfdisc_t* disc);" +\f5dcnewfilter()\fP creates a discipline that +when inserted into a stream \f5f\fP will run the command \f5cmd\fP +to process any input data before making it available to the application. +For example, \f5dcnewfilter("uncompress")\fP is an equivalent but slower +alternative to the lzw discipline below. +\f5dcnewfilter()\fP returns the discipline on success and \f5NULL\fP on failure. + +.Ss " Sfdisc_t* dcnewsubstream(Sfio_t* base, long offset, long extent);" +.Ss " int dcdelsubstream(Sfdisc_t* disc);" +\f5dcnewsubstream()\fP creates a discipline that +reserves a portion of the stream \f5base\fP starting at \f5offset\fP +with length \f5extent\fP and makes this portion appear as if it is +a stream. When this discipline is inserted into a stream, it will make +cause all IO operations on this stream to take place in the reserved +portion of the \f5base\fP stream. +\f5dcnewsubstream()\fP returns the discipline on success and \f5NULL\fP on failure. + +.Ss " Sfdisc_t* dcnewlzw(void); +.Ss " int dcdellzw(Sfdisc_t* disc);" +\f5dcnewlzw()\fP creates a discipline that when inserted into +a stream \f5f\fP will run the \fBuncompress\fP algorithm +on input data from \f5f\fP before making it available to the +application. This is useful to allow applications to process +data from a file packed with the UNIX \fBcompress\fP utility +as if the data is in plain text. +\f5dcnewlzw()\fP returns the discipline on success and \f5NULL\fP on failure. + +.Ss " Sfdisc_t* dcnewunion(Sfio_t** list, int n); +.Ss " int dcdelunion(Sfdisc_t* disc);" +\f5dcnewunion()\fP creates a discipline that concatenates +input data from all \f5n\fP streams in \f5list\fP. +When inserted into a stream \f5f\fP, this discipline will cause +all input operations on \f5f\fP to come from the merged data stream. +\f5dcnewunion()\fP returns the discipline on success and \f5NULL\fP on failure. + +.SH ACKNOWLEDGMENTS +Dave Korn contributed the substream discipline. +Jim Arnold contributed the lzw discipline. + +.SH NOTES +Since we are not sure of the legal responsibilities concerning the lzw patent, +the lzw discipline is not currently distributed with any release of sfio +outside of AT&T. + +.SH AUTHOR +Kiem-Phong Vo, kpv@research.att.com. diff --git a/src/lib/libast/man/sfio.3 b/src/lib/libast/man/sfio.3 new file mode 100644 index 0000000..f22d0b7 --- /dev/null +++ b/src/lib/libast/man/sfio.3 @@ -0,0 +1,2373 @@ +.fp 5 CW +.TH SFIO 3 "01 June 2008" +.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 <sfio.h> + +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 +SF_IOINTR +.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, ...); +char* sfvprints(const char* format, va_list args); +ssize_t sfaprints(char** sp, const char* format, ...); +ssize_t sfvaprints(char** sp, const char* format, va_list args); +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_JFLAG +SFFMT_CENTER +SFFMT_CHOP +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, Void_t* data)); + +int sfwalk(Sfwalk_f walkf, Void_t* data, int type); +.ft 1 +.fi +.Ss "MISCELLANEOUS FUNCTIONS" +.nf +.ft 5 +ssize_t sfmaxr(ssize_t maxr, int s); +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 action); +.ft 1 +.fi +.Ss "FULL STRUCTURE SFIO_T" +.nf +.ft 5 +#include <sfio_t.h> +#define SFNEW(buf,size,file,flags,disc) +.ft 1 +.fi +.Ss "EXAMPLE DISCIPLINES" +.nf +.ft 5 +#include <sfdisc.h> + +int sfdcdio(Sfio_t* f, size_t bufsize); +int sfdcdos(Sfio_t* f); +int sfdcfilter(Sfio_t* f, const char* cmd); +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); +int sfdclzw(Sfio_t* f); +int sfdcgzip(Sfio_t* f, int flags); +.ft 1 +.fi +.Ss "STDIO-COMPATIBILITY" +.nf +.ft 5 +#include <stdio.h> +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 much 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. +.Tp +\f5SF_IOINTR\fP: +This flag indicates that I/O system calls should not be resumed +after being interrupted by signals. It is useful for +aborting I/O operations on such interruptions. Note, however, +than certain operating systems (e.g., BSD Unix systems) may automatically +resume interrupted system calls outside the scope of the library. On such systems, +\f5SF_IOINTR\fP will be ineffective. + +.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, +\f5f\fP is a file stream and +\f5mode\fP does not imply a string stream, +\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. +Note also that \f5SF_READ\fP and \f5SF_WRITE\fP can only be reset if the stream +is not yet initialized. + +\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 serialize 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 to +protect it from concurrent accesses via multiple threads. +\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. This call will block until it is +possible to lock the stream. +.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. +See also \f5sfmaxr()\fP for limiting the amount of data read to construct a record. + +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 can be either a byte if the record separator argument +\f5rsc\fP is negative or a record of \f5rsc\fP is non-negative. +In the latter case, a record is incomplete if it does not end in \f5rsc\fP. +Generally speaking, a stream can have at most one incomplete record. +If \f5n\fP is negative, all complete objects 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 +counts the number of complete 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. +It returns the reserved data block on success and \f5NULL\fP on failure. + +If \f5f\fP is a \f5SF_READ\fP stream, the data block is a segment of input data. +If \f5f\fP 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 normally be treated as if it is a \f5SF_READ\fP stream +(see \f5sfset()\fP for forcing a particular mode) but the returned +buffer can also be written into (more below). +However, it is possible to bias to \f5SF_WRITE\fP when the \f5type\fP +argument is non-negative by adding the \f5SF_WRITE\fP bit \f5type\fP. +In any case, a reserved data block is guaranteed to be valid only until +a future access to the stream \f5f\fP. + +When \f5f\fP is \f5SF_READ\fP, \f5SF_SHARE\fP and unseekable, +\f5sfreserve()\fP will attempt to peek at input data without +consuming it. This enables separate processes to share in reading +input from unseekable file descriptors (e.g., pipes or devices). +However, this use of \f5sfreserve()\fP may fail +on certain platforms that do not properly support +peeking on unseekable file descriptors. + +After a \f5sfreserve()\fP call, whether or not it succeeds, +\f5sfvalue(f)\fP gives the size of the available data block. +Any partially reserved data block after a failed \f5sfreserve()\fP +call can be obtained in another \f5sfreserve()\fP call with the argument +\f5type\fP being \f5SF_LASTR\fP. The second argument \f5n\fP +to \f5sfreserve()\fP will be ignored in this case. + +A \f5sfreserve()\fP call is successful if it can obtain a data block +of size at least the absolute value of \f5n\fP. +For a \f5SF_READ\fP atream, the argument \f5n\fP is treated as follows: +.Tp +\f5n < 0\fP: +\f5sfreserve()\fP attempts to get \fIat least\fP \f5|n|\fP bytes +into the buffer. +.Tp +\f5n == 0\fP: +If the argument \f5type\fP is \f50\fP, +\f5sfreserve()\fP attempts to get \fIat least\fP \f51\fP byte into the buffer +but does not consume it (as consistent with \f5n == 0\fP). +If \f5type != 0\fP, no attempt will be made to read data into the buffer. +For example, the call \f5sfreserve(f, 0, -1)\fP only returns the buffer status, +i.e., size of existing buffered data and pointer to such data, if any. +The call \f5sfreserve(f, 0, SF_LOCKR)\fP is similar but also locks the stream. +.Tp +\f5n > 0\fP: +\f5sfreserve()\fP will use attempt to get \fIat most\fP \f5n\fP bytes into +the buffer. Further, if \f5type == \f5SF_LOCKR\fP (see below), read attempts +end on a positive amount. + +For a successful reservation, the argument \f5type\fP dictates treatment +as follows: +.Tp +\f5type == SF_LASTR\fP: +After a \f5sfreserve()\fP call with \f5type != SF_LOCKR\fP fails, +there may be some left over data not accessible via conventional Sfio calls. +Immediately after such a failed call, +another call to \f5sfreserve\fP with \f5type == SF_LASTR\fP will return any left over +data and also advance the stream I/O position by the amount of returned data. +.Tp +\f5type < 0\fP: +If \f5n > 0\fP, the stream I/O position is advanced by \f5n\fP. +If \f5n < 0\fP, the stream I/O position is advanced by the amount +of available data. +For example, a successful \f5sfreserve(f, -1, -1)\fP call will return a +buffer of data and simultanously advance the stream I/O position by the amount +indicated by \f5sfvalue(f)\fP. +.Tp +\f5type == SF_LOCKR\fP: +The stream I/O position remains unchanged. +In addition, \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,1)\fP will reopen the stream and simultaneously +advance the stream I/O position by \f51\fP. +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 reads 10 bytes of data from a stream +opened with both \f5SF_READ\fP and \f5SF_WRITE\fP, modifies the data in place, +then rewrites the new data back to the stream: + +.nf +.ft 5 + rsrv = sfreserve(f, 10, 1); + for(i = 0; i < 10; ++i) + rsrv[i] = toupper(rsrv[i]); + sfwrite(f, rsrv, 10); +.ft 1 +.fi + +.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_JFLAG\fP: flag \f5j\fP in \f5sfprintf()\fP and \f5sfscanf()\fP. + +\f5SFFMT_CENTER\fP: flag \f5=\fP in \f5sfprintf()\fP and \f5sfscanf()\fP. + +\f5SFFMT_CHOP\fP: flag \f5-\fP in \fIprecis\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 " char* sfvprints(const char* format, va_list args);" +.Ss " ssize_t sfaprints(char** sp, const char* format, ...);" +.Ss " ssize_t sfvaprints(char** sp, const char* format, va_list args);" +.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 and \f5sfvprints()\fP construct data in some Sfio-defined buffer. +\f5sfaprints()\fP and \f5sfvaprints()\fP are similar to \f5sfprints()\fP +and \f5sfvprints()\fP +but they return a string constructed via \f5malloc()\fP in \f5*sp\fP +and expect this string to be freed by the caller when no longer needed. +\f5sfvprintf()\fP is the underlying primitive for the other functions. +Except for \f5sfprints()\fP and \f5sfvprints()\fP +which return 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, \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, \f5j\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 centers data within the field. + +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. +Finally, for \f5%c\fP, bytes will be printed in the C format. +For example, when the ASCII character set is used, +the byte value 10 will be printed as \f5\\n\fP while 255 is printed +as \f5\\377\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; +-\f5precis\fP also defines the maximum number of characters to output, but +retains the rightmost \f5precis\fP characters. +.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 changes the buffering scheme for the stream \f5f\fP. +The stream 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. + +Sfio attempts to read data in blocks likely to be serviced fast by the file system. +This means block sizes being multiples of a suitable alignment value +(e.g., 512, 1024 or 8192). By default, the alignment value +is computed via some internal mechanism depending on the local platform but +it can also be explicitly set via the call \f5sfsetbuf(f, (Void_t*)f, size)\fP. + +In invocations of \f5sfsetbuf()\fP other than the above case, +the \f5size\fP argument is treated as follows: +.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. +\f5sfdisc()\fP returns \f5NULL\fP on failure. + +If the value of \f5disc\fP is identical to the value of \f5f\fP, +then the top discipline on the discipline +stack is returned without any further action. +An application can then use this feature of \f5sfdisc()\fP +and the field \f5disc\fP (below) of the discipline structure +to traverse the entire discipline stack of a stream \f5f\fP as follows: + +.nf +.ft 5 + for(disc = sfdisc(f, (Sfdisc_t*)f); disc; disc = disc->disc) +.ft 1 +.fi + +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. + +Note that a discipline can be used on only 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; + Sfdisc_t* disc; +.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 data still in the buffer. +If the return value of \f5exceptf\fP is non-negative, +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)" +If \f5f\fP is non-\f5NULL\fP, \f5sfraise()\fP calls all exception handlers +of \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. + +If \f5f\fP is \f5NULL\fP, \f5sfraise()\fP iterates over all streams +and raise events as described above. In this case, +\f5sfraise()\fP returns \f50\fP on success and a negative value +on failure. The absolute value of the return value tells how many +streams failed on raising the given event. + +.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, void*) )" +This sets a function \f5(*notify)()\fP to be called +as \f5(*notify)(f, type, data)\fP on various stream events. +Arguments \f5type\fP and \f5data\fP indicate the reason for the call and accompanying data: +.Tp +\f5SF_NEW\fP: +\f5f\fP is being opened and \f5data\fP is the underlying file descriptor. +.Tp +\f5SF_CLOSING\fP (\f5SF_CLOSE\fP): +\f5f\fP is the stream being closed and \f5data\fP is the underlying file descriptor. +.Tp +\f5SF_SETFD\fP: +The file descriptor of \f5f\fP is being changed to the one +defined by \f5data\fP (see \f5sfsetfd()\fP.) +.Tp +\f5SF_READ\fP: +An attempt to change \f5f\fP to read mode failed. +\f5data\fP is the file descriptor of the stream. +.Tp +\f5SF_WRITE\fP: +An attempt to change \f5f\fP to write mode failed. +\f5data\fP is the file descriptor of the stream. +.Tp +\f5SF_MTACCESS\fP: +When a notifying function was registered (see \f5sfnotify()\fP), +every Sfio call on a stream with flag \f5SF_MTSAFE\fP will +invoke the notifying function +once on entry after the stream is locked +as \f5(*notify)(f, SF_MTACCESS, Sfio_t** fp), and +once on return before unlocking as +as \f5(*notify)(f, SF_MTACCESS, (Sfio_t**)0). +In the call entry case, +the notification function could use the argument \f5fp\fP +to set a stream that would be used for performing the actual I/O operation. +In this way, certain global streams such as the standard streams \f5sfstdin\fP, +\f5sfstdout\fP and \f5sfstderr\fP could be made to act differently when used +in different streams. + +.Ss " int sfwalk(Sfwalk_f walkf, Void_t* data, int type)" +This function invokes \f5(*walkf)(f, data)\fP on every open stream \f5f\fP +whose flags as defined by \f5sfset()\fP contains all bit flags given in \f5type\fP. +On such a call, if the return value is negative, \f5sfwalk()\fP will terminate. +\f5sfwalk()\fP returns 0 if no stream was processed. +Otherwise, it returns the return value from the last invocation of \f5walkf()\fP. + +As an example, the call \f5sfwalk(walkf, data, SF_READ)\fP will iterate over all streams +opened for reading. Similarly, \f5sfwalk(walkf, data, SF_READ|SF_WRITE)\fP +iterates over all streams opened for both reading and writing. +Lastly, \f5sfwalk(walkf, data, 0)\fP iterates over all streams. + +.PP +.Ss "MISCELLANEOUS FUNCTIONS" +.PP +.Ss " ssize_t sfmaxr(ssize_t maxr, int set)" +Certain records may require too much memory for storage, thus, causing +undesirable side effects. Therefore, the library normally bounds the amount +of memory used by \f5sfgetr()\fP. A different memory bound +can be set via \f5sfmaxr()\fP. While a positive \f5maxr\fP hints to \f5sfgetr()\fP +to use only about that much memory to construct a record, a non-positive bound +allows \f5sfgetr()\fP to use as much memory as necessary. +\f5sfmaxr()\fP sets the value only if \f5set\fP is non-zero. +It returns the value before setting or the current value if not setting. + +.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. +If the last returned byte is not the record separator, then +the read data did not contain a complete record. Otherwise, +it contains one or more records. +See also \f5action\fP below. +.Tp +\f5tm\fP: +If \f5>=0\fP, this defines a time interval in milliseconds to wait for incoming data. +.Tp +\f5action\fP: +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 and there are two cases. +If \f5rsc < 0\fP, an attempt is made to read \f5n\fP bytes. +If \f5rsc >= 0\fP, an attempt is made to read one record. + +.PP +.Ss "FULL STRUCTURE SFIO_T" +.PP +.Ss " #include <sfio_t.h>" +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 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. + +.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 sfdcgzip(Sfio_t* f, int opt)" +This creates a discipline for reading/writing data compressed by zlib. +The argument \f5opt\fP defines the optimization level. + +.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. +.PP +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 can be built for thread-safety. This is based largely on +Posix pthread mutexes except for on UWIN where native Windows APIs +are used. +.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. +.PP +The formatting pattern \f5%c\fP for \f5sf*printf\fP was extended +to allow the flag \f5#\fP to print unprintable character values +using the C convention. For example, \f5%#c\fP prints the octal value 012 +as \f5\\n\fP. + +.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. diff --git a/src/lib/libast/man/sig.3 b/src/lib/libast/man/sig.3 new file mode 100644 index 0000000..db41a2b --- /dev/null +++ b/src/lib/libast/man/sig.3 @@ -0,0 +1,75 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH SIG 3 +.SH NAME +sig \- signal interface routines +.SH SYNOPSIS +.L "#include <ast.h>" +.L "#include <sig.h>" +.sp +.L "int sigunblock(int sig);" +.L "int sigcritical(int op);" +.SH DESCRIPTION +.L sigunblock +is called to +unblocks the signal +.L sig +from within a handler currently servicing +.LR sig . +.PP +.L sigcritical +controls a critical region for the +.LR SIGINT , +.L SIGQUIT +and +.L SIGHUP +signals. +.L "op > 0" +pushes the region, +.L "op == 0" +pops the region, and +.L "op < 0" +returns non-zero if any signals are being held in the current +critical region. +Signal critical regions may be nested. +The current critical region level is returned, +.L \-1 +on error. +.SH "SEE ALSO" +signal(2) diff --git a/src/lib/libast/man/spawnveg.3 b/src/lib/libast/man/spawnveg.3 new file mode 100644 index 0000000..3dfd424 --- /dev/null +++ b/src/lib/libast/man/spawnveg.3 @@ -0,0 +1,97 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH SPAWNVEG 3 +.SH NAME +spawnveg \- process spawn with process group and session control +.SH SYNOPSIS +.L "#include <ast.h>" +.sp +.L "int spawnveg(const char* command, char** argv, char** envv, pid_t pgid);" +.SH DESCRIPTION +.L spwanveg +combines +.IR fork (2), +.IR exec (2), +.IR setpgid (2) +and +.IR setsid (2) +into a single call. +.PP +.LR command , +.L argv +and +.L envv +are as in +.IR execve (2). +.L pgid +controls the new process group and session: +.TP +.L <0 +The new process becomes a session leader. +is called in the child context. +.TP +.L 0 +The new process is in the callers process group. +.TP +.L 1 +The new process becomes a process group leader. +.TP +.L >1 +The new process joins the process group +.IR pgid . +.SH COMMENTS +It is possible to code all process creation (except for +.IR vfork (2) +hack like in +.IR csh (1)) +using +.LR spawnveg . +The +.IR proc (3) +routines and +.IR ksh (1) +do this on systems that don't support +.IR fork (2). +This makes porting to NT and Windows a snap: a simple +.IR iffe (1) +probe provides a +.L spawnveg +implementation using the NT or Windows process primitives. +.SH "SEE ALSO" +fork(2), exec(2), setpgid(2), setsid(2), spawnve(2) diff --git a/src/lib/libast/man/stak.3 b/src/lib/libast/man/stak.3 new file mode 100644 index 0000000..5feac69 --- /dev/null +++ b/src/lib/libast/man/stak.3 @@ -0,0 +1,169 @@ +.fp 5 CW +.TH STAK 3 +.SH NAME +\fBstak\fR \- data stack storage library (obsolete: use \fBstk\fR instead) +.SH SYNOPSIS +.ta .75i 1.5i 2.25i 3i 3.75i 4.5i 5.25i 6i +.PP +.nf +\f5 +#include <stak.h> + +Stak_t *stakcreate(int \fIflags\fP); +Stak_t *stakinstall(Stak_t *\fIstack\fP, char *(\fIoverflow\fP)(int)); +int stakdelete(Stak_t *\fIstack\fP); +void staklink(Stak_t *\fIstack\fP) + +char *stakalloc(unsigned \fIsize\fP); +char *stakcopy(const char *\fIstring\fP); +char *stakset(char *\fIaddress\fP, unsigned \fIoffset\fP); + +char *stakseek(unsigned \fIoffset\fP); +int stakputc(int \fIc\fP); +int stakputs(const char *\fIstring\fP); +int stakwrite(const char *\fIaddress\fP, unsigned \fIsize\fP); +int staktell(void); +char *stakptr(unsigned \fIoffset\fP); +char *stakfreeze(unsigned \fIextra\fP); +\fR +.fi +.SH DESCRIPTION +.PP +\f5stak\fP is a package of routines designed to provide efficient +stack oriented dynamic storage. +A stack abstraction consists of an ordered list of contiguous +memory regions, called stack frames, that can hold objects of +arbitrary size. +A stack is represented by the type \f5Stak_t\fP +defined in header \f5<stak.h>\fP. +At any instant there is one active stack. +Variable size objects can be +added to the active stack +and programs can reference these objects directly with pointers. +In addition, the last object on the stack +(referred to here as the current object) +can be built incrementally. +The current object has an associated offset that determines its +current size. +While the current object is being built incrementally, +its location might +change so that it is necessary to reference the object with +relative offsets ranging from zero to the current offset of the object. +.PP +There is a preset initial active stack. +To use an additional stack, it is necessary to create it and to +install it as the active stack. +A stack is created with the \f5stakcreate\fP() function. +A \fIflags\fP argument of \f5STAK_SMALL\fP indicates that unused +space on the stack should be freed whenever this stack ceases +to be the active stack. +If successful, +\f5stakcreate\fP() returns a pointer to a stack whose reference +count is 1. +Otherwise, \f5stakcreate\fP() returns a null pointer. +The \f5staklink\fP() function increases the reference count for the +given \fIstack\fP. +The \f5stakinstall\fP() function +makes the specified \fIstack\fP the active stack and returns a pointer +to the previous active stack. +When the \fIoverflow\fP argument is not null, +it specifies a function that will +be called whenever \f5malloc\fP(3) fails while trying to grow the +stack. +The \fIoverflow\fP function will be called with the size that was passed +to \f5malloc\fP(3). +The \fIoverflow\fP function can call \f5exit\fP(3), call \f5longjmp\fP(3) +or return. +If the \f5overflow\fP function returns, +it must return a pointer to a memory region of the given size. +The default action is to write an error to standard error and to +call \f5exit\fP(2) with a non-zero exit value. +When \fIstack\fP is a null pointer, +the active stack is not changed +but the \fIoverflow\fP function for the active stack can be changed +and a pointer to the active stack is returned. +The \f5stakdelete\fP() function decrements the reference count and +frees the memory associated with +the specified stack +when the reference count is zero. +The effect of subsequent references to objects +on the stack are undefined. +.PP +The +\f5stakalloc\fP() function returns an aligned pointer to space on the +active stack that can be used to hold any object of the given \fIsize\fP. +\f5stakalloc\fP() is similar to \f5malloc\fP(3) except that individual +items returned by \f5stakalloc\fP() can not be freed. +\f5stakalloc\fP() causes the offset of the current object to be set to +zero. +.PP +The +\f5stakcopy\fP() function copies the given string onto the stack +and returns a pointer to the \fIstring\fP on the stack. +\f5stakcopy\fP() causes the offset of the current object to be set to +zero. +.PP +The \f5stakset\fP() function finds the frame containing the given +\fIaddress\fP, frees all frames that were created after the one containing +the given \fIaddress\fP, and sets the current object to the given +\fIaddress\fP. +The top of the current object is set to \fIoffset\fP bytes from +current object. +If \fIaddress\fP is not the address of an object on the +stack the result is undefined. +.PP +The remaining functions are used to build the current object incrementally. +An object that is built incrementally on the stack will +always occupy contiguous memory within a stack frame but +until \f5stakfreeze\fP() is called, +the location in memory for the object can change. +There is a current offset associated with the current object that +determines where subsequent operations apply. +Initially, this offset is zero, and the offset changes as a result +of the operations you specify. +The \f5stakseek\fP() function is used set the offset for the +current object. +The \fIoffset\fP argument to \f5stakseek\fP() specifies the new +offset for the current object. +The frame will be extended or moved +if \f5offset\fP causes the new current offset to extend beyond the +current frame. +\f5stakseek\fP() returns a pointer to the beginning of the current object. +The \f5staktell\fP() function gives the offset of the current object. +.PP +The \f5stakputc\fP() function adds a given character to the current object +on the stack. +The current offset is advanced by 1. +The \f5stakputs\fP() function appends the given \fIstring\fP onto the current +object in the stack and returns the length of the string. +The current offset is advanced by the length of the string. +The \f5stakwrite\fP() function appends the given \fIsize\fP byte memory +region starting at \fIaddress\fP onto the current +object in the stack and advances the current offset by \fIsize\fP. +The current offset is returned. +.PP +The \f5stakptr\fP() function converts the given \f5offset\fP +for the current object into a memory address on the stack. +This address is only valid until another stack operation is given. +The result is not defined if \fIoffset\fP exceeds the size of the current +object. +The \f5stakfreeze\fP() +function terminates the current object on the +stack and returns a pointer to the beginning of this object. +If \fIextra\fP is non-zero, \fIextra\fP bytes are added to the stack +before the current object is terminated. The first added byte will +contain zero and the contents of the remaining bytes are undefined. +.PP +.SH HISTORY +The +\f5stak\fP +interface was derived from similar routines in the KornShell code +that is used for building parse trees and carrying out expansions. +It provides an efficient mechanism for grouping dynamically allocated +objects so that they can be freed all at once rather than individually. +.SH AUTHOR + David Korn +.SH SEE ALSO +\f5exit(2)\fP +\f5longjmp(3)\fP +\f5malloc(3)\fP diff --git a/src/lib/libast/man/stk.3 b/src/lib/libast/man/stk.3 new file mode 100644 index 0000000..3e65821 --- /dev/null +++ b/src/lib/libast/man/stk.3 @@ -0,0 +1,165 @@ +.fp 5 CW +.TH STK 3 +.SH NAME +\fBstk\fR \- data stack storage library +.SH SYNOPSIS +.ta .75i 1.5i 2.25i 3i 3.75i 4.5i 5.25i 6i +.PP +.nf +\f5 +#include <stk.h> + +Stk_t *stkopen(int \fIflags\fP); +Stk_t *stkinstall(Stk_t *\fIstack\fP, char *(\fIoverflow\fP)(int)); +int stkclose(Stk_t *\fIstack\fP); +void stklink(Stk_t *\fIstack\fP) + +char *stkalloc(Stk_t *\fIstack\fP, unsigned \fIsize\fP); +char *stkcopy(Stk_t *\fIstack\fP, const char *\fIstring\fP); +char *stkset(Stk_t *\fIstack\fP, char *\fIaddress\fP, unsigned \fIoffset\fP); + +char *stkseek(Stk_t *\fIstack\fP, unsigned \fIoffset\fP); +int stktell(Stk_t *\fIstack\fP); +char *stkptr(Stk_t *\fIstack\fP, unsigned \fIoffset\fP); +char *stkfreeze(Stk_t *\fIstack\fP, unsigned \fIextra\fP); +int stkon(Stk *\fIstack\fP, char* \fIaddr\fP) +\fR +.fi +.SH DESCRIPTION +.PP +\f5stk\fP is a package of routines designed to provide efficient +stack oriented dynamic storage. +A stack abstraction consists of an ordered list of contiguous +memory regions, called stack frames, that can hold objects of +arbitrary size. +A stack is represented by the type \f5Stk_t\fP +defined in header \f5<stk.h>\fP. +The type \f5Stk_t\fP is compatible with the type \f5Sfio_t\fP +defined by the \f5sfio\fP(3) library. +At any instant there is one active stack which can be referenced +by the constant \f5stkstd\fP. +Variable size objects can be +added to the active stack +and programs can reference these objects directly with pointers. +In addition, the last object on the stack +(referred to here as the current object) +can be built incrementally. +The current object has an associated offset that determines its +current size. +While the current object is being built incrementally, +its location might +change so that it is necessary to reference the object with +relative offsets ranging from zero to the current offset of the object. +.PP +There is a preset initial active stack. +To use an additional stack, it is necessary to create it and to +install it as the active stack. +A stack is created with the \f5stkopen\fP() function. +A \fIflags\fP argument of \f5STK_SMALL\fP indicates that unused +space on the stack should be freed whenever this stack ceases +to be the active stack. +If successful, +\f5stkopen\fP() returns a pointer to a stack whose reference +count is 1. +Otherwise, \f5stkopen\fP() returns a null pointer. +The \f5stklink\fP() function increases the reference count for the +given \fIstack\fP. +The \f5stkinstall\fP() function +makes the specified \fIstack\fP the active stack and returns a pointer +to the previous active stack. +When the \fIoverflow\fP argument is not null, +it specifies a function that will +be called whenever \f5malloc\fP(3) fails while trying to grow the +stack. +The \fIoverflow\fP function will be called with the size that was passed +to \f5malloc\fP(3). +The \fIoverflow\fP function can call \f5exit\fP(3), call \f5longjmp\fP(3) +or return. +If the \f5overflow\fP function returns, +it must return a pointer to a memory region of the given size. +The default action is to write an error to standard error and to +call \f5exit\fP(2) with a non-zero exit value. +When \fIstack\fP is a null pointer, +the active stack is not changed +but the \fIoverflow\fP function for the active stack can be changed +and a pointer to the active stack is returned. +The \f5stkclose\fP() function decrements the reference count and +frees the memory associated with +the specified stack +when the reference count is zero. +The effect of subsequent references to objects +on the stack are undefined. +.PP +The +\f5stkalloc\fP() function returns an aligned pointer to space on the +active stack that can be used to hold any object of the given \fIsize\fP. +\f5stkalloc\fP() is similar to \f5malloc\fP(3) except that individual +items returned by \f5stkalloc\fP() can not be freed. +\f5stkalloc\fP() causes the offset of the current object to be set to +zero. +.PP +The +\f5stkcopy\fP() function copies the given string onto the stack +and returns a pointer to the \fIstring\fP on the stack. +\f5stkcopy\fP() causes the offset of the current object to be set to +zero. +.PP +The \f5stkset\fP() function finds the frame containing the given +\fIaddress\fP, frees all frames that were created after the one containing +the given \fIaddress\fP, and sets the current object to the given +\fIaddress\fP. +The top of the current object is set to \fIoffset\fP bytes from +current object. +If \fIaddress\fP is not the address of an object on the +stack the result is undefined. +.PP +The \f5sfio\fP(3) output functions can be used to build +current object incrementally. +An object that is built incrementally on the stack will +always occupy contiguous memory within a stack frame but +until \f5stkfreeze\fP() is called, +the location in memory for the object can change. +There is a current offset associated with the current object that +determines where subsequent operations apply. +Initially, this offset is zero, and the offset changes as a result +of the operations you specify. +The \f5stkseek\fP() function is used set the offset for the +current object. +The \fIoffset\fP argument to \f5stkseek\fP() specifies the new +offset for the current object. +The frame will be extended or moved +if \f5offset\fP causes the new current offset to extend beyond the +current frame. +\f5stkseek\fP() returns a pointer to the beginning of the current object. +The \f5stktell\fP() function gives the offset of the current object. +.PP +The \f5stkptr\fP() function converts the given \f5offset\fP +for the current object into a memory address on the stack. +This address is only valid until another stack operation is given. +The result is not defined if \fIoffset\fP exceeds the size of the current +object. +The \f5stkfreeze\fP() +function terminates the current object on the +stack and returns a pointer to the beginning of this object. +If \fIextra\fP is non-zero, \fIextra\fP bytes are added to the stack +before the current object is terminated. The first added byte will +contain zero and the contents of the remaining bytes are undefined. +.PP +The \f5stkon\fP() +function returns non-zero if the address given by \fIaddr\fP is +on the stack \fIstack\fP and \f50\fP otherwise. +.PP +.SH HISTORY +The +\f5stk\fP +interface was derived from similar routines in the KornShell code +that is used for building parse trees and carrying out expansions. +It provides an efficient mechanism for grouping dynamically allocated +objects so that they can be freed all at once rather than individually. +.SH AUTHOR + David Korn +.SH SEE ALSO +\f5exit(2)\fP +\f5longjmp(3)\fP +\f5malloc(3)\fP +\f5sfio(3)\fP diff --git a/src/lib/libast/man/strcopy.3 b/src/lib/libast/man/strcopy.3 new file mode 100644 index 0000000..c08d885 --- /dev/null +++ b/src/lib/libast/man/strcopy.3 @@ -0,0 +1,54 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRCOPY 3 +.SH NAME +strcopy \- copy strings +.SH SYNOPSIS +.L "char* strcopy(char* a, char* b)" +.SH DESCRIPTION +.I strcopy +copies the nul-terminated string +.I b +into +.IR a . +A pointer to the 0 character in +.I a +is returned. +.SH "SEE ALSO" +strcpy(3) diff --git a/src/lib/libast/man/strdup.3 b/src/lib/libast/man/strdup.3 new file mode 100644 index 0000000..3b26ec4 --- /dev/null +++ b/src/lib/libast/man/strdup.3 @@ -0,0 +1,55 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRDUP 3 +.SH NAME +strdup \- duplicate nul-terminated string +.SH SYNOPSIS +.L "char* strdup(char* s)" +.SH DESCRIPTION +.I strdup +copies the nul-terminated string +.I s +to a new location provided by +.IR malloc (3) +and returns a pointer to the new copy. +0 is returned if +.IR malloc (3) +failed. +.SH "SEE ALSO" +malloc(3), memdup(3) diff --git a/src/lib/libast/man/strelapsed.3 b/src/lib/libast/man/strelapsed.3 new file mode 100644 index 0000000..8c3fa4a --- /dev/null +++ b/src/lib/libast/man/strelapsed.3 @@ -0,0 +1,77 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRELAPSED 3 +.SH NAME +strelapsed \- parse elapsed time expression +.SH SYNOPSIS +.L "unsigned long strelapsed(char* buf, char** next, int persec)" +.SH DESCRIPTION +.I strelapsed +returns a pointer to a string representation of the elapsed time for +.L (count/persec) +seconds. +The two largest time units are used, limiting the return value length +to at most 6 characters. +The units are: +.TP +.B s +seconds +.TP +.B m +minutes +.TP +.B h +hours +.TP +.B days +.TP +.B weeks +.TP +.B M +months +.TP +.B Y +years +.TP +.B S +scores +.SH "SEE ALSO" +strelapsed(3) +.SH CAVEATS +The return value points to a static area that is overwritten on each call. diff --git a/src/lib/libast/man/strerror.3 b/src/lib/libast/man/strerror.3 new file mode 100644 index 0000000..0084e3a --- /dev/null +++ b/src/lib/libast/man/strerror.3 @@ -0,0 +1,53 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRERROR 3 +.SH NAME +strerror \- return error message string given error number +.SH SYNOPSIS +.L "char* strerror(int err)" +.SH DESCRIPTION +.I strerror +returns the error message string corresponding to the error message number +.IR err . +.BI "Error " nnn +is returned if +.I err +is invalid. +.SH "SEE ALSO" +error(3) diff --git a/src/lib/libast/man/stresc.3 b/src/lib/libast/man/stresc.3 new file mode 100644 index 0000000..c09a0e9 --- /dev/null +++ b/src/lib/libast/man/stresc.3 @@ -0,0 +1,53 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRESC 3 +.SH NAME +stresc \- convert character constants in string +.SH SYNOPSIS +.L "int stresc(char* s)" +.SH DESCRIPTION +.I stresc +converts +.L \e +character constant expressions in the nul-terminated string +.I s +in place and returns the length of the converted +.IR s . +.SH "SEE ALSO" +chresc(3), ctoi(3) diff --git a/src/lib/libast/man/streval.3 b/src/lib/libast/man/streval.3 new file mode 100644 index 0000000..2b491c8 --- /dev/null +++ b/src/lib/libast/man/streval.3 @@ -0,0 +1,83 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STREVAL 3 +.SH NAME +streval \- long integer arithmetic expression evaluator +.SH SYNOPSIS +.L "long streval(char* s, char** e, long (*conv)(char* cs, char** ce))" +.SH DESCRIPTION +.I streval +evaluates the long integer arithmetic expression in the nul-terminated string +.I s +and returns the result. +If +.I e +is not 0 then +.I *e +is set to point to the first unknown character in the expression. +.PP +If +.I conv +is not 0 then it is called when an unknown token is encountered in +.IR s . +.I cs +points to the beginning of the unknown token. +The return value is the long integer value of the unknown token and +.I ce +must be set to point to the first character after the unknown token. +If an expression syntax error is encountered the +.I conv +is called with +.I cs +set to 0 and +.I *ce +pointing to the error message text. +.PP +In addition to the normal C expressions and integer constant styles, +numbers in any base +.I b +<= 2 <=36 +may be represented as +.IR b # nnnn , +where the extra digits in +.I nnnn +are taken from +.BR [A-Z] . +.SH "SEE ALSO" +strtol(3) diff --git a/src/lib/libast/man/strgid.3 b/src/lib/libast/man/strgid.3 new file mode 100644 index 0000000..d7a2663 --- /dev/null +++ b/src/lib/libast/man/strgid.3 @@ -0,0 +1,53 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRGID 3 +.SH NAME +strgid \- return group name given group number +.SH SYNOPSIS +.L "char* strgid(int gid)" +.SH DESCRIPTION +.I strgid +returns the group id name string given the group number +.IR gid . +.I strgid +maintains an internal cache to avoid repeated password database scans +by the low level +.IR getgrgid (3). +.SH "SEE ALSO" +getgrent(3) diff --git a/src/lib/libast/man/strmatch.3 b/src/lib/libast/man/strmatch.3 new file mode 100644 index 0000000..5f5af89 --- /dev/null +++ b/src/lib/libast/man/strmatch.3 @@ -0,0 +1,101 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRMATCH 3 +.SH NAME +strmatch \- match shell file patterns +.SH SYNOPSIS +.L "int strmatch(char* s, char* p)" +.br +.L "char* submatch(char* s, char* p, int m)" +.SH DESCRIPTION +.I strmatch +compares the string +.I s +with the shell pattern +.I p +and returns 1 for match and 0 otherwise. +.I submatch +does a leading substring match of the shell pattern +.I p +with the string +.IR s . +If +.I m +is 0 then the match is minimal, otherwise a maximal match is done. +A pointer to the first character after the matched substring is returned, +.I 0 +if there is no match. +.PP +Except for +.I & +and +.IR ! , +each shell pattern has an equivalent +.IR egrep (1) +construct. +.EX + \fBsh pattern egrep RE description\fP + * .* 0 or more chars + ? . any single char + [.] [.] char class + [!.] [^.] negated char class + *(.) (.)* 0 or more of + +(.) (.)+ 1 or more of + ?(.) (.)? 0 or 1 of + (.) (.) 1 of + @(.) (.) 1 of + a|b a|b a or b + a&b a and b + !(.) none of +.EE +.L \e +is used to escape *, ?, (, |, &, ), [, and \e +outside of [...]. +.SH "SEE ALSO" +grep(1) +.SH BUGS +An unbalanced +.L ) +terminates the top level pattern. +.br +Nested +.L & +and +.L ! +constructs are non-intuitive and are computationally intensive. diff --git a/src/lib/libast/man/stropt.3 b/src/lib/libast/man/stropt.3 new file mode 100644 index 0000000..f2a8dae --- /dev/null +++ b/src/lib/libast/man/stropt.3 @@ -0,0 +1,130 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STROPT 3 +.SH NAME +stropt \- table driven option expression evaluator +.SH SYNOPSIS +.L "#include <namval.h>" +.br +.L "int stropt(char* s, struct namval* tab, +.br +.L " int (*fun)(void* a, struct namval* p, int n, char* v)," +.br +.L " void* a)" +.SH DESCRIPTION +.I stropt +parses option expressions in the nul-terminated string +.I s +using the option names in +.IR tab . +.I tab +is an array of +.B "struct namval" +name value pairs: +.EX +char* name; +int value; +.EE +The last entry must be followed by a sentinel with +.B name +set to 0. +.PP +An option expression contains 0 or more of [\fBno\fP]\fIname\fP[=\fIvalue\fP] +separate by +.B space +or +.BR tab , +where +.I name +must be one of the option names in +.IR tab , +.I value +is an optional value, and +.B no +is for Boolean options. +Each option is passed to +.I fun +for processing. +.I a +is the +.L void* +pointer that is passed from the +.I stropt +call but is otherwise not interpreted. +.I p +points to the option name value pair from +.IR tab . +.I n +is 0 if +.B no +preceded the option +.I name +and +.I v +points to the beginning of the option +.I value +in +.IR s . +and +If +.I name +is not found in +.I tab +then +.I fun +is called with +.I p +pointing to an internal +.I namval +entry with +.I p\->name +pointing to the unknown option and +.I p\->value +set to the +.I value +of the sentinel entry in +.IR tab . +.PP +If +.I fun +returns non-zero then this value is returned and no further +options are processed. +Otherwise +.I stropt +returns 0 after processing all options. diff --git a/src/lib/libast/man/strperm.3 b/src/lib/libast/man/strperm.3 new file mode 100644 index 0000000..9b68946 --- /dev/null +++ b/src/lib/libast/man/strperm.3 @@ -0,0 +1,109 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRPERM 3 +.SH NAME +strperm \- evaluate file permission expression +.SH SYNOPSIS +.L "int strperm(char* s, char** e, int p)" +.SH DESCRIPTION +.I strperm +applies a file permission expression in the nul-terminated string +.I s +to the initial file permission mask +.IR p . +The new permission mask is returned. +If +.I e +not 0 then +.I *e +is set to point to the first unrecognized character in +.IR s . +.PP +A tape device specification is composed of one or more +.I who-op-permission +terms separated by +.BR , . +.I who +selects portions of the permission bits and may be any combination of: +.TP 3 +.B u +the user permission bits; +.TP +.B g +the group permission bits; +.TP +.B o +the `other' permission bits; +.TP +.B a +all permission bits. +.PP +If omitted, all permission bits are selected. +.I op +specifies how the original permission +.I p +is to be modified: +.TP 3 +.B + +.br +.ns +.B | +the new bits are set in +.IR p ; +.TP 3 +.B \- +the new bits are cleared in +.IR p ; +.TP +.B & +the new bits are and'd with +.IR p ; +.TP +.B = +the select bits in +.I p +are set equal to the new bits +.PP +A permission expression term may also be an octal number. +Octal specifications are inherently non-portable. +Refer to +.IR chmod (1) +for an explanation of this form. +.SH "SEE ALSO" +chmod(1), ls(1), strmode(3) diff --git a/src/lib/libast/man/strsignal.3 b/src/lib/libast/man/strsignal.3 new file mode 100644 index 0000000..4141980 --- /dev/null +++ b/src/lib/libast/man/strsignal.3 @@ -0,0 +1,53 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRSIGNAL 3 +.SH NAME +strsignal \- return signal description string given signal number +.SH SYNOPSIS +.L "char* strsignal(int sig)" +.SH DESCRIPTION +.I strsignal +returns the signal description string corresponding to the signal number +.IR sig . +.BI "Signal " nnn +is returned if +.I sig +is invalid. +.SH "SEE ALSO" +signal(2), sigvec(2) diff --git a/src/lib/libast/man/strsort.3 b/src/lib/libast/man/strsort.3 new file mode 100644 index 0000000..c48cfc2 --- /dev/null +++ b/src/lib/libast/man/strsort.3 @@ -0,0 +1,73 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH HSORT 3 +.SH NAME +hsort \- array heap sort +.SH SYNOPSIS +.EX +#include <ast.h> + +void strsort(char** \fIarray\fP, int \fIelements\fP, int (*\fIcompare\fP)(const char* \fIa\fP, const char* \fIb\fP)); +.EE +.SH DESCRIPTION +.L strsort +does a heap sort on the array of pointers +.I array +with +.I elements +elements using the comparison function +.IR compare . +.I compare +returns +.L \-1 +if +.I a +is lexicographically less than +.IR b , +.L 0 +if +.I a +is equal to +.IR b , +and +.L 1 +if +.I a +is lexicographically greater than +.IR b . diff --git a/src/lib/libast/man/strtape.3 b/src/lib/libast/man/strtape.3 new file mode 100644 index 0000000..06c33ba --- /dev/null +++ b/src/lib/libast/man/strtape.3 @@ -0,0 +1,86 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRTAPE 3 +.SH NAME +strtape \- convert string to tape device pathname +.SH SYNOPSIS +.L "char* strtape(char* s, char** e)" +.SH DESCRIPTION +.I strtape +converts the generic tape device specification in the nul-terminated string +.I s +to a local tape device pathname. +A pointer to the device pathname is returned. +If +.I e +not 0 then +.I *e +is set to point to the first unrecognized character in +.IR s . +.PP +A tape device specification is composed of +.IR unit-density-rewind . +All are optional. +.I unit +is a unit number in the range +.BR [0-7] . +The default unit is +.BR 1 . +Density may be one of: +.TP 3 +.B l +for low; +.TP 3 +.B m +for medium, and +.TP +.B h +for high. +.PP +The default is +.BR m . +.I rewind +is +.B n +for no-rewind on device close. +The default is to rewind on device close. +.SH "SEE ALSO" +pax(1), tar(1) +.SH CAVEATS +The return value points to a static area that is overwritten on each call. diff --git a/src/lib/libast/man/strton.3 b/src/lib/libast/man/strton.3 new file mode 100644 index 0000000..bfcf891 --- /dev/null +++ b/src/lib/libast/man/strton.3 @@ -0,0 +1,97 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRTON 3 +.SH NAME +strton \- convert string to long integer +.SH SYNOPSIS +.L "long strton(char* s, char** e)" +.SH DESCRIPTION +.I strton +converts the nul-terminated string +.I s +to a long integer. +If +.I e +not 0 then +.I *e +is set to point to the first unrecognized character in +.IR s . +Leading spaces in +.I s +are ignored. +.PP +A number is composed of +.IR sign-base-number-suffix . +All but +.I number +are optional. +.I sign +may be \+ or \-. +.I base +may be: +.TP +.B 0x +for hexadecimal; +.TP +.B 0 +for octal, or +.TP +.IR nn # +for base +2 \(le +.I nn +\(le 36. +.PP +For bases greater than 10 the additional digits are take from the set +.BR [a-zA-Z] . +The suffix multiplies the converted number and may be: +.TP +.B b +block (512) +.TP +.B g +giga (1024 * 1024 * 1024) +.TP +.B k +kilo (1024) +.TP +.B m +mega (1024 * 1024) +.SH "SEE ALSO" +atoi(3), scanf(3), strtod(3) diff --git a/src/lib/libast/man/struid.3 b/src/lib/libast/man/struid.3 new file mode 100644 index 0000000..522deb5 --- /dev/null +++ b/src/lib/libast/man/struid.3 @@ -0,0 +1,53 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH STRUID 3 +.SH NAME +struid \- return user name given user number +.SH SYNOPSIS +.L "char* struid(int uid)" +.SH DESCRIPTION +.I struid +returns the user id name string given the user number +.IR uid . +.I struid +maintains an internal cache to avoid repeated password database scans +by the low level +.IR getpwuid (3). +.SH "SEE ALSO" +getpwent(3) diff --git a/src/lib/libast/man/swap.3 b/src/lib/libast/man/swap.3 new file mode 100644 index 0000000..82176de --- /dev/null +++ b/src/lib/libast/man/swap.3 @@ -0,0 +1,138 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH SWAP 3 +.SH NAME +swap \- integral representation conversion routines +.SH SYNOPSIS +.L "#include <swap.h>" +.sp +.L "int swapop(const void* internal, const void* external, int width); +.L "int_max swapget(int op, const void* from, int width);" +.L "void* swapput(int op, void* to, int width, int_max value);" +.L "void* swapmem(int op, const void* from, void* to, size_t n);" +.SH DESCRIPTION +These routines convert integral constants between internal and +external representations. +They are used to handle binary data generated by foreign programs. +New binary data representations should use the compact canonical form +provided by the +.IR sfio (3) +routines +.L sfputu +and +.LR sgetu . +.PP +.L swapop +returns the swap operation required to convert the +.L width +byte integer +.L external +to the +.L width +byte integer +.LR internal . +The swap operation is a bit mask: +.TP +.L 0 +No swapping necessary. +.TP +.L 1 +Swap byte +.L 0 +with byte +.LR 1 . +.TP +.L 2 +Swap bytes +.L 0 +and +.L 1 +with bytes +.L 2 +and +.LR 3 . +.TP +.L 4 +Swap bytes +.L 0-3 +with bytes +.LR 4-7 , +and so on. +The largest native integral type is defined by the macro +.L int_max +in the header +.L <int.h> +described in +.IR int (3). +.PP +.L swapget +returns the +.L width +byte integer in the buffer +.LR from , +swapped according to +.LR op . +.PP +.L swapput +copies the +.L width +byte integer +.L value +into the buffer +.LR to , +swapped according to +.LR op . +.L to +is returned. +.PP +.L swapmem +swaps +.L n +bytes from the buffer +.L from +to the buffer +.L to +according to +.LR op . +.L to +and +.L from +may be the same. +.SH "SEE ALSO" +int(3) diff --git a/src/lib/libast/man/tab.3 b/src/lib/libast/man/tab.3 new file mode 100644 index 0000000..e1c76f3 --- /dev/null +++ b/src/lib/libast/man/tab.3 @@ -0,0 +1,74 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH TAB 3 +.SH NAME +tab \- simple table lookup routines +.SH SYNOPSIS +.L "#include <ast.h>" +.sp +.L "int tabindex(const void* tab, int size, const char* name);" +.L "void* tablook(const void* tab, int size, const char* name);" +.SH DESCRIPTION +These routines do linear lookups in +.I small +tables (on the order of 32 elements). +Each table element has a size of +.L size +bytes and the beginning of the element points to a name that is +matched by the lookup routines. +.PP +.L tabindex +returns the index of the table element in +.L tab +that matches +.LR name . +If there is no match then +.L \-1 +is returned. +.PP +.L tablook +returns a pointer to the table element in +.L tab +that matches +.LR name . +If there is no match then +.L 0 +is returned. +.SH "SEE ALSO" +hash(3) diff --git a/src/lib/libast/man/tm.3 b/src/lib/libast/man/tm.3 new file mode 100644 index 0000000..12eb4ec --- /dev/null +++ b/src/lib/libast/man/tm.3 @@ -0,0 +1,775 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH TM 3 +.SH NAME +tm \- seconds resolution time conversion support +.SH SYNOPSIS +.L "#include <tm.h>" +.SH DESCRIPTION +The +.I tm +library supports conversion between +string date specifications, +seconds reolution +.L time_t +clock values and +.LR Tm_t . +.L Tm_t +contains the elements of +.L "struct tm" +along with these additions: +.TP +.L "unsigned _ast_int4_t tm_nsec" +The subsecond portion of the time in nanoseconds. +.TP +.L "Tm_zone_t* tm_zone" +The time zone name. +.PP +.L localtime() +and +.L gmtime() +(see +.BR ctime (3)) +are used to determine local time zone and savings time information. +.PP +.L time_t +values are the number of seconds since the epoch, +.BR "Jan 1 00:00:00 GMT 1970" , +with leap seconds omitted. +.PP +The global variable +.L "int tm_info.flags" +contains flags that allow all programs using the library +to be controlled in a consistent manner. +.L tm_info.flags +is initialized by the +.L tminit() +routine described below, and may be explicitly reset after +.L tminit() +is called. +The flags are: +.TP +.L TM_ADJUST +Set by +.L tminit() +if +.L localtime() +and +.L gmtime() +do not compensate for leap seconds. +.TP +.L TM_LEAP +.L time_t +values are interpreted as if they include leap seconds. +Set by +.L tminit() +if the +.L leap +option is set in the +.L TM_OPTIONS +environment variable. +.TP +.L TM_UTC +Times are relative to +.B UTC +(universal coordinated time, i.e., +.BR GMT .) +Otherwise times are relative to the local time zone. +Set by +.L tminit() +if the time zone name matches one of +.L tm_info.format[43] +through +.L tm_info.format[46] +described below. +If the time zone name is not determined by +.L localtime() +then the environment variables +.L TZNAME +(as described in BSD 4.3) and +.L TZ +(as described in System V) +are checked, in order. +If this fails then the time zone name is constructed using +the local time zone offset. +.PP +The routines are: +.TP +.L "time_t tmdate(const char* date, char** end, time_t* clock)" +Parses the date specification +.L date +using the +.L tm_info.format +string table (described below) +and returns the equivalent +.L time_t +value. +If +.RL non- NULL , +.L end +is set to the position of the first unrecognized character in +.LR date . +.L clock +is used to provide default values for omitted components in +.LR date . +If +.L clock +is +.L NULL +then the current time is used. +.TP +.L "Tm_t* tmfix(Tm_t* tp)" +Corrects any out of bounds fields in +.L tp +and returns +.L tp +as its value. +The corrections start with +.L tp->tm_sec +and propagate down to +.LR tp->tm_year . +For example, if +.L tp->tm_sec +were 61 then it would change to 1 and +.L tp->tm_min +would be incremented by 1, and so on. +.L tp->tm_isdst +is not changed -- call +.L tmtime() +to determine its proper value after the +.L tmfix() +adjustments. +.TP +.L "char* tmfmt(char* buf, size_t len, const char* format, time_t* clock)" +Formats the date pointed to by +.L clock +into the buffer +.L buf +with size +.L len +bytes according to the format specification +.LR format . +If +.L format +is +.L NULL +or empty then the string +.L tm_info.format[40] +is used. +If +.L clock +is +.L NULL +then the current time is used. +A pointer to the end of +.L buf +(i.e., the terminating +.LR "'\e0'" ) +is returned. +.RS +.PP +.L format +is in +.BR printf (3) +style, where +.RI % field +names a fixed size field, zero padded if necessary, +and +.I \ec +and +.I \ennn +sequences are as in C. Invalid +.RI % field +specifications and all other characters are copied +without change. +.I field +may be preceded by +.B %- +to turn off padding or +.B %_ +to pad with space, otherwise numeric fields +are padded with +.B 0 +and string fields are padded with space. +.I field +may also be preceded by +.B E +for alternate era representation or +.B O +for alternate digit representation (if supported by the current locale.) +Finally, an integral +.I width +preceding +.I field +truncates the field to +.I width +characters. +sequences are interpreted as in the C language. +String field values are taken from the +.L tm_info.format +string table. +The +.I fields +are: +.TP +.PD 0 +.B % +.B % +character. +.TP +.B a +Abbreviated weekday name. +.TP +.B A +Full weekday name. +.TP +.B b +Abbreviated month name. +.TP +.B c +.BR ctime (3) +style date without the trailing +.BR newline . +.TP +.B C +.BR date (1) +style date. +.TP +.B d +Day of month number. +.TP +.B D +Date as +.IR mm / dd / yy . +.TP +.B e +Blank padded day of month number. +.TP +.B E +Unpadded day of month number. +.TP +.B f +Locale default override date format. +.TP +.B F +Locale default date format +.RL ( tm_info.format[40] .) +.TP +.B h +Abbreviated month name. +.TP +.B H +24-hour clock hour. +.TP +.B i +International +.BR date (1) +date that includes the time zone type name +.RL ( tm_info.format[107] .) +.TP +.B I +12-hour clock hour. +.TP +.B j +1-offset Julian date. +.TP +.B J +0-offset Julian date. +.TP +.B k +.BR date (1) +style date +.RL ( tm_info.format[106] .) +.TP +.B K +Language neutral, all numeric, no embedded space date +with larger to smaller time units from left to right, +suitable for sorting: +.LR '"%Y-%m-%d+%H:%M:%S"' . +.TP +.B l +.BR ls (1) +.B \-l +date that lists recent dates with +.L %g +and distant dates with +.BR %G . +.TP +.B m +Month number. +.TP +.B M +Minutes. +.TP +.B n +.B newline +character. +.TP +.B N +The time zone type or nation code. +.TP +.B p +Meridian (e.g., +.B AM +or +.BR PM .) +.TP +.B q +The nanosecond part of the time. +.TP +\fB%Q\fP\fI<delim>recent<delim>distant<delim>\fP +Recent dates are formatted with +.I recent +and distand dates are formatted with +.IR distant , +where +.I <delim> +is any character not appearing in +.I recent +or +.IR distant . +.TP +.B r +12-hour time as +.IR hh : mm : ss +.IR meridian . +.TP +.B R +24-hour time as +.IR hh : mm . +.TP +.B s +Seconds since the epoch. +.RI . prec +preceding +.B s +appends +.I prec +nanosecond digits, +.B 9 +if +.I prec +is omitted. +.TP +.B S +.I seconds.subseconds +since the epoch. +.TP +.B t +.B tab +character. +.TP +.B T +24-hour time as +.IR hh : mm : ss . +.TP +.B u +Weeday number with 1 for Monday, 7 for Sunday. +.TP +.B U +Week number with Sunday as the first day. +.TP +.B V +ISO week number (i18n is \fIfun\fP.) +.TP +.B w +Weekday number with 0 for Sunday, 6 for Saturday. +.TP +.B W +Week number with Monday as the first day. +.TP +.B x +Local date style, using +.LR tm_info.format[39] , +that includes the month, day and year. +.TP +.B X +Local time style, using +.LR tm_info.format[38] , +that includes the hours and minutes. +.TP +.B y +2-digit year (you'll be sorry.) +.TP +.B Y +4-digit year. +.TP +.B z +Time zone +.I SHHMM +west of GMT offset where +.I S +is +.B + +or +.BR - . +.TP +.B Z +Time zone name. +.TP +=[=]][-+]]\fIflag\fP +Set (default or +) or clear (-) +.I flag +in +.L tm_info.flags +for the remainder of +.IR format , +or for the remainder of the process if +.B == +is specified. +.I flag +may be: +.RS +.TP +.B l +.L (TM_LEAP) +Enable leap second adjustments. +.TP +.B s +.L (TM_SUBSECOND) +Append nanosecond +.B .%N +to +.BR %S . +.TP +.B u +.L (TM_UTC) +UTC time zone. +.RE +.TP +.B # +Equivalent to +.BR %s . +.TP +\fP?\fP\fIalternate\fP +Use +.I alternate +format is a default format override has not been specified. +e.g., +.BR ls (1) +uses +.BR %?%l . +Export +\f5TM_OPTIONS="format='\fP\fIoverride\fP\f5'"\fP +to override the default. +.PD +.RE +.TP +.L "void tminit(Tm_zone_t* zone)" +Implicitly called by the other +.I tm +library routines to initialize global data, including the +.L tm_info.format +table and the +.L tm_info.flags +global flags. +Global data should only be modified after an explicit call to +.LR tminit . +If +.L "zone != 0" +then it specifies a time zone other that the local time zone. +.TP +.L "void tmset(Tm_zone_t* zone);" +.L tmset +sets the reference timezoe to +.LR zone . +.L tm_info.local +points to the local timezone and +.L tm_info.zone +points to the current reference timezone. +.TP +.L "time_t tmleap(time_t* clock)" +Returns a +.L time_t +value for the time pointed to by +.L clock +with leap seconds adjusted for external +routines that do not handle leap seconds. +If +.L clock +is +.L NULL +then the current time is used. +Adjustments are only done if the +.L TM_ADJUST +flag is set in +.LR tm_info.flags . +.TP +.L "Tm_t* tmmake(time_t* clock)" +Returns a pointer to the +.L Tm_t +struct corresponding to the time pointed to by +.LR clock . +If +.L clock +is +.L NULL +then the current time is used. +.TP +.L "time_t tmtime(Tm_t* tp, int west)" +Returns the +.L time_t +value corresponding to +.LR tp . +If +.L west +is +.L TM_LOCALZONE +then +.L tm +is relative to the local time zone, +otherwise +.L west +is the number of minutes west of +.B UTC +with daylight savings time taken into account. +.LR tp->tm_wday , +.LR tp->tm_yday +and +.L tp->tm_isdst +are ignored in the conversion. +.PP +The library routines use a table of date strings pointed to by +.LR "char** tm_info.format" . +The indices in +.L tm_info.format +are fixed by category. +.L tm_info.format +may be changed to point to other tables +according to local language and date conventions. +The contents by index (showing the USA English values) are: +.RS +.TP +.PD 0 +.B 0-11 +3-character abbreviated month names. +.TP +.B 12-23 +Full month names. +.TP +.B 24-30 +3-character abbreviated weekday names. +.TP +.B 31-37 +Full weekday names. +.TP +.B 38 +.L tmfmt() +local time format used by the +.B %X +field. +.TP +.B 39 +.L tmfmt() +local date format used by the +.B %x +field. +.TP +.B 40 +.L tmfmt() +format used if the +.L format +argument is +.L NULL +or empty. +.TP +.B 41-42 +Meridian names: AM, PM. +.TP +.B 43-46 +.B UTC +time zone names: GMT, UTC, UCT, CUT. +.TP +.B 47-50 +Daylight savings time suffix names: DST. +.TP +.B 51-54 +Suffixes to be ignored when matching strings in +.LR tmfmt() . +.TP +.B 55-61 +Time part names: second, hour, minute, day, week, month, year. +.TP +.B 62-65 +Hours of the day names: midnight, morning, noon, evening. +.TP +.B 66-68 +Relative day names: yesterday, today, tomorrow. +.TP +.B 69-71 +Past relative time references: last, ago, past. +.TP +.B 72-75 +Current relative time references: this, now, current. +.TP +.B 75-77 +Future relative time references: next, hence, coming. +.TP +.B 78-80 +Exact relative time references: exactly. +.TP +.B 81-84 +Noise words to be ignored: at, in, on. +.TP +.B 85-94 +Ordinal suffixes: st, nd, rd, th, th, th, th, th, th, th. +.TP +.B 95-104 +Digit names. +.TP +.B 105 +The +.L tmfmt() +format equivalent for +.BR ctime (3): +.LR '"%a %b %e %T %Y"' . +.TP +.B 106 +The +.L tmfmt() +.BR date (1) +default format: +.LR '"%a %b %e %T %Z %Y"' . +.TP +.B 107 +The +.L tmfmt() +.BR date (1) +international format: +.LR '"%a %b %e %T %z %Z %Y"' . +.TP +.B 108 +The +.L tmfmt() +.BR ls (1) +recent date format: +.LR '"%b %e %H:%M"' . +.TP +.B 109 +The +.L tmfmt() +.BR ls (1) +distant date format: +.LR '"%b %e %Y"' . +.TP +.B 110 +The +.L tmfmt() +.BR date (1) +meridian date format: +.LR '"%I:%M:%S %p"' . +.TP +.B 111 +The ERA name. +.TP +.B 112 +ERA alternative for +.BR 39 . +.TP +.B 113 +ERA alternative for +.BR 38 . +.TP +.B 114 +ERA alternative for +.BR 40 . +.TP +.B 115 +The ERA year. +.TP +.B 116-125 +Ordinal names: first, \fIno second!\fP, third, fourth, fifth, sixth, seventh, eighth, ninth, tenth. +.TP +.B 126-128 +Final time references, as in \fIthe last in the list\fP: final, ending, nth. +.PD +.RE +.PP +Low level support functions and data are described in +.LR <tm.h> . +.SH EXAMPLES +.EX +#include <tm.h> +main() { + int i; + time_t t; + char buf[128]; + struct { + char* date; + char* format; + } x[] = { + "now", "%i", + "2 months ago", "%C", + "this Wednesday noon", "%x %I:%M %p", + "last December 25", "%A", + 0, 0 + }; + for (i = 0; x[i].date; i++) { + t = tmdate(x[i].date, (char*)0, (time_t*)0); + (void)tmfmt(buf, sizeof(buf), x[i].format, &t); + puts(buf); + } +} +.EE +produces +.EX +Fri Sep 30 12:10:14 USA EDT 1988 +Fri Jul 1 00:00:00 EDT 1988 +10/05/88 12:00 PM +Friday +.EE +.SH "SEE ALSO" +.BR date (1), +.BR time (2), +.BR ctime (3) +.SH BUGS +The C library static +.L "struct tm" +values may get clobbered by +.I tm +library routines as the +.BR ctime (3) +and +.BR localtime (3) +routines typically return pointers to a single static +.L "struct tm" +area. +.L tmdate() +uses an internal international time zone name table that will +probably always be incomplete. diff --git a/src/lib/libast/man/tmx.3 b/src/lib/libast/man/tmx.3 new file mode 100644 index 0000000..268d40a --- /dev/null +++ b/src/lib/libast/man/tmx.3 @@ -0,0 +1,576 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH TM 3 +.SH NAME +tm \- time conversion support +.SH SYNOPSIS +.L "#include <tm.h>" +.SH DESCRIPTION +The +.I tm +library supports conversion between +string date specifications, +.L time_t +clock values and +.L "struct tm" +values. +.L localtime() +and +.L gmtime() +(see +.IR ctime (3)) +are used to determine local time zone information. +.PP +.L time_t +values are the number of seconds since the epoch, +.BR "Jan 1 00:00:00 GMT 1970" , +with leap seconds omitted. +.PP +The global variable +.L "int tm_info.flags" +contains flags that allow all programs using the library +to be controlled in a consistent manner. +.L tm_info.flags +is initialized by the +.L tminit() +routine described below, and may be explicitly reset after +.L tminit() +is called. +The flags are: +.TP +.L TM_ADJUST +Set by +.L tminit() +if +.L localtime() +and +.L gmtime() +do not compensate for leap seconds. +.TP +.L TM_LEAP +.L time_t +values are interpreted as if they include leap seconds. +Set by +.L tminit() +if the +.L leap +option is set in the +.L TM_OPTIONS +environment variable. +.TP +.L TM_UTC +Times are relative to +.B UTC +(universal coordinated time, i.e., +.BR GMT ). +Otherwise times are relative to the local time zone. +Set by +.L tminit() +if the time zone name matches one of +.L tm_info.format[43] +through +.L tm_info.format[46] +described below. +If the time zone name is not determined by +.L localtime() +then the environment variables +.L TZNAME +(as described in BSD 4.3) and +.L TZ +(as described in System V) +are checked, in order. +If this fails then the time zone name is constructed using +the local time zone offset. +.PP +The routines are: +.TP +.L "time_t tmdate(const char* date, char** end, time_t* clock)" +Parses the date specification +.L date +using the +.L tm_info.format +string table (described below) +and returns the equivalent +.L time_t +value. +If +.RL non- NULL , +.L end +is set to the position of the first unrecognized character in +.LR date . +.L clock +is used to provide default values for omitted components in +.LR date . +If +.L clock +is +.L NULL +then the current time is used. +.TP +.L "struct tm* tmfix(struct tm* tp)" +Corrects any out of bounds fields in +.L tp +and returns +.L tp +as its value. +The corrections start with +.L tp->tm_sec +and propagate down to +.LR tp->tm_year . +For example, if +.L tp->tm_sec +were 61 then it would change to 1 and +.L tp->tm_min +would be incremented by 1, and so on. +.LR tp->tm_wday , +.LR tp->tm_yday +and +.L tp->tm_isdst +are not changed as these can be computed from the other fields. +.TP +.L "char* tmfmt(char* buf, size_t len, const char* format, time_t* clock)" +Formats the date pointed to by +.L clock +into the buffer +.L buf +with size +.L len +bytes according to the format specification +.LR format . +If +.L format +is +.L NULL +or empty then the string +.L tm_info.format[40] +is used. +If +.L clock +is +.L NULL +then the current time is used. +A pointer to the end of +.L buf +(i.e., the terminating +.LR "'\e0'" ) +is returned. +.RS +.PP +.L format +is in the style of +.IR printf (3), +where +.BI % field +causes the corresponding fixed size field to be placed in +.LR buf , +zero padded if necessary, and \e\fIc\fP and \e\fInnn\fP +sequences are interpreted as in the C language. +Otherwise invalid +.BI % field +specifications and all other characters in +.L format +are copied into +.L buf +without change. +String field values are taken from the +.L tm_info.format +string table. +The +.I fields +are: +.TP +.PD 0 +.B % +.B % +character. +.TP +.B a +Abbreviated weekday name. +.TP +.B A +Full weekday name. +.TP +.B b +Abbreviated month name. +.TP +.B c +.IR ctime (3) +style date without the trailing +.BR newline . +.TP +.B C +.IR date (1) +style date. +.TP +.B d +Day of month number. +.TP +.B D +Date as +.IR mm / dd / yy . +.TP +.B e +Blank padded day of month number. +.TP +.B E +Unpadded day of month number. +.TP +.B h +Abbreviated month name. +.TP +.B H +24-hour clock hour. +.TP +.B i +International +.IR date (1) +date that includes the time zone type name. +.TP +.B I +12-hour clock hour. +.TP +.B j +1-offset Julian date. +.TP +.B J +0-offset Julian date. +.TP +.B l +.IR ls (1) +.B \-l +date that lists recent dates with +.IR hh : mm +and distant dates with +.IR yyyy . +.TP +.B m +Month number. +.TP +.B M +Minutes. +.TP +.B n +.B newline +character. +.TP +.B p +Meridian (e.g., +.B AM +or +.BR PM ). +.TP +.B r +12-hour time as +.IR hh : mm : ss +.IR meridian . +.TP +.B R +24-hour time as +.IR hh : mm . +.TP +.B S +Seconds. +.TP +.B t +.B tab +character. +.TP +.B T +24-hour time as +.IR hh : mm : ss . +.TP +.B U +Week number with Sunday as the first day. +.TP +.B w +Weekday number. +.TP +.B W +Week number with Monday as the first day. +.TP +.B x +Local date style, using +.LR tm_info.format[39] , +that includes the month, day and year. +.TP +.B X +Local time style, using +.LR tm_info.format[38] , +that includes the hours and minutes. +.TP +.B y +2-digit year. +.TP +.B Y +4-digit year. +.TP +.B z +Time zone type name. +.TP +.B Z +Time zone name. +.TP +.BI + flag +.TP +.BI \- flag +Temporarily (until +.L tmform() +returns) sets (+) or clears (\-) the +.L tm_info.flags +flags specified by +.IR flag : +.RS +.TP +.B l +.L TM_LEAP +.TP +.B u +.L TM_UTC +.RE +.TP +.B # +Number of seconds since the epoch. +.PD +.RE +.TP +.L "void tminit(Tm_zone_t* zone)" +Implicitly called by the other +.I tm +library routines to initialize global data, including the +.L tm_info.format +table and the +.L tm_info.flags +global flags. +Global data should only be modified after an explicit call to +.LR tminit . +If +.L "zone != 0" +then it specifies a time zone other that the local time zone. +.TP +.L "void tmset(Tm_zone_t* zone);" +.L tmset +sets the reference timezoe to +.LR zone . +.L tm_info.local +points to the local timezone and +.L tm_info.zone +points to the current reference timezone. +.TP +.L "time_t tmleap(time_t* clock)" +Returns a +.L time_t +value for the time pointed to by +.L clock +with leap seconds adjusted for external +routines that do not handle leap seconds. +If +.L clock +is +.L NULL +then the current time is used. +Adjustments are only done if the +.L TM_ADJUST +flag is set in +.LR tm_info.flags . +.TP +.L "struct tm* tmmake(time_t* clock)" +Returns a pointer to the +.L tm +struct corresponding to the time pointed to by +.LR clock . +If +.L clock +is +.L NULL +then the current time is used. +.TP +.L "time_t tmtime(struct tm* tp, int west)" +Returns the +.L time_t +value corresponding to +.LR tp . +If +.L west +is +.L TM_LOCALZONE +then +.L tm +is relative to the local time zone, +otherwise +.L west +is the number of minutes west of +.B UTC +with daylight savings time taken into account. +.LR tp->tm_wday , +.LR tp->tm_yday +and +.L tp->tm_isdst +are ignored in the conversion. +.PP +The library routines use a table of date strings pointed to by +.LR "char** tm_info.format" . +The indices in +.L tm_info.format +are fixed by category. +.L tm_info.format +may be changed to point to other tables +according to local language and date conventions. +The contents by index (showing the USA English values) are: +.RS +.TP +.PD 0 +.B 0-11 +3-character abbreviated month names. +.TP +.B 12-23 +Full month names. +.TP +.B 24-30 +3-character abbreviated weekday names. +.TP +.B 31-37 +Full weekday names. +.TP +.B 38 +.L tmform() +local time format used by the +.B %X +field. +.TP +.B 39 +.L tmform() +local date format used by the +.B %x +field. +.TP +.B 40 +.L tmform() +format used if the +.L format +argument is +.L NULL +or empty. +.TP +.B 41-42 +Meridian names: AM, PM. +.TP +.B 43-46 +.B UTC +time zone names: GMT, UTC, UCT, CUT. +.TP +.B 47-50 +Daylight savings time suffix names: DST. +.TP +.B 51-54 +Suffixes to be ignored when matching strings in +.LR tmform() . +.TP +.B 55-61 +Time part names: second, hour, minute, day, week, month, year. +.TP +.B 62-65 +Hours of the day names: midnight, morning, noon, evening. +.TP +.B 66-68 +Relative day names: yesterday, today, tomorrow. +.TP +.B 69-71 +Past relative time references: last, ago, past. +.TP +.B 72-75 +Current relative time references: this, now, current. +.TP +.B 75-77 +Future relative time references: next, hence, coming. +.TP +.B 78-80 +Exact relative time references: exactly. +.TP +.B 81-85 +Noise words to be ignored: at, in, on. +.PD +.RE +.PP +Low level support functions and data are described in +.LR <tm.h> . +.SH EXAMPLES +.EX +#include <tm.h> +main() { + int i; + time_t t; + char buf[128]; + struct { + char* date; + char* format; + } x[] = { + "now", "%i", + "2 months ago", "%C", + "this Wednesday noon", "%x %I:%M %p", + "last December 25", "%A", + 0, 0 + }; + for (i = 0; x[i].date; i++) { + t = tmdate(x[i].date, (char*)0, (time_t*)0); + (void)tmform(buf, x[i].format, &t); + puts(buf); + } +} +.EE +produces +.EX +Fri Sep 30 12:10:14 USA EDT 1988 +Fri Jul 1 00:00:00 EDT 1988 +10/05/88 12:00 PM +Friday +.EE +.SH "SEE ALSO" +date(1), time(2), ctime(3) +.SH BUGS +.L "struct tm" +values may get clobbered by the +.I tm +library routines as the +.IR ctime (3) +routines typically return pointers to a single static +.L "struct tm" +area. +.L tmdate() +uses an internal international time zone name table that will +probably always be incomplete. diff --git a/src/lib/libast/man/tok.3 b/src/lib/libast/man/tok.3 new file mode 100644 index 0000000..46fbff9 --- /dev/null +++ b/src/lib/libast/man/tok.3 @@ -0,0 +1,217 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH TOK 3 +.SH NAME +tok \- space separated token stream routines +.SH SYNOPSIS +.L "#include <ast.h>" +.sp +.L "void* tokopen(char* string)" +.L "char* tokread(void* tok)" +.L "void tokclose(void* tok)" +.sp +.L "int tokscan(char* string, char** next, const char* format, ...);" +.sp +.L "Sfio_t* tokline(const char* input, int flags, int* line);" +.SH DESCRIPTION +.L tokopen +returns a pointer to a space separated token stream on the 0 terminated +string +.LR string . +.L tokread +returns a pointer to the next +space separated token in the token stream +.L tok +as returned by +.LR tokopen . +0 is returned when no tokens remain. +.L tokread +temporarily modifies +.L string +by inserting 0's to terminate each token. +.L tokclose +closes the token stream and restores +.L string +to its original state. +.PP +.L tokscan +scans the string +.L string +for tokens specified in +.LR format . +It is a more forgiving +.IR sscanf (3). +If +.L "next != 0" +then it will point to the next unread character in +.L string +on return. +The number of scanned tokens is returned. +.L \-1 +is returned if +.L string +was not empty and +.L format +failed to match and tokens. +.PP +.I space +in +.L format +matches 0 or more +.I space +or +.I tab +characters. +.I newline +in format eats the remainder of the current line in +.LR string . +"...", '...' and \e\fIcharacter\fP quotes are interpreted. +A quoted +.I carriage-return +is converted to +.IR newline . +.I newline +in +.L string +is equivalent to end of string except when quoted. +.I \enewline +is a line splice. +.PP +.L % +in +.L format +prefixes format conversion characters; each conversion character +corresponds to a +.L tokscan +argument following the +.L format +argument. +The format conversions are: +.TP +.L %c +A single +.LR char . +.TP +.L "%hd %d %ld" +[short, int, long] base 10 integer. +.TP +.L "%hn %n %ln" +[short, int, long] C-style base integer. +.TP +.L "%ho %o %lo" +[short, int, long] base 8 integer. +.TP +.L %s +String. +.TP +.L "%hu %u %lu" +[short, int, long] C-style base unsigned integer. +.TP +.L %v +The next two arguments are a pointer to a +.L char** +argument vector and the maximum number of elements in the vector. +.TP +.L "%hx %x %lx" +[short, int, long] base 16 integer. +.PP +.L %s +and +.L %v +data may also be counted length strings of the form +\f5(\fIcount\fP:\fIdata\fP)\fR +where +.I count +is the number of characters in +.I data +and the terminating +.L ) +may also be a +.IR tab , +or the data may be +.L (null) +which represents the +.L NULL +string. +.PP +.L tokline +returns an +.IR sfio (3) +stream to a file or string that splices +.I \enewline +into single lines, +allows "..." and '...' to quotes to span +.I newlines +(done by translating quoted +.I newline +to +.IR carriage-return ; +.L tokscan +above converts quoted +.I carriage-return +back to +.IR newline ), +and deletes +.I "# ... newline" +comments. +This is done by pushing an +.I sfio +discipline onto a string or file stream. +Seeks are disabled on the resulting stream. +If +.L "flags == SF_READ" +then +.L input +is a file name; +If +.L "flags == SF_STRING" +then +.L input +is a 0 terminated string; +otherwise +.L input +is an open +.L Sfio_t* +stream. +If +.L "line != 0" +then it points to a line count that is initialized to 0 +and is incremented for each input line. +.SH "SEE ALSO" +sfio(3) diff --git a/src/lib/libast/man/touch.3 b/src/lib/libast/man/touch.3 new file mode 100644 index 0000000..908a8b1 --- /dev/null +++ b/src/lib/libast/man/touch.3 @@ -0,0 +1,68 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH TOUCH 3 +.SH NAME +touch \- set file access and modify times +.SH SYNOPSIS +.L "#include <ast.h>" +.sp +.L "int touch(const char* path, time_t atime, time_t mtime, int force);" +.SH DESCRIPTION +.L touch +sets the access and modify times of the file named by +.LR path . +If +.L "force != 0" +then the file is created if it doesn't exist; +otherwise the file is not created and +.L \-1 +is returned. +If +.L "force < 0" +then +.L atime +and +.L mtime +are taken verbatim; otherwise +.L "(time_t)(-1)" +retains the current value for the file and +.L "(time_t)(0)" +uses the current time. +.SH CAVEATS +By default the change time is always changed to the current time. diff --git a/src/lib/libast/man/tv.3 b/src/lib/libast/man/tv.3 new file mode 100644 index 0000000..b90a559 --- /dev/null +++ b/src/lib/libast/man/tv.3 @@ -0,0 +1,173 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH TM 3 +.SH NAME +tv \- high resolution time support +.SH SYNOPSIS +.L "#include <tv.h>" +.SH DESCRIPTION +The +.I tv +library supports high resolution +.B Tv_t +time specifications. +.SS Tv_t +contains these elements: +.TP +.L unsigned +.L _ast_int4_t +.L tv_sec +Seconds since the epoch. +.TP +.L unsigned +.L _ast_int4_t +.L tv_nsec +Nanosecond resolution. +.PP +In practice resolution is much coarser than 1 nanosecond. +Systems that only support 1 second resolution always set +.L tv_nsec +to 0. +.SS "int tvgettime(Tv_t* tv)" +Sets +.L tv +to the current time. +.L 0 +is returned on success, +.L -1 +on error. +.SS "int tvsettime(const Tv_t* tv)" +Sets the system time to +.LR tv . +The caller must have sufficient privilege. +.L 0 +is returned on success, +.L -1 +on error. +.SS "int tvcmp(const Tv_t* av, const Tv_t* bv)" +Compares the times +.L av +and +.L bv +and returns +.L -1 +if +.L av +is less than +.LR bv , +.L 0 +if +.L av +is equal to +.LR bv , +and +.L 1 +if +.L av +is greater than +.LR bv . +.SS "time_t tvgetatime(Tv_t* tv, const struct stat* st)" +.SS "time_t tvgetmtime(Tv_t* tv, const struct stat* st)" +.SS "time_t tvgetctime(Tv_t* tv, const struct stat* st)" +These macros set +.L tv +to the +.L st +the access, modify, or change time, respectively. +The seconds portion of +.L tv +is returned. +.SS "time_t tvsetatime(Tv_t* tv, struct stat* st)" +.SS "time_t tvsetmtime(Tv_t* tv, struct stat* st)" +.SS "time_t tvsetctime(Tv_t* tv, struct stat* st)" +These macros set the +.L st +access, modify, or change time, respectively, to +.LR tv . +The seconds portion of +.L tv +is returned. +.SS "int tvtouch(const char* path, const Tv_t* av, const Tv_t* mv, const Tv_t* cv, int copy)" +Sets the file +.L path +access time from +.LR av , +modify time from +.LR mv , +and change time from +.LR cv . +Any of +.LR av , +.LR mv , +and +.L cv +may be 0; the corresponding file time will retain the previous value if +.L path +exists and +.L copy +is +.L 1 ; +otherwise the corresponding file time will be set to the current time. +.L 0 +is returned on success, +.L -1 +on error. +.SS "int tvsleep(const Tv_t* tv, Tv_t* rv)" +Pauses execution for +.L tv +time. +.L 0 +is returned if the full +.L tv +amount has expired. +Otherwise +.L -1 +is returned and +.LR rv , +if not 0, is set to the sleep time remaining. +.SH "RETURN VALUE" +Except for +.LR tvcmp() , +an error return of +.L -1 +also sets +.L errno +to the corresponding error code. +.SH "SEE ALSO" +tm(3) diff --git a/src/lib/libast/man/vecargs.3 b/src/lib/libast/man/vecargs.3 new file mode 100644 index 0000000..29e492b --- /dev/null +++ b/src/lib/libast/man/vecargs.3 @@ -0,0 +1,126 @@ +.fp 5 CW +.de Af +.ds ;G \\*(;G\\f\\$1\\$3\\f\\$2 +.if !\\$4 .Af \\$2 \\$1 "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +.. +.de aF +.ie \\$3 .ft \\$1 +.el \{\ +.ds ;G \& +.nr ;G \\n(.f +.Af "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" +\\*(;G +.ft \\n(;G \} +.. +.de L +.aF 5 \\n(.f "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de LR +.aF 5 1 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de RL +.aF 1 5 "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" +.. +.de EX \" start example +.ta 1i 2i 3i 4i 5i 6i +.PP +.RS +.PD 0 +.ft 5 +.nf +.. +.de EE \" end example +.fi +.ft +.PD +.RE +.PP +.. +.TH VECARGS 3 +.SH NAME +vecargs \- command argument vector insertion routines +.SH SYNOPSIS +.L "#include <vecargs.h>" +.sp +.L "char** vecload(char* string);" +.L "char** vecfile(const char* path);" +.L "char** vecstring(const char* string);" +.L "void vecfree(char**, int);" +.L "int vecargs(char** vec, int* argcp, char*** argvp);" +.SH DESCRIPTION +.L vecload +loads a string vector from lines in +.LR string . +.L string +may be modified upon return. +Each line in +.L string +is treated as a new vector element. +Lines with +.L # +as the first character are comments. +.I \enewline +joins consecutive lines. +A string vector pointer is returned, 0 on error. +.PP +.L vecfile +constructs a string vector by calling +.L vecload +on the contents of the file named by +.LR path . +The string vector pointer is returned, 0 on error. +.PP +.L vecstring +constructs a string vector by calling +.L vecload +on a copy of +.LR string . +The string vector pointer is returned, 0 on error. +.PP +.L vecfree +frees a string vector allocated by +.LR vecfile , +.L vecload +or +.LR vecstring . +.PP +.L vecargs +inserts the string vector +.L vec +(as returned by +.LR vecfile , +.L vecload +or +.LR vecstring ) +between +.L "(*argvp)[0]" +and +.LR "(*argvp)[1]" , +sliding +.L "(*argvp)[1] ..." +over. +NULL and empty string args in +.L vec +are not copied. +.L "vecfree(vec)" +is called before the return. +.L \-1 +is returned if the insertion failed. +.SH EXAMPLES +.L vecargs +is commonly used to modify command +.L argv +from fixed files. +For example, +.IR make (1) +checks for the files +.L ./Makeargs +and +.L ./makeargs +to modify its arguments on startup. +Its a handy way to override default options on a directory by directory basis +without modify the standard control files +(\f5Makefile\fP in this case.) +.SH CAVEATS +This paradigm is not recommended for all commands; only a few exceptions +make sense. diff --git a/src/lib/libast/man/vmalloc.3 b/src/lib/libast/man/vmalloc.3 new file mode 100644 index 0000000..3bc6413 --- /dev/null +++ b/src/lib/libast/man/vmalloc.3 @@ -0,0 +1,640 @@ +.fp 5 CW +.de MW +\f5\\$1\fP +.. +.TH VMALLOC 3 "1 May 1998" +.SH NAME +vmalloc \- virtual memory allocation +.SH SYNOPSIS +.MW "#include <vmalloc.h>" +.SS Regions +.nf +.MW "Vmalloc_t* vmopen(Vmdisc_t* disc, Vmethod_t* meth, int flags);" +.MW "int vmclose(Vmalloc_t*);" +.MW "int vmclear(Vmalloc_t*);" +.MW "int vmcompact(Vmalloc_t* region);" +.MW "int vmset(Vmalloc_t* region, int flags, int type);" +.MW "Vmalloc_t* Vmheap;" +.MW "Vmdisc_t* vmdisc(Vmalloc_t* region, Vmdisc_t* disc);" +.MW "Vmalloc_t* vmmopen(char* file, int project, ssize_t size);" +.MW "Void_t* vmmvalue(Vmalloc_t* vm, int key, Void_t* value, int op);" +.MW "Void_t* vmmcleanup(Vmalloc_t* vm);" +.MW "Void_t* vmmaddress(size_t size);" +.fi +.SS "Allocation functions" +.nf +.MW "Void_t* vmalloc(Vmalloc_t* region, size_t size);" +.MW "Void_t* vmalign(Vmalloc_t* region, size_t size, size_t align);" +.MW "Void_t* vmresize(Vmalloc_t* region, Void_t* addr, size_t size, int type);" +.MW "int vmfree(Vmalloc_t* region, Void_t* addr);" +.MW "Void_t* vmnewof(Vmalloc_t* region, Void_t* addr, type, size_t n, size_t x);" +.MW "Void_t* vmoldof(Vmalloc_t* region, Void_t* addr, type, size_t n, size_t x);" +.MW "Void_t* vmgetmem(Vmalloc_t* region, Void_t* addr, size_t size);" +.fi +.SS "Debugging" +.nf +.MW "int vmdebug(int);" +.MW "int vmdbcheck(Vmalloc_t* vm);" +.MW "int vmdbwatch(Void_t* addr);" +.MW "static void vmdbwarn(Vmalloc_t*, char* mesg, int n);" +.fi +.SS "Profiling" +.nf +.MW "void vmprofile(Vmalloc_t* vm, int fd);" +.fi +.SS "Information and statistics" +.nf +.MW "int vmbusy(Vmalloc_t* region);" +.MW "Vmalloc_t* vmregion(Void_t* addr);" +.MW "Void_t* vmsegment(Vmalloc_t* region, Void_t* addr);" +.MW "int vmwalk(Vmalloc_t* region, int(*walkf)(Vmalloc_t*, Void_t*, size_t, Vmdisc_t*);" +.MW "long vmaddr(Vmalloc_t* region, Void_t* addr);" +.MW "long vmsize(Vmalloc_t* region, Void_t* addr);" +.MW "int vmstat(Vmalloc_t* vm, Vmstat_t* statb);" +.MW "int vmtrace(int fd);" +.MW "int vmtrbusy(Vmalloc_t* vm);" +.MW "Void_t* vmdata(Vmalloc_t* vm);" +.fi +.SS "Malloc-compatible functions" +.nf +.MW "Void_t* malloc(size_t size);" +.MW "Void_t* realloc(Void_t* addr, size_t size);" +.MW "Void_t* calloc(size_t n_obj, size_t s_obj);" +.MW "int cfree(Void_t* addr);" +.MW "void free(Void_t* addr);" +.MW "Void_t* memalign(size_t align, size_t size);" +.MW "Void_t* valloc(size_t size);" +.MW "int setregmax(int regmax);" +.fi +.SH DESCRIPTION +These functions for dynamic storage allocation work in +\fIregions\fP of memory. +Each region has an \fIallocation method\fP +for parceling out blocks of storage and a +\fImemory discipline\fP for obtaining raw space. +Automatic locking prevents interference by reentrant +access to a region. +.PP +Pointers to space have type \f5Void_t*\fP +where \f5Void_t\fP is \f5#define\fPd as \f5void\fP if possible, otherwise \f5char\fP. +Space is counted in type \f5size_t\fP. + +.ne 4 +.SS Regions +Regions have type \f5Vmalloc_t\fP. +Two predefined regions are pointed to by: +.TP +.MW Vmheap +A general-purpose region, with best-fit +allocation, and system memory discipline \f5Vmdcsystem\fP. +.PP +These functions manipulate regions: +.PP +.I vmopen +creates a region with memory discipline \fIdisc\fP, +allocation method \fImeth\fP, +and a setting for control \fIflags\fP. +It returns a pointer to the region on success and \f5NULL\fP on failure. +The flags, represented by bit values or-ed together, are: +.TP +.MW VM_SHARE +This region may be accessed concurrently by multiple threads or processes. +.TP +.MW VM_TRACE +Place tracing messages for each allocation event +on the tracing file established by \fIvmtrace\fP. +.TP +\f5VM_DBCHECK\fP, \f5VM_DBABORT\fP +.br +See \fBDebugging\fP below. +.PP +.I vmclose +closes a \fIregion\fP and releases all associated memory +according to the region's discipline. +The first segment obtained from the discipline's +\f5memoryf\fP function (see `Disciplines' below) will be the last released. +\fIvmclose\fP returns \-1 on failure and a non-negative value otherwise. +.PP +.I vmclear +frees all allocated blocks in \fIregion\fP regardless of methods. +It returns \-1 on failure and a non-negative value otherwise. +.PP +.I vmcompact +releases as much of a \fIregion\fP's +free space to its discipline's \f5memoryf\fP +function as possible. +It returns a nonnegative value on success and \-1 on failure. +.PP +.I vmset +adjusts and queries a \fIregion\fP's \fIflags\fP. +The indicated flags are turned on if \fItype\fP is nonzero, off if zero. +\fIvmset\fP returns the previous value of all flags. +Thus, \f5vmset(region,0,0)\fP queries the flags without changing them. +In addition to the settable flags, one of +\f5VM_MTBEST\fP, \f5VM_MTDEBUG\fP, \f5VM_MTPROFILE\fP, +\f5VM_MTPOOL\fP, or \f5VM_MTLAST\fP +is returned to indicate the method used in creating the \fIregion\fP. +.PP +.I vmdisc +changes the discipline of \fIregion\fP to the given new discipline +\fIdisc\fP if \fIdisc\fP is not \f5NULL\fP and its \f5memoryf\fP function +is the same as the current discipline. If the current discipline +has an \f5exceptf\fP function, it will be called with event \f5VM_DISC\fP. +This function always returns the current discipline. +.PP +.I vmmopen +creates a region to allocate memory obtained via either +\fImmap(2)\fP when \fIproject < 0\fP or \fIshmget(2)\fP when \fIproject >= 0\fP. +The region is built from a single memory segment +guaranteed to be at least as large as \fIsize\fP. +When \fIproject >= 0\fP, +\fIfile\fP and \fIproject\fP are used in a call to \fIftok(3)\fP +to get a key suitable for getting a shared memory segment via \fIshmget(2)\fP. +Otherwise, \fIfile\fP is the backing store for the mapped data. +In this case, not only the region may be used concurrently by different processes, +it is also persistent. That is, process could even exit, move the file to +a different but similar machine then restart and open the same +region to continue working. +.PP +Note that Vmalloc can protect concurrent accesses only on region entry and exit +for memory allocation operations. +This means that at the time when regions are being opened or closed, there will be no +protection for the memory segments being attached into or detached from process memory space. +This limitation has a special impact on \fIvmmopen()\fP as follows. +.PP +A shared memory segment opened via \fIvmmopen()\fP corresponds uniquely +to a combination of the \fIfile\fP and \fIproject\fP parameters. +Thus, if multiple \fIvmmopen()\fP calls are done in the same process using a +same combination of \fIfile\fP and \fIproject\fP, +the joined behavior of such regions will be unpredictable when opening and closing +are done concurrently with other memory allocation operations. +Beware that this effect can be subtle with library functions that may attempt +to create their own memory allocation regions. +.PP +.I vmmvalue +manages pairs of \fIkey\fP and \fIvalue\fP in a region opened via \fIvmopen()\fP. +If \fIop\fP is \f5VM_MMGET\fP, the value associated with \f5key\fP is returned. +If \fIop\fP is \f5VM_MMSET\fP, the value associated with \f5key\fP will be +set to \fIvalue\fP. +If \fIop\fP is \f5VM_MMADD\fP, the value associated with \f5key\fP will be +treated as a signed long value to which \f5val\fP (also treated as a signed long value) +will be added. +The call always returns the updated data value associated with \fIkey\fP. +.PP +.I vmmcleanup +sets region up to remove backing store or \fIshmid\fP on closing. +.PP +.I vmmaddress +computes an address suitable for attaching a shared memory segment or +memory mapping a segment of file data of the given \fIsize\fP. +The address is chosen with hope to minimize collision with other activities +related to memory such as growth of stack space or space used +for dynamically linked libraries, etc. + +.SS "Allocation functions" +.I vmalloc +returns a pointer to a block of the requested \fIsize\fP +in a \fIregion\fP, aligned to the \fIstrictest alignment\fP +that is suitable for the needs of any basic data type. +It returns \f5NULL\fP on failure. +.PP +.I vmalign +works like \fIvmalloc\fP, but returns a block aligned to a common +multiple of \fIalign\fP and the \fIstrictest alignment\fP. +.PP +.I vmresize +attempts to change the length of the block pointed to by +\fIaddr\fP to the specified \fIsize\fP. +If that is impossible and \fItype\fP has +at least one of \f5VM_RSMOVE\fP and \f5VM_RSCOPY\fP, +a new block is allocated and the old block is freed. +The bit \f5VM_RSCOPY\fP also causes +the new block to be initialized with +as much of the old contents as will fit. +When a resized block gets larger, the new space will be cleared +if \fItype\fP has the bit \f5VM_RSZERO\fP. +\fIvmresize\fP +returns a pointer to the final block, or \f5NULL\fP on failure. +If \fIaddr\fP is \f5NULL\fP, \fIvmresize\fP behaves like \fIvmalloc\fP; +otherwise, if \fIsize\fP is 0, it behaves like \fIvmfree\fP. +.PP +.I vmfree +makes the currently allocated block pointed to by +\fIaddr\fP available for future allocations in its \fIregion\fP. +If \fIaddr\fP is \f5NULL\fP, \fIvmfree\fP does nothing. +It returns \-1 on error, and nonnegative otherwise. +.PP +.I vmnewof +is a macro function that attempts to change the length of +the block pointed to by \fIaddr\fP to the size \f5n*sizeof(type)+x\fP. +If the block is moved, new space will be initialized with as much of the +old content as will fit. +Additional space will be set to zero. +.PP +.I vmoldof +is similar to \fIvmnewof\fP but it neither copies data nor clears space. +.PP +.I vmgetmem +provides a handy function to creat/close regions and allocate/free memory +based on chunks of memory obtained from the heap region \fIVmheap\fP. +.TP +.MW "vmgetmem(0,0,0)" +This call opens a new region. +.TP +.MW "vmgetmem(region, 0, 0)" +This call closes the given \f5region\fP. +.TP +.MW "vmgetmem(region,0,n)" +This call allocates a block of length \f5n\fP and clears it to zeros. +.TP +.MW "vmgetmem(region,p,0)" +This call frees the block \f5p\fP. +.TP +.MW "vmgetmem(region,p,n)" +This call resizes the block \f5p\fP to length \f5n\fP +and clears the new memory to zeros if the block grows. +The block may be moved as deemed necessary by the allocator. +.PP +.SS "Memory disciplines" +Memory disciplines have type \f5Vmdisc_t\fP, +a structure with these members: +.in +.5i +.nf +.MW "Void_t* (*memoryf)(Vmalloc_t *region, Void_t* obj," +.ti +.5i +.MW "size_t csz, size_t nsz, Vmdisc_t *disc);" +.MW "int (*exceptf)(Vmalloc_t *region, int type, Void_t* obj, Vmdisc_t *disc);" +.MW "int round;" +.fi +.in -.5i +.TP +.MW round +If this value is positive, all size arguments to the +\f5memoryf\fP function will be multiples of it. +.TP +.MW memoryf +Points to a function to get or release segments of space for the +\fIregion\fP. +.TP +.MW exceptf +If this pointer is not \f5NULL\fP, +the function it points to is called to announce +events in a \fIregion\fP. +.PP +There are two standard disciplines, both with \f5round\fP being 0 and \f5exceptf\fP being \f5NULL\fP. +.TP +.MW Vmdcsystem +A discipline whose \f5memoryf\fP function gets space from the operation system +via different available methods which include \fImmap(2)\fP, \fIsbrk(2)\fP and +functions from the WIN32 API. +For historical reason, \fIVmdcsbrk\fP is also available and functions like \fIVmdcsystem\fP. +.TP +.MW Vmdcheap +A discipline whose \f5memoryf\fP function gets space from the region \f5Vmheap\fP. +A region with \f5Vmdcheap\fP discipline and \f5Vmlast\fP +allocation is good for building throwaway data structures. +.PP +A \fImemoryf\fP +function returns a pointer to a memory segment on success, and \f5NULL\fP on failure. +When \fInsz >= 0\fP and \fIcsz > 0\fP, +the function first attempts to change the current segment \fIaddr\fP to fit \fInsz\fP +(for example, \fInsz == 0\fP means deleting the segment \fIaddr\fP). +If this attempt is successful, it should return \fIaddr\fP. +Otherwise, if \fInsz > csz\fP, the function may try to allocate a new segment +of size \fInsz-csz\fP. If successful, it should return the address of the new segment. +In all other cases, it should return NULL. +.PP +An \fIexceptf\fP +function is called for events identified by \fItype\fP, which is coded thus: +.TP +.MW VM_OPEN +This event is raised at the start of the process to open a new region. +Argument \fIobj\fP will be a pointer to an object of type \f5Void_t*\fP +initialized to NULL before the call. The return value of \fIexceptf\fP +is significant as follows: + +On a negative return value, \fIvmopen\fP will terminate with failure. + +On a zero return value, \fIexceptf\fP may set \f5*((Void_t**)obj)\fP +to some non-NULL value to tell \fIvmopen\fP +to allocate the region handle itself via \fImemoryf\fP. Otherwise, +the region handle will be allocated from the \f5Vmheap\fP region. + +On a positive return value, +the new region is being reconstructed +based on existing states of some previous region. +In this case, \fIexceptf\fP should set \f5*(Void_t**)\fP\fIobj\fP to point to +the field \f5Vmalloc_t.data\fP of the corresponding previous region +(see \f5VM_CLOSE\fP below). +If the handle of the previous region was allocated +via \fImemoryf\fP as discussed above in the case of the zero return value, +then it will be exactly restored. Otherwise, a new handle will be allocated from \f5Vmheap\fP. +The ability to create regions sharing the same states allows for +managing shared and/or persistent memory. +.TP +.MW VM_ENDOPEN +This event is raised at the end of the process to open a new region. +The return value of \fIexceptf\fP will be ignored. +.TP +.MW VM_CLOSE +This event is raised at the start of the process to close a region, +The return value of \fIexceptf\fP is significant as follows: + +On a negative return value, \fIvmclose\fP immediately returns with failure. + +On a zero return value, \fIvmclose\fP proceeds normally by calling \f5memoryf\fP to free +all allocated memory segments and also freeing the region itself. + +On a positive return value, \fIvmclose\fP will only free the region +without deallocating the associated memory segments. That is, +the field \fIVmalloc_t.data\fP of the region handle remains intact. +This is useful for managing shared and/or persistent memory (see \f5VM_OPEN\fP above). +.TP +.MW VM_ENDCLOSE +This event is raised at the end of the process to close a region. +The return value of \fIexceptf\fP will be ignored. +.TP +.MW VM_NOMEM +An attempt to extend the region by the amount +\f5(size_t)\fP\fIobj\fP failed. The region is unlocked, so the +\fIexceptf\fP function may free blocks. +If the function returns a positive value the memory +request will be repeated. +.TP +.MW VM_DISC +The discipline structure is being changed. + +.SS "Allocation methods" +Methods are of type \f5Vmethod_t*\fP. +.TP +.MW Vmbest +An approximately best-fit allocation strategy. +.TP +.MW Vmlast +A strategy for building structures that are only deleted in whole. +Only the latest allocated block can be freed. +This means that as soon as a block \f5a\fP is allocated, +\fIvmfree\fP calls on blocks other than \c5a\fP are ignored. +.TP +.MW Vmpool +A strategy for blocks of one size, +set by the first \fIvmalloc\fP call after \fIvmopen\fP or \fIvmclear\fP. +.TP +.MW Vmdebug +An allocation strategy with extra-stringent checking and locking. +It is useful for finding misuses of dynamically allocated +memory, such as writing beyond the boundary of a block, or +freeing a block twice. +.ne 3 +.TP +.MW Vmprofile +An allocation method that records and prints summaries of memory usage. + +.SS Debugging +The method \f5Vmdebug\fP is used to debug common memory violation problems. +When a problem is found, +a warning message is written to file descriptor 2 (standard error). +In addition, if flag \f5VM_DBABORT\fP is on, +the program is terminated by calling \fIabort\fP(2). +Each message is a line of self-explanatory fields separated by colons. +The optional flag \f5-DVMFL\fP, if used during compilation, +enables recording of file names and line numbers. +The following functions work with method \f5Vmdebug\fP. +.PP +.I vmdebug +resets the file descriptor to write out warnings to the given argument. +By default, this file descriptor is 2, the standard error. +\fIvmdebug\fP returns the previous file descriptor. +.PP +.I vmdbcheck +checks a region using \f5Vmdebug\fP or \f5Vmbest\fP for integrity. +If \f5Vmdebug\fP, this also checks for block overwriting errors. +On errors, \fIvmdbwarn\fP is called. +If flag \f5VM_DBCHECK\fP is on, +\fIvmdbcheck\fP is called at each invocation of +\fIvmalloc\fP, \fIvmfree\fP, or \fIvmresize\fP. +.PP +.I vmdbwatch +causes address \fIaddr\fP +to be watched, and reported whenever met in +\fIvmalloc\fP, \fIvmresize\fP or \fIvmfree\fP. +The watch list has finite size and if it becomes full, +watches will be removed in a first-in-first-out fashion. +If \fIaddr\fP is \f5NULL\fP, +all current watches are canceled. +\fIvmdbwatch\fP returns the watch bumped out due to an insertion +into a full list or \f5NULL\fP otherwise. +.PP +.I vmdbwarn +is an internal function that processes +warning messages for discovered errors. +It can't be called from outside the \fIvmalloc\fP package, +but is a good place to plant debugger traps because +control goes there at every trouble. + +.SS "Profiling" +The method \f5Vmprofile\fP is used to profile memory usage. +Profiling data are maintained in private memory of a process so +\f5Vmprofile\fP should be avoided from regions manipulating +persistent or shared memory. +The optional flag \f5-DVMFL\fP, if used during compilation, +enables recording of file names and line numbers. +.PP +.I vmprofile +prints memory usage summary. +The summary is restricted to region \fIvm\fP if \fIvm\fP is not \f5NULL\fP; +otherwise, it is for all regions created with \f5Vmprofile\fP. +Summary records are written to file descriptor \fIfd\fP as lines with +colon-separated fields. Here are some of the fields: +.TP +.I n_alloc,n_free: +Number of allocation and free calls respectively. Note that a resize +operation is coded as a free and an allocation. +.TP +.I s_alloc,s_free: +Total amounts allocated and freed. The difference between these numbers +is the amount of space not yet freed. +.TP +.I max_busy, extent: +These fields are only with the summary record for region. +They show the maximum busy space at any time and the extent of the region. + +.SS "Information and statistics" +.I vmbusy +returns the busy status of a region. +A region is busy if some allocation operation is accessing it. +.PP +.I vmregion +returns the region to which the block pointed to by +\fIaddr\fP belongs. +This works only in regions that allocate with +\f5Vmbest\fP, \f5Vmdebug\fP or \f5Vmprofile\fP. +.PP +.I vmsegment +finds if some segment of memory in \fIregion\fP +contains the address \fIaddr\fP. +It returns the address of a found segment or \f5NULL\fP if none found. +.PP +.I vmwalk +walks all segments in \fIregion\fP or if \fIregion\fP is \f5NULL\fP, +all segments in all regions. +At each segment, \fI(*walkf)(vm,addr,size,disc)\fP +is called where \fIvm\fP is the region, \fIaddr\fP is the segment, +\fIsize\fP is the size of the segment, and \fIdisc\fP is the region's discipline. +If \fIwalkf\fP returns a negative value, the walk stops and returns the same value. +On success, \fIvmwalk\fP returns 0; otherwise, it returns \-1. +.PP +.I vmaddr +checks whether \fIaddr\fP +points to an address within some allocated block of the given region. +If not, it returns \-1. +If so, it returns the offset from the beginning of the block. +The function does not work for a \f5Vmlast\fP region except +on the latest allocated block. +.PP +.I vmsize +returns the size of the allocated block pointed to by \fIaddr\fP. +It returns \-1 if \fIaddr\fP +does not point to a valid block in the region. +Sizes may be padded beyond that requested; in +particular no block has size 0. +The function does not work for a \f5Vmlast\fP region except +on the latest allocated block. +.PP +.I vmstat +gathers statistics on the given \fIregion\fP. +If \f5region\fP is NULL, it computes statistics for the \fIMalloc\fP calls. +This may include summing statistics from more than one regions constructed to avoid blocking +due to parallel or asynchronous operations. +If \fIstatb\fP is not NULL, \fIvmstat\fP computes and stores the statistics in \fIstatb\fP then returns 0. +If \fIstatb\fP is NULL, no statistics will be computed and +the returned value is either 1 if the region is busy, i.e., +being accessed by some allocation call or 0 otherwise. + +A \f5Vmstat_t\fP structure has at least these members: +.in +.5i +.nf +.ta \w'\f5size_t \fP'u +\w'\f5extent \fP'u +.MW "int n_busy; /* # of busy blocks */ +.MW "int n_free; /* # of free blocks */ +.MW "size_t s_busy; /* total busy space */ +.MW "size_t s_free; /* total free space */ +.MW "size_t m_busy; /* maximum busy block size */ +.MW "size_t m_free; /* maximum free block size */ +.MW "int n_seg; /* count of segments */ +.MW "size_t extent; /* memory extent of region */ +.MW "int n_region; /* total Malloc regions */ +.MW "int n_open; /* non-blocked operations */ +.MW "int n_lock; /* blocked operations */ +.MW "int n_probe; /* region searches */ +.fi +.in -.5i +.PP +Bookeeping overhead is counted in \f5extent\fP, +but not in \f5s_busy\fP or \f5s_free\fP. +.PP +.I vmtrace +establishes file descriptor \fIfd\fP +as the trace file and returns +the previous value of the trace file descriptor. +The trace descriptor is initially invalid. +Output is sent to the trace file by successful allocation +events when flag \f5VM_TRACE\fP is on. +.PP +Tools for analyzing traces are described in \fImtreplay\fP(1). +The trace record for an allocation event +is a line with colon-separated fields, four numbers and one string. +.TP +.I old +Zero for a fresh allocation; +the address argument for freeing and resizing. +.TP +.I new +Zero for freeing; +the address returned by allocation or resizing. +.TP +.I size +The size argument for allocation or resizing; +the size freed by freeing. +Sizes may differ due to padding for alignment. +.TP +.I region +The address of the affected region. +.TP +.I method +A string that tells the region's method: +\f5best\fP, \f5last\fP, \f5pool\fP, \f5profile\fP, or \f5debug\fP. +.PP +.I vmtrbusy +outputs a trace of all currently busy blocks in region \f5vm\fP. +This only works with the \f5Vmbest\fP, \f5Vmdebug\fP and \f5Vmprofile\fP methods. +.PP +.I vmdata +returns the core data of the given region. +The core data hold the data structures for allocated and free blocks. +Depending on the region discipline, +the core data of a region may be in shared or persistent memory even +if the region pointer created with \fIvmopen\fP is always in private process memory. + +.SS "Malloc-compatible functions" +This set of functions implement \fImalloc\fP(3). +They allocate via the \fIVmregion\fP region which is initially set +to be \fIVmheap\fP. + +Concurrent accesses are supported unless an application +change \fIVmregion\fP to something other than \fIVmheap\fP. +New regions may be created on the fly to avoid blocking. +The maximum number of regions that can be created +this way is set to 64 by default. An application could +reduce this number by calling \fIsetregmax(regmax)\fP to +set the maximum number of these extra regions to \fIregmax\fP. +\fIsetregmax()\fP always returns the previous value. +.PP +These functions are instrumented for run-time debugging, profiling and tracing. +For accurate reporting of files and line numbers, +application code should include \f5vmalloc.h\fP and compile with \f5-DVMFL\fP. +The following environment variables can be set before any memory allocation +(e.g., before a process starts) to drive different modes: +.TP +.I VMETHOD +This defines the method to use for allocation. +Its value should be one of the strings: +\fIVmbest, Vmdebug, Vmprofile, Vmlast, Vmpool\fP. +The 'V' can be in lower case. +.TP +.I VMDEBUG +This is ignored if +a method other than \f5Vmdebug\fP has been selected with \fIVMETHOD\fP. +\fIVMDEBUG\fP can be any combination of `a', +a decimal number and a list of hexadecimal numbers. +`a' causes the program to abort on any discovered allocation error. +A hexadecimal number starts with either \fI0x\fP or \fI0X\fP +and defines an address to watch (see \fIvmdbwatch\fP). +Any other number is taken to be decimal and defines a period \fIp\fP +to check the arena for integrity. The default period is 1, ie, the +arena is checked on every call to a \fImalloc\fP function. +Other letters not part of the defined set are ignored. +.TP +.I VMPROFILE +This is ignored if a method other than \f5Vmprofile\fP +has been selected by \fIVMETHOD\fP or \fIVMDEBUG\fP. +\fIVMPROFILE\fP defines a file name to store profile data. +Each instance of the pattern `%p' found in \fIVMPROFILE\fP +is transformed to the process id of the running process. +If the file cannot be created, file descriptor 2 (standard error) +is used for output. +.TP +.I VMTRACE +If this defines a valid writable file, trace messages of all allocation calls +are written to the given file (see \fIvmopen()\fP and \fIvmtrace()\fP). +Similar to \fIVMPROFILE\fP, each instance of the pattern `%p' found +in \fIVMTRACE\fP is turned to the process id of the running process. + +.SH RECENT CHANGES +\f5Vmlast\fP: allocated blocks are now allowed to be resized (09/1998). + +.SH SEE ALSO +\fImtreplay\fP(1), \fImalloc\fP(3). + +.SH AUTHOR +Kiem-Phong Vo, kpv@research.att.com |