Save 314 bytes on not handling contexts in core

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2009-12-20 02:52:39 +01:00
parent 0d48a435a0
commit 2fbcbbc389
17 changed files with 259 additions and 243 deletions

View file

@ -27,7 +27,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \
normal/handler.c normal/auth.c normal/autofs.c \
normal/completion.c normal/main.c normal/color.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \
normal/menu_text.c \
normal/menu_text.c normal/context.c \
script/main.c script/execute.c script/function.c \
script/lexer.c script/script.c grub_script.tab.c \
partmap/amiga.c partmap/apple.c partmap/msdos.c partmap/sun.c \

View file

@ -543,7 +543,7 @@ normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \
normal/auth.c normal/autofs.c normal/handler.c \
normal/color.c normal/completion.c normal/datetime.c normal/menu.c \
normal/menu_entry.c normal/menu_text.c normal/menu_viewer.c \
normal/misc.c
normal/misc.c normal/context.c
normal_mod_CFLAGS = $(COMMON_CFLAGS)
normal_mod_LDFLAGS = $(COMMON_LDFLAGS)

View file

@ -35,7 +35,8 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
machine/boot.h machine/console.h machine/init.h \
machine/memory.h machine/loader.h list.h handler.h command.h i18n.h
machine/memory.h machine/loader.h list.h handler.h command.h i18n.h \
env_private.h
kernel_img_CFLAGS = $(COMMON_CFLAGS)
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,$(GRUB_KERNEL_MACHINE_LINK_ADDR),-Bstatic

View file

@ -51,7 +51,8 @@ kernel_img_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \
kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
efi/efi.h efi/time.h efi/disk.h i386/pit.h list.h handler.h command.h i18n.h
efi/efi.h efi/time.h efi/disk.h i386/pit.h list.h handler.h command.h \
i18n.h env_private.h
kernel_img_CFLAGS = $(COMMON_CFLAGS)
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
kernel_img_LDFLAGS = $(COMMON_LDFLAGS)

View file

@ -33,7 +33,7 @@ kernel_img_HEADERS = cache.h device.h disk.h dl.h elf.h elfload.h \
env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
ieee1275/ieee1275.h machine/kernel.h machine/loader.h machine/memory.h \
list.h handler.h command.h i18n.h
list.h handler.h command.h i18n.h env_private.h
kernel_img_CFLAGS = $(COMMON_CFLAGS)
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x10000,-Bstatic

View file

@ -64,7 +64,8 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \
machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \
machine/kernel.h machine/pxe.h i386/pit.h list.h handler.h command.h i18n.h
machine/kernel.h machine/pxe.h i386/pit.h list.h handler.h command.h \
i18n.h env_private.h
kernel_img_CFLAGS = $(COMMON_CFLAGS) $(TARGET_IMG_CFLAGS)
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_KERNEL_MACHINE_LINK_ADDR) $(COMMON_CFLAGS)

View file

@ -17,7 +17,7 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
env.h err.h file.h fs.h kernel.h misc.h mm.h net.h parser.h reader.h \
symbol.h term.h time.h types.h powerpc/libgcc.h loader.h partition.h \
msdos_partition.h ieee1275/ieee1275.h machine/kernel.h handler.h list.h \
command.h i18n.h
command.h i18n.h env_private.h
symlist.c: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h gensymlist.sh
/bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1)

View file

@ -31,7 +31,7 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
list.h handler.h command.h i18n.h \
sparc64/libgcc.h ieee1275/ieee1275.h machine/kernel.h \
sparc64/ieee1275/ieee1275.h
sparc64/ieee1275/ieee1275.h env_private.h
kernel_img_SOURCES = kern/sparc64/ieee1275/crt0.S kern/ieee1275/cmain.c \
kern/ieee1275/ieee1275.c kern/main.c kern/device.c \
kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \

View file

@ -51,7 +51,7 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \
partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \
efi/efi.h efi/time.h efi/disk.h machine/loader.h i386/pit.h list.h \
handler.h command.h i18n.h
handler.h command.h i18n.h env_private.h
kernel_img_CFLAGS = $(COMMON_CFLAGS)
kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
kernel_img_LDFLAGS = $(COMMON_LDFLAGS)

View file

@ -22,6 +22,7 @@
#include <grub/symbol.h>
#include <grub/err.h>
#include <grub/types.h>
#include <grub/menu.h>
struct grub_env_var;
@ -30,18 +31,6 @@ typedef char *(*grub_env_read_hook_t) (struct grub_env_var *var,
typedef char *(*grub_env_write_hook_t) (struct grub_env_var *var,
const char *val);
enum grub_env_var_type
{
/* The default variable type which is local in current context. */
GRUB_ENV_VAR_LOCAL,
/* The exported type, which is passed to new contexts. */
GRUB_ENV_VAR_GLOBAL,
/* The data slot type, which is used to store arbitrary data. */
GRUB_ENV_VAR_DATA
};
struct grub_env_var
{
char *name;
@ -50,23 +39,24 @@ struct grub_env_var
grub_env_write_hook_t write_hook;
struct grub_env_var *next;
struct grub_env_var **prevp;
enum grub_env_var_type type;
int global;
};
grub_err_t EXPORT_FUNC(grub_env_set) (const char *name, const char *val);
char *EXPORT_FUNC(grub_env_get) (const char *name);
void EXPORT_FUNC(grub_env_unset) (const char *name);
void EXPORT_FUNC(grub_env_iterate) (int (*func) (struct grub_env_var *var));
struct grub_env_var *EXPORT_FUNC(grub_env_find) (const char *name);
grub_err_t EXPORT_FUNC(grub_register_variable_hook) (const char *name,
grub_env_read_hook_t read_hook,
grub_env_write_hook_t write_hook);
grub_err_t EXPORT_FUNC(grub_env_context_open) (int export);
grub_err_t EXPORT_FUNC(grub_env_context_close) (void);
grub_err_t EXPORT_FUNC(grub_env_export) (const char *name);
grub_err_t EXPORT_FUNC(grub_env_set_data_slot) (const char *name,
const void *ptr);
void *EXPORT_FUNC(grub_env_get_data_slot) (const char *name);
void EXPORT_FUNC(grub_env_unset_data_slot) (const char *name);
grub_err_t grub_env_context_open (int export);
grub_err_t grub_env_context_close (void);
grub_err_t grub_env_export (const char *name);
void grub_env_unset_menu (void);
grub_menu_t grub_env_get_menu (void);
void grub_env_set_menu (grub_menu_t nmenu);
#endif /* ! GRUB_ENV_HEADER */

View file

@ -0,0 +1,46 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2005,2006,2007,2009 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 3 of the License, or
* (at your option) any later version.
*
* GRUB 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_ENV_PRIVATE_HEADER
#define GRUB_ENV_PRIVATE_HEADER 1
#include <grub/env.h>
/* The size of the hash table. */
#define HASHSZ 13
/* A hashtable for quick lookup of variables. */
struct grub_env_context
{
/* A hash table for variables. */
struct grub_env_var *vars[HASHSZ];
/* One level deeper on the stack. */
struct grub_env_context *prev;
};
/* This is used for sorting only. */
struct grub_env_sorted_var
{
struct grub_env_var *var;
struct grub_env_sorted_var *next;
};
extern struct grub_env_context *EXPORT_VAR(grub_current_context);
#endif /* ! GRUB_ENV_PRIVATE_HEADER */

View file

@ -84,6 +84,8 @@ void read_command_list (void);
/* Defined in `autofs.c'. */
void read_fs_list (void);
void grub_context_init (void);
void grub_context_fini (void);
#ifdef GRUB_UTIL
void grub_normal_init (void);

View file

@ -73,18 +73,6 @@ grub_core_cmd_unset (struct grub_command *cmd __attribute__ ((unused)),
return 0;
}
static grub_err_t
grub_core_cmd_export (struct grub_command *cmd __attribute__ ((unused)),
int argc, char **args)
{
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"no environment variable specified");
grub_env_export (args[0]);
return 0;
}
/* insmod MODULE */
static grub_err_t
grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)),
@ -193,8 +181,6 @@ grub_register_core_commands (void)
"set [ENVVAR=VALUE]", "set an environment variable");
grub_register_command ("unset", grub_core_cmd_unset,
"unset ENVVAR", "remove an environment variable");
grub_register_command ("export", grub_core_cmd_export,
"export ENVVAR", "Export a variable.");
grub_register_command ("ls", grub_core_cmd_ls,
"ls [ARG]", "list devices or files");
grub_register_command ("insmod", grub_core_cmd_insmod,

View file

@ -18,34 +18,15 @@
*/
#include <grub/env.h>
#include <grub/env_private.h>
#include <grub/misc.h>
#include <grub/mm.h>
/* The size of the hash table. */
#define HASHSZ 13
/* A hashtable for quick lookup of variables. */
struct grub_env_context
{
/* A hash table for variables. */
struct grub_env_var *vars[HASHSZ];
/* One level deeper on the stack. */
struct grub_env_context *prev;
};
/* This is used for sorting only. */
struct grub_env_sorted_var
{
struct grub_env_var *var;
struct grub_env_sorted_var *next;
};
/* The initial context. */
static struct grub_env_context initial_context;
/* The current context. */
static struct grub_env_context *current_context = &initial_context;
struct grub_env_context *grub_current_context = &initial_context;
/* Return the hash representation of the string S. */
static unsigned int
@ -60,87 +41,20 @@ grub_env_hashval (const char *s)
return i % HASHSZ;
}
static struct grub_env_var *
struct grub_env_var *
grub_env_find (const char *name)
{
struct grub_env_var *var;
int idx = grub_env_hashval (name);
/* Look for the variable in the current context. */
for (var = current_context->vars[idx]; var; var = var->next)
for (var = grub_current_context->vars[idx]; var; var = var->next)
if (grub_strcmp (var->name, name) == 0)
return var;
return 0;
}
grub_err_t
grub_env_context_open (int export)
{
struct grub_env_context *context;
int i;
context = grub_zalloc (sizeof (*context));
if (! context)
return grub_errno;
context->prev = current_context;
current_context = context;
/* Copy exported variables. */
for (i = 0; i < HASHSZ; i++)
{
struct grub_env_var *var;
for (var = context->prev->vars[i]; var; var = var->next)
{
if (export && var->type == GRUB_ENV_VAR_GLOBAL)
{
if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
{
grub_env_context_close ();
return grub_errno;
}
grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
}
}
}
return GRUB_ERR_NONE;
}
grub_err_t
grub_env_context_close (void)
{
struct grub_env_context *context;
int i;
if (! current_context->prev)
grub_fatal ("cannot close the initial context");
/* Free the variables associated with this context. */
for (i = 0; i < HASHSZ; i++)
{
struct grub_env_var *p, *q;
for (p = current_context->vars[i]; p; p = q)
{
q = p->next;
grub_free (p->name);
if (p->type != GRUB_ENV_VAR_DATA)
grub_free (p->value);
grub_free (p);
}
}
/* Restore the previous context. */
context = current_context->prev;
grub_free (current_context);
current_context = context;
return GRUB_ERR_NONE;
}
static void
grub_env_insert (struct grub_env_context *context,
struct grub_env_var *var)
@ -164,18 +78,6 @@ grub_env_remove (struct grub_env_var *var)
var->next->prevp = var->prevp;
}
grub_err_t
grub_env_export (const char *name)
{
struct grub_env_var *var;
var = grub_env_find (name);
if (var)
var->type = GRUB_ENV_VAR_GLOBAL;
return GRUB_ERR_NONE;
}
grub_err_t
grub_env_set (const char *name, const char *val)
{
@ -207,9 +109,8 @@ grub_env_set (const char *name, const char *val)
if (! var)
return grub_errno;
/* This is not necessary, because GRUB_ENV_VAR_LOCAL == 0. But leave
this for readability. */
var->type = GRUB_ENV_VAR_LOCAL;
/* This is not necessary. But leave this for readability. */
var->global = 0;
var->name = grub_strdup (name);
if (! var->name)
@ -219,7 +120,7 @@ grub_env_set (const char *name, const char *val)
if (! var->value)
goto fail;
grub_env_insert (current_context, var);
grub_env_insert (grub_current_context, var);
return GRUB_ERR_NONE;
@ -263,8 +164,7 @@ grub_env_unset (const char *name)
grub_env_remove (var);
grub_free (var->name);
if (var->type != GRUB_ENV_VAR_DATA)
grub_free (var->value);
grub_free (var->value);
grub_free (var);
}
@ -280,14 +180,10 @@ grub_env_iterate (int (*func) (struct grub_env_var *var))
{
struct grub_env_var *var;
for (var = current_context->vars[i]; var; var = var->next)
for (var = grub_current_context->vars[i]; var; var = var->next)
{
struct grub_env_sorted_var *p, **q;
/* Ignore data slots. */
if (var->type == GRUB_ENV_VAR_DATA)
continue;
sorted_var = grub_malloc (sizeof (*sorted_var));
if (! sorted_var)
goto fail;
@ -343,84 +239,3 @@ grub_register_variable_hook (const char *name,
return GRUB_ERR_NONE;
}
static char *
mangle_data_slot_name (const char *name)
{
char *mangled_name;
mangled_name = grub_malloc (grub_strlen (name) + 2);
if (! mangled_name)
return 0;
grub_sprintf (mangled_name, "\e%s", name);
return mangled_name;
}
grub_err_t
grub_env_set_data_slot (const char *name, const void *ptr)
{
char *mangled_name;
struct grub_env_var *var;
mangled_name = mangle_data_slot_name (name);
if (! mangled_name)
goto fail;
/* If the variable does already exist, just update the variable. */
var = grub_env_find (mangled_name);
if (var)
{
var->value = (char *) ptr;
return GRUB_ERR_NONE;
}
/* The variable does not exist, so create a new one. */
var = grub_zalloc (sizeof (*var));
if (! var)
goto fail;
var->type = GRUB_ENV_VAR_DATA;
var->name = mangled_name;
var->value = (char *) ptr;
grub_env_insert (current_context, var);
return GRUB_ERR_NONE;
fail:
grub_free (mangled_name);
return grub_errno;
}
void *
grub_env_get_data_slot (const char *name)
{
char *mangled_name;
void *ptr = 0;
mangled_name = mangle_data_slot_name (name);
if (! mangled_name)
goto fail;
ptr = grub_env_get (mangled_name);
grub_free (mangled_name);
fail:
return ptr;
}
void
grub_env_unset_data_slot (const char *name)
{
char *mangled_name;
mangled_name = mangle_data_slot_name (name);
if (! mangled_name)
return;
grub_env_unset (mangled_name);
grub_free (mangled_name);
}

View file

@ -114,7 +114,6 @@ grub_set_root_dev (void)
const char *prefix;
grub_register_variable_hook ("root", 0, grub_env_write_root);
grub_env_export ("root");
prefix = grub_env_get ("prefix");
@ -164,7 +163,6 @@ grub_main (void)
/* It is better to set the root device as soon as possible,
for convenience. */
grub_machine_set_prefix ();
grub_env_export ("prefix");
grub_set_root_dev ();
grub_register_core_commands ();

172
normal/context.c Normal file
View file

@ -0,0 +1,172 @@
/* env.c - Environment variables */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2005,2006,2007,2008,2009 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 3 of the License, or
* (at your option) any later version.
*
* GRUB 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, see <http://www.gnu.org/licenses/>.
*/
#include <grub/env.h>
#include <grub/env_private.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/command.h>
struct menu_pointer
{
grub_menu_t menu;
struct menu_pointer *prev;
};
struct menu_pointer initial_menu;
struct menu_pointer *current_menu = &initial_menu;
void
grub_env_unset_menu (void)
{
current_menu->menu = NULL;
}
grub_menu_t
grub_env_get_menu (void)
{
return current_menu->menu;
}
void
grub_env_set_menu (grub_menu_t nmenu)
{
current_menu->menu = nmenu;
}
grub_err_t
grub_env_context_open (int export)
{
struct grub_env_context *context;
int i;
struct menu_pointer *menu;
context = grub_zalloc (sizeof (*context));
if (! context)
return grub_errno;
menu = grub_zalloc (sizeof (*menu));
if (! menu)
return grub_errno;
context->prev = grub_current_context;
grub_current_context = context;
menu->prev = current_menu;
current_menu = menu;
/* Copy exported variables. */
for (i = 0; i < HASHSZ; i++)
{
struct grub_env_var *var;
for (var = context->prev->vars[i]; var; var = var->next)
{
if (export && var->global)
{
if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
{
grub_env_context_close ();
return grub_errno;
}
grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
}
}
}
return GRUB_ERR_NONE;
}
grub_err_t
grub_env_context_close (void)
{
struct grub_env_context *context;
int i;
struct menu_pointer *menu;
if (! grub_current_context->prev)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"cannot close the initial context");
/* Free the variables associated with this context. */
for (i = 0; i < HASHSZ; i++)
{
struct grub_env_var *p, *q;
for (p = grub_current_context->vars[i]; p; p = q)
{
q = p->next;
grub_free (p->name);
grub_free (p->value);
grub_free (p);
}
}
/* Restore the previous context. */
context = grub_current_context->prev;
grub_free (grub_current_context);
grub_current_context = context;
menu = current_menu->prev;
grub_free (current_menu);
current_menu = menu;
return GRUB_ERR_NONE;
}
grub_err_t
grub_env_export (const char *name)
{
struct grub_env_var *var;
var = grub_env_find (name);
if (var)
var->global = 1;
return GRUB_ERR_NONE;
}
static grub_command_t export_cmd;
static grub_err_t
grub_cmd_export (struct grub_command *cmd __attribute__ ((unused)),
int argc, char **args)
{
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"no environment variable specified");
grub_env_export (args[0]);
return 0;
}
void
grub_context_init (void)
{
grub_env_export ("root");
grub_env_export ("prefix");
export_cmd = grub_register_command ("export", grub_cmd_export,
"export ENVVAR", "Export a variable.");
}
void
grub_context_fini (void)
{
grub_unregister_command (export_cmd);
}

View file

@ -133,7 +133,7 @@ free_menu (grub_menu_t menu)
}
grub_free (menu);
grub_env_unset_data_slot ("menu");
grub_env_unset_menu ();
}
static void
@ -174,7 +174,7 @@ grub_normal_add_menu_entry (int argc, const char **args,
return grub_errno;
classes_tail = classes_head;
menu = grub_env_get_data_slot ("menu");
menu = grub_env_get_menu ();
if (! menu)
return grub_error (GRUB_ERR_MENU, "no menu context");
@ -357,14 +357,14 @@ read_config_file (const char *config)
grub_menu_t newmenu;
newmenu = grub_env_get_data_slot ("menu");
newmenu = grub_env_get_menu ();
if (! newmenu)
{
newmenu = grub_zalloc (sizeof (*newmenu));
if (! newmenu)
return 0;
grub_env_set_data_slot ("menu", newmenu);
grub_env_set_menu (newmenu);
}
/* Try to open the config file. */
@ -562,6 +562,8 @@ grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)),
GRUB_MOD_INIT(normal)
{
grub_context_init ();
/* Normal mode shouldn't be unloaded. */
if (mod)
grub_dl_ref (mod);
@ -589,6 +591,8 @@ GRUB_MOD_INIT(normal)
GRUB_MOD_FINI(normal)
{
grub_context_fini ();
grub_set_history (0);
grub_reader_unregister (&grub_normal_reader);
grub_register_variable_hook ("pager", 0, 0);