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