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