|
@@ -40,32 +40,6 @@ static uint8_t type_sizes[] = {
|
40
|
40
|
[SIZE_T_LEN] = sizeof ( size_t ),
|
41
|
41
|
};
|
42
|
42
|
|
43
|
|
-/**
|
44
|
|
- * A printf context
|
45
|
|
- *
|
46
|
|
- * Contexts are used in order to be able to share code between
|
47
|
|
- * vprintf() and vsnprintf(), without requiring the allocation of a
|
48
|
|
- * buffer for vprintf().
|
49
|
|
- */
|
50
|
|
-struct printf_context {
|
51
|
|
- /**
|
52
|
|
- * Character handler
|
53
|
|
- *
|
54
|
|
- * @v ctx Context
|
55
|
|
- * @v c Character
|
56
|
|
- *
|
57
|
|
- * This method is called for each character written to the
|
58
|
|
- * formatted string. It must increment @len.
|
59
|
|
- */
|
60
|
|
- void ( * handler ) ( struct printf_context *ctx, unsigned int c );
|
61
|
|
- /** Length of formatted string */
|
62
|
|
- size_t len;
|
63
|
|
- /** Buffer for formatted string (used by printf_sputc()) */
|
64
|
|
- char *buf;
|
65
|
|
- /** Buffer length (used by printf_sputc()) */
|
66
|
|
- size_t max_len;
|
67
|
|
-};
|
68
|
|
-
|
69
|
43
|
/**
|
70
|
44
|
* Use lower-case for hexadecimal digits
|
71
|
45
|
*
|
|
@@ -163,6 +137,20 @@ static char * format_decimal ( char *end, signed long num, int width ) {
|
163
|
137
|
return ptr;
|
164
|
138
|
}
|
165
|
139
|
|
|
140
|
+/**
|
|
141
|
+ * Print character via a printf context
|
|
142
|
+ *
|
|
143
|
+ * @v ctx Context
|
|
144
|
+ * @v c Character
|
|
145
|
+ *
|
|
146
|
+ * Call's the printf_context::handler() method and increments
|
|
147
|
+ * printf_context::len.
|
|
148
|
+ */
|
|
149
|
+static inline void cputchar ( struct printf_context *ctx, unsigned int c ) {
|
|
150
|
+ ctx->handler ( ctx, c );
|
|
151
|
+ ++ctx->len;
|
|
152
|
+}
|
|
153
|
+
|
166
|
154
|
/**
|
167
|
155
|
* Write a formatted string to a printf context
|
168
|
156
|
*
|
|
@@ -185,7 +173,7 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
|
185
|
173
|
for ( ; *fmt ; fmt++ ) {
|
186
|
174
|
/* Pass through ordinary characters */
|
187
|
175
|
if ( *fmt != '%' ) {
|
188
|
|
- ctx->handler ( ctx, *fmt );
|
|
176
|
+ cputchar ( ctx, *fmt );
|
189
|
177
|
continue;
|
190
|
178
|
}
|
191
|
179
|
fmt++;
|
|
@@ -228,7 +216,7 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
|
228
|
216
|
ptr = tmp_buf + sizeof ( tmp_buf ) - 1;
|
229
|
217
|
*ptr = '\0';
|
230
|
218
|
if ( *fmt == 'c' ) {
|
231
|
|
- ctx->handler ( ctx, va_arg ( args, unsigned int ) );
|
|
219
|
+ cputchar ( ctx, va_arg ( args, unsigned int ) );
|
232
|
220
|
} else if ( *fmt == 's' ) {
|
233
|
221
|
ptr = va_arg ( args, char * );
|
234
|
222
|
} else if ( *fmt == 'p' ) {
|
|
@@ -263,13 +251,22 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
|
263
|
251
|
}
|
264
|
252
|
/* Write out conversion result */
|
265
|
253
|
for ( ; *ptr ; ptr++ ) {
|
266
|
|
- ctx->handler ( ctx, *ptr );
|
|
254
|
+ cputchar ( ctx, *ptr );
|
267
|
255
|
}
|
268
|
256
|
}
|
269
|
257
|
|
270
|
258
|
return ctx->len;
|
271
|
259
|
}
|
272
|
260
|
|
|
261
|
+/** Context used by vsnprintf() and friends */
|
|
262
|
+struct sputc_context {
|
|
263
|
+ struct printf_context ctx;
|
|
264
|
+ /** Buffer for formatted string (used by printf_sputc()) */
|
|
265
|
+ char *buf;
|
|
266
|
+ /** Buffer length (used by printf_sputc()) */
|
|
267
|
+ size_t max_len;
|
|
268
|
+};
|
|
269
|
+
|
273
|
270
|
/**
|
274
|
271
|
* Write character to buffer
|
275
|
272
|
*
|
|
@@ -277,8 +274,11 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) {
|
277
|
274
|
* @v c Character
|
278
|
275
|
*/
|
279
|
276
|
static void printf_sputc ( struct printf_context *ctx, unsigned int c ) {
|
280
|
|
- if ( ++ctx->len < ctx->max_len )
|
281
|
|
- ctx->buf[ctx->len-1] = c;
|
|
277
|
+ struct sputc_context * sctx =
|
|
278
|
+ container_of ( ctx, struct sputc_context, ctx );
|
|
279
|
+
|
|
280
|
+ if ( ctx->len <= sctx->max_len )
|
|
281
|
+ sctx->buf[ctx->len] = c;
|
282
|
282
|
}
|
283
|
283
|
|
284
|
284
|
/**
|
|
@@ -295,15 +295,15 @@ static void printf_sputc ( struct printf_context *ctx, unsigned int c ) {
|
295
|
295
|
* been available.
|
296
|
296
|
*/
|
297
|
297
|
int vsnprintf ( char *buf, size_t size, const char *fmt, va_list args ) {
|
298
|
|
- struct printf_context ctx;
|
|
298
|
+ struct sputc_context sctx;
|
299
|
299
|
size_t len;
|
300
|
300
|
size_t end;
|
301
|
301
|
|
302
|
302
|
/* Hand off to vcprintf */
|
303
|
|
- ctx.handler = printf_sputc;
|
304
|
|
- ctx.buf = buf;
|
305
|
|
- ctx.max_len = size;
|
306
|
|
- len = vcprintf ( &ctx, fmt, args );
|
|
303
|
+ sctx.ctx.handler = printf_sputc;
|
|
304
|
+ sctx.buf = buf;
|
|
305
|
+ sctx.max_len = size;
|
|
306
|
+ len = vcprintf ( &sctx.ctx, fmt, args );
|
307
|
307
|
|
308
|
308
|
/* Add trailing NUL */
|
309
|
309
|
if ( size ) {
|
|
@@ -341,8 +341,8 @@ int snprintf ( char *buf, size_t size, const char *fmt, ... ) {
|
341
|
341
|
* @v ctx Context
|
342
|
342
|
* @v c Character
|
343
|
343
|
*/
|
344
|
|
-static void printf_putchar ( struct printf_context *ctx, unsigned int c ) {
|
345
|
|
- ++ctx->len;
|
|
344
|
+static void printf_putchar ( struct printf_context *ctx __unused,
|
|
345
|
+ unsigned int c ) {
|
346
|
346
|
putchar ( c );
|
347
|
347
|
}
|
348
|
348
|
|