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