1 /* misc.c - definitions of misc functions */
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>
24 #include <grub/term.h>
26 #include <grub/time.h>
29 grub_memmove (void *dest
, const void *src
, grub_size_t n
)
31 char *d
= (char *) dest
;
32 const char *s
= (const char *) src
;
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")));
55 grub_strcpy (char *dest
, const char *src
)
59 while ((*p
++ = *src
++) != '\0')
66 grub_strncpy (char *dest
, const char *src
, int c
)
70 while ((*p
++ = *src
++) != '\0' && --c
)
77 grub_stpcpy (char *dest
, const char *src
)
90 grub_strcat (char *dest
, const char *src
)
97 while ((*p
++ = *src
++) != '\0')
104 grub_strncat (char *dest
, const char *src
, int c
)
111 while ((*p
++ = *src
++) != '\0' && --c
)
119 grub_printf (const char *fmt
, ...)
125 ret
= grub_vprintf (fmt
, ap
);
132 grub_real_dprintf (const char *file
, const int line
, const char *condition
,
133 const char *fmt
, ...)
136 const char *debug
= grub_env_get ("debug");
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
);
151 grub_vprintf (const char *fmt
, va_list args
)
155 ret
= grub_vsprintf (0, fmt
, args
);
161 grub_memcmp (const void *s1
, const void *s2
, grub_size_t n
)
169 return (int) *t1
- (int) *t2
;
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
)
186 return (int) *s1
- (int) *s2
;
192 return (int) *s1
- (int) *s2
;
196 grub_strncmp (const char *s1
, const char *s2
, grub_size_t n
)
201 while (*s1
&& *s2
&& --n
)
204 return (int) *s1
- (int) *s2
;
210 return (int) *s1
- (int) *s2
;
214 grub_strncasecmp (const char *s1
, const char *s2
, int c
)
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
);
228 return (int) *s1
- (int) *s2
;
232 grub_strchr (const char *s
, int c
)
245 grub_strrchr (const char *s
, int c
)
259 /* Copied from gnulib.
260 Written by Bruno Haible <bruno@clisp.org>, 2005. */
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. */
271 /* Speed up the following searches of needle by caching its first
277 if (*haystack
== '\0')
281 /* The first character matches. */
283 const char *rhaystack
= haystack
+ 1;
284 const char *rneedle
= needle
;
286 for (;; rhaystack
++, rneedle
++)
288 if (*rneedle
== '\0')
290 return (char *) haystack
;
291 if (*rhaystack
== '\0')
294 if (*rhaystack
!= *rneedle
)
295 /* Nothing in this round. */
302 return (char *) haystack
;
306 grub_strword (const char *haystack
, const char *needle
)
308 const char *n_pos
= needle
;
310 while (grub_iswordseparator (*haystack
))
315 /* Crawl both the needle and the haystack word we're on. */
316 while(*haystack
&& !grub_iswordseparator (*haystack
)
317 && *haystack
== *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
)))
332 while (*haystack
&& !grub_iswordseparator (*haystack
))
334 while (grub_iswordseparator (*haystack
))
343 grub_iswordseparator (int c
)
345 return (grub_isspace (c
) || c
== ',' || c
== ';' || c
== '|' || c
== '&');
351 return (c
== '\n' || c
== '\r' || c
== ' ' || c
== '\t');
357 return (c
>= ' ' && c
<= '~');
363 return (c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z');
369 return (c
>= '0' && c
<= '9');
375 return (c
>= '!' && c
<= '~');
381 if (c
>= 'A' && c
<= 'Z')
382 return c
- 'A' + 'a';
389 grub_strtoul (const char *str
, char **end
, int base
)
391 unsigned long long num
;
393 num
= grub_strtoull (str
, end
, base
);
396 grub_error (GRUB_ERR_OUT_OF_RANGE
, "overflow is detected");
400 return (unsigned long) num
;
404 grub_strtoull (const char *str
, char **end
, int base
)
406 unsigned long long num
= 0;
409 /* Skip white spaces. */
410 while (*str
&& grub_isspace (*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')
419 if (base
== 0 || base
== 16)
425 else if (str
[1] >= '0' && str
[1] <= '7')
436 digit
= grub_tolower (*str
) - '0';
439 digit
+= '0' - 'a' + 10;
440 if (digit
>= (unsigned long) base
)
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");
453 num
= num
* base
+ digit
;
459 grub_error (GRUB_ERR_BAD_NUMBER
, "unrecognized number");
470 grub_strdup (const char *s
)
475 len
= grub_strlen (s
) + 1;
476 p
= (char *) grub_malloc (len
);
480 return grub_memcpy (p
, s
, len
);
484 grub_strndup (const char *s
, grub_size_t n
)
489 len
= grub_strlen (s
);
492 p
= (char *) grub_malloc (len
+ 1);
496 grub_memcpy (p
, s
, len
);
502 grub_memset (void *s
, int c
, grub_size_t n
)
504 unsigned char *p
= (unsigned char *) s
;
507 *p
++ = (unsigned char) c
;
511 void *memset (void *s
, int c
, grub_size_t n
)
512 __attribute__ ((alias ("grub_memset")));
515 grub_strlen (const char *s
)
526 grub_reverse (char *str
)
528 char *p
= str
+ grub_strlen (str
) - 1;
543 grub_itoa (char *str
, int c
, unsigned n
)
545 unsigned base
= (c
== 'x') ? 16 : 10;
548 if ((int) n
< 0 && c
== 'd')
550 n
= (unsigned) (-((int) n
));
557 unsigned d
= n
% base
;
558 *p
++ = (d
> 9) ? d
+ 'a' - 10 : d
+ '0';
567 /* Divide N by D, return the quotient, and store the remainder in *R. */
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. */
576 unsigned long long q
= 0;
579 /* Skip the slow computation if 32-bit arithmetic is possible. */
583 *r
= ((grub_uint32_t
) n
) % d
;
585 return ((grub_uint32_t
) n
) / d
;
592 if (n
& (1ULL << 63))
611 /* Convert a long long value to a string. This function avoids 64-bit
612 modular arithmetic or divisions. */
614 grub_lltoa (char *str
, int c
, unsigned long long n
)
616 unsigned base
= (c
== 'x') ? 16 : 10;
619 if ((long long) n
< 0 && c
== 'd')
621 n
= (unsigned long long) (-((long long) n
));
630 unsigned d
= (unsigned) (n
& 0xf);
631 *p
++ = (d
> 9) ? d
+ 'a' - 10 : d
+ '0';
640 n
= grub_divmod64 (n
, 10, &m
);
652 grub_ftoa (char *str
, double f
, int round
)
656 unsigned int power
= 1;
659 for (i
= 0; i
< round
; i
++)
663 fractp
= (f
- (float) intp
) * power
;
665 grub_sprintf (str
, "%d.%d", intp
, fractp
);
670 grub_vsprintf (char *str
, const char *fmt
, va_list args
)
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
)
688 void write_str (const char *s
)
694 void write_fill (const char ch
, int n
)
697 for (i
= 0; i
< n
; i
++)
701 while ((c
= *fmt
++) != 0)
709 unsigned int format1
= 0;
710 unsigned int format2
= 3;
717 if (*fmt
&& *fmt
=='-')
724 /* Read formatting parameters. */
725 while (*p
&& grub_isdigit (*p
))
731 grub_strncpy (s
, fmt
, p
- fmt
);
735 format1
= grub_strtoul (s
, 0, 10);
741 while (*p
&& grub_isdigit (*p
))
747 grub_strncpy (fstr
, fmt
, p
- fmt
);
748 format2
= grub_strtoul (fstr
, 0, 10);
771 longlongfmt
|= (sizeof (void *) == sizeof (long long));
780 ll
= va_arg (args
, long long);
781 grub_lltoa (tmp
, c
, ll
);
786 n
= va_arg (args
, long);
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
));
794 if (rightfill
&& grub_strlen (tmp
) < format1
)
795 write_fill (zerofill
, format1
- grub_strlen (tmp
));
799 n
= va_arg (args
, int);
800 write_char (n
& 0xff);
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
));
811 if (rightfill
&& grub_strlen (tmp
) < format1
)
812 write_fill (zerofill
, format1
- grub_strlen (tmp
));
818 grub_uint32_t code
= va_arg (args
, grub_uint32_t
);
827 else if (code
<= 0x7ff)
832 else if (code
<= 0xffff)
837 else if (code
<= 0x1fffff)
842 else if (code
<= 0x3ffffff)
847 else if (code
<= 0x7fffffff)
859 write_char (mask
| (code
>> shift
));
861 for (shift
-= 6; shift
>= 0; shift
-= 6)
862 write_char (0x80 | (0x3f & (code
>> shift
)));
867 p
= va_arg (args
, char *);
870 if (!rightfill
&& grub_strlen (p
) < format1
)
871 write_fill (zerofill
, format1
- grub_strlen (p
));
875 if (rightfill
&& grub_strlen (p
) < format1
)
876 write_fill (zerofill
, format1
- grub_strlen (p
));
879 write_str ("(null)");
900 grub_sprintf (char *str
, const char *fmt
, ...)
906 ret
= grub_vsprintf (str
, fmt
, ap
);
912 /* Convert UTF-16 to UTF-8. */
914 grub_utf16_to_utf8 (grub_uint8_t
*dest
, grub_uint16_t
*src
,
917 grub_uint32_t code_high
= 0;
921 grub_uint32_t code
= *src
++;
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;
947 else if (code
<= 0x07FF)
949 *dest
++ = (code
>> 6) | 0xC0;
950 *dest
++ = (code
& 0x3F) | 0x80;
952 else if (code
>= 0xD800 && code
<= 0xDBFF)
957 else if (code
>= 0xDC00 && code
<= 0xDFFF)
964 *dest
++ = (code
>> 12) | 0xE0;
965 *dest
++ = ((code
>> 6) & 0x3F) | 0x80;
966 *dest
++ = (code
& 0x3F) | 0x80;
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,
979 grub_utf8_to_ucs4 (grub_uint32_t
*dest
, const grub_uint8_t
*src
,
982 grub_uint32_t
*p
= dest
;
984 grub_uint32_t code
= 0;
988 grub_uint32_t c
= *src
++;
992 if ((c
& 0xc0) != 0x80)
1006 if ((c
& 0x80) == 0x00)
1008 else if ((c
& 0xe0) == 0xc0)
1013 else if ((c
& 0xf0) == 0xe0)
1018 else if ((c
& 0xf8) == 0xf0)
1023 else if ((c
& 0xfc) == 0xf8)
1028 else if ((c
& 0xfe) == 0xfc)
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
)
1056 /* Abort GRUB. This function does not return. */
1060 if (grub_term_get_current ())
1062 grub_printf ("\nAborted. Press any key to exit.");
1068 /* GCC emits references to abort(). */
1069 void abort (void) __attribute__ ((alias ("grub_abort")));