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