1 // SPDX-License-Identifier: GPL-2.0-only
2 /* -*- linux-c -*- ------------------------------------------------------- *
3  *
4  *   Copyright (C) 1991, 1992 Linus Torvalds
5  *   Copyright 2007 rPath, Inc. - All Rights Reserved
6  *
7  * ----------------------------------------------------------------------- */
8 
9 /*
10  * Oh, it's a waste of space, but oh-so-yummy for debugging.
11  */
12 
13 #include <stdarg.h>
14 
15 #include <linux/compiler.h>
16 #include <linux/ctype.h>
17 #include <linux/kernel.h>
18 #include <linux/limits.h>
19 #include <linux/string.h>
20 
21 static
22 int skip_atoi(const char **s)
23 {
24 	int i = 0;
25 
26 	while (isdigit(**s))
27 		i = i * 10 + *((*s)++) - '0';
28 	return i;
29 }
30 
31 /*
32  * put_dec_full4 handles numbers in the range 0 <= r < 10000.
33  * The multiplier 0xccd is round(2^15/10), and the approximation
34  * r/10 == (r * 0xccd) >> 15 is exact for all r < 16389.
35  */
36 static
37 void put_dec_full4(char *end, unsigned int r)
38 {
39 	int i;
40 
41 	for (i = 0; i < 3; i++) {
42 		unsigned int q = (r * 0xccd) >> 15;
43 		*--end = '0' + (r - q * 10);
44 		r = q;
45 	}
46 	*--end = '0' + r;
47 }
48 
49 /* put_dec is copied from lib/vsprintf.c with small modifications */
50 
51 /*
52  * Call put_dec_full4 on x % 10000, return x / 10000.
53  * The approximation x/10000 == (x * 0x346DC5D7) >> 43
54  * holds for all x < 1,128,869,999.  The largest value this
55  * helper will ever be asked to convert is 1,125,520,955.
56  * (second call in the put_dec code, assuming n is all-ones).
57  */
58 static
59 unsigned int put_dec_helper4(char *end, unsigned int x)
60 {
61 	unsigned int q = (x * 0x346DC5D7ULL) >> 43;
62 
63 	put_dec_full4(end, x - q * 10000);
64 	return q;
65 }
66 
67 /* Based on code by Douglas W. Jones found at
68  * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour>
69  * (with permission from the author).
70  * Performs no 64-bit division and hence should be fast on 32-bit machines.
71  */
72 static
73 char *put_dec(char *end, unsigned long long n)
74 {
75 	unsigned int d3, d2, d1, q, h;
76 	char *p = end;
77 
78 	d1  = ((unsigned int)n >> 16); /* implicit "& 0xffff" */
79 	h   = (n >> 32);
80 	d2  = (h      ) & 0xffff;
81 	d3  = (h >> 16); /* implicit "& 0xffff" */
82 
83 	/* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0
84 	     = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */
85 	q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((unsigned int)n & 0xffff);
86 	q = put_dec_helper4(p, q);
87 	p -= 4;
88 
89 	q += 7671 * d3 + 9496 * d2 + 6 * d1;
90 	q = put_dec_helper4(p, q);
91 	p -= 4;
92 
93 	q += 4749 * d3 + 42 * d2;
94 	q = put_dec_helper4(p, q);
95 	p -= 4;
96 
97 	q += 281 * d3;
98 	q = put_dec_helper4(p, q);
99 	p -= 4;
100 
101 	put_dec_full4(p, q);
102 	p -= 4;
103 
104 	/* strip off the extra 0's we printed */
105 	while (p < end && *p == '0')
106 		++p;
107 
108 	return p;
109 }
110 
111 static
112 char *number(char *end, unsigned long long num, int base, char locase)
113 {
114 	/*
115 	 * locase = 0 or 0x20. ORing digits or letters with 'locase'
116 	 * produces same digits or (maybe lowercased) letters
117 	 */
118 
119 	/* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
120 	static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
121 
122 	switch (base) {
123 	case 10:
124 		if (num != 0)
125 			end = put_dec(end, num);
126 		break;
127 	case 8:
128 		for (; num != 0; num >>= 3)
129 			*--end = '0' + (num & 07);
130 		break;
131 	case 16:
132 		for (; num != 0; num >>= 4)
133 			*--end = digits[num & 0xf] | locase;
134 		break;
135 	default:
136 		unreachable();
137 	};
138 
139 	return end;
140 }
141 
142 #define ZEROPAD	1		/* pad with zero */
143 #define SIGN	2		/* unsigned/signed long */
144 #define PLUS	4		/* show plus */
145 #define SPACE	8		/* space if plus */
146 #define LEFT	16		/* left justified */
147 #define SMALL	32		/* Must be 32 == 0x20 */
148 #define SPECIAL	64		/* 0x */
149 
150 static
151 int get_flags(const char **fmt)
152 {
153 	int flags = 0;
154 
155 	do {
156 		switch (**fmt) {
157 		case '-':
158 			flags |= LEFT;
159 			break;
160 		case '+':
161 			flags |= PLUS;
162 			break;
163 		case ' ':
164 			flags |= SPACE;
165 			break;
166 		case '#':
167 			flags |= SPECIAL;
168 			break;
169 		case '0':
170 			flags |= ZEROPAD;
171 			break;
172 		default:
173 			return flags;
174 		}
175 		++(*fmt);
176 	} while (1);
177 }
178 
179 static
180 int get_int(const char **fmt, va_list *ap)
181 {
182 	if (isdigit(**fmt))
183 		return skip_atoi(fmt);
184 	if (**fmt == '*') {
185 		++(*fmt);
186 		/* it's the next argument */
187 		return va_arg(*ap, int);
188 	}
189 	return 0;
190 }
191 
192 static
193 unsigned long long get_number(int sign, int qualifier, va_list *ap)
194 {
195 	if (sign) {
196 		switch (qualifier) {
197 		case 'L':
198 			return va_arg(*ap, long long);
199 		case 'l':
200 			return va_arg(*ap, long);
201 		case 'h':
202 			return (short)va_arg(*ap, int);
203 		case 'H':
204 			return (signed char)va_arg(*ap, int);
205 		default:
206 			return va_arg(*ap, int);
207 		};
208 	} else {
209 		switch (qualifier) {
210 		case 'L':
211 			return va_arg(*ap, unsigned long long);
212 		case 'l':
213 			return va_arg(*ap, unsigned long);
214 		case 'h':
215 			return (unsigned short)va_arg(*ap, int);
216 		case 'H':
217 			return (unsigned char)va_arg(*ap, int);
218 		default:
219 			return va_arg(*ap, unsigned int);
220 		}
221 	}
222 }
223 
224 static
225 char get_sign(long long *num, int flags)
226 {
227 	if (!(flags & SIGN))
228 		return 0;
229 	if (*num < 0) {
230 		*num = -(*num);
231 		return '-';
232 	}
233 	if (flags & PLUS)
234 		return '+';
235 	if (flags & SPACE)
236 		return ' ';
237 	return 0;
238 }
239 
240 int vsprintf(char *buf, const char *fmt, va_list ap)
241 {
242 	/* The maximum space required is to print a 64-bit number in octal */
243 	char tmp[(sizeof(unsigned long long) * 8 + 2) / 3];
244 	char *tmp_end = &tmp[ARRAY_SIZE(tmp)];
245 	long long num;
246 	int base;
247 	char *str;
248 	const char *s;
249 	int len;
250 	char sign;
251 
252 	int flags;		/* flags to number() */
253 
254 	int field_width;	/* width of output field */
255 	int precision;		/* min. # of digits for integers; max
256 				   number of chars for from string */
257 	int qualifier;		/* 'h', 'hh', 'l' or 'll' for integer fields */
258 
259 	va_list args;
260 
261 	/*
262 	 * We want to pass our input va_list to helper functions by reference,
263 	 * but there's an annoying edge case. If va_list was originally passed
264 	 * to us by value, we could just pass &ap down to the helpers. This is
265 	 * the case on, for example, X86_32.
266 	 * However, on X86_64 (and possibly others), va_list is actually a
267 	 * size-1 array containing a structure. Our function parameter ap has
268 	 * decayed from T[1] to T*, and &ap has type T** rather than T(*)[1],
269 	 * which is what will be expected by a function taking a va_list *
270 	 * parameter.
271 	 * One standard way to solve this mess is by creating a copy in a local
272 	 * variable of type va_list and then passing a pointer to that local
273 	 * copy instead, which is what we do here.
274 	 */
275 	va_copy(args, ap);
276 
277 	for (str = buf; *fmt; ++fmt) {
278 		if (*fmt != '%' || *++fmt == '%') {
279 			*str++ = *fmt;
280 			continue;
281 		}
282 
283 		/* process flags */
284 		flags = get_flags(&fmt);
285 
286 		/* get field width */
287 		field_width = get_int(&fmt, &args);
288 		if (field_width < 0) {
289 			field_width = -field_width;
290 			flags |= LEFT;
291 		}
292 
293 		if (flags & LEFT)
294 			flags &= ~ZEROPAD;
295 
296 		/* get the precision */
297 		precision = -1;
298 		if (*fmt == '.') {
299 			++fmt;
300 			precision = get_int(&fmt, &args);
301 			if (precision >= 0)
302 				flags &= ~ZEROPAD;
303 		}
304 
305 		/* get the conversion qualifier */
306 		qualifier = -1;
307 		if (*fmt == 'h' || *fmt == 'l') {
308 			qualifier = *fmt;
309 			++fmt;
310 			if (qualifier == *fmt) {
311 				qualifier -= 'a'-'A';
312 				++fmt;
313 			}
314 		}
315 
316 		sign = 0;
317 
318 		switch (*fmt) {
319 		case 'c':
320 			flags &= LEFT;
321 			tmp[0] = (unsigned char)va_arg(args, int);
322 			s = tmp;
323 			precision = len = 1;
324 			goto output;
325 
326 		case 's':
327 			flags &= LEFT;
328 			if (precision < 0)
329 				precision = INT_MAX;
330 			s = va_arg(args, char *);
331 			if (!s)
332 				s = precision < 6 ? "" : "(null)";
333 			precision = len = strnlen(s, precision);
334 			goto output;
335 
336 			/* integer number formats - set up the flags and "break" */
337 		case 'o':
338 			base = 8;
339 			break;
340 
341 		case 'p':
342 			if (precision < 0)
343 				precision = 2 * sizeof(void *);
344 			fallthrough;
345 		case 'x':
346 			flags |= SMALL;
347 			fallthrough;
348 		case 'X':
349 			base = 16;
350 			break;
351 
352 		case 'd':
353 		case 'i':
354 			flags |= SIGN;
355 			fallthrough;
356 		case 'u':
357 			flags &= ~SPECIAL;
358 			base = 10;
359 			break;
360 
361 		default:
362 			*str++ = '%';
363 			if (*fmt)
364 				*str++ = *fmt;
365 			else
366 				--fmt;
367 			continue;
368 		}
369 		if (*fmt == 'p') {
370 			num = (unsigned long)va_arg(args, void *);
371 		} else {
372 			num = get_number(flags & SIGN, qualifier, &args);
373 		}
374 
375 		sign = get_sign(&num, flags);
376 		if (sign)
377 			--field_width;
378 
379 		s = number(tmp_end, num, base, flags & SMALL);
380 		len = tmp_end - s;
381 		/* default precision is 1 */
382 		if (precision < 0)
383 			precision = 1;
384 		/* precision is minimum number of digits to print */
385 		if (precision < len)
386 			precision = len;
387 		if (flags & SPECIAL) {
388 			/*
389 			 * For octal, a leading 0 is printed only if necessary,
390 			 * i.e. if it's not already there because of the
391 			 * precision.
392 			 */
393 			if (base == 8 && precision == len)
394 				++precision;
395 			/*
396 			 * For hexadecimal, the leading 0x is skipped if the
397 			 * output is empty, i.e. both the number and the
398 			 * precision are 0.
399 			 */
400 			if (base == 16 && precision > 0)
401 				field_width -= 2;
402 			else
403 				flags &= ~SPECIAL;
404 		}
405 		/*
406 		 * For zero padding, increase the precision to fill the field
407 		 * width.
408 		 */
409 		if ((flags & ZEROPAD) && field_width > precision)
410 			precision = field_width;
411 
412 output:
413 		/* Calculate the padding necessary */
414 		field_width -= precision;
415 		/* Leading padding with ' ' */
416 		if (!(flags & LEFT))
417 			while (field_width-- > 0)
418 				*str++ = ' ';
419 		/* sign */
420 		if (sign)
421 			*str++ = sign;
422 		/* 0x/0X for hexadecimal */
423 		if (flags & SPECIAL) {
424 			*str++ = '0';
425 			*str++ = 'X' | (flags & SMALL);
426 		}
427 		/* Zero padding and excess precision */
428 		while (precision-- > len)
429 			*str++ = '0';
430 		/* Actual output */
431 		while (len-- > 0)
432 			*str++ = *s++;
433 		/* Trailing padding with ' ' */
434 		while (field_width-- > 0)
435 			*str++ = ' ';
436 	}
437 	*str = '\0';
438 
439 	va_end(args);
440 
441 	return str - buf;
442 }
443 
444 int sprintf(char *buf, const char *fmt, ...)
445 {
446 	va_list args;
447 	int i;
448 
449 	va_start(args, fmt);
450 	i = vsprintf(buf, fmt, args);
451 	va_end(args);
452 	return i;
453 }
454