2009-02-07 Robert Millan <rmh@aybabtu.com>
[grub2/jjazz.git] / kern / misc.c
blob641bd7aef41f0ba5c8d1aeca69f4d359e6dcce57
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;
47 void *memmove (void *dest, const void *src, grub_size_t n)
48 __attribute__ ((alias ("grub_memmove")));
49 /* GCC emits references to memcpy() for struct copies etc. */
50 void *memcpy (void *dest, const void *src, grub_size_t n)
51 __attribute__ ((alias ("grub_memmove")));
53 char *
54 grub_strcpy (char *dest, const char *src)
56 char *p = dest;
58 while ((*p++ = *src++) != '\0')
61 return dest;
64 char *
65 grub_strncpy (char *dest, const char *src, int c)
67 char *p = dest;
69 while ((*p++ = *src++) != '\0' && --c)
72 return dest;
75 char *
76 grub_stpcpy (char *dest, const char *src)
78 char *d = dest;
79 const char *s = src;
82 *d++ = *s;
83 while (*s++ != '\0');
85 return d - 1;
88 char *
89 grub_strcat (char *dest, const char *src)
91 char *p = dest;
93 while (*p)
94 p++;
96 while ((*p = *src) != '\0')
98 p++;
99 src++;
102 return dest;
105 char *
106 grub_strncat (char *dest, const char *src, int c)
108 char *p = dest;
110 while (*p)
111 p++;
113 while ((*p = *src) != '\0' && c--)
115 p++;
116 src++;
119 *p = '\0';
121 return dest;
125 grub_printf (const char *fmt, ...)
127 va_list ap;
128 int ret;
130 va_start (ap, fmt);
131 ret = grub_vprintf (fmt, ap);
132 va_end (ap);
134 return ret;
137 #ifndef GRUB_UTIL
138 int grub_err_printf (const char *fmt, ...)
139 __attribute__ ((alias("grub_printf")));
140 #endif
142 void
143 grub_real_dprintf (const char *file, const int line, const char *condition,
144 const char *fmt, ...)
146 va_list args;
147 const char *debug = grub_env_get ("debug");
149 if (! debug)
150 return;
152 if (grub_strword (debug, "all") || grub_strword (debug, condition))
154 grub_printf ("%s:%d: ", file, line);
155 va_start (args, fmt);
156 grub_vprintf (fmt, args);
157 va_end (args);
162 grub_vprintf (const char *fmt, va_list args)
164 int ret;
166 ret = grub_vsprintf (0, fmt, args);
167 grub_refresh ();
168 return ret;
172 grub_memcmp (const void *s1, const void *s2, grub_size_t n)
174 const char *t1 = s1;
175 const char *t2 = s2;
177 while (n--)
179 if (*t1 != *t2)
180 return (int) *t1 - (int) *t2;
182 t1++;
183 t2++;
186 return 0;
188 int memcmp (const void *s1, const void *s2, grub_size_t n)
189 __attribute__ ((alias ("grub_memcmp")));
192 grub_strcmp (const char *s1, const char *s2)
194 while (*s1 && *s2)
196 if (*s1 != *s2)
197 break;
199 s1++;
200 s2++;
203 return (int) *s1 - (int) *s2;
207 grub_strncmp (const char *s1, const char *s2, grub_size_t n)
209 if (n == 0)
210 return 0;
212 while (*s1 && *s2 && --n)
214 if (*s1 != *s2)
215 break;
217 s1++;
218 s2++;
221 return (int) *s1 - (int) *s2;
225 grub_strcasecmp (const char *s1, const char *s2)
227 while (*s1 && *s2)
229 if (grub_tolower (*s1) != grub_tolower (*s2))
230 break;
232 s1++;
233 s2++;
236 return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
240 grub_strncasecmp (const char *s1, const char *s2, grub_size_t n)
242 if (n == 0)
243 return 0;
245 while (*s1 && *s2 && --n)
247 if (grub_tolower (*s1) != grub_tolower (*s2))
248 break;
250 s1++;
251 s2++;
254 return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
257 char *
258 grub_strchr (const char *s, int c)
260 while (*s)
262 if (*s == c)
263 return (char *) s;
264 s++;
267 return 0;
270 char *
271 grub_strrchr (const char *s, int c)
273 char *p = 0;
275 while (*s)
277 if (*s == c)
278 p = (char *) s;
279 s++;
282 return p;
285 /* Copied from gnulib.
286 Written by Bruno Haible <bruno@clisp.org>, 2005. */
287 char *
288 grub_strstr (const char *haystack, const char *needle)
290 /* Be careful not to look at the entire extent of haystack or needle
291 until needed. This is useful because of these two cases:
292 - haystack may be very long, and a match of needle found early,
293 - needle may be very long, and not even a short initial segment of
294 needle may be found in haystack. */
295 if (*needle != '\0')
297 /* Speed up the following searches of needle by caching its first
298 character. */
299 char b = *needle++;
301 for (;; haystack++)
303 if (*haystack == '\0')
304 /* No match. */
305 return NULL;
306 if (*haystack == b)
307 /* The first character matches. */
309 const char *rhaystack = haystack + 1;
310 const char *rneedle = needle;
312 for (;; rhaystack++, rneedle++)
314 if (*rneedle == '\0')
315 /* Found a match. */
316 return (char *) haystack;
317 if (*rhaystack == '\0')
318 /* No match. */
319 return NULL;
320 if (*rhaystack != *rneedle)
321 /* Nothing in this round. */
322 break;
327 else
328 return (char *) haystack;
332 grub_strword (const char *haystack, const char *needle)
334 const char *n_pos = needle;
336 while (grub_iswordseparator (*haystack))
337 haystack++;
339 while (*haystack)
341 /* Crawl both the needle and the haystack word we're on. */
342 while(*haystack && !grub_iswordseparator (*haystack)
343 && *haystack == *n_pos)
345 haystack++;
346 n_pos++;
349 /* If we reached the end of both words at the same time, the word
350 is found. If not, eat everything in the haystack that isn't the
351 next word (or the end of string) and "reset" the needle. */
352 if ( (!*haystack || grub_iswordseparator (*haystack))
353 && (!*n_pos || grub_iswordseparator (*n_pos)))
354 return 1;
355 else
357 n_pos = needle;
358 while (*haystack && !grub_iswordseparator (*haystack))
359 haystack++;
360 while (grub_iswordseparator (*haystack))
361 haystack++;
365 return 0;
369 grub_iswordseparator (int c)
371 return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
375 grub_isspace (int c)
377 return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
381 grub_isprint (int c)
383 return (c >= ' ' && c <= '~');
387 grub_isalpha (int c)
389 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
393 grub_isdigit (int c)
395 return (c >= '0' && c <= '9');
399 grub_isgraph (int c)
401 return (c >= '!' && c <= '~');
405 grub_tolower (int c)
407 if (c >= 'A' && c <= 'Z')
408 return c - 'A' + 'a';
410 return c;
414 unsigned long
415 grub_strtoul (const char *str, char **end, int base)
417 unsigned long long num;
419 num = grub_strtoull (str, end, base);
420 if (num > ~0UL)
422 grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
423 return ~0UL;
426 return (unsigned long) num;
429 unsigned long long
430 grub_strtoull (const char *str, char **end, int base)
432 unsigned long long num = 0;
433 int found = 0;
435 /* Skip white spaces. */
436 while (*str && grub_isspace (*str))
437 str++;
439 /* Guess the base, if not specified. The prefix `0x' means 16, and
440 the prefix `0' means 8. */
441 if (base == 0 && str[0] == '0')
443 if (str[1] == 'x')
445 if (base == 0 || base == 16)
447 base = 16;
448 str += 2;
451 else if (str[1] >= '0' && str[1] <= '7')
452 base = 8;
455 if (base == 0)
456 base = 10;
458 while (*str)
460 unsigned long digit;
462 digit = grub_tolower (*str) - '0';
463 if (digit > 9)
465 digit += '0' - 'a' + 10;
466 if (digit >= (unsigned long) base)
467 break;
470 found = 1;
472 /* NUM * BASE + DIGIT > ~0ULL */
473 if (num > grub_divmod64 (~0ULL - digit, base, 0))
475 grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
476 return ~0ULL;
479 num = num * base + digit;
480 str++;
483 if (! found)
485 grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number");
486 return 0;
489 if (end)
490 *end = (char *) str;
492 return num;
495 char *
496 grub_strdup (const char *s)
498 grub_size_t len;
499 char *p;
501 len = grub_strlen (s) + 1;
502 p = (char *) grub_malloc (len);
503 if (! p)
504 return 0;
506 return grub_memcpy (p, s, len);
509 char *
510 grub_strndup (const char *s, grub_size_t n)
512 grub_size_t len;
513 char *p;
515 len = grub_strlen (s);
516 if (len > n)
517 len = n;
518 p = (char *) grub_malloc (len + 1);
519 if (! p)
520 return 0;
522 grub_memcpy (p, s, len);
523 p[len] = '\0';
524 return p;
527 void *
528 grub_memset (void *s, int c, grub_size_t n)
530 unsigned char *p = (unsigned char *) s;
532 while (n--)
533 *p++ = (unsigned char) c;
535 return s;
537 void *memset (void *s, int c, grub_size_t n)
538 __attribute__ ((alias ("grub_memset")));
540 grub_size_t
541 grub_strlen (const char *s)
543 const char *p = s;
545 while (*p)
546 p++;
548 return p - s;
551 static inline void
552 grub_reverse (char *str)
554 char *p = str + grub_strlen (str) - 1;
556 while (str < p)
558 char tmp;
560 tmp = *str;
561 *str = *p;
562 *p = tmp;
563 str++;
564 p--;
568 static char *
569 grub_itoa (char *str, int c, unsigned n)
571 unsigned base = (c == 'x') ? 16 : 10;
572 char *p;
574 if ((int) n < 0 && c == 'd')
576 n = (unsigned) (-((int) n));
577 *str++ = '-';
580 p = str;
583 unsigned d = n % base;
584 *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
586 while (n /= base);
587 *p = 0;
589 grub_reverse (str);
590 return p;
593 /* Divide N by D, return the quotient, and store the remainder in *R. */
594 grub_uint64_t
595 grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r)
597 /* This algorithm is typically implemented by hardware. The idea
598 is to get the highest bit in N, 64 times, by keeping
599 upper(N * 2^i) = upper((Q * 10 + M) * 2^i), where upper
600 represents the high 64 bits in 128-bits space. */
601 unsigned bits = 64;
602 unsigned long long q = 0;
603 unsigned m = 0;
605 /* Skip the slow computation if 32-bit arithmetic is possible. */
606 if (n < 0xffffffff)
608 if (r)
609 *r = ((grub_uint32_t) n) % d;
611 return ((grub_uint32_t) n) / d;
614 while (bits--)
616 m <<= 1;
618 if (n & (1ULL << 63))
619 m |= 1;
621 q <<= 1;
622 n <<= 1;
624 if (m >= d)
626 q |= 1;
627 m -= d;
631 if (r)
632 *r = m;
634 return q;
637 /* Convert a long long value to a string. This function avoids 64-bit
638 modular arithmetic or divisions. */
639 static char *
640 grub_lltoa (char *str, int c, unsigned long long n)
642 unsigned base = (c == 'x') ? 16 : 10;
643 char *p;
645 if ((long long) n < 0 && c == 'd')
647 n = (unsigned long long) (-((long long) n));
648 *str++ = '-';
651 p = str;
653 if (base == 16)
656 unsigned d = (unsigned) (n & 0xf);
657 *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
659 while (n >>= 4);
660 else
661 /* BASE == 10 */
664 unsigned m;
666 n = grub_divmod64 (n, 10, &m);
667 *p++ = m + '0';
669 while (n);
671 *p = 0;
673 grub_reverse (str);
674 return p;
678 grub_vsprintf (char *str, const char *fmt, va_list args)
680 char c;
681 int count = 0;
682 auto void write_char (unsigned char ch);
683 auto void write_str (const char *s);
684 auto void write_fill (const char ch, int n);
686 void write_char (unsigned char ch)
688 if (str)
689 *str++ = ch;
690 else
691 grub_putchar (ch);
693 count++;
696 void write_str (const char *s)
698 while (*s)
699 write_char (*s++);
702 void write_fill (const char ch, int n)
704 int i;
705 for (i = 0; i < n; i++)
706 write_char (ch);
709 while ((c = *fmt++) != 0)
711 if (c != '%')
712 write_char (c);
713 else
715 char tmp[32];
716 char *p;
717 unsigned int format1 = 0;
718 unsigned int format2 = ~ 0U;
719 char zerofill = ' ';
720 int rightfill = 0;
721 int n;
722 int longfmt = 0;
723 int longlongfmt = 0;
725 if (*fmt && *fmt =='-')
727 rightfill = 1;
728 fmt++;
731 p = (char *) fmt;
732 /* Read formatting parameters. */
733 while (*p && grub_isdigit (*p))
734 p++;
736 if (p > fmt)
738 char s[p - fmt + 1];
739 grub_strncpy (s, fmt, p - fmt);
740 s[p - fmt] = 0;
741 if (s[0] == '0')
742 zerofill = '0';
743 format1 = grub_strtoul (s, 0, 10);
744 fmt = p;
747 if (*p && *p == '.')
749 p++;
750 fmt++;
751 while (*p && grub_isdigit (*p))
752 p++;
754 if (p > fmt)
756 char fstr[p - fmt + 1];
757 grub_strncpy (fstr, fmt, p - fmt);
758 fstr[p - fmt] = 0;
759 format2 = grub_strtoul (fstr, 0, 10);
760 fmt = p;
764 c = *fmt++;
765 if (c == 'l')
767 longfmt = 1;
768 c = *fmt++;
769 if (c == 'l')
771 longlongfmt = 1;
772 c = *fmt++;
776 switch (c)
778 case 'p':
779 write_str ("0x");
780 c = 'x';
781 longlongfmt |= (sizeof (void *) == sizeof (long long));
782 /* fall through */
783 case 'x':
784 case 'u':
785 case 'd':
786 if (longlongfmt)
788 long long ll;
790 ll = va_arg (args, long long);
791 grub_lltoa (tmp, c, ll);
793 else
795 if (longfmt)
796 n = va_arg (args, long);
797 else
798 n = va_arg (args, int);
799 grub_itoa (tmp, c, n);
801 if (! rightfill && grub_strlen (tmp) < format1)
802 write_fill (zerofill, format1 - grub_strlen (tmp));
803 write_str (tmp);
804 if (rightfill && grub_strlen (tmp) < format1)
805 write_fill (zerofill, format1 - grub_strlen (tmp));
806 break;
808 case 'c':
809 n = va_arg (args, int);
810 write_char (n & 0xff);
811 break;
813 case 'C':
815 grub_uint32_t code = va_arg (args, grub_uint32_t);
816 int shift;
817 unsigned mask;
819 if (code <= 0x7f)
821 shift = 0;
822 mask = 0;
824 else if (code <= 0x7ff)
826 shift = 6;
827 mask = 0xc0;
829 else if (code <= 0xffff)
831 shift = 12;
832 mask = 0xe0;
834 else if (code <= 0x1fffff)
836 shift = 18;
837 mask = 0xf0;
839 else if (code <= 0x3ffffff)
841 shift = 24;
842 mask = 0xf8;
844 else if (code <= 0x7fffffff)
846 shift = 30;
847 mask = 0xfc;
849 else
851 code = '?';
852 shift = 0;
853 mask = 0;
856 write_char (mask | (code >> shift));
858 for (shift -= 6; shift >= 0; shift -= 6)
859 write_char (0x80 | (0x3f & (code >> shift)));
861 break;
863 case 's':
864 p = va_arg (args, char *);
865 if (p)
867 grub_size_t len = 0;
868 while (len < format2 && p[len])
869 len++;
871 if (!rightfill && len < format1)
872 write_fill (zerofill, format1 - len);
874 grub_size_t i;
875 for (i = 0; i < len; i++)
876 write_char (*p++);
878 if (rightfill && len < format1)
879 write_fill (zerofill, format1 - len);
881 else
882 write_str ("(null)");
884 break;
886 default:
887 write_char (c);
888 break;
893 if (str)
894 *str = '\0';
896 if (count && !str)
897 grub_refresh ();
899 return count;
903 grub_sprintf (char *str, const char *fmt, ...)
905 va_list ap;
906 int ret;
908 va_start (ap, fmt);
909 ret = grub_vsprintf (str, fmt, ap);
910 va_end (ap);
912 return ret;
915 /* Convert UTF-16 to UTF-8. */
916 grub_uint8_t *
917 grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
918 grub_size_t size)
920 grub_uint32_t code_high = 0;
922 while (size--)
924 grub_uint32_t code = *src++;
926 if (code_high)
928 if (code >= 0xDC00 && code <= 0xDFFF)
930 /* Surrogate pair. */
931 code = ((code_high - 0xD800) << 12) + (code - 0xDC00) + 0x10000;
933 *dest++ = (code >> 18) | 0xF0;
934 *dest++ = ((code >> 12) & 0x3F) | 0x80;
935 *dest++ = ((code >> 6) & 0x3F) | 0x80;
936 *dest++ = (code & 0x3F) | 0x80;
938 else
940 /* Error... */
941 *dest++ = '?';
944 code_high = 0;
946 else
948 if (code <= 0x007F)
949 *dest++ = code;
950 else if (code <= 0x07FF)
952 *dest++ = (code >> 6) | 0xC0;
953 *dest++ = (code & 0x3F) | 0x80;
955 else if (code >= 0xD800 && code <= 0xDBFF)
957 code_high = code;
958 continue;
960 else if (code >= 0xDC00 && code <= 0xDFFF)
962 /* Error... */
963 *dest++ = '?';
965 else
967 *dest++ = (code >> 12) | 0xE0;
968 *dest++ = ((code >> 6) & 0x3F) | 0x80;
969 *dest++ = (code & 0x3F) | 0x80;
974 return dest;
977 /* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
978 bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string.
979 Return the number of characters converted. DEST must be able to hold
980 at least DESTSIZE characters. If an invalid sequence is found, return -1.
981 If SRCEND is not NULL, then *SRCEND is set to the next byte after the
982 last byte used in SRC. */
983 grub_ssize_t
984 grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
985 const grub_uint8_t *src, grub_size_t srcsize,
986 const grub_uint8_t **srcend)
988 grub_uint32_t *p = dest;
989 int count = 0;
990 grub_uint32_t code = 0;
992 if (srcend)
993 *srcend = src;
995 while (srcsize && destsize)
997 grub_uint32_t c = *src++;
998 if (srcsize != (grub_size_t)-1)
999 srcsize--;
1000 if (count)
1002 if ((c & 0xc0) != 0x80)
1004 /* invalid */
1005 return -1;
1007 else
1009 code <<= 6;
1010 code |= (c & 0x3f);
1011 count--;
1014 else
1016 if (c == 0)
1017 break;
1019 if ((c & 0x80) == 0x00)
1020 code = c;
1021 else if ((c & 0xe0) == 0xc0)
1023 count = 1;
1024 code = c & 0x1f;
1026 else if ((c & 0xf0) == 0xe0)
1028 count = 2;
1029 code = c & 0x0f;
1031 else if ((c & 0xf8) == 0xf0)
1033 count = 3;
1034 code = c & 0x07;
1036 else if ((c & 0xfc) == 0xf8)
1038 count = 4;
1039 code = c & 0x03;
1041 else if ((c & 0xfe) == 0xfc)
1043 count = 5;
1044 code = c & 0x01;
1046 else
1047 return -1;
1050 if (count == 0)
1052 *p++ = code;
1053 destsize--;
1057 if (srcend)
1058 *srcend = src;
1059 return p - dest;
1062 /* Abort GRUB. This function does not return. */
1063 void
1064 grub_abort (void)
1066 if (grub_term_get_current_output ())
1068 grub_printf ("\nAborted.");
1070 if (grub_term_get_current_input ())
1072 grub_printf (" Press any key to exit.");
1073 grub_getkey ();
1077 grub_exit ();
1079 /* GCC emits references to abort(). */
1080 void abort (void) __attribute__ ((alias ("grub_abort")));
1082 #ifdef NEED_ENABLE_EXECUTE_STACK
1083 /* Some gcc versions generate a call to this function
1084 in trampolines for nested functions. */
1085 __enable_execute_stack (void *addr __attribute__ ((unused)))
1088 #endif