Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
.TH FMTINSTALL 2
2
.SH NAME
3
fmtinstall, dofmt, dorfmt, fmtprint, fmtvprint, fmtrune, fmtstrcpy, fmtrunestrcpy, fmtfdinit, fmtfdflush, fmtstrinit, fmtstrflush, runefmtstrinit, runefmtstrflush, errfmt \- support for user-defined print formats and output routines
4
.SH SYNOPSIS
5
.B #include <u.h>
6
.br
7
.B #include <libc.h>
8
.PP
9
.ft L
10
.nf
11
.ta \w'    'u +\w'    'u +\w'    'u +\w'    'u +\w'    'u
12
typedef struct Fmt	Fmt;
13
struct Fmt{
14
	uchar	runes;		/* output buffer is runes or chars? */
15
	void	*start;		/* of buffer */
16
	void	*to;		/* current place in the buffer */
17
	void	*stop;		/* end of the buffer; overwritten if flush fails */
18
	int		(*flush)(Fmt*);	/* called when to == stop */
19
	void	*farg;		/* to make flush a closure */
20
	int		nfmt;		/* num chars formatted so far */
21
	va_list	args;		/* args passed to dofmt */
22
	int		r;			/* % format Rune */
23
	int		width;
24
	int		prec;
25
	ulong	flags;
26
};
27
.sp 0.3v
28
enum{
29
	FmtWidth	= 1,
30
	FmtLeft		= FmtWidth << 1,
31
	FmtPrec		= FmtLeft << 1,
32
	FmtSharp	= FmtPrec << 1,
33
	FmtSpace	= FmtSharp << 1,
34
	FmtSign		= FmtSpace << 1,
35
	FmtZero		= FmtSign << 1,
36
	FmtUnsigned	= FmtZero << 1,
37
	FmtShort	= FmtUnsigned << 1,
38
	FmtLong		= FmtShort << 1,
39
	FmtVLong	= FmtLong << 1,
40
	FmtComma	= FmtVLong << 1,
41
.sp 0.3v
42
	FmtFlag		= FmtComma << 1
43
};
44
.fi
45
.PP
46
.B
47
.ta \w'\fLchar* 'u
48
.sp 0.3v
49
.PP
50
.B
51
int	fmtfdinit(Fmt *f, int fd, char *buf, int nbuf);
52
.PP
53
.B
54
int	fmtfdflush(Fmt *f);
55
.PP
56
.B
57
int	fmtstrinit(Fmt *f);
58
.PP
59
.B
60
char*	fmtstrflush(Fmt *f);
61
.PP
62
.B
63
int	runefmtstrinit(Fmt *f);
64
.PP
65
.B
66
Rune*	runefmtstrflush(Fmt *f);
67
.sp 0.3v
68
.PP
69
.B
70
int	fmtinstall(int c, int (*fn)(Fmt*));
71
.PP
72
.B
73
int	dofmt(Fmt *f, char *fmt);
74
.PP
75
.B
76
int	dorfmt(Fmt*, Rune *fmt);
77
.PP
78
.B
79
int	fmtprint(Fmt *f, char *fmt, ...);
80
.PP
81
.B
82
int	fmtvprint(Fmt *f, char *fmt, va_list v);
83
.PP
84
.B
85
int	fmtrune(Fmt *f, int r);
86
.PP
87
.B
88
int	fmtstrcpy(Fmt *f, char *s);
89
.PP
90
.B
91
int	fmtrunestrcpy(Fmt *f, Rune *s);
92
.PP
93
.B
94
int	errfmt(Fmt *f);
95
.SH DESCRIPTION
96
The interface described here allows the construction of custom
97
.IR print (2)
98
verbs and output routines.
99
In essence, they provide access to the workings of the formatted print code.
100
.PP
101
The
102
.IR print (2)
103
suite maintains its state with a data structure called
104
.BR Fmt .
105
A typical call to
106
.IR print (2)
107
or its relatives initializes a
108
.B Fmt
109
structure, passes it to subsidiary routines to process the output,
110
and finishes by emitting any saved state recorded in the
111
.BR Fmt .
112
The details of the
113
.B Fmt
114
are unimportant to outside users, except insofar as the general
115
design influences the interface.
116
The
117
.B Fmt
118
records whether the output is in runes or bytes,
119
the verb being processed, its precision and width,
120
and buffering parameters.
121
Most important, it also records a
122
.I flush
123
routine that the library will call if a buffer overflows.
124
When printing to a file descriptor, the flush routine will
125
emit saved characters and reset the buffer; when printing
126
to an allocated string, it will resize the string to receive more output.
127
The flush routine is nil when printing to fixed-size buffers.
128
User code need never provide a flush routine; this is done internally
129
by the library.
130
.SS Custom output routines
131
To write a custom output routine, such as an error handler that
132
formats and prints custom error messages, the output sequence can be run
133
from outside the library using the routines described here.
134
There are two main cases: output to an open file descriptor
135
and output to a string.
136
.PP
137
To write to a file descriptor, call
138
.I fmtfdinit
139
to initialize the local
140
.B Fmt
141
structure
142
.IR f ,
143
giving the file descriptor
144
.IR fd ,
145
the buffer
146
.IR buf ,
147
and its size
148
.IR nbuf .
149
Then call
150
.IR fmtprint
151
or
152
.IR fmtvprint
153
to generate the output.
154
These behave like
155
.B fprint
156
(see
157
.IR print (2))
158
or
159
.B vfprint
160
except that the characters are buffered until
161
.I fmtfdflush
162
is called and the return value is either 0 or \-1.
163
A typical example of this sequence appears in the Examples section.
164
.PP
165
The same basic sequence applies when outputting to an allocated string:
166
call
167
.I fmtstrinit
168
to initialize the
169
.BR Fmt ,
170
then call
171
.I fmtprint
172
and
173
.I fmtvprint
174
to generate the output.
175
Finally,
176
.I fmtstrflush
177
will return the allocated string, which should be freed after use.
178
To output to a rune string, use
179
.I runefmtstrinit
180
and
181
.IR runefmtstrflush .
182
Regardless of the output style or type,
183
.I fmtprint
184
or
185
.I fmtvprint
186
generates the characters.
187
.SS Custom format verbs
188
.I Fmtinstall
189
is used to install custom verbs and flags labeled by character
190
.IR c ,
191
which may be any non-zero Unicode character.
192
.I Fn
193
should be declared as
194
.IP
195
.EX
196
int	fn(Fmt*)
197
.EE
198
.PP
199
.IB Fp ->r
200
is the flag or verb character to cause
201
.I fn
202
to be called.
203
In
204
.IR fn ,
205
.IB fp ->width ,
206
.IB fp ->prec
207
are the width and precision, and
208
.IB fp ->flags
209
the decoded flags for the verb (see
210
.IR print (2)
211
for a description of these items).
212
The standard flag values are:
213
.B FmtSign
214
.RB ( + ),
215
.B FmtLeft
216
.RB ( - ),
217
.B FmtSpace
218
.RB ( '\ ' ),
219
.B FmtSharp
220
.RB ( # ),
221
.B FmtComma
222
.RB ( , ),
223
.B FmtLong
224
.RB ( l ),
225
.B FmtShort
226
.RB ( h ),
227
.B FmtUnsigned
228
.RB ( u ),
229
and
230
.B FmtVLong
231
.RB ( ll ).
232
The flag bits
233
.B FmtWidth
234
and
235
.B FmtPrec
236
identify whether a width and precision were specified.
237
.PP
238
.I Fn
239
is passed a pointer to the
240
.B Fmt
241
structure recording the state of the output.
242
If
243
.IB fp ->r
244
is a verb (rather than a flag),
245
.I fn
246
should use 
247
.B Fmt->args
248
to fetch its argument from the list,
249
then format it, and return zero.
250
If
251
.IB fp ->r
252
is a flag,
253
.I fn
254
should return one.
255
All interpretation of
256
.IB fp ->width\f1,
257
.IB fp ->prec\f1,
258
and
259
.IB fp-> flags
260
is left up to the conversion routine.
261
.I Fmtinstall
262
returns 0 if the installation succeeds, \-1 if it fails.
263
.PP
264
.IR Fmtprint
265
and
266
.IR fmtvprint
267
may be called to
268
help prepare output in custom conversion routines.
269
These functions will preserve width, precision, and flags.
270
Both functions return 0 for success and \-1 for failure.
271
.PP
272
The functions
273
.I dofmt
274
and
275
.I dorfmt
276
are the underlying formatters; they
277
use the existing contents of
278
.B Fmt
279
and should be called only by sophisticated conversion routines.
280
These routines return the number of characters (bytes of UTF or runes)
281
produced.
282
.PP
283
Some internal functions may be useful to format primitive types.
284
They honor the width, precision and flags as described in
285
.IR print (2).
286
.I Fmtrune
287
formats a single character
288
.BR r .
289
.I Fmtstrcpy
290
formats a string
291
.BR s ;
292
.I fmtrunestrcpy
293
formats a rune string
294
.BR s .
295
.I Errfmt
296
formats the system error string.
297
All these routines return zero for successful execution.
298
Conversion routines that call these functions will work properly
299
regardless of whether the output is bytes or runes.
300
.PP
301
.IR 8c (1)
302
describes the C directive
303
.B #pragma
304
.B varargck
305
that can be used to provide type-checking for custom print verbs and output routines.
306
.SH EXAMPLES
307
This function prints an error message with a variable
308
number of arguments and then quits.
309
Compared to the corresponding example in
310
.IR print (2),
311
this version uses a smaller buffer, will never truncate
312
the output message, but might generate multiple
313
.B write
314
system calls to produce its output.
315
.IP
316
.EX
317
.ta 6n +6n +6n +6n +6n +6n +6n +6n +6n
318
#pragma	varargck	argpos	fatal	1
319
.sp 0.3v
320
void
321
fatal(char *fmt, ...)
322
{
323
	Fmt f;
324
	char buf[64];
325
	va_list arg;
326
.sp 0.3v
327
	fmtfdinit(&f, 1, buf, sizeof buf);
328
	fmtprint(&f, "fatal: ");
329
	va_start(arg, fmt);
330
	fmtvprint(&f, fmt, arg);
331
	va_end(arg);
332
	fmtprint(&f, "\en");
333
	fmtfdflush(&f);
334
	exits("fatal error");
335
}
336
.EE
337
.PP
338
This example adds a verb to print complex numbers.
339
.IP
340
.EX
341
typedef struct {
342
	double	r, i;
343
} Complex;
344
.sp 0.3v
345
#pragma	varargck	type	"X"	Complex
346
.sp 0.3v
347
int
348
Xfmt(Fmt *f)
349
{
350
	Complex c;
351
.sp 0.3v
352
	c = va_arg(f->args, Complex);
353
	return fmtprint(f, "(%g,%g)", c.r, c.i);
354
}
355
.sp 0.3v
356
main(...)
357
{
358
	Complex x = (Complex){ 1.5, -2.3 };
359
.sp 0.3v
360
	fmtinstall('X', Xfmt);
361
	print("x = %X\en", x);
362
}
363
.EE
364
.SH SOURCE
365
.B /sys/src/libc/fmt
366
.SH SEE ALSO
367
.IR print (2),
368
.IR utf (6),
369
.IR errstr (2)
370
.SH DIAGNOSTICS
371
These routines return negative numbers or nil for errors and set
372
.IR errstr .