2008-04-04 Pavel Roskin <proski@gnu.org>
[grub2/bean.git] / kern / misc.c
blobe6d5c057fe020cde469edae941368d50690e7512
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 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/time.h>
28 void *
29 grub_memmove (void *dest, const void *src, grub_size_t n)
31 char *d = (char *) dest;
32 const char *s = (const char *) src;
34 if (d < s)
35 while (n--)
36 *d++ = *s++;
37 else
39 d += n;
40 s += n;
42 while (n--)
43 *--d = *--s;
46 return dest;
48 void *memmove (void *dest, const void *src, grub_size_t n)
49 __attribute__ ((alias ("grub_memmove")));
50 /* GCC emits references to memcpy() for struct copies etc. */
51 void *memcpy (void *dest, const void *src, grub_size_t n)
52 __attribute__ ((alias ("grub_memmove")));
54 char *
55 grub_strcpy (char *dest, const char *src)
57 char *p = dest;
59 while ((*p++ = *src++) != '\0')
62 return dest;
65 char *
66 grub_strncpy (char *dest, const char *src, int c)
68 char *p = dest;
70 while ((*p++ = *src++) != '\0' && --c)
73 return dest;
76 char *
77 grub_stpcpy (char *dest, const char *src)
79 char *d = dest;
80 const char *s = src;
83 *d++ = *s;
84 while (*s++ != '\0');
86 return d - 1;
89 char *
90 grub_strcat (char *dest, const char *src)
92 char *p = dest;
94 while (*p)
95 p++;
97 while ((*p++ = *src++) != '\0')
100 return dest;
103 char *
104 grub_strncat (char *dest, const char *src, int c)
106 char *p = dest;
108 while (*p)
109 p++;
111 while ((*p++ = *src++) != '\0' && --c)
113 *(--p) = '\0';
115 return dest;
119 grub_printf (const char *fmt, ...)
121 va_list ap;
122 int ret;
124 va_start (ap, fmt);
125 ret = grub_vprintf (fmt, ap);
126 va_end (ap);
128 return ret;
131 void
132 grub_real_dprintf (const char *file, const int line, const char *condition,
133 const char *fmt, ...)
135 va_list args;
136 const char *debug = grub_env_get ("debug");
138 if (! debug)
139 return;
141 if (grub_strword (debug, "all") || grub_strword (debug, condition))
143 grub_printf ("%s:%d: ", file, line);
144 va_start (args, fmt);
145 grub_vprintf (fmt, args);
146 va_end (args);
151 grub_vprintf (const char *fmt, va_list args)
153 int ret;
155 ret = grub_vsprintf (0, fmt, args);
156 grub_refresh ();
157 return ret;
161 grub_memcmp (const void *s1, const void *s2, grub_size_t n)
163 const char *t1 = s1;
164 const char *t2 = s2;
166 while (n--)
168 if (*t1 != *t2)
169 return (int) *t1 - (int) *t2;
171 t1++;
172 t2++;
175 return 0;
177 int memcmp (const void *s1, const void *s2, grub_size_t n)
178 __attribute__ ((alias ("grub_memcmp")));
181 grub_strcmp (const char *s1, const char *s2)
183 while (*s1 && *s2)
185 if (*s1 != *s2)
186 return (int) *s1 - (int) *s2;
188 s1++;
189 s2++;
192 return (int) *s1 - (int) *s2;
196 grub_strncmp (const char *s1, const char *s2, grub_size_t n)
198 if (n == 0)
199 return 0;
201 while (*s1 && *s2 && --n)
203 if (*s1 != *s2)
204 return (int) *s1 - (int) *s2;
206 s1++;
207 s2++;
210 return (int) *s1 - (int) *s2;
214 grub_strncasecmp (const char *s1, const char *s2, int c)
216 int p = 1;
218 while (grub_tolower (*s1) && grub_tolower (*s2) && p < c)
220 if (grub_tolower (*s1) != grub_tolower (*s2))
221 return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
223 s1++;
224 s2++;
225 p++;
228 return (int) *s1 - (int) *s2;
231 char *
232 grub_strchr (const char *s, int c)
234 while (*s)
236 if (*s == c)
237 return (char *) s;
238 s++;
241 return 0;
244 char *
245 grub_strrchr (const char *s, int c)
247 char *p = 0;
249 while (*s)
251 if (*s == c)
252 p = (char *) s;
253 s++;
256 return p;
259 /* Copied from gnulib.
260 Written by Bruno Haible <bruno@clisp.org>, 2005. */
261 char *
262 grub_strstr (const char *haystack, const char *needle)
264 /* Be careful not to look at the entire extent of haystack or needle
265 until needed. This is useful because of these two cases:
266 - haystack may be very long, and a match of needle found early,
267 - needle may be very long, and not even a short initial segment of
268 needle may be found in haystack. */
269 if (*needle != '\0')
271 /* Speed up the following searches of needle by caching its first
272 character. */
273 char b = *needle++;
275 for (;; haystack++)
277 if (*haystack == '\0')
278 /* No match. */
279 return NULL;
280 if (*haystack == b)
281 /* The first character matches. */
283 const char *rhaystack = haystack + 1;
284 const char *rneedle = needle;
286 for (;; rhaystack++, rneedle++)
288 if (*rneedle == '\0')
289 /* Found a match. */
290 return (char *) haystack;
291 if (*rhaystack == '\0')
292 /* No match. */
293 return NULL;
294 if (*rhaystack != *rneedle)
295 /* Nothing in this round. */
296 break;
301 else
302 return (char *) haystack;
306 grub_strword (const char *haystack, const char *needle)
308 const char *n_pos = needle;
310 while (grub_iswordseparator (*haystack))
311 haystack++;
313 while (*haystack)
315 /* Crawl both the needle and the haystack word we're on. */
316 while(*haystack && !grub_iswordseparator (*haystack)
317 && *haystack == *n_pos)
319 haystack++;
320 n_pos++;
323 /* If we reached the end of both words at the same time, the word
324 is found. If not, eat everything in the haystack that isn't the
325 next word (or the end of string) and "reset" the needle. */
326 if ( (!*haystack || grub_iswordseparator (*haystack))
327 && (!*n_pos || grub_iswordseparator (*n_pos)))
328 return 1;
329 else
331 n_pos = needle;
332 while (*haystack && !grub_iswordseparator (*haystack))
333 haystack++;
334 while (grub_iswordseparator (*haystack))
335 haystack++;
339 return 0;
343 grub_iswordseparator (int c)
345 return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
349 grub_isspace (int c)
351 return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
355 grub_isprint (int c)
357 return (c >= ' ' && c <= '~');
361 grub_isalpha (int c)
363 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
367 grub_isdigit (int c)
369 return (c >= '0' && c <= '9');
373 grub_isgraph (int c)
375 return (c >= '!' && c <= '~');
379 grub_tolower (int c)
381 if (c >= 'A' && c <= 'Z')
382 return c - 'A' + 'a';
384 return c;
388 unsigned long
389 grub_strtoul (const char *str, char **end, int base)
391 unsigned long long num;
393 num = grub_strtoull (str, end, base);
394 if (num > ~0UL)
396 grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
397 return ~0UL;
400 return (unsigned long) num;
403 unsigned long long
404 grub_strtoull (const char *str, char **end, int base)
406 unsigned long long num = 0;
407 int found = 0;
409 /* Skip white spaces. */
410 while (*str && grub_isspace (*str))
411 str++;
413 /* Guess the base, if not specified. The prefix `0x' means 16, and
414 the prefix `0' means 8. */
415 if (base == 0 && str[0] == '0')
417 if (str[1] == 'x')
419 if (base == 0 || base == 16)
421 base = 16;
422 str += 2;
425 else if (str[1] >= '0' && str[1] <= '7')
426 base = 8;
429 if (base == 0)
430 base = 10;
432 while (*str)
434 unsigned long digit;
436 digit = grub_tolower (*str) - '0';
437 if (digit > 9)
439 digit += '0' - 'a' + 10;
440 if (digit >= (unsigned long) base)
441 break;
444 found = 1;
446 /* NUM * BASE + DIGIT > ~0ULL */
447 if (num > grub_divmod64 (~0ULL - digit, base, 0))
449 grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
450 return ~0ULL;
453 num = num * base + digit;
454 str++;
457 if (! found)
459 grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number");
460 return 0;
463 if (end)
464 *end = (char *) str;
466 return num;
469 char *
470 grub_strdup (const char *s)
472 grub_size_t len;
473 char *p;
475 len = grub_strlen (s) + 1;
476 p = (char *) grub_malloc (len);
477 if (! p)
478 return 0;
480 return grub_memcpy (p, s, len);
483 char *
484 grub_strndup (const char *s, grub_size_t n)
486 grub_size_t len;
487 char *p;
489 len = grub_strlen (s);
490 if (len > n)
491 len = n;
492 p = (char *) grub_malloc (len + 1);
493 if (! p)
494 return 0;
496 grub_memcpy (p, s, len);
497 p[len] = '\0';
498 return p;
501 void *
502 grub_memset (void *s, int c, grub_size_t n)
504 unsigned char *p = (unsigned char *) s;
506 while (n--)
507 *p++ = (unsigned char) c;
509 return s;
511 void *memset (void *s, int c, grub_size_t n)
512 __attribute__ ((alias ("grub_memset")));
514 grub_size_t
515 grub_strlen (const char *s)
517 const char *p = s;
519 while (*p)
520 p++;
522 return p - s;
525 static inline void
526 grub_reverse (char *str)
528 char *p = str + grub_strlen (str) - 1;
530 while (str < p)
532 char tmp;
534 tmp = *str;
535 *str = *p;
536 *p = tmp;
537 str++;
538 p--;
542 static char *
543 grub_itoa (char *str, int c, unsigned n)
545 unsigned base = (c == 'x') ? 16 : 10;
546 char *p;
548 if ((int) n < 0 && c == 'd')
550 n = (unsigned) (-((int) n));
551 *str++ = '-';
554 p = str;
557 unsigned d = n % base;
558 *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
560 while (n /= base);
561 *p = 0;
563 grub_reverse (str);
564 return p;
567 /* Divide N by D, return the quotient, and store the remainder in *R. */
568 grub_uint64_t
569 grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r)
571 /* This algorithm is typically implemented by hardware. The idea
572 is to get the highest bit in N, 64 times, by keeping
573 upper(N * 2^i) = upper((Q * 10 + M) * 2^i), where upper
574 represents the high 64 bits in 128-bits space. */
575 unsigned bits = 64;
576 unsigned long long q = 0;
577 unsigned m = 0;
579 /* Skip the slow computation if 32-bit arithmetic is possible. */
580 if (n < 0xffffffff)
582 if (r)
583 *r = ((grub_uint32_t) n) % d;
585 return ((grub_uint32_t) n) / d;
588 while (bits--)
590 m <<= 1;
592 if (n & (1ULL << 63))
593 m |= 1;
595 q <<= 1;
596 n <<= 1;
598 if (m >= d)
600 q |= 1;
601 m -= d;
605 if (r)
606 *r = m;
608 return q;
611 /* Convert a long long value to a string. This function avoids 64-bit
612 modular arithmetic or divisions. */
613 static char *
614 grub_lltoa (char *str, int c, unsigned long long n)
616 unsigned base = (c == 'x') ? 16 : 10;
617 char *p;
619 if ((long long) n < 0 && c == 'd')
621 n = (unsigned long long) (-((long long) n));
622 *str++ = '-';
625 p = str;
627 if (base == 16)
630 unsigned d = (unsigned) (n & 0xf);
631 *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
633 while (n >>= 4);
634 else
635 /* BASE == 10 */
638 unsigned m;
640 n = grub_divmod64 (n, 10, &m);
641 *p++ = m + '0';
643 while (n);
645 *p = 0;
647 grub_reverse (str);
648 return p;
651 static char *
652 grub_ftoa (char *str, double f, int round)
654 unsigned int intp;
655 unsigned int fractp;
656 unsigned int power = 1;
657 int i;
659 for (i = 0; i < round; i++)
660 power *= 10;
662 intp = f;
663 fractp = (f - (float) intp) * power;
665 grub_sprintf (str, "%d.%d", intp, fractp);
666 return str;
670 grub_vsprintf (char *str, const char *fmt, va_list args)
672 char c;
673 int count = 0;
674 auto void write_char (unsigned char ch);
675 auto void write_str (const char *s);
676 auto void write_fill (const char ch, int n);
678 void write_char (unsigned char ch)
680 if (str)
681 *str++ = ch;
682 else
683 grub_putchar (ch);
685 count++;
688 void write_str (const char *s)
690 while (*s)
691 write_char (*s++);
694 void write_fill (const char ch, int n)
696 int i;
697 for (i = 0; i < n; i++)
698 write_char (ch);
701 while ((c = *fmt++) != 0)
703 if (c != '%')
704 write_char (c);
705 else
707 char tmp[32];
708 char *p;
709 unsigned int format1 = 0;
710 unsigned int format2 = 3;
711 char zerofill = ' ';
712 int rightfill = 0;
713 int n;
714 int longfmt = 0;
715 int longlongfmt = 0;
717 if (*fmt && *fmt =='-')
719 rightfill = 1;
720 fmt++;
723 p = (char *) fmt;
724 /* Read formatting parameters. */
725 while (*p && grub_isdigit (*p))
726 p++;
728 if (p > fmt)
730 char s[p - fmt + 1];
731 grub_strncpy (s, fmt, p - fmt);
732 s[p - fmt] = 0;
733 if (s[0] == '0')
734 zerofill = '0';
735 format1 = grub_strtoul (s, 0, 10);
736 fmt = p;
737 if (*p && *p == '.')
739 p++;
740 fmt++;
741 while (*p && grub_isdigit (*p))
742 p++;
744 if (p > fmt)
746 char fstr[p - fmt];
747 grub_strncpy (fstr, fmt, p - fmt);
748 format2 = grub_strtoul (fstr, 0, 10);
749 fmt = p;
754 c = *fmt++;
755 if (c == 'l')
757 longfmt = 1;
758 c = *fmt++;
759 if (c == 'l')
761 longlongfmt = 1;
762 c = *fmt++;
766 switch (c)
768 case 'p':
769 write_str ("0x");
770 c = 'x';
771 longlongfmt |= (sizeof (void *) == sizeof (long long));
772 /* fall through */
773 case 'x':
774 case 'u':
775 case 'd':
776 if (longlongfmt)
778 long long ll;
780 ll = va_arg (args, long long);
781 grub_lltoa (tmp, c, ll);
783 else
785 if (longfmt)
786 n = va_arg (args, long);
787 else
788 n = va_arg (args, int);
789 grub_itoa (tmp, c, n);
791 if (! rightfill && grub_strlen (tmp) < format1)
792 write_fill (zerofill, format1 - grub_strlen (tmp));
793 write_str (tmp);
794 if (rightfill && grub_strlen (tmp) < format1)
795 write_fill (zerofill, format1 - grub_strlen (tmp));
796 break;
798 case 'c':
799 n = va_arg (args, int);
800 write_char (n & 0xff);
801 break;
803 case 'f':
805 float f;
806 f = va_arg (args, double);
807 grub_ftoa (tmp, f, format2);
808 if (!rightfill && grub_strlen (tmp) < format1)
809 write_fill (zerofill, format1 - grub_strlen (tmp));
810 write_str (tmp);
811 if (rightfill && grub_strlen (tmp) < format1)
812 write_fill (zerofill, format1 - grub_strlen (tmp));
813 break;
816 case 'C':
818 grub_uint32_t code = va_arg (args, grub_uint32_t);
819 int shift;
820 unsigned mask;
822 if (code <= 0x7f)
824 shift = 0;
825 mask = 0;
827 else if (code <= 0x7ff)
829 shift = 6;
830 mask = 0xc0;
832 else if (code <= 0xffff)
834 shift = 12;
835 mask = 0xe0;
837 else if (code <= 0x1fffff)
839 shift = 18;
840 mask = 0xf0;
842 else if (code <= 0x3ffffff)
844 shift = 24;
845 mask = 0xf8;
847 else if (code <= 0x7fffffff)
849 shift = 30;
850 mask = 0xfc;
852 else
854 code = '?';
855 shift = 0;
856 mask = 0;
859 write_char (mask | (code >> shift));
861 for (shift -= 6; shift >= 0; shift -= 6)
862 write_char (0x80 | (0x3f & (code >> shift)));
864 break;
866 case 's':
867 p = va_arg (args, char *);
868 if (p)
870 if (!rightfill && grub_strlen (p) < format1)
871 write_fill (zerofill, format1 - grub_strlen (p));
873 write_str (p);
875 if (rightfill && grub_strlen (p) < format1)
876 write_fill (zerofill, format1 - grub_strlen (p));
878 else
879 write_str ("(null)");
881 break;
883 default:
884 write_char (c);
885 break;
890 if (str)
891 *str = '\0';
893 if (count && !str)
894 grub_refresh ();
896 return count;
900 grub_sprintf (char *str, const char *fmt, ...)
902 va_list ap;
903 int ret;
905 va_start (ap, fmt);
906 ret = grub_vsprintf (str, fmt, ap);
907 va_end (ap);
909 return ret;
912 /* Convert UTF-16 to UTF-8. */
913 grub_uint8_t *
914 grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
915 grub_size_t size)
917 grub_uint32_t code_high = 0;
919 while (size--)
921 grub_uint32_t code = *src++;
923 if (code_high)
925 if (code >= 0xDC00 && code <= 0xDFFF)
927 /* Surrogate pair. */
928 code = ((code_high - 0xD800) << 12) + (code - 0xDC00) + 0x10000;
930 *dest++ = (code >> 18) | 0xF0;
931 *dest++ = ((code >> 12) & 0x3F) | 0x80;
932 *dest++ = ((code >> 6) & 0x3F) | 0x80;
933 *dest++ = (code & 0x3F) | 0x80;
935 else
937 /* Error... */
938 *dest++ = '?';
941 code_high = 0;
943 else
945 if (code <= 0x007F)
946 *dest++ = code;
947 else if (code <= 0x07FF)
949 *dest++ = (code >> 6) | 0xC0;
950 *dest++ = (code & 0x3F) | 0x80;
952 else if (code >= 0xD800 && code <= 0xDBFF)
954 code_high = code;
955 continue;
957 else if (code >= 0xDC00 && code <= 0xDFFF)
959 /* Error... */
960 *dest++ = '?';
962 else
964 *dest++ = (code >> 12) | 0xE0;
965 *dest++ = ((code >> 6) & 0x3F) | 0x80;
966 *dest++ = (code & 0x3F) | 0x80;
971 return dest;
974 /* Convert an UTF-8 string to an UCS-4 string. Return the number of
975 characters converted. DEST must be able to hold at least SIZE
976 characters (when the input is unknown). If an invalid sequence is found,
977 return -1. */
978 grub_ssize_t
979 grub_utf8_to_ucs4 (grub_uint32_t *dest, const grub_uint8_t *src,
980 grub_size_t size)
982 grub_uint32_t *p = dest;
983 int count = 0;
984 grub_uint32_t code = 0;
986 while (size--)
988 grub_uint32_t c = *src++;
990 if (count)
992 if ((c & 0xc0) != 0x80)
994 /* invalid */
995 return -1;
997 else
999 code <<= 6;
1000 code |= (c & 0x3f);
1001 count--;
1004 else
1006 if ((c & 0x80) == 0x00)
1007 code = c;
1008 else if ((c & 0xe0) == 0xc0)
1010 count = 1;
1011 code = c & 0x1f;
1013 else if ((c & 0xf0) == 0xe0)
1015 count = 2;
1016 code = c & 0x0f;
1018 else if ((c & 0xf8) == 0xf0)
1020 count = 3;
1021 code = c & 0x07;
1023 else if ((c & 0xfc) == 0xf8)
1025 count = 4;
1026 code = c & 0x03;
1028 else if ((c & 0xfe) == 0xfc)
1030 count = 5;
1031 code = c & 0x01;
1033 else
1034 /* invalid */
1035 return -1;
1038 if (count == 0)
1039 *p++ = code;
1042 return p - dest;
1045 void
1046 grub_millisleep_generic (grub_uint32_t ms)
1048 grub_uint32_t end_at;
1050 end_at = grub_get_rtc () + grub_div_roundup (ms * GRUB_TICKS_PER_SECOND, 1000);
1052 while (grub_get_rtc () < end_at)
1053 grub_cpu_idle ();
1056 /* Abort GRUB. This function does not return. */
1057 void
1058 grub_abort (void)
1060 if (grub_term_get_current ())
1062 grub_printf ("\nAborted. Press any key to exit.");
1063 grub_getkey ();
1066 grub_exit ();
1068 /* GCC emits references to abort(). */
1069 void abort (void) __attribute__ ((alias ("grub_abort")));