misc.c 19 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  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,2010 Free Software Foundation, Inc.
  5. *
  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.
  10. *
  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.
  15. *
  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/>.
  18. */
  19. #include <grub/misc.h>
  20. #include <grub/err.h>
  21. #include <grub/mm.h>
  22. #include <stdarg.h>
  23. #include <grub/term.h>
  24. #include <grub/env.h>
  25. #include <grub/i18n.h>
  26. GRUB_EXPORT(grub_memmove);
  27. GRUB_EXPORT(grub_strcpy);
  28. GRUB_EXPORT(grub_strncpy);
  29. GRUB_EXPORT(grub_stpcpy);
  30. GRUB_EXPORT(grub_memcmp);
  31. GRUB_EXPORT(grub_strcmp);
  32. GRUB_EXPORT(grub_strncmp);
  33. GRUB_EXPORT(grub_strchr);
  34. GRUB_EXPORT(grub_strrchr);
  35. GRUB_EXPORT(grub_strword);
  36. GRUB_EXPORT(grub_strstr);
  37. GRUB_EXPORT(grub_isspace);
  38. GRUB_EXPORT(grub_isprint);
  39. GRUB_EXPORT(grub_strtoul);
  40. GRUB_EXPORT(grub_strtoull);
  41. GRUB_EXPORT(grub_strdup);
  42. GRUB_EXPORT(grub_strndup);
  43. GRUB_EXPORT(grub_memset);
  44. GRUB_EXPORT(grub_strlen);
  45. GRUB_EXPORT(grub_printf);
  46. GRUB_EXPORT(grub_printf_);
  47. GRUB_EXPORT(grub_puts);
  48. GRUB_EXPORT(grub_puts_);
  49. GRUB_EXPORT(grub_real_dprintf);
  50. GRUB_EXPORT(grub_vprintf);
  51. GRUB_EXPORT(grub_snprintf);
  52. GRUB_EXPORT(grub_vsnprintf);
  53. GRUB_EXPORT(grub_xasprintf);
  54. GRUB_EXPORT(grub_xvasprintf);
  55. GRUB_EXPORT(grub_exit);
  56. GRUB_EXPORT(grub_abort);
  57. GRUB_EXPORT(grub_utf8_to_ucs4);
  58. GRUB_EXPORT(grub_divmod64);
  59. GRUB_EXPORT(grub_gettext);
  60. static int
  61. grub_vsnprintf_real (char *str, grub_size_t n, const char *fmt, va_list args);
  62. static int
  63. grub_iswordseparator (int c)
  64. {
  65. return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
  66. }
  67. /* grub_gettext_dummy is not translating anything. */
  68. static const char *
  69. grub_gettext_dummy (const char *s)
  70. {
  71. return s;
  72. }
  73. const char* (*grub_gettext) (const char *s) = grub_gettext_dummy;
  74. void *
  75. grub_memmove (void *dest, const void *src, grub_size_t n)
  76. {
  77. char *d = (char *) dest;
  78. const char *s = (const char *) src;
  79. if (d < s)
  80. while (n--)
  81. *d++ = *s++;
  82. else
  83. {
  84. d += n;
  85. s += n;
  86. while (n--)
  87. *--d = *--s;
  88. }
  89. return dest;
  90. }
  91. char *
  92. grub_strcpy (char *dest, const char *src)
  93. {
  94. char *p = dest;
  95. while ((*p++ = *src++) != '\0')
  96. ;
  97. return dest;
  98. }
  99. char *
  100. grub_strncpy (char *dest, const char *src, int c)
  101. {
  102. char *p = dest;
  103. while ((*p++ = *src++) != '\0' && --c)
  104. ;
  105. return dest;
  106. }
  107. char *
  108. grub_stpcpy (char *dest, const char *src)
  109. {
  110. char *d = dest;
  111. const char *s = src;
  112. do
  113. *d++ = *s;
  114. while (*s++ != '\0');
  115. return d - 1;
  116. }
  117. int
  118. grub_printf (const char *fmt, ...)
  119. {
  120. va_list ap;
  121. int ret;
  122. va_start (ap, fmt);
  123. ret = grub_vprintf (fmt, ap);
  124. va_end (ap);
  125. return ret;
  126. }
  127. int
  128. grub_printf_ (const char *fmt, ...)
  129. {
  130. va_list ap;
  131. int ret;
  132. va_start (ap, fmt);
  133. ret = grub_vprintf (_(fmt), ap);
  134. va_end (ap);
  135. return ret;
  136. }
  137. int
  138. grub_puts (const char *s)
  139. {
  140. while (*s)
  141. {
  142. grub_putchar (*s);
  143. s++;
  144. }
  145. grub_putchar ('\n');
  146. return 1; /* Cannot fail. */
  147. }
  148. int
  149. grub_puts_ (const char *s)
  150. {
  151. return grub_puts (_(s));
  152. }
  153. #if defined (APPLE_CC) && ! defined (GRUB_UTIL)
  154. int
  155. grub_err_printf (const char *fmt, ...)
  156. {
  157. va_list ap;
  158. int ret;
  159. va_start (ap, fmt);
  160. ret = grub_vprintf (fmt, ap);
  161. va_end (ap);
  162. return ret;
  163. }
  164. #endif
  165. #if ! defined (APPLE_CC) && ! defined (GRUB_UTIL)
  166. int grub_err_printf (const char *fmt, ...)
  167. __attribute__ ((alias("grub_printf")));
  168. #endif
  169. void
  170. grub_real_dprintf (const char *file, const int line, const char *condition,
  171. const char *fmt, ...)
  172. {
  173. va_list args;
  174. const char *debug = grub_env_get ("debug");
  175. if (! debug)
  176. return;
  177. if (grub_strword (debug, "all") || grub_strword (debug, condition))
  178. {
  179. grub_printf ("%s:%d: ", file, line);
  180. va_start (args, fmt);
  181. grub_vprintf (fmt, args);
  182. va_end (args);
  183. }
  184. }
  185. int
  186. grub_vprintf (const char *fmt, va_list args)
  187. {
  188. int ret;
  189. ret = grub_vsnprintf_real (0, 0, fmt, args);
  190. return ret;
  191. }
  192. int
  193. grub_memcmp (const void *s1, const void *s2, grub_size_t n)
  194. {
  195. const char *t1 = s1;
  196. const char *t2 = s2;
  197. while (n--)
  198. {
  199. if (*t1 != *t2)
  200. return (int) *t1 - (int) *t2;
  201. t1++;
  202. t2++;
  203. }
  204. return 0;
  205. }
  206. int
  207. grub_strcmp (const char *s1, const char *s2)
  208. {
  209. while (*s1 && *s2)
  210. {
  211. if (*s1 != *s2)
  212. break;
  213. s1++;
  214. s2++;
  215. }
  216. return (int) *s1 - (int) *s2;
  217. }
  218. int
  219. grub_strncmp (const char *s1, const char *s2, grub_size_t n)
  220. {
  221. if (n == 0)
  222. return 0;
  223. while (*s1 && *s2 && --n)
  224. {
  225. if (*s1 != *s2)
  226. break;
  227. s1++;
  228. s2++;
  229. }
  230. return (int) *s1 - (int) *s2;
  231. }
  232. char *
  233. grub_strchr (const char *s, int c)
  234. {
  235. do
  236. {
  237. if (*s == c)
  238. return (char *) s;
  239. }
  240. while (*s++);
  241. return 0;
  242. }
  243. char *
  244. grub_strrchr (const char *s, int c)
  245. {
  246. char *p = NULL;
  247. do
  248. {
  249. if (*s == c)
  250. p = (char *) s;
  251. }
  252. while (*s++);
  253. return p;
  254. }
  255. /* Copied from gnulib.
  256. Written by Bruno Haible <bruno@clisp.org>, 2005. */
  257. char *
  258. grub_strstr (const char *haystack, const char *needle)
  259. {
  260. /* Be careful not to look at the entire extent of haystack or needle
  261. until needed. This is useful because of these two cases:
  262. - haystack may be very long, and a match of needle found early,
  263. - needle may be very long, and not even a short initial segment of
  264. needle may be found in haystack. */
  265. if (*needle != '\0')
  266. {
  267. /* Speed up the following searches of needle by caching its first
  268. character. */
  269. char b = *needle++;
  270. for (;; haystack++)
  271. {
  272. if (*haystack == '\0')
  273. /* No match. */
  274. return NULL;
  275. if (*haystack == b)
  276. /* The first character matches. */
  277. {
  278. const char *rhaystack = haystack + 1;
  279. const char *rneedle = needle;
  280. for (;; rhaystack++, rneedle++)
  281. {
  282. if (*rneedle == '\0')
  283. /* Found a match. */
  284. return (char *) haystack;
  285. if (*rhaystack == '\0')
  286. /* No match. */
  287. return NULL;
  288. if (*rhaystack != *rneedle)
  289. /* Nothing in this round. */
  290. break;
  291. }
  292. }
  293. }
  294. }
  295. else
  296. return (char *) haystack;
  297. }
  298. int
  299. grub_strword (const char *haystack, const char *needle)
  300. {
  301. const char *n_pos = needle;
  302. while (grub_iswordseparator (*haystack))
  303. haystack++;
  304. while (*haystack)
  305. {
  306. /* Crawl both the needle and the haystack word we're on. */
  307. while(*haystack && !grub_iswordseparator (*haystack)
  308. && *haystack == *n_pos)
  309. {
  310. haystack++;
  311. n_pos++;
  312. }
  313. /* If we reached the end of both words at the same time, the word
  314. is found. If not, eat everything in the haystack that isn't the
  315. next word (or the end of string) and "reset" the needle. */
  316. if ( (!*haystack || grub_iswordseparator (*haystack))
  317. && (!*n_pos || grub_iswordseparator (*n_pos)))
  318. return 1;
  319. else
  320. {
  321. n_pos = needle;
  322. while (*haystack && !grub_iswordseparator (*haystack))
  323. haystack++;
  324. while (grub_iswordseparator (*haystack))
  325. haystack++;
  326. }
  327. }
  328. return 0;
  329. }
  330. int
  331. grub_isspace (int c)
  332. {
  333. return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
  334. }
  335. int
  336. grub_isprint (int c)
  337. {
  338. return (c >= ' ' && c <= '~');
  339. }
  340. unsigned long
  341. grub_strtoul (const char *str, char **end, int base)
  342. {
  343. unsigned long long num;
  344. num = grub_strtoull (str, end, base);
  345. if (num > ~0UL)
  346. {
  347. grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
  348. return ~0UL;
  349. }
  350. return (unsigned long) num;
  351. }
  352. unsigned long long
  353. grub_strtoull (const char *str, char **end, int base)
  354. {
  355. unsigned long long num = 0;
  356. int found = 0;
  357. /* Skip white spaces. */
  358. while (*str && grub_isspace (*str))
  359. str++;
  360. /* Guess the base, if not specified. The prefix `0x' means 16, and
  361. the prefix `0' means 8. */
  362. if (str[0] == '0')
  363. {
  364. if (str[1] == 'x')
  365. {
  366. if (base == 0 || base == 16)
  367. {
  368. base = 16;
  369. str += 2;
  370. }
  371. }
  372. else if (base == 0 && str[1] >= '0' && str[1] <= '7')
  373. base = 8;
  374. }
  375. if (base == 0)
  376. base = 10;
  377. while (*str)
  378. {
  379. unsigned long digit;
  380. digit = grub_tolower (*str) - '0';
  381. if (digit > 9)
  382. {
  383. digit += '0' - 'a' + 10;
  384. if (digit >= (unsigned long) base)
  385. break;
  386. }
  387. found = 1;
  388. /* NUM * BASE + DIGIT > ~0ULL */
  389. if (num > grub_divmod64 (~0ULL - digit, base, 0))
  390. {
  391. grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected");
  392. return ~0ULL;
  393. }
  394. num = num * base + digit;
  395. str++;
  396. }
  397. if (! found)
  398. {
  399. grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number");
  400. return 0;
  401. }
  402. if (end)
  403. *end = (char *) str;
  404. return num;
  405. }
  406. char *
  407. grub_strdup (const char *s)
  408. {
  409. grub_size_t len;
  410. char *p;
  411. len = grub_strlen (s) + 1;
  412. p = (char *) grub_malloc (len);
  413. if (! p)
  414. return 0;
  415. return grub_memcpy (p, s, len);
  416. }
  417. char *
  418. grub_strndup (const char *s, grub_size_t n)
  419. {
  420. grub_size_t len;
  421. char *p;
  422. len = grub_strlen (s);
  423. if (len > n)
  424. len = n;
  425. p = (char *) grub_malloc (len + 1);
  426. if (! p)
  427. return 0;
  428. grub_memcpy (p, s, len);
  429. p[len] = '\0';
  430. return p;
  431. }
  432. void *
  433. grub_memset (void *s, int c, grub_size_t n)
  434. {
  435. unsigned char *p = (unsigned char *) s;
  436. while (n--)
  437. *p++ = (unsigned char) c;
  438. return s;
  439. }
  440. grub_size_t
  441. grub_strlen (const char *s)
  442. {
  443. const char *p = s;
  444. while (*p)
  445. p++;
  446. return p - s;
  447. }
  448. static inline void
  449. grub_reverse (char *str)
  450. {
  451. char *p = str + grub_strlen (str) - 1;
  452. while (str < p)
  453. {
  454. char tmp;
  455. tmp = *str;
  456. *str = *p;
  457. *p = tmp;
  458. str++;
  459. p--;
  460. }
  461. }
  462. /* Divide N by D, return the quotient, and store the remainder in *R. */
  463. grub_uint64_t
  464. grub_divmod64 (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r)
  465. {
  466. /* This algorithm is typically implemented by hardware. The idea
  467. is to get the highest bit in N, 64 times, by keeping
  468. upper(N * 2^i) = upper((Q * 10 + M) * 2^i), where upper
  469. represents the high 64 bits in 128-bits space. */
  470. unsigned bits = 64;
  471. unsigned long long q = 0;
  472. unsigned m = 0;
  473. /* Skip the slow computation if 32-bit arithmetic is possible. */
  474. if (n < 0xffffffff)
  475. {
  476. if (r)
  477. *r = ((grub_uint32_t) n) % d;
  478. return ((grub_uint32_t) n) / d;
  479. }
  480. while (bits--)
  481. {
  482. m <<= 1;
  483. if (n & (1ULL << 63))
  484. m |= 1;
  485. q <<= 1;
  486. n <<= 1;
  487. if (m >= d)
  488. {
  489. q |= 1;
  490. m -= d;
  491. }
  492. }
  493. if (r)
  494. *r = m;
  495. return q;
  496. }
  497. /* Convert a long long value to a string. This function avoids 64-bit
  498. modular arithmetic or divisions. */
  499. static char *
  500. grub_lltoa (char *str, int c, unsigned long long n)
  501. {
  502. unsigned base = (c == 'x') ? 16 : 10;
  503. char *p;
  504. if ((long long) n < 0 && c == 'd')
  505. {
  506. n = (unsigned long long) (-((long long) n));
  507. *str++ = '-';
  508. }
  509. p = str;
  510. if (base == 16)
  511. do
  512. {
  513. unsigned d = (unsigned) (n & 0xf);
  514. *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
  515. }
  516. while (n >>= 4);
  517. else
  518. /* BASE == 10 */
  519. do
  520. {
  521. unsigned m;
  522. n = grub_divmod64 (n, 10, &m);
  523. *p++ = m + '0';
  524. }
  525. while (n);
  526. *p = 0;
  527. grub_reverse (str);
  528. return p;
  529. }
  530. struct vsnprintf_closure
  531. {
  532. char *str;
  533. grub_size_t count;
  534. grub_size_t max_len;
  535. };
  536. static void
  537. write_char (unsigned char ch, struct vsnprintf_closure *cc)
  538. {
  539. if (cc->str)
  540. {
  541. if (cc->count < cc->max_len)
  542. *(cc->str)++ = ch;
  543. }
  544. else
  545. grub_putchar (ch);
  546. (cc->count)++;
  547. }
  548. static void
  549. write_str (const char *s, struct vsnprintf_closure *cc)
  550. {
  551. while (*s)
  552. write_char (*s++, cc);
  553. }
  554. static void
  555. write_fill (const char ch, int n, struct vsnprintf_closure *cc)
  556. {
  557. int i;
  558. for (i = 0; i < n; i++)
  559. write_char (ch, cc);
  560. }
  561. static int
  562. grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt, va_list args)
  563. {
  564. char c;
  565. struct vsnprintf_closure cc;
  566. cc.str = str;
  567. cc.max_len = max_len;
  568. cc.count = 0;
  569. while ((c = *fmt++) != 0)
  570. {
  571. if (c != '%')
  572. write_char (c, &cc);
  573. else
  574. {
  575. char tmp[32];
  576. char *p;
  577. unsigned int format1 = 0;
  578. unsigned int format2 = ~ 0U;
  579. char zerofill = ' ';
  580. int rightfill = 0;
  581. int n;
  582. int longfmt = 0;
  583. int longlongfmt = 0;
  584. int unsig = 0;
  585. if (*fmt && *fmt =='-')
  586. {
  587. rightfill = 1;
  588. fmt++;
  589. }
  590. p = (char *) fmt;
  591. /* Read formatting parameters. */
  592. while (*p && grub_isdigit (*p))
  593. p++;
  594. if (p > fmt)
  595. {
  596. char s[p - fmt + 1];
  597. grub_strncpy (s, fmt, p - fmt);
  598. s[p - fmt] = 0;
  599. if (s[0] == '0')
  600. zerofill = '0';
  601. format1 = grub_strtoul (s, 0, 10);
  602. fmt = p;
  603. }
  604. if (*p && *p == '.')
  605. {
  606. p++;
  607. fmt++;
  608. while (*p && grub_isdigit (*p))
  609. p++;
  610. if (p > fmt)
  611. {
  612. char fstr[p - fmt + 1];
  613. grub_strncpy (fstr, fmt, p - fmt);
  614. fstr[p - fmt] = 0;
  615. format2 = grub_strtoul (fstr, 0, 10);
  616. fmt = p;
  617. }
  618. }
  619. c = *fmt++;
  620. if (c == 'l')
  621. {
  622. longfmt = 1;
  623. c = *fmt++;
  624. if (c == 'l')
  625. {
  626. longlongfmt = 1;
  627. c = *fmt++;
  628. }
  629. }
  630. switch (c)
  631. {
  632. case 'p':
  633. write_str ("0x", &cc);
  634. c = 'x';
  635. longlongfmt |= (sizeof (void *) == sizeof (long long));
  636. /* Fall through. */
  637. case 'x':
  638. case 'u':
  639. unsig = 1;
  640. /* Fall through. */
  641. case 'd':
  642. if (longlongfmt)
  643. {
  644. long long ll;
  645. ll = va_arg (args, long long);
  646. grub_lltoa (tmp, c, ll);
  647. }
  648. else if (longfmt && unsig)
  649. {
  650. unsigned long l = va_arg (args, unsigned long);
  651. grub_lltoa (tmp, c, l);
  652. }
  653. else if (longfmt)
  654. {
  655. long l = va_arg (args, long);
  656. grub_lltoa (tmp, c, l);
  657. }
  658. else if (unsig)
  659. {
  660. unsigned u = va_arg (args, unsigned);
  661. grub_lltoa (tmp, c, u);
  662. }
  663. else
  664. {
  665. n = va_arg (args, int);
  666. grub_lltoa (tmp, c, n);
  667. }
  668. if (! rightfill && grub_strlen (tmp) < format1)
  669. write_fill (zerofill, format1 - grub_strlen (tmp), &cc);
  670. write_str (tmp, &cc);
  671. if (rightfill && grub_strlen (tmp) < format1)
  672. write_fill (zerofill, format1 - grub_strlen (tmp), &cc);
  673. break;
  674. case 'c':
  675. n = va_arg (args, int);
  676. write_char (n & 0xff, &cc);
  677. break;
  678. case 'C':
  679. {
  680. grub_uint32_t code = va_arg (args, grub_uint32_t);
  681. int shift;
  682. unsigned mask;
  683. if (code <= 0x7f)
  684. {
  685. shift = 0;
  686. mask = 0;
  687. }
  688. else if (code <= 0x7ff)
  689. {
  690. shift = 6;
  691. mask = 0xc0;
  692. }
  693. else if (code <= 0xffff)
  694. {
  695. shift = 12;
  696. mask = 0xe0;
  697. }
  698. else if (code <= 0x1fffff)
  699. {
  700. shift = 18;
  701. mask = 0xf0;
  702. }
  703. else if (code <= 0x3ffffff)
  704. {
  705. shift = 24;
  706. mask = 0xf8;
  707. }
  708. else if (code <= 0x7fffffff)
  709. {
  710. shift = 30;
  711. mask = 0xfc;
  712. }
  713. else
  714. {
  715. code = '?';
  716. shift = 0;
  717. mask = 0;
  718. }
  719. write_char (mask | (code >> shift), &cc);
  720. for (shift -= 6; shift >= 0; shift -= 6)
  721. write_char (0x80 | (0x3f & (code >> shift)), &cc);
  722. }
  723. break;
  724. case 's':
  725. p = va_arg (args, char *);
  726. if (p)
  727. {
  728. grub_size_t len = 0;
  729. while (len < format2 && p[len])
  730. len++;
  731. if (!rightfill && len < format1)
  732. write_fill (zerofill, format1 - len, &cc);
  733. grub_size_t i;
  734. for (i = 0; i < len; i++)
  735. write_char (*p++, &cc);
  736. if (rightfill && len < format1)
  737. write_fill (zerofill, format1 - len, &cc);
  738. }
  739. else
  740. write_str ("(null)", &cc);
  741. break;
  742. default:
  743. write_char (c, &cc);
  744. break;
  745. }
  746. }
  747. }
  748. if (cc.str)
  749. *(cc.str) = '\0';
  750. return cc.count;
  751. }
  752. int
  753. grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list ap)
  754. {
  755. grub_size_t ret;
  756. if (!n)
  757. return 0;
  758. n--;
  759. ret = grub_vsnprintf_real (str, n, fmt, ap);
  760. return ret < n ? ret : n;
  761. }
  762. int
  763. grub_snprintf (char *str, grub_size_t n, const char *fmt, ...)
  764. {
  765. va_list ap;
  766. int ret;
  767. va_start (ap, fmt);
  768. ret = grub_vsnprintf (str, n, fmt, ap);
  769. va_end (ap);
  770. return ret;
  771. }
  772. #define PREALLOC_SIZE 255
  773. char *
  774. grub_xvasprintf (const char *fmt, va_list ap)
  775. {
  776. grub_size_t s, as = PREALLOC_SIZE;
  777. char *ret;
  778. while (1)
  779. {
  780. ret = grub_malloc (as + 1);
  781. if (!ret)
  782. return NULL;
  783. s = grub_vsnprintf_real (ret, as, fmt, ap);
  784. if (s <= as)
  785. return ret;
  786. grub_free (ret);
  787. as = s;
  788. }
  789. }
  790. char *
  791. grub_xasprintf (const char *fmt, ...)
  792. {
  793. va_list ap;
  794. char *ret;
  795. va_start (ap, fmt);
  796. ret = grub_xvasprintf (fmt, ap);
  797. va_end (ap);
  798. return ret;
  799. }
  800. /* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
  801. bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string.
  802. Return the number of characters converted. DEST must be able to hold
  803. at least DESTSIZE characters.
  804. If SRCEND is not NULL, then *SRCEND is set to the next byte after the
  805. last byte used in SRC. */
  806. grub_size_t
  807. grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
  808. const grub_uint8_t *src, grub_size_t srcsize,
  809. const grub_uint8_t **srcend)
  810. {
  811. grub_uint32_t *p = dest;
  812. int count = 0;
  813. grub_uint32_t code = 0;
  814. if (srcend)
  815. *srcend = src;
  816. while (srcsize && destsize)
  817. {
  818. grub_uint32_t c = *src++;
  819. if (srcsize != (grub_size_t)-1)
  820. srcsize--;
  821. if (count)
  822. {
  823. if ((c & 0xc0) != 0x80)
  824. {
  825. /* invalid */
  826. code = '?';
  827. /* Character c may be valid, don't eat it. */
  828. src--;
  829. if (srcsize != (grub_size_t)-1)
  830. srcsize++;
  831. count = 0;
  832. }
  833. else
  834. {
  835. code <<= 6;
  836. code |= (c & 0x3f);
  837. count--;
  838. }
  839. }
  840. else
  841. {
  842. if (c == 0)
  843. break;
  844. if ((c & 0x80) == 0x00)
  845. code = c;
  846. else if ((c & 0xe0) == 0xc0)
  847. {
  848. count = 1;
  849. code = c & 0x1f;
  850. }
  851. else if ((c & 0xf0) == 0xe0)
  852. {
  853. count = 2;
  854. code = c & 0x0f;
  855. }
  856. else if ((c & 0xf8) == 0xf0)
  857. {
  858. count = 3;
  859. code = c & 0x07;
  860. }
  861. else if ((c & 0xfc) == 0xf8)
  862. {
  863. count = 4;
  864. code = c & 0x03;
  865. }
  866. else if ((c & 0xfe) == 0xfc)
  867. {
  868. count = 5;
  869. code = c & 0x01;
  870. }
  871. else
  872. {
  873. /* invalid */
  874. code = '?';
  875. count = 0;
  876. }
  877. }
  878. if (count == 0)
  879. {
  880. *p++ = code;
  881. destsize--;
  882. }
  883. }
  884. if (srcend)
  885. *srcend = src;
  886. return p - dest;
  887. }
  888. /* Abort GRUB. This function does not return. */
  889. void
  890. grub_abort (void)
  891. {
  892. grub_printf ("\nAborted.");
  893. #ifndef GRUB_UTIL
  894. if (grub_term_inputs)
  895. #endif
  896. {
  897. grub_printf (" Press any key to exit.");
  898. grub_getkey ();
  899. }
  900. grub_exit ();
  901. }
  902. #ifndef APPLE_CC
  903. /* GCC emits references to abort(). */
  904. void abort (void) __attribute__ ((alias ("grub_abort")));
  905. #endif
  906. #if defined(NEED_ENABLE_EXECUTE_STACK) && !defined(GRUB_UTIL)
  907. /* Some gcc versions generate a call to this function
  908. in trampolines for nested functions. */
  909. void __enable_execute_stack (void *addr __attribute__ ((unused)))
  910. {
  911. }
  912. #endif
  913. #if defined (NEED_REGISTER_FRAME_INFO) && !defined(GRUB_UTIL)
  914. void __register_frame_info (void)
  915. {
  916. }
  917. void __deregister_frame_info (void)
  918. {
  919. }
  920. #endif