1 /* Simple printf like functions taken from GRUB project */
4 * GRUB -- GRand Unified Bootloader
5 * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
7 * GRUB is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * GRUB is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
28 grub_printf (const char *fmt, ...)
34 ret = grub_vprintf (fmt, ap);
41 grub_vprintf (const char *fmt, va_list args)
45 ret = grub_vsprintf (0, fmt, args);
50 grub_strtoull (const char *str, char **end, int base)
52 unsigned long long num = 0;
55 /* Skip white spaces. */
56 while (*str && isspace (*str))
59 /* Guess the base, if not specified. The prefix `0x' means 16, and
60 the prefix `0' means 8. */
61 if (base == 0 && str[0] == '0')
65 if (base == 0 || base == 16)
71 else if (str[1] >= '0' && str[1] <= '7')
82 digit = tolower (*str) - '0';
85 digit += '0' - 'a' + 10;
86 if (digit >= (unsigned long) base)
92 /* NUM * BASE + DIGIT > ~0ULL */
93 if (num > grub_divmod64 (~0ULL - digit, base, 0))
95 /* grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected"); */
99 num = num * base + digit;
105 /* grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number"); */
116 grub_reverse (char *str)
118 char *p = str + strlen (str) - 1;
133 grub_itoa (char *str, int c, unsigned n)
135 unsigned base = (c == 'x') ? 16 : 10;
138 if ((int) n < 0 && c == 'd')
140 n = (unsigned) (-((int) n));
147 unsigned d = n % base;
148 *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
157 /* Divide N by D, return the quotient, and store the remainder in *R. */
159 grub_divmod64 (uint64_t n, uint32_t d, uint32_t *r)
161 /* This algorithm is typically implemented by hardware. The idea
162 is to get the highest bit in N, 64 times, by keeping
163 upper(N * 2^i) = upper((Q * 10 + M) * 2^i), where upper
164 represents the high 64 bits in 128-bits space. */
166 unsigned long long q = 0;
169 /* Skip the slow computation if 32-bit arithmetic is possible. */
173 *r = ((uint32_t) n) % d;
175 return ((uint32_t) n) / d;
182 if (n & (1ULL << 63))
201 /* Convert a long long value to a string. This function avoids 64-bit
202 modular arithmetic or divisions. */
204 grub_lltoa (char *str, int c, unsigned long long n)
206 unsigned base = (c == 'x') ? 16 : 10;
209 if ((long long) n < 0 && c == 'd')
211 n = (unsigned long long) (-((long long) n));
220 unsigned d = (unsigned) (n & 0xf);
221 *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
230 n = grub_divmod64 (n, 10, &m);
242 grub_vsprintf (char *str, const char *fmt, va_list args)
246 auto void write_char (unsigned char ch);
247 auto void write_str (const char *s);
248 auto void write_fill (const char ch, int n);
250 void write_char (unsigned char ch)
260 void write_str (const char *s)
266 void write_fill (const char ch, int n)
269 for (i = 0; i < n; i++)
273 while ((c = *fmt++) != 0)
281 unsigned int format1 = 0;
282 unsigned int format2 = 3;
289 if (*fmt && *fmt =='-')
296 /* Read formatting parameters. */
297 while (*p && isdigit (*p))
303 strncpy (s, fmt, p - fmt);
307 format1 = strtoul (s, 0, 10);
313 while (*p && isdigit (*p))
319 strncpy (fstr, fmt, p - fmt);
320 format2 = strtoul (fstr, 0, 10);
343 longlongfmt |= (sizeof (void *) == sizeof (long long));
352 ll = va_arg (args, long long);
353 grub_lltoa (tmp, c, ll);
358 n = va_arg (args, long);
360 n = va_arg (args, int);
361 grub_itoa (tmp, c, n);
363 if (! rightfill && strlen (tmp) < format1)
364 write_fill (zerofill, format1 - strlen (tmp));
366 if (rightfill && strlen (tmp) < format1)
367 write_fill (zerofill, format1 - strlen (tmp));
371 n = va_arg (args, int);
372 write_char (n & 0xff);
377 va_arg (args, double);
378 tmp[0] = '?'; /* Not implemented */
380 if (!rightfill && strlen (tmp) < format1)
381 write_fill (zerofill, format1 - strlen (tmp));
383 if (rightfill && strlen (tmp) < format1)
384 write_fill (zerofill, format1 - strlen (tmp));
390 uint32_t code = va_arg (args, uint32_t);
399 else if (code <= 0x7ff)
404 else if (code <= 0xffff)
409 else if (code <= 0x1fffff)
414 else if (code <= 0x3ffffff)
419 else if (code <= 0x7fffffff)
431 write_char (mask | (code >> shift));
433 for (shift -= 6; shift >= 0; shift -= 6)
434 write_char (0x80 | (0x3f & (code >> shift)));
439 p = va_arg (args, char *);
442 if (!rightfill && strlen (p) < format1)
443 write_fill (zerofill, format1 - strlen (p));
447 if (rightfill && strlen (p) < format1)
448 write_fill (zerofill, format1 - strlen (p));
451 write_str ("(null)");
469 grub_sprintf (char *str, const char *fmt, ...)
475 ret = grub_vsprintf (str, fmt, ap);