~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/boot/printf.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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.  This
 11  * version of printf() does not include 64-bit support.  "Live with
 12  * it."
 13  *
 14  */
 15 
 16 #include "boot.h"
 17 
 18 static int skip_atoi(const char **s)
 19 {
 20         int i = 0;
 21 
 22         while (isdigit(**s))
 23                 i = i * 10 + *((*s)++) - '';
 24         return i;
 25 }
 26 
 27 #define ZEROPAD 1               /* pad with zero */
 28 #define SIGN    2               /* unsigned/signed long */
 29 #define PLUS    4               /* show plus */
 30 #define SPACE   8               /* space if plus */
 31 #define LEFT    16              /* left justified */
 32 #define SMALL   32              /* Must be 32 == 0x20 */
 33 #define SPECIAL 64              /* 0x */
 34 
 35 #define __do_div(n, base) ({ \
 36 int __res; \
 37 __res = ((unsigned long) n) % (unsigned) base; \
 38 n = ((unsigned long) n) / (unsigned) base; \
 39 __res; })
 40 
 41 static char *number(char *str, long num, int base, int size, int precision,
 42                     int type)
 43 {
 44         /* we are called with base 8, 10 or 16, only, thus don't need "G..."  */
 45         static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
 46 
 47         char tmp[66];
 48         char c, sign, locase;
 49         int i;
 50 
 51         /* locase = 0 or 0x20. ORing digits or letters with 'locase'
 52          * produces same digits or (maybe lowercased) letters */
 53         locase = (type & SMALL);
 54         if (type & LEFT)
 55                 type &= ~ZEROPAD;
 56         if (base < 2 || base > 16)
 57                 return NULL;
 58         c = (type & ZEROPAD) ? '' : ' ';
 59         sign = 0;
 60         if (type & SIGN) {
 61                 if (num < 0) {
 62                         sign = '-';
 63                         num = -num;
 64                         size--;
 65                 } else if (type & PLUS) {
 66                         sign = '+';
 67                         size--;
 68                 } else if (type & SPACE) {
 69                         sign = ' ';
 70                         size--;
 71                 }
 72         }
 73         if (type & SPECIAL) {
 74                 if (base == 16)
 75                         size -= 2;
 76                 else if (base == 8)
 77                         size--;
 78         }
 79         i = 0;
 80         if (num == 0)
 81                 tmp[i++] = '';
 82         else
 83                 while (num != 0)
 84                         tmp[i++] = (digits[__do_div(num, base)] | locase);
 85         if (i > precision)
 86                 precision = i;
 87         size -= precision;
 88         if (!(type & (ZEROPAD + LEFT)))
 89                 while (size-- > 0)
 90                         *str++ = ' ';
 91         if (sign)
 92                 *str++ = sign;
 93         if (type & SPECIAL) {
 94                 if (base == 8)
 95                         *str++ = '';
 96                 else if (base == 16) {
 97                         *str++ = '';
 98                         *str++ = ('X' | locase);
 99                 }
100         }
101         if (!(type & LEFT))
102                 while (size-- > 0)
103                         *str++ = c;
104         while (i < precision--)
105                 *str++ = '';
106         while (i-- > 0)
107                 *str++ = tmp[i];
108         while (size-- > 0)
109                 *str++ = ' ';
110         return str;
111 }
112 
113 int vsprintf(char *buf, const char *fmt, va_list args)
114 {
115         int len;
116         unsigned long num;
117         int i, base;
118         char *str;
119         const char *s;
120 
121         int flags;              /* flags to number() */
122 
123         int field_width;        /* width of output field */
124         int precision;          /* min. # of digits for integers; max
125                                    number of chars for from string */
126         int qualifier;          /* 'h', 'l', or 'L' for integer fields */
127 
128         for (str = buf; *fmt; ++fmt) {
129                 if (*fmt != '%') {
130                         *str++ = *fmt;
131                         continue;
132                 }
133 
134                 /* process flags */
135                 flags = 0;
136               repeat:
137                 ++fmt;          /* this also skips first '%' */
138                 switch (*fmt) {
139                 case '-':
140                         flags |= LEFT;
141                         goto repeat;
142                 case '+':
143                         flags |= PLUS;
144                         goto repeat;
145                 case ' ':
146                         flags |= SPACE;
147                         goto repeat;
148                 case '#':
149                         flags |= SPECIAL;
150                         goto repeat;
151                 case '':
152                         flags |= ZEROPAD;
153                         goto repeat;
154                 }
155 
156                 /* get field width */
157                 field_width = -1;
158                 if (isdigit(*fmt))
159                         field_width = skip_atoi(&fmt);
160                 else if (*fmt == '*') {
161                         ++fmt;
162                         /* it's the next argument */
163                         field_width = va_arg(args, int);
164                         if (field_width < 0) {
165                                 field_width = -field_width;
166                                 flags |= LEFT;
167                         }
168                 }
169 
170                 /* get the precision */
171                 precision = -1;
172                 if (*fmt == '.') {
173                         ++fmt;
174                         if (isdigit(*fmt))
175                                 precision = skip_atoi(&fmt);
176                         else if (*fmt == '*') {
177                                 ++fmt;
178                                 /* it's the next argument */
179                                 precision = va_arg(args, int);
180                         }
181                         if (precision < 0)
182                                 precision = 0;
183                 }
184 
185                 /* get the conversion qualifier */
186                 qualifier = -1;
187                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
188                         qualifier = *fmt;
189                         ++fmt;
190                 }
191 
192                 /* default base */
193                 base = 10;
194 
195                 switch (*fmt) {
196                 case 'c':
197                         if (!(flags & LEFT))
198                                 while (--field_width > 0)
199                                         *str++ = ' ';
200                         *str++ = (unsigned char)va_arg(args, int);
201                         while (--field_width > 0)
202                                 *str++ = ' ';
203                         continue;
204 
205                 case 's':
206                         s = va_arg(args, char *);
207                         len = strnlen(s, precision);
208 
209                         if (!(flags & LEFT))
210                                 while (len < field_width--)
211                                         *str++ = ' ';
212                         for (i = 0; i < len; ++i)
213                                 *str++ = *s++;
214                         while (len < field_width--)
215                                 *str++ = ' ';
216                         continue;
217 
218                 case 'p':
219                         if (field_width == -1) {
220                                 field_width = 2 * sizeof(void *);
221                                 flags |= ZEROPAD;
222                         }
223                         str = number(str,
224                                      (unsigned long)va_arg(args, void *), 16,
225                                      field_width, precision, flags);
226                         continue;
227 
228                 case 'n':
229                         if (qualifier == 'l') {
230                                 long *ip = va_arg(args, long *);
231                                 *ip = (str - buf);
232                         } else {
233                                 int *ip = va_arg(args, int *);
234                                 *ip = (str - buf);
235                         }
236                         continue;
237 
238                 case '%':
239                         *str++ = '%';
240                         continue;
241 
242                         /* integer number formats - set up the flags and "break" */
243                 case 'o':
244                         base = 8;
245                         break;
246 
247                 case 'x':
248                         flags |= SMALL;
249                         fallthrough;
250                 case 'X':
251                         base = 16;
252                         break;
253 
254                 case 'd':
255                 case 'i':
256                         flags |= SIGN;
257                         break;
258 
259                 case 'u':
260                         break;
261 
262                 default:
263                         *str++ = '%';
264                         if (*fmt)
265                                 *str++ = *fmt;
266                         else
267                                 --fmt;
268                         continue;
269                 }
270                 if (qualifier == 'l')
271                         num = va_arg(args, unsigned long);
272                 else if (qualifier == 'h') {
273                         num = (unsigned short)va_arg(args, int);
274                         if (flags & SIGN)
275                                 num = (short)num;
276                 } else if (flags & SIGN)
277                         num = va_arg(args, int);
278                 else
279                         num = va_arg(args, unsigned int);
280                 str = number(str, num, base, field_width, precision, flags);
281         }
282         *str = '\0';
283         return str - buf;
284 }
285 
286 int sprintf(char *buf, const char *fmt, ...)
287 {
288         va_list args;
289         int i;
290 
291         va_start(args, fmt);
292         i = vsprintf(buf, fmt, args);
293         va_end(args);
294         return i;
295 }
296 
297 int printf(const char *fmt, ...)
298 {
299         char printf_buf[1024];
300         va_list args;
301         int printed;
302 
303         va_start(args, fmt);
304         printed = vsprintf(printf_buf, fmt, args);
305         va_end(args);
306 
307         puts(printf_buf);
308 
309         return printed;
310 }
311 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php