[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Bash pre-alpha
From: |
Serbinenko Vladimir |
Subject: |
Re: Bash pre-alpha |
Date: |
Mon, 31 Jan 2005 06:59:54 +0100 |
User-agent: |
Mozilla Thunderbird 1.0 (X11/20041206) |
Here I send a patch for bash scripting. New version. Here it's not an
incremental patch. it's a patch for current CVS version. Current problems:
Not enough testing
Badly commented.
Best wishes
Serbinenko
Vladimir
--------------------------------------------------------------------------
diff -b -B -r -u -E -N -x '*~' -x '*.d' -x 'config*' -x kernel_syms.lst
-x Makefile -x stamp-h -x symlist.c -x output.0 -x requests -x traces.0
-x '*.mk' -x cpu -x machine -x Entries --expand-tabs grub2/ChangeLog
grub2ch/ChangeLog
--- grub2/ChangeLog 2005-01-29 23:01:54.000000000 +0100
+++ grub2ch/ChangeLog 2005-01-30 19:24:08.852259864 +0100
@@ -1,3 +1,38 @@
+2005-01-30 Serbinenko Vladimir <address@hidden>
+
+ * Scripting: new constructions: for((...;...;...)); do ...; done
+ for .. in ...; do ...; done
+ braces expansion
+ GCS cleanup
+ Integrating token spliting in scripting
+ Function script_expand is now split up in
script_expand_braces,
+ script_expand_dollar and script_split_tokens
+ some bugfixing
+
+2005-01-29 Serbinenko Vladimir <address@hidden>
+
+ * include/grub/script.h: New type return reason
+ * normal/command.c : New commands: true,false, '.'
+ * normal/script.c: Bug fixed
+ New keywords: until, while,
break,continue,return
+
+2005-01-29 Serbinenko Vladimir <address@hidden>
+
+ Scripting support
+ * normal/script.c: New file
+ * include/grub/normal.h: New prototype
+ * include/grub/script.h: New file
+ * normal/script.c: Likewise
+ * normal/command.c : grub_command_execute: redirect to
scripting engine
+ grub_exec_norm: Normal
executing
+ grub_command_set: using
script_env_set
+ grub_command_unset:
Likewise
+ New commands: ':',
echo, source, showmenu
+ Due to new menu syntax
title command removed
+ * normal/main.c: get_line and read_config_file replaced
by scripting
+ menu variable redeclared as global
+ * normal/menu.c: run_menu_entry: redirected to scripting
engine
+
2005-01-29 Yoshinori K. Okuji <address@hidden>
* include/grub/misc.h (memmove): New prototype.
diff -b -B -r -u -E -N -x '*~' -x '*.d' -x 'config*' -x kernel_syms.lst
-x Makefile -x stamp-h -x symlist.c -x output.0 -x requests -x traces.0
-x '*.mk' -x cpu -x machine -x Entries --expand-tabs
grub2/conf/i386-pc.rmk grub2ch/conf/i386-pc.rmk
--- grub2/conf/i386-pc.rmk 2005-01-21 22:32:03.000000000 +0100
+++ grub2ch/conf/i386-pc.rmk 2005-01-29 13:41:05.000000000 +0100
@@ -72,7 +72,7 @@
partmap/pc.c partmap/apple.c \
commands/terminal.c commands/boot.c commands/cmp.c
commands/cat.c \
util/i386/pc/biosdisk.c fs/fat.c fs/ext2.c fs/ufs.c fs/minix.c
fs/hfs.c fs/jfs.c fs/iso9660.c \
- normal/cmdline.c normal/command.c normal/main.c normal/menu.c
normal/arg.c \
+ normal/cmdline.c normal/command.c normal/script.c normal/main.c
normal/menu.c normal/arg.c \
util/console.c util/grub-emu.c util/misc.c
util/i386/pc/getroot.c disk/loopback.c
grub_emu_LDFLAGS = -lncurses
@@ -134,7 +134,7 @@
linux_mod_CFLAGS = $(COMMON_CFLAGS)
# For normal.mod.
-normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/main.c \
+normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/script.c
normal/main.c \
normal/menu.c normal/arg.c normal/i386/setjmp.S
normal_mod_CFLAGS = $(COMMON_CFLAGS)
normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
diff -b -B -r -u -E -N -x '*~' -x '*.d' -x 'config*' -x kernel_syms.lst
-x Makefile -x stamp-h -x symlist.c -x output.0 -x requests -x traces.0
-x '*.mk' -x cpu -x machine -x Entries --expand-tabs
grub2/conf/powerpc-ieee1275.rmk grub2ch/conf/powerpc-ieee1275.rmk
--- grub2/conf/powerpc-ieee1275.rmk 2005-01-21 22:32:03.000000000 +0100
+++ grub2ch/conf/powerpc-ieee1275.rmk 2005-01-29 13:42:19.000000000 +0100
@@ -38,7 +38,7 @@
partmap/amiga.c partmap/pc.c partmap/apple.c fs/fshelp.c \
util/i386/pc/biosdisk.c fs/fat.c fs/ext2.c fs/ufs.c fs/minix.c
fs/hfs.c \
fs/jfs.c fs/iso9660.c \
- normal/cmdline.c normal/command.c normal/main.c normal/menu.c \
+ normal/cmdline.c normal/command.c normal/script.c normal/main.c
normal/menu.c \
normal/arg.c kern/partition.c \
util/console.c util/grub-emu.c util/misc.c util/i386/pc/getroot.c \
kern/env.c disk/loopback.c commands/ls.c \
@@ -108,7 +108,7 @@
linux_mod_CFLAGS = $(COMMON_CFLAGS)
# For normal.mod.
-normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/main.c \
+normal_mod_SOURCES = normal/cmdline.c normal/command.c normal/script.c
normal/main.c \
normal/menu.c normal/arg.c normal/powerpc/setjmp.S
normal_mod_CFLAGS = $(COMMON_CFLAGS)
normal_mod_ASFLAGS = $(COMMON_ASFLAGS)
diff -b -B -r -u -E -N -x '*~' -x '*.d' -x 'config*' -x kernel_syms.lst
-x Makefile -x stamp-h -x symlist.c -x output.0 -x requests -x traces.0
-x '*.mk' -x cpu -x machine -x Entries --expand-tabs
grub2/include/grub/normal.h grub2ch/include/grub/normal.h
--- grub2/include/grub/normal.h 2005-01-21 22:32:03.000000000 +0100
+++ grub2ch/include/grub/normal.h 2005-01-30 11:57:04.000000000 +0100
@@ -141,7 +141,7 @@
void grub_normal_init_page (void);
int grub_arg_parse (grub_command_t parser, int argc, char **argv,
struct grub_arg_list *usr, char ***args, int *argnum);
-
+int grub_exec_norm(char**args,int num);
#ifdef GRUB_UTIL
void grub_normal_init (void);
diff -b -B -r -u -E -N -x '*~' -x '*.d' -x 'config*' -x kernel_syms.lst
-x Makefile -x stamp-h -x symlist.c -x output.0 -x requests -x traces.0
-x '*.mk' -x cpu -x machine -x Entries --expand-tabs
grub2/include/grub/script.h grub2ch/include/grub/script.h
--- grub2/include/grub/script.h 1970-01-01 01:00:00.000000000 +0100
+++ grub2ch/include/grub/script.h 2005-01-30 12:13:54.000000000 +0100
@@ -0,0 +1,94 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ * GRUB is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef SCRIPT_H
+#define SCRIPT_H 1
+#define EXPAND_BUF_SIZE 1024
+#define BRACE_BUFFER 64
+
+#define SCRIPT_BRACK 0
+#define SCRIPT_LEFT 1
+#define SCRIPT_RIGHT 2
+#define SCRIPT_BIN 3
+#define SCRIPT_TERN 4
+#define SCRIPT_AND 5
+#define SCRIPT_OR 6
+#define SCRIPT_LEFTS SCRIPT_LEFT
+#define SCRIPT_ARGPART 7
+#define SCRIPT_LVALUE 8
+#define SCRIPT_RASSOC 16
+#define SCRIPT_NEEDLVALUEA 16
+struct script_oper{
+ int priority;
+ char seq[10];
+ int type;
+ char* (*func_do)(char*a,char*b,int opn);
+};
+struct braceset
+{
+ char*word;
+ int len;
+ struct braceset*next;
+};
+enum vartype {SCRIPT_STR,SCRIPT_VAR_NAME};
+enum returnreason
{SCRIPT_NONE=0,SCRIPT_RETURN,SCRIPT_BREAK,SCRIPT_CONTINUE};
+extern struct script_oper script_opers[];
+int
+script_find_oper(char*exp,int searchleft);
+char*
+script_eval_arith(char*,enum vartype*);
+char*
+script_env_get(char*nm);
+void
+script_env_unset(char*nm);
+void
+script_env_set(char*nm,char*val);
+char*
+script_get_str(char*var,enum vartype tp);
+char*
+script_get_arrayelem(char*elem,char*indx);
+char*
+script_expand_dollar (char*exp);
+char*
+script_get_array(char*exp,char**cont,int contcnt);
+char*
+script_escape_string(char*str);
+void
+script_unescape(char*str);
+void
+script_del_arrayelem(char**arr,char*indx);
+void
+script_add_arrayelem(char**arr,char*indx,char*val);
+int
+script_find_pas(char cbeg,char cend,char *str);
+int
+script_get_strend(char*str);
+int
+script_execute(char*cmdline,grub_err_t(*getline)(char**),char**rest,enum
returnreason*retres,int*depth);
+int
+script_list_execute( grub_menu_entry_t fn,enum
returnreason*retres,int*depth);
+int
+script_exec_file (char*fname,int argc, char**argv);
+char**
+script_split_tokens(char*cmdline,int*argc,grub_err_t (* getline) (char
**),char**end);
+grub_menu_t menu;
+#define EXPAND_DOLLAR 1
+#define EXPAND_BRACE 2
+#define EXPAND_ALL 3
+#endif /* ! SCRIPT_H*/
diff -b -B -r -u -E -N -x '*~' -x '*.d' -x 'config*' -x kernel_syms.lst
-x Makefile -x stamp-h -x symlist.c -x output.0 -x requests -x traces.0
-x '*.mk' -x cpu -x machine -x Entries --expand-tabs
grub2/normal/command.c grub2ch/normal/command.c
--- grub2/normal/command.c 2004-09-17 11:36:52.000000000 +0200
+++ grub2ch/normal/command.c 2005-01-30 12:01:30.000000000 +0100
@@ -24,6 +24,7 @@
#include <grub/term.h>
#include <grub/env.h>
#include <grub/dl.h>
+#include <grub/script.h>
static grub_command_t grub_command_list;
@@ -120,31 +121,19 @@
return grub_cmdline_get (">", *s, GRUB_MAX_CMDLINE, 0, 1);
}
+ return script_execute(cmdline,cmdline_get,0,0,0);
+}
+int
+grub_exec_norm(char**args,int num)
+{
grub_command_t cmd;
grub_err_t ret = 0;
char *pager;
- int num;
- char **args;
struct grub_arg_list *state;
struct grub_arg_option *parser;
int maxargs = 0;
char **arglist;
int numargs;
-
- if (grub_split_cmdline (cmdline, cmdline_get, &num, &args))
- return 0;
-
- /* In case of an assignment set the environment accordingly instead
- of calling a function. */
- if (num == 0 && grub_strchr (args[0], '='))
- {
- char *val = grub_strchr (args[0], '=');
- val[0] = 0;
- grub_env_set (args[0], val + 1);
- val[0] = '=';
- return 0;
- }
-
cmd = grub_command_find (args[0]);
if (! cmd)
return -1;
@@ -162,11 +151,11 @@
grub_memset (state, 0, sizeof (struct grub_arg_list) * maxargs);
if (! (cmd->flags & GRUB_COMMAND_FLAG_NO_ARG_PARSE))
{
- if (grub_arg_parse (cmd, num, &args[1], state, &arglist, &numargs))
+ if (grub_arg_parse (cmd, num-1, &args[1], state, &arglist, &numargs))
ret = (cmd->func) (state, numargs, arglist);
}
else
- ret = (cmd->func) (state, num, &args[1]);
+ ret = (cmd->func) (state, num-1, &args[1]);
grub_free (state);
@@ -218,7 +208,7 @@
}
val[0] = 0;
- grub_env_set (var, val + 1);
+ script_env_set (var, val + 1);
val[0] = '=';
return 0;
}
@@ -231,7 +221,7 @@
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"no environment variable specified");
- grub_env_unset (args[0]);
+ script_env_unset (args[0]);
return 0;
}
@@ -306,11 +296,70 @@
return 0;
}
+
+static grub_err_t
+echo_command (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc,
+ char **args)
+{
+ int i;
+ for(i=0;i<argc;i++)
+ grub_printf ("%s ",args[i]);
+ grub_printf("\n");
+ return 0;
+}
+
+static grub_err_t
+empty_command (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ return 0;
+}
+
+static grub_err_t
+source_command (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc,
+ char **args)
+{
+ if(!argc)
+ {
+ grub_error(GRUB_ERR_BAD_ARGUMENT,"Filename expected");
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+ return script_exec_file(args[0],argc-1,args+1);
+}
+static grub_err_t
+showmenu_command (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ if (menu->size)
+ grub_menu_run (menu, 0);
+ else
+ grub_cmdline_run (0);
+ return 0;
+}
+
+static grub_err_t
+true_command (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ return 0;
+}
+
+static grub_err_t
+false_command (struct grub_arg_list *state __attribute__ ((unused)),
+ int argc __attribute__ ((unused)),
+ char **args __attribute__ ((unused)))
+{
+ return 1;
+}
+
void
grub_command_init (void)
{
- /* This is a special command, because this never be called actually. */
- grub_register_command ("title", 0, GRUB_COMMAND_FLAG_TITLE, 0, 0, 0);
grub_register_command ("rescue", rescue_command, GRUB_COMMAND_FLAG_BOTH,
"rescue", "Enter into the rescue mode.", 0);
@@ -329,4 +378,23 @@
grub_register_command ("lsmod", lsmod_command, GRUB_COMMAND_FLAG_BOTH,
"lsmod", "Show loaded modules.", 0);
+
+ grub_register_command ("echo", echo_command, GRUB_COMMAND_FLAG_BOTH,
+ "echo MESSAGE", "Print a message.", 0);
+
+ grub_register_command (":", empty_command, GRUB_COMMAND_FLAG_BOTH,
+ ":", "Does nothing except expanding.", 0);
+
+ grub_register_command ("source", source_command, GRUB_COMMAND_FLAG_BOTH,
+ "source FILE [ARGUMENTS ...]", "Execute script
FILE.", 0);
+
+ grub_register_command (".", source_command, GRUB_COMMAND_FLAG_BOTH,
+ ". FILE [ARGUMENTS ...]", "Execute script
FILE.", 0);
+
+ grub_register_command ("showmenu", showmenu_command,
GRUB_COMMAND_FLAG_BOTH,
+ "showmenu", "Show menu.", 0);
+ grub_register_command ("true", true_command, GRUB_COMMAND_FLAG_BOTH,
+ "true", "Return success.", 0);
+ grub_register_command ("false", false_command, GRUB_COMMAND_FLAG_BOTH,
+ "false", "Return failure.", 0);
}
diff -b -B -r -u -E -N -x '*~' -x '*.d' -x 'config*' -x kernel_syms.lst
-x Makefile -x stamp-h -x symlist.c -x output.0 -x requests -x traces.0
-x '*.mk' -x cpu -x machine -x Entries --expand-tabs grub2/normal/main.c
grub2ch/normal/main.c
--- grub2/normal/main.c 2004-08-21 15:54:22.000000000 +0200
+++ grub2ch/normal/main.c 2005-01-29 13:57:28.000000000 +0100
@@ -32,74 +32,6 @@
#define GRUB_DEFAULT_HISTORY_SIZE 50
-/* Read a line from the file FILE. */
-static int
-get_line (grub_file_t file, char cmdline[], int max_len)
-{
- char c;
- int pos = 0;
- int literal = 0;
- int comment = 0;
-
- while (1)
- {
- if (grub_file_read (file, &c, 1) != 1)
- break;
-
- /* Skip all carriage returns. */
- if (c == '\r')
- continue;
-
- /* Replace tabs with spaces. */
- if (c == '\t')
- c = ' ';
-
- /* The previous is a backslash, then... */
- if (literal)
- {
- /* If it is a newline, replace it with a space and continue. */
- if (c == '\n')
- {
- c = ' ';
-
- /* Go back to overwrite the backslash. */
- if (pos > 0)
- pos--;
- }
-
- literal = 0;
- }
-
- if (c == '\\')
- literal = 1;
-
- if (comment)
- {
- if (c == '\n')
- comment = 0;
- }
- else if (pos == 0)
- {
- if (c == '#')
- comment = 1;
- else if (! grub_isspace (c))
- cmdline[pos++] = c;
- }
- else
- {
- if (c == '\n')
- break;
-
- if (pos < max_len)
- cmdline[pos++] = c;
- }
- }
-
- cmdline[pos] = '\0';
-
- return pos;
-}
-
static void
free_menu (grub_menu_t menu)
{
@@ -125,148 +57,6 @@
grub_free (menu);
}
-/* Read the config file CONFIG and return a menu. If no entry is present,
- return NULL. */
-static grub_menu_t
-read_config_file (const char *config)
-{
- grub_file_t file;
- static char cmdline[GRUB_MAX_CMDLINE];
- grub_menu_t menu;
- grub_menu_entry_t *next_entry, cur_entry = 0;
- grub_command_list_t *next_cmd, cur_cmd;
-
- /* Try to open the config file. */
- file = grub_file_open (config);
- if (! file)
- return 0;
-
- /* Initialize the menu. */
- menu = (grub_menu_t) grub_malloc (sizeof (*menu));
- if (! menu)
- {
- grub_file_close (file);
- return 0;
- }
- menu->default_entry = 0;
- menu->fallback_entry = -1;
- menu->timeout = -1;
- menu->size = 0;
- menu->entry_list = 0;
-
- next_entry = &(menu->entry_list);
- next_cmd = 0;
-
- /* Read each line. */
- while (get_line (file, cmdline, sizeof (cmdline)))
- {
- grub_command_t cmd;
-
- cmd = grub_command_find (cmdline);
- grub_errno = GRUB_ERR_NONE;
- if (! cmd)
- {
- grub_printf ("Unknown command `%s' is ignored.\n", cmdline);
- continue;
- }
-
- if (cmd->flags & GRUB_COMMAND_FLAG_TITLE)
- {
- char *p;
-
- cur_entry = (grub_menu_entry_t) grub_malloc (sizeof
(*cur_entry));
- if (! cur_entry)
- goto fail;
-
- p = grub_strchr (cmdline, ' ');
- if (p)
- cur_entry->title = grub_strdup (p);
- else
- cur_entry->title = grub_strdup ("");
-
- if (! cur_entry->title)
- {
- grub_free (cur_entry);
- goto fail;
- }
-
- cur_entry->num = 0;
- cur_entry->command_list = 0;
- cur_entry->next = 0;
-
- *next_entry = cur_entry;
- next_entry = &(cur_entry->next);
-
- next_cmd = &(cur_entry->command_list);
-
- menu->size++;
- }
- else if (! cur_entry)
- {
- /* Run the command if possible. */
- if (cmd->flags & GRUB_COMMAND_FLAG_MENU)
- {
- grub_command_execute (cmdline);
- grub_print_error ();
- grub_errno = GRUB_ERR_NONE;
- }
- else
- {
- grub_printf ("Invalid command `%s' is ignored.\n", cmdline);
- continue;
- }
- }
- else
- {
- cur_cmd = (grub_command_list_t) grub_malloc (sizeof (*cur_cmd));
- if (! cur_cmd)
- goto fail;
-
- cur_cmd->command = grub_strdup (cmdline);
- if (! cur_cmd->command)
- {
- grub_free (cur_cmd);
- goto fail;
- }
-
- cur_cmd->next = 0;
-
- *next_cmd = cur_cmd;
- next_cmd = &(cur_cmd->next);
-
- cur_entry->num++;
- }
- }
-
- fail:
-
- grub_file_close (file);
-
- /* If no entry was found or any error occurred, return NULL. */
- if (menu->size == 0 || grub_errno != GRUB_ERR_NONE)
- {
- free_menu (menu);
- return 0;
- }
-
- /* Check values of the default entry and the fallback one. */
- if (menu->fallback_entry >= menu->size)
- menu->fallback_entry = -1;
-
- if (menu->default_entry < 0 || menu->default_entry >= menu->size)
- {
- if (menu->fallback_entry < 0)
- menu->default_entry = 0;
- else
- {
- menu->default_entry = menu->fallback_entry;
- menu->fallback_entry = -1;
- }
- }
-
- return menu;
-}
-
/* This starts the normal mode. */
void
grub_enter_normal_mode (const char *config)
@@ -285,22 +75,32 @@
PACKAGE_VERSION);
}
+struct grub_menu pre_menu=
+ {
+ .size=0,
+ .default_entry = 0,
+ .fallback_entry = -1,
+ .timeout = -1,
+ .entry_list = 0,
+ };
+
+grub_menu_t menu = &pre_menu;
+
/* Read the config file CONFIG and execute the menu interface or
the command-line interface. */
void
grub_normal_execute (const char *config, int nested)
{
- grub_menu_t menu = 0;
if (config)
{
- menu = read_config_file (config);
+ script_exec_file (config,0,0);
/* Ignore any error. */
grub_errno = GRUB_ERR_NONE;
}
- if (menu)
+ if (menu->size)
grub_menu_run (menu, nested);
else
grub_cmdline_run (nested);
diff -b -B -r -u -E -N -x '*~' -x '*.d' -x 'config*' -x kernel_syms.lst
-x Makefile -x stamp-h -x symlist.c -x output.0 -x requests -x traces.0
-x '*.mk' -x cpu -x machine -x Entries --expand-tabs grub2/normal/menu.c
grub2ch/normal/menu.c
--- grub2/normal/menu.c 2005-01-22 14:29:18.000000000 +0100
+++ grub2ch/normal/menu.c 2005-01-29 17:07:57.000000000 +0100
@@ -23,6 +23,7 @@
#include <grub/loader.h>
#include <grub/mm.h>
#include <grub/machine/time.h>
+#include <grub/script.h>
/* FIXME: These below are all runaround. */
@@ -378,35 +379,7 @@
static void
run_menu_entry (grub_menu_entry_t entry)
{
- grub_command_list_t cl;
-
- for (cl = entry->command_list; cl != 0; cl = cl->next)
- {
- grub_command_t c;
-
- if (cl->command[0] == '\0')
- /* Ignore an empty command line. */
- continue;
-
- c = grub_command_find (cl->command);
- if (! c)
- break;
-
- if (! (c->flags & GRUB_COMMAND_FLAG_CMDLINE))
- {
- grub_error (GRUB_ERR_INVALID_COMMAND,
- "invalid command `%s'",
- cl->command);
- break;
- }
-
- if (! (c->flags & GRUB_COMMAND_FLAG_NO_ECHO))
- grub_printf ("%s\n", cl->command);
-
- if (grub_command_execute (cl->command) != 0)
- break;
- }
-
+ script_list_execute(entry,0,0);
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
/* Implicit execution of boot, only if something is loaded. */
grub_command_execute ("boot");
diff -b -B -r -u -E -N -x '*~' -x '*.d' -x 'config*' -x kernel_syms.lst
-x Makefile -x stamp-h -x symlist.c -x output.0 -x requests -x traces.0
-x '*.mk' -x cpu -x machine -x Entries --expand-tabs
grub2/normal/script.c grub2ch/normal/script.c
--- grub2/normal/script.c 1970-01-01 01:00:00.000000000 +0100
+++ grub2ch/normal/script.c 2005-01-30 19:01:35.000000000 +0100
@@ -0,0 +1,2539 @@
+/* script.c - scripting engine */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2005 Vladimir Serbinenko <address@hidden>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/env.h>
+#include <grub/script.h>
+#include <grub/file.h>
+
+/*TODO:
+alpha:
+cond expr [[ ... ]], [...]
+
+beta:
+line numbers
+select,case
+local, func args and script file parameters
+expansions:
+ ${..:..},...
+ pathname
+built-in coms
+built-in vars
+``,$()
+
+gamma:
+**
+pipes
+subshell,(list)
+$'...' $"..."
+arr[*] address@hidden
+redirecting
+*/
+
+struct grub_menu funcs={.default_entry=0,.fallback_entry=0,.timeout=0,
//dummy values
+.size=0,
+.entry_list=0 //empty list
+ };
+
+char*
+script_dupstr(char*what)
+{
+ char*rtval=grub_malloc(grub_strlen(what)+1);
+ grub_memcpy(rtval,what,grub_strlen(what)+1);
+ return rtval;
+}
+
+static char*
+script_strchr_real(char*str,char c,int rr)
+{
+ char*expcur,*rtval=0;
+ for(expcur=str;*expcur;expcur++)
+ {
+ if(*expcur==c)
+ {
+ rtval=expcur;
+ if(!rr)
+ return rtval;
+ }
+ if(*expcur=='\\')
+ {
+ expcur+=2;
+ continue;
+ }
+ if(*expcur=='(')
+ {
+ expcur+=script_find_pas('(',')',expcur);
+ continue;
+ }
+ if(*expcur=='{')
+ {
+ expcur+=script_find_pas('{','}',expcur);
+ continue;
+ }
+ if(*expcur=='[')
+ {
+ expcur+=script_find_pas('[',']',expcur);
+ continue;
+ }
+ if(*expcur=='"' || *expcur=='\'')
+ {
+ expcur+=script_get_strend(expcur);
+ continue;
+ }
+ }
+ return rtval;
+}
+
+char*
+script_strrchr(char*str,char c)
+{
+ return script_strchr_real(str,c,1);
+}
+
+char*
+script_strchr(char*str,char c)
+{
+ return script_strchr_real(str,c,0);
+}
+
+char*
+script_env_get(char*nm)
+{
+ char*rtval;
+ if(script_strrchr(nm,'['))
+ {
+ char*eptr=script_strrchr(nm,'[');
+ char*ptr=eptr+1;
+ ptr+=script_find_pas('[',']',ptr);
+ char c=*ptr,c2=*eptr;
+ *ptr=0;
+ *eptr=0;
+ enum vartype vtp;
+ char*tm=script_eval_arith(script_expand_dollar(eptr+1),&vtp);
+
rtval=script_get_arrayelem(script_env_get(nm),script_get_str(tm,vtp));
+ *ptr=c;
+ *eptr=c2;
+ }
+ else
+ rtval=grub_env_get(nm);
+ if(!rtval)
+ {
+ rtval=grub_malloc(3);
+ *rtval=0;
+ }
+ return rtval;
+}
+
+int
+script_get_strend(char*str)
+{
+ char c=str[0];int i;
+ for(i=1;str[i]!=c && str[i];i++)
+ if(str[i]=='\\')
+ i++;
+ return i;
+}
+
+/*Finds closing brace corresponding to specificied opening.
+str must point to the first character after opening brace.
+cbeg and cend must contain opening and closing brace respectivelly('('
and ')' or '{' and '}')
+Return vale is so that str+value points to closing brace */
+
+int
+script_find_pas(char cbeg,char cend,char *str)
+{
+ int op=1,i;
+ for(i=0;op&&str[i];i++)
+ {
+ if(str[i]=='\\')
+ {
+ i+=2;
+ continue;
+ }
+ if(str[i]=='"' || str[i]=='\'')
+ {
+ i+=script_get_strend(str+i);
+ continue;
+ }
+ if(str[i]==cbeg)op++;
+ if(str[i]==cend)op--;
+ }
+ return op?i:i-1;
+}
+void
+script_env_unset(char*nm)
+{
+ if(script_strrchr(nm,'['))
+ {
+ char*eptr=script_strrchr(nm,'[');
+ char*ptr=eptr+1;
+ ptr+=script_find_pas('[',']',ptr);
+ char c=*ptr,c2=*eptr;
+ *ptr=0;
+ *eptr=0;
+ char*arr=script_env_get(nm);
+ if(!arr)
+ return;
+ enum vartype vtp;
+ char*tm=script_eval_arith(script_expand_dollar(eptr+1),&vtp);
+ script_del_arrayelem(&arr,script_get_str(tm,vtp));
+ grub_env_set(nm,arr);
+ *ptr=c;
+ *eptr=c2;
+ return ;
+ }
+ grub_env_unset(nm);
+}
+
+void
+script_env_set(char*nm,char*val)
+{
+ if(script_strrchr(nm,'['))
+ {
+ char*eptr=script_strrchr(nm,'[');
+ char*ptr=eptr+1;
+ ptr+=script_find_pas('[',']',ptr);
+ char c=*ptr,c2=*eptr;
+ *ptr=0;
+ *eptr=0;
+ char*arr=script_env_get(nm);
+ if(!arr)
+ {
+ arr=grub_malloc(3);
+ arr[0]=0;
+ }
+ else
+ arr=script_dupstr(arr);
+ enum vartype vtp;
+ char*tm=script_eval_arith(script_expand_dollar(eptr+1),&vtp);
+ script_add_arrayelem(&arr,script_get_str(tm,vtp),script_dupstr(val));
+ grub_env_set(nm,arr);
+ *ptr=c;
+ *eptr=c2;
+ return ;
+ }
+ grub_env_set(nm,val);
+}
+
+char*
+script_get_str(char*var,enum vartype tp)
+{
+ char*rtval;
+ switch(tp)
+ {
+ case SCRIPT_STR:
+ if(var)
+ return var;
+ rtval=grub_malloc(3);
+ *rtval=0;
+ return rtval;
+ case SCRIPT_VAR_NAME:
+ {
+ char*tmp;
+ tmp=script_env_get(var);
+ grub_free(var);
+ if(!tmp)
+ {
+ rtval=grub_malloc(sizeof(char));
+ rtval[0]=0;
+ return rtval;
+ }
+ rtval=grub_malloc(sizeof(char)*(grub_strlen(tmp)+1));
+ grub_memcpy(rtval,tmp,sizeof(char)*(grub_strlen(tmp)+1));
+ return rtval;
+ }
+ }
+ return 0;
+}
+
+int
+grub_strtol(char*exp,char**end,int base)
+{
+ while(grub_isspace(*exp))
+ exp++;
+ if(*exp=='-')
+ return -grub_strtoul(exp+1,end,base);
+ else
+ return grub_strtoul(exp,end,base);
+}
+
+int
+script_strtol(char*str)
+{
+ /*TODO: base#*/
+ char*end;
+
+ int rtval=grub_strtol(str,&end,0);
+ grub_free(str);
+ return rtval;
+}
+
+char*
+script_ltostr(int vl){
+ char *s=grub_malloc(12*sizeof(char)),*t=s;
+ if(vl<0)
+ *(t++)='-',vl=-vl;
+ grub_sprintf(t,"%d",vl);
+ return s;
+}
+
+char*
+script_getnum(char**exp)
+{
+ return script_ltostr(grub_strtol(*exp,exp,0));
+}
+
+/*operator {}*/
+char*
+script_char_str(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ int n=script_strtol(b);
+ char *rtval=grub_malloc(3*sizeof(char));
+ rtval[1]=0;
+ rtval[0]=(n<0 || grub_strlen(a)>=(unsigned)n)?0:a[n];
+ return rtval;
+}
+
+int
+script_get_bool(char*a)
+{
+ int rtval=a && (grub_isdigit(a[0]) || (a[0]!='-' &&
!grub_isdigit(a[1]))) && grub_strcmp(a,"0")
+ && grub_strcmp(a,"-0");
+ grub_free(a);
+ return rtval;
+}
+
+/*Operator !*/
+char*
+script_bool_not(char*a,char*b __attribute__ ((unused)),int opn
__attribute__ ((unused)))
+{
+ char *rtval=grub_malloc(3*sizeof(char));
+ rtval[1]=0;
+ if(!script_get_bool(a))
+ rtval[0]='1';
+ else
+ rtval[0]='0';
+ return rtval;
+}
+
+/*Operator ~*/
+char*
+script_bin_not(char*a,char*b __attribute__ ((unused)),int opn
__attribute__ ((unused)))
+{
+ return script_ltostr(!script_strtol(a));
+}
+
+/*Unary -*/
+char*
+script_neg(char*a,char*b __attribute__ ((unused)),int opn __attribute__
((unused)))
+{
+ return script_ltostr(-script_strtol(a));
+}
+/*Unary +*/
+char*
+script_pos(char*a,char*b __attribute__ ((unused)),int opn __attribute__
((unused)))
+{
+ return script_ltostr(-script_strtol(a));
+}
+
+/*Binary +*/
+char*
+script_add(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ return script_ltostr(script_strtol(a)+script_strtol(b));
+}
+
+/*Binary +*/
+char*
+script_sub(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ return script_ltostr(script_strtol(a)-script_strtol(b));
+}
+
+/*Binary **/
+char*
+script_mult(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ return script_ltostr(script_strtol(a)*script_strtol(b));
+}
+
+/*Binary /*/
+char*
+script_div(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ return script_ltostr(script_strtol(a)/script_strtol(b));
+}
+
+/*Binary %*/
+char*
+script_mod(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ return script_ltostr(script_strtol(a)%script_strtol(b));
+}
+
+/*Binary <<*/
+char*
+script_binl(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ return script_ltostr(script_strtol(a)<<script_strtol(b));
+}
+
+/*Binary >>*/
+char*
+script_binr(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ return script_ltostr(script_strtol(a)>>script_strtol(b));
+}
+
+/*Operators >, <, <=, >=*/
+char*
+script_cmpop(char*a,char*b,int opn)
+{
+ char*rtval=grub_malloc(3*sizeof(char));
+ int cmpval=grub_strcmp(a,b);
+ if(script_opers[opn].seq[1]=='=' && cmpval==0)
+ {
+ rtval[0]='1';
+ return rtval;
+ }
+ if(script_opers[opn].seq[0]=='<')
+ rtval[0]=(cmpval<0)?'1':'0';
+ else
+ rtval[0]=(cmpval>0)?'1':'0';
+ return rtval;
+}
+
+/*Operators !=,==,<>*/
+char*
+script_eqop(char*a,char*b,int opn)
+{
+ int cnt=1;
+ char*rtval=grub_malloc(3*sizeof(char));
+ rtval[1]=0;
+ if(cnt && grub_strcmp(a,b)!=0)
+ cnt=0;
+ if(script_opers[opn].seq[0]=='!' || script_opers[opn].seq[0]=='<')
+ cnt=!cnt;
+ rtval[0]=cnt?'1':'0';
+ return rtval;
+}
+
+/*Binary ^*/
+char*
+script_bxor(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ return script_ltostr(script_strtol(a)^script_strtol(b));
+}
+/*Binary |*/
+char*
+script_bor(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ return script_ltostr(script_strtol(a)|script_strtol(b));
+}
+
+/*Binary &*/
+char*
+script_band(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ return script_ltostr(script_strtol(a)&script_strtol(b));
+}
+
+/*logic xor*/
+char*
+script_logicxor(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ char *rtval=grub_malloc(3*sizeof(char));
+ rtval[1]=0;
+ if(script_get_bool(a)!=script_get_bool(b))
+ rtval[0]='1';
+ else
+ rtval[0]='0';
+ return rtval;
+}
+
+/*Operator ,*/
+char*
+script_comma(char*a __attribute__ ((unused)),char*b,
+ int opn __attribute__ ((unused)))
+{
+ return b;
+}
+
+/*Operator =*/
+char*
+script_set(char*a, char*b,int opn __attribute__ ((unused)))
+{
+ script_env_set(a,b);
+ return a;
+}
+
+/*Operators ...=*/
+char*
+script_setop(char*a, char*b,int opn)
+{
+ char tm[3]={0,0,0};
+ char*val=script_dupstr(a);
+ tm[0]=script_opers[opn].seq[0];
+ if(script_opers[opn].seq[1]!='=')
+ tm[1]=script_opers[opn].seq[1];
+ int op=script_find_oper(tm,0);
+
script_env_set(a,script_opers[op].func_do(script_get_str(val,SCRIPT_VAR_NAME),b,op));
+ return a;
+}
+
+/*Operator .*/
+char*
+script_concat(char*a,char*b,int opn __attribute__ ((unused)))
+{
+ grub_realloc(a,grub_strlen(a)+grub_strlen(b));
+ grub_memcpy(a+grub_strlen(a),b,grub_strlen(b)+1);
+ grub_free(b);
+ return a;
+}
+static char*
+script_incl(char*a,char*b __attribute__((unused)),int op
__attribute__((unused)))
+{
+ int intval;
+ char*val=script_dupstr(a);
+
script_env_set(val,script_ltostr((intval=script_strtol(script_get_str(a,SCRIPT_VAR_NAME)))+1));
+ grub_free(val);
+ return script_ltostr(intval+1);
+}
+static char*
+script_decl(char*a,char*b __attribute__((unused)),int op
__attribute__((unused)))
+{
+ int intval;
+ char*val=script_dupstr(a);
+
script_env_set(val,script_ltostr((intval=script_strtol(script_get_str(a,SCRIPT_VAR_NAME)))-1));
+ grub_free(val);
+ return script_ltostr(intval-1);
+}
+static char*
+script_incr(char*a,char*b __attribute__((unused)),int op
__attribute__((unused)))
+{
+ int intval;
+ char*val=script_dupstr(a);
+
script_env_set(val,script_ltostr((intval=script_strtol(script_get_str(a,SCRIPT_VAR_NAME)))+1));
+ grub_free(val);
+ return script_ltostr(intval);
+}
+static char*
+script_decr(char*a,char*b __attribute__((unused)),int op
__attribute__((unused)))
+{
+ int intval;
+ char*val=script_dupstr(a);
+
script_env_set(val,script_ltostr((intval=script_strtol(script_get_str(a,SCRIPT_VAR_NAME)))-1));
+ grub_free(val);
+ return script_ltostr(intval);
+}
+/*Array of possible operators*/
+struct script_oper script_opers[]={
+//{.priority=190, .seq="[", .func_do=script_elemarray,
.type=SCRIPT_BRACK|SCRIPT_LVALUE},
+{.priority=190, .seq="{", .func_do=script_char_str, .type=SCRIPT_BRACK},
+{.priority=180, .seq="!", .func_do=script_bool_not,
.type=SCRIPT_LEFT|SCRIPT_RASSOC},
+{.priority=180, .seq="~", .func_do=script_bin_not,
.type=SCRIPT_LEFT|SCRIPT_RASSOC},
+{.priority=180, .seq="++", .func_do=script_incl,
.type=SCRIPT_LEFT|SCRIPT_NEEDLVALUEA|SCRIPT_RASSOC},
+{.priority=180, .seq="++", .func_do=script_incr,
.type=SCRIPT_RIGHT|SCRIPT_NEEDLVALUEA},
+{.priority=180, .seq="--", .func_do=script_decl,
.type=SCRIPT_LEFT|SCRIPT_NEEDLVALUEA|SCRIPT_RASSOC},
+{.priority=180, .seq="--", .func_do=script_decr,
.type=SCRIPT_RIGHT|SCRIPT_NEEDLVALUEA},
+{.priority=180, .seq="-", .func_do=script_neg,
.type=SCRIPT_LEFT|SCRIPT_RASSOC},
+{.priority=180, .seq="+", .func_do=script_pos,
.type=SCRIPT_LEFT|SCRIPT_RASSOC},
+{.priority=170, .seq="*", .func_do=script_mult, .type=SCRIPT_BIN},
+{.priority=170, .seq="/", .func_do=script_div, .type=SCRIPT_BIN},
+{.priority=170, .seq="%", .func_do=script_mod, .type=SCRIPT_BIN},
+{.priority=160, .seq="+", .func_do=script_add, .type=SCRIPT_BIN},
+{.priority=160, .seq="-", .func_do=script_sub, .type=SCRIPT_BIN},
+{.priority=160, .seq=".", .func_do=script_concat, .type=SCRIPT_BIN},
+{.priority=150, .seq=">>", .func_do=script_binr, .type=SCRIPT_BIN},
+{.priority=150, .seq="<<", .func_do=script_binl, .type=SCRIPT_BIN},
+{.priority=140, .seq="<=", .func_do=script_cmpop, .type=SCRIPT_BIN},
+{.priority=140, .seq="<", .func_do=script_cmpop, .type=SCRIPT_BIN},
+{.priority=140, .seq=">=", .func_do=script_cmpop, .type=SCRIPT_BIN},
+{.priority=140, .seq=">", .func_do=script_cmpop, .type=SCRIPT_BIN},
+{.priority=130, .seq="==", .func_do=script_eqop, .type=SCRIPT_BIN},
+{.priority=130, .seq="!=", .func_do=script_eqop, .type=SCRIPT_BIN},
+{.priority=130, .seq="<>", .func_do=script_eqop, .type=SCRIPT_BIN},
+{.priority=120, .seq="&", .func_do=script_band, .type=SCRIPT_BIN},
+{.priority=110, .seq="^", .func_do=script_bxor, .type=SCRIPT_BIN},
+{.priority=100, .seq="|", .func_do=script_bor, .type=SCRIPT_BIN},
+{.priority=90, .seq="&&", .func_do=0, .type=SCRIPT_AND},
+{.priority=80, .seq="||", .func_do=0, .type=SCRIPT_OR},
+{.priority=70, .seq="?", .func_do=0, .type=SCRIPT_TERN},//? :
+{.priority=60, .seq="=", .func_do=script_set,
.type=SCRIPT_BIN|SCRIPT_NEEDLVALUEA|SCRIPT_LVALUE},
+{.priority=60, .seq="+=", .func_do=script_setop,
.type=SCRIPT_BIN|SCRIPT_NEEDLVALUEA|SCRIPT_LVALUE},
+{.priority=60, .seq="-=", .func_do=script_setop,
.type=SCRIPT_BIN|SCRIPT_NEEDLVALUEA|SCRIPT_LVALUE},
+{.priority=60, .seq="*=", .func_do=script_setop,
.type=SCRIPT_BIN|SCRIPT_NEEDLVALUEA|SCRIPT_LVALUE},
+{.priority=60, .seq="/=", .func_do=script_setop,
.type=SCRIPT_BIN|SCRIPT_NEEDLVALUEA|SCRIPT_LVALUE},
+{.priority=60, .seq="%=", .func_do=script_setop,
.type=SCRIPT_BIN|SCRIPT_NEEDLVALUEA|SCRIPT_LVALUE},
+{.priority=60, .seq="&=", .func_do=script_setop,
.type=SCRIPT_BIN|SCRIPT_NEEDLVALUEA|SCRIPT_LVALUE},
+{.priority=60, .seq="^=", .func_do=script_setop,
.type=SCRIPT_BIN|SCRIPT_NEEDLVALUEA|SCRIPT_LVALUE},
+{.priority=60, .seq="|=", .func_do=script_setop,
.type=SCRIPT_BIN|SCRIPT_NEEDLVALUEA|SCRIPT_LVALUE},
+{.priority=60, .seq=">>=", .func_do=script_setop,
.type=SCRIPT_BIN|SCRIPT_NEEDLVALUEA|SCRIPT_LVALUE},
+{.priority=60, .seq="<<=", .func_do=script_setop,
.type=SCRIPT_BIN|SCRIPT_NEEDLVALUEA|SCRIPT_LVALUE},
+{.priority=60, .seq=".=", .func_do=script_setop,
.type=SCRIPT_BIN|SCRIPT_NEEDLVALUEA|SCRIPT_LVALUE},
+{.priority=40, .seq="and", .func_do=0, .type=SCRIPT_AND},
+{.priority=30, .seq="xor", .func_do=script_logicxor, .type=SCRIPT_BIN},
+{.priority=20, .seq="or", .func_do=0, .type=SCRIPT_OR},
+{.priority=10, .seq=",", .func_do=script_comma, .type=SCRIPT_BIN},
+};
+
+int
+script_islexend(char c)
+{
+ return !(c &&(grub_isalpha(c) ||grub_isdigit(c) ||c=='_'));
+}
+
+int
+script_isfuncbeg(char*str)
+{
+ while(*str && grub_isspace(*str))str++;
+ if(!*str)
+ return 0;
+ if(!grub_memcmp(str,"function",sizeof("function")-1) &&
script_islexend(str[sizeof("function")-1]))
+ return 1;
+ if(!grub_memcmp(str,"entry",sizeof("entry")-1) &&
script_islexend(str[sizeof("entry")-1]))
+ return 1;
+ while(*str && !script_islexend(*str))str++;
+ if(!*str)
+ return 0;
+ if(*str!='(')
+ return 0;
+ str++;
+ if(!*str)
+ return 0;
+ while(*str && grub_isspace(*str))str++;
+ if(!*str)
+ return 0;
+ if(*str!=')')
+ return 0;
+ return 1;
+}
+void
+script_skipfuncbeg(char**exp)
+{
+ while(**exp && grub_isspace(**exp))(*exp)++;
+ if(!grub_memcmp(*exp,"entry",sizeof("entry")-1) &&
script_islexend((*exp)[sizeof("entry")-1]))
+ *exp+=sizeof("entry")-1;
+ if(!grub_memcmp(*exp,"function",sizeof("function")-1) &&
script_islexend((*exp)[sizeof("function")-1]))
+ *exp+=sizeof("function")-1;
+ switch(**exp)
+ {
+ case '"':
+ case '\'':
+ *exp+=script_get_strend(*exp)+1;
+ break;
+ default:
+ while(!script_islexend(**exp))
+ (*exp)++;
+ }
+ while(grub_isspace(**exp))(*exp)++;
+ if(**exp=='(')(*exp)++;//skip (
+ while(grub_isspace(**exp))(*exp)++;
+ if(**exp==')')(*exp)++;//skip )
+}
+
+
+int
+script_find_oper(char*exp,int searchleft)
+{
+ unsigned i, lenfound=0;int foundn=-1;
+ for(i=0;i<sizeof(script_opers)/sizeof(script_opers[0]);i++)
+ if(grub_strlen(script_opers[i].seq)>lenfound &&
+
((searchleft==((script_opers[i].type&SCRIPT_ARGPART)==SCRIPT_LEFT)) ||
(searchleft==2))
+ &&
!grub_memcmp(script_opers[i].seq,exp,grub_strlen(script_opers[i].seq))
+
&&(script_islexend(exp[grub_strlen(script_opers[i].seq)-1]
+ ||script_islexend(exp[grub_strlen(script_opers[i].seq)]))))
+
foundn=i,lenfound=grub_strlen(script_opers[i].seq);
+ return foundn;
+}
+
+char*
+script_list_arrayelems(char**elem)
+{
+ char*indxbeg,*indxend;
+ if(!**elem)
+ return 0;
+ while(grub_isspace(**elem))(*elem)++;
+ if(**elem!='[')
+ return 0;
+ (*elem)++;
+ if(**elem!='\'')
+ return 0;
+ indxbeg=*elem+1;
+ *elem+=script_get_strend(*elem);
+ indxend=*elem;
+ (*elem)++;
+ if(**elem!=']')
+ return 0;
+ (*elem)++;
+ if(**elem!='=')
+ return 0;
+ (*elem)++;
+ if(**elem!='\'')
+ return 0;
+ *elem+=script_get_strend(*elem);
+ (*elem)++;
+ char*rtval=grub_malloc(indxend-indxbeg+1);
+ grub_memcpy(rtval,indxbeg,indxend-indxbeg);
+ rtval[indxend-indxbeg]=0;
+ return rtval;
+}
+char*
+script_get_arrayelem(char*elem,char*indx)
+{
+ char*escindx=script_escape_string(indx);
+ grub_free(indx);
+ char*indxbeg,*indxend;
+ char*valbeg=0,*valend=0;
+ while(1)
+ {
+ if(!*elem)
+ return 0;
+ while(grub_isspace(*elem))elem++;
+ if(*elem!='[')
+ return 0;
+ elem++;
+ if(*elem!='\'')
+ return 0;
+ indxbeg=elem+1;
+ elem+=script_get_strend(elem);
+ indxend=elem;
+ elem++;
+ if(*elem!=']')
+ return 0;
+ elem++;
+ if(*elem!='=')
+ return 0;
+ elem++;
+ if(*elem!='\'')
+ return 0;
+ valbeg=elem+1;
+ elem+=script_get_strend(elem);
+ valend=elem;
+ elem++;
+ if((unsigned)(indxend-indxbeg)==grub_strlen(escindx) &&
!grub_memcmp(indxbeg,escindx,indxend-indxbeg))
+ {
+ char*rtval=grub_malloc(valend-valbeg+1);
+ grub_memcpy(rtval,valbeg,valend-valbeg);
+ rtval[valend-valbeg]=0;
+ script_unescape(rtval);
+ return rtval;
+ }
+ }
+}
+#define STR_BUFFER 256
+char*
+script_escape_string(char*str)
+{
+ char*res=grub_malloc(STR_BUFFER),*rptr=res;
+ char*ptr=str;
+ while(*ptr)
+ {
+ if((rptr-res+2)%STR_BUFFER==0)
+ {
+ int delta=rptr-res;
+ res=grub_realloc(res,rptr-res+2+STR_BUFFER);
+ rptr=res+delta;
+ }
+ if(*ptr=='\'' || *ptr=='\\')
+ *(rptr++)='\\';
+ *(rptr++)=*(ptr++);
+ }
+ *(rptr++)=*(ptr++);
+ return res;
+}
+void
+script_del_arrayelem(char**arr,char*indx)
+{
+ char*escindx=script_escape_string(indx);
+ grub_free(indx);
+ char*arptr=*arr;
+ char*prevarptr=*arr;
+ char*curindx;
+ int wfnd=0;
+ while(*arptr)
+ {
+ prevarptr=arptr;
+ curindx=script_list_arrayelems(&arptr);
+ if(!curindx)
+ break;
+ if(!grub_strcmp(escindx,curindx))
+ {
+ grub_free(curindx);
+ wfnd=1;
+ break;
+ }
+ grub_free(curindx);
+ }
+ if(wfnd)
+ while(*arptr)
+ *(prevarptr++)=*(arptr++);
+ else
+ prevarptr=arptr;
+ int delta=prevarptr-*arr;
+ *arr=grub_realloc(*arr,delta+1);
+ (*arr)[delta]=0;
+}
+void
+script_add_arrayelem(char**arr,char*indx,char*val)
+{
+ char*escval=script_escape_string(val);
+ char*escindx=script_escape_string(indx);
+ grub_free(indx);
+ grub_free(val);
+ char*arptr=*arr;
+ char*prevarptr=*arr;
+ char*curindx;
+ int wfnd=0;
+ while(*arptr)
+ {
+ prevarptr=arptr;
+ curindx=script_list_arrayelems(&arptr);
+ if(!curindx)
+ break;
+ if(!grub_strcmp(escindx,curindx))
+ {
+ grub_free(curindx);
+ wfnd=1;
+ break;
+ }
+ grub_free(curindx);
+ }
+ if(wfnd)
+ while(*arptr)
+ *(prevarptr++)=*(arptr++);
+ else
+ prevarptr=arptr;
+ int delta=prevarptr-*arr;
+
*arr=grub_realloc(*arr,delta+grub_strlen(escindx)+grub_strlen(escval)+9);
+ char*ptr=*arr+delta;
+ ptr[0]=' ';
+ ptr[1]='[';
+ ptr[2]='\'';
+ ptr+=3;
+ grub_memcpy(ptr,escindx,grub_strlen(escindx));
+ ptr+=grub_strlen(escindx);
+ ptr[0]='\'';
+ ptr[1]=']';
+ ptr[2]='=';
+ ptr[3]='\'';
+ ptr+=4;
+ grub_memcpy(ptr,escval,grub_strlen(escval));
+ ptr+=grub_strlen(escval);
+ ptr[0]='\'';
+ ptr[1]=0;
+}
+
+void
+script_unescape(char*str)
+{
+ char*to=str,*from=str;
+ while(*from)
+ {
+ if(*to=='\\')
+ {
+ from++;
+ switch(*(from++))
+ {
+ case 'n':
+ *(to++)='\n';
+ break;
+ case 'r':
+ *(to++)='\r';
+ break;
+ case 't':
+ *(to++)='\t';
+ break;
+ case 'x':
+ *(to++)=grub_strtoul(from,&from,16);
+ break;
+ default:
+ if(*(from-1)>='0' && *(from-1)<='7')
+ {
+ *(to++)=grub_strtoul(from-1,&from,16);
+ break;
+ }
+ *(to++)=*(from-1);
+ }
+ }
+ *(to++)=*(from++);
+ }
+ *to=0;
+}
+
+char*
+script_get_singlestring(char**exp)
+{
+ char*rtval=grub_malloc(STR_BUFFER);
+ int j;
+ for(j=0;**exp!='\'' && **exp;(*exp)++)
+ {
+ if((j+1)%STR_BUFFER==0)
+ rtval=grub_realloc(rtval,j+1+STR_BUFFER);
+ if(**exp=='\\')
+ {
+ switch(*((*exp)++))
+ {
+ case '\n':
+ break;
+ case '\'':
+ case '\\':
+ rtval[j++]=**exp;
+ break;
+ default:
+ rtval[j++]='\\';
+ rtval[j++]=**exp;
+ }
+ }
+ else
+ rtval[j++]=**exp;
+ }
+ rtval[j]=0;
+ (*exp)++;
+ return rtval;
+}
+
+char*
+script_get_doublestring(char**exp)
+{
+ char*rtval=grub_malloc(STR_BUFFER);
+ int j;char *end;
+ for(j=0;**exp!='"' && **exp!=0;(*exp)++,j++)
+ {
+ if((j+1)%STR_BUFFER==0)
+ rtval=grub_realloc(rtval,j+1+STR_BUFFER);
+ if(**exp=='\\')
+ {
+ switch(*(*exp+1))
+ {
+ case '\n':
+ j--;
+ break;
+ case 'n':
+ rtval[j]='\n';
+ break;
+ case 'r':
+ rtval[j]='\r';
+ break;
+ case 'x':
+ rtval[j]=grub_strtoul(*exp+2,&end,16);
+ *exp=end-2;
+ break;
+ case 't':
+ rtval[j]='\t';
+ break;
+ case '\'':
+ case '\\':
+ case '"':
+ case '$':
+ rtval[j]=*(*exp+1);
+ break;
+ default:
+ if(*(*exp+1)>='0' && *(*exp+1)<='7')
+ {
+ rtval[j]=grub_strtoul(*exp+1,&end,8);
+ *exp=end-2;
+ }
+ else
+ {
+ rtval[j]='\\';
+ (*exp)--;
+ }
+ }
+ (*exp)++;
+ }
+ else
+ rtval[j]=**exp;
+ }
+ rtval[j]=0;
+ (*exp)++;
+ return rtval;
+}
+#if 0 //Some problems with GRUB device notation
+char*
+script_get_array(char*exp,char**cont,int contcnt)
+{
+ char*rtval=grub_malloc(3);
+ rtval[0]=0;
+ int ptr=0;
+ char*expcur=script_dupstr(exp);
+ char*exp0;
+ int maxindx=-1;
+ void arr_putc(char c)
+ {
+ if((ptr+2)%STR_BUFFER==0)
+ rtval=grub_realloc(rtval,(ptr+2)+STR_BUFFER);
+ rtval[ptr++]=c;
+ }
+ char**ct;
+ for(ct=cont;ct-cont<contcnt;ct++)
+ {
+ expcur=grub_realloc(expcur,grub_strlen(expcur)+grub_strlen(*ct)+1);
+ expcur[grub_strlen(expcur)+grub_strlen(*ct)]=0;
+ grub_memcpy(expcur+grub_strlen(expcur),*ct,grub_strlen(*ct));
+ }
+ exp0=expcur;
+ while(*expcur && *expcur!=')')
+ {
+ char*indx;
+ if(grub_isspace(*expcur))
+ {
+ expcur++;
+ continue;
+ }
+ if(*expcur=='[')
+ {
+ char*expend=expcur+1+script_find_pas('[',']',expcur+1);
+ char c=*expend;
+ char*end;
+ enum vartype vtp;
+ *expend=0;
+ char*tm=script_eval_arith(expcur+1,&vtp);
+ indx=script_get_str(tm,vtp);
+ char *t=indx;
+ int z=-1;
+ while(*t && grub_isdigit(*t))t++;
+ if(!*t)
+ z=grub_strtoul(indx,&end,0);
+ if(z>maxindx)
+ maxindx=z;
+ *expend=c;
+ expcur=expend+1;
+ while(grub_isspace(*expcur))expcur++;
+ expcur++;
+ }
+ else
+ indx=script_ltostr(++maxindx);
+ while(grub_isspace(*expcur))
+ expcur++;
+ {
+ char *expbeg=expcur;
+ int brack=0;
+ while((!grub_isspace(*expcur)&&*expcur!=')') || brack!=0)
+ {
+ if(*expcur=='\\')
+ {
+ expcur+=2;
+ continue;
+ }
+ if(*expcur=='(' || *expcur=='[' || *expcur=='{')
+ brack++;
+ if(*expcur==')' || *expcur==']' || *expcur=='}')
+ brack--;
+ if(*expcur=='"' || *expcur=='\'')
+ expcur+=script_get_strend(expcur);
+ expcur++;
+ }
+ char*expcpy=grub_malloc(expcur-expbeg+1);
+ grub_memcpy(expcpy,expbeg,expcur-expbeg);
+ expcpy[expcur-expbeg]=0;
+ script_unescape(expcpy);
+ script_add_arrayelem(&rtval,indx,expcpy);
+ }
+ }
+ grub_free(exp0);
+ return rtval;
+}
+#endif
+char*
+script_eval_arith(char*exp,enum vartype*vtp)
+{
+ char*cur=0;
+ char*expcur=exp;
+ *vtp=SCRIPT_STR;
+ while(*expcur)
+ {
+ if(!*expcur)
+ return cur;
+ if(grub_isspace(*expcur))
+ {
+ expcur++;
+ continue;
+ }
+ int op=script_find_oper(expcur,!cur);
+ if(op!=-1)
+ {
+ int newop=0,unary;char*tern1=expcur;
+ char*expbeg;
+ expcur+=grub_strlen(script_opers[op].seq);
+ expbeg=expcur;
+ switch(script_opers[op].type&SCRIPT_ARGPART)
+ {
+ case SCRIPT_BRACK:
+
expcur+=script_find_pas(script_opers[op].seq[0],(script_opers[op].seq[0]=='['?']':'}'),expcur);
+ break;
+ case SCRIPT_RIGHT:
+ break;
+ case SCRIPT_TERN:
+ for(;*expcur;expcur++)
+ {
+ if(*expcur==':')
+ break;
+
if(grub_isalpha(*expcur)||grub_isdigit(*expcur)||*expcur=='_')
+ unary=0;
+ if(*expcur=='(')
+ expcur+=script_find_pas('(',')',expcur),unary=0;
+ if(*expcur=='{')
+ expcur+=script_find_pas('{','}',expcur),unary=0;
+ if(*expcur=='[')
+ expcur+=script_find_pas('[',']',expcur),unary=0;
+ if(*expcur=='"' || *expcur=='\'')
+ {
+ expcur+=script_get_strend(expcur),unary=0;
+ continue;
+ }
+ }
+ tern1=expcur;
+ expcur++;
+ case SCRIPT_LEFT:
+ case SCRIPT_BIN:
+ case SCRIPT_AND:
+ case SCRIPT_OR:
+ unary=1;
+ for(;*expcur;expcur++)
+ {
+ newop=script_find_oper(expcur,unary);
+ if(newop!=-1 &&!unary)
+ unary=1;
+ if(newop!=-1 &&
(script_opers[newop].priority<script_opers[op].priority ||
+
(script_opers[newop].priority==script_opers[op].priority
+ && !(script_opers[op].type&SCRIPT_RASSOC)) ) )
+ break;
+
if(grub_isalpha(*expcur)||grub_isdigit(*expcur)||*expcur=='_')
+ unary=0;
+ if(*expcur=='(')
+ {
+ expcur+=script_find_pas('(',')',expcur),unary=0;
+ continue;
+ }
+ if(*expcur=='{')
+ {
+ expcur+=script_find_pas('{','}',expcur),unary=0;
+ continue;
+ }
+ if(*expcur=='[')
+ {
+ expcur+=script_find_pas('[',']',expcur),unary=0;
+ continue;
+ }
+ if(*expcur=='"' || *expcur=='\'')
+ {
+ expcur+=script_get_strend(expcur),unary=0;
+ continue;
+ }
+ }
+ }
+ char c=*expcur;
+ *expcur=0;
+ switch(script_opers[op].type&SCRIPT_ARGPART)
+ {
+ case SCRIPT_TERN:
+ {
+ char c2;
+ int ncur=script_get_bool(script_get_str(cur,*vtp));
+ if(ncur)
+ {
+ c2=*tern1;
+ *tern1=0;
+ cur=script_eval_arith(expbeg,vtp);
+ *tern1=c2;
+ }
+ else
+ cur=script_eval_arith(tern1+1,vtp);
+ }
+ break;
+ case SCRIPT_OR:
+ case SCRIPT_AND:
+ {
+ int ncur=script_get_bool(script_get_str(cur,*vtp));
+
if(ncur==((script_opers[op].type&SCRIPT_ARGPART)==SCRIPT_AND))
+ {
+ cur=script_eval_arith(expbeg,vtp);
+ ncur=script_get_bool(script_get_str(cur,*vtp));
+ }
+ cur=script_ltostr(ncur);
+ *vtp=SCRIPT_STR;
+ }
+ break;
+ case SCRIPT_RIGHT:
+ {
+ if((script_opers[op].type&SCRIPT_NEEDLVALUEA) &&
*vtp==SCRIPT_STR)
+ {
+ grub_error(GRUB_ERR_BAD_ARGUMENT,"Error: Lvalue
needed for %s",script_opers[op].seq);
+ return 0;
+ }
+ cur=script_opers[op].func_do(
+
(script_opers[op].type&SCRIPT_NEEDLVALUEA)?cur:script_get_str(cur,*vtp),0,op);
+ }
+
*vtp=(script_opers[op].type&SCRIPT_LVALUE)?SCRIPT_VAR_NAME:SCRIPT_STR;
+ break;
+ default:
+ {
+ enum vartype rtype;
+ char*right=script_eval_arith(expbeg,&rtype);
+ if(!right)
+ {
+ grub_error(GRUB_ERR_BAD_ARGUMENT,"Error: unexpected
end of expression");
+ return 0;
+ }
+ if((script_opers[op].type&SCRIPT_ARGPART)==SCRIPT_LEFT)
+ {
+ if((script_opers[op].type&SCRIPT_NEEDLVALUEA) &&
rtype==SCRIPT_STR)
+ {
+ grub_error(GRUB_ERR_BAD_ARGUMENT,"Error: Lvalue
needed for %s",script_opers[op].seq);
+ return 0;
+ }
+ cur=script_opers[op].func_do(
+
(script_opers[op].type&SCRIPT_NEEDLVALUEA)?right:script_get_str(right,rtype),0,op);
+ }
+ else
+ {
+ if((script_opers[op].type&SCRIPT_NEEDLVALUEA) &&
*vtp==SCRIPT_STR)
+ {
+ grub_error(GRUB_ERR_BAD_ARGUMENT,"Error: Lvalue
needed for %s",script_opers[op].seq);
+ return 0;
+ }
+ cur=script_opers[op].func_do(
+
(script_opers[op].type&SCRIPT_NEEDLVALUEA)?cur:script_get_str(cur,*vtp),
+ script_get_str(right,rtype),op);
+ }
+ }
+
*vtp=(script_opers[op].type&SCRIPT_LVALUE)?SCRIPT_VAR_NAME:SCRIPT_STR;
+ break;
+ }
+ *expcur=c;
+ if((script_opers[op].type&SCRIPT_ARGPART)==SCRIPT_BRACK)
+ expcur++;
+ continue;
+ }
+ if(grub_isalpha(*expcur))
+ {
+ char*nmbeg=expcur;
+ char t;
+ while(grub_isalpha(*expcur) || grub_isdigit(*expcur) ||
*expcur=='_')
+ expcur++;
+ t=*expcur;
+ *expcur=0;
+ *vtp=SCRIPT_VAR_NAME;
+ cur=grub_malloc(expcur-nmbeg+1);
+ grub_memcpy(cur,nmbeg,expcur-nmbeg+1);
+ *expcur=t;
+ continue;
+ }
+ if(*expcur=='(')
+ {
+ expcur++;
+ char*expbeg=expcur;
+ char c;
+ expcur+=script_find_pas('(',')',expbeg);
+ c=*expcur;
+ *expcur=0;
+ cur=script_eval_arith(expbeg,vtp);
+ *expcur=c;
+ if(*expcur)
+ expcur++;
+ continue;
+ }
+ if(*expcur=='[')
+ {
+ expcur++;
+ char*expbeg=expcur;
+ char c;
+ char *indx;
+ enum vartype rttype;
+ expcur+=script_find_pas('[',']',expbeg);
+ c=*expcur;
+ *expcur=0;
+ char*tm=script_eval_arith(expbeg,&rttype);
+ indx=script_escape_string(script_get_str(tm,rttype));
+ *expcur=c;
+ if(*expcur)
+ expcur++;
+ if(*vtp==SCRIPT_VAR_NAME)
+ {
+ int curlen=grub_strlen(cur),indxlen=grub_strlen(indx);
+ cur=grub_realloc(cur,curlen+indxlen+5);
+ cur[curlen]='[';
+ cur[curlen+1]='\'';
+ grub_memcpy(cur+curlen+2,indx,indxlen);
+ cur[curlen+2+indxlen]='\'';
+ cur[curlen+3+indxlen]=']';
+ cur[curlen+4+indxlen]=0;
+ }
+ continue;
+ }
+ if(grub_isdigit(*expcur))
+ {
+ cur=script_getnum(&expcur);
+ continue;
+ }
+ if(*expcur=='"')
+ {
+ expcur++;
+ cur=script_get_doublestring(&expcur);
+ *vtp=SCRIPT_STR;
+ continue;
+ }
+ if(*expcur=='\'')
+ {
+ expcur++;
+ cur=script_get_singlestring(&expcur);
+ *vtp=SCRIPT_STR;
+ continue;
+ }
+ }
+ return cur;
+}
+
+char**
+script_split_tokens(char*cmdline,int*argc,grub_err_t (* getline) (char
**),char**end)
+{
+ char *rd = (char *) cmdline;
+ char**argret=grub_malloc(sizeof(char*));
+ int wor=0,wand=0;
+ enum stat
{STAT_NORM,STAT_QUOTE,STAT_DQUOTE,STAT_DOLLAR_BRACK,STAT_DOLLAR_BRACE};
+ enum stat status=STAT_NORM;
+ int ptr=0;
+ int esc=0;
+ int brack=0;
+ int fbrack=0;
+ int wasd=0;
+ int wnw=1;//1 at the begin of word, 0 otherwise
+ /* Get one character from the commandline. If the caller reads
+ beyond the end of the string a new line will be read. This
+ function will not chech for errors, the caller has to check for
+ grub_errno. */
+ char getchar (void)
+ {
+ int c;
+
+ if (! rd)
+ {
+ if(getline)
+ getline (&rd);
+ else
+ return 0;
+ /* Error is ignored here, the caller will check for this
+ when it reads beyond the EOL. */
+ c = *(rd)++;
+ return c;
+ }
+
+ c = *(rd)++;
+ if (! c)
+ {
+ rd = 0;
+ return '\n';
+ }
+
+ return c;
+ }
+ void putchar(char c)
+ {
+ if(!wnw || !grub_isspace(c))
+ {
+ if((ptr+1)%EXPAND_BUF_SIZE==0)
+
argret[*argc]=grub_realloc(argret[*argc],ptr+1+EXPAND_BUF_SIZE);
+ (argret[*argc])[ptr++]=c;
+ }
+ wnw=0;
+ }
+ void newword()
+ {
+ if(ptr)
+ {
+ putchar(0);
+ argret=grub_realloc(argret,(*argc+2)*sizeof(char*));
+ argret[++(*argc)]=grub_malloc(EXPAND_BUF_SIZE);
+ ptr=0;
+ wnw=1;
+ }
+ }
+ *argc=0;
+ argret[0]=grub_malloc(EXPAND_BUF_SIZE);
+
+ while(1)
+ {
+ char c;
+ c=getchar();
+ if(wasd&&c=='{' && status==STAT_NORM && fbrack==-1)
+ status=STAT_DOLLAR_BRACE;
+ if(wasd&&c=='(' && status==STAT_NORM && fbrack==-1)
+ {
+ brack=0;
+ status=STAT_DOLLAR_BRACK;
+ }
+ if(c==')' && !esc && brack==1 && status==STAT_DOLLAR_BRACK)
+ {
+ status=STAT_NORM;
+ brack=0;
+ putchar(c);
+ newword();
+ continue;
+ }
+ if(c=='}' && !esc && status==STAT_DOLLAR_BRACE)
+ {
+ status=STAT_NORM;
+ brack=0;
+ putchar(c);
+ newword();
+ continue;
+ }
+ wasd=(c=='$');
+ if(wnw&&grub_isspace(c)&&c!='\n')
+ continue;
+ wnw=0;
+ if(fbrack!=-1 && fbrack!=2 && c=='(')
+ fbrack++;
+ if(c!='(' && fbrack!=2)
+ fbrack=-1;
+ if(c=='(' && (status==STAT_NORM||status==STAT_DOLLAR_BRACK))
+ brack++;
+ if(c==')' && (status==STAT_NORM ||status==STAT_DOLLAR_BRACK))
+ brack--;
+ if(!esc && status==STAT_NORM
+ && (grub_isspace(c) || c==';' || c=='<' || c=='>')
+ && !brack && fbrack==-1)
+ {
+ newword();
+ if(c==';' || c=='\n')
+ break;
+ if(!grub_isspace(c))
+ {
+ putchar(c);
+ newword();
+ }
+ continue;
+ }
+ if(!esc && (c=='#'||(c=='|'&&wor)||(c=='&'&&wand)) &&
status==STAT_NORM && fbrack==-1)
+ break;
+ if(!brack && fbrack!=-1)
+ break;
+ if(wor)
+ {
+ newword();
+ putchar('|');
+ newword();
+ wor=0;
+ }
+ if(wand)
+ {
+ newword();
+ putchar('&');
+ newword();
+ wand=0;
+ }
+ if(c=='|' && fbrack==-1)
+ {
+ wor=1;
+ continue;
+ }
+ if(c=='&'&& fbrack==-1)
+ {
+ wand=1;
+ continue;
+ }
+ if(c=='"'&&(status==STAT_NORM ||status==STAT_DQUOTE))
+ {
+ putchar(c);
+ status=STAT_DQUOTE-status;
+ continue;
+ }
+ if(c=='\''&&(status==STAT_NORM ||status==STAT_QUOTE))
+ {
+ putchar(c);
+ status=STAT_QUOTE-status;
+ continue;
+ }
+ if(c=='\\')
+ {
+ putchar(c);
+ putchar(getchar());
+ continue;
+ }
+ putchar(c);
+ }
+ if(fbrack!=-1)
+ {
+ char c;
+ while(grub_isspace(c=getchar()) && c!='\n');
+ }
+ if(end)
+ *end=rd?rd-1:0;
+ putchar(0);
+ if(ptr!=1)(*argc)++;
+ return argret;
+}
+
+char**
+script_expand_braces(char**argv,int*argc)
+{
+ char**argret=0;int argcret=0;
+ void brace_putch(struct braceset*where,char c)
+ {
+ struct braceset*cur=where;
+ while(cur)
+ {
+ if((cur->len+1)%BRACE_BUFFER==0)
+ cur->word=grub_realloc(cur->word,cur->len+1+BRACE_BUFFER);
+ cur->word[cur->len++]=c;
+ cur=cur->next;
+ }
+ }
+ void brace_fuse(struct braceset*first,struct braceset*second)
+ {
+ struct braceset*ptr1=first,*ptr2;char*frstch; int frstlen;
+ while(ptr1)
+ {
+ ptr2=second;
+
ptr1->word=grub_realloc(ptr1->word,ptr1->len+ptr2->len+BRACE_BUFFER);
+ frstch=ptr1->word;
+ frstlen=ptr1->len;
+ grub_memcpy(ptr1->word+ptr1->len,ptr2->word,ptr2->len);
+ ptr1->len+=ptr2->len;
+ ptr2=ptr2->next;
+ while(ptr2)
+ {
+ struct braceset*new=grub_malloc(sizeof(*new));
+ new->word=grub_malloc(frstlen+ptr2->len+BRACE_BUFFER);
+ new->len=frstlen+ptr2->len;
+ grub_memcpy(new->word,frstch,frstlen);
+ grub_memcpy(new->word+frstlen,ptr2->word,ptr2->len);
+ new->next=ptr1->next;
+ ptr1->next=new;
+ ptr1=ptr1->next;
+ ptr2=ptr2->next;
+ }
+ ptr1=ptr1->next;
+ }
+ }
+ struct braceset*expand_brace(char**exp)
+ {
+ int cnt=0;
+ int esc=0;
+ int wasdol=0;
+ struct braceset*cur=grub_malloc(sizeof(*cur));
+ struct braceset*ret=cur;
+ cur->next=0;
+ cur->len=0;
+ cur->word=grub_malloc(BRACE_BUFFER);
+ for(;**exp && (esc ||
**exp!='}');esc=(**exp=='\\')&&!esc,wasdol=(**exp=='$'),(*exp)++)
+ {
+ if(**exp=='\'' || **exp=='"')
+ {
+ char*optr=*exp;
+ *exp+=script_get_strend(*exp);
+ while(optr<*exp)
+ brace_putch(cur,*((*exp)++));
+ }
+ if(**exp==',' && !esc)
+ {
+ struct braceset**nextptr=&ret;
+ while(*nextptr)nextptr=&(*nextptr)->next;
+ cur=grub_malloc(sizeof(*cur));
+ *nextptr=cur;
+ cur->next=0;
+ cur->len=0;
+ cur->word=grub_malloc(BRACE_BUFFER);
+ cnt++;
+ continue;
+ }
+ if(**exp=='{' && !wasdol &&
*(*exp+1+script_find_pas('{','}',*exp+1))=='}' && !esc)
+ {
+ (*exp)++;
+ brace_fuse(cur,expand_brace(exp));
+ continue;
+ }
+ brace_putch(cur,**exp);
+ }
+ if(!cnt) /*Incorrect brace restore '{' and '}'*/
+ {
+ cur=ret;
+ while(cur)
+ {
+ char*oldword=cur->word;
+ cur->len+=2;
+ cur->word=grub_malloc(cur->len);
+ cur->word[0]='{';
+ grub_memcpy(cur->word+1,oldword,cur->len-2);
+ cur->word[cur->len-1]='}';
+ cur=cur->next;
+ }
+ }
+ return ret;
+ }
+ int i;
+ for(i=0;i<*argc;i++)
+ {
+ struct braceset*brcs=grub_malloc(sizeof(*brcs)),*cur;
+ brcs->next=0;
+ brcs->len=0;
+ brcs->word=grub_malloc(BRACE_BUFFER);
+ char*ptr;
+ int esc=0;
+ int wasdol=0;
+ for(ptr=argv[i];*ptr;esc=(*ptr=='\\')&&!esc,wasdol=(*ptr=='$'),ptr++)
+ {
+ if(*ptr=='\'' || *ptr=='"')
+ {
+ char*optr=ptr;
+ ptr+=script_get_strend(ptr);
+ while(optr<ptr)
+ brace_putch(brcs,*(optr++));
+ }
+ if(*ptr=='{' && !wasdol &&
*(ptr+1+script_find_pas('{','}',ptr+1))=='}' && !esc)
+ {
+ ptr++;
+ brace_fuse(brcs,expand_brace(&ptr));
+ continue;
+ }
+ brace_putch(brcs,*ptr);
+ }
+ cur=brcs;
+ while(cur)
+ {
+ argret=grub_realloc(argret,sizeof(char*)*(argcret+1));
+ cur->word=grub_realloc(cur->word,cur->len+1);
+ cur->word[cur->len]=0;
+ argret[argcret++]=cur->word;
+ cur=cur->next;
+ }
+ }
+ *argc=argcret;
+ return argret;
+}
+
+char*
+script_expand_dollar (char*exp)
+{
+ char*ptr=exp;
+ char*rtval=grub_malloc(EXPAND_BUF_SIZE);
+ int wto=0;
+ rtval[0]=0;
+ void putchar(char c)
+ {
+ if((wto+1)%EXPAND_BUF_SIZE==0)
+ {
+ grub_realloc(rtval,wto+1+EXPAND_BUF_SIZE);
+ }
+ rtval[wto++]=c;
+ }
+ void puts(char*str)
+ {
+ for(;*str;str++)
+ putchar(*str);
+ }
+ for(ptr=exp;*ptr;ptr++)
+ {
+ if(*ptr=='\\' && *(ptr+1))
+ {
+ putchar(*(ptr++));
+ putchar(*ptr);
+ continue;
+ }
+ if(*ptr=='"' || *ptr=='\'')
+ {
+ char *optr=ptr;
+ ptr+=script_get_strend(ptr);
+ while(optr<=ptr)
+ putchar(*(optr++));
+ continue;
+ }
+ if(*ptr=='$')
+ {
+ ptr++;
+ char *expr=ptr;
+ if(*ptr=='(')
+ {
+ enum vartype vtp;
+ if(*(++ptr)=='(')
+ {
+ char c;
+ ptr++;
+ ptr+=script_find_pas('(',')',ptr);
+ c=*ptr;
+ *ptr=0;
+
char*tm=script_eval_arith(script_expand_dollar(expr+2),&vtp);
+ puts(script_get_str(tm,vtp));
+ *ptr=c;
+ ptr++;
+ ptr+=script_find_pas('(',')',ptr);
+ }
+ }
+ else
+ {
+ if (*ptr == '{')
+ {
+ ptr++;
+ expr++;
+ while (*ptr != '}')
+ ptr++;
+ }
+ else
+ {
+ /* XXX: An env. variable can have characters and
digits in
+ its name, are more characters allowed here? */
+ while (*ptr && (grub_isalpha (*ptr) || grub_isdigit
(*ptr)))
+ ptr++;
+ }
+ char c;
+ c=*ptr;
+ *ptr=0;
+ puts(script_env_get (expr));
+ *ptr=c;
+ if(c!='}')ptr--;
+ }
+ continue;
+ }
+ putchar(*ptr);
+ }
+ putchar(0);
+ return rtval;
+}
+void
+script_parse_list(grub_menu_entry_t
fnptr,char**cmd,grub_err_t(*getline)(char**),int flgs)
+{
+ grub_command_list_t listptr=0;char*lastcmd=*cmd,*bfrcmd=0;
+ /* Get one character from the commandline. If the caller reads
+ beyond the end of the string a new line will be read. This
+ function will not chech for errors, the caller has to check for
+ grub_errno. */
+ char getchar (void)
+ {
+ int c;
+
+ if (! *cmd)
+ {
+ if(getline)
+ {
+ if(listptr)
+
listptr->next=grub_malloc(sizeof(*listptr));
+ getline (cmd);
+ lastcmd=*cmd;
+ if(listptr)
+ {
+ listptr=listptr->next;
+ listptr->next=0;
+ listptr->command=grub_malloc(grub_strlen(*cmd)+2);
+ grub_memcpy(listptr->command,*cmd,grub_strlen(*cmd)+1);
+ }
+ }
+ else
+ return 0;
+ fnptr->num++;
+
+ /* Error is ignored here, the caller will check for this
+ when it reads beyond the EOL. */
+ c = *(*cmd)++;
+ return c;
+ }
+
+ c = *(*cmd)++;
+ if (! c)
+ {
+ bfrcmd=*cmd;
+ *cmd = 0;
+ return '\n';
+ }
+
+ return c;
+ }
+ void skip_oper()
+ {
+ int esc=0;char c;
+ while(1)
+ {
+ c=getchar();
+ if((c=='\n'||c==';') && !esc)
+ break;
+ if(c=='"' && !esc)
+ {
+ while((c=getchar())&& (c!='"' ||esc))
+ esc=(c=='\\')&&!esc;
+ continue;
+ }
+ if(c=='\'' && !esc)
+ {
+ while((c=getchar())&& (c!='\'' ||esc))
+ esc=(c=='\\')&&!esc;
+ continue;
+ }
+ }
+ }
+ char c;int brack=1;int lmin=0;
+ if(!(flgs&1))
+ {
+ while(grub_isspace((c=getchar())));
+ switch(c)
+ {
+ case '{':
+ break;
+ default:
+ grub_error(GRUB_ERR_BAD_ARGUMENT,"unexpected %c '{' expected",c);
+ return;
+ }
+ }
+ listptr=grub_malloc(sizeof(*listptr));
+ listptr->command=grub_malloc(grub_strlen(*cmd)+2);
+ listptr->next=0;
+ fnptr->command_list=listptr;
+ grub_memcpy(listptr->command,*cmd,grub_strlen(*cmd)+1);
+ while(brack)
+ {
+ lmin=0;
+ c=getchar();
+ if(grub_isspace(c))
+ continue;
+ if(c=='\n' || c==';')
+ continue;
+ if(c=='}')
+ {
+ brack--;
+ continue;
+ }
+ if(c=='{')
+ {
+ brack++;
+ continue;
+ }
+ if(c=='i')
+ {
+ if((c=getchar())=='f' && script_islexend(c=getchar()))
+ {
+ brack++;
+ continue;
+ }
+ else
+ {
+ if(c!=';' && c!='\n')
+ skip_oper();
+ continue;
+ }
+ }
+ if(c=='f')
+ {
+ if((c=getchar())=='i' && script_islexend(c=getchar()))
+ {
+ brack--;
+ lmin=3;
+ continue;
+ }
+ else
+ {
+ if(c!=';' && c!='\n')
+ skip_oper();
+ continue;
+ }
+ }
+ if(c=='d')
+ {
+ if((c=getchar())=='o')
+ {
+ c=getchar();
+ if(script_islexend(c))
+ {
+ if((flgs&2) && brack==1)
+ {
+ lmin=3;
+ break;
+ }
+ brack++;
+ continue;
+ }
+ if(c=='n' && (c=getchar())=='e' &&
script_islexend(c=getchar()))
+ {
+ brack--;
+ continue;
+ }
+ if(c!=';' && c!='\n')
+ skip_oper();
+ continue;
+ }
+ else
+ {
+ if(c!=';' && c!='\n')
+ skip_oper();
+ continue;
+ }
+ }
+ if(c=='e'&& brack==1)
+ {
+ while(1)
+ {
+ if((c=getchar())!='l')
+ break;
+ c=getchar();
+ if(c=='s')
+ {
+ if((c=getchar())!='e' || !script_islexend(c=getchar()))
+ break;
+ brack=0;
+ lmin=5;
+ break;
+ }
+ if(c=='i')
+ {
+ if((c=getchar())!='f' || !script_islexend(c=getchar()))
+ break;
+ brack=0;
+ lmin=5;
+ break;
+ }
+ }
+ if(c!='\n' && c!=';'&& brack)
+ skip_oper();
+ continue;
+ }
+ if(script_isfuncbeg(*cmd))
+ {
+ script_skipfuncbeg(cmd);
+ continue;
+ }
+ skip_oper();
+ }
+ if(*cmd)
+ {
+ (*cmd)-=lmin;
+ listptr->command[(*cmd)-lastcmd]=0;
+ }
+ if(!*cmd&& lmin)
+ {
+ *cmd=bfrcmd-lmin;
+ listptr->command[grub_strlen(listptr->command)-lmin+1]=0;
+ }
+}
+int
+script_list_execute( grub_menu_entry_t fn,enum
returnreason*retres,int*depth)
+{
+ grub_command_list_t cmdlist=fn->command_list;
+ grub_err_t getln(char**s)
+ {
+ if(cmdlist&& cmdlist->next)
+ {
+ cmdlist=cmdlist->next;
+ *s=cmdlist->command;
+ }
+ else
+ *s=0;
+ return 0;
+ }
+ int rtval=0;
+ while(cmdlist)
+ {
+ enum returnreason rt=SCRIPT_NONE;
+
if(cmdlist->command[0])rtval=script_execute(cmdlist->command,getln,0,&rt,depth);
+ if(retres)
+ *retres=rt;
+ if(rt)
+ return rtval;
+ if(cmdlist)
+ cmdlist=cmdlist->next;
+ }
+ return rtval;
+}
+void
+script_free_list(grub_menu_entry_t arg)
+{
+ grub_command_list_t lst=arg->command_list,last;
+ while(lst)
+ {
+ grub_free(lst->command);
+ last=lst;
+ lst=lst->next;
+ grub_free(last);
+ }
+ grub_free(arg);
+}
+int
+script_exec_file (char*fname,int argc, char**argv)
+{
+ grub_file_t file;char*lastalloc=0;
+ grub_err_t getln(char**s)
+ {
+ *s=grub_malloc(GRUB_MAX_CMDLINE);
+ if(lastalloc)
+ grub_free(lastalloc);
+ lastalloc=*s;
+ char c;
+ int pos = 0;
+ int literal = 0;
+ int comment = 0;
+ while (1)
+ {
+ if (grub_file_read (file, &c, 1) != 1)
+ break;
+
+ /* Skip all carriage returns. */
+ if (c == '\r')
+ continue;
+
+ /* Replace tabs with spaces. */
+ if (c == '\t')
+ c = ' ';
+
+ /* The previous is a backslash, then... */
+ if (literal)
+ {
+ /* If it is a newline, replace it with a space and
continue. */
+ if (c == '\n')
+ {
+ c = ' ';
+
+ /* Go back to overwrite the backslash. */
+ if (pos > 0)
+ pos--;
+ }
+
+ literal = 0;
+ }
+
+ if (c == '\\')
+ literal = 1;
+
+ if (comment)
+ {
+ if (c == '\n')
+ comment = 0;
+ }
+ else if (pos == 0)
+ {
+ if (c == '#')
+ comment = 1;
+ else if (! grub_isspace (c))
+ (*s)[pos++] = c;
+ }
+ else
+ {
+ if (c == '\n')
+ break;
+
+ if (pos < GRUB_MAX_CMDLINE)
+ (*s)[pos++] = c;
+ }
+ }
+ if(pos==0)
+ {
+ grub_free(*s);
+ *s=0;
+ }
+ else
+ (*s)[pos] = '\0';
+ return 0;
+ }
+ char*ln;int ret=0;
+ file=grub_file_open(fname);
+ if(!file)
+ return grub_errno;
+ while(1)
+ {
+ getln(&ln);
+ if(!ln)
+ break;
+ ret=script_execute(ln,getln,0,0,0);
+ }
+ return ret;
+}
+int
+script_execute(char*cmdline,grub_err_t(*getline)(char**),char**rest,enum
returnreason*retres,int*depth)
+{
+ int rtval=0,semdel=0;
+ int invrtval=0;
+ char*end=cmdline;
+ int skip_spaces()
+ {
+ if(!end)
+ return 0;
+ do
+ {
+ if(!*end)
+ getline(&end);
+ if(!end)
+ return 0;
+ while(*end && grub_isspace(*end))
+ end++;
+ }
+ while(!*end);
+ return 1;
+ }
+ if(rest)*rest=0;
+ if(retres)
+ *retres=SCRIPT_NONE;
+ while(1)
+ {
+ if(invrtval)
+ rtval=!rtval;
+ invrtval=0;
+ if(!end || !*end || *end=='#' || *end=='\n')
+ break;
+ if(*end=='|' && !rtval)
+ break;
+ if(*end=='&' && rtval)
+ break;
+ semdel=(*end==';');
+ if(*end==';' || *end=='|' ||*end=='&')
+ end++;
+ if(!*end &&semdel)
+ break;
+ if(!skip_spaces())return rtval;
+ if(*end=='!')
+ invrtval=1,end++;
+ if(!skip_spaces())return rtval;
+ if(*end=='{')
+ end++;
+ if(!skip_spaces())return rtval;
+ if(*end=='}')
+ end++;
+ while(*end && grub_isspace(*end))
+ end++;
+ if(!*end)
+ break;
+ if((!grub_memcmp(end,"then",4) && script_islexend(end[4]))
+ ||(!grub_memcmp(end,"else",4) && script_islexend(end[4]))
+ ||(!grub_memcmp(end,"elif",4) && script_islexend(end[4]))
+ ||(!grub_memcmp(end,"done",4) && script_islexend(end[4]))
+ ||(!grub_memcmp(end,"fi",2) && script_islexend(end[2])))
+ {
+ if(rest)
+ *rest=end;
+ break;
+ }
+ if(end[0]=='i' && end[1]=='f'&& script_islexend(end[2]))
+ {
+ int ret=0,crtval=0;
+ end+=2;
+ while(!end || !*end || grub_memcmp(end,"then",4)||
!script_islexend(end[4]))
+ {
+ enum returnreason rt;
+ if(!end || !*end)
+ getline(&end);
+ if(*end)
+ {
+ ret=!script_execute(end,getline,&end,&rt,depth);
+ if(retres)
+ *retres=rt;
+ if(rt)
+ return rtval;
+ }
+ }
+ grub_menu_entry_t lst=grub_malloc(sizeof(*lst));
+ lst->num=0;
+ lst->title=0;
+ lst->next=0;
+ end+=4;
+ script_parse_list(lst,&end,getline,1);
+ if(ret)
+ {
+ enum returnreason rt;
+ rtval=script_list_execute(lst,&rt,depth);
+ script_free_list(lst);
+ if(retres)
+ *retres=rt;
+ if(rt)
+ return rtval;
+ }
+ script_free_list(lst);
+ while((!grub_memcmp(end,"else",4)&&script_islexend(end[4]))
+ ||(!grub_memcmp(end,"elif",4)&&script_islexend(end[4])))
+ {
+ lst=grub_malloc(sizeof(*lst));
+ lst->num=0;
+ lst->title=0;
+ lst->next=0;
+ lst->command_list=0;
+ end+=4;
+ if(!ret&& !grub_memcmp(end-4,"elif",4))
+ {
+ while(!end || !*end || grub_memcmp(end,"then",4)||
!script_islexend(end[4]))
+ {
+ enum returnreason rt;
+ if(!end || !*end)
+ getline(&end);
+ if(*end)
+ {
+ ret=!script_execute(end,getline,&end,&rt,depth);
+ if(retres)
+ *retres=rt;
+ if(rt)
+ return rtval;
+ }
+ }
+ end+=4;
+ }
+ else
+ crtval=!ret;
+ script_parse_list(lst,&end,getline,1);
+ if(crtval)
+ {
+ enum returnreason rt;
+ rtval=script_list_execute(lst,&rt,depth);
+ script_free_list(lst);
+ if(retres)
+ *retres=rt;
+ if(rt)
+ return rtval;
+ ret=1;
+ }
+ else
+ script_free_list(lst);
+ }
+ end+=2;
+ continue;
+ }
+ if(!grub_memcmp(end,"for",sizeof("for")-1)&&
script_islexend(end[sizeof("for")-1]))
+ {
+ char* nmbeg;
+ end+=sizeof("for")-1;
+ if(!skip_spaces())
+ return rtval;
+ if(*end=='(')
+ {
+ char**exps;char*exp1,*exp2,*exp3;int argc;
+ enum vartype vtp;
+ grub_menu_entry_t lst=grub_malloc(sizeof(*lst));
+ exps=script_split_tokens(end,&argc,getline,&end);
+ exp1=*exps+2;
+ exp2=script_strchr(exp1,';')+1;
+ if(!(exp2-1))
+ {
+ grub_error(GRUB_ERR_BAD_ARGUMENT,"; expected");
+ return rtval;
+ }
+ *(exp2-1)=0;
+ exp3=script_strchr(exp2,';')+1;
+ if(!(exp3-1))
+ {
+ grub_error(GRUB_ERR_BAD_ARGUMENT,"; expected");
+ return rtval;
+ }
+ *(exp3-1)=0;
+ exp3[grub_strlen(exp3)-1]=0;
+ end++;
+ if(!skip_spaces())
+ return rtval;
+ if(grub_memcmp(end,"do",2) ||
!script_islexend(end[2]))
+ {
+ grub_error(GRUB_ERR_BAD_ARGUMENT,"do expected");
+ return rtval;
+ }
+ end+=2;
+ script_parse_list(lst,&end,getline,1);
+ char*exptm,*ret;
+ exptm=script_expand_dollar(exp1);
+ script_eval_arith(exptm,&vtp);
+ grub_free(exptm);
+ while(1)
+ {
+ int dpth;
+ exptm=script_expand_dollar(exp2);
+ ret=script_eval_arith(exptm,&vtp);
+ grub_free(exptm);
+ if(!script_get_bool(script_get_str(ret,vtp)))
+ break;
+ enum returnreason rt;
+ rtval=script_list_execute(lst,&rt,&dpth);
+ if(retres)
+
*retres=((rt==SCRIPT_CONTINUE||rt==SCRIPT_BREAK)&&dpth==1)?SCRIPT_NONE:rt;
+ if(depth)
+ *depth=dpth-1;
+ if(rt &&
(rt!=SCRIPT_CONTINUE||dpth!=1)&&(rt!=SCRIPT_BREAK||dpth!=1))
+ return rtval;
+ if(rt==SCRIPT_BREAK)
+ break;
+ exptm=script_expand_dollar(exp3);
+ script_eval_arith(exptm,&vtp);
+ grub_free(exptm);
+ }
+ grub_free(exps);
+ grub_free(exp1-2);
+ script_free_list(lst);
+ continue;
+ }
+ else
+ {
+ grub_menu_entry_t lst=grub_malloc(sizeof(*lst));
+ nmbeg=end;
+ while(*end && !grub_isspace(*end))end++;
+ char*name=grub_malloc(end-nmbeg+1);
+ grub_memcpy(name,nmbeg,end-nmbeg);
+ name[end-nmbeg]=0;
+ if(!skip_spaces())
+ return rtval;
+ if(grub_memcmp(end,"in",2) ||
!script_islexend(end[2]))
+ {
+ grub_error(GRUB_ERR_BAD_ARGUMENT,"in expected");
+ return rtval;
+ }
+ end+=2;
+ if(!skip_spaces())
+ return rtval;
+ int argc,i,argco;
+
char**exps=script_split_tokens(end,&argc,getline,&end),**exp2,**tmp;
+ argco=argc;
+ exp2=script_expand_braces(exps,&argc);
+ for(tmp=exps;tmp-exps<argco;tmp++)
+ grub_free(*tmp);
+ grub_free(exps);
+ exps=exp2;
+ if(*end!=';')
+ {
+ grub_error(GRUB_ERR_BAD_ARGUMENT,"; expected");
+ return rtval;
+ }
+ end++;
+ if(!skip_spaces())
+ return rtval;
+ if(grub_memcmp(end,"do",2) ||
!script_islexend(end[2]))
+ {
+ grub_error(GRUB_ERR_BAD_ARGUMENT,"do expected");
+ return rtval;
+ }
+ end+=2;
+ script_parse_list(lst,&end,getline,1);
+ for(i=0;i<argc;i++)
+ {
+ enum returnreason rt;int dpth;
+ script_env_set(script_dupstr(name),exps[i]);
+ rtval=script_list_execute(lst,&rt,&dpth);
+ if(retres)
+
*retres=((rt==SCRIPT_CONTINUE||rt==SCRIPT_BREAK)&&dpth==1)?SCRIPT_NONE:rt;
+ if(depth)
+ *depth=dpth-1;
+ if(rt &&
(rt!=SCRIPT_CONTINUE||dpth!=1)&&(rt!=SCRIPT_BREAK||dpth!=1))
+ return rtval;
+ if(rt==SCRIPT_BREAK)
+ break;
+ }
+ grub_free(name);
+ for(tmp=exps;tmp-exps<argc;tmp++)
+ grub_free(*tmp);
+ grub_free(exps);
+ script_free_list(lst);
+ continue;
+ }
+ }
+ if((!grub_memcmp(end,"while",sizeof("while")-1)&&
script_islexend(end[sizeof("while")-1]))
+ ||(!grub_memcmp(end,"until",sizeof("until")-1)&&
script_islexend(end[sizeof("until")-1])))
+ {
+ int invrt=(*end=='u');
+ end+=sizeof("while")-1;
+ grub_menu_entry_t condlst=grub_malloc(sizeof(*condlst));
+ grub_menu_entry_t lst=grub_malloc(sizeof(*lst));
+ condlst->num=0;
+ condlst->title=0;
+ condlst->next=0;
+ script_parse_list(condlst,&end,getline,3);
+ lst->num=0;
+ lst->title=0;
+ lst->next=0;
+ end+=2;
+ script_parse_list(lst,&end,getline,1);
+ while(1)
+ {
+ enum returnreason rt;
+ int ret=script_list_execute(condlst,&rt,depth),dpth;
+ if(retres)
+ *retres=rt;
+ if(rt)
+ return rtval;
+ if((!ret)==invrt)
+ break;
+ rtval=script_list_execute(lst,&rt,&dpth);
+ if(retres)
+
*retres=((rt==SCRIPT_CONTINUE||rt==SCRIPT_BREAK)&&dpth==1)?SCRIPT_NONE:rt;
+ if(depth)
+ *depth=dpth-1;
+ if(rt &&
(rt!=SCRIPT_CONTINUE||dpth!=1)&&(rt!=SCRIPT_BREAK||dpth!=1))
+ return rtval;
+ if(rt==SCRIPT_BREAK)
+ break;
+ }
+ script_free_list(lst);
+ script_free_list(condlst);
+ continue;
+ }
+ if (script_isfuncbeg(end))
+ {
+ grub_menu_t baseptr=&funcs;
+ grub_menu_entry_t bbptr,bptr2;
+ char*name=0;
+ while(grub_isspace(*end))end++;
+ if(!grub_memcmp(end,"entry",sizeof("entry")-1) &&
script_islexend(end[sizeof("entry")-1]))
+ end+=sizeof("entry")-1,baseptr=menu;
+ while(grub_isspace(*end))end++;
+ if(!grub_memcmp(end,"function",sizeof("function")-1) &&
script_islexend(end[sizeof("function")-1]))
+ end+=sizeof("function")-1;
+ while(grub_isspace(*end))end++;
+ switch(*end)
+ {
+ case '"':
+ end++;
+ name=script_get_doublestring(&end);
+ break;
+ case '\'':
+ end++;
+ name=script_get_singlestring(&end);
+ break;
+ default:
+ name=grub_malloc(64);//Must be enough
+ char*ptr=name;
+ while(!script_islexend(*end))
+ *(ptr++)=*(end++);
+ *ptr=0;
+ }
+ while(grub_isspace(*end))end++;
+ if(*end=='(')end++;//skip (
+ while(grub_isspace(*end))end++;
+ if(*end==')')end++;//skip )
+ while(grub_isspace(*end))end++;
+ baseptr->size++;
+ bbptr=bptr2=baseptr->entry_list;
+ while(bptr2)bbptr=bptr2,bptr2=bptr2->next;
+ bptr2=grub_malloc(sizeof(struct grub_menu_entry));
+ if(bbptr)
+ bbptr->next=bptr2;
+ else
+ baseptr->entry_list=bptr2;
+ bptr2->title=name;
+ bptr2->num=0;
+ bptr2->next=0;
+ script_parse_list(bptr2,&end,getline,0);
+ continue;
+ }
+ int argc,argco;
+ char**exps=script_split_tokens(end,&argc,getline,&end),**exp2,**tmp;
+ if(argc==1 && (exps[0])[0]=='(' && (exps[0])[1]=='(')
+ {
+ char*exp=script_expand_dollar(exps[0])+2;
+ char*expend,c;
+ char*ret;enum vartype vtp;
+ expend=exp+grub_strlen(exp)-1;
+ c=*expend;
+ *expend=0;
+ ret=script_eval_arith(exp,&vtp);
+ *expend=c;
+ rtval=!script_get_bool(script_get_str(ret,vtp));
+ continue;
+ }
+ argco=argc;
+ exp2=script_expand_braces(exps,&argc);
+ for(tmp=exps;tmp-exps<argco;tmp++)
+ grub_free(*tmp);
+ grub_free(exps);
+ exps=exp2;
+ for(tmp=exps;tmp-exps<argc;tmp++)
+ {
+ char*t;
+ t=*tmp;
+ *tmp=script_expand_dollar(*tmp);
+ grub_free(t);
+ }
+ if(!grub_strcmp("return",exps[0]))
+ {
+ if(*(exps[1])=='-' ||grub_isdigit(*(exps[1])))
+ rtval=grub_strtol(exps[1],0,0);
+ if(retres)
+ *retres=SCRIPT_RETURN;
+ return rtval;
+ }
+ if(!grub_strcmp("continue",exps[0]))
+ {
+ if(depth)
+ *depth=1;
+ if(depth && (*(exps[1])=='-' ||grub_isdigit(*(exps[1])) ))
+ *depth=grub_strtol(exps[1],0,0);;
+ if(retres)
+ *retres=SCRIPT_CONTINUE;
+ return rtval;
+ }
+ if(!grub_strcmp("break",exps[0]))
+ {
+ if(depth)
+ *depth=1;
+ if(depth && (*(exps[1])=='-' ||grub_isdigit(*(exps[1])) ))
+ *depth=grub_strtol(exps[1],0,0);;
+ if(retres)
+ *retres=SCRIPT_CONTINUE;
+ return rtval;
+ }
+ /* In case of an assignment set the environment accordingly instead
+ of calling a function. */
+ if (script_strchr(exps[0],'='))
+ {
+ char*expcur=script_strchr(exps[0],'=');
+ expcur[0] = 0;
+ char*ptr2=expcur+1;
+ #if 0
+ int array=0;
+ // if(ptr2[0]=='(')
+ // array=1;
+ #endif
+ script_env_set (exps[0], ptr2);
+ expcur[0] = '=';
+ rtval=0;
+ continue;
+ }
+ int i;
+ for(i=0;i<argc;i++)
+ {
+ char*wfrom=exps[i],*wto=exps[i];
+ while(*wfrom)
+ {
+ if(*wfrom=='\\')
+ {
+ *(wto++)=*(++wfrom);
+ wfrom++;
+ continue;
+ }
+ if(*wfrom=='\'' || *wfrom=='"')
+ {
+ wfrom++;
+ continue;
+ }
+ *(wto++)=*(wfrom++);
+ }
+ *wto=0;
+ }
+ {
+ grub_menu_entry_t cur=funcs.entry_list;
+ if(funcs.entry_list)
+ {
+ while(cur)
+ {
+ if(!grub_strcmp(cur->title,exps[0]))
+ break;
+ cur=cur->next;
+ }
+ if(cur)
+ {
+ rtval=script_list_execute(cur,0,0);
+ continue;
+ }
+ }
+ }
+ rtval=grub_exec_norm(exps,argc);
+ }
+ return rtval;
+}
- Feature suggestion to grub, Aki Tossavainen, 2005/01/12
- Re: Feature suggestion to grub, Marco Gerards, 2005/01/22
- Re: Feature suggestion to grub, Yoshinori K. Okuji, 2005/01/22
- Re: Feature suggestion to grub, Aki Tossavainen, 2005/01/22
- Re: Feature suggestion to grub, Yoshinori K. Okuji, 2005/01/22
- Bash pre-alpha, Serbinenko Vladimir, 2005/01/29
- Re: Bash pre-alpha, Serbinenko Vladimir, 2005/01/29
- Re: Bash pre-alpha, Marco Gerards, 2005/01/29
- Re: Bash pre-alpha, Serbinenko Vladimir, 2005/01/29
- Re: Bash pre-alpha,
Serbinenko Vladimir <=