]> git.proxmox.com Git - grub2.git/blame - grub-core/kern/misc.c
* grub-core/hook/datehook.c (grub_read_hook_datetime): Small stylistic
[grub2.git] / grub-core / kern / misc.c
CommitLineData
6a161fa9 1/* misc.c - definitions of misc functions */
2/*
4b13b216 3 * GRUB -- GRand Unified Bootloader
18f81dfc 4 * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
6a161fa9 5 *
5a79f472 6 * GRUB is free software: you can redistribute it and/or modify
6a161fa9 7 * it under the terms of the GNU General Public License as published by
5a79f472 8 * the Free Software Foundation, either version 3 of the License, or
6a161fa9 9 * (at your option) any later version.
10 *
5a79f472 11 * GRUB is distributed in the hope that it will be useful,
6a161fa9 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
5a79f472 17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
6a161fa9 18 */
19
4b13b216 20#include <grub/misc.h>
21#include <grub/err.h>
22#include <grub/mm.h>
6a161fa9 23#include <stdarg.h>
4b13b216 24#include <grub/term.h>
25#include <grub/env.h>
4a8572e9 26#include <grub/i18n.h>
6a161fa9 27
8b442f3f
VS
28static int
29grub_vsnprintf_real (char *str, grub_size_t n, const char *fmt, va_list args);
30
70f1161d 31static int
32grub_iswordseparator (int c)
33{
34 return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
35}
36
4a8572e9 37/* grub_gettext_dummy is not translating anything. */
007d0695 38static const char *
4a8572e9
CPE
39grub_gettext_dummy (const char *s)
40{
41 return s;
42}
43
203ffbfa
CPE
44const char* (*grub_gettext) (const char *s) = grub_gettext_dummy;
45
6a161fa9 46void *
4b13b216 47grub_memmove (void *dest, const void *src, grub_size_t n)
6a161fa9 48{
49 char *d = (char *) dest;
a5ffe966 50 const char *s = (const char *) src;
51
52 if (d < s)
53 while (n--)
54 *d++ = *s++;
55 else
56 {
57 d += n;
58 s += n;
b39f9d20 59
a5ffe966 60 while (n--)
61 *--d = *--s;
62 }
b39f9d20 63
6a161fa9 64 return dest;
65}
6c688477 66
67#ifndef APPLE_CC
062b24c2 68void *memmove (void *dest, const void *src, grub_size_t n)
69 __attribute__ ((alias ("grub_memmove")));
8c8cc205 70/* GCC emits references to memcpy() for struct copies etc. */
4b13b216 71void *memcpy (void *dest, const void *src, grub_size_t n)
72 __attribute__ ((alias ("grub_memmove")));
6c688477 73#else
74void *memcpy (void *dest, const void *src, grub_size_t n)
75{
76 return grub_memmove (dest, src, n);
77}
78void *memmove (void *dest, const void *src, grub_size_t n)
79{
80 return grub_memmove (dest, src, n);
81}
82#endif
6a161fa9 83
a5ffe966 84char *
4b13b216 85grub_strcpy (char *dest, const char *src)
a5ffe966 86{
87 char *p = dest;
88
89 while ((*p++ = *src++) != '\0')
90 ;
91
92 return dest;
93}
94
a35eed7c 95char *
4b13b216 96grub_strncpy (char *dest, const char *src, int c)
a35eed7c 97{
98 char *p = dest;
b39f9d20 99
e15199cb 100 while ((*p++ = *src++) != '\0' && --c)
101 ;
a35eed7c 102
103 return dest;
104}
105
9a5c1ade 106char *
4b13b216 107grub_stpcpy (char *dest, const char *src)
9a5c1ade 108{
109 char *d = dest;
110 const char *s = src;
111
112 do
113 *d++ = *s;
114 while (*s++ != '\0');
115
116 return d - 1;
117}
118
6a161fa9 119int
4b13b216 120grub_printf (const char *fmt, ...)
6a161fa9 121{
122 va_list ap;
123 int ret;
b39f9d20 124
6a161fa9 125 va_start (ap, fmt);
4b13b216 126 ret = grub_vprintf (fmt, ap);
6a161fa9 127 va_end (ap);
128
129 return ret;
b39f9d20 130}
6a161fa9 131
e3069ec1
CPE
132int
133grub_printf_ (const char *fmt, ...)
134{
135 va_list ap;
136 int ret;
137
138 va_start (ap, fmt);
139 ret = grub_vprintf (_(fmt), ap);
140 va_end (ap);
141
142 return ret;
143}
144
c4a3e41a
CPE
145int
146grub_puts_ (const char *s)
147{
148 return grub_puts (_(s));
149}
150
6c688477 151#if defined (APPLE_CC) && ! defined (GRUB_UTIL)
152int
153grub_err_printf (const char *fmt, ...)
154{
155 va_list ap;
156 int ret;
b39f9d20 157
6c688477 158 va_start (ap, fmt);
159 ret = grub_vprintf (fmt, ap);
160 va_end (ap);
b39f9d20 161
6c688477 162 return ret;
b39f9d20 163}
6c688477 164#endif
165
166#if ! defined (APPLE_CC) && ! defined (GRUB_UTIL)
b86408f8 167int grub_err_printf (const char *fmt, ...)
168__attribute__ ((alias("grub_printf")));
169#endif
170
708b345f 171void
9cacaa17 172grub_real_dprintf (const char *file, const int line, const char *condition,
173 const char *fmt, ...)
708b345f 174{
175 va_list args;
176 const char *debug = grub_env_get ("debug");
b39f9d20 177
708b345f 178 if (! debug)
179 return;
b39f9d20 180
708b345f 181 if (grub_strword (debug, "all") || grub_strword (debug, condition))
182 {
9cacaa17 183 grub_printf ("%s:%d: ", file, line);
708b345f 184 va_start (args, fmt);
185 grub_vprintf (fmt, args);
186 va_end (args);
3626810e 187 grub_refresh ();
708b345f 188 }
189}
190
dfed5c6b
VS
191#define PREALLOC_SIZE 255
192
6a161fa9 193int
4b13b216 194grub_vprintf (const char *fmt, va_list args)
6a161fa9 195{
dfed5c6b
VS
196 grub_size_t s;
197 static char buf[PREALLOC_SIZE + 1];
198 char *curbuf = buf;
768ec2e2
VS
199 va_list ap2;
200 va_copy (ap2, args);
4d4e372e 201
dfed5c6b
VS
202 s = grub_vsnprintf_real (buf, PREALLOC_SIZE, fmt, args);
203 if (s > PREALLOC_SIZE)
204 {
205 curbuf = grub_malloc (s + 1);
206 if (!curbuf)
207 {
208 grub_errno = GRUB_ERR_NONE;
209 buf[PREALLOC_SIZE - 3] = '.';
210 buf[PREALLOC_SIZE - 2] = '.';
211 buf[PREALLOC_SIZE - 1] = '.';
212 buf[PREALLOC_SIZE] = 0;
84beb0ee 213 curbuf = buf;
dfed5c6b
VS
214 }
215 else
768ec2e2 216 s = grub_vsnprintf_real (curbuf, s, fmt, ap2);
dfed5c6b
VS
217 }
218
c1860f87
VS
219 va_end (ap2);
220
dfed5c6b
VS
221 grub_xputs (curbuf);
222
223 if (curbuf != buf)
224 grub_free (curbuf);
225
226 return s;
6a161fa9 227}
228
229int
4b13b216 230grub_memcmp (const void *s1, const void *s2, grub_size_t n)
6a161fa9 231{
232 const char *t1 = s1;
233 const char *t2 = s2;
b39f9d20 234
6a161fa9 235 while (n--)
236 {
237 if (*t1 != *t2)
238 return (int) *t1 - (int) *t2;
239
240 t1++;
241 t2++;
242 }
243
244 return 0;
245}
6c688477 246#ifndef APPLE_CC
21c8cbb1 247int memcmp (const void *s1, const void *s2, grub_size_t n)
062b24c2 248 __attribute__ ((alias ("grub_memcmp")));
18f81dfc
YB
249#else
250int memcmp (const void *s1, const void *s2, grub_size_t n)
251{
252 return grub_memcmp (s1, s2, n);
253}
6c688477 254#endif
6a161fa9 255
256int
4b13b216 257grub_strcmp (const char *s1, const char *s2)
6a161fa9 258{
259 while (*s1 && *s2)
260 {
261 if (*s1 != *s2)
1806b56e 262 break;
b39f9d20 263
6a161fa9 264 s1++;
265 s2++;
266 }
267
268 return (int) *s1 - (int) *s2;
269}
270
a35eed7c 271int
8de3495c 272grub_strncmp (const char *s1, const char *s2, grub_size_t n)
a35eed7c 273{
8de3495c 274 if (n == 0)
275 return 0;
b39f9d20 276
8de3495c 277 while (*s1 && *s2 && --n)
a35eed7c 278 {
279 if (*s1 != *s2)
1806b56e 280 break;
b39f9d20 281
a35eed7c 282 s1++;
283 s2++;
a35eed7c 284 }
285
286 return (int) *s1 - (int) *s2;
287}
288
6a161fa9 289char *
4b13b216 290grub_strchr (const char *s, int c)
6a161fa9 291{
a50569e1 292 do
6a161fa9 293 {
294 if (*s == c)
295 return (char *) s;
6a161fa9 296 }
a50569e1 297 while (*s++);
6a161fa9 298
299 return 0;
300}
301
302char *
4b13b216 303grub_strrchr (const char *s, int c)
6a161fa9 304{
a50569e1 305 char *p = NULL;
6a161fa9 306
a50569e1 307 do
6a161fa9 308 {
309 if (*s == c)
310 p = (char *) s;
6a161fa9 311 }
a50569e1 312 while (*s++);
6a161fa9 313
314 return p;
315}
316
708b345f 317int
318grub_strword (const char *haystack, const char *needle)
319{
320 const char *n_pos = needle;
321
322 while (grub_iswordseparator (*haystack))
323 haystack++;
324
325 while (*haystack)
326 {
327 /* Crawl both the needle and the haystack word we're on. */
328 while(*haystack && !grub_iswordseparator (*haystack)
329 && *haystack == *n_pos)
330 {
331 haystack++;
332 n_pos++;
333 }
334
335 /* If we reached the end of both words at the same time, the word
336 is found. If not, eat everything in the haystack that isn't the
337 next word (or the end of string) and "reset" the needle. */
338 if ( (!*haystack || grub_iswordseparator (*haystack))
339 && (!*n_pos || grub_iswordseparator (*n_pos)))
340 return 1;
341 else
342 {
343 n_pos = needle;
344 while (*haystack && !grub_iswordseparator (*haystack))
345 haystack++;
346 while (grub_iswordseparator (*haystack))
347 haystack++;
348 }
349 }
350
351 return 0;
352}
353
6a161fa9 354int
4b13b216 355grub_isspace (int c)
6a161fa9 356{
357 return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
358}
359
360int
4b13b216 361grub_isprint (int c)
6a161fa9 362{
363 return (c >= ' ' && c <= '~');
364}
365
524a1e6a 366
6a161fa9 367unsigned long
4b13b216 368grub_strtoul (const char *str, char **end, int base)
6a161fa9 369{
524a1e6a 370 unsigned long long num;
371
372 num = grub_strtoull (str, end, base);
373 if (num > ~0UL)
374 {
375 grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
376 return ~0UL;
377 }
378
379 return (unsigned long) num;
380}
381
382unsigned long long
383grub_strtoull (const char *str, char **end, int base)
384{
385 unsigned long long num = 0;
6a161fa9 386 int found = 0;
b39f9d20 387
6a161fa9 388 /* Skip white spaces. */
4b13b216 389 while (*str && grub_isspace (*str))
6a161fa9 390 str++;
b39f9d20 391
6a161fa9 392 /* Guess the base, if not specified. The prefix `0x' means 16, and
393 the prefix `0' means 8. */
8cc50345 394 if (str[0] == '0')
6a161fa9 395 {
396 if (str[1] == 'x')
397 {
398 if (base == 0 || base == 16)
399 {
400 base = 16;
401 str += 2;
402 }
403 }
8cc50345 404 else if (base == 0 && str[1] >= '0' && str[1] <= '7')
6a161fa9 405 base = 8;
406 }
b39f9d20 407
6a161fa9 408 if (base == 0)
409 base = 10;
410
411 while (*str)
412 {
413 unsigned long digit;
414
4b13b216 415 digit = grub_tolower (*str) - '0';
6a161fa9 416 if (digit > 9)
417 {
418 digit += '0' - 'a' + 10;
419 if (digit >= (unsigned long) base)
420 break;
421 }
422
423 found = 1;
524a1e6a 424
425 /* NUM * BASE + DIGIT > ~0ULL */
426 if (num > grub_divmod64 (~0ULL - digit, base, 0))
6a161fa9 427 {
4b13b216 428 grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
524a1e6a 429 return ~0ULL;
6a161fa9 430 }
431
e15199cb 432 num = num * base + digit;
6a161fa9 433 str++;
434 }
435
436 if (! found)
437 {
4b13b216 438 grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number");
6a161fa9 439 return 0;
440 }
b39f9d20 441
6a161fa9 442 if (end)
443 *end = (char *) str;
444
445 return num;
446}
447
448char *
4b13b216 449grub_strdup (const char *s)
6a161fa9 450{
4b13b216 451 grub_size_t len;
6a161fa9 452 char *p;
b39f9d20 453
4b13b216 454 len = grub_strlen (s) + 1;
455 p = (char *) grub_malloc (len);
5aded270 456 if (! p)
457 return 0;
458
4b13b216 459 return grub_memcpy (p, s, len);
5aded270 460}
461
462char *
4b13b216 463grub_strndup (const char *s, grub_size_t n)
5aded270 464{
e3741a27 465 grub_size_t len;
466 char *p;
b39f9d20 467
e3741a27 468 len = grub_strlen (s);
469 if (len > n)
470 len = n;
471 p = (char *) grub_malloc (len + 1);
6a161fa9 472 if (! p)
473 return 0;
b39f9d20 474
e3741a27 475 grub_memcpy (p, s, len);
476 p[len] = '\0';
477 return p;
6a161fa9 478}
479
480void *
7decd202 481grub_memset (void *s, int c, grub_size_t len)
6a161fa9 482{
7decd202
VS
483 void *p = s;
484 grub_uint8_t pattern8 = c;
6a161fa9 485
7decd202
VS
486 if (len >= 3 * sizeof (unsigned long))
487 {
488 unsigned long patternl = 0;
489 grub_size_t i;
490
491 for (i = 0; i < sizeof (unsigned long); i++)
492 patternl |= ((unsigned long) pattern8) << (8 * i);
493
494 while (len > 0 && (((grub_addr_t) p) & (sizeof (unsigned long) - 1)))
495 {
496 *(grub_uint8_t *) p = pattern8;
497 p = (grub_uint8_t *) p + 1;
498 len--;
499 }
500 while (len >= sizeof (unsigned long))
501 {
502 *(unsigned long *) p = patternl;
503 p = (unsigned long *) p + 1;
504 len -= sizeof (unsigned long);
505 }
506 }
507
508 while (len > 0)
509 {
510 *(grub_uint8_t *) p = pattern8;
511 p = (grub_uint8_t *) p + 1;
512 len--;
513 }
6a161fa9 514
515 return s;
516}
6c688477 517#ifndef APPLE_CC
062b24c2 518void *memset (void *s, int c, grub_size_t n)
519 __attribute__ ((alias ("grub_memset")));
18f81dfc
YB
520#else
521void *memset (void *s, int c, grub_size_t n)
522{
523 return grub_memset (s, c, n);
524}
6c688477 525#endif
6a161fa9 526
4b13b216 527grub_size_t
528grub_strlen (const char *s)
6a161fa9 529{
a5ffe966 530 const char *p = s;
6a161fa9 531
532 while (*p)
533 p++;
534
535 return p - s;
536}
537
538static inline void
4b13b216 539grub_reverse (char *str)
6a161fa9 540{
4b13b216 541 char *p = str + grub_strlen (str) - 1;
6a161fa9 542
543 while (str < p)
544 {
545 char tmp;
546
547 tmp = *str;
548 *str = *p;
549 *p = tmp;
550 str++;
551 p--;
552 }
553}
554
524a1e6a 555/* Divide N by D, return the quotient, and store the remainder in *R. */
556grub_uint64_t
bf947d36 557grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
524a1e6a 558{
559 /* This algorithm is typically implemented by hardware. The idea
560 is to get the highest bit in N, 64 times, by keeping
93a777e3 561 upper(N * 2^i) = (Q * D + M), where upper
524a1e6a 562 represents the high 64 bits in 128-bits space. */
563 unsigned bits = 64;
93a777e3
VS
564 grub_uint64_t q = 0;
565 grub_uint64_t m = 0;
524a1e6a 566
cc85c3c3 567 /* Skip the slow computation if 32-bit arithmetic is possible. */
93a777e3 568 if (n < 0xffffffff && d < 0xffffffff)
524a1e6a 569 {
570 if (r)
93a777e3 571 *r = ((grub_uint32_t) n) % (grub_uint32_t) d;
524a1e6a 572
93a777e3 573 return ((grub_uint32_t) n) / (grub_uint32_t) d;
524a1e6a 574 }
b39f9d20 575
524a1e6a 576 while (bits--)
577 {
578 m <<= 1;
b39f9d20 579
524a1e6a 580 if (n & (1ULL << 63))
581 m |= 1;
b39f9d20 582
524a1e6a 583 q <<= 1;
584 n <<= 1;
b39f9d20 585
524a1e6a 586 if (m >= d)
587 {
588 q |= 1;
589 m -= d;
590 }
591 }
592
593 if (r)
594 *r = m;
b39f9d20 595
524a1e6a 596 return q;
597}
598
970d3b8a 599/* Convert a long long value to a string. This function avoids 64-bit
600 modular arithmetic or divisions. */
601static char *
602grub_lltoa (char *str, int c, unsigned long long n)
603{
604 unsigned base = (c == 'x') ? 16 : 10;
605 char *p;
b39f9d20 606
970d3b8a 607 if ((long long) n < 0 && c == 'd')
608 {
609 n = (unsigned long long) (-((long long) n));
610 *str++ = '-';
611 }
612
613 p = str;
614
615 if (base == 16)
616 do
617 {
618 unsigned d = (unsigned) (n & 0xf);
619 *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
620 }
621 while (n >>= 4);
622 else
623 /* BASE == 10 */
624 do
625 {
bf947d36 626 grub_uint64_t m;
b39f9d20 627
524a1e6a 628 n = grub_divmod64 (n, 10, &m);
49986a9f 629 *p++ = m + '0';
970d3b8a 630 }
631 while (n);
b39f9d20 632
970d3b8a 633 *p = 0;
634
635 grub_reverse (str);
636 return p;
637}
638
8b442f3f 639static int
11c22894 640grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt, va_list args)
6a161fa9 641{
642 char c;
8b442f3f 643 grub_size_t count = 0;
18d9c7cd 644 auto void write_char (unsigned char ch);
6a161fa9 645 auto void write_str (const char *s);
db1771cf 646 auto void write_fill (const char ch, int n);
b39f9d20 647
18d9c7cd 648 void write_char (unsigned char ch)
6a161fa9 649 {
dfed5c6b
VS
650 if (count < max_len)
651 *str++ = ch;
6a161fa9 652
653 count++;
654 }
655
656 void write_str (const char *s)
657 {
658 while (*s)
659 write_char (*s++);
660 }
db1771cf 661
662 void write_fill (const char ch, int n)
663 {
664 int i;
665 for (i = 0; i < n; i++)
666 write_char (ch);
667 }
b39f9d20 668
6a161fa9 669 while ((c = *fmt++) != 0)
670 {
671 if (c != '%')
672 write_char (c);
673 else
674 {
970d3b8a 675 char tmp[32];
6a161fa9 676 char *p;
db1771cf 677 unsigned int format1 = 0;
d31c24f1 678 unsigned int format2 = ~ 0U;
db1771cf 679 char zerofill = ' ';
680 int rightfill = 0;
6a161fa9 681 int n;
e75d76e1 682 int longfmt = 0;
970d3b8a 683 int longlongfmt = 0;
5999d619 684 int unsig = 0;
e75d76e1 685
db1771cf 686 if (*fmt && *fmt =='-')
687 {
688 rightfill = 1;
689 fmt++;
690 }
e75d76e1 691
db1771cf 692 p = (char *) fmt;
693 /* Read formatting parameters. */
4b13b216 694 while (*p && grub_isdigit (*p))
db1771cf 695 p++;
696
697 if (p > fmt)
698 {
25fe6f03 699 char s[p - fmt + 1];
4b13b216 700 grub_strncpy (s, fmt, p - fmt);
25fe6f03 701 s[p - fmt] = 0;
db1771cf 702 if (s[0] == '0')
703 zerofill = '0';
4b13b216 704 format1 = grub_strtoul (s, 0, 10);
db1771cf 705 fmt = p;
d31c24f1 706 }
707
708 if (*p && *p == '.')
709 {
710 p++;
711 fmt++;
712 while (*p && grub_isdigit (*p))
713 p++;
714
715 if (p > fmt)
db1771cf 716 {
d31c24f1 717 char fstr[p - fmt + 1];
718 grub_strncpy (fstr, fmt, p - fmt);
719 fstr[p - fmt] = 0;
720 format2 = grub_strtoul (fstr, 0, 10);
721 fmt = p;
db1771cf 722 }
723 }
724
725 c = *fmt++;
e75d76e1 726 if (c == 'l')
727 {
728 longfmt = 1;
729 c = *fmt++;
970d3b8a 730 if (c == 'l')
731 {
732 longlongfmt = 1;
733 c = *fmt++;
734 }
e75d76e1 735 }
db1771cf 736
6a161fa9 737 switch (c)
738 {
739 case 'p':
740 write_str ("0x");
741 c = 'x';
d1bc1b73 742 longlongfmt |= (sizeof (void *) == sizeof (long long));
5999d619 743 /* Fall through. */
6a161fa9 744 case 'x':
745 case 'u':
5999d619 746 unsig = 1;
747 /* Fall through. */
6a161fa9 748 case 'd':
970d3b8a 749 if (longlongfmt)
750 {
751 long long ll;
752
753 ll = va_arg (args, long long);
754 grub_lltoa (tmp, c, ll);
755 }
5999d619 756 else if (longfmt && unsig)
757 {
758 unsigned long l = va_arg (args, unsigned long);
759 grub_lltoa (tmp, c, l);
760 }
ed3d2bc2 761 else if (longfmt)
762 {
763 long l = va_arg (args, long);
5999d619 764 grub_lltoa (tmp, c, l);
765 }
766 else if (unsig)
767 {
768 unsigned u = va_arg (args, unsigned);
769 grub_lltoa (tmp, c, u);
ed3d2bc2 770 }
e75d76e1 771 else
970d3b8a 772 {
ed3d2bc2 773 n = va_arg (args, int);
5999d619 774 grub_lltoa (tmp, c, n);
970d3b8a 775 }
776 if (! rightfill && grub_strlen (tmp) < format1)
4b13b216 777 write_fill (zerofill, format1 - grub_strlen (tmp));
6a161fa9 778 write_str (tmp);
4b13b216 779 if (rightfill && grub_strlen (tmp) < format1)
780 write_fill (zerofill, format1 - grub_strlen (tmp));
6a161fa9 781 break;
b39f9d20 782
6a161fa9 783 case 'c':
784 n = va_arg (args, int);
18d9c7cd 785 write_char (n & 0xff);
786 break;
787
788 case 'C':
789 {
4b13b216 790 grub_uint32_t code = va_arg (args, grub_uint32_t);
18d9c7cd 791 int shift;
792 unsigned mask;
b39f9d20 793
18d9c7cd 794 if (code <= 0x7f)
795 {
796 shift = 0;
797 mask = 0;
798 }
799 else if (code <= 0x7ff)
800 {
801 shift = 6;
802 mask = 0xc0;
803 }
804 else if (code <= 0xffff)
805 {
806 shift = 12;
807 mask = 0xe0;
808 }
809 else if (code <= 0x1fffff)
810 {
811 shift = 18;
812 mask = 0xf0;
813 }
814 else if (code <= 0x3ffffff)
815 {
816 shift = 24;
817 mask = 0xf8;
818 }
819 else if (code <= 0x7fffffff)
820 {
821 shift = 30;
822 mask = 0xfc;
823 }
824 else
825 {
826 code = '?';
827 shift = 0;
828 mask = 0;
829 }
830
831 write_char (mask | (code >> shift));
b39f9d20 832
18d9c7cd 833 for (shift -= 6; shift >= 0; shift -= 6)
834 write_char (0x80 | (0x3f & (code >> shift)));
835 }
6a161fa9 836 break;
837
838 case 's':
839 p = va_arg (args, char *);
840 if (p)
db1771cf 841 {
d31c24f1 842 grub_size_t len = 0;
843 while (len < format2 && p[len])
844 len++;
845
846 if (!rightfill && len < format1)
847 write_fill (zerofill, format1 - len);
848
849 grub_size_t i;
850 for (i = 0; i < len; i++)
851 write_char (*p++);
852
853 if (rightfill && len < format1)
854 write_fill (zerofill, format1 - len);
db1771cf 855 }
6a161fa9 856 else
857 write_str ("(null)");
b39f9d20 858
6a161fa9 859 break;
860
861 default:
862 write_char (c);
863 break;
864 }
865 }
866 }
867
dfed5c6b 868 *str = '\0';
1f7315a3 869
6a161fa9 870 return count;
871}
872
873int
8b442f3f
VS
874grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list ap)
875{
876 grub_size_t ret;
877
878 if (!n)
879 return 0;
880
881 n--;
882
883 ret = grub_vsnprintf_real (str, n, fmt, ap);
884
885 return ret < n ? ret : n;
886}
887
888int
889grub_snprintf (char *str, grub_size_t n, const char *fmt, ...)
6a161fa9 890{
891 va_list ap;
892 int ret;
b39f9d20 893
6a161fa9 894 va_start (ap, fmt);
8b442f3f
VS
895 ret = grub_vsnprintf (str, n, fmt, ap);
896 va_end (ap);
897
898 return ret;
899}
900
8b442f3f 901char *
61eb45ee 902grub_xvasprintf (const char *fmt, va_list ap)
8b442f3f
VS
903{
904 grub_size_t s, as = PREALLOC_SIZE;
905 char *ret;
906
907 while (1)
908 {
768ec2e2
VS
909 va_list ap2;
910 va_copy (ap2, ap);
8b442f3f
VS
911 ret = grub_malloc (as + 1);
912 if (!ret)
913 return NULL;
914
768ec2e2 915 s = grub_vsnprintf_real (ret, as, fmt, ap2);
c1860f87
VS
916
917 va_end (ap2);
918
8b442f3f
VS
919 if (s <= as)
920 return ret;
921
922 grub_free (ret);
923 as = s;
924 }
925}
926
927char *
61eb45ee 928grub_xasprintf (const char *fmt, ...)
8b442f3f
VS
929{
930 va_list ap;
931 char *ret;
932
933 va_start (ap, fmt);
61eb45ee 934 ret = grub_xvasprintf (fmt, ap);
6a161fa9 935 va_end (ap);
936
937 return ret;
938}
db1771cf 939
9cacaa17 940/* Abort GRUB. This function does not return. */
941void
942grub_abort (void)
943{
f4c623e1
VS
944 grub_printf ("\nAborted.");
945
8eca55a6
RM
946#ifndef GRUB_UTIL
947 if (grub_term_inputs)
948#endif
9cacaa17 949 {
f4c623e1
VS
950 grub_printf (" Press any key to exit.");
951 grub_getkey ();
9cacaa17 952 }
2965c7cc 953
9cacaa17 954 grub_exit ();
955}
6c688477 956
dda060dd 957#if ! defined (APPLE_CC) && !defined (GRUB_UTIL)
71538dff 958/* GCC emits references to abort(). */
959void abort (void) __attribute__ ((alias ("grub_abort")));
6c688477 960#endif
9035dce4 961
742f9232 962#if NEED_ENABLE_EXECUTE_STACK && !defined(GRUB_UTIL) && !defined(GRUB_MACHINE_EMU)
9035dce4 963/* Some gcc versions generate a call to this function
964 in trampolines for nested functions. */
af1f4f55 965void __enable_execute_stack (void *addr __attribute__ ((unused)))
9035dce4 966{
967}
968#endif
969
742f9232 970#if NEED_REGISTER_FRAME_INFO && !defined(GRUB_UTIL)
4b0cd8f8
VS
971void __register_frame_info (void)
972{
973}
974
975void __deregister_frame_info (void)
976{
977}
978#endif
fa4b8490 979