~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to term/tparm.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  GRUB  --  GRand Unified Bootloader
3
 
 *  Copyright (C) 1998-2003,2004,2005 Free Software Foundation, Inc.
4
 
 *
5
 
 *  GRUB is free software: you can redistribute it and/or modify
6
 
 *  it under the terms of the GNU General Public License as published by
7
 
 *  the Free Software Foundation, either version 3 of the License, or
8
 
 *  (at your option) any later version.
9
 
 *
10
 
 *  GRUB is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17
 
 */
18
 
 
19
 
/**********************************************************************
20
 
 * This code is a modification of lib_tparm.c found in ncurses-5.2. The
21
 
 * modification are for use in grub by replacing all libc function through
22
 
 * special grub functions. This also meant to delete all dynamic memory
23
 
 * allocation and replace it by a number of fixed buffers.
24
 
 *
25
 
 * Modifications by Tilmann Bubeck <t.bubeck@reinform.de> 2002
26
 
 *
27
 
 * Resync with ncurses-5.4 by Omniflux <omniflux+devel@omniflux.com> 2005
28
 
 **********************************************************************/
29
 
 
30
 
/****************************************************************************
31
 
 *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
32
 
 *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
33
 
 *     and: Thomas E. Dickey, 1996 on                                       *
34
 
 ****************************************************************************/
35
 
 
36
 
/*
37
 
 *      tparm.c
38
 
 *
39
 
 */
40
 
 
41
 
#include <grub/misc.h>
42
 
#include <grub/mm.h>
43
 
#include <grub/types.h>
44
 
#include <grub/tparm.h>
45
 
 
46
 
/*
47
 
 * Common/troublesome character definitions
48
 
 */
49
 
typedef char grub_bool_t;
50
 
#ifndef FALSE
51
 
# define FALSE (0)
52
 
#endif
53
 
#ifndef TRUE
54
 
# define TRUE (!FALSE)
55
 
#endif
56
 
 
57
 
#define NUM_PARM 9
58
 
#define NUM_VARS 26
59
 
#define STACKSIZE 20
60
 
#define MAX_FORMAT_LEN 256
61
 
 
62
 
#define max(a,b) ((a) > (b) ? (a) : (b))
63
 
#define isdigit(c) ((c) >= '0' && (c) <= '9')
64
 
#define isUPPER(c) ((c) >= 'A' && (c) <= 'Z')
65
 
#define isLOWER(c) ((c) >= 'a' && (c) <= 'z')
66
 
 
67
 
#define UChar(c) ((unsigned char)(c))
68
 
 
69
 
//MODULE_ID("$Id$")
70
 
 
71
 
/*
72
 
 *      char *
73
 
 *      tparm(string, ...)
74
 
 *
75
 
 *      Substitute the given parameters into the given string by the following
76
 
 *      rules (taken from terminfo(5)):
77
 
 *
78
 
 *           Cursor addressing and other strings  requiring  parame-
79
 
 *      ters in the terminal are described by a parameterized string
80
 
 *      capability, with like escapes %x in  it.   For  example,  to
81
 
 *      address  the  cursor, the cup capability is given, using two
82
 
 *      parameters: the row and column to  address  to.   (Rows  and
83
 
 *      columns  are  numbered  from  zero and refer to the physical
84
 
 *      screen visible to the user, not to any  unseen  memory.)  If
85
 
 *      the terminal has memory relative cursor addressing, that can
86
 
 *      be indicated by
87
 
 *
88
 
 *           The parameter mechanism uses  a  stack  and  special  %
89
 
 *      codes  to manipulate it.  Typically a sequence will push one
90
 
 *      of the parameters onto the stack and then print it  in  some
91
 
 *      format.  Often more complex operations are necessary.
92
 
 *
93
 
 *           The % encodings have the following meanings:
94
 
 *
95
 
 *           %%        outputs `%'
96
 
 *           %c        print pop() like %c in printf()
97
 
 *           %s        print pop() like %s in printf()
98
 
 *           %[[:]flags][width[.precision]][doxXs]
99
 
 *                     as in printf, flags are [-+#] and space
100
 
 *                     The ':' is used to avoid making %+ or %-
101
 
 *                     patterns (see below).
102
 
 *
103
 
 *           %p[1-9]   push ith parm
104
 
 *           %P[a-z]   set dynamic variable [a-z] to pop()
105
 
 *           %g[a-z]   get dynamic variable [a-z] and push it
106
 
 *           %P[A-Z]   set static variable [A-Z] to pop()
107
 
 *           %g[A-Z]   get static variable [A-Z] and push it
108
 
 *           %l        push strlen(pop)
109
 
 *           %'c'      push char constant c
110
 
 *           %{nn}     push integer constant nn
111
 
 *
112
 
 *           %+ %- %* %/ %m
113
 
 *                     arithmetic (%m is mod): push(pop() op pop())
114
 
 *           %& %| %^  bit operations: push(pop() op pop())
115
 
 *           %= %> %<  logical operations: push(pop() op pop())
116
 
 *           %A %O     logical and & or operations for conditionals
117
 
 *           %! %~     unary operations push(op pop())
118
 
 *           %i        add 1 to first two parms (for ANSI terminals)
119
 
 *
120
 
 *           %? expr %t thenpart %e elsepart %;
121
 
 *                     if-then-else, %e elsepart is optional.
122
 
 *                     else-if's are possible ala Algol 68:
123
 
 *                     %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %;
124
 
 *
125
 
 *      For those of the above operators which are binary and not commutative,
126
 
 *      the stack works in the usual way, with
127
 
 *                      %gx %gy %m
128
 
 *      resulting in x mod y, not the reverse.
129
 
 */
130
 
 
131
 
typedef struct {
132
 
    union {
133
 
        int num;
134
 
        char *str;
135
 
    } data;
136
 
    grub_bool_t num_type;
137
 
} stack_frame;
138
 
 
139
 
static stack_frame stack[STACKSIZE];
140
 
static int stack_ptr;
141
 
static const char *tparam_base = "";
142
 
 
143
 
static char *out_buff;
144
 
static grub_size_t out_size;
145
 
static grub_size_t out_used;
146
 
 
147
 
static char *fmt_buff;
148
 
static grub_size_t fmt_size;
149
 
 
150
 
static inline void
151
 
get_space(grub_size_t need)
152
 
{
153
 
    need += out_used;
154
 
    if (need > out_size) {
155
 
        out_size = need * 2;
156
 
        out_buff = grub_realloc(out_buff, out_size*sizeof(char));
157
 
        /* FIX ME! handle out_buff == 0.  */
158
 
    }
159
 
}
160
 
 
161
 
static inline void
162
 
save_text(const char *fmt, const char *s, int len)
163
 
{
164
 
    grub_size_t s_len = grub_strlen(s);
165
 
    if (len > (int) s_len)
166
 
        s_len = len;
167
 
 
168
 
    get_space(s_len + 1);
169
 
 
170
 
    (void) grub_snprintf(out_buff + out_used, s_len + 1, fmt, s);
171
 
    out_used += grub_strlen(out_buff + out_used);
172
 
}
173
 
 
174
 
static inline void
175
 
save_number(const char *fmt, int number, int len)
176
 
{
177
 
    if (len < 30)
178
 
        len = 30;               /* actually log10(MAX_INT)+1 */
179
 
 
180
 
    get_space((unsigned) len + 1);
181
 
 
182
 
    (void) grub_snprintf(out_buff + out_used, len + 1, fmt, number);
183
 
    out_used += grub_strlen(out_buff + out_used);
184
 
}
185
 
 
186
 
static inline void
187
 
save_char(int c)
188
 
{
189
 
    if (c == 0)
190
 
        c = 0200;
191
 
    get_space(1);
192
 
    out_buff[out_used++] = c;
193
 
}
194
 
 
195
 
static inline void
196
 
npush(int x)
197
 
{
198
 
    if (stack_ptr < STACKSIZE) {
199
 
        stack[stack_ptr].num_type = TRUE;
200
 
        stack[stack_ptr].data.num = x;
201
 
        stack_ptr++;
202
 
    }
203
 
}
204
 
 
205
 
static inline int
206
 
npop(void)
207
 
{
208
 
    int result = 0;
209
 
    if (stack_ptr > 0) {
210
 
        stack_ptr--;
211
 
        if (stack[stack_ptr].num_type)
212
 
            result = stack[stack_ptr].data.num;
213
 
    }
214
 
    return result;
215
 
}
216
 
 
217
 
static inline void
218
 
spush(char *x)
219
 
{
220
 
    if (stack_ptr < STACKSIZE) {
221
 
        stack[stack_ptr].num_type = FALSE;
222
 
        stack[stack_ptr].data.str = x;
223
 
        stack_ptr++;
224
 
    }
225
 
}
226
 
 
227
 
static inline char *
228
 
spop(void)
229
 
{
230
 
    static char dummy[] = "";   /* avoid const-cast */
231
 
    char *result = dummy;
232
 
    if (stack_ptr > 0) {
233
 
        stack_ptr--;
234
 
        if (!stack[stack_ptr].num_type && stack[stack_ptr].data.str != 0)
235
 
            result = stack[stack_ptr].data.str;
236
 
    }
237
 
    return result;
238
 
}
239
 
 
240
 
static inline const char *
241
 
parse_format(const char *s, char *format, int *len)
242
 
{
243
 
    *len = 0;
244
 
    if (format != 0) {
245
 
        grub_bool_t done = FALSE;
246
 
        grub_bool_t allowminus = FALSE;
247
 
        grub_bool_t dot = FALSE;
248
 
        grub_bool_t err = FALSE;
249
 
        char *fmt = format;
250
 
        int my_width = 0;
251
 
        int my_prec = 0;
252
 
        int value = 0;
253
 
 
254
 
        *len = 0;
255
 
        *format++ = '%';
256
 
        while (*s != '\0' && !done) {
257
 
            switch (*s) {
258
 
            case 'c':           /* FALLTHRU */
259
 
            case 'd':           /* FALLTHRU */
260
 
            case 'o':           /* FALLTHRU */
261
 
            case 'x':           /* FALLTHRU */
262
 
            case 'X':           /* FALLTHRU */
263
 
            case 's':
264
 
                *format++ = *s;
265
 
                done = TRUE;
266
 
                break;
267
 
            case '.':
268
 
                *format++ = *s++;
269
 
                if (dot) {
270
 
                    err = TRUE;
271
 
                } else {        /* value before '.' is the width */
272
 
                    dot = TRUE;
273
 
                    my_width = value;
274
 
                }
275
 
                value = 0;
276
 
                break;
277
 
            case '#':
278
 
                *format++ = *s++;
279
 
                break;
280
 
            case ' ':
281
 
                *format++ = *s++;
282
 
                break;
283
 
            case ':':
284
 
                s++;
285
 
                allowminus = TRUE;
286
 
                break;
287
 
            case '-':
288
 
                if (allowminus) {
289
 
                    *format++ = *s++;
290
 
                } else {
291
 
                    done = TRUE;
292
 
                }
293
 
                break;
294
 
            default:
295
 
                if (isdigit(UChar(*s))) {
296
 
                    value = (value * 10) + (*s - '0');
297
 
                    if (value > 10000)
298
 
                        err = TRUE;
299
 
                    *format++ = *s++;
300
 
                } else {
301
 
                    done = TRUE;
302
 
                }
303
 
            }
304
 
        }
305
 
 
306
 
        /*
307
 
         * If we found an error, ignore (and remove) the flags.
308
 
         */
309
 
        if (err) {
310
 
            my_width = my_prec = value = 0;
311
 
            format = fmt;
312
 
            *format++ = '%';
313
 
            *format++ = *s;
314
 
        }
315
 
 
316
 
        /*
317
 
         * Any value after '.' is the precision.  If we did not see '.', then
318
 
         * the value is the width.
319
 
         */
320
 
        if (dot)
321
 
            my_prec = value;
322
 
        else
323
 
            my_width = value;
324
 
 
325
 
        *format = '\0';
326
 
        /* return maximum string length in print */
327
 
        *len = (my_width > my_prec) ? my_width : my_prec;
328
 
    }
329
 
    return s;
330
 
}
331
 
 
332
 
/*
333
 
 * Analyze the string to see how many parameters we need from the varargs list,
334
 
 * and what their types are.  We will only accept string parameters if they
335
 
 * appear as a %l or %s format following an explicit parameter reference (e.g.,
336
 
 * %p2%s).  All other parameters are numbers.
337
 
 *
338
 
 * 'number' counts coarsely the number of pop's we see in the string, and
339
 
 * 'popcount' shows the highest parameter number in the string.  We would like
340
 
 * to simply use the latter count, but if we are reading termcap strings, there
341
 
 * may be cases that we cannot see the explicit parameter numbers.
342
 
 */
343
 
static inline int
344
 
analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount)
345
 
{
346
 
    grub_size_t len2;
347
 
    int i;
348
 
    int lastpop = -1;
349
 
    int len;
350
 
    int number = 0;
351
 
    const char *cp = string;
352
 
    static char dummy[] = "";
353
 
 
354
 
    *popcount = 0;
355
 
 
356
 
    if (cp == 0)
357
 
        return 0;
358
 
 
359
 
    if ((len2 = grub_strlen(cp)) > fmt_size) {
360
 
        fmt_size = len2 + fmt_size + 2;
361
 
        if ((fmt_buff = grub_realloc(fmt_buff, fmt_size*sizeof(char))) == 0)
362
 
              return 0;
363
 
    }
364
 
 
365
 
    grub_memset(p_is_s, 0, sizeof(p_is_s[0]) * NUM_PARM);
366
 
 
367
 
    while ((cp - string) < (int) len2) {
368
 
        if (*cp == '%') {
369
 
            cp++;
370
 
            cp = parse_format(cp, fmt_buff, &len);
371
 
            switch (*cp) {
372
 
            default:
373
 
                break;
374
 
 
375
 
            case 'd':           /* FALLTHRU */
376
 
            case 'o':           /* FALLTHRU */
377
 
            case 'x':           /* FALLTHRU */
378
 
            case 'X':           /* FALLTHRU */
379
 
            case 'c':           /* FALLTHRU */
380
 
                if (lastpop <= 0)
381
 
                    number++;
382
 
                lastpop = -1;
383
 
                break;
384
 
 
385
 
            case 'l':
386
 
            case 's':
387
 
                if (lastpop > 0)
388
 
                    p_is_s[lastpop - 1] = dummy;
389
 
                ++number;
390
 
                break;
391
 
 
392
 
            case 'p':
393
 
                cp++;
394
 
                i = (UChar(*cp) - '0');
395
 
                if (i >= 0 && i <= NUM_PARM) {
396
 
                    lastpop = i;
397
 
                    if (lastpop > *popcount)
398
 
                        *popcount = lastpop;
399
 
                }
400
 
                break;
401
 
 
402
 
            case 'P':
403
 
                ++number;
404
 
                ++cp;
405
 
                break;
406
 
 
407
 
            case 'g':
408
 
                cp++;
409
 
                break;
410
 
 
411
 
            case '\'':
412
 
                cp += 2;
413
 
                lastpop = -1;
414
 
                break;
415
 
 
416
 
            case '{':
417
 
                cp++;
418
 
                while (isdigit(UChar(*cp))) {
419
 
                    cp++;
420
 
                }
421
 
                break;
422
 
 
423
 
            case '+':
424
 
            case '-':
425
 
            case '*':
426
 
            case '/':
427
 
            case 'm':
428
 
            case 'A':
429
 
            case 'O':
430
 
            case '&':
431
 
            case '|':
432
 
            case '^':
433
 
            case '=':
434
 
            case '<':
435
 
            case '>':
436
 
                lastpop = -1;
437
 
                number += 2;
438
 
                break;
439
 
 
440
 
            case '!':
441
 
            case '~':
442
 
                lastpop = -1;
443
 
                ++number;
444
 
                break;
445
 
 
446
 
            case 'i':
447
 
                /* will add 1 to first (usually two) parameters */
448
 
                break;
449
 
            }
450
 
        }
451
 
        if (*cp != '\0')
452
 
            cp++;
453
 
    }
454
 
 
455
 
    if (number > NUM_PARM)
456
 
        number = NUM_PARM;
457
 
    return number;
458
 
}
459
 
 
460
 
static inline char *
461
 
tparam_internal(const char *string, va_list ap)
462
 
{
463
 
    char *p_is_s[NUM_PARM];
464
 
    long param[NUM_PARM];
465
 
    int popcount;
466
 
    int number;
467
 
    int len;
468
 
    int level;
469
 
    int x, y;
470
 
    int i;
471
 
    const char *cp = string;
472
 
    grub_size_t len2;
473
 
    static int dynamic_var[NUM_VARS];
474
 
    static int static_vars[NUM_VARS];
475
 
 
476
 
    if (cp == 0)
477
 
        return 0;
478
 
 
479
 
    out_used = out_size = fmt_size = 0;
480
 
 
481
 
    len2 = (int) grub_strlen(cp);
482
 
 
483
 
    /*
484
 
     * Find the highest parameter-number referred to in the format string.
485
 
     * Use this value to limit the number of arguments copied from the
486
 
     * variable-length argument list.
487
 
     */
488
 
    number = analyze(cp, p_is_s, &popcount);
489
 
    if (fmt_buff == 0)
490
 
        return 0;
491
 
 
492
 
    for (i = 0; i < max(popcount, number); i++) {
493
 
        /*
494
 
         * A few caps (such as plab_norm) have string-valued parms.
495
 
         * We'll have to assume that the caller knows the difference, since
496
 
         * a char* and an int may not be the same size on the stack.
497
 
         */
498
 
        if (p_is_s[i] != 0) {
499
 
            p_is_s[i] = va_arg(ap, char *);
500
 
        } else {
501
 
            param[i] = va_arg(ap, long int);
502
 
        }
503
 
    }
504
 
 
505
 
    /*
506
 
     * This is a termcap compatibility hack.  If there are no explicit pop
507
 
     * operations in the string, load the stack in such a way that
508
 
     * successive pops will grab successive parameters.  That will make
509
 
     * the expansion of (for example) \E[%d;%dH work correctly in termcap
510
 
     * style, which means tparam() will expand termcap strings OK.
511
 
     */
512
 
    stack_ptr = 0;
513
 
    if (popcount == 0) {
514
 
        popcount = number;
515
 
        for (i = number - 1; i >= 0; i--)
516
 
            npush(param[i]);
517
 
    }
518
 
 
519
 
    while ((cp - string) < (int) len2) {
520
 
        if (*cp != '%') {
521
 
            save_char(UChar(*cp));
522
 
        } else {
523
 
            tparam_base = cp++;
524
 
            cp = parse_format(cp, fmt_buff, &len);
525
 
            switch (*cp) {
526
 
            default:
527
 
                break;
528
 
            case '%':
529
 
                save_char('%');
530
 
                break;
531
 
 
532
 
            case 'd':           /* FALLTHRU */
533
 
            case 'o':           /* FALLTHRU */
534
 
            case 'x':           /* FALLTHRU */
535
 
            case 'X':           /* FALLTHRU */
536
 
                save_number(fmt_buff, npop(), len);
537
 
                break;
538
 
 
539
 
            case 'c':           /* FALLTHRU */
540
 
                save_char(npop());
541
 
                break;
542
 
 
543
 
            case 'l':
544
 
                save_number("%d", (int) grub_strlen(spop()), 0);
545
 
                break;
546
 
 
547
 
            case 's':
548
 
                save_text(fmt_buff, spop(), len);
549
 
                break;
550
 
 
551
 
            case 'p':
552
 
                cp++;
553
 
                i = (UChar(*cp) - '1');
554
 
                if (i >= 0 && i < NUM_PARM) {
555
 
                    if (p_is_s[i])
556
 
                        spush(p_is_s[i]);
557
 
                    else
558
 
                        npush(param[i]);
559
 
                }
560
 
                break;
561
 
 
562
 
            case 'P':
563
 
                cp++;
564
 
                if (isUPPER(*cp)) {
565
 
                    i = (UChar(*cp) - 'A');
566
 
                    static_vars[i] = npop();
567
 
                } else if (isLOWER(*cp)) {
568
 
                    i = (UChar(*cp) - 'a');
569
 
                    dynamic_var[i] = npop();
570
 
                }
571
 
                break;
572
 
 
573
 
            case 'g':
574
 
                cp++;
575
 
                if (isUPPER(*cp)) {
576
 
                    i = (UChar(*cp) - 'A');
577
 
                    npush(static_vars[i]);
578
 
                } else if (isLOWER(*cp)) {
579
 
                    i = (UChar(*cp) - 'a');
580
 
                    npush(dynamic_var[i]);
581
 
                }
582
 
                break;
583
 
 
584
 
            case '\'':
585
 
                cp++;
586
 
                npush(UChar(*cp));
587
 
                cp++;
588
 
                break;
589
 
 
590
 
            case '{':
591
 
                number = 0;
592
 
                cp++;
593
 
                while (isdigit(UChar(*cp))) {
594
 
                    number = (number * 10) + (UChar(*cp) - '0');
595
 
                    cp++;
596
 
                }
597
 
                npush(number);
598
 
                break;
599
 
 
600
 
            case '+':
601
 
                npush(npop() + npop());
602
 
                break;
603
 
 
604
 
            case '-':
605
 
                y = npop();
606
 
                x = npop();
607
 
                npush(x - y);
608
 
                break;
609
 
 
610
 
            case '*':
611
 
                npush(npop() * npop());
612
 
                break;
613
 
 
614
 
            case '/':
615
 
                y = npop();
616
 
                x = npop();
617
 
                npush(y ? (x / y) : 0);
618
 
                break;
619
 
 
620
 
            case 'm':
621
 
                y = npop();
622
 
                x = npop();
623
 
                npush(y ? (x % y) : 0);
624
 
                break;
625
 
 
626
 
            case 'A':
627
 
                npush(npop() && npop());
628
 
                break;
629
 
 
630
 
            case 'O':
631
 
                npush(npop() || npop());
632
 
                break;
633
 
 
634
 
            case '&':
635
 
                npush(npop() & npop());
636
 
                break;
637
 
 
638
 
            case '|':
639
 
                npush(npop() | npop());
640
 
                break;
641
 
 
642
 
            case '^':
643
 
                npush(npop() ^ npop());
644
 
                break;
645
 
 
646
 
            case '=':
647
 
                y = npop();
648
 
                x = npop();
649
 
                npush(x == y);
650
 
                break;
651
 
 
652
 
            case '<':
653
 
                y = npop();
654
 
                x = npop();
655
 
                npush(x < y);
656
 
                break;
657
 
 
658
 
            case '>':
659
 
                y = npop();
660
 
                x = npop();
661
 
                npush(x > y);
662
 
                break;
663
 
 
664
 
            case '!':
665
 
                npush(!npop());
666
 
                break;
667
 
 
668
 
            case '~':
669
 
                npush(~npop());
670
 
                break;
671
 
 
672
 
            case 'i':
673
 
                if (p_is_s[0] == 0)
674
 
                    param[0]++;
675
 
                if (p_is_s[1] == 0)
676
 
                    param[1]++;
677
 
                break;
678
 
 
679
 
            case '?':
680
 
                break;
681
 
 
682
 
            case 't':
683
 
                x = npop();
684
 
                if (!x) {
685
 
                    /* scan forward for %e or %; at level zero */
686
 
                    cp++;
687
 
                    level = 0;
688
 
                    while (*cp) {
689
 
                        if (*cp == '%') {
690
 
                            cp++;
691
 
                            if (*cp == '?')
692
 
                                level++;
693
 
                            else if (*cp == ';') {
694
 
                                if (level > 0)
695
 
                                    level--;
696
 
                                else
697
 
                                    break;
698
 
                            } else if (*cp == 'e' && level == 0)
699
 
                                break;
700
 
                        }
701
 
 
702
 
                        if (*cp)
703
 
                            cp++;
704
 
                    }
705
 
                }
706
 
                break;
707
 
 
708
 
            case 'e':
709
 
                /* scan forward for a %; at level zero */
710
 
                cp++;
711
 
                level = 0;
712
 
                while (*cp) {
713
 
                    if (*cp == '%') {
714
 
                        cp++;
715
 
                        if (*cp == '?')
716
 
                            level++;
717
 
                        else if (*cp == ';') {
718
 
                            if (level > 0)
719
 
                                level--;
720
 
                            else
721
 
                                break;
722
 
                        }
723
 
                    }
724
 
 
725
 
                    if (*cp)
726
 
                        cp++;
727
 
                }
728
 
                break;
729
 
 
730
 
            case ';':
731
 
                break;
732
 
 
733
 
            }                   /* endswitch (*cp) */
734
 
        }                       /* endelse (*cp == '%') */
735
 
 
736
 
        if (*cp == '\0')
737
 
            break;
738
 
 
739
 
        cp++;
740
 
    }                           /* endwhile (*cp) */
741
 
 
742
 
    get_space(1);
743
 
    out_buff[out_used] = '\0';
744
 
 
745
 
    return (out_buff);
746
 
}
747
 
 
748
 
char *
749
 
grub_terminfo_tparm (const char *string, ...)
750
 
{
751
 
    va_list ap;
752
 
    char *result;
753
 
 
754
 
    if (!string)
755
 
      return "";
756
 
 
757
 
    va_start (ap, string);
758
 
    result = tparam_internal (string, ap);
759
 
    va_end (ap);
760
 
    return result;
761
 
}