]> git.proxmox.com Git - grub2.git/blame - kern/misc.c
Merge mainline into asprintf
[grub2.git] / kern / misc.c
CommitLineData
6a161fa9 1/* misc.c - definitions of misc functions */
2/*
4b13b216 3 * GRUB -- GRand Unified Bootloader
1e901a75 4 * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 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
CPE
37/* grub_gettext_dummy is not translating anything. */
38const char *
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 while (*s)
149 {
150 grub_putchar (*s);
151 s++;
152 }
153 grub_putchar ('\n');
154
155 return 1; /* Cannot fail. */
156}
157
158int
159grub_puts_ (const char *s)
160{
161 return grub_puts (_(s));
162}
163
6c688477 164#if defined (APPLE_CC) && ! defined (GRUB_UTIL)
165int
166grub_err_printf (const char *fmt, ...)
167{
168 va_list ap;
169 int ret;
b39f9d20 170
6c688477 171 va_start (ap, fmt);
172 ret = grub_vprintf (fmt, ap);
173 va_end (ap);
b39f9d20 174
6c688477 175 return ret;
b39f9d20 176}
6c688477 177#endif
178
179#if ! defined (APPLE_CC) && ! defined (GRUB_UTIL)
b86408f8 180int grub_err_printf (const char *fmt, ...)
181__attribute__ ((alias("grub_printf")));
182#endif
183
708b345f 184void
9cacaa17 185grub_real_dprintf (const char *file, const int line, const char *condition,
186 const char *fmt, ...)
708b345f 187{
188 va_list args;
189 const char *debug = grub_env_get ("debug");
b39f9d20 190
708b345f 191 if (! debug)
192 return;
b39f9d20 193
708b345f 194 if (grub_strword (debug, "all") || grub_strword (debug, condition))
195 {
9cacaa17 196 grub_printf ("%s:%d: ", file, line);
708b345f 197 va_start (args, fmt);
198 grub_vprintf (fmt, args);
199 va_end (args);
200 }
201}
202
6a161fa9 203int
4b13b216 204grub_vprintf (const char *fmt, va_list args)
6a161fa9 205{
4d4e372e 206 int ret;
207
8b442f3f 208 ret = grub_vsnprintf_real (0, 0, fmt, args);
4d4e372e 209 grub_refresh ();
210 return ret;
6a161fa9 211}
212
213int
4b13b216 214grub_memcmp (const void *s1, const void *s2, grub_size_t n)
6a161fa9 215{
216 const char *t1 = s1;
217 const char *t2 = s2;
b39f9d20 218
6a161fa9 219 while (n--)
220 {
221 if (*t1 != *t2)
222 return (int) *t1 - (int) *t2;
223
224 t1++;
225 t2++;
226 }
227
228 return 0;
229}
6c688477 230#ifndef APPLE_CC
21c8cbb1 231int memcmp (const void *s1, const void *s2, grub_size_t n)
062b24c2 232 __attribute__ ((alias ("grub_memcmp")));
6c688477 233#endif
6a161fa9 234
235int
4b13b216 236grub_strcmp (const char *s1, const char *s2)
6a161fa9 237{
238 while (*s1 && *s2)
239 {
240 if (*s1 != *s2)
1806b56e 241 break;
b39f9d20 242
6a161fa9 243 s1++;
244 s2++;
245 }
246
247 return (int) *s1 - (int) *s2;
248}
249
a35eed7c 250int
8de3495c 251grub_strncmp (const char *s1, const char *s2, grub_size_t n)
a35eed7c 252{
8de3495c 253 if (n == 0)
254 return 0;
b39f9d20 255
8de3495c 256 while (*s1 && *s2 && --n)
a35eed7c 257 {
258 if (*s1 != *s2)
1806b56e 259 break;
b39f9d20 260
a35eed7c 261 s1++;
262 s2++;
a35eed7c 263 }
264
265 return (int) *s1 - (int) *s2;
266}
267
6a161fa9 268char *
4b13b216 269grub_strchr (const char *s, int c)
6a161fa9 270{
a50569e1 271 do
6a161fa9 272 {
273 if (*s == c)
274 return (char *) s;
6a161fa9 275 }
a50569e1 276 while (*s++);
6a161fa9 277
278 return 0;
279}
280
281char *
4b13b216 282grub_strrchr (const char *s, int c)
6a161fa9 283{
a50569e1 284 char *p = NULL;
6a161fa9 285
a50569e1 286 do
6a161fa9 287 {
288 if (*s == c)
289 p = (char *) s;
6a161fa9 290 }
a50569e1 291 while (*s++);
6a161fa9 292
293 return p;
294}
295
2b002173 296/* Copied from gnulib.
297 Written by Bruno Haible <bruno@clisp.org>, 2005. */
298char *
299grub_strstr (const char *haystack, const char *needle)
300{
301 /* Be careful not to look at the entire extent of haystack or needle
302 until needed. This is useful because of these two cases:
303 - haystack may be very long, and a match of needle found early,
304 - needle may be very long, and not even a short initial segment of
305 needle may be found in haystack. */
306 if (*needle != '\0')
307 {
308 /* Speed up the following searches of needle by caching its first
309 character. */
310 char b = *needle++;
b39f9d20 311
2b002173 312 for (;; haystack++)
313 {
314 if (*haystack == '\0')
315 /* No match. */
316 return NULL;
317 if (*haystack == b)
318 /* The first character matches. */
319 {
320 const char *rhaystack = haystack + 1;
321 const char *rneedle = needle;
322
323 for (;; rhaystack++, rneedle++)
324 {
325 if (*rneedle == '\0')
326 /* Found a match. */
327 return (char *) haystack;
328 if (*rhaystack == '\0')
329 /* No match. */
330 return NULL;
331 if (*rhaystack != *rneedle)
332 /* Nothing in this round. */
333 break;
334 }
335 }
336 }
337 }
338 else
339 return (char *) haystack;
340}
341
708b345f 342int
343grub_strword (const char *haystack, const char *needle)
344{
345 const char *n_pos = needle;
346
347 while (grub_iswordseparator (*haystack))
348 haystack++;
349
350 while (*haystack)
351 {
352 /* Crawl both the needle and the haystack word we're on. */
353 while(*haystack && !grub_iswordseparator (*haystack)
354 && *haystack == *n_pos)
355 {
356 haystack++;
357 n_pos++;
358 }
359
360 /* If we reached the end of both words at the same time, the word
361 is found. If not, eat everything in the haystack that isn't the
362 next word (or the end of string) and "reset" the needle. */
363 if ( (!*haystack || grub_iswordseparator (*haystack))
364 && (!*n_pos || grub_iswordseparator (*n_pos)))
365 return 1;
366 else
367 {
368 n_pos = needle;
369 while (*haystack && !grub_iswordseparator (*haystack))
370 haystack++;
371 while (grub_iswordseparator (*haystack))
372 haystack++;
373 }
374 }
375
376 return 0;
377}
378
6a161fa9 379int
4b13b216 380grub_isspace (int c)
6a161fa9 381{
382 return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
383}
384
385int
4b13b216 386grub_isprint (int c)
6a161fa9 387{
388 return (c >= ' ' && c <= '~');
389}
390
524a1e6a 391
6a161fa9 392unsigned long
4b13b216 393grub_strtoul (const char *str, char **end, int base)
6a161fa9 394{
524a1e6a 395 unsigned long long num;
396
397 num = grub_strtoull (str, end, base);
398 if (num > ~0UL)
399 {
400 grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
401 return ~0UL;
402 }
403
404 return (unsigned long) num;
405}
406
407unsigned long long
408grub_strtoull (const char *str, char **end, int base)
409{
410 unsigned long long num = 0;
6a161fa9 411 int found = 0;
b39f9d20 412
6a161fa9 413 /* Skip white spaces. */
4b13b216 414 while (*str && grub_isspace (*str))
6a161fa9 415 str++;
b39f9d20 416
6a161fa9 417 /* Guess the base, if not specified. The prefix `0x' means 16, and
418 the prefix `0' means 8. */
8cc50345 419 if (str[0] == '0')
6a161fa9 420 {
421 if (str[1] == 'x')
422 {
423 if (base == 0 || base == 16)
424 {
425 base = 16;
426 str += 2;
427 }
428 }
8cc50345 429 else if (base == 0 && str[1] >= '0' && str[1] <= '7')
6a161fa9 430 base = 8;
431 }
b39f9d20 432
6a161fa9 433 if (base == 0)
434 base = 10;
435
436 while (*str)
437 {
438 unsigned long digit;
439
4b13b216 440 digit = grub_tolower (*str) - '0';
6a161fa9 441 if (digit > 9)
442 {
443 digit += '0' - 'a' + 10;
444 if (digit >= (unsigned long) base)
445 break;
446 }
447
448 found = 1;
524a1e6a 449
450 /* NUM * BASE + DIGIT > ~0ULL */
451 if (num > grub_divmod64 (~0ULL - digit, base, 0))
6a161fa9 452 {
4b13b216 453 grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
524a1e6a 454 return ~0ULL;
6a161fa9 455 }
456
e15199cb 457 num = num * base + digit;
6a161fa9 458 str++;
459 }
460
461 if (! found)
462 {
4b13b216 463 grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number");
6a161fa9 464 return 0;
465 }
b39f9d20 466
6a161fa9 467 if (end)
468 *end = (char *) str;
469
470 return num;
471}
472
473char *
4b13b216 474grub_strdup (const char *s)
6a161fa9 475{
4b13b216 476 grub_size_t len;
6a161fa9 477 char *p;
b39f9d20 478
4b13b216 479 len = grub_strlen (s) + 1;
480 p = (char *) grub_malloc (len);
5aded270 481 if (! p)
482 return 0;
483
4b13b216 484 return grub_memcpy (p, s, len);
5aded270 485}
486
487char *
4b13b216 488grub_strndup (const char *s, grub_size_t n)
5aded270 489{
e3741a27 490 grub_size_t len;
491 char *p;
b39f9d20 492
e3741a27 493 len = grub_strlen (s);
494 if (len > n)
495 len = n;
496 p = (char *) grub_malloc (len + 1);
6a161fa9 497 if (! p)
498 return 0;
b39f9d20 499
e3741a27 500 grub_memcpy (p, s, len);
501 p[len] = '\0';
502 return p;
6a161fa9 503}
504
505void *
4b13b216 506grub_memset (void *s, int c, grub_size_t n)
6a161fa9 507{
508 unsigned char *p = (unsigned char *) s;
509
510 while (n--)
511 *p++ = (unsigned char) c;
512
513 return s;
514}
6c688477 515#ifndef APPLE_CC
062b24c2 516void *memset (void *s, int c, grub_size_t n)
517 __attribute__ ((alias ("grub_memset")));
6c688477 518#endif
6a161fa9 519
4b13b216 520grub_size_t
521grub_strlen (const char *s)
6a161fa9 522{
a5ffe966 523 const char *p = s;
6a161fa9 524
525 while (*p)
526 p++;
527
528 return p - s;
529}
530
531static inline void
4b13b216 532grub_reverse (char *str)
6a161fa9 533{
4b13b216 534 char *p = str + grub_strlen (str) - 1;
6a161fa9 535
536 while (str < p)
537 {
538 char tmp;
539
540 tmp = *str;
541 *str = *p;
542 *p = tmp;
543 str++;
544 p--;
545 }
546}
547
524a1e6a 548/* Divide N by D, return the quotient, and store the remainder in *R. */
549grub_uint64_t
550grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r)
551{
552 /* This algorithm is typically implemented by hardware. The idea
553 is to get the highest bit in N, 64 times, by keeping
554 upper(N * 2^i) = upper((Q * 10 + M) * 2^i), where upper
555 represents the high 64 bits in 128-bits space. */
556 unsigned bits = 64;
557 unsigned long long q = 0;
558 unsigned m = 0;
559
cc85c3c3 560 /* Skip the slow computation if 32-bit arithmetic is possible. */
524a1e6a 561 if (n < 0xffffffff)
562 {
563 if (r)
564 *r = ((grub_uint32_t) n) % d;
565
566 return ((grub_uint32_t) n) / d;
567 }
b39f9d20 568
524a1e6a 569 while (bits--)
570 {
571 m <<= 1;
b39f9d20 572
524a1e6a 573 if (n & (1ULL << 63))
574 m |= 1;
b39f9d20 575
524a1e6a 576 q <<= 1;
577 n <<= 1;
b39f9d20 578
524a1e6a 579 if (m >= d)
580 {
581 q |= 1;
582 m -= d;
583 }
584 }
585
586 if (r)
587 *r = m;
b39f9d20 588
524a1e6a 589 return q;
590}
591
970d3b8a 592/* Convert a long long value to a string. This function avoids 64-bit
593 modular arithmetic or divisions. */
594static char *
595grub_lltoa (char *str, int c, unsigned long long n)
596{
597 unsigned base = (c == 'x') ? 16 : 10;
598 char *p;
b39f9d20 599
970d3b8a 600 if ((long long) n < 0 && c == 'd')
601 {
602 n = (unsigned long long) (-((long long) n));
603 *str++ = '-';
604 }
605
606 p = str;
607
608 if (base == 16)
609 do
610 {
611 unsigned d = (unsigned) (n & 0xf);
612 *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
613 }
614 while (n >>= 4);
615 else
616 /* BASE == 10 */
617 do
618 {
524a1e6a 619 unsigned m;
b39f9d20 620
524a1e6a 621 n = grub_divmod64 (n, 10, &m);
49986a9f 622 *p++ = m + '0';
970d3b8a 623 }
624 while (n);
b39f9d20 625
970d3b8a 626 *p = 0;
627
628 grub_reverse (str);
629 return p;
630}
631
8b442f3f
VS
632static int
633grub_vsnprintf_real (char *str, grub_size_t n, const char *fmt, va_list args)
6a161fa9 634{
635 char c;
8b442f3f 636 grub_size_t count = 0;
18d9c7cd 637 auto void write_char (unsigned char ch);
6a161fa9 638 auto void write_str (const char *s);
db1771cf 639 auto void write_fill (const char ch, int n);
b39f9d20 640
18d9c7cd 641 void write_char (unsigned char ch)
6a161fa9 642 {
643 if (str)
8b442f3f
VS
644 {
645 if (count < n)
646 *str++ = ch;
647 }
6a161fa9 648 else
4b13b216 649 grub_putchar (ch);
6a161fa9 650
651 count++;
652 }
653
654 void write_str (const char *s)
655 {
656 while (*s)
657 write_char (*s++);
658 }
db1771cf 659
660 void write_fill (const char ch, int n)
661 {
662 int i;
663 for (i = 0; i < n; i++)
664 write_char (ch);
665 }
b39f9d20 666
6a161fa9 667 while ((c = *fmt++) != 0)
668 {
669 if (c != '%')
670 write_char (c);
671 else
672 {
970d3b8a 673 char tmp[32];
6a161fa9 674 char *p;
db1771cf 675 unsigned int format1 = 0;
d31c24f1 676 unsigned int format2 = ~ 0U;
db1771cf 677 char zerofill = ' ';
678 int rightfill = 0;
6a161fa9 679 int n;
e75d76e1 680 int longfmt = 0;
970d3b8a 681 int longlongfmt = 0;
5999d619 682 int unsig = 0;
e75d76e1 683
db1771cf 684 if (*fmt && *fmt =='-')
685 {
686 rightfill = 1;
687 fmt++;
688 }
e75d76e1 689
db1771cf 690 p = (char *) fmt;
691 /* Read formatting parameters. */
4b13b216 692 while (*p && grub_isdigit (*p))
db1771cf 693 p++;
694
695 if (p > fmt)
696 {
25fe6f03 697 char s[p - fmt + 1];
4b13b216 698 grub_strncpy (s, fmt, p - fmt);
25fe6f03 699 s[p - fmt] = 0;
db1771cf 700 if (s[0] == '0')
701 zerofill = '0';
4b13b216 702 format1 = grub_strtoul (s, 0, 10);
db1771cf 703 fmt = p;
d31c24f1 704 }
705
706 if (*p && *p == '.')
707 {
708 p++;
709 fmt++;
710 while (*p && grub_isdigit (*p))
711 p++;
712
713 if (p > fmt)
db1771cf 714 {
d31c24f1 715 char fstr[p - fmt + 1];
716 grub_strncpy (fstr, fmt, p - fmt);
717 fstr[p - fmt] = 0;
718 format2 = grub_strtoul (fstr, 0, 10);
719 fmt = p;
db1771cf 720 }
721 }
722
723 c = *fmt++;
e75d76e1 724 if (c == 'l')
725 {
726 longfmt = 1;
727 c = *fmt++;
970d3b8a 728 if (c == 'l')
729 {
730 longlongfmt = 1;
731 c = *fmt++;
732 }
e75d76e1 733 }
db1771cf 734
6a161fa9 735 switch (c)
736 {
737 case 'p':
738 write_str ("0x");
739 c = 'x';
d1bc1b73 740 longlongfmt |= (sizeof (void *) == sizeof (long long));
5999d619 741 /* Fall through. */
6a161fa9 742 case 'x':
743 case 'u':
5999d619 744 unsig = 1;
745 /* Fall through. */
6a161fa9 746 case 'd':
970d3b8a 747 if (longlongfmt)
748 {
749 long long ll;
750
751 ll = va_arg (args, long long);
752 grub_lltoa (tmp, c, ll);
753 }
5999d619 754 else if (longfmt && unsig)
755 {
756 unsigned long l = va_arg (args, unsigned long);
757 grub_lltoa (tmp, c, l);
758 }
ed3d2bc2 759 else if (longfmt)
760 {
761 long l = va_arg (args, long);
5999d619 762 grub_lltoa (tmp, c, l);
763 }
764 else if (unsig)
765 {
766 unsigned u = va_arg (args, unsigned);
767 grub_lltoa (tmp, c, u);
ed3d2bc2 768 }
e75d76e1 769 else
970d3b8a 770 {
ed3d2bc2 771 n = va_arg (args, int);
5999d619 772 grub_lltoa (tmp, c, n);
970d3b8a 773 }
774 if (! rightfill && grub_strlen (tmp) < format1)
4b13b216 775 write_fill (zerofill, format1 - grub_strlen (tmp));
6a161fa9 776 write_str (tmp);
4b13b216 777 if (rightfill && grub_strlen (tmp) < format1)
778 write_fill (zerofill, format1 - grub_strlen (tmp));
6a161fa9 779 break;
b39f9d20 780
6a161fa9 781 case 'c':
782 n = va_arg (args, int);
18d9c7cd 783 write_char (n & 0xff);
784 break;
785
786 case 'C':
787 {
4b13b216 788 grub_uint32_t code = va_arg (args, grub_uint32_t);
18d9c7cd 789 int shift;
790 unsigned mask;
b39f9d20 791
18d9c7cd 792 if (code <= 0x7f)
793 {
794 shift = 0;
795 mask = 0;
796 }
797 else if (code <= 0x7ff)
798 {
799 shift = 6;
800 mask = 0xc0;
801 }
802 else if (code <= 0xffff)
803 {
804 shift = 12;
805 mask = 0xe0;
806 }
807 else if (code <= 0x1fffff)
808 {
809 shift = 18;
810 mask = 0xf0;
811 }
812 else if (code <= 0x3ffffff)
813 {
814 shift = 24;
815 mask = 0xf8;
816 }
817 else if (code <= 0x7fffffff)
818 {
819 shift = 30;
820 mask = 0xfc;
821 }
822 else
823 {
824 code = '?';
825 shift = 0;
826 mask = 0;
827 }
828
829 write_char (mask | (code >> shift));
b39f9d20 830
18d9c7cd 831 for (shift -= 6; shift >= 0; shift -= 6)
832 write_char (0x80 | (0x3f & (code >> shift)));
833 }
6a161fa9 834 break;
835
836 case 's':
837 p = va_arg (args, char *);
838 if (p)
db1771cf 839 {
d31c24f1 840 grub_size_t len = 0;
841 while (len < format2 && p[len])
842 len++;
843
844 if (!rightfill && len < format1)
845 write_fill (zerofill, format1 - len);
846
847 grub_size_t i;
848 for (i = 0; i < len; i++)
849 write_char (*p++);
850
851 if (rightfill && len < format1)
852 write_fill (zerofill, format1 - len);
db1771cf 853 }
6a161fa9 854 else
855 write_str ("(null)");
b39f9d20 856
6a161fa9 857 break;
858
859 default:
860 write_char (c);
861 break;
862 }
863 }
864 }
865
866 if (str)
867 *str = '\0';
1f7315a3 868
869 if (count && !str)
4b13b216 870 grub_refresh ();
b39f9d20 871
6a161fa9 872 return count;
873}
874
875int
8b442f3f
VS
876grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list ap)
877{
878 grub_size_t ret;
879
880 if (!n)
881 return 0;
882
883 n--;
884
885 ret = grub_vsnprintf_real (str, n, fmt, ap);
886
887 return ret < n ? ret : n;
888}
889
890int
891grub_snprintf (char *str, grub_size_t n, const char *fmt, ...)
6a161fa9 892{
893 va_list ap;
894 int ret;
b39f9d20 895
6a161fa9 896 va_start (ap, fmt);
8b442f3f
VS
897 ret = grub_vsnprintf (str, n, fmt, ap);
898 va_end (ap);
899
900 return ret;
901}
902
903#define PREALLOC_SIZE 255
904
905char *
906grub_avsprintf (const char *fmt, va_list ap)
907{
908 grub_size_t s, as = PREALLOC_SIZE;
909 char *ret;
910
911 while (1)
912 {
913 ret = grub_malloc (as + 1);
914 if (!ret)
915 return NULL;
916
917 s = grub_vsnprintf (ret, as, fmt, ap);
918 if (s <= as)
919 return ret;
920
921 grub_free (ret);
922 as = s;
923 }
924}
925
926char *
927grub_asprintf (const char *fmt, ...)
928{
929 va_list ap;
930 char *ret;
931
932 va_start (ap, fmt);
933 ret = grub_avsprintf (fmt, ap);
6a161fa9 934 va_end (ap);
935
936 return ret;
937}
db1771cf 938
1e901a75 939/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
940 bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string.
941 Return the number of characters converted. DEST must be able to hold
942 at least DESTSIZE characters. If an invalid sequence is found, return -1.
943 If SRCEND is not NULL, then *SRCEND is set to the next byte after the
944 last byte used in SRC. */
ef095434 945grub_ssize_t
1e901a75 946grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
947 const grub_uint8_t *src, grub_size_t srcsize,
948 const grub_uint8_t **srcend)
ef095434 949{
950 grub_uint32_t *p = dest;
951 int count = 0;
952 grub_uint32_t code = 0;
b39f9d20 953
1e901a75 954 if (srcend)
955 *srcend = src;
956
957 while (srcsize && destsize)
ef095434 958 {
959 grub_uint32_t c = *src++;
1e901a75 960 if (srcsize != (grub_size_t)-1)
961 srcsize--;
ef095434 962 if (count)
963 {
964 if ((c & 0xc0) != 0x80)
965 {
966 /* invalid */
967 return -1;
968 }
969 else
970 {
971 code <<= 6;
972 code |= (c & 0x3f);
973 count--;
974 }
975 }
976 else
977 {
1e901a75 978 if (c == 0)
979 break;
b39f9d20 980
ef095434 981 if ((c & 0x80) == 0x00)
982 code = c;
983 else if ((c & 0xe0) == 0xc0)
984 {
985 count = 1;
986 code = c & 0x1f;
987 }
988 else if ((c & 0xf0) == 0xe0)
989 {
990 count = 2;
991 code = c & 0x0f;
992 }
993 else if ((c & 0xf8) == 0xf0)
994 {
995 count = 3;
996 code = c & 0x07;
997 }
998 else if ((c & 0xfc) == 0xf8)
999 {
1000 count = 4;
1001 code = c & 0x03;
1002 }
1003 else if ((c & 0xfe) == 0xfc)
1004 {
1005 count = 5;
1006 code = c & 0x01;
1007 }
1008 else
ef095434 1009 return -1;
1010 }
1011
1012 if (count == 0)
1e901a75 1013 {
1014 *p++ = code;
1015 destsize--;
1016 }
ef095434 1017 }
1018
1e901a75 1019 if (srcend)
1020 *srcend = src;
ef095434 1021 return p - dest;
1022}
9cacaa17 1023
1024/* Abort GRUB. This function does not return. */
1025void
1026grub_abort (void)
1027{
651c29b7 1028 if (grub_term_get_current_output ())
9cacaa17 1029 {
651c29b7 1030 grub_printf ("\nAborted.");
1031
1032 if (grub_term_get_current_input ())
1033 {
1034 grub_printf (" Press any key to exit.");
1035 grub_getkey ();
1036 }
9cacaa17 1037 }
2965c7cc 1038
9cacaa17 1039 grub_exit ();
1040}
6c688477 1041
1042#ifndef APPLE_CC
71538dff 1043/* GCC emits references to abort(). */
1044void abort (void) __attribute__ ((alias ("grub_abort")));
6c688477 1045#endif
9035dce4 1046
1047#ifdef NEED_ENABLE_EXECUTE_STACK
1048/* Some gcc versions generate a call to this function
1049 in trampolines for nested functions. */
af1f4f55 1050void __enable_execute_stack (void *addr __attribute__ ((unused)))
9035dce4 1051{
1052}
1053#endif
1054