mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
346 lines
7 KiB
Groff
346 lines
7 KiB
Groff
.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.
|