1 /*
2  * Taken from Linux kernel's linux/lib/vsprintf.c
3  * and somewhat simplified.
4  *
5  * Copyright (C) 1991, 1992  Linus Torvalds
6  */
7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8 /*
9  * Wirzenius wrote this portably, Torvalds fucked it up :-)
10  */
11 
12 #include "defs.h"
13 
14 #if USE_CUSTOM_PRINTF
15 
16 #include <stdarg.h>
17 #include <limits.h>
18 
19 #ifndef HAVE_FPUTS_UNLOCKED
20 # define fputs_unlocked fputs
21 #endif
22 
23 #define noinline_for_stack /*nothing*/
24 #define likely(expr)       (expr)
25 #define unlikely(expr)     (expr)
26 
27 #define do_div(n, d)       ({ __typeof(num) t = n % d; n /= d; t; })
28 
29 #undef isdigit
30 #define isdigit(a) ((unsigned char)((a) - '0') <= 9)
31 
32 static inline
skip_atoi(const char ** s)33 int skip_atoi(const char **s)
34 {
35 	int i = 0;
36 	const char *p = *s;
37 
38 	while (isdigit(*p))
39 		i = i*10 + *p++ - '0';
40 
41 	*s = p;
42 	return i;
43 }
44 
45 /* Decimal conversion is by far the most typical, and is used
46  * for /proc and /sys data. This directly impacts e.g. top performance
47  * with many processes running. We optimize it for speed
48  * using ideas described at <http://www.cs.uiowa.edu/~jones/bcd/divide.html>
49  * (with permission from the author, Douglas W. Jones).
50  */
51 
52 #if LONG_MAX != 0x7fffffffUL || LLONG_MAX != 0x7fffffffffffffffULL
53 /* Formats correctly any integer in [0, 999999999] */
54 static noinline_for_stack
put_dec_full9(char * buf,unsigned q)55 char *put_dec_full9(char *buf, unsigned q)
56 {
57 	unsigned r;
58 
59 	/* Possible ways to approx. divide by 10
60 	 * (x * 0x1999999a) >> 32 x < 1073741829 (multiply must be 64-bit)
61 	 * (x * 0xcccd) >> 19     x <      81920 (x < 262149 when 64-bit mul)
62 	 * (x * 0x6667) >> 18     x <      43699
63 	 * (x * 0x3334) >> 17     x <      16389
64 	 * (x * 0x199a) >> 16     x <      16389
65 	 * (x * 0x0ccd) >> 15     x <      16389
66 	 * (x * 0x0667) >> 14     x <       2739
67 	 * (x * 0x0334) >> 13     x <       1029
68 	 * (x * 0x019a) >> 12     x <       1029
69 	 * (x * 0x00cd) >> 11     x <       1029 shorter code than * 0x67 (on i386)
70 	 * (x * 0x0067) >> 10     x <        179
71 	 * (x * 0x0034) >>  9     x <         69 same
72 	 * (x * 0x001a) >>  8     x <         69 same
73 	 * (x * 0x000d) >>  7     x <         69 same, shortest code (on i386)
74 	 * (x * 0x0007) >>  6     x <         19
75 	 * See <http://www.cs.uiowa.edu/~jones/bcd/divide.html>
76 	 */
77 	r      = (q * (uint64_t)0x1999999a) >> 32;
78 	*buf++ = (q - 10 * r) + '0'; /* 1 */
79 	q      = (r * (uint64_t)0x1999999a) >> 32;
80 	*buf++ = (r - 10 * q) + '0'; /* 2 */
81 	r      = (q * (uint64_t)0x1999999a) >> 32;
82 	*buf++ = (q - 10 * r) + '0'; /* 3 */
83 	q      = (r * (uint64_t)0x1999999a) >> 32;
84 	*buf++ = (r - 10 * q) + '0'; /* 4 */
85 	r      = (q * (uint64_t)0x1999999a) >> 32;
86 	*buf++ = (q - 10 * r) + '0'; /* 5 */
87 	/* Now value is under 10000, can avoid 64-bit multiply */
88 	q      = (r * 0x199a) >> 16;
89 	*buf++ = (r - 10 * q)  + '0'; /* 6 */
90 	r      = (q * 0xcd) >> 11;
91 	*buf++ = (q - 10 * r)  + '0'; /* 7 */
92 	q      = (r * 0xcd) >> 11;
93 	*buf++ = (r - 10 * q) + '0'; /* 8 */
94 	*buf++ = q + '0'; /* 9 */
95 	return buf;
96 }
97 #endif
98 
99 /* Similar to above but do not pad with zeros.
100  * Code can be easily arranged to print 9 digits too, but our callers
101  * always call put_dec_full9() instead when the number has 9 decimal digits.
102  */
103 static noinline_for_stack
put_dec_trunc8(char * buf,unsigned r)104 char *put_dec_trunc8(char *buf, unsigned r)
105 {
106 	unsigned q;
107 
108 	/* Copy of previous function's body with added early returns */
109 	q      = (r * (uint64_t)0x1999999a) >> 32;
110 	*buf++ = (r - 10 * q) + '0'; /* 2 */
111 	if (q == 0) return buf;
112 	r      = (q * (uint64_t)0x1999999a) >> 32;
113 	*buf++ = (q - 10 * r) + '0'; /* 3 */
114 	if (r == 0) return buf;
115 	q      = (r * (uint64_t)0x1999999a) >> 32;
116 	*buf++ = (r - 10 * q) + '0'; /* 4 */
117 	if (q == 0) return buf;
118 	r      = (q * (uint64_t)0x1999999a) >> 32;
119 	*buf++ = (q - 10 * r) + '0'; /* 5 */
120 	if (r == 0) return buf;
121 	q      = (r * 0x199a) >> 16;
122 	*buf++ = (r - 10 * q)  + '0'; /* 6 */
123 	if (q == 0) return buf;
124 	r      = (q * 0xcd) >> 11;
125 	*buf++ = (q - 10 * r)  + '0'; /* 7 */
126 	if (r == 0) return buf;
127 	q      = (r * 0xcd) >> 11;
128 	*buf++ = (r - 10 * q) + '0'; /* 8 */
129 	if (q == 0) return buf;
130 	*buf++ = q + '0'; /* 9 */
131 	return buf;
132 }
133 
134 /* There are two algorithms to print larger numbers.
135  * One is generic: divide by 1000000000 and repeatedly print
136  * groups of (up to) 9 digits. It's conceptually simple,
137  * but requires a (unsigned long long) / 1000000000 division.
138  *
139  * Second algorithm splits 64-bit unsigned long long into 16-bit chunks,
140  * manipulates them cleverly and generates groups of 4 decimal digits.
141  * It so happens that it does NOT require long long division.
142  *
143  * If long is > 32 bits, division of 64-bit values is relatively easy,
144  * and we will use the first algorithm.
145  * If long long is > 64 bits (strange architecture with VERY large long long),
146  * second algorithm can't be used, and we again use the first one.
147  *
148  * Else (if long is 32 bits and long long is 64 bits) we use second one.
149  */
150 
151 #if LONG_MAX != 0x7fffffffUL || LLONG_MAX != 0x7fffffffffffffffULL
152 
153 /* First algorithm: generic */
154 
155 static
put_dec(char * buf,unsigned long long n)156 char *put_dec(char *buf, unsigned long long n)
157 {
158 	if (n >= 100*1000*1000) {
159 		while (n >= 1000*1000*1000)
160 			buf = put_dec_full9(buf, do_div(n, 1000*1000*1000));
161 		if (n >= 100*1000*1000)
162 			return put_dec_full9(buf, n);
163 	}
164 	return put_dec_trunc8(buf, n);
165 }
166 
167 #else
168 
169 /* Second algorithm: valid only for 64-bit long longs */
170 
171 static noinline_for_stack
put_dec_full4(char * buf,unsigned q)172 char *put_dec_full4(char *buf, unsigned q)
173 {
174 	unsigned r;
175 	r      = (q * 0xcccd) >> 19;
176 	*buf++ = (q - 10 * r) + '0';
177 	q      = (r * 0x199a) >> 16;
178 	*buf++ = (r - 10 * q)  + '0';
179 	r      = (q * 0xcd) >> 11;
180 	*buf++ = (q - 10 * r)  + '0';
181 	*buf++ = r + '0';
182 	return buf;
183 }
184 
185 /* Based on code by Douglas W. Jones found at
186  * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour>
187  * (with permission from the author).
188  * Performs no 64-bit division and hence should be fast on 32-bit machines.
189  */
190 static
put_dec(char * buf,unsigned long long n)191 char *put_dec(char *buf, unsigned long long n)
192 {
193 	uint32_t d3, d2, d1, q, h;
194 
195 	if (n < 100*1000*1000)
196 		return put_dec_trunc8(buf, n);
197 
198 	d1  = ((uint32_t)n >> 16); /* implicit "& 0xffff" */
199 	h   = (n >> 32);
200 	d2  = (h      ) & 0xffff;
201 	d3  = (h >> 16); /* implicit "& 0xffff" */
202 
203 	q   = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff);
204 
205 	buf = put_dec_full4(buf, q % 10000);
206 	q   = q / 10000;
207 
208 	d1  = q + 7671 * d3 + 9496 * d2 + 6 * d1;
209 	buf = put_dec_full4(buf, d1 % 10000);
210 	q   = d1 / 10000;
211 
212 	d2  = q + 4749 * d3 + 42 * d2;
213 	buf = put_dec_full4(buf, d2 % 10000);
214 	q   = d2 / 10000;
215 
216 	d3  = q + 281 * d3;
217 	if (!d3)
218 		goto done;
219 	buf = put_dec_full4(buf, d3 % 10000);
220 	q   = d3 / 10000;
221 	if (!q)
222 		goto done;
223 	buf = put_dec_full4(buf, q);
224  done:
225 	while (buf[-1] == '0')
226 		--buf;
227 
228 	return buf;
229 }
230 
231 #endif
232 
233 /*
234  * For strace, the following formats are not supported:
235  * %h[h]u, %zu, %tu  - use [unsigned] int/long/long long fmt instead
236  * %8.4u  - no precision field for integers allowed (ok for strings)
237  * %+d, % d  - no forced sign or force "space positive" sign
238  * %-07u  - use %-7u instead
239  * %X  - works as %x
240  */
241 
242 #define ZEROPAD	1		/* pad with zero */
243 #define SIGN	2		/* unsigned/signed long */
244 //#define PLUS	4		/* show plus */
245 //#define SPACE	8		/* space if plus */
246 #define LEFT	16		/* left justified */
247 //#deefine SMALL	32		/* use lowercase in hex (must be 32 == 0x20) */
248 #define SPECIAL	64		/* prefix hex with "0x", octal with "0" */
249 
250 enum format_type {
251 	FORMAT_TYPE_NONE, /* Just a string part */
252 	FORMAT_TYPE_WIDTH,
253 	FORMAT_TYPE_PRECISION,
254 	FORMAT_TYPE_CHAR,
255 	FORMAT_TYPE_STR,
256 	FORMAT_TYPE_PTR,
257 	FORMAT_TYPE_PERCENT_CHAR,
258 	FORMAT_TYPE_INVALID,
259 	FORMAT_TYPE_LONG_LONG,
260 	FORMAT_TYPE_ULONG,
261 	FORMAT_TYPE_LONG,
262 	FORMAT_TYPE_UINT,
263 	FORMAT_TYPE_INT,
264 };
265 
266 struct printf_spec {
267 	uint8_t	type;		/* format_type enum */
268 	uint8_t	flags;		/* flags to number() */
269 	uint8_t	base;		/* number base, 8, 10 or 16 only */
270 	uint8_t	qualifier;	/* number qualifier, one of 'hHlLtzZ' */
271 	int	field_width;	/* width of output field */
272 	int	precision;	/* # of digits/chars */
273 };
274 
275 static noinline_for_stack
number(char * buf,char * end,unsigned long long num,struct printf_spec spec)276 char *number(char *buf, char *end, unsigned long long num,
277 	     struct printf_spec spec)
278 {
279 	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
280 	static const char digits[16] = "0123456789abcdef"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
281 
282 	char tmp[sizeof(long long)*3 + 4];
283 	char sign;
284 	int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
285 	int i;
286 
287 	/* We may overflow the buf. Crudely check for it */
288 	i = sizeof(long long)*3 + 4;
289 	if (i < spec.field_width)
290 		i = spec.field_width;
291 	if ((end - buf) <= i)
292 		return buf + i;
293 
294 //we don't use formats like "%-07u"
295 //	if (spec.flags & LEFT)
296 //		spec.flags &= ~ZEROPAD;
297 	sign = 0;
298 	if (spec.flags & SIGN) {
299 		if ((signed long long)num < 0) {
300 			sign = '-';
301 			num = -(signed long long)num;
302 			spec.field_width--;
303 //		} else if (spec.flags & PLUS) {
304 //			sign = '+';
305 //			spec.field_width--;
306 //		} else if (spec.flags & SPACE) {
307 //			sign = ' ';
308 //			spec.field_width--;
309 		}
310 	}
311 	if (need_pfx) {
312 		spec.field_width--;
313 		if (spec.base == 16)
314 			spec.field_width--;
315 	}
316 
317 	/* generate full string in tmp[], in reverse order */
318 	i = 0;
319 	if (num < spec.base)
320 		tmp[i++] = digits[num];
321 	/* Generic code, for any base:
322 	else do {
323 		tmp[i++] = (digits[do_div(num,base)]);
324 	} while (num != 0);
325 	*/
326 	else if (spec.base != 10) { /* 8 or 16 */
327 		int mask = spec.base - 1;
328 		int shift = 3;
329 
330 		if (spec.base == 16)
331 			shift = 4;
332 		do {
333 			tmp[i++] = digits[((unsigned char)num) & mask];
334 			num >>= shift;
335 		} while (num);
336 	} else { /* base 10 */
337 		i = put_dec(tmp, num) - tmp;
338 	}
339 
340 //spec.precision is assumed 0 ("not specified")
341 //	/* printing 100 using %2d gives "100", not "00" */
342 //	if (i > spec.precision)
343 //		spec.precision = i;
344 //	/* leading space padding */
345 //	spec.field_width -= spec.precision;
346 	spec.field_width -= i;
347 	if (!(spec.flags & (ZEROPAD+LEFT))) {
348 		while (--spec.field_width >= 0) {
349 			///if (buf < end)
350 				*buf = ' ';
351 			++buf;
352 		}
353 	}
354 	/* sign */
355 	if (sign) {
356 		///if (buf < end)
357 			*buf = sign;
358 		++buf;
359 	}
360 	/* "0x" / "0" prefix */
361 	if (need_pfx) {
362 		///if (buf < end)
363 			*buf = '0';
364 		++buf;
365 		if (spec.base == 16) {
366 			///if (buf < end)
367 				*buf = 'x';
368 			++buf;
369 		}
370 	}
371 	/* zero or space padding */
372 	if (!(spec.flags & LEFT)) {
373 		char c = (spec.flags & ZEROPAD) ? '0' : ' ';
374 		while (--spec.field_width >= 0) {
375 			///if (buf < end)
376 				*buf = c;
377 			++buf;
378 		}
379 	}
380 //	/* hmm even more zero padding? */
381 //	while (i <= --spec.precision) {
382 //		///if (buf < end)
383 //			*buf = '0';
384 //		++buf;
385 //	}
386 	/* actual digits of result */
387 	while (--i >= 0) {
388 		///if (buf < end)
389 			*buf = tmp[i];
390 		++buf;
391 	}
392 	/* trailing space padding */
393 	while (--spec.field_width >= 0) {
394 		///if (buf < end)
395 			*buf = ' ';
396 		++buf;
397 	}
398 
399 	return buf;
400 }
401 
402 static noinline_for_stack
string(char * buf,char * end,const char * s,struct printf_spec spec)403 char *string(char *buf, char *end, const char *s, struct printf_spec spec)
404 {
405 	int len, i;
406 
407 	if (!s)
408 		s = "(null)";
409 
410 	len = strnlen(s, spec.precision);
411 
412 	/* We may overflow the buf. Crudely check for it */
413 	i = len;
414 	if (i < spec.field_width)
415 		i = spec.field_width;
416 	if ((end - buf) <= i)
417 		return buf + i;
418 
419 	if (!(spec.flags & LEFT)) {
420 		while (len < spec.field_width--) {
421 			///if (buf < end)
422 				*buf = ' ';
423 			++buf;
424 		}
425 	}
426 	for (i = 0; i < len; ++i) {
427 		///if (buf < end)
428 			*buf = *s;
429 		++buf; ++s;
430 	}
431 	while (len < spec.field_width--) {
432 		///if (buf < end)
433 			*buf = ' ';
434 		++buf;
435 	}
436 
437 	return buf;
438 }
439 
440 static noinline_for_stack
pointer(const char * fmt,char * buf,char * end,void * ptr,struct printf_spec spec)441 char *pointer(const char *fmt, char *buf, char *end, void *ptr,
442 	      struct printf_spec spec)
443 {
444 //	spec.flags |= SMALL;
445 	if (spec.field_width == -1) {
446 		spec.field_width = 2 * sizeof(void *);
447 		spec.flags |= ZEROPAD;
448 	}
449 	spec.base = 16;
450 
451 	return number(buf, end, (unsigned long) ptr, spec);
452 }
453 
454 /*
455  * Helper function to decode printf style format.
456  * Each call decode a token from the format and return the
457  * number of characters read (or likely the delta where it wants
458  * to go on the next call).
459  * The decoded token is returned through the parameters
460  *
461  * 'h', 'l', or 'L' for integer fields
462  * 'z' support added 23/7/1999 S.H.
463  * 'z' changed to 'Z' --davidm 1/25/99
464  * 't' added for ptrdiff_t
465  *
466  * @fmt: the format string
467  * @type of the token returned
468  * @flags: various flags such as +, -, # tokens..
469  * @field_width: overwritten width
470  * @base: base of the number (octal, hex, ...)
471  * @precision: precision of a number
472  * @qualifier: qualifier of a number (long, size_t, ...)
473  */
474 static noinline_for_stack
format_decode(const char * fmt,struct printf_spec * spec)475 int format_decode(const char *fmt, struct printf_spec *spec)
476 {
477 	const char *start = fmt;
478 
479 	/* we finished early by reading the field width */
480 	if (spec->type == FORMAT_TYPE_WIDTH) {
481 		if (spec->field_width < 0) {
482 			spec->field_width = -spec->field_width;
483 			spec->flags |= LEFT;
484 		}
485 		spec->type = FORMAT_TYPE_NONE;
486 		goto precision;
487 	}
488 
489 	/* we finished early by reading the precision */
490 	if (spec->type == FORMAT_TYPE_PRECISION) {
491 		if (spec->precision < 0)
492 			spec->precision = 0;
493 
494 		spec->type = FORMAT_TYPE_NONE;
495 		goto qualifier;
496 	}
497 
498 	/* By default */
499 	spec->type = FORMAT_TYPE_NONE;
500 
501 	for (;;) {
502 		if (*fmt == '\0')
503 			return fmt - start;
504 		if (*fmt == '%')
505 			break;
506 		++fmt;
507 	}
508 
509 	/* Return the current non-format string */
510 	if (fmt != start)
511 		return fmt - start;
512 
513 	/* Process flags */
514 	spec->flags = 0;
515 
516 	while (1) { /* this also skips first '%' */
517 		bool found = true;
518 
519 		++fmt;
520 
521 		switch (*fmt) {
522 		case '-': spec->flags |= LEFT;    break;
523 //		case '+': spec->flags |= PLUS;    break;
524 //		case ' ': spec->flags |= SPACE;   break;
525 		case '#': spec->flags |= SPECIAL; break;
526 		case '0': spec->flags |= ZEROPAD; break;
527 		default:  found = false;
528 		}
529 
530 		if (!found)
531 			break;
532 	}
533 
534 	/* get field width */
535 	spec->field_width = -1;
536 
537 	if (isdigit(*fmt))
538 		spec->field_width = skip_atoi(&fmt);
539 	else if (*fmt == '*') {
540 		/* it's the next argument */
541 		spec->type = FORMAT_TYPE_WIDTH;
542 		return ++fmt - start;
543 	}
544 
545 precision:
546 	/* get the precision */
547 	spec->precision = -1;
548 	if (*fmt == '.') {
549 		++fmt;
550 		if (isdigit(*fmt)) {
551 			spec->precision = skip_atoi(&fmt);
552 //			if (spec->precision < 0)
553 //				spec->precision = 0;
554 		} else if (*fmt == '*') {
555 			/* it's the next argument */
556 			spec->type = FORMAT_TYPE_PRECISION;
557 			return ++fmt - start;
558 		}
559 	}
560 
561 qualifier:
562 	/* get the conversion qualifier */
563 	spec->qualifier = -1;
564 	if (*fmt == 'l') {
565 		spec->qualifier = *fmt++;
566 		if (unlikely(spec->qualifier == *fmt)) {
567 			spec->qualifier = 'L';
568 			++fmt;
569 		}
570 	}
571 
572 	/* default base */
573 	spec->base = 10;
574 	switch (*fmt) {
575 	case 'c':
576 		spec->type = FORMAT_TYPE_CHAR;
577 		return ++fmt - start;
578 
579 	case 's':
580 		spec->type = FORMAT_TYPE_STR;
581 		return ++fmt - start;
582 
583 	case 'p':
584 		spec->type = FORMAT_TYPE_PTR;
585 		return ++fmt - start;
586 
587 	case '%':
588 		spec->type = FORMAT_TYPE_PERCENT_CHAR;
589 		return ++fmt - start;
590 
591 	/* integer number formats - set up the flags and "break" */
592 	case 'o':
593 		spec->base = 8;
594 		break;
595 
596 	case 'x':
597 //		spec->flags |= SMALL;
598 
599 	case 'X':
600 		spec->base = 16;
601 		break;
602 
603 	case 'd':
604 	case 'i':
605 		spec->flags |= SIGN;
606 	case 'u':
607 		break;
608 
609 	default:
610 		spec->type = FORMAT_TYPE_INVALID;
611 		return fmt - start;
612 	}
613 
614 	if (spec->qualifier == 'L')
615 		spec->type = FORMAT_TYPE_LONG_LONG;
616 	else if (spec->qualifier == 'l') {
617 		if (spec->flags & SIGN)
618 			spec->type = FORMAT_TYPE_LONG;
619 		else
620 			spec->type = FORMAT_TYPE_ULONG;
621 	} else {
622 		if (spec->flags & SIGN)
623 			spec->type = FORMAT_TYPE_INT;
624 		else
625 			spec->type = FORMAT_TYPE_UINT;
626 	}
627 
628 	return ++fmt - start;
629 }
630 
631 /**
632  * vsnprintf - Format a string and place it in a buffer
633  * @buf: The buffer to place the result into
634  * @size: The size of the buffer, including the trailing null space
635  * @fmt: The format string to use
636  * @args: Arguments for the format string
637  *
638  * The return value is the number of characters which would
639  * be generated for the given input, excluding the trailing
640  * '\0', as per ISO C99. If you want to have the exact
641  * number of characters written into @buf as return value
642  * (not including the trailing '\0'), use vscnprintf(). If the
643  * return is greater than or equal to @size, the resulting
644  * string is truncated.
645  *
646  * If you're not already dealing with a va_list consider using snprintf().
647  */
648 static
kernel_vsnprintf(char * buf,size_t size,const char * fmt,va_list args)649 int kernel_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
650 {
651 	unsigned long long num;
652 	char *str, *end;
653 	struct printf_spec spec = {0};
654 
655 	str = buf;
656 	end = buf + size;
657 
658 	while (*fmt) {
659 		const char *old_fmt = fmt;
660 		int read = format_decode(fmt, &spec);
661 
662 		fmt += read;
663 
664 		switch (spec.type) {
665 		case FORMAT_TYPE_NONE: {
666 			int copy = read;
667 			if (str < end) {
668 				if (copy > end - str)
669 					copy = end - str;
670 				memcpy(str, old_fmt, copy);
671 			}
672 			str += read;
673 			break;
674 		}
675 
676 		case FORMAT_TYPE_WIDTH:
677 			spec.field_width = va_arg(args, int);
678 			break;
679 
680 		case FORMAT_TYPE_PRECISION:
681 			spec.precision = va_arg(args, int);
682 			break;
683 
684 		case FORMAT_TYPE_CHAR: {
685 			char c;
686 
687 			if (!(spec.flags & LEFT)) {
688 				while (--spec.field_width > 0) {
689 					if (str < end)
690 						*str = ' ';
691 					++str;
692 
693 				}
694 			}
695 			c = (unsigned char) va_arg(args, int);
696 			if (str < end)
697 				*str = c;
698 			++str;
699 			while (--spec.field_width > 0) {
700 				if (str < end)
701 					*str = ' ';
702 				++str;
703 			}
704 			break;
705 		}
706 
707 		case FORMAT_TYPE_STR:
708 			str = string(str, end, va_arg(args, char *), spec);
709 			break;
710 
711 		case FORMAT_TYPE_PTR:
712 			str = pointer(fmt+1, str, end, va_arg(args, void *),
713 				      spec);
714 //			while (isalnum(*fmt))
715 //				fmt++;
716 			break;
717 
718 		case FORMAT_TYPE_PERCENT_CHAR:
719 			if (str < end)
720 				*str = '%';
721 			++str;
722 			break;
723 
724 		case FORMAT_TYPE_INVALID:
725 			if (str < end)
726 				*str = '%';
727 			++str;
728 			break;
729 
730 		default:
731 			switch (spec.type) {
732 			case FORMAT_TYPE_LONG_LONG:
733 				num = va_arg(args, long long);
734 				break;
735 			case FORMAT_TYPE_ULONG:
736 				num = va_arg(args, unsigned long);
737 				break;
738 			case FORMAT_TYPE_LONG:
739 				num = va_arg(args, long);
740 				break;
741 			case FORMAT_TYPE_INT:
742 				num = (int) va_arg(args, int);
743 				break;
744 			default:
745 				num = va_arg(args, unsigned int);
746 			}
747 
748 			str = number(str, end, num, spec);
749 		}
750 	}
751 
752 //	if (size > 0) {
753 		if (str < end)
754 			*str = '\0';
755 //		else
756 //			end[-1] = '\0';
757 //	}
758 
759 	/* the trailing null byte doesn't count towards the total */
760 	return str-buf;
761 
762 }
763 
strace_vfprintf(FILE * fp,const char * fmt,va_list args)764 int strace_vfprintf(FILE *fp, const char *fmt, va_list args)
765 {
766 	static char *buf = NULL;
767 	static unsigned buflen = 0;
768 
769 	int r;
770 	va_list a1;
771 
772 	va_copy(a1, args);
773 	unsigned len = kernel_vsnprintf(buf, buflen, fmt, a1);
774 	va_end(a1);
775 
776 	if (len >= buflen) {
777 		buflen = len + 256;
778 		free(buf);
779 		buf = xmalloc(buflen);
780 		/*len =*/ kernel_vsnprintf(buf, buflen, fmt, args);
781 	}
782 
783 	r = fputs_unlocked(buf, fp);
784 	if (r < 0) return r;
785 	return len;
786 }
787 
788 #endif /* USE_CUSTOM_PRINTF */
789