| .TH FMTINSTALL 3 |
| .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; |
| }; |
| |
| 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, |
| |
| FmtFlag = FmtComma << 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 runefmtstrinit(Fmt *f); |
| .PP |
| .B |
| Rune* runefmtstrflush(Fmt *f); |
| |
| .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 (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 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 (3)) |
| 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 (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 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. |
| However, these functions clear the 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 (3). |
| .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 2c (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 (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 |
| #pragma varargck argpos error 1 |
| |
| 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; |
| |
| #pragma varargck type "X" 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 = (Complex){ 1.5, -2.3 }; |
| |
| fmtinstall('X', Xfmt); |
| print("x = %X\en", x); |
| } |
| .EE |
| .SH SOURCE |
| .B \*9/src/lib9/fmt |
| .SH SEE ALSO |
| .IR print (3), |
| .IR utf (7), |
| .IR errstr (3) |
| .SH DIAGNOSTICS |
| These routines return negative numbers or nil for errors and set |
| .IR errstr . |