123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- .TH FMTINSTALL 2
- .SH NAME
- fmtinstall, dofmt, dorfmt, fmtprint, fmtvprint, fmtrune, fmtstrcpy, fmtrunestrcpy, fmtfdinit, fmtfdflush, fmtstrinit, fmtstrflush, runefmtstrinit, runefmtstrflush, errfmt \- support for user-defined print formats and output routines
- .SH SYNOPSIS
- .B #include <u.h>
- .br
- .B #include <libc.h>
- .PP
- .ft L
- .nf
- .ta \w' 'u +\w' 'u +\w' 'u +\w' 'u +\w' 'u
- typedef struct Fmt Fmt;
- struct Fmt{
- uchar runes; /* output buffer is runes or chars? */
- 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 Rune */
- int width;
- int prec;
- ulong flags;
- };
- .sp 0.3v
- 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,
- .sp 0.3v
- FmtFlag = FmtComma << 1
- };
- .fi
- .PP
- .B
- .ta \w'\fLchar* 'u
- .sp 0.3v
- .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 runefmtstrinit(Fmt *f);
- .PP
- .B
- Rune* runefmtstrflush(Fmt *f);
- .sp 0.3v
- .PP
- .B
- int fmtinstall(int c, int (*fn)(Fmt*));
- .PP
- .B
- int dofmt(Fmt *f, char *fmt);
- .PP
- .B
- int dorfmt(Fmt*, Rune *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);
- .PP
- .B
- int fmtrunestrcpy(Fmt *f, Rune *s);
- .PP
- .B
- int errfmt(Fmt *f);
- .SH DESCRIPTION
- The interface described here allows the construction of custom
- .IR print (2)
- verbs and output routines.
- In essence, they provide access to the workings of the formatted print code.
- .PP
- The
- .IR print (2)
- suite maintains its state with a data structure called
- .BR Fmt .
- A typical call to
- .IR print (2)
- 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 whether the output is in runes or bytes,
- 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 like
- .B fprint
- (see
- .IR print (2))
- or
- .B vfprint
- except that the characters are buffered until
- .I fmtfdflush
- is called and the return value is either 0 or \-1.
- 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.
- To output to a rune string, use
- .I runefmtstrinit
- and
- .IR runefmtstrflush .
- 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 (2)
- 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 FmtUnsigned
- .RB ( u ),
- 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 one.
- 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.
- These functions will preserve width, precision, and flags.
- Both functions return 0 for success and \-1 for failure.
- .PP
- The functions
- .I dofmt
- and
- .I dorfmt
- are the underlying formatters; they
- use the existing contents of
- .B Fmt
- and should be called only by sophisticated conversion routines.
- These routines return the number of characters (bytes of UTF or runes)
- produced.
- .PP
- Some internal functions may be useful to format primitive types.
- They honor the width, precision and flags as described in
- .IR print (2).
- .I Fmtrune
- formats a single character
- .BR r .
- .I Fmtstrcpy
- formats a string
- .BR s ;
- .I fmtrunestrcpy
- formats a rune string
- .BR s .
- .I Errfmt
- formats the system error string.
- All these routines return zero for successful execution.
- Conversion routines that call these functions will work properly
- regardless of whether the output is bytes or runes.
- .PP
- .IR 8c (1)
- describes the C directive
- .B #pragma
- .B varargck
- that can be used to provide type-checking for custom print verbs and output routines.
- .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 (2),
- 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
- .sp 0.3v
- void
- fatal(char *fmt, ...)
- {
- Fmt f;
- char buf[64];
- va_list arg;
- .sp 0.3v
- 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;
- .sp 0.3v
- .sp 0.3v
- int
- Xfmt(Fmt *f)
- {
- Complex c;
- .sp 0.3v
- c = va_arg(f->args, Complex);
- return fmtprint(f, "(%g,%g)", c.r, c.i);
- }
- .sp 0.3v
- main(...)
- {
- Complex x = (Complex){ 1.5, -2.3 };
- .sp 0.3v
- fmtinstall('X', Xfmt);
- print("x = %X\en", x);
- }
- .EE
- .SH SOURCE
- .B /sys/src/libc/fmt
- .SH SEE ALSO
- .IR print (2),
- .IR utf (6),
- .IR errstr (2)
- .SH DIAGNOSTICS
- These routines return negative numbers or nil for errors and set
- .IR errstr .
|