chiark / gitweb /
New manual page.
authormdw <mdw>
Fri, 22 Oct 1999 22:41:20 +0000 (22:41 +0000)
committermdw <mdw>
Fri, 22 Oct 1999 22:41:20 +0000 (22:41 +0000)
man/darray.3 [new file with mode: 0644]
man/trace.3 [new file with mode: 0644]

diff --git a/man/darray.3 b/man/darray.3
new file mode 100644 (file)
index 0000000..76b0ced
--- /dev/null
@@ -0,0 +1,400 @@
+.\" -*-nroff-*-
+.de VS
+.sp 1
+.RS
+.nf
+.ft B
+..
+.de VE
+.ft R
+.fi
+.RE
+.sp 1
+..
+.de hP
+.IP
+.ft B
+\h'-\w'\\$1\ 'u'\\$1\ \c
+.ft P
+..
+.ie t .ds o \(bu
+.el .ds o o
+.TH darray 3 "21 October 1999" mLib
+.SH "NAME"
+darray \- dense, dynamically resizing arrays
+.\" @DA_INIT
+.\" @DA_DECL
+.\" @DA_CREATE
+.\" @DA_DESTROY
+.\" @DA_ENSURE
+.\" @DA_SHUNT
+.\" @DA_TIDY
+.\" @DA
+.\" @DA_LEN
+.\" @DA_SPARE
+.\" @DA_OFFSET
+.\" @DA_INCLUDE
+.\" @DA_EXTEND
+.\" @DA_UNSAFE_EXTEND
+.\" @DA_SLIDE
+.\" @DA_UNSAFE_SLIDE
+.\" @DA_PUSH
+.\" @DA_POP
+.\" @DA_UNSHIFT
+.\" @DA_SHIFT
+.\" @DAEXC_UFLOW
+.\" @DAEXC_OFLOW
+.\" @da_ensure
+.\" @da_shunt
+.\" @da_tidy
+.SH "SYNOPSIS"
+.nf
+.B "#include <mLib/darray.h>"
+
+.BI DA_DECL( atype ", " type );
+.IB atype " " a " = DA_INIT;"
+.BI "void DA_CREATE(" atype " *" a );
+.BI "void DA_DESTROY(" atype " *" a );
+
+.BI "void DA_ENSURE(" atype " *" a ", size_t " n );
+.BI "void DA_SHUNT(" atype " *" a ", size_t " n );
+.BI "void DA_TIDY(" atype " *" a );
+
+.IB type " *DA(" atype " *" a );
+.BI "size_t DA_LEN(" atype " *" a );
+.BI "size_t DA_SPARE(" atype " *" a );
+.BI "size_t DA_OFFSET(" atype " *" a );
+.BI "void DA_INCLUDE(" atype " *" a ", size_t " i );
+.BI "void DA_EXTEND(" atype " *" a ", long " n );
+.BI "void DA_UNSAFE_EXTEND(" atype " *" a ", long " n );
+.BI "void DA_SLIDE(" atype " *" a ", long " n );
+.BI "void DA_UNSAFE_SLIDE(" atype " *" a ", long " n );
+
+.BI "void DA_PUSH(" atype " *" a ", " type " " x );
+.IB type " DA_POP(" atype " *" a );
+.BI "void DA_UNSHIFT(" atype " *" a ", " type " " x );
+.IB type " DA_SHIFT(" atype " *" a );
+
+.BI "void *da_ensure(da_base *" b ", void *" v ", size_t " sz ", size_t " n );
+.BI "void *da_shunt(da_base *" b ", void *" v ", size_t " sz ", size_t " n );
+.BI "void *da_tidy(da_base *" b ", void *" v ", size_t " sz );
+.fi
+.SH "DESCRIPTION"
+The
+.B <mLib/darray.h>
+declares a collection of types, macros and functions which implement
+dynamically resizing arrays.
+.PP
+The macros described here may evaluate their arguments multiple times
+unless otherwise specified.
+.SS "Creation and destruction"
+Each element type must have its own array
+type declared using the
+.B DA_DECL
+macro.  Calling
+.VS
+.BI DA_DECL( atype ", " type );
+.VE
+Declares a new dynamic array type
+.I atype
+whose elements have type
+.IR type .
+.PP
+The macro
+.B DA_INIT
+is a valid static initializer for all types of dynamic arrays.  For
+cases where this isn't appropriate, a dynamic array may be initialized
+using the macro
+.BR DA_INIT ,
+passing it the address of the array.
+.PP
+Arrays may be disposed of using the
+.B DA_DESTROY
+macro, which again takes the address of the array.
+.SS "Storage allocation"
+.PP
+Space for new array elements may be reserved using the
+.B DA_ENSURE
+and
+.B DA_SHUNT
+macros, which reserve space at the end and beginning of the array
+respectively.  Both macros take two arguments: the address of an array
+object and the number of spare elements required.
+.PP
+Neither of these macros actually extends the array; both merely allocate
+memory for the array to extend itself into.  Use the macros
+.B DA_EXTEND
+and
+.B DA_SLIDE
+to actually increase the bounds of the array.
+.PP
+Note that when space is reserved, all the array elements might move.
+You should be careful not to depend on the addresses of array elements.
+If sufficient storage cannot be allocated, the exception
+.B EXC_NOMEM
+is thrown (see
+.BR exc (3)).
+.PP
+The macro
+.B DA_TIDY
+takes one argument: the address of a dynamic array.  It minimizes the
+amount of memory used by the array.  This is a useful function to call
+when the array's size has finally settled down.
+.SS "Accessing array elements"
+If
+.I a
+is the address of a dynamic array object, then
+.BI DA( a )
+is the base address of the actual array.  The elements are stored
+contiguously starting at this address.  An element at index
+.I i
+may be referenced using the syntax
+.BI DA( a )[ i \fR.
+.PP
+The number of elements in the array
+.I a
+is given by
+.BI DA_LEN( a )\fR.
+An integer array index
+.I i
+is
+.I valid
+if 0 \(<=
+.I i
+<
+.BI DA_LEN( a )\fR.
+.PP
+There may be some spare slots at the end of the array.  In particular,
+after a call to
+.BI DA_ENSURE( a ", " n )
+there will be at least
+.I n
+spare slots.  The number of spare slots at the end of the array may be
+obtained as
+.BI DA_SPARE( a )\fR.
+.PP
+Similarly, there may be spare slots before the start of the array.  In
+particular, after a call to
+.BI DA_SHUNT( a ", " n )
+there will be at least
+.I n
+spare slots.  The number of spare slots before the start of the array
+may be obtained as
+.BI DA_OFFSET( a )\fR.
+.PP
+The call
+.BI DA_INCLUDE( a ", " i )
+ensures that the array's bounds include the index
+.I i
+by extending the array if necessary.  The exception
+.B EXC_NOMEM
+is thrown if there isn't enough memory to do this.
+.PP
+The array's bounds may be extended by
+.I n
+slots by calling
+.BI DA_EXTEND( a ", " n )\fR.
+The integer
+.I n
+must be less than
+.BI DA_SPARE( a )\fR;
+if this is not the case then the exception
+.B DAEXC_OFLOW
+is thrown.
+Note that
+.I n
+may be negative to reduce the bounds of the array: in this case it must
+be greater than
+.BI \-DA_LEN( a )
+or the exception
+.B DAEXC_UFLOW
+is thrown.  The macro
+.B DA_UNSAFE_EXTEND
+does the same job, but performs no error checking.
+.PP
+The macro
+.BI DA_SLIDE( a ", " n )
+offsets the array elements by
+.IR n .
+If
+.I n
+is positive, the array elements are slid upwards, to higher-numbered
+indices; if
+.I n
+is negative, the elements are slid downwards.  Precisely, what happens
+is that elements which used to have index
+.I i
+\-
+.I n
+now have index
+.IR i .
+The exception
+.B DAEXC_OFLOW
+is thrown if
+.I n
+>
+.BI DA_OFFSET( a )\fR;
+.B DAEXC_UFLOW
+is thrown if
+.I n
+<
+.BI \-DA_LEN( a )\fR.
+The macro
+.B DA_UNSAFE_SLIDE
+does the same job, only without the error checking.
+.SS "Stack operations"
+Dynamic arrays support Perl-like stack operations.  Given an array
+(pointer)
+.I a
+and an object of the array's element type
+.I x
+the following operations are provided:
+.TP
+.BI DA_PUSH( a ", " x )
+Add
+.I x
+to the end of the array, increasing the array size by one.
+.TP
+.IB x " = DA_POP(" a )
+Remove the final element of the array, assigning
+.I x
+its value and decreasing the array size by one.
+.TP
+.BI DA_UNSHIFT( a ", " x )
+Insert
+.I x
+at the beginning of the array, shifting all the elements up one place
+and increasing the array size by one.
+.TP
+.IB x " = DA_SHIFT(" a )
+Remove the first element of the array, assigning
+.I x
+its value, shifting all the subsequent array items down one place and
+decreasing the array size by one.
+.PP
+The operations
+.B DA_PUSH
+and
+.B DA_UNSHIFT
+can fail due to lack of memory, in which case
+.B EXC_NOMEM
+is thrown.  The operations
+.B DA_POP
+and
+.B DA_SHIFT
+can fail because the array is empty, in which case
+.B DAEXC_UFLOW
+is thrown.
+.SS "Low-level details"
+This section describes low-level details of the dynamic array
+implementation.  You should try to avoid making use of this information
+if you can, since the interface may change in later library versions.
+In particular, more subtleties may be added which low-level access will
+miss.
+.PP
+Dynamic arrays are structures with the format
+.VS
+.BI "typedef struct " atype " {"
+.B "  da_base b;"
+.BI "  " type " *v;"
+.BI "} " atype ";"
+.VE
+The pointer
+.B v
+indicates the current base of the array.  This will move in the
+allocated space as a result of
+.B DA_SHIFT
+and
+.B DA_UNSHIFT
+(and
+.BR DA_SLIDE )
+operations.
+.PP
+The
+.B da_base
+structure contains the following elements:
+.TP
+.B "size_t sz"
+The number of allocated slots from
+.B v
+onwards.
+.TP
+.B "size_t len"
+The number of items considered to be in the array.  The allocated space
+is usually larger than this.
+.TP
+.B "size_t off"
+The number of allocated slots preceding
+.BR v .
+The total number of allocated items is therefore
+.B sz
++
+.BR off .
+.TP
+.B "unsigned push"
+The number of items pushed or ensured since the last array expansion.
+.TP
+.B "unsigned unshift"
+The number of items unshifted or shunted since the last array expansion.
+.PP
+The
+.B push
+and
+.B unshift
+members are used by the expansion routines to decide how to allocate
+free space before and after the array elements following a reallocation.
+The other members should be fairly self-explanatory.
+.PP
+The reallocation routines
+.BR da_ensure ,
+.B da_shunt
+and
+.B da_tidy
+have a regular interface.  They're a bit
+strange, though, because they have to deal with lots of different types
+of arrays.  The arguments they take are:
+.TP
+.BI "da_base *" b
+Pointer to the
+.B da_base
+member of the array block.
+.TP
+.BI "void *" v
+The array base pointer from the array block (i.e., the
+.B v
+member).
+.TP
+.BI "size_t " sz
+The element size for the array.
+.TP
+.BI "size_t " n
+(For
+.B da_ensure
+and
+.B da_shunt
+only.)  The number of spare slots required.
+.PP
+The functions may modify the base structure, and return a newly
+allocated (or at least repositioned) array base pointer, or throw
+.B EXC_NOMEM
+if there's not enough memory.
+.PP
+The three functions behave as follows:
+.TP
+.B da_ensure
+Ensure that there are at least
+.I n
+spare slots after the end of the array.
+.TP
+.B da_shunt
+Ensure that there are at least
+.I n
+spare slots preceding the start of the array.
+.TP
+.B da_tidy
+Reallocate the array to use the smallest amount of memory possible.
+.SH "SEE ALSO"
+.BR exc (3),
+.BR mLib (3).
+.SH "AUTHOR"
+Mark Wooding, <mdw@nsict.org>
diff --git a/man/trace.3 b/man/trace.3
new file mode 100644 (file)
index 0000000..68d87ad
--- /dev/null
@@ -0,0 +1,162 @@
+.\" -*-nroff-*-
+.TH trace 3 "21 October 1999" mLib
+.SH "NAME"
+trace \- configurable tracing output
+.\" @trace
+.\" @trace_block
+.\" @trace_on
+.\" @trace_level
+.\" @tracing
+.\" @traceopt
+.\" @NTRACE
+.\" @T
+.\" IF_TRACING
+.SH "SYNOPSIS"
+.nf
+.B "#include <mLib/trace.h>"
+
+.BI "void trace(unsigned " l ", const char *" f ", ...);"
+.BI "void trace_block(unsigned " l ", const char *" s ,
+.BI "                 const void *" b ", size_t " sz );
+
+.BI "void trace_on(FILE *" fp ", unsigned " l );
+.BI "void trace_level(unsigned " l );
+.BI "unsigned tracing(void);"
+
+.BI "unsigned traceopt(trace_opt *" t ", const char *" p ,
+.BI "                  unsigned " f ", unsigned " bad );
+
+.BI T( statements\fR... )
+.BI "IF_TRACING(unsigned " l ", " statements\fR... )
+.fi
+.SH "DESCRIPTION"
+The
+.B <mLib/trace.h>
+header declares some functions and macros for handling trace output.
+The emphasis for this system is primarily on user configurability of
+what gets traced rather than where the output goes.  That's a project
+for later.
+.SS "Trace levels"
+Each trace message is assigned a
+.I level
+by the programmer.  A tracing level is set during program
+initialization, usually by the user.  A trace message is output if there
+is a trace destination set, and the result of a bitwise AND between the
+message level and the overall tracing level is nonzero.  The idea is
+that the programmer assigns a different bit to each group of trace
+messages, and allows a user to select which ones are wanted.
+.SS "Producing trace output"
+The basic function is
+.BR trace .
+It is passed an integer message level and a
+.BR printf (3)-style
+format string together with arguments for the placeholders and emits the
+resulting message.
+.PP
+The function
+.B trace_block
+formats an arbitrary block of memory as a hex dump.  The arguments are,
+in order, the message level, a pointer to the header string for the hex
+dump, the base address of the block to dump, and the size of the block
+in bytes.
+.SS "Configuring trace output"
+The tracing destination is set with the function
+.BR trace_on :
+it is passed a
+.B stdio
+stream and a trace level to set.  The stream may be null to disable
+tracing completely (which is the default).  The trace level may be set
+on its own using
+.BR trace_level ,
+which takes the new level as its single argument.  The function
+.B tracing
+returns the current trace level, or zero if there is no trace
+destination set.
+.SS "Parsing user trace options"
+The function
+.B traceopt
+may be used to allow a user to set the trace level.  It is passed a
+table describing the available trace level bits, and some other
+information, and returns a new trace level.  The table consists of a
+number of
+.B trace_opt
+structures, each of which describes a bit or selection of bits which may
+be controlled.  The structure contains the following members, in order:
+.TP
+.B "char ch;"
+The character used to select this bit or collection of bits.
+.TP
+.B "unsigned f;"
+The level bits for this option.
+.TP
+.B "const char *help;"
+A help string describing this option.
+.PP
+The table is terminated by an entry whose
+.B ch
+member is zero.
+.PP
+The arguments to
+.B traceopt
+are:
+.TP
+.BI "trace_opt *" t
+Pointer to the trace options table.
+.TP
+.BI "const char *" p
+Pointer to the user's option string.
+.TP
+.BI "unsigned " f
+The default trace options, or the previously-set options.
+.TP
+.BI "unsigned " bad
+A bitmask of level bits which should be disallowed.
+.PP
+If the option string
+.I p
+is a null pointer or contains only a
+.RB ` ? '
+character, a help message is printed and the default is returned.  Only
+trace options which contain non-bad bits are displayed.  Otherwise the
+string contains option characters together with
+.RB ` + '
+and
+.RB ` \- '
+which respectively turn on or off the following options; the default is
+to turn options on.  Again, only options which contain non-bad bits are
+allowed.
+.PP
+The `bad bit' mechanism is provided for setuid programs which in their
+normal configuration deal with privileged information which mustn't be
+given out to users.  However, if run by someone with appropriate
+privilege such options are safe and may be useful for debugging.  The
+program can set the
+.I bad
+mask to prevent access to secret information when running setuid, or to
+zero when not.
+.SS "Macro support for tracing"
+The tracing macros are intended to make insertion of tracing information
+unobtrusive and painless.  If the
+.B NTRACE
+macro is defined, all of the tracing macros are disabled and generate no
+code; otherwise they do their normal jobs.
+.PP
+The
+.B T
+macro simply expands to its argument.  It may be wrapped around small
+pieces of code which is only needed when compiling with tracing
+enabled.  (Larger blocks, of course, should use
+.RB ` #ifndef NTRACE '/` #endif '
+pairs for clarity's sake.)
+.PP
+For slightly larger code chunks which do some processing to generate
+trace output, the
+.B IF_TRACING
+macro is useful.  Its first argument is a message level; if the trace
+level is set such that the message will be printed, the code in the
+second argument is executed.  If code is being compiled without tracing,
+of course, the entire contents of the macro is ignored.
+.SH "SEE ALSO"
+.BR mLib (3).
+.SH "AUTHOR"
+Mark Wooding, <mdw@nsict.org>