cca6b802b028d843811843dc865115af62ac4b8b
[linux-2.6-microblaze.git] / drivers / firmware / efi / libstub / vsprintf.c
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                         /*
363                          * Bail out if the conversion specifier is invalid.
364                          * There's probably a typo in the format string and the
365                          * remaining specifiers are unlikely to match up with
366                          * the arguments.
367                          */
368                         goto fail;
369                 }
370                 if (*fmt == 'p') {
371                         num = (unsigned long)va_arg(args, void *);
372                 } else {
373                         num = get_number(flags & SIGN, qualifier, &args);
374                 }
375
376                 sign = get_sign(&num, flags);
377                 if (sign)
378                         --field_width;
379
380                 s = number(tmp_end, num, base, flags & SMALL);
381                 len = tmp_end - s;
382                 /* default precision is 1 */
383                 if (precision < 0)
384                         precision = 1;
385                 /* precision is minimum number of digits to print */
386                 if (precision < len)
387                         precision = len;
388                 if (flags & SPECIAL) {
389                         /*
390                          * For octal, a leading 0 is printed only if necessary,
391                          * i.e. if it's not already there because of the
392                          * precision.
393                          */
394                         if (base == 8 && precision == len)
395                                 ++precision;
396                         /*
397                          * For hexadecimal, the leading 0x is skipped if the
398                          * output is empty, i.e. both the number and the
399                          * precision are 0.
400                          */
401                         if (base == 16 && precision > 0)
402                                 field_width -= 2;
403                         else
404                                 flags &= ~SPECIAL;
405                 }
406                 /*
407                  * For zero padding, increase the precision to fill the field
408                  * width.
409                  */
410                 if ((flags & ZEROPAD) && field_width > precision)
411                         precision = field_width;
412
413 output:
414                 /* Calculate the padding necessary */
415                 field_width -= precision;
416                 /* Leading padding with ' ' */
417                 if (!(flags & LEFT))
418                         while (field_width-- > 0)
419                                 *str++ = ' ';
420                 /* sign */
421                 if (sign)
422                         *str++ = sign;
423                 /* 0x/0X for hexadecimal */
424                 if (flags & SPECIAL) {
425                         *str++ = '0';
426                         *str++ = 'X' | (flags & SMALL);
427                 }
428                 /* Zero padding and excess precision */
429                 while (precision-- > len)
430                         *str++ = '0';
431                 /* Actual output */
432                 while (len-- > 0)
433                         *str++ = *s++;
434                 /* Trailing padding with ' ' */
435                 while (field_width-- > 0)
436                         *str++ = ' ';
437         }
438 fail:
439         *str = '\0';
440
441         va_end(args);
442
443         return str - buf;
444 }
445
446 int sprintf(char *buf, const char *fmt, ...)
447 {
448         va_list args;
449         int i;
450
451         va_start(args, fmt);
452         i = vsprintf(buf, fmt, args);
453         va_end(args);
454         return i;
455 }