Blame


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