~ubuntu-branches/debian/sid/grub2/sid-200907171837

« back to all changes in this revision

Viewing changes to term/tparm.c

  • Committer: Bazaar Package Importer
  • Author(s): Otavio Salvador
  • Date: 2006-01-05 15:20:40 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060105152040-1ab076d4n3y2o5yf
Tags: 1.92-1
* New upstream release.
  - Add support for GPT partition table format.
  - Add a new command "play" to play an audio file on PC.
  - Add support for Linux/ADFS partition table format.
  - Add support for BASH-like scripting.
  - Add support for Apple HFS+ filesystems.
* 01_fix_grub-install.patch: Added. Fix grub-install to use
  /bin/grub-mkimage instead of /sbin/grub-mkimage. Closes: #338824
* Do not use CDBS tarball mode anymore. Closes: #344272  

Show diffs side-by-side

added added

removed removed

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