1 /* misc.c - definitions of misc functions */
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>
24 #include <grub/term.h>
28 grub_memmove (void *dest
, const void *src
, grub_size_t n
)
30 char *d
= (char *) dest
;
31 const char *s
= (const char *) src
;
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")));
54 grub_strcpy (char *dest
, const char *src
)
58 while ((*p
++ = *src
++) != '\0')
65 grub_strncpy (char *dest
, const char *src
, int c
)
69 while ((*p
++ = *src
++) != '\0' && --c
)
76 grub_stpcpy (char *dest
, const char *src
)
89 grub_strcat (char *dest
, const char *src
)
96 while ((*p
= *src
) != '\0')
106 grub_strncat (char *dest
, const char *src
, int c
)
113 while ((*p
= *src
) != '\0' && c
--)
125 grub_printf (const char *fmt
, ...)
131 ret
= grub_vprintf (fmt
, ap
);
138 int grub_err_printf (const char *fmt
, ...)
139 __attribute__ ((alias("grub_printf")));
143 grub_real_dprintf (const char *file
, const int line
, const char *condition
,
144 const char *fmt
, ...)
147 const char *debug
= grub_env_get ("debug");
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
);
162 grub_vprintf (const char *fmt
, va_list args
)
166 ret
= grub_vsprintf (0, fmt
, args
);
172 grub_memcmp (const void *s1
, const void *s2
, grub_size_t n
)
180 return (int) *t1
- (int) *t2
;
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
)
203 return (int) *s1
- (int) *s2
;
207 grub_strncmp (const char *s1
, const char *s2
, grub_size_t n
)
212 while (*s1
&& *s2
&& --n
)
221 return (int) *s1
- (int) *s2
;
225 grub_strcasecmp (const char *s1
, const char *s2
)
229 if (grub_tolower (*s1
) != grub_tolower (*s2
))
236 return (int) grub_tolower (*s1
) - (int) grub_tolower (*s2
);
240 grub_strncasecmp (const char *s1
, const char *s2
, grub_size_t n
)
245 while (*s1
&& *s2
&& --n
)
247 if (grub_tolower (*s1
) != grub_tolower (*s2
))
254 return (int) grub_tolower (*s1
) - (int) grub_tolower (*s2
);
258 grub_strchr (const char *s
, int c
)
271 grub_strrchr (const char *s
, int c
)
285 /* Copied from gnulib.
286 Written by Bruno Haible <bruno@clisp.org>, 2005. */
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. */
297 /* Speed up the following searches of needle by caching its first
303 if (*haystack
== '\0')
307 /* The first character matches. */
309 const char *rhaystack
= haystack
+ 1;
310 const char *rneedle
= needle
;
312 for (;; rhaystack
++, rneedle
++)
314 if (*rneedle
== '\0')
316 return (char *) haystack
;
317 if (*rhaystack
== '\0')
320 if (*rhaystack
!= *rneedle
)
321 /* Nothing in this round. */
328 return (char *) haystack
;
332 grub_strword (const char *haystack
, const char *needle
)
334 const char *n_pos
= needle
;
336 while (grub_iswordseparator (*haystack
))
341 /* Crawl both the needle and the haystack word we're on. */
342 while(*haystack
&& !grub_iswordseparator (*haystack
)
343 && *haystack
== *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
)))
358 while (*haystack
&& !grub_iswordseparator (*haystack
))
360 while (grub_iswordseparator (*haystack
))
369 grub_iswordseparator (int c
)
371 return (grub_isspace (c
) || c
== ',' || c
== ';' || c
== '|' || c
== '&');
377 return (c
== '\n' || c
== '\r' || c
== ' ' || c
== '\t');
383 return (c
>= ' ' && c
<= '~');
389 return (c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z');
395 return (c
>= '0' && c
<= '9');
401 return (c
>= '!' && c
<= '~');
407 if (c
>= 'A' && c
<= 'Z')
408 return c
- 'A' + 'a';
415 grub_strtoul (const char *str
, char **end
, int base
)
417 unsigned long long num
;
419 num
= grub_strtoull (str
, end
, base
);
422 grub_error (GRUB_ERR_OUT_OF_RANGE
, "overflow is detected");
426 return (unsigned long) num
;
430 grub_strtoull (const char *str
, char **end
, int base
)
432 unsigned long long num
= 0;
435 /* Skip white spaces. */
436 while (*str
&& grub_isspace (*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')
445 if (base
== 0 || base
== 16)
451 else if (str
[1] >= '0' && str
[1] <= '7')
462 digit
= grub_tolower (*str
) - '0';
465 digit
+= '0' - 'a' + 10;
466 if (digit
>= (unsigned long) base
)
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");
479 num
= num
* base
+ digit
;
485 grub_error (GRUB_ERR_BAD_NUMBER
, "unrecognized number");
496 grub_strdup (const char *s
)
501 len
= grub_strlen (s
) + 1;
502 p
= (char *) grub_malloc (len
);
506 return grub_memcpy (p
, s
, len
);
510 grub_strndup (const char *s
, grub_size_t n
)
515 len
= grub_strlen (s
);
518 p
= (char *) grub_malloc (len
+ 1);
522 grub_memcpy (p
, s
, len
);
528 grub_memset (void *s
, int c
, grub_size_t n
)
530 unsigned char *p
= (unsigned char *) s
;
533 *p
++ = (unsigned char) c
;
537 void *memset (void *s
, int c
, grub_size_t n
)
538 __attribute__ ((alias ("grub_memset")));
541 grub_strlen (const char *s
)
552 grub_reverse (char *str
)
554 char *p
= str
+ grub_strlen (str
) - 1;
569 grub_itoa (char *str
, int c
, unsigned n
)
571 unsigned base
= (c
== 'x') ? 16 : 10;
574 if ((int) n
< 0 && c
== 'd')
576 n
= (unsigned) (-((int) n
));
583 unsigned d
= n
% base
;
584 *p
++ = (d
> 9) ? d
+ 'a' - 10 : d
+ '0';
593 /* Divide N by D, return the quotient, and store the remainder in *R. */
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. */
602 unsigned long long q
= 0;
605 /* Skip the slow computation if 32-bit arithmetic is possible. */
609 *r
= ((grub_uint32_t
) n
) % d
;
611 return ((grub_uint32_t
) n
) / d
;
618 if (n
& (1ULL << 63))
637 /* Convert a long long value to a string. This function avoids 64-bit
638 modular arithmetic or divisions. */
640 grub_lltoa (char *str
, int c
, unsigned long long n
)
642 unsigned base
= (c
== 'x') ? 16 : 10;
645 if ((long long) n
< 0 && c
== 'd')
647 n
= (unsigned long long) (-((long long) n
));
656 unsigned d
= (unsigned) (n
& 0xf);
657 *p
++ = (d
> 9) ? d
+ 'a' - 10 : d
+ '0';
666 n
= grub_divmod64 (n
, 10, &m
);
678 grub_vsprintf (char *str
, const char *fmt
, va_list args
)
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
)
696 void write_str (const char *s
)
702 void write_fill (const char ch
, int n
)
705 for (i
= 0; i
< n
; i
++)
709 while ((c
= *fmt
++) != 0)
717 unsigned int format1
= 0;
718 unsigned int format2
= ~ 0U;
725 if (*fmt
&& *fmt
=='-')
732 /* Read formatting parameters. */
733 while (*p
&& grub_isdigit (*p
))
739 grub_strncpy (s
, fmt
, p
- fmt
);
743 format1
= grub_strtoul (s
, 0, 10);
751 while (*p
&& grub_isdigit (*p
))
756 char fstr
[p
- fmt
+ 1];
757 grub_strncpy (fstr
, fmt
, p
- fmt
);
759 format2
= grub_strtoul (fstr
, 0, 10);
781 longlongfmt
|= (sizeof (void *) == sizeof (long long));
790 ll
= va_arg (args
, long long);
791 grub_lltoa (tmp
, c
, ll
);
796 n
= va_arg (args
, long);
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
));
804 if (rightfill
&& grub_strlen (tmp
) < format1
)
805 write_fill (zerofill
, format1
- grub_strlen (tmp
));
809 n
= va_arg (args
, int);
810 write_char (n
& 0xff);
815 grub_uint32_t code
= va_arg (args
, grub_uint32_t
);
824 else if (code
<= 0x7ff)
829 else if (code
<= 0xffff)
834 else if (code
<= 0x1fffff)
839 else if (code
<= 0x3ffffff)
844 else if (code
<= 0x7fffffff)
856 write_char (mask
| (code
>> shift
));
858 for (shift
-= 6; shift
>= 0; shift
-= 6)
859 write_char (0x80 | (0x3f & (code
>> shift
)));
864 p
= va_arg (args
, char *);
868 while (len
< format2
&& p
[len
])
871 if (!rightfill
&& len
< format1
)
872 write_fill (zerofill
, format1
- len
);
875 for (i
= 0; i
< len
; i
++)
878 if (rightfill
&& len
< format1
)
879 write_fill (zerofill
, format1
- len
);
882 write_str ("(null)");
903 grub_sprintf (char *str
, const char *fmt
, ...)
909 ret
= grub_vsprintf (str
, fmt
, ap
);
915 /* Convert UTF-16 to UTF-8. */
917 grub_utf16_to_utf8 (grub_uint8_t
*dest
, grub_uint16_t
*src
,
920 grub_uint32_t code_high
= 0;
924 grub_uint32_t code
= *src
++;
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;
950 else if (code
<= 0x07FF)
952 *dest
++ = (code
>> 6) | 0xC0;
953 *dest
++ = (code
& 0x3F) | 0x80;
955 else if (code
>= 0xD800 && code
<= 0xDBFF)
960 else if (code
>= 0xDC00 && code
<= 0xDFFF)
967 *dest
++ = (code
>> 12) | 0xE0;
968 *dest
++ = ((code
>> 6) & 0x3F) | 0x80;
969 *dest
++ = (code
& 0x3F) | 0x80;
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. */
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
;
990 grub_uint32_t code
= 0;
995 while (srcsize
&& destsize
)
997 grub_uint32_t c
= *src
++;
998 if (srcsize
!= (grub_size_t
)-1)
1002 if ((c
& 0xc0) != 0x80)
1019 if ((c
& 0x80) == 0x00)
1021 else if ((c
& 0xe0) == 0xc0)
1026 else if ((c
& 0xf0) == 0xe0)
1031 else if ((c
& 0xf8) == 0xf0)
1036 else if ((c
& 0xfc) == 0xf8)
1041 else if ((c
& 0xfe) == 0xfc)
1062 /* Abort GRUB. This function does not return. */
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.");
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
)))