Initial revision
This commit is contained in:
parent
5f7d5e8d18
commit
b2cfc4e2e7
242 changed files with 18177 additions and 0 deletions
346
man/man3/fmtinstall.3
Normal file
346
man/man3/fmtinstall.3
Normal file
|
|
@ -0,0 +1,346 @@
|
|||
.TH FMTINSTALL 3
|
||||
.de EX
|
||||
.nf
|
||||
.ft B
|
||||
..
|
||||
.de EE
|
||||
.fi
|
||||
.ft R
|
||||
..
|
||||
.SH NAME
|
||||
fmtinstall, dofmt, fmtprint, fmtvprint, fmtstrcpy, fmtfdinit, fmtfdflush, fmtstrinit, fmtstrflush \- support for user-defined print formats and output routines
|
||||
.SH SYNOPSIS
|
||||
.B #include <fmt.h>
|
||||
.PP
|
||||
.ft L
|
||||
.nf
|
||||
.ta \w' 'u +\w' 'u +\w' 'u +\w' 'u +\w' 'u
|
||||
typedef struct Fmt Fmt;
|
||||
struct Fmt{
|
||||
void *start; /* of buffer */
|
||||
void *to; /* current place in the buffer */
|
||||
void *stop; /* end of the buffer; overwritten if flush fails */
|
||||
int (*flush)(Fmt*); /* called when to == stop */
|
||||
void *farg; /* to make flush a closure */
|
||||
int nfmt; /* num chars formatted so far */
|
||||
va_list args; /* args passed to dofmt */
|
||||
int r; /* % format character */
|
||||
int width;
|
||||
int prec;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
enum{
|
||||
FmtWidth = 1,
|
||||
FmtLeft = FmtWidth << 1,
|
||||
FmtPrec = FmtLeft << 1,
|
||||
FmtSharp = FmtPrec << 1,
|
||||
FmtSpace = FmtSharp << 1,
|
||||
FmtSign = FmtSpace << 1,
|
||||
FmtZero = FmtSign << 1,
|
||||
FmtUnsigned = FmtZero << 1,
|
||||
FmtShort = FmtUnsigned << 1,
|
||||
FmtLong = FmtShort << 1,
|
||||
FmtVLong = FmtLong << 1,
|
||||
FmtComma = FmtVLong << 1,
|
||||
FmtByte = FmtComma << 1,
|
||||
FmtLDouble = FmtByte << 1,
|
||||
|
||||
FmtFlag = FmtLDouble << 1
|
||||
};
|
||||
.fi
|
||||
.PP
|
||||
.B
|
||||
.ta \w'\fLchar* 'u
|
||||
|
||||
.PP
|
||||
.B
|
||||
int fmtfdinit(Fmt *f, int fd, char *buf, int nbuf);
|
||||
.PP
|
||||
.B
|
||||
int fmtfdflush(Fmt *f);
|
||||
.PP
|
||||
.B
|
||||
int fmtstrinit(Fmt *f);
|
||||
.PP
|
||||
.B
|
||||
char* fmtstrflush(Fmt *f);
|
||||
.PP
|
||||
.B
|
||||
int fmtinstall(int c, int (*fn)(Fmt*));
|
||||
.PP
|
||||
.B
|
||||
int dofmt(Fmt *f, char *fmt);
|
||||
.PP
|
||||
.B
|
||||
int fmtprint(Fmt *f, char *fmt, ...);
|
||||
.PP
|
||||
.B
|
||||
int fmtvprint(Fmt *f, char *fmt, va_list v);
|
||||
.PP
|
||||
.B
|
||||
int fmtrune(Fmt *f, int r);
|
||||
.PP
|
||||
.B
|
||||
int fmtstrcpy(Fmt *f, char *s);
|
||||
.SH DESCRIPTION
|
||||
The interface described here allows the construction of custom
|
||||
.IR print (3)
|
||||
verbs and output routines.
|
||||
In essence, they provide access to the workings of the formatted print code.
|
||||
.PP
|
||||
The
|
||||
.IR print (3)
|
||||
suite maintains its state with a data structure called
|
||||
.BR Fmt .
|
||||
A typical call to
|
||||
.IR print (3)
|
||||
or its relatives initializes a
|
||||
.B Fmt
|
||||
structure, passes it to subsidiary routines to process the output,
|
||||
and finishes by emitting any saved state recorded in the
|
||||
.BR Fmt .
|
||||
The details of the
|
||||
.B Fmt
|
||||
are unimportant to outside users, except insofar as the general
|
||||
design influences the interface.
|
||||
The
|
||||
.B Fmt
|
||||
records
|
||||
the verb being processed, its precision and width,
|
||||
and buffering parameters.
|
||||
Most important, it also records a
|
||||
.I flush
|
||||
routine that the library will call if a buffer overflows.
|
||||
When printing to a file descriptor, the flush routine will
|
||||
emit saved characters and reset the buffer; when printing
|
||||
to an allocated string, it will resize the string to receive more output.
|
||||
The flush routine is nil when printing to fixed-size buffers.
|
||||
User code need never provide a flush routine; this is done internally
|
||||
by the library.
|
||||
.SS Custom output routines
|
||||
To write a custom output routine, such as an error handler that
|
||||
formats and prints custom error messages, the output sequence can be run
|
||||
from outside the library using the routines described here.
|
||||
There are two main cases: output to an open file descriptor
|
||||
and output to a string.
|
||||
.PP
|
||||
To write to a file descriptor, call
|
||||
.I fmtfdinit
|
||||
to initialize the local
|
||||
.B Fmt
|
||||
structure
|
||||
.IR f ,
|
||||
giving the file descriptor
|
||||
.IR fd ,
|
||||
the buffer
|
||||
.IR buf ,
|
||||
and its size
|
||||
.IR nbuf .
|
||||
Then call
|
||||
.IR fmtprint
|
||||
or
|
||||
.IR fmtvprint
|
||||
to generate the output.
|
||||
These behave just like
|
||||
.B fprint
|
||||
(see
|
||||
.IR print (3))
|
||||
or
|
||||
.B vfprint
|
||||
except that the characters are buffered until
|
||||
.I fmtfdflush
|
||||
is called.
|
||||
A typical example of this sequence appears in the Examples section.
|
||||
.PP
|
||||
The same basic sequence applies when outputting to an allocated string:
|
||||
call
|
||||
.I fmtstrinit
|
||||
to initialize the
|
||||
.BR Fmt ,
|
||||
then call
|
||||
.I fmtprint
|
||||
and
|
||||
.I fmtvprint
|
||||
to generate the output.
|
||||
Finally,
|
||||
.I fmtstrflush
|
||||
will return the allocated string, which should be freed after use.
|
||||
Regardless of the output style or type,
|
||||
.I fmtprint
|
||||
or
|
||||
.I fmtvprint
|
||||
generates the characters.
|
||||
.SS Custom format verbs
|
||||
.I Fmtinstall
|
||||
is used to install custom verbs and flags labeled by character
|
||||
.IR c ,
|
||||
which may be any non-zero Unicode character.
|
||||
.I Fn
|
||||
should be declared as
|
||||
.IP
|
||||
.EX
|
||||
int fn(Fmt*)
|
||||
.EE
|
||||
.PP
|
||||
.IB Fp ->r
|
||||
is the flag or verb character to cause
|
||||
.I fn
|
||||
to be called.
|
||||
In
|
||||
.IR fn ,
|
||||
.IB fp ->width ,
|
||||
.IB fp ->prec
|
||||
are the width and precision, and
|
||||
.IB fp ->flags
|
||||
the decoded flags for the verb (see
|
||||
.IR print (3)
|
||||
for a description of these items).
|
||||
The standard flag values are:
|
||||
.B FmtSign
|
||||
.RB ( + ),
|
||||
.B FmtLeft
|
||||
.RB ( - ),
|
||||
.B FmtSpace
|
||||
.RB ( '\ ' ),
|
||||
.B FmtSharp
|
||||
.RB ( # ),
|
||||
.B FmtComma
|
||||
.RB ( , ),
|
||||
.B FmtLong
|
||||
.RB ( l ),
|
||||
.B FmtShort
|
||||
.RB ( h ),
|
||||
.B FmtByte
|
||||
.RB ( hh ),
|
||||
.B FmtUnsigned
|
||||
.RB ( u ),
|
||||
.B FmtLDouble
|
||||
.RB ( L ),
|
||||
and
|
||||
.B FmtVLong
|
||||
.RB ( ll ).
|
||||
The flag bits
|
||||
.B FmtWidth
|
||||
and
|
||||
.B FmtPrec
|
||||
identify whether a width and precision were specified.
|
||||
.PP
|
||||
.I Fn
|
||||
is passed a pointer to the
|
||||
.B Fmt
|
||||
structure recording the state of the output.
|
||||
If
|
||||
.IB fp ->r
|
||||
is a verb (rather than a flag),
|
||||
.I fn
|
||||
should use
|
||||
.B Fmt->args
|
||||
to fetch its argument from the list,
|
||||
then format it, and return zero.
|
||||
If
|
||||
.IB fp ->r
|
||||
is a flag,
|
||||
.I fn
|
||||
should return a negative value:
|
||||
the negation of one of the above flag values, or some otherwise unused power of two.
|
||||
All interpretation of
|
||||
.IB fp ->width\f1,
|
||||
.IB fp ->prec\f1,
|
||||
and
|
||||
.IB fp-> flags
|
||||
is left up to the conversion routine.
|
||||
.I Fmtinstall
|
||||
returns 0 if the installation succeeds, \-1 if it fails.
|
||||
.PP
|
||||
.IR Fmtprint
|
||||
and
|
||||
.IR fmtvprint
|
||||
may be called to
|
||||
help prepare output in custom conversion routines.
|
||||
However, these functions clear the width, precision, and flags.
|
||||
The function
|
||||
.I dofmt
|
||||
is the underlying formatter; it
|
||||
uses the existing contents of
|
||||
.B Fmt
|
||||
and should be called only by sophisticated conversion routines.
|
||||
All these routines return the number of characters
|
||||
produced.
|
||||
.PP
|
||||
Some internal functions may be useful to format primitive types.
|
||||
They honor the width, precision and flags as described in
|
||||
.IR print (3).
|
||||
.I Fmtrune
|
||||
formats a single character
|
||||
.BR r .
|
||||
.I Fmtstrcpy
|
||||
formats a string
|
||||
.BR s .
|
||||
All these routines return zero for successful execution.
|
||||
.SH EXAMPLES
|
||||
This function prints an error message with a variable
|
||||
number of arguments and then quits.
|
||||
Compared to the corresponding example in
|
||||
.IR print (3),
|
||||
this version uses a smaller buffer, will never truncate
|
||||
the output message, but might generate multiple
|
||||
.B write
|
||||
system calls to produce its output.
|
||||
.IP
|
||||
.EX
|
||||
.ta 6n +6n +6n +6n +6n +6n +6n +6n +6n
|
||||
|
||||
void fatal(char *fmt, ...)
|
||||
{
|
||||
Fmt f;
|
||||
char buf[64];
|
||||
va_list arg;
|
||||
|
||||
fmtfdinit(&f, 1, buf, sizeof buf);
|
||||
fmtprint(&f, "fatal: ");
|
||||
va_start(arg, fmt);
|
||||
fmtvprint(&f, fmt, arg);
|
||||
va_end(arg);
|
||||
fmtprint(&f, "\en");
|
||||
fmtfdflush(&f);
|
||||
exits("fatal error");
|
||||
}
|
||||
.EE
|
||||
.PP
|
||||
This example adds a verb to print complex numbers.
|
||||
.IP
|
||||
.EX
|
||||
typedef
|
||||
struct {
|
||||
double r, i;
|
||||
} Complex;
|
||||
|
||||
int
|
||||
Xfmt(Fmt *f)
|
||||
{
|
||||
Complex c;
|
||||
|
||||
c = va_arg(f->args, Complex);
|
||||
return fmtprint(f, "(%g,%g)", c.r, c.i);
|
||||
}
|
||||
|
||||
main(...)
|
||||
{
|
||||
Complex x;
|
||||
|
||||
x.r = 1.5;
|
||||
x.i = -2.3;
|
||||
|
||||
fmtinstall('X', Xfmt);
|
||||
print("x = %X\en", x);
|
||||
}
|
||||
.EE
|
||||
.SH SEE ALSO
|
||||
.IR print (3)
|
||||
.SH HISTORY
|
||||
This formatted print library originally
|
||||
appeared as part of the Plan 9 C library.
|
||||
.SH BUGS
|
||||
The Plan 9 version supports Unicode strings and produces UTF output.
|
||||
This version assumes that characters are always represented by 1-byte values.
|
||||
Loading…
Add table
Add a link
Reference in a new issue