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

« back to all changes in this revision

Viewing changes to grub-core/script/parser.y

  • 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
/* parser.y - The scripting parser.  */
 
2
/*
 
3
 *  GRUB  --  GRand Unified Bootloader
 
4
 *  Copyright (C) 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
%{
 
21
#include <grub/script_sh.h>
 
22
#include <grub/mm.h>
 
23
#include <grub/misc.h>
 
24
 
 
25
#define YYFREE          grub_free
 
26
#define YYMALLOC        grub_malloc
 
27
#define YYLTYPE_IS_TRIVIAL      0
 
28
#define YYENABLE_NLS    0
 
29
 
 
30
#include "grub_script.tab.h"
 
31
%}
 
32
 
 
33
%union {
 
34
  struct grub_script_cmd *cmd;
 
35
  struct grub_script_arglist *arglist;
 
36
  struct grub_script_arg *arg;
 
37
  char *string;
 
38
  struct {
 
39
    unsigned offset;
 
40
    struct grub_script_mem *memory;
 
41
    struct grub_script *scripts;
 
42
  };
 
43
}
 
44
 
 
45
%token GRUB_PARSER_TOKEN_BAD
 
46
%token GRUB_PARSER_TOKEN_EOF 0 "end-of-input"
 
47
 
 
48
%token GRUB_PARSER_TOKEN_NEWLINE "\n"
 
49
%token GRUB_PARSER_TOKEN_AND     "&&"
 
50
%token GRUB_PARSER_TOKEN_OR      "||"
 
51
%token GRUB_PARSER_TOKEN_SEMI2   ";;"
 
52
%token GRUB_PARSER_TOKEN_PIPE    "|"
 
53
%token GRUB_PARSER_TOKEN_AMP     "&"
 
54
%token GRUB_PARSER_TOKEN_SEMI    ";"
 
55
%token GRUB_PARSER_TOKEN_LBR     "{"
 
56
%token GRUB_PARSER_TOKEN_RBR     "}"
 
57
%token GRUB_PARSER_TOKEN_NOT     "!"
 
58
%token GRUB_PARSER_TOKEN_LSQBR2  "["
 
59
%token GRUB_PARSER_TOKEN_RSQBR2  "]"
 
60
%token GRUB_PARSER_TOKEN_LT      "<"
 
61
%token GRUB_PARSER_TOKEN_GT      ">"
 
62
 
 
63
%token <arg> GRUB_PARSER_TOKEN_CASE      "case"
 
64
%token <arg> GRUB_PARSER_TOKEN_DO        "do"
 
65
%token <arg> GRUB_PARSER_TOKEN_DONE      "done"
 
66
%token <arg> GRUB_PARSER_TOKEN_ELIF      "elif"
 
67
%token <arg> GRUB_PARSER_TOKEN_ELSE      "else"
 
68
%token <arg> GRUB_PARSER_TOKEN_ESAC      "esac"
 
69
%token <arg> GRUB_PARSER_TOKEN_FI        "fi"
 
70
%token <arg> GRUB_PARSER_TOKEN_FOR       "for"
 
71
%token <arg> GRUB_PARSER_TOKEN_IF        "if"
 
72
%token <arg> GRUB_PARSER_TOKEN_IN        "in"
 
73
%token <arg> GRUB_PARSER_TOKEN_SELECT    "select"
 
74
%token <arg> GRUB_PARSER_TOKEN_THEN      "then"
 
75
%token <arg> GRUB_PARSER_TOKEN_UNTIL     "until"
 
76
%token <arg> GRUB_PARSER_TOKEN_WHILE     "while"
 
77
%token <arg> GRUB_PARSER_TOKEN_TIME      "time"
 
78
%token <arg> GRUB_PARSER_TOKEN_FUNCTION  "function"
 
79
%token <arg> GRUB_PARSER_TOKEN_NAME      "name"
 
80
%token <arg> GRUB_PARSER_TOKEN_WORD      "word"
 
81
 
 
82
%type <arg> block block0
 
83
%type <arglist> word argument arguments0 arguments1
 
84
 
 
85
%type <cmd> script_init script
 
86
%type <cmd> grubcmd ifclause ifcmd forcmd whilecmd untilcmd
 
87
%type <cmd> command commands1 statement
 
88
 
 
89
%pure-parser
 
90
%lex-param   { struct grub_parser_param *state };
 
91
%parse-param { struct grub_parser_param *state };
 
92
 
 
93
%start script_init
 
94
 
 
95
%%
 
96
/* It should be possible to do this in a clean way...  */
 
97
script_init: { state->err = 0; } script { state->parsed = $2; state->err = 0; }
 
98
;
 
99
 
 
100
script: newlines0
 
101
        {
 
102
          $$ = 0;
 
103
        }
 
104
      | script statement delimiter newlines0
 
105
        {
 
106
          $$ = grub_script_append_cmd (state, $1, $2);
 
107
        }
 
108
      | error
 
109
        {
 
110
          $$ = 0;
 
111
          yyerror (state, "Incorrect command");
 
112
          yyerrok;
 
113
        }
 
114
;
 
115
 
 
116
newlines0: /* Empty */ | newlines1 ;
 
117
newlines1: newlines0 "\n" ;
 
118
 
 
119
delimiter: ";"
 
120
         | "\n"
 
121
;
 
122
delimiters0: /* Empty */ | delimiters1 ;
 
123
delimiters1: delimiter
 
124
          | delimiters1 "\n"
 
125
;
 
126
 
 
127
word: GRUB_PARSER_TOKEN_NAME { $$ = grub_script_add_arglist (state, 0, $1); }
 
128
    | GRUB_PARSER_TOKEN_WORD { $$ = grub_script_add_arglist (state, 0, $1); }
 
129
;
 
130
 
 
131
statement: command   { $$ = $1; }
 
132
         | function  { $$ = 0;  }
 
133
;
 
134
 
 
135
argument : "case"      { $$ = grub_script_add_arglist (state, 0, $1); }
 
136
         | "do"        { $$ = grub_script_add_arglist (state, 0, $1); }
 
137
         | "done"      { $$ = grub_script_add_arglist (state, 0, $1); }
 
138
         | "elif"      { $$ = grub_script_add_arglist (state, 0, $1); }
 
139
         | "else"      { $$ = grub_script_add_arglist (state, 0, $1); }
 
140
         | "esac"      { $$ = grub_script_add_arglist (state, 0, $1); }
 
141
         | "fi"        { $$ = grub_script_add_arglist (state, 0, $1); }
 
142
         | "for"       { $$ = grub_script_add_arglist (state, 0, $1); }
 
143
         | "if"        { $$ = grub_script_add_arglist (state, 0, $1); }
 
144
         | "in"        { $$ = grub_script_add_arglist (state, 0, $1); }
 
145
         | "select"    { $$ = grub_script_add_arglist (state, 0, $1); }
 
146
         | "then"      { $$ = grub_script_add_arglist (state, 0, $1); }
 
147
         | "until"     { $$ = grub_script_add_arglist (state, 0, $1); }
 
148
         | "while"     { $$ = grub_script_add_arglist (state, 0, $1); }
 
149
         | "function"  { $$ = grub_script_add_arglist (state, 0, $1); }
 
150
         | word { $$ = $1; }
 
151
;
 
152
 
 
153
/*
 
154
  Block parameter is passed to commands in two forms: as unparsed
 
155
  string and as pre-parsed grub_script object.  Passing as grub_script
 
156
  object makes memory management difficult, because:
 
157
 
 
158
  (1) Command may want to keep a reference to grub_script objects for
 
159
      later use, so script framework may not free the grub_script
 
160
      object after command completes.
 
161
 
 
162
  (2) Command may get called multiple times with same grub_script
 
163
      object under loops, so we should not let command implementation
 
164
      to free the grub_script object.
 
165
 
 
166
  To solve above problems, we rely on reference counting for
 
167
  grub_script objects.  Commands that want to keep the grub_script
 
168
  object must take a reference to it.
 
169
 
 
170
  Other complexity comes with arbitrary nesting of grub_script
 
171
  objects: a grub_script object may have commands with several block
 
172
  parameters, and each block parameter may further contain multiple
 
173
  block parameters nested.  We use temporary variable, state->scripts
 
174
  to collect nested child scripts (that are linked by siblings and
 
175
  children members), and will build grub_scripts tree from bottom.
 
176
 */
 
177
block: "{"
 
178
       {
 
179
         grub_script_lexer_ref (state->lexerstate);
 
180
         $<offset>$ = grub_script_lexer_record_start (state);
 
181
         $<memory>$ = grub_script_mem_record (state);
 
182
 
 
183
         /* save currently known scripts.  */
 
184
         $<scripts>$ = state->scripts;
 
185
         state->scripts = 0;
 
186
       }
 
187
       commands1 delimiters0 "}"
 
188
       {
 
189
         char *p;
 
190
         struct grub_script_mem *memory;
 
191
         struct grub_script *s = $<scripts>2;
 
192
 
 
193
         memory = grub_script_mem_record_stop (state, $<memory>2);
 
194
         if ((p = grub_script_lexer_record_stop (state, $<offset>2)))
 
195
           *grub_strrchr (p, '}') = '\0';
 
196
 
 
197
         $$ = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_BLOCK, p);
 
198
         if (! $$ || ! ($$->script = grub_script_create ($3, memory)))
 
199
           grub_script_mem_free (memory);
 
200
 
 
201
         else {
 
202
           /* attach nested scripts to $$->script as children */
 
203
           $$->script->children = state->scripts;
 
204
 
 
205
           /* restore old scripts; append $$->script to siblings. */
 
206
           state->scripts = $<scripts>2 ?: $$->script;
 
207
           if (s) {
 
208
             while (s->next_siblings)
 
209
               s = s->next_siblings;
 
210
             s->next_siblings = $$->script;
 
211
           }
 
212
         }
 
213
 
 
214
         grub_script_lexer_deref (state->lexerstate);
 
215
       }
 
216
;
 
217
block0: /* Empty */ { $$ = 0; }
 
218
      | block { $$ = $1; }
 
219
;
 
220
 
 
221
arguments0: /* Empty */ { $$ = 0; }
 
222
          | arguments1  { $$ = $1; }
 
223
;
 
224
arguments1: argument arguments0
 
225
            {
 
226
              if ($1 && $2)
 
227
                {
 
228
                  $1->next = $2;
 
229
                  $1->argcount += $2->argcount;
 
230
                  $2->argcount = 0;
 
231
                }
 
232
              $$ = $1;
 
233
            }
 
234
;
 
235
 
 
236
grubcmd: word arguments0 block0
 
237
         {
 
238
           struct grub_script_arglist *x = $2;
 
239
 
 
240
           if ($3)
 
241
             x = grub_script_add_arglist (state, $2, $3);
 
242
 
 
243
           if ($1 && x) {
 
244
             $1->next = x;
 
245
             $1->argcount += x->argcount;
 
246
             x->argcount = 0;
 
247
           }
 
248
           $$ = grub_script_create_cmdline (state, $1);
 
249
         }
 
250
;
 
251
 
 
252
/* A single command.  */
 
253
command: grubcmd  { $$ = $1; }
 
254
       | ifcmd    { $$ = $1; }
 
255
       | forcmd   { $$ = $1; }
 
256
       | whilecmd { $$ = $1; }
 
257
       | untilcmd { $$ = $1; }
 
258
;
 
259
 
 
260
/* A list of commands. */
 
261
commands1: newlines0 command
 
262
           {
 
263
             $$ = grub_script_append_cmd (state, 0, $2);
 
264
           }
 
265
         | commands1 delimiters1 command
 
266
           {
 
267
             $$ = grub_script_append_cmd (state, $1, $3);
 
268
           }
 
269
;
 
270
 
 
271
function: "function" "name"
 
272
          {
 
273
            grub_script_lexer_ref (state->lexerstate);
 
274
            state->func_mem = grub_script_mem_record (state);
 
275
 
 
276
            $<scripts>$ = state->scripts;
 
277
            state->scripts = 0;
 
278
          }
 
279
          delimiters0 "{" commands1 delimiters1 "}"
 
280
          {
 
281
            struct grub_script *script;
 
282
            state->func_mem = grub_script_mem_record_stop (state,
 
283
                                                           state->func_mem);
 
284
            script = grub_script_create ($6, state->func_mem);
 
285
            if (! script)
 
286
              grub_script_mem_free (state->func_mem);
 
287
            else {
 
288
              script->children = state->scripts;
 
289
              grub_script_function_create ($2, script);
 
290
            }
 
291
 
 
292
            state->scripts = $<scripts>3;
 
293
            grub_script_lexer_deref (state->lexerstate);
 
294
          }
 
295
;
 
296
 
 
297
ifcmd: "if"
 
298
        {
 
299
          grub_script_lexer_ref (state->lexerstate);
 
300
        }
 
301
        ifclause "fi"
 
302
        {
 
303
          $$ = $3;
 
304
          grub_script_lexer_deref (state->lexerstate);
 
305
        }
 
306
;
 
307
ifclause: commands1 delimiters1 "then" commands1 delimiters1
 
308
          {
 
309
            $$ = grub_script_create_cmdif (state, $1, $4, 0);
 
310
          }
 
311
        | commands1 delimiters1 "then" commands1 delimiters1 "else" commands1 delimiters1
 
312
          {
 
313
            $$ = grub_script_create_cmdif (state, $1, $4, $7);
 
314
          }
 
315
        | commands1 delimiters1 "then" commands1 delimiters1 "elif" ifclause
 
316
          {
 
317
            $$ = grub_script_create_cmdif (state, $1, $4, $7);
 
318
          }
 
319
;
 
320
 
 
321
forcmd: "for" "name"
 
322
        {
 
323
          grub_script_lexer_ref (state->lexerstate);
 
324
        }
 
325
        "in" arguments0 delimiters1 "do" commands1 delimiters1 "done"
 
326
        {
 
327
          $$ = grub_script_create_cmdfor (state, $2, $5, $8);
 
328
          grub_script_lexer_deref (state->lexerstate);
 
329
        }
 
330
;
 
331
 
 
332
whilecmd: "while"
 
333
          {
 
334
            grub_script_lexer_ref (state->lexerstate);
 
335
          }
 
336
          commands1 delimiters1 "do" commands1 delimiters1 "done"
 
337
          {
 
338
            $$ = grub_script_create_cmdwhile (state, $3, $6, 0);
 
339
            grub_script_lexer_deref (state->lexerstate);
 
340
          }
 
341
;
 
342
 
 
343
untilcmd: "until"
 
344
          {
 
345
            grub_script_lexer_ref (state->lexerstate);
 
346
          }
 
347
          commands1 delimiters1 "do" commands1 delimiters1 "done"
 
348
          {
 
349
            $$ = grub_script_create_cmdwhile (state, $3, $6, 1);
 
350
            grub_script_lexer_deref (state->lexerstate);
 
351
          }
 
352
;