2008-09-29 Felix Zielcke <fzielcke@z-51.de>
[grub2/phcoder/solaris.git] / kern / misc.c
blob635eb7227fa6ff57505996b9f989653d40cb0126
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 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 return (int) *s1 - (int) *s2;
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 return (int) *s1 - (int) *s2;
217 s1++;
218 s2++;
221 return (int) *s1 - (int) *s2;
225 grub_strncasecmp (const char *s1, const char *s2, int c)
227 int p = 1;
229 while (grub_tolower (*s1) && grub_tolower (*s2) && p < c)
231 if (grub_tolower (*s1) != grub_tolower (*s2))
232 return (int) grub_tolower (*s1) - (int) grub_tolower (*s2);
234 s1++;
235 s2++;
236 p++;
239 return (int) *s1 - (int) *s2;
242 char *
243 grub_strchr (const char *s, int c)
245 while (*s)
247 if (*s == c)
248 return (char *) s;
249 s++;
252 return 0;
255 char *
256 grub_strrchr (const char *s, int c)
258 char *p = 0;
260 while (*s)
262 if (*s == c)
263 p = (char *) s;
264 s++;
267 return p;
270 /* Copied from gnulib.
271 Written by Bruno Haible <bruno@clisp.org>, 2005. */
272 char *
273 grub_strstr (const char *haystack, const char *needle)
275 /* Be careful not to look at the entire extent of haystack or needle
276 until needed. This is useful because of these two cases:
277 - haystack may be very long, and a match of needle found early,
278 - needle may be very long, and not even a short initial segment of
279 needle may be found in haystack. */
280 if (*needle != '\0')
282 /* Speed up the following searches of needle by caching its first
283 character. */
284 char b = *needle++;
286 for (;; haystack++)
288 if (*haystack == '\0')
289 /* No match. */
290 return NULL;
291 if (*haystack == b)
292 /* The first character matches. */
294 const char *rhaystack = haystack + 1;
295 const char *rneedle = needle;
297 for (;; rhaystack++, rneedle++)
299 if (*rneedle == '\0')
300 /* Found a match. */
301 return (char *) haystack;
302 if (*rhaystack == '\0')
303 /* No match. */
304 return NULL;
305 if (*rhaystack != *rneedle)
306 /* Nothing in this round. */
307 break;
312 else
313 return (char *) haystack;
317 grub_strword (const char *haystack, const char *needle)
319 const char *n_pos = needle;
321 while (grub_iswordseparator (*haystack))
322 haystack++;
324 while (*haystack)
326 /* Crawl both the needle and the haystack word we're on. */
327 while(*haystack && !grub_iswordseparator (*haystack)
328 && *haystack == *n_pos)
330 haystack++;
331 n_pos++;
334 /* If we reached the end of both words at the same time, the word
335 is found. If not, eat everything in the haystack that isn't the
336 next word (or the end of string) and "reset" the needle. */
337 if ( (!*haystack || grub_iswordseparator (*haystack))
338 && (!*n_pos || grub_iswordseparator (*n_pos)))
339 return 1;
340 else
342 n_pos = needle;
343 while (*haystack && !grub_iswordseparator (*haystack))
344 haystack++;
345 while (grub_iswordseparator (*haystack))
346 haystack++;
350 return 0;
354 grub_iswordseparator (int c)
356 return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
360 grub_isspace (int c)
362 return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
366 grub_isprint (int c)
368 return (c >= ' ' && c <= '~');
372 grub_isalpha (int c)
374 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
378 grub_isdigit (int c)
380 return (c >= '0' && c <= '9');
384 grub_isgraph (int c)
386 return (c >= '!' && c <= '~');
390 grub_tolower (int c)
392 if (c >= 'A' && c <= 'Z')
393 return c - 'A' + 'a';
395 return c;
399 unsigned long
400 grub_strtoul (const char *str, char **end, int base)
402 unsigned long long num;
404 num = grub_strtoull (str, end, base);
405 if (num > ~0UL)
407 grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
408 return ~0UL;
411 return (unsigned long) num;
414 unsigned long long
415 grub_strtoull (const char *str, char **end, int base)
417 unsigned long long num = 0;
418 int found = 0;
420 /* Skip white spaces. */
421 while (*str && grub_isspace (*str))
422 str++;
424 /* Guess the base, if not specified. The prefix `0x' means 16, and
425 the prefix `0' means 8. */
426 if (base == 0 && str[0] == '0')
428 if (str[1] == 'x')
430 if (base == 0 || base == 16)
432 base = 16;
433 str += 2;
436 else if (str[1] >= '0' && str[1] <= '7')
437 base = 8;
440 if (base == 0)
441 base = 10;
443 while (*str)
445 unsigned long digit;
447 digit = grub_tolower (*str) - '0';
448 if (digit > 9)
450 digit += '0' - 'a' + 10;
451 if (digit >= (unsigned long) base)
452 break;
455 found = 1;
457 /* NUM * BASE + DIGIT > ~0ULL */
458 if (num > grub_divmod64 (~0ULL - digit, base, 0))
460 grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
461 return ~0ULL;
464 num = num * base + digit;
465 str++;
468 if (! found)
470 grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number");
471 return 0;
474 if (end)
475 *end = (char *) str;
477 return num;
480 char *
481 grub_strdup (const char *s)
483 grub_size_t len;
484 char *p;
486 len = grub_strlen (s) + 1;
487 p = (char *) grub_malloc (len);
488 if (! p)
489 return 0;
491 return grub_memcpy (p, s, len);
494 char *
495 grub_strndup (const char *s, grub_size_t n)
497 grub_size_t len;
498 char *p;
500 len = grub_strlen (s);
501 if (len > n)
502 len = n;
503 p = (char *) grub_malloc (len + 1);
504 if (! p)
505 return 0;
507 grub_memcpy (p, s, len);
508 p[len] = '\0';
509 return p;
512 void *
513 grub_memset (void *s, int c, grub_size_t n)
515 unsigned char *p = (unsigned char *) s;
517 while (n--)
518 *p++ = (unsigned char) c;
520 return s;
522 void *memset (void *s, int c, grub_size_t n)
523 __attribute__ ((alias ("grub_memset")));
525 grub_size_t
526 grub_strlen (const char *s)
528 const char *p = s;
530 while (*p)
531 p++;
533 return p - s;
536 static inline void
537 grub_reverse (char *str)
539 char *p = str + grub_strlen (str) - 1;
541 while (str < p)
543 char tmp;
545 tmp = *str;
546 *str = *p;
547 *p = tmp;
548 str++;
549 p--;
553 static char *
554 grub_itoa (char *str, int c, unsigned n)
556 unsigned base = (c == 'x') ? 16 : 10;
557 char *p;
559 if ((int) n < 0 && c == 'd')
561 n = (unsigned) (-((int) n));
562 *str++ = '-';
565 p = str;
568 unsigned d = n % base;
569 *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
571 while (n /= base);
572 *p = 0;
574 grub_reverse (str);
575 return p;
578 /* Divide N by D, return the quotient, and store the remainder in *R. */
579 grub_uint64_t
580 grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r)
582 /* This algorithm is typically implemented by hardware. The idea
583 is to get the highest bit in N, 64 times, by keeping
584 upper(N * 2^i) = upper((Q * 10 + M) * 2^i), where upper
585 represents the high 64 bits in 128-bits space. */
586 unsigned bits = 64;
587 unsigned long long q = 0;
588 unsigned m = 0;
590 /* Skip the slow computation if 32-bit arithmetic is possible. */
591 if (n < 0xffffffff)
593 if (r)
594 *r = ((grub_uint32_t) n) % d;
596 return ((grub_uint32_t) n) / d;
599 while (bits--)
601 m <<= 1;
603 if (n & (1ULL << 63))
604 m |= 1;
606 q <<= 1;
607 n <<= 1;
609 if (m >= d)
611 q |= 1;
612 m -= d;
616 if (r)
617 *r = m;
619 return q;
622 /* Convert a long long value to a string. This function avoids 64-bit
623 modular arithmetic or divisions. */
624 static char *
625 grub_lltoa (char *str, int c, unsigned long long n)
627 unsigned base = (c == 'x') ? 16 : 10;
628 char *p;
630 if ((long long) n < 0 && c == 'd')
632 n = (unsigned long long) (-((long long) n));
633 *str++ = '-';
636 p = str;
638 if (base == 16)
641 unsigned d = (unsigned) (n & 0xf);
642 *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
644 while (n >>= 4);
645 else
646 /* BASE == 10 */
649 unsigned m;
651 n = grub_divmod64 (n, 10, &m);
652 *p++ = m + '0';
654 while (n);
656 *p = 0;
658 grub_reverse (str);
659 return p;
663 grub_vsprintf (char *str, const char *fmt, va_list args)
665 char c;
666 int count = 0;
667 auto void write_char (unsigned char ch);
668 auto void write_str (const char *s);
669 auto void write_fill (const char ch, int n);
671 void write_char (unsigned char ch)
673 if (str)
674 *str++ = ch;
675 else
676 grub_putchar (ch);
678 count++;
681 void write_str (const char *s)
683 while (*s)
684 write_char (*s++);
687 void write_fill (const char ch, int n)
689 int i;
690 for (i = 0; i < n; i++)
691 write_char (ch);
694 while ((c = *fmt++) != 0)
696 if (c != '%')
697 write_char (c);
698 else
700 char tmp[32];
701 char *p;
702 unsigned int format1 = 0;
703 unsigned int format2 = 3;
704 char zerofill = ' ';
705 int rightfill = 0;
706 int n;
707 int longfmt = 0;
708 int longlongfmt = 0;
710 if (*fmt && *fmt =='-')
712 rightfill = 1;
713 fmt++;
716 p = (char *) fmt;
717 /* Read formatting parameters. */
718 while (*p && grub_isdigit (*p))
719 p++;
721 if (p > fmt)
723 char s[p - fmt + 1];
724 grub_strncpy (s, fmt, p - fmt);
725 s[p - fmt] = 0;
726 if (s[0] == '0')
727 zerofill = '0';
728 format1 = grub_strtoul (s, 0, 10);
729 fmt = p;
730 if (*p && *p == '.')
732 p++;
733 fmt++;
734 while (*p && grub_isdigit (*p))
735 p++;
737 if (p > fmt)
739 char fstr[p - fmt];
740 grub_strncpy (fstr, fmt, p - fmt);
741 format2 = grub_strtoul (fstr, 0, 10);
742 fmt = p;
747 c = *fmt++;
748 if (c == 'l')
750 longfmt = 1;
751 c = *fmt++;
752 if (c == 'l')
754 longlongfmt = 1;
755 c = *fmt++;
759 switch (c)
761 case 'p':
762 write_str ("0x");
763 c = 'x';
764 longlongfmt |= (sizeof (void *) == sizeof (long long));
765 /* fall through */
766 case 'x':
767 case 'u':
768 case 'd':
769 if (longlongfmt)
771 long long ll;
773 ll = va_arg (args, long long);
774 grub_lltoa (tmp, c, ll);
776 else
778 if (longfmt)
779 n = va_arg (args, long);
780 else
781 n = va_arg (args, int);
782 grub_itoa (tmp, c, n);
784 if (! rightfill && grub_strlen (tmp) < format1)
785 write_fill (zerofill, format1 - grub_strlen (tmp));
786 write_str (tmp);
787 if (rightfill && grub_strlen (tmp) < format1)
788 write_fill (zerofill, format1 - grub_strlen (tmp));
789 break;
791 case 'c':
792 n = va_arg (args, int);
793 write_char (n & 0xff);
794 break;
796 case 'C':
798 grub_uint32_t code = va_arg (args, grub_uint32_t);
799 int shift;
800 unsigned mask;
802 if (code <= 0x7f)
804 shift = 0;
805 mask = 0;
807 else if (code <= 0x7ff)
809 shift = 6;
810 mask = 0xc0;
812 else if (code <= 0xffff)
814 shift = 12;
815 mask = 0xe0;
817 else if (code <= 0x1fffff)
819 shift = 18;
820 mask = 0xf0;
822 else if (code <= 0x3ffffff)
824 shift = 24;
825 mask = 0xf8;
827 else if (code <= 0x7fffffff)
829 shift = 30;
830 mask = 0xfc;
832 else
834 code = '?';
835 shift = 0;
836 mask = 0;
839 write_char (mask | (code >> shift));
841 for (shift -= 6; shift >= 0; shift -= 6)
842 write_char (0x80 | (0x3f & (code >> shift)));
844 break;
846 case 's':
847 p = va_arg (args, char *);
848 if (p)
850 if (!rightfill && grub_strlen (p) < format1)
851 write_fill (zerofill, format1 - grub_strlen (p));
853 write_str (p);
855 if (rightfill && grub_strlen (p) < format1)
856 write_fill (zerofill, format1 - grub_strlen (p));
858 else
859 write_str ("(null)");
861 break;
863 default:
864 write_char (c);
865 break;
870 if (str)
871 *str = '\0';
873 if (count && !str)
874 grub_refresh ();
876 return count;
880 grub_sprintf (char *str, const char *fmt, ...)
882 va_list ap;
883 int ret;
885 va_start (ap, fmt);
886 ret = grub_vsprintf (str, fmt, ap);
887 va_end (ap);
889 return ret;
892 /* Convert UTF-16 to UTF-8. */
893 grub_uint8_t *
894 grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
895 grub_size_t size)
897 grub_uint32_t code_high = 0;
899 while (size--)
901 grub_uint32_t code = *src++;
903 if (code_high)
905 if (code >= 0xDC00 && code <= 0xDFFF)
907 /* Surrogate pair. */
908 code = ((code_high - 0xD800) << 12) + (code - 0xDC00) + 0x10000;
910 *dest++ = (code >> 18) | 0xF0;
911 *dest++ = ((code >> 12) & 0x3F) | 0x80;
912 *dest++ = ((code >> 6) & 0x3F) | 0x80;
913 *dest++ = (code & 0x3F) | 0x80;
915 else
917 /* Error... */
918 *dest++ = '?';
921 code_high = 0;
923 else
925 if (code <= 0x007F)
926 *dest++ = code;
927 else if (code <= 0x07FF)
929 *dest++ = (code >> 6) | 0xC0;
930 *dest++ = (code & 0x3F) | 0x80;
932 else if (code >= 0xD800 && code <= 0xDBFF)
934 code_high = code;
935 continue;
937 else if (code >= 0xDC00 && code <= 0xDFFF)
939 /* Error... */
940 *dest++ = '?';
942 else
944 *dest++ = (code >> 12) | 0xE0;
945 *dest++ = ((code >> 6) & 0x3F) | 0x80;
946 *dest++ = (code & 0x3F) | 0x80;
951 return dest;
954 /* Convert an UTF-8 string to an UCS-4 string. Return the number of
955 characters converted. DEST must be able to hold at least SIZE
956 characters (when the input is unknown). If an invalid sequence is found,
957 return -1. */
958 grub_ssize_t
959 grub_utf8_to_ucs4 (grub_uint32_t *dest, const grub_uint8_t *src,
960 grub_size_t size)
962 grub_uint32_t *p = dest;
963 int count = 0;
964 grub_uint32_t code = 0;
966 while (size--)
968 grub_uint32_t c = *src++;
970 if (count)
972 if ((c & 0xc0) != 0x80)
974 /* invalid */
975 return -1;
977 else
979 code <<= 6;
980 code |= (c & 0x3f);
981 count--;
984 else
986 if ((c & 0x80) == 0x00)
987 code = c;
988 else if ((c & 0xe0) == 0xc0)
990 count = 1;
991 code = c & 0x1f;
993 else if ((c & 0xf0) == 0xe0)
995 count = 2;
996 code = c & 0x0f;
998 else if ((c & 0xf8) == 0xf0)
1000 count = 3;
1001 code = c & 0x07;
1003 else if ((c & 0xfc) == 0xf8)
1005 count = 4;
1006 code = c & 0x03;
1008 else if ((c & 0xfe) == 0xfc)
1010 count = 5;
1011 code = c & 0x01;
1013 else
1014 /* invalid */
1015 return -1;
1018 if (count == 0)
1019 *p++ = code;
1022 return p - dest;
1025 /* Abort GRUB. This function does not return. */
1026 void
1027 grub_abort (void)
1029 if (grub_term_get_current ())
1031 grub_printf ("\nAborted. Press any key to exit.");
1032 grub_getkey ();
1035 grub_exit ();
1037 /* GCC emits references to abort(). */
1038 void abort (void) __attribute__ ((alias ("grub_abort")));
1040 #ifdef NEED_ENABLE_EXECUTE_STACK
1041 /* Some gcc versions generate a call to this function
1042 in trampolines for nested functions. */
1043 __enable_execute_stack (void *addr __attribute__ ((unused)))
1046 #endif