Fix cross compilation (e.g. on Darwin). Following changes to make.tmpl,
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / kern / misc.c
blobc5c815d8d13b627f8529381ecd98fb7ee795c90e
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.
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.
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.
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/>.
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>
28 union printf_arg
30 /* Yes, type is also part of union as the moment we fill the value
31 we don't need to store its type anymore (when we'll need it, we'll
32 have format spec again. So save some space. */
33 enum
35 INT, LONG, LONGLONG,
36 UNSIGNED_INT = 3, UNSIGNED_LONG, UNSIGNED_LONGLONG
37 } type;
38 long long ll;
41 struct printf_args
43 union printf_arg prealloc[32];
44 union printf_arg *ptr;
45 grub_size_t count;
48 static void
49 parse_printf_args (const char *fmt0, struct printf_args *args,
50 va_list args_in);
51 static int
52 grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0,
53 struct printf_args *args);
55 static void
56 free_printf_args (struct printf_args *args)
58 if (args->ptr != args->prealloc)
59 grub_free (args->ptr);
62 static int
63 grub_iswordseparator (int c)
65 return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
68 /* grub_gettext_dummy is not translating anything. */
69 static const char *
70 grub_gettext_dummy (const char *s)
72 return s;
75 const char* (*grub_gettext) (const char *s) = grub_gettext_dummy;
77 void *
78 grub_memmove (void *dest, const void *src, grub_size_t n)
80 char *d = (char *) dest;
81 const char *s = (const char *) src;
83 if (d < s)
84 while (n--)
85 *d++ = *s++;
86 else
88 d += n;
89 s += n;
91 while (n--)
92 *--d = *--s;
95 return dest;
98 #ifndef __APPLE__
99 void *memmove (void *dest, const void *src, grub_size_t n)
100 __attribute__ ((alias ("grub_memmove")));
101 /* GCC emits references to memcpy() for struct copies etc. */
102 void *memcpy (void *dest, const void *src, grub_size_t n)
103 __attribute__ ((alias ("grub_memmove")));
104 #else
105 void * GRUB_BUILTIN_ATTR
106 memcpy (void *dest, const void *src, grub_size_t n)
108 return grub_memmove (dest, src, n);
110 void * GRUB_BUILTIN_ATTR
111 memmove (void *dest, const void *src, grub_size_t n)
113 return grub_memmove (dest, src, n);
115 #endif
117 char *
118 grub_strcpy (char *dest, const char *src)
120 char *p = dest;
122 while ((*p++ = *src++) != '\0')
125 return dest;
129 grub_printf (const char *fmt, ...)
131 va_list ap;
132 int ret;
134 va_start (ap, fmt);
135 ret = grub_vprintf (fmt, ap);
136 va_end (ap);
138 return ret;
142 grub_printf_ (const char *fmt, ...)
144 va_list ap;
145 int ret;
147 va_start (ap, fmt);
148 ret = grub_vprintf (_(fmt), ap);
149 va_end (ap);
151 return ret;
155 grub_puts_ (const char *s)
157 return grub_puts (_(s));
160 #if defined (__APPLE__) && ! defined (GRUB_UTIL)
162 grub_err_printf (const char *fmt, ...)
164 va_list ap;
165 int ret;
167 va_start (ap, fmt);
168 ret = grub_vprintf (fmt, ap);
169 va_end (ap);
171 return ret;
173 #endif
175 #if ! defined (__APPLE__) && ! defined (GRUB_UTIL)
176 int grub_err_printf (const char *fmt, ...)
177 __attribute__ ((alias("grub_printf")));
178 #endif
180 void
181 grub_real_dprintf (const char *file, const int line, const char *condition,
182 const char *fmt, ...)
184 va_list args;
185 const char *debug = grub_env_get ("debug");
187 if (! debug)
188 return;
190 if (grub_strword (debug, "all") || grub_strword (debug, condition))
192 grub_printf ("%s:%d: ", file, line);
193 va_start (args, fmt);
194 grub_vprintf (fmt, args);
195 va_end (args);
196 grub_refresh ();
200 #define PREALLOC_SIZE 255
203 grub_vprintf (const char *fmt, va_list ap)
205 grub_size_t s;
206 static char buf[PREALLOC_SIZE + 1];
207 char *curbuf = buf;
208 struct printf_args args;
210 parse_printf_args (fmt, &args, ap);
212 s = grub_vsnprintf_real (buf, PREALLOC_SIZE, fmt, &args);
213 if (s > PREALLOC_SIZE)
215 curbuf = grub_malloc (s + 1);
216 if (!curbuf)
218 grub_errno = GRUB_ERR_NONE;
219 buf[PREALLOC_SIZE - 3] = '.';
220 buf[PREALLOC_SIZE - 2] = '.';
221 buf[PREALLOC_SIZE - 1] = '.';
222 buf[PREALLOC_SIZE] = 0;
223 curbuf = buf;
225 else
226 s = grub_vsnprintf_real (curbuf, s, fmt, &args);
229 free_printf_args (&args);
231 grub_xputs (curbuf);
233 if (curbuf != buf)
234 grub_free (curbuf);
236 return s;
240 grub_memcmp (const void *s1, const void *s2, grub_size_t n)
242 const grub_uint8_t *t1 = s1;
243 const grub_uint8_t *t2 = s2;
245 while (n--)
247 if (*t1 != *t2)
248 return (int) *t1 - (int) *t2;
250 t1++;
251 t2++;
254 return 0;
256 #ifndef __APPLE__
257 int memcmp (const void *s1, const void *s2, grub_size_t n)
258 __attribute__ ((alias ("grub_memcmp")));
259 #else
260 int GRUB_BUILTIN_ATTR
261 memcmp (const void *s1, const void *s2, grub_size_t n)
263 return grub_memcmp (s1, s2, n);
265 #endif
268 grub_strcmp (const char *s1, const char *s2)
270 while (*s1 && *s2)
272 if (*s1 != *s2)
273 break;
275 s1++;
276 s2++;
279 return (int) (grub_uint8_t) *s1 - (int) (grub_uint8_t) *s2;
283 grub_strncmp (const char *s1, const char *s2, grub_size_t n)
285 if (n == 0)
286 return 0;
288 while (*s1 && *s2 && --n)
290 if (*s1 != *s2)
291 break;
293 s1++;
294 s2++;
297 return (int) (grub_uint8_t) *s1 - (int) (grub_uint8_t) *s2;
300 char *
301 grub_strchr (const char *s, int c)
305 if (*s == c)
306 return (char *) s;
308 while (*s++);
310 return 0;
313 char *
314 grub_strrchr (const char *s, int c)
316 char *p = NULL;
320 if (*s == c)
321 p = (char *) s;
323 while (*s++);
325 return p;
329 grub_strword (const char *haystack, const char *needle)
331 const char *n_pos = needle;
333 while (grub_iswordseparator (*haystack))
334 haystack++;
336 while (*haystack)
338 /* Crawl both the needle and the haystack word we're on. */
339 while(*haystack && !grub_iswordseparator (*haystack)
340 && *haystack == *n_pos)
342 haystack++;
343 n_pos++;
346 /* If we reached the end of both words at the same time, the word
347 is found. If not, eat everything in the haystack that isn't the
348 next word (or the end of string) and "reset" the needle. */
349 if ( (!*haystack || grub_iswordseparator (*haystack))
350 && (!*n_pos || grub_iswordseparator (*n_pos)))
351 return 1;
352 else
354 n_pos = needle;
355 while (*haystack && !grub_iswordseparator (*haystack))
356 haystack++;
357 while (grub_iswordseparator (*haystack))
358 haystack++;
362 return 0;
366 grub_isspace (int c)
368 return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
371 unsigned long
372 grub_strtoul (const char *str, char **end, int base)
374 unsigned long long num;
376 num = grub_strtoull (str, end, base);
377 #if GRUB_CPU_SIZEOF_LONG != 8
378 if (num > ~0UL)
380 grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
381 return ~0UL;
383 #endif
385 return (unsigned long) num;
388 unsigned long long
389 grub_strtoull (const char *str, char **end, int base)
391 unsigned long long num = 0;
392 int found = 0;
394 /* Skip white spaces. */
395 /* grub_isspace checks that *str != '\0'. */
396 while (grub_isspace (*str))
397 str++;
399 /* Guess the base, if not specified. The prefix `0x' means 16, and
400 the prefix `0' means 8. */
401 if (str[0] == '0')
403 if (str[1] == 'x')
405 if (base == 0 || base == 16)
407 base = 16;
408 str += 2;
411 else if (base == 0 && str[1] >= '0' && str[1] <= '7')
412 base = 8;
415 if (base == 0)
416 base = 10;
418 while (*str)
420 unsigned long digit;
422 digit = grub_tolower (*str) - '0';
423 if (digit > 9)
425 digit += '0' - 'a' + 10;
426 if (digit >= (unsigned long) base)
427 break;
430 found = 1;
432 /* NUM * BASE + DIGIT > ~0ULL */
433 if (num > grub_divmod64 (~0ULL - digit, base, 0))
435 grub_error (GRUB_ERR_OUT_OF_RANGE,
436 N_("overflow is detected"));
437 return ~0ULL;
440 num = num * base + digit;
441 str++;
444 if (! found)
446 grub_error (GRUB_ERR_BAD_NUMBER,
447 N_("unrecognized number"));
448 return 0;
451 if (end)
452 *end = (char *) str;
454 return num;
457 char *
458 grub_strdup (const char *s)
460 grub_size_t len;
461 char *p;
463 len = grub_strlen (s) + 1;
464 p = (char *) grub_malloc (len);
465 if (! p)
466 return 0;
468 return grub_memcpy (p, s, len);
471 char *
472 grub_strndup (const char *s, grub_size_t n)
474 grub_size_t len;
475 char *p;
477 len = grub_strlen (s);
478 if (len > n)
479 len = n;
480 p = (char *) grub_malloc (len + 1);
481 if (! p)
482 return 0;
484 grub_memcpy (p, s, len);
485 p[len] = '\0';
486 return p;
489 /* clang detects that we're implementing here a memset so it decides to
490 optimise and calls memset resulting in infinite recursion. With volatile
491 we make it not optimise in this way. */
492 #ifdef __clang__
493 #define VOLATILE_CLANG volatile
494 #else
495 #define VOLATILE_CLANG
496 #endif
498 void *
499 grub_memset (void *s, int c, grub_size_t len)
501 void *p = s;
502 grub_uint8_t pattern8 = c;
504 if (len >= 3 * sizeof (unsigned long))
506 unsigned long patternl = 0;
507 grub_size_t i;
509 for (i = 0; i < sizeof (unsigned long); i++)
510 patternl |= ((unsigned long) pattern8) << (8 * i);
512 while (len > 0 && (((grub_addr_t) p) & (sizeof (unsigned long) - 1)))
514 *(VOLATILE_CLANG grub_uint8_t *) p = pattern8;
515 p = (grub_uint8_t *) p + 1;
516 len--;
518 while (len >= sizeof (unsigned long))
520 *(VOLATILE_CLANG unsigned long *) p = patternl;
521 p = (unsigned long *) p + 1;
522 len -= sizeof (unsigned long);
526 while (len > 0)
528 *(VOLATILE_CLANG grub_uint8_t *) p = pattern8;
529 p = (grub_uint8_t *) p + 1;
530 len--;
533 return s;
535 #ifndef __APPLE__
536 void *memset (void *s, int c, grub_size_t n)
537 __attribute__ ((alias ("grub_memset")));
538 #else
539 void * GRUB_BUILTIN_ATTR
540 memset (void *s, int c, grub_size_t n)
542 return grub_memset (s, c, n);
545 #endif
547 #if !defined(GRUB_UTIL) && defined(__APPLE__)
548 void GRUB_BUILTIN_ATTR
549 __bzero (void *s, grub_size_t n)
551 grub_memset (s, 0, n);
554 #endif
556 grub_size_t
557 grub_strlen (const char *s)
559 const char *p = s;
561 while (*p)
562 p++;
564 return p - s;
567 static inline void
568 grub_reverse (char *str)
570 char *p = str + grub_strlen (str) - 1;
572 while (str < p)
574 char tmp;
576 tmp = *str;
577 *str = *p;
578 *p = tmp;
579 str++;
580 p--;
584 /* Divide N by D, return the quotient, and store the remainder in *R. */
585 grub_uint64_t
586 grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
588 /* This algorithm is typically implemented by hardware. The idea
589 is to get the highest bit in N, 64 times, by keeping
590 upper(N * 2^i) = (Q * D + M), where upper
591 represents the high 64 bits in 128-bits space. */
592 unsigned bits = 64;
593 grub_uint64_t q = 0;
594 grub_uint64_t m = 0;
596 /* ARM and IA64 don't have a fast 32-bit division.
597 Using that code would just make us use libgcc routines, calling
598 them twice (once for modulo and once for quotient.
600 #if !defined (__arm__) && !defined (__ia64__)
601 /* Skip the slow computation if 32-bit arithmetic is possible. */
602 if (n < 0xffffffff && d < 0xffffffff)
604 if (r)
605 *r = ((grub_uint32_t) n) % (grub_uint32_t) d;
607 return ((grub_uint32_t) n) / (grub_uint32_t) d;
609 #endif
611 while (bits--)
613 m <<= 1;
615 if (n & (1ULL << 63))
616 m |= 1;
618 q <<= 1;
619 n <<= 1;
621 if (m >= d)
623 q |= 1;
624 m -= d;
628 if (r)
629 *r = m;
631 return q;
634 #if !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU)
636 #if defined (__arm__)
638 grub_uint32_t
639 __udivsi3 (grub_uint32_t a, grub_uint32_t b)
641 return grub_divmod64 (a, b, 0);
644 grub_uint32_t
645 __umodsi3 (grub_uint32_t a, grub_uint32_t b)
647 grub_uint64_t ret;
648 grub_divmod64 (a, b, &ret);
649 return ret;
652 #endif
654 #ifdef NEED_CTZDI2
656 unsigned
657 __ctzdi2 (grub_uint64_t x)
659 unsigned ret = 0;
660 if (!x)
661 return 64;
662 if (!(x & 0xffffffff))
664 x >>= 32;
665 ret |= 32;
667 if (!(x & 0xffff))
669 x >>= 16;
670 ret |= 16;
672 if (!(x & 0xff))
674 x >>= 8;
675 ret |= 8;
677 if (!(x & 0xf))
679 x >>= 4;
680 ret |= 4;
682 if (!(x & 0x3))
684 x >>= 2;
685 ret |= 2;
687 if (!(x & 0x1))
689 x >>= 1;
690 ret |= 1;
692 return ret;
694 #endif
696 #ifdef NEED_CTZSI2
697 unsigned
698 __ctzsi2 (grub_uint32_t x)
700 unsigned ret = 0;
701 if (!x)
702 return 32;
704 if (!(x & 0xffff))
706 x >>= 16;
707 ret |= 16;
709 if (!(x & 0xff))
711 x >>= 8;
712 ret |= 8;
714 if (!(x & 0xf))
716 x >>= 4;
717 ret |= 4;
719 if (!(x & 0x3))
721 x >>= 2;
722 ret |= 2;
724 if (!(x & 0x1))
726 x >>= 1;
727 ret |= 1;
729 return ret;
732 #endif
734 #ifdef __arm__
735 grub_uint32_t
736 __aeabi_uidiv (grub_uint32_t a, grub_uint32_t b)
737 __attribute__ ((alias ("__udivsi3")));
738 #endif
740 #if defined (__ia64__)
742 grub_uint64_t
743 __udivdi3 (grub_uint64_t a, grub_uint64_t b)
745 return grub_divmod64 (a, b, 0);
748 grub_uint64_t
749 __umoddi3 (grub_uint64_t a, grub_uint64_t b)
751 grub_uint64_t ret;
752 grub_divmod64 (a, b, &ret);
753 return ret;
756 #endif
758 #endif /* GRUB_UTIL */
760 /* Convert a long long value to a string. This function avoids 64-bit
761 modular arithmetic or divisions. */
762 static inline char *
763 grub_lltoa (char *str, int c, unsigned long long n)
765 unsigned base = (c == 'x') ? 16 : 10;
766 char *p;
768 if ((long long) n < 0 && c == 'd')
770 n = (unsigned long long) (-((long long) n));
771 *str++ = '-';
774 p = str;
776 if (base == 16)
779 unsigned d = (unsigned) (n & 0xf);
780 *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
782 while (n >>= 4);
783 else
784 /* BASE == 10 */
787 grub_uint64_t m;
789 n = grub_divmod64 (n, 10, &m);
790 *p++ = m + '0';
792 while (n);
794 *p = 0;
796 grub_reverse (str);
797 return p;
800 static void
801 parse_printf_args (const char *fmt0, struct printf_args *args,
802 va_list args_in)
804 const char *fmt;
805 char c;
806 grub_size_t n = 0;
808 args->count = 0;
810 COMPILE_TIME_ASSERT (sizeof (int) == sizeof (grub_uint32_t));
811 COMPILE_TIME_ASSERT (sizeof (int) <= sizeof (long long));
812 COMPILE_TIME_ASSERT (sizeof (long) <= sizeof (long long));
813 COMPILE_TIME_ASSERT (sizeof (long long) == sizeof (void *)
814 || sizeof (int) == sizeof (void *));
816 fmt = fmt0;
817 while ((c = *fmt++) != 0)
819 if (c != '%')
820 continue;
822 if (*fmt =='-')
823 fmt++;
825 while (grub_isdigit (*fmt))
826 fmt++;
828 if (*fmt == '$')
829 fmt++;
831 if (*fmt =='-')
832 fmt++;
834 while (grub_isdigit (*fmt))
835 fmt++;
837 if (*fmt =='.')
838 fmt++;
840 while (grub_isdigit (*fmt))
841 fmt++;
843 c = *fmt++;
844 if (c == 'l')
845 c = *fmt++;
846 if (c == 'l')
847 c = *fmt++;
849 switch (c)
851 case 'p':
852 case 'x':
853 case 'u':
854 case 'd':
855 case 'c':
856 case 'C':
857 case 's':
858 args->count++;
859 break;
863 if (args->count <= ARRAY_SIZE (args->prealloc))
864 args->ptr = args->prealloc;
865 else
867 args->ptr = grub_malloc (args->count * sizeof (args->ptr[0]));
868 if (!args->ptr)
870 grub_errno = GRUB_ERR_NONE;
871 args->ptr = args->prealloc;
872 args->count = ARRAY_SIZE (args->prealloc);
876 grub_memset (args->ptr, 0, args->count * sizeof (args->ptr[0]));
878 fmt = fmt0;
879 n = 0;
880 while ((c = *fmt++) != 0)
882 int longfmt = 0;
883 grub_size_t curn;
884 const char *p;
886 if (c != '%')
887 continue;
889 curn = n++;
891 if (*fmt =='-')
892 fmt++;
894 p = fmt;
896 while (grub_isdigit (*fmt))
897 fmt++;
899 if (*fmt == '$')
901 curn = grub_strtoull (p, 0, 10) - 1;
902 fmt++;
905 if (*fmt =='-')
906 fmt++;
908 while (grub_isdigit (*fmt))
909 fmt++;
911 if (*fmt =='.')
912 fmt++;
914 while (grub_isdigit (*fmt))
915 fmt++;
917 c = *fmt++;
918 if (c == 'l')
920 c = *fmt++;
921 longfmt = 1;
923 if (c == 'l')
925 c = *fmt++;
926 longfmt = 2;
928 if (curn >= args->count)
929 continue;
930 switch (c)
932 case 'x':
933 case 'u':
934 args->ptr[curn].type = UNSIGNED_INT + longfmt;
935 break;
936 case 'd':
937 args->ptr[curn].type = INT + longfmt;
938 break;
939 case 'p':
940 case 's':
941 if (sizeof (void *) == sizeof (long long))
942 args->ptr[curn].type = UNSIGNED_LONGLONG;
943 else
944 args->ptr[curn].type = UNSIGNED_INT;
945 break;
946 case 'C':
947 case 'c':
948 args->ptr[curn].type = INT;
949 break;
953 for (n = 0; n < args->count; n++)
954 switch (args->ptr[n].type)
956 case INT:
957 args->ptr[n].ll = va_arg (args_in, int);
958 break;
959 case LONG:
960 args->ptr[n].ll = va_arg (args_in, long);
961 break;
962 case UNSIGNED_INT:
963 args->ptr[n].ll = va_arg (args_in, unsigned int);
964 break;
965 case UNSIGNED_LONG:
966 args->ptr[n].ll = va_arg (args_in, unsigned long);
967 break;
968 case LONGLONG:
969 case UNSIGNED_LONGLONG:
970 args->ptr[n].ll = va_arg (args_in, long long);
971 break;
975 static inline void __attribute__ ((always_inline))
976 write_char (char *str, grub_size_t *count, grub_size_t max_len, unsigned char ch)
978 if (*count < max_len)
979 str[*count] = ch;
981 (*count)++;
984 static int
985 grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0,
986 struct printf_args *args)
988 char c;
989 grub_size_t n = 0;
990 grub_size_t count = 0;
991 const char *fmt;
993 fmt = fmt0;
995 while ((c = *fmt++) != 0)
997 unsigned int format1 = 0;
998 unsigned int format2 = ~ 0U;
999 char zerofill = ' ';
1000 char rightfill = 0;
1001 grub_size_t curn;
1003 if (c != '%')
1005 write_char (str, &count, max_len,c);
1006 continue;
1009 curn = n++;
1011 rescan:;
1013 if (*fmt =='-')
1015 rightfill = 1;
1016 fmt++;
1019 /* Read formatting parameters. */
1020 if (grub_isdigit (*fmt))
1022 if (fmt[0] == '0')
1023 zerofill = '0';
1024 format1 = grub_strtoul (fmt, (char **) &fmt, 10);
1027 if (*fmt == '.')
1028 fmt++;
1030 if (grub_isdigit (*fmt))
1031 format2 = grub_strtoul (fmt, (char **) &fmt, 10);
1033 if (*fmt == '$')
1035 curn = format1 - 1;
1036 fmt++;
1037 format1 = 0;
1038 format2 = ~ 0U;
1039 zerofill = ' ';
1040 rightfill = 0;
1042 goto rescan;
1045 c = *fmt++;
1046 if (c == 'l')
1047 c = *fmt++;
1048 if (c == 'l')
1049 c = *fmt++;
1051 if (c == '%')
1053 write_char (str, &count, max_len,c);
1054 continue;
1057 if (curn >= args->count)
1058 continue;
1060 long long curarg = args->ptr[curn].ll;
1062 switch (c)
1064 case 'p':
1065 write_char (str, &count, max_len, '0');
1066 write_char (str, &count, max_len, 'x');
1067 c = 'x';
1068 /* Fall through. */
1069 case 'x':
1070 case 'u':
1071 case 'd':
1073 char tmp[32];
1074 const char *p = tmp;
1075 grub_size_t len;
1076 grub_size_t fill;
1078 len = grub_lltoa (tmp, c, curarg) - tmp;
1079 fill = len < format1 ? format1 - len : 0;
1080 if (! rightfill)
1081 while (fill--)
1082 write_char (str, &count, max_len, zerofill);
1083 while (*p)
1084 write_char (str, &count, max_len, *p++);
1085 if (rightfill)
1086 while (fill--)
1087 write_char (str, &count, max_len, zerofill);
1089 break;
1091 case 'c':
1092 write_char (str, &count, max_len,curarg & 0xff);
1093 break;
1095 case 'C':
1097 grub_uint32_t code = curarg;
1098 int shift;
1099 unsigned mask;
1101 if (code <= 0x7f)
1103 shift = 0;
1104 mask = 0;
1106 else if (code <= 0x7ff)
1108 shift = 6;
1109 mask = 0xc0;
1111 else if (code <= 0xffff)
1113 shift = 12;
1114 mask = 0xe0;
1116 else if (code <= 0x10ffff)
1118 shift = 18;
1119 mask = 0xf0;
1121 else
1123 code = '?';
1124 shift = 0;
1125 mask = 0;
1128 write_char (str, &count, max_len,mask | (code >> shift));
1130 for (shift -= 6; shift >= 0; shift -= 6)
1131 write_char (str, &count, max_len,0x80 | (0x3f & (code >> shift)));
1133 break;
1135 case 's':
1137 grub_size_t len = 0;
1138 grub_size_t fill;
1139 const char *p = ((char *) (grub_addr_t) curarg) ? : "(null)";
1140 grub_size_t i;
1142 while (len < format2 && p[len])
1143 len++;
1145 fill = len < format1 ? format1 - len : 0;
1147 if (!rightfill)
1148 while (fill--)
1149 write_char (str, &count, max_len, zerofill);
1151 for (i = 0; i < len; i++)
1152 write_char (str, &count, max_len,*p++);
1154 if (rightfill)
1155 while (fill--)
1156 write_char (str, &count, max_len, zerofill);
1159 break;
1161 default:
1162 write_char (str, &count, max_len,c);
1163 break;
1167 if (count < max_len)
1168 str[count] = '\0';
1169 else
1170 str[max_len] = '\0';
1171 return count;
1175 grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list ap)
1177 grub_size_t ret;
1178 struct printf_args args;
1180 if (!n)
1181 return 0;
1183 n--;
1185 parse_printf_args (fmt, &args, ap);
1187 ret = grub_vsnprintf_real (str, n, fmt, &args);
1189 free_printf_args (&args);
1191 return ret < n ? ret : n;
1195 grub_snprintf (char *str, grub_size_t n, const char *fmt, ...)
1197 va_list ap;
1198 int ret;
1200 va_start (ap, fmt);
1201 ret = grub_vsnprintf (str, n, fmt, ap);
1202 va_end (ap);
1204 return ret;
1207 char *
1208 grub_xvasprintf (const char *fmt, va_list ap)
1210 grub_size_t s, as = PREALLOC_SIZE;
1211 char *ret;
1212 struct printf_args args;
1214 parse_printf_args (fmt, &args, ap);
1216 while (1)
1218 ret = grub_malloc (as + 1);
1219 if (!ret)
1221 free_printf_args (&args);
1222 return NULL;
1225 s = grub_vsnprintf_real (ret, as, fmt, &args);
1227 if (s <= as)
1229 free_printf_args (&args);
1230 return ret;
1233 grub_free (ret);
1234 as = s;
1238 char *
1239 grub_xasprintf (const char *fmt, ...)
1241 va_list ap;
1242 char *ret;
1244 va_start (ap, fmt);
1245 ret = grub_xvasprintf (fmt, ap);
1246 va_end (ap);
1248 return ret;
1251 /* Abort GRUB. This function does not return. */
1252 static void __attribute__ ((noreturn))
1253 grub_abort (void)
1255 grub_printf ("\nAborted.");
1257 #ifndef GRUB_UTIL
1258 if (grub_term_inputs)
1259 #endif
1261 grub_printf (" Press any key to exit.");
1262 grub_getkey ();
1265 grub_exit ();
1268 #if defined (__clang__) && !defined (GRUB_UTIL)
1269 /* clang emits references to abort(). */
1270 void __attribute__ ((noreturn))
1271 abort (void)
1273 grub_abort ();
1275 #endif
1277 void
1278 grub_fatal (const char *fmt, ...)
1280 va_list ap;
1282 va_start (ap, fmt);
1283 grub_vprintf (_(fmt), ap);
1284 va_end (ap);
1286 grub_abort ();
1289 #if (defined (__MINGW32__) || defined (__CYGWIN__)) && !defined(GRUB_UTIL)
1290 void __register_frame_info (void)
1294 void __deregister_frame_info (void)
1297 void ___chkstk_ms (void)
1301 void __chkstk_ms (void)
1304 #endif
1306 #if BOOT_TIME_STATS
1308 #include <grub/time.h>
1310 struct grub_boot_time *grub_boot_time_head;
1311 static struct grub_boot_time **boot_time_last = &grub_boot_time_head;
1313 void
1314 grub_real_boot_time (const char *file,
1315 const int line,
1316 const char *fmt, ...)
1318 struct grub_boot_time *n;
1319 va_list args;
1321 grub_error_push ();
1322 n = grub_malloc (sizeof (*n));
1323 if (!n)
1325 grub_errno = 0;
1326 grub_error_pop ();
1327 return;
1329 n->file = file;
1330 n->line = line;
1331 n->tp = grub_get_time_ms ();
1332 n->next = 0;
1334 va_start (args, fmt);
1335 n->msg = grub_xvasprintf (fmt, args);
1336 va_end (args);
1338 *boot_time_last = n;
1339 boot_time_last = &n->next;
1341 grub_errno = 0;
1342 grub_error_pop ();
1344 #endif