~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to grub-core/kern/misc.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

Show diffs side-by-side

added added

removed removed

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