2009-07-05 Pavel Roskin <proski@gnu.org>
[grub2/bean.git] / kern / misc.c
blobd797f17814000863f44722224dac167601f2baf5
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 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>
27 void *
28 grub_memmove (void *dest, const void *src, grub_size_t n)
30 char *d = (char *) dest;
31 const char *s = (const char *) src;
33 if (d < s)
34 while (n--)
35 *d++ = *s++;
36 else
38 d += n;
39 s += n;
41 while (n--)
42 *--d = *--s;
45 return dest;
48 #ifndef APPLE_CC
49 void *memmove (void *dest, const void *src, grub_size_t n)
50 __attribute__ ((alias ("grub_memmove")));
51 /* GCC emits references to memcpy() for struct copies etc. */
52 void *memcpy (void *dest, const void *src, grub_size_t n)
53 __attribute__ ((alias ("grub_memmove")));
54 #else
55 void *memcpy (void *dest, const void *src, grub_size_t n)
57 return grub_memmove (dest, src, n);
59 void *memmove (void *dest, const void *src, grub_size_t n)
61 return grub_memmove (dest, src, n);
63 #endif
65 char *
66 grub_strcpy (char *dest, const char *src)
68 char *p = dest;
70 while ((*p++ = *src++) != '\0')
73 return dest;
76 char *
77 grub_strncpy (char *dest, const char *src, int c)
79 char *p = dest;
81 while ((*p++ = *src++) != '\0' && --c)
84 return dest;
87 char *
88 grub_stpcpy (char *dest, const char *src)
90 char *d = dest;
91 const char *s = src;
94 *d++ = *s;
95 while (*s++ != '\0');
97 return d - 1;
100 char *
101 grub_strcat (char *dest, const char *src)
103 char *p = dest;
105 while (*p)
106 p++;
108 while ((*p = *src) != '\0')
110 p++;
111 src++;
114 return dest;
117 char *
118 grub_strncat (char *dest, const char *src, int c)
120 char *p = dest;
122 while (*p)
123 p++;
125 while ((*p = *src) != '\0' && c--)
127 p++;
128 src++;
131 *p = '\0';
133 return dest;
137 grub_printf (const char *fmt, ...)
139 va_list ap;
140 int ret;
142 va_start (ap, fmt);
143 ret = grub_vprintf (fmt, ap);
144 va_end (ap);
146 return ret;
149 #if defined (APPLE_CC) && ! defined (GRUB_UTIL)
151 grub_err_printf (const char *fmt, ...)
153 va_list ap;
154 int ret;
156 va_start (ap, fmt);
157 ret = grub_vprintf (fmt, ap);
158 va_end (ap);
160 return ret;
162 #endif
164 #if ! defined (APPLE_CC) && ! defined (GRUB_UTIL)
165 int grub_err_printf (const char *fmt, ...)
166 __attribute__ ((alias("grub_printf")));
167 #endif
169 void
170 grub_real_dprintf (const char *file, const int line, const char *condition,
171 const char *fmt, ...)
173 va_list args;
174 const char *debug = grub_env_get ("debug");
176 if (! debug)
177 return;
179 if (grub_strword (debug, "all") || grub_strword (debug, condition))
181 grub_printf ("%s:%d: ", file, line);
182 va_start (args, fmt);
183 grub_vprintf (fmt, args);
184 va_end (args);
189 grub_vprintf (const char *fmt, va_list args)
191 int ret;
193 ret = grub_vsprintf (0, fmt, args);
194 grub_refresh ();
195 return ret;
199 grub_memcmp (const void *s1, const void *s2, grub_size_t n)
201 const char *t1 = s1;
202 const char *t2 = s2;
204 while (n--)
206 if (*t1 != *t2)
207 return (int) *t1 - (int) *t2;
209 t1++;
210 t2++;
213 return 0;
215 #ifndef APPLE_CC
216 int memcmp (const void *s1, const void *s2, grub_size_t n)
217 __attribute__ ((alias ("grub_memcmp")));
218 #endif
221 grub_strcmp (const char *s1, const char *s2)
223 while (*s1 && *s2)
225 if (*s1 != *s2)
226 break;
228 s1++;
229 s2++;
232 return (int) *s1 - (int) *s2;
236 grub_strncmp (const char *s1, const char *s2, grub_size_t n)
238 if (n == 0)
239 return 0;
241 while (*s1 && *s2 && --n)
243 if (*s1 != *s2)
244 break;
246 s1++;
247 s2++;
250 return (int) *s1 - (int) *s2;
254 grub_strcasecmp (const char *s1, const char *s2)
256 while (*s1 && *s2)
258 if (grub_tolower (*s1) != grub_tolower (*s2))
259 break;
261 s1++;
262 s2++;
265 return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
269 grub_strncasecmp (const char *s1, const char *s2, grub_size_t n)
271 if (n == 0)
272 return 0;
274 while (*s1 && *s2 && --n)
276 if (grub_tolower (*s1) != grub_tolower (*s2))
277 break;
279 s1++;
280 s2++;
283 return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
286 char *
287 grub_strchr (const char *s, int c)
289 while (*s)
291 if (*s == c)
292 return (char *) s;
293 s++;
296 return 0;
299 char *
300 grub_strrchr (const char *s, int c)
302 char *p = 0;
304 while (*s)
306 if (*s == c)
307 p = (char *) s;
308 s++;
311 return p;
314 /* Copied from gnulib.
315 Written by Bruno Haible <bruno@clisp.org>, 2005. */
316 char *
317 grub_strstr (const char *haystack, const char *needle)
319 /* Be careful not to look at the entire extent of haystack or needle
320 until needed. This is useful because of these two cases:
321 - haystack may be very long, and a match of needle found early,
322 - needle may be very long, and not even a short initial segment of
323 needle may be found in haystack. */
324 if (*needle != '\0')
326 /* Speed up the following searches of needle by caching its first
327 character. */
328 char b = *needle++;
330 for (;; haystack++)
332 if (*haystack == '\0')
333 /* No match. */
334 return NULL;
335 if (*haystack == b)
336 /* The first character matches. */
338 const char *rhaystack = haystack + 1;
339 const char *rneedle = needle;
341 for (;; rhaystack++, rneedle++)
343 if (*rneedle == '\0')
344 /* Found a match. */
345 return (char *) haystack;
346 if (*rhaystack == '\0')
347 /* No match. */
348 return NULL;
349 if (*rhaystack != *rneedle)
350 /* Nothing in this round. */
351 break;
356 else
357 return (char *) haystack;
361 grub_strword (const char *haystack, const char *needle)
363 const char *n_pos = needle;
365 while (grub_iswordseparator (*haystack))
366 haystack++;
368 while (*haystack)
370 /* Crawl both the needle and the haystack word we're on. */
371 while(*haystack && !grub_iswordseparator (*haystack)
372 && *haystack == *n_pos)
374 haystack++;
375 n_pos++;
378 /* If we reached the end of both words at the same time, the word
379 is found. If not, eat everything in the haystack that isn't the
380 next word (or the end of string) and "reset" the needle. */
381 if ( (!*haystack || grub_iswordseparator (*haystack))
382 && (!*n_pos || grub_iswordseparator (*n_pos)))
383 return 1;
384 else
386 n_pos = needle;
387 while (*haystack && !grub_iswordseparator (*haystack))
388 haystack++;
389 while (grub_iswordseparator (*haystack))
390 haystack++;
394 return 0;
398 grub_iswordseparator (int c)
400 return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
404 grub_isspace (int c)
406 return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
410 grub_isprint (int c)
412 return (c >= ' ' && c <= '~');
416 grub_isalpha (int c)
418 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
422 grub_isdigit (int c)
424 return (c >= '0' && c <= '9');
428 grub_isgraph (int c)
430 return (c >= '!' && c <= '~');
434 grub_tolower (int c)
436 if (c >= 'A' && c <= 'Z')
437 return c - 'A' + 'a';
439 return c;
443 unsigned long
444 grub_strtoul (const char *str, char **end, int base)
446 unsigned long long num;
448 num = grub_strtoull (str, end, base);
449 if (num > ~0UL)
451 grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
452 return ~0UL;
455 return (unsigned long) num;
458 unsigned long long
459 grub_strtoull (const char *str, char **end, int base)
461 unsigned long long num = 0;
462 int found = 0;
464 /* Skip white spaces. */
465 while (*str && grub_isspace (*str))
466 str++;
468 /* Guess the base, if not specified. The prefix `0x' means 16, and
469 the prefix `0' means 8. */
470 if (str[0] == '0')
472 if (str[1] == 'x')
474 if (base == 0 || base == 16)
476 base = 16;
477 str += 2;
480 else if (base == 0 && str[1] >= '0' && str[1] <= '7')
481 base = 8;
484 if (base == 0)
485 base = 10;
487 while (*str)
489 unsigned long digit;
491 digit = grub_tolower (*str) - '0';
492 if (digit > 9)
494 digit += '0' - 'a' + 10;
495 if (digit >= (unsigned long) base)
496 break;
499 found = 1;
501 /* NUM * BASE + DIGIT > ~0ULL */
502 if (num > grub_divmod64 (~0ULL - digit, base, 0))
504 grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
505 return ~0ULL;
508 num = num * base + digit;
509 str++;
512 if (! found)
514 grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number");
515 return 0;
518 if (end)
519 *end = (char *) str;
521 return num;
524 char *
525 grub_strdup (const char *s)
527 grub_size_t len;
528 char *p;
530 len = grub_strlen (s) + 1;
531 p = (char *) grub_malloc (len);
532 if (! p)
533 return 0;
535 return grub_memcpy (p, s, len);
538 char *
539 grub_strndup (const char *s, grub_size_t n)
541 grub_size_t len;
542 char *p;
544 len = grub_strlen (s);
545 if (len > n)
546 len = n;
547 p = (char *) grub_malloc (len + 1);
548 if (! p)
549 return 0;
551 grub_memcpy (p, s, len);
552 p[len] = '\0';
553 return p;
556 void *
557 grub_memset (void *s, int c, grub_size_t n)
559 unsigned char *p = (unsigned char *) s;
561 while (n--)
562 *p++ = (unsigned char) c;
564 return s;
566 #ifndef APPLE_CC
567 void *memset (void *s, int c, grub_size_t n)
568 __attribute__ ((alias ("grub_memset")));
569 #endif
571 grub_size_t
572 grub_strlen (const char *s)
574 const char *p = s;
576 while (*p)
577 p++;
579 return p - s;
582 static inline void
583 grub_reverse (char *str)
585 char *p = str + grub_strlen (str) - 1;
587 while (str < p)
589 char tmp;
591 tmp = *str;
592 *str = *p;
593 *p = tmp;
594 str++;
595 p--;
599 /* Divide N by D, return the quotient, and store the remainder in *R. */
600 grub_uint64_t
601 grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r)
603 /* This algorithm is typically implemented by hardware. The idea
604 is to get the highest bit in N, 64 times, by keeping
605 upper(N * 2^i) = upper((Q * 10 + M) * 2^i), where upper
606 represents the high 64 bits in 128-bits space. */
607 unsigned bits = 64;
608 unsigned long long q = 0;
609 unsigned m = 0;
611 /* Skip the slow computation if 32-bit arithmetic is possible. */
612 if (n < 0xffffffff)
614 if (r)
615 *r = ((grub_uint32_t) n) % d;
617 return ((grub_uint32_t) n) / d;
620 while (bits--)
622 m <<= 1;
624 if (n & (1ULL << 63))
625 m |= 1;
627 q <<= 1;
628 n <<= 1;
630 if (m >= d)
632 q |= 1;
633 m -= d;
637 if (r)
638 *r = m;
640 return q;
643 /* Convert a long long value to a string. This function avoids 64-bit
644 modular arithmetic or divisions. */
645 static char *
646 grub_lltoa (char *str, int c, unsigned long long n)
648 unsigned base = (c == 'x') ? 16 : 10;
649 char *p;
651 if ((long long) n < 0 && c == 'd')
653 n = (unsigned long long) (-((long long) n));
654 *str++ = '-';
657 p = str;
659 if (base == 16)
662 unsigned d = (unsigned) (n & 0xf);
663 *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
665 while (n >>= 4);
666 else
667 /* BASE == 10 */
670 unsigned m;
672 n = grub_divmod64 (n, 10, &m);
673 *p++ = m + '0';
675 while (n);
677 *p = 0;
679 grub_reverse (str);
680 return p;
684 grub_vsprintf (char *str, const char *fmt, va_list args)
686 char c;
687 int count = 0;
688 auto void write_char (unsigned char ch);
689 auto void write_str (const char *s);
690 auto void write_fill (const char ch, int n);
692 void write_char (unsigned char ch)
694 if (str)
695 *str++ = ch;
696 else
697 grub_putchar (ch);
699 count++;
702 void write_str (const char *s)
704 while (*s)
705 write_char (*s++);
708 void write_fill (const char ch, int n)
710 int i;
711 for (i = 0; i < n; i++)
712 write_char (ch);
715 while ((c = *fmt++) != 0)
717 if (c != '%')
718 write_char (c);
719 else
721 char tmp[32];
722 char *p;
723 unsigned int format1 = 0;
724 unsigned int format2 = ~ 0U;
725 char zerofill = ' ';
726 int rightfill = 0;
727 int n;
728 int longfmt = 0;
729 int longlongfmt = 0;
730 int unsig = 0;
732 if (*fmt && *fmt =='-')
734 rightfill = 1;
735 fmt++;
738 p = (char *) fmt;
739 /* Read formatting parameters. */
740 while (*p && grub_isdigit (*p))
741 p++;
743 if (p > fmt)
745 char s[p - fmt + 1];
746 grub_strncpy (s, fmt, p - fmt);
747 s[p - fmt] = 0;
748 if (s[0] == '0')
749 zerofill = '0';
750 format1 = grub_strtoul (s, 0, 10);
751 fmt = p;
754 if (*p && *p == '.')
756 p++;
757 fmt++;
758 while (*p && grub_isdigit (*p))
759 p++;
761 if (p > fmt)
763 char fstr[p - fmt + 1];
764 grub_strncpy (fstr, fmt, p - fmt);
765 fstr[p - fmt] = 0;
766 format2 = grub_strtoul (fstr, 0, 10);
767 fmt = p;
771 c = *fmt++;
772 if (c == 'l')
774 longfmt = 1;
775 c = *fmt++;
776 if (c == 'l')
778 longlongfmt = 1;
779 c = *fmt++;
783 switch (c)
785 case 'p':
786 write_str ("0x");
787 c = 'x';
788 longlongfmt |= (sizeof (void *) == sizeof (long long));
789 /* Fall through. */
790 case 'x':
791 case 'u':
792 unsig = 1;
793 /* Fall through. */
794 case 'd':
795 if (longlongfmt)
797 long long ll;
799 ll = va_arg (args, long long);
800 grub_lltoa (tmp, c, ll);
802 else if (longfmt && unsig)
804 unsigned long l = va_arg (args, unsigned long);
805 grub_lltoa (tmp, c, l);
807 else if (longfmt)
809 long l = va_arg (args, long);
810 grub_lltoa (tmp, c, l);
812 else if (unsig)
814 unsigned u = va_arg (args, unsigned);
815 grub_lltoa (tmp, c, u);
817 else
819 n = va_arg (args, int);
820 grub_lltoa (tmp, c, n);
822 if (! rightfill && grub_strlen (tmp) < format1)
823 write_fill (zerofill, format1 - grub_strlen (tmp));
824 write_str (tmp);
825 if (rightfill && grub_strlen (tmp) < format1)
826 write_fill (zerofill, format1 - grub_strlen (tmp));
827 break;
829 case 'c':
830 n = va_arg (args, int);
831 write_char (n & 0xff);
832 break;
834 case 'C':
836 grub_uint32_t code = va_arg (args, grub_uint32_t);
837 int shift;
838 unsigned mask;
840 if (code <= 0x7f)
842 shift = 0;
843 mask = 0;
845 else if (code <= 0x7ff)
847 shift = 6;
848 mask = 0xc0;
850 else if (code <= 0xffff)
852 shift = 12;
853 mask = 0xe0;
855 else if (code <= 0x1fffff)
857 shift = 18;
858 mask = 0xf0;
860 else if (code <= 0x3ffffff)
862 shift = 24;
863 mask = 0xf8;
865 else if (code <= 0x7fffffff)
867 shift = 30;
868 mask = 0xfc;
870 else
872 code = '?';
873 shift = 0;
874 mask = 0;
877 write_char (mask | (code >> shift));
879 for (shift -= 6; shift >= 0; shift -= 6)
880 write_char (0x80 | (0x3f & (code >> shift)));
882 break;
884 case 's':
885 p = va_arg (args, char *);
886 if (p)
888 grub_size_t len = 0;
889 while (len < format2 && p[len])
890 len++;
892 if (!rightfill && len < format1)
893 write_fill (zerofill, format1 - len);
895 grub_size_t i;
896 for (i = 0; i < len; i++)
897 write_char (*p++);
899 if (rightfill && len < format1)
900 write_fill (zerofill, format1 - len);
902 else
903 write_str ("(null)");
905 break;
907 default:
908 write_char (c);
909 break;
914 if (str)
915 *str = '\0';
917 if (count && !str)
918 grub_refresh ();
920 return count;
924 grub_sprintf (char *str, const char *fmt, ...)
926 va_list ap;
927 int ret;
929 va_start (ap, fmt);
930 ret = grub_vsprintf (str, fmt, ap);
931 va_end (ap);
933 return ret;
936 /* Convert UTF-16 to UTF-8. */
937 grub_uint8_t *
938 grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
939 grub_size_t size)
941 grub_uint32_t code_high = 0;
943 while (size--)
945 grub_uint32_t code = *src++;
947 if (code_high)
949 if (code >= 0xDC00 && code <= 0xDFFF)
951 /* Surrogate pair. */
952 code = ((code_high - 0xD800) << 12) + (code - 0xDC00) + 0x10000;
954 *dest++ = (code >> 18) | 0xF0;
955 *dest++ = ((code >> 12) & 0x3F) | 0x80;
956 *dest++ = ((code >> 6) & 0x3F) | 0x80;
957 *dest++ = (code & 0x3F) | 0x80;
959 else
961 /* Error... */
962 *dest++ = '?';
965 code_high = 0;
967 else
969 if (code <= 0x007F)
970 *dest++ = code;
971 else if (code <= 0x07FF)
973 *dest++ = (code >> 6) | 0xC0;
974 *dest++ = (code & 0x3F) | 0x80;
976 else if (code >= 0xD800 && code <= 0xDBFF)
978 code_high = code;
979 continue;
981 else if (code >= 0xDC00 && code <= 0xDFFF)
983 /* Error... */
984 *dest++ = '?';
986 else
988 *dest++ = (code >> 12) | 0xE0;
989 *dest++ = ((code >> 6) & 0x3F) | 0x80;
990 *dest++ = (code & 0x3F) | 0x80;
995 return dest;
998 /* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
999 bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string.
1000 Return the number of characters converted. DEST must be able to hold
1001 at least DESTSIZE characters. If an invalid sequence is found, return -1.
1002 If SRCEND is not NULL, then *SRCEND is set to the next byte after the
1003 last byte used in SRC. */
1004 grub_ssize_t
1005 grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
1006 const grub_uint8_t *src, grub_size_t srcsize,
1007 const grub_uint8_t **srcend)
1009 grub_uint32_t *p = dest;
1010 int count = 0;
1011 grub_uint32_t code = 0;
1013 if (srcend)
1014 *srcend = src;
1016 while (srcsize && destsize)
1018 grub_uint32_t c = *src++;
1019 if (srcsize != (grub_size_t)-1)
1020 srcsize--;
1021 if (count)
1023 if ((c & 0xc0) != 0x80)
1025 /* invalid */
1026 return -1;
1028 else
1030 code <<= 6;
1031 code |= (c & 0x3f);
1032 count--;
1035 else
1037 if (c == 0)
1038 break;
1040 if ((c & 0x80) == 0x00)
1041 code = c;
1042 else if ((c & 0xe0) == 0xc0)
1044 count = 1;
1045 code = c & 0x1f;
1047 else if ((c & 0xf0) == 0xe0)
1049 count = 2;
1050 code = c & 0x0f;
1052 else if ((c & 0xf8) == 0xf0)
1054 count = 3;
1055 code = c & 0x07;
1057 else if ((c & 0xfc) == 0xf8)
1059 count = 4;
1060 code = c & 0x03;
1062 else if ((c & 0xfe) == 0xfc)
1064 count = 5;
1065 code = c & 0x01;
1067 else
1068 return -1;
1071 if (count == 0)
1073 *p++ = code;
1074 destsize--;
1078 if (srcend)
1079 *srcend = src;
1080 return p - dest;
1083 /* Abort GRUB. This function does not return. */
1084 void
1085 grub_abort (void)
1087 if (grub_term_get_current_output ())
1089 grub_printf ("\nAborted.");
1091 if (grub_term_get_current_input ())
1093 grub_printf (" Press any key to exit.");
1094 grub_getkey ();
1098 grub_exit ();
1101 #ifndef APPLE_CC
1102 /* GCC emits references to abort(). */
1103 void abort (void) __attribute__ ((alias ("grub_abort")));
1104 #endif
1106 #ifdef NEED_ENABLE_EXECUTE_STACK
1107 /* Some gcc versions generate a call to this function
1108 in trampolines for nested functions. */
1109 void __enable_execute_stack (void *addr __attribute__ ((unused)))
1112 #endif