Merge mainline into for_macros

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-04-09 22:35:32 +02:00
commit 4a55d631d7
113 changed files with 21429 additions and 3110 deletions

360
ChangeLog
View file

@ -1,3 +1,363 @@
2010-04-09 Vladimir Serbinenko <phcoder@gmail.com>
* term/efi/console.c (grub_console_checkkey): Macroify key contants.
2010-04-09 EFI Coder <eficoder@hotmail.com>
* normal/menu_text.c (print_message): Clean up the message and show
the Fn information when on EFI
* term/efi/console.c (grub_console_checkkey): Add F4 support.
2010-04-09 Vladimir Serbinenko <phcoder@gmail.com>
* normal/autofs.c (read_fs_list): New parameter 'prefix'.
All users updated.
* normal/crypto.c (read_crypto_list): Likewise.
* normal/dyncmd.c (read_command_list): Likewise.
* normal/term.c (read_terminal_list): Likewise.
* normal/main.c (read_lists): Use explicit prefix.
(read_lists_hook): Use read_lists.
(grub_normal_execute): Likewise.
2010-04-09 Vladimir Serbinenko <phcoder@gmail.com>
* util/grub-mkrescue.in: Fix incorrect path in coreboot part.
Reported by: Thomas Schmitt.
Add -no-emul-boot to grub-mkisofs parameters.
2010-04-09 Vladimir Serbinenko <phcoder@gmail.com>
* font/font.c: Indented.
2010-04-09 BVK Chaitanya <bvk.groups@gmail.com>
Elif support to GRUB script (by Deepak Vankadaru).
* tests/grub_script_if.in: New testcase.
* conf/tests.rmk: Rule for new testcase.
* script/parser.y: Grammar rules for elif.
2010-04-09 BVK Chaitanya <bvk.groups@gmail.com>
While and until loops support to GRUB script.
* include/grub/script_sh.h (grub_script_cmdwhile): New struct.
(grub_script_create_cmdwhile): New function prototype.
(grub_script_execute_cmdwhile): New function prototype.
* script/execute.c (grub_script_execute_cmdwhile): New function.
* script/parser.y (command): New commands.
(whilecmd): New grammar rule.
(untilcmd): New grammar rule.
* script/script.c (grub_script_create_cmdwhile): New function.
* util/grub-script-check.c (grub_script_execute_cmdwhile): New
function.
* tests/grub_script_while1.in: New testcase.
* conf/tests.rmk: Rule for new testcase.
2010-04-09 Vladimir Serbinenko <phcoder@gmail.com>
* util/grub.d/00_header.in: Add few missing quotes. Recognise *.jpeg
as *.jpg.
2010-04-09 Mario Vazquez <mariovazq@gmail.com>
GRUB_BACKGROUND support.
* util/grub-mkconfig.in: Export GRUB_BACKGROUND.
* util/grub.d/00_header.in: Parse GRUB_BACKGROUND.
2010-04-09 Vladimir Serbinenko <phcoder@gmail.com>
Load fonts and modules for gfxmenu in grub-mkconfig.
Idea by: Mario Vazquez
* util/grub.d/00_header.in: Load pf2 and image modules.
2010-04-09 Vladimir Serbinenko <phcoder@gmail.com>
grub-mkconfig multiple terminal support.
* util/grub-mkconfig.in: Handle multiple terminals correctly.
* util/grub.d/00_header.in: Likewise.
2010-04-09 Vladimir Serbinenko <phcoder@gmail.com>
* Makefile.in: Specify files explicitly instead of using $< and $@ since
we use cd $(srcdir).
2010-04-08 Colin Watson <cjwatson@ubuntu.com>
* util/grub.d/10_linux.in: Only use the first word of
GRUB_DISTRIBUTOR for --class, to avoid problems if somebody puts
spaces in GRUB_DISTRIBUTOR.
* util/grub.d/10_kfreebsd.in: Likewise.
* util/grub.d/10_hurd.in: Likewise.
2010-04-06 BVK Chaitanya <bvk.groups@gmail.com>
Fix unit testing framework for Qemu 0.12.
* tests/util/grub-shell.in: Remove -serial stdio option.
2010-04-06 Vladimir Serbinenko <phcoder@gmail.com>
POSIX header file wrappers.
* lib/posix_wrap/assert.h: New file. Wrapper for its POSIX
equivalents.
* lib/posix_wrap/ctype.h: Likewise.
* lib/posix_wrap/errno.h: Likewise.
* lib/posix_wrap/langinfo.h: Likewise.
* lib/posix_wrap/limits.h: Likewise.
* lib/posix_wrap/localcharset.h: Likewise.
* lib/posix_wrap/stdint.h: Likewise.
* lib/posix_wrap/stdio.h: Likewise.
* lib/posix_wrap/stdlib.h: Likewise.
* lib/posix_wrap/string.h: Likewise.
* lib/posix_wrap/sys/types.h: Likewise.
* lib/posix_wrap/unistd.h: Likewise.
* lib/posix_wrap/wchar.h: Likewise.
* lib/posix_wrap/wctype.h: Likewise.
* conf/common.rmk (grub_script.yy.c): Remove #include elimination.
(grub_script.yy.h): Likewise.
* script/yylex.l: Remove POSIX emulation #defines.
* Makefile.in (POSIX_CFLAGS): New variable.
(GNULIB_UTIL_CFLAGS): Likewise.
Regexp support.
* conf/common.rmk (pkglib_MODULES): Add regexp.mod.
(regexp_mod_SOURCES): New variable.
(regexp_mod_CFLAGS): Likewise.
(regexp_mod_LDFLAGS): Likewise.
* commands/regexp.c: New file.
* gnulib/regcomp.c: New file. Imported from gnulib.
* gnulib/regex.c: Likewise.
* gnulib/regex_internal.c: Likewise.
* gnulib/regex_internal.h: Likewise.
* gnulib/regexec.c: Likewise.
* gnulib/regex.h: Likewise.
2010-04-05 Vladimir Serbinenko <phcoder@gmail.com>
* loader/i386/multiboot_mbi.c (grub_multiboot_load): Correctly report
unsupported video mode types.
2010-04-05 Vladimir Serbinenko <phcoder@gmail.com>
* kern/i386/pc/startup.S (grub_getrtsecs): Removed (dead code).
2010-04-05 Vladimir Serbinenko <phcoder@gmail.com>
* include/grub/i386/pc/init.h (grub_get_mmap_entry): Don't export.
* conf/i386-pc.rmk (kernel_img_HEADERS): Remove machine/init.h.
2010-04-04 Vladimir Serbinenko <phcoder@gmail.com>
Remove unused grub_vga_get_font.
* kern/i386/pc/startup.S (grub_vga_get_font): Removed.
* include/grub/i386/pc/vga.h (grub_vga_get_font): Likewise.
2010-04-03 Grégoire Sutre <gregoire.sutre@gmail.com>
* kern/misc.c: Disable the __enable_execute_stack hack for utilities.
* include/grub/misc.h: Likewise.
2010-04-03 Grégoire Sutre <gregoire.sutre@gmail.com>
* util/grub-install.in: Add `|| exit 1' to all grub-probe calls
for which failure is fatal.
2010-04-03 Grégoire Sutre <gregoire.sutre@gmail.com>
* util/grub-install.in: Use mkdir -p to create grub directory.
* util/i386/efi/grub-install.in: Likewise.
* util/ieee1275/grub-install.in: Likewise.
2010-04-03 Grégoire Sutre <gregoire.sutre@gmail.com>
* Makefile.in (LEX): new variable.
2010-04-03 Grégoire Sutre <gregoire.sutre@gmail.com>
* util/i386/efi/grub-dumpdevtree: replaced the non-portable `==' by
`=' and added double quotes on operands of this equality test.
2010-04-03 Vladimir Serbinenko <phcoder@gmail.com>
* Makefile.in (uninstall): Remove a leftover debug echo.
Reported by: Grégoire Sutre
2010-04-03 Vladimir Serbinenko <phcoder@gmail.com>
MIPS multiboot2 support.
* conf/mips.rmk (pkglib_MODULES): Add multiboot2.mod.
(multiboot2_mod_SOURCES): New variable.
(multiboot2_mod_CFLAGS): Likewise.
(multiboot2_mod_LDFLAGS): Likewise.
(multiboot2_mod_ASFLAGS): Likewise.
* include/grub/i386/multiboot.h (MULTIBOOT_INITIAL_STATE): New
definition.
(MULTIBOOT_ENTRY_REGISTER): Likewise.
(MULTIBOOT_MBI_REGISTER): Likewise.
(MULTIBOOT_ARCHITECTURE_CURRENT): Likewise.
(MULTIBOOT_ELF32_MACHINE): Likewise.
(MULTIBOOT_ELF64_MACHINE): Likewise.
* include/grub/mips/multiboot.h: New file.
* include/grub/video.h (grub_video_driver_id): New type
GRUB_VIDEO_DRIVER_SM712.
(grub_video_get_info_and_fini): Export.
(grub_video_get_palette): Likewise.
(grub_video_get_driver_id): Likewise.
* include/multiboot2.h: Resynced with spec.
* loader/i386/multiboot.c: Moved from here ...
* loader/multiboot.c: ... here. All users updated.
(grub_multiboot_boot): Use platform-specific macros.
* loader/i386/multiboot_elfxx.c: Moved from here ...
* loader/multiboot_elfxx.c: ... here. All users updated.
(E_MACHINE): Use MULTIBOOT_ELF32_MACHINE and MULTIBOOT_ELF64_MACHINE.
* loader/i386/multiboot_mbi2.c (grub_multiboot_load): Check arcitecture.
* video/sm712.c (grub_video_sm712_adapter): Add missing id field.
2010-04-02 Vladimir Serbinenko <phcoder@gmail.com>
Import gnulib argp module.
* gnulib/argp-ba.c: New file.
* gnulib/argp-eexst.c: Likewise.
* gnulib/argp-fmtstream.c: Likewise.
* gnulib/argp-fmtstream.h: Likewise.
* gnulib/argp-fs-xinl.c: Likewise.
* gnulib/argp-help.c: Likewise.
* gnulib/argp-namefrob.h: Likewise.
* gnulib/argp-parse.c: Likewise.
* gnulib/argp-pin.c: Likewise.
* gnulib/argp-pv.c: Likewise.
* gnulib/argp-pvh.c: Likewise.
* gnulib/argp-version-etc.c: Likewise.
* gnulib/argp-version-etc.h: Likewise.
* gnulib/argp-xinl.c: Likewise.
* gnulib/argp.h: Likewise.
2010-03-31 Vladimir Serbinenko <phcoder@gmail.com>
* kern/device.c (grub_device_iterate): Clear errors after failed
opening device.
2010-03-31 Vladimir Serbinenko <phcoder@gmail.com>
* kern/ieee1275/openfw.c (grub_children_iterate): Skip device itself if
returned by firmware.
2010-03-30 Vladimir Serbinenko <phcoder@gmail.com>
* loader/i386/multiboot_mbi2.c (retrieve_video_parameters): Fix
compilation on coreboot and qemu
2010-03-28 Vladimir Serbinenko <phcoder@gmail.com>
* include/multiboot2.h: Resync with spec.
2010-03-28 Vladimir Serbinenko <phcoder@gmail.com>
Multiboot2 tag support
* conf/i386.rmk (multiboot2_mod_SOURCES): Replace
loader/i386/multiboot_mbi.c with loader/i386/multiboot_mbi2.c.
Remove loader/multiboot_loader.c.
* include/grub/i386/multiboot.h (grub_multiboot_real_boot): Removed.
(grub_multiboot2_real_boot): Likewise.
* include/grub/multiboot.h (grub_multiboot_set_accepts_video): Removed.
(grub_get_multiboot_mmap_count): New proto.
(grub_fill_multiboot_mmap): Likewise.
(grub_multiboot_set_video_mode): Likewise.
(grub_multiboot_set_console): Likewise.
(grub_multiboot_load): Likewise.
(grub_multiboot_load_elf): Likewise.
(GRUB_MULTIBOOT_CONSOLE_EGA_TEXT): New definition.
(GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER): Likewise.
* include/multiboot.h: Resynced with specification.
* include/multiboot2.h: Resynced with specification.
* loader/i386/multiboot_mbi.c (DEFAULT_VIDEO_MODE): Moved from here...
* loader/i386/multiboot.c (DEFAULT_VIDEO_MODE): ... here.
* loader/i386/multiboot_mbi.c (HAS_VGA_TEXT): Moved from here ..
* include/grub/multiboot.h (GRUB_MACHINE_HAS_VGA_TEXT): ... here. All
users updated.
* loader/i386/multiboot_mbi.c (accepts_video): Moved from here...
* loader/i386/multiboot.c (accepts_video): ... here. All users updated.
* loader/i386/multiboot_mbi.c (grub_multiboot_set_accepts_video):
Removed.
* loader/i386/multiboot_mbi.c (grub_get_multiboot_mmap_len):
Moved from here...
* loader/i386/multiboot.c (grub_get_multiboot_mmap_len): ... here.
* loader/i386/multiboot_mbi.c (grub_fill_multiboot_mmap):
Moved from here...
* loader/i386/multiboot.c (grub_fill_multiboot_mmap): ... here.
* loader/i386/multiboot_mbi.c (set_video_mode): Moved from here...
* loader/i386/multiboot.c (grub_multiboot_set_video_mode): ... here.
All users updated.
* loader/i386/multiboot_mbi2.c: New file.
2010-03-27 Vladimir Serbinenko <phcoder@gmail.com>
Resync with gnulib.
* Makefile.in (GNULIB_CFLAGS): New variable.
* conf/common.rmk (grub_mkisofs_CFLAGS): Add GNULIB_CFLAGS.
(grub_script_check_CFLAGS): New variable.
* gnulib/alloca.h: Resync with gnulib.
* gnulib/error.c: Likewise.
* gnulib/error.h: Likewise.
* gnulib/fnmatch.c: Likewise.
* gnulib/fnmatch_loop.c: Likewise.
* gnulib/getdelim.c: Likewise.
* gnulib/getline.c: Likewise.
* gnulib/getopt.c: Likewise.
* gnulib/getopt1.c: Likewise.
* gnulib/getopt_int.h: Likewise.
* gnulib/gettext.h: Likewise.
* gnulib/progname.c: Likewise.
* gnulib/progname.h: Likewise.
2010-03-27 Grégoire Sutre <gregoire.sutre@gmail.com>
Fix a build failure (-Wundef -Werror) when ENABLE_NLS is not defined,
which is the case with --disabled-nls.
* include/grub/i18n.h: Use (defined(ENABLE_NLS)
&& ENABLE_NLS) instead of ENABLE_NLS in all #if preprocessor macros.
* util/misc.c: Likewise.
* util/mkisofs/mkisofs.c: Likewise.
* util/mkisofs/mkisofs.h: Likewise.
2010-03-27 Vladimir Serbinenko <phcoder@gmail.com>
Simplify Apple CC support.
* commands/i386/pc/drivemap_int13h.S: Use LOCAL when possible.
Add 0 byte at the end not to have a symbol with empty target.
* mmap/i386/pc/mmap_helper.S: Likewise.
* genmk.rb: Ignore errors 2030 and 2050.
* kern/i386/pc/startup.S: Use LOCAL when possible.
2010-03-26 BVK Chaitanya <bvk.groups@gmail.com>
Testcase and the fix for final semicolon on cmdline.
* tests/grub_script_final_semicolon.in: New testcase.
* conf/tests.rmk: Rules for the new testcase.
* script/parser.y: Grammar fix.
2010-03-26 BVK Chaitanya <bvk@localhost>
Blank lines testcase for GRUB script.
* tests/grub_script_blanklines.in: New testcase.
* conf/tests.rmk: Rules for the new testcase.
2010-03-26 Vladimir Serbinenko <phcoder@gmail.com>
Don't use __FILE__.

View file

@ -79,6 +79,9 @@ LIBS = @LIBS@ $(LIBINTL)
CC = @CC@
CFLAGS = @CFLAGS@
POSIX_CFLAGS = -I$(srcdir)/lib/posix_wrap
GNULIB_UTIL_CFLAGS = -Wno-undef -Wno-sign-compare -Wno-unused -D_GL_UNUSED="__attribute__ ((unused))" -I$(srcdir)/gnulib
GNULIB_CFLAGS = $(GNULIB_UTIL_CFLAGS) $(POSIX_CFLAGS)
ASFLAGS = @ASFLAGS@
LDFLAGS = @LDFLAGS@ $(LIBS)
CPPFLAGS = @CPPFLAGS@ -I$(builddir) -I$(builddir)/include -I$(srcdir)/gnulib -I$(srcdir)/include -Wall -W \
@ -116,6 +119,7 @@ LIBCURSES = @LIBCURSES@
LIBUSB = @LIBUSB@
LIBSDL = @LIBSDL@
LIBPCIACCESS = @LIBPCIACCESS@
LEX = @LEX@
YACC = @YACC@
FONT_SOURCE = @FONT_SOURCE@
@ -395,7 +399,6 @@ uninstall:
@list='$(lib_SCRIPTS)'; \
for file in $$list; do \
dest="`echo $$file | sed 's,.*/,,'`"; \
echo rm -f $(DESTDIR)$(libdir)/$$dest; \
rm -f $(DESTDIR)$(libdir)/grub/$$dest; \
done
@list='$(info_INFOS)'; \
@ -527,8 +530,8 @@ genkernsyms.sh: genkernsyms.sh.in config.status
$(SHELL) ./config.status
$(srcdir)/po/$(PACKAGE).pot: po/POTFILES po/POTFILES-shell
cd $(srcdir) && $(XGETTEXT) -ctranslate --from-code=utf-8 -o $@ -f $< --keyword=_ --keyword=N_
cd $(srcdir) && $(XGETTEXT) -ctranslate --from-code=utf-8 -o $@ -f po/POTFILES-shell -j --language=Shell
cd $(srcdir) && $(XGETTEXT) -ctranslate --from-code=utf-8 -o po/$(PACKAGE).pot -f po/POTFILES --keyword=_ --keyword=N_
cd $(srcdir) && $(XGETTEXT) -ctranslate --from-code=utf-8 -o po/$(PACKAGE).pot -f po/POTFILES-shell -j --language=Shell
$(foreach lang, $(LINGUAS), $(srcdir)/po/$(lang).po): po/$(PACKAGE).pot
$(MSGMERGE) -U $@ $^

View file

@ -19,7 +19,7 @@
#include <grub/symbol.h>
#define INT13H_OFFSET(x) ((x) - EXT_C(grub_drivemap_handler))
#define INT13H_OFFSET(x) ((x) - LOCAL (base))
.code16
@ -27,6 +27,7 @@
/* The replacement int13 handler. Preserve all registers. */
FUNCTION(grub_drivemap_handler)
LOCAL (base):
/* Save %dx for future restore. */
push %dx
/* Push flags. Used to simulate interrupt with original flags. */
@ -35,12 +36,7 @@ FUNCTION(grub_drivemap_handler)
/* Map the drive number (always in DL). */
push %ax
push %bx
#ifdef APPLE_CC
grub_drivemap_mapstart_ofs = INT13H_OFFSET(EXT_C(grub_drivemap_mapstart))
movw $grub_drivemap_mapstart_ofs, %bx
#else
movw $INT13H_OFFSET(EXT_C(grub_drivemap_mapstart)), %bx
#endif
movw $INT13H_OFFSET(LOCAL (mapstart)), %bx
more_remaining:
movw %cs:(%bx), %ax
@ -66,12 +62,7 @@ not_found:
popf
pushf
#ifdef APPLE_CC
grub_drivemap_oldhandler_ofs = INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler))
lcall *%cs:grub_drivemap_oldhandler_ofs
#else
lcall *%cs:INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler))
#endif
lcall *%cs:INT13H_OFFSET (LOCAL (oldhandler))
push %bp
mov %sp, %bp
@ -94,11 +85,7 @@ norestore:
popf
pushf
#ifdef APPLE_CC
lcall *%cs:grub_drivemap_oldhandler_ofs
#else
lcall *%cs:INT13H_OFFSET (EXT_C (grub_drivemap_oldhandler))
#endif
lcall *%cs:INT13H_OFFSET (LOCAL (oldhandler))
push %bp
mov %sp, %bp
@ -111,9 +98,13 @@ norestore:
/* Far pointer to the old handler. Stored as a CS:IP in the style of real-mode
IVT entries (thus PI:SC in mem). */
VARIABLE(grub_drivemap_oldhandler)
LOCAL (oldhandler):
.word 0x0, 0x0
/* This label MUST be at the end of the copied block, since the installer code
reserves additional space for mappings at runtime and copies them over it. */
.align 2
.align 2
VARIABLE(grub_drivemap_mapstart)
LOCAL (mapstart):
.byte 0

79
commands/regexp.c Normal file
View file

@ -0,0 +1,79 @@
/* regexp.c -- The regexp command. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,2007 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/dl.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/command.h>
#include <regex.h>
static grub_err_t
grub_cmd_regexp (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
int argn = 0;
int matches = 0;
regex_t regex;
int ret;
grub_size_t s;
char *comperr;
grub_err_t err;
if (argc != 2)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "2 arguments expected");
ret = regcomp (&regex, args[0], RE_SYNTAX_GNU_AWK);
if (ret)
goto fail;
ret = regexec (&regex, args[1], 0, 0, 0);
if (!ret)
{
regfree (&regex);
return GRUB_ERR_NONE;
}
fail:
s = regerror (ret, &regex, 0, 0);
comperr = grub_malloc (s);
if (!comperr)
{
regfree (&regex);
return grub_errno;
}
regerror (ret, &regex, comperr, s);
err = grub_error (GRUB_ERR_TEST_FAILURE, "%s", comperr);
regfree (&regex);
grub_free (comperr);
return err;
}
static grub_command_t cmd;
GRUB_MOD_INIT(regexp)
{
cmd = grub_register_command ("regexp", grub_cmd_regexp,
"REGEXP STRING",
"Test if REGEXP matches STRING.");
}
GRUB_MOD_FINI(regexp)
{
grub_unregister_command (cmd);
}

View file

@ -56,7 +56,7 @@ grub_mkisofs_SOURCES = util/mkisofs/eltorito.c \
gnulib/error.c gnulib/progname.c
grub_mkisofs_CFLAGS = -D_FILE_OFFSET_BITS=64 \
-I$(srcdir)/util/mkisofs/include \
-Wno-all -Werror
-Wno-all -Werror $(GNULIB_UTIL_CFLAGS)
# For grub-fstest.
util/grub-fstest.c_DEPENDENCIES = grub_fstest_init.h
@ -98,8 +98,6 @@ grub_bin2h_SOURCES = gnulib/progname.c util/bin2h.c
# For the lexer.
grub_script.yy.c grub_script.yy.h: script/yylex.l
$(LEX) -o grub_script.yy.c --header-file=grub_script.yy.h $(srcdir)/script/yylex.l
sed -i 's/^#include.*\(<stdio\.h>\|<string\.h>\|<errno\.h>\|<stdlib\.h>\|<unistd\.h>\)//g' grub_script.yy.h
sed -i 's/^#include.*\(<stdio\.h>\|<string\.h>\|<errno\.h>\|<stdlib\.h>\|<unistd\.h>\)//g' grub_script.yy.c
DISTCLEANFILES += grub_script.yy.c grub_script.yy.h
# For grub-script-check.
@ -110,7 +108,7 @@ grub_script_check_SOURCES = gnulib/progname.c gnulib/getdelim.c gnulib/getline.c
kern/err.c kern/list.c \
kern/misc.c kern/env.c grub_script.tab.c \
grub_script.yy.c
grub_script_check_CFLAGS = $(GNULIB_UTIL_CFLAGS)
MOSTLYCLEANFILES += symlist.c kernel_syms.lst
DEFSYMFILES += kernel_syms.lst
@ -632,7 +630,7 @@ normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \
normal/misc.c normal/crypto.c normal/term.c normal/context.c \
script/main.c script/script.c script/execute.c \
script/function.c script/lexer.c grub_script.tab.c grub_script.yy.c
normal_mod_CFLAGS = $(COMMON_CFLAGS)
normal_mod_CFLAGS = $(COMMON_CFLAGS) $(POSIX_CFLAGS)
normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
ifneq (, $(FONT_SOURCE))
@ -763,6 +761,11 @@ charset_mod_SOURCES = lib/charset.c
charset_mod_CFLAGS = $(COMMON_CFLAGS)
charset_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += regexp.mod
regexp_mod_SOURCES = gnulib/regex.c commands/regexp.c
regexp_mod_CFLAGS = $(COMMON_CFLAGS) $(GNULIB_CFLAGS)
regexp_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += terminal.mod
terminal_mod_SOURCES = commands/terminal.c
terminal_mod_CFLAGS = $(COMMON_CFLAGS)

View file

@ -55,7 +55,7 @@ kernel_img_SOURCES = kern/i386/pc/startup.S \
term/i386/pc/console.c term/i386/vga_common.c \
symlist.c
kernel_img_HEADERS += machine/biosdisk.h machine/vga.h machine/vbe.h \
machine/pxe.h i386/pit.h machine/init.h
machine/pxe.h i386/pit.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

@ -33,17 +33,13 @@ setpci_mod_CFLAGS = $(COMMON_CFLAGS)
setpci_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += multiboot.mod
multiboot_mod_SOURCES = loader/i386/multiboot.c \
loader/i386/multiboot_mbi.c \
loader/multiboot_loader.c
multiboot_mod_SOURCES = loader/multiboot.c loader/i386/multiboot_mbi.c
multiboot_mod_CFLAGS = $(COMMON_CFLAGS)
multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS)
multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS)
pkglib_MODULES += multiboot2.mod
multiboot2_mod_SOURCES = loader/i386/multiboot.c \
loader/i386/multiboot_mbi.c \
loader/multiboot_loader.c
multiboot2_mod_SOURCES = loader/multiboot.c loader/multiboot_mbi2.c
multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2
multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS)
multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS)

View file

@ -30,4 +30,11 @@ relocator_mod_CFLAGS = $(COMMON_CFLAGS)
relocator_mod_ASFLAGS = $(COMMON_ASFLAGS)
relocator_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += multiboot2.mod
multiboot2_mod_SOURCES = loader/multiboot.c \
loader/multiboot_mbi2.c
multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2
multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS)
multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS)
include $(srcdir)/conf/common.mk

View file

@ -53,6 +53,18 @@ grub_script_vars1_SOURCES = tests/grub_script_vars1.in
check_SCRIPTS += grub_script_for1
grub_script_for1_SOURCES = tests/grub_script_for1.in
check_SCRIPTS += grub_script_while1
grub_script_while1_SOURCES = tests/grub_script_while1.in
check_SCRIPTS += grub_script_if
grub_script_if_SOURCES = tests/grub_script_if.in
check_SCRIPTS += grub_script_blanklines
grub_script_blanklines_SOURCES = tests/grub_script_blanklines.in
check_SCRIPTS += grub_script_final_semicolon
grub_script_final_semicolon_SOURCES = tests/grub_script_final_semicolon.in
# List of tests to execute on "make check"
# SCRIPTED_TESTS = example_scripted_test
# SCRIPTED_TESTS += example_grub_script_test
@ -63,6 +75,11 @@ SCRIPTED_TESTS = grub_script_echo1
SCRIPTED_TESTS += grub_script_echo_keywords
SCRIPTED_TESTS += grub_script_vars1
SCRIPTED_TESTS += grub_script_for1
SCRIPTED_TESTS += grub_script_while1
SCRIPTED_TESTS += grub_script_if
SCRIPTED_TESTS += grub_script_blanklines
SCRIPTED_TESTS += grub_script_final_semicolon
# dependencies between tests and testing-tools
$(SCRIPTED_TESTS): grub-shell grub-shell-tester

View file

@ -91,25 +91,24 @@ struct font_file_section
};
/* Replace unknown glyphs with a rounded question mark. */
static grub_uint8_t unknown_glyph_bitmap[] =
{
/* 76543210 */
0x7C, /* ooooo */
0x82, /* o o */
0xBA, /* o ooo o */
0xAA, /* o o o o */
0xAA, /* o o o o */
0x8A, /* o o o */
0x9A, /* o oo o */
0x92, /* o o o */
0x92, /* o o o */
0x92, /* o o o */
0x92, /* o o o */
0x82, /* o o */
0x92, /* o o o */
0x82, /* o o */
0x7C, /* ooooo */
0x00 /* */
static grub_uint8_t unknown_glyph_bitmap[] = {
/* 76543210 */
0x7C, /* ooooo */
0x82, /* o o */
0xBA, /* o ooo o */
0xAA, /* o o o o */
0xAA, /* o o o o */
0x8A, /* o o o */
0x9A, /* o oo o */
0x92, /* o o o */
0x92, /* o o o */
0x92, /* o o o */
0x92, /* o o o */
0x82, /* o o */
0x92, /* o o o */
0x82, /* o o */
0x7C, /* ooooo */
0x00 /* */
};
/* The "unknown glyph" glyph, used as a last resort. */
@ -130,7 +129,7 @@ static struct grub_font_glyph *ascii_font_glyph[0x80];
static struct grub_font_glyph *
ascii_glyph_lookup (grub_uint32_t code)
{
#ifdef USE_ASCII_FAILBACK
#ifdef USE_ASCII_FAILBACK
static int ascii_failback_initialized = 0;
if (code >= 0x80)
@ -140,14 +139,14 @@ ascii_glyph_lookup (grub_uint32_t code)
{
int current;
for (current = 0; current < 0x80; current++)
{
ascii_font_glyph[current] = grub_malloc(sizeof(struct grub_font_glyph)
+ ASCII_BITMAP_SIZE);
{
ascii_font_glyph[current] =
grub_malloc (sizeof (struct grub_font_glyph) + ASCII_BITMAP_SIZE);
ascii_font_glyph[current]->width = 8;
ascii_font_glyph[current]->height = 16;
ascii_font_glyph[current]->offset_x = 0;
ascii_font_glyph[current]->offset_y = -2;
ascii_font_glyph[current]->width = 8;
ascii_font_glyph[current]->height = 16;
ascii_font_glyph[current]->offset_x = 0;
ascii_font_glyph[current]->offset_y = -2;
ascii_font_glyph[current]->device_width = 8;
grub_memcpy (ascii_font_glyph[current]->bitmap,
@ -173,9 +172,9 @@ grub_font_loader_init (void)
return;
/* Make glyph for unknown glyph. */
unknown_glyph = grub_malloc(sizeof(struct grub_font_glyph)
+ sizeof(unknown_glyph_bitmap));
if (! unknown_glyph)
unknown_glyph = grub_malloc (sizeof (struct grub_font_glyph)
+ sizeof (unknown_glyph_bitmap));
if (!unknown_glyph)
return;
unknown_glyph->width = 8;
@ -183,13 +182,13 @@ grub_font_loader_init (void)
unknown_glyph->offset_x = 0;
unknown_glyph->offset_y = -3;
unknown_glyph->device_width = 8;
grub_memcpy(unknown_glyph->bitmap,
unknown_glyph_bitmap, sizeof(unknown_glyph_bitmap));
grub_memcpy (unknown_glyph->bitmap,
unknown_glyph_bitmap, sizeof (unknown_glyph_bitmap));
/* Initialize the null font. */
font_init (&null_font);
null_font.name = "<No Font>";
null_font.ascent = unknown_glyph->height-3;
null_font.ascent = unknown_glyph->height - 3;
null_font.descent = 3;
null_font.max_char_width = unknown_glyph->width;
null_font.max_char_height = unknown_glyph->height;
@ -247,7 +246,7 @@ open_section (grub_file_t file, struct font_file_section *section)
else if (retval < 0)
{
grub_error (GRUB_ERR_BAD_FONT,
"font format error: can't read section name");
"font format error: can't read section name");
return 1;
}
@ -262,7 +261,7 @@ open_section (grub_file_t file, struct font_file_section *section)
else if (retval < 0)
{
grub_error (GRUB_ERR_BAD_FONT,
"font format error: can't read section length");
"font format error: can't read section length");
return 1;
}
@ -283,22 +282,22 @@ open_section (grub_file_t file, struct font_file_section *section)
grub_errno is set appropriately). */
static int
load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
grub_font *font)
grub_font *font)
{
unsigned i;
grub_uint32_t last_code;
#if FONT_DEBUG >= 2
grub_printf("load_font_index(sect_length=%d)\n", sect_length);
grub_printf ("load_font_index(sect_length=%d)\n", sect_length);
#endif
/* Sanity check: ensure section length is divisible by the entry size. */
if ((sect_length % FONT_CHAR_INDEX_ENTRY_SIZE) != 0)
{
grub_error (GRUB_ERR_BAD_FONT,
"font file format error: character index length %d "
"is not a multiple of the entry size %d",
sect_length, FONT_CHAR_INDEX_ENTRY_SIZE);
"font file format error: character index length %d "
"is not a multiple of the entry size %d",
sect_length, FONT_CHAR_INDEX_ENTRY_SIZE);
return 1;
}
@ -307,11 +306,11 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
/* Allocate the character index array. */
font->char_index = grub_malloc (font->num_chars
* sizeof (struct char_index_entry));
if (! font->char_index)
* sizeof (struct char_index_entry));
if (!font->char_index)
return 1;
font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t));
if (! font->bmp_idx)
if (!font->bmp_idx)
{
grub_free (font->char_index);
return 1;
@ -320,7 +319,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
#if FONT_DEBUG >= 2
grub_printf("num_chars=%d)\n", font->num_chars);
grub_printf ("num_chars=%d)\n", font->num_chars);
#endif
last_code = 0;
@ -332,17 +331,17 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
/* Read code point value; convert to native byte order. */
if (grub_file_read (file, &entry->code, 4) != 4)
return 1;
return 1;
entry->code = grub_be_to_cpu32 (entry->code);
/* Verify that characters are in ascending order. */
if (i != 0 && entry->code <= last_code)
{
grub_error (GRUB_ERR_BAD_FONT,
"font characters not in ascending order: %u <= %u",
entry->code, last_code);
return 1;
}
{
grub_error (GRUB_ERR_BAD_FONT,
"font characters not in ascending order: %u <= %u",
entry->code, last_code);
return 1;
}
if (entry->code < 0x10000)
font->bmp_idx[entry->code] = i;
@ -351,11 +350,11 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
/* Read storage flags byte. */
if (grub_file_read (file, &entry->storage_flags, 1) != 1)
return 1;
return 1;
/* Read glyph data offset; convert to native byte order. */
if (grub_file_read (file, &entry->offset, 4) != 4)
return 1;
return 1;
entry->offset = grub_be_to_cpu32 (entry->offset);
/* No glyph loaded. Will be loaded on demand and cached thereafter. */
@ -364,7 +363,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct
#if FONT_DEBUG >= 5
/* Print the 1st 10 characters. */
if (i < 10)
grub_printf("c=%d o=%d\n", entry->code, entry->offset);
grub_printf ("c=%d o=%d\n", entry->code, entry->offset);
#endif
}
@ -380,7 +379,7 @@ read_section_as_string (struct font_file_section *section)
grub_ssize_t ret;
str = grub_malloc (section->length + 1);
if (! str)
if (!str)
return 0;
ret = grub_file_read (section->file, str, section->length);
@ -398,18 +397,18 @@ read_section_as_string (struct font_file_section *section)
which is stored into *VALUE.
Returns 0 upon success, nonzero upon failure. */
static int
read_section_as_short (struct font_file_section *section, grub_int16_t *value)
read_section_as_short (struct font_file_section *section,
grub_int16_t * value)
{
grub_uint16_t raw_value;
if (section->length != 2)
{
grub_error (GRUB_ERR_BAD_FONT,
"font file format error: section %c%c%c%c length "
"is %d but should be 2",
section->name[0], section->name[1],
section->name[2], section->name[3],
section->length);
"font file format error: section %c%c%c%c length "
"is %d but should be 2",
section->name[0], section->name[1],
section->name[2], section->name[3], section->length);
return 1;
}
if (grub_file_read (section->file, &raw_value, 2) != 2)
@ -430,7 +429,7 @@ grub_font_load (const char *filename)
grub_font_t font = 0;
#if FONT_DEBUG >= 1
grub_printf("add_font(%s)\n", filename);
grub_printf ("add_font(%s)\n", filename);
#endif
file = grub_buffile_open (filename, 1024);
@ -438,7 +437,7 @@ grub_font_load (const char *filename)
goto fail;
#if FONT_DEBUG >= 3
grub_printf("file opened\n");
grub_printf ("file opened\n");
#endif
/* Read the FILE section. It indicates the file format. */
@ -446,159 +445,166 @@ grub_font_load (const char *filename)
goto fail;
#if FONT_DEBUG >= 3
grub_printf("opened FILE section\n");
grub_printf ("opened FILE section\n");
#endif
if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FILE,
sizeof(FONT_FORMAT_SECTION_NAMES_FILE) - 1) != 0)
sizeof (FONT_FORMAT_SECTION_NAMES_FILE) - 1) != 0)
{
grub_error (GRUB_ERR_BAD_FONT,
"font file format error: 1st section must be FILE");
"font file format error: 1st section must be FILE");
goto fail;
}
#if FONT_DEBUG >= 3
grub_printf("section name ok\n");
grub_printf ("section name ok\n");
#endif
if (section.length != 4)
{
grub_error (GRUB_ERR_BAD_FONT,
"font file format error (file type ID length is %d "
"but should be 4)", section.length);
"font file format error (file type ID length is %d "
"but should be 4)", section.length);
goto fail;
}
#if FONT_DEBUG >= 3
grub_printf("section length ok\n");
grub_printf ("section length ok\n");
#endif
/* Check the file format type code. */
if (grub_file_read (file, magic, 4) != 4)
goto fail;
#if FONT_DEBUG >= 3
grub_printf("read magic ok\n");
grub_printf ("read magic ok\n");
#endif
if (grub_memcmp (magic, FONT_FORMAT_PFF2_MAGIC, 4) != 0)
{
grub_error (GRUB_ERR_BAD_FONT, "invalid font magic %x %x %x %x",
magic[0], magic[1], magic[2], magic[3]);
magic[0], magic[1], magic[2], magic[3]);
goto fail;
}
#if FONT_DEBUG >= 3
grub_printf("compare magic ok\n");
grub_printf ("compare magic ok\n");
#endif
/* Allocate the font object. */
font = (grub_font_t) grub_malloc (sizeof (struct grub_font));
if (! font)
if (!font)
goto fail;
font_init (font);
font->file = file;
#if FONT_DEBUG >= 3
grub_printf("allocate font ok; loading font info\n");
grub_printf ("allocate font ok; loading font info\n");
#endif
/* Load the font information. */
while (1)
{
if (open_section (file, &section) != 0)
{
if (section.eof)
break; /* Done reading the font file. */
else
goto fail;
}
{
if (section.eof)
break; /* Done reading the font file. */
else
goto fail;
}
#if FONT_DEBUG >= 2
grub_printf("opened section %c%c%c%c ok\n",
section.name[0], section.name[1],
section.name[2], section.name[3]);
grub_printf ("opened section %c%c%c%c ok\n",
section.name[0], section.name[1],
section.name[2], section.name[3]);
#endif
if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FONT_NAME,
sizeof(FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0)
{
font->name = read_section_as_string (&section);
if (!font->name)
goto fail;
}
sizeof (FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0)
{
font->name = read_section_as_string (&section);
if (!font->name)
goto fail;
}
else if (grub_memcmp (section.name,
FONT_FORMAT_SECTION_NAMES_POINT_SIZE,
sizeof(FONT_FORMAT_SECTION_NAMES_POINT_SIZE) - 1) == 0)
{
if (read_section_as_short (&section, &font->point_size) != 0)
goto fail;
}
FONT_FORMAT_SECTION_NAMES_POINT_SIZE,
sizeof (FONT_FORMAT_SECTION_NAMES_POINT_SIZE) -
1) == 0)
{
if (read_section_as_short (&section, &font->point_size) != 0)
goto fail;
}
else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_WEIGHT,
sizeof(FONT_FORMAT_SECTION_NAMES_WEIGHT) - 1) == 0)
{
char *wt;
wt = read_section_as_string (&section);
if (!wt)
continue;
/* Convert the weight string 'normal' or 'bold' into a number. */
if (grub_strcmp (wt, "normal") == 0)
font->weight = FONT_WEIGHT_NORMAL;
else if (grub_strcmp (wt, "bold") == 0)
font->weight = FONT_WEIGHT_BOLD;
grub_free (wt);
}
sizeof (FONT_FORMAT_SECTION_NAMES_WEIGHT) - 1)
== 0)
{
char *wt;
wt = read_section_as_string (&section);
if (!wt)
continue;
/* Convert the weight string 'normal' or 'bold' into a number. */
if (grub_strcmp (wt, "normal") == 0)
font->weight = FONT_WEIGHT_NORMAL;
else if (grub_strcmp (wt, "bold") == 0)
font->weight = FONT_WEIGHT_BOLD;
grub_free (wt);
}
else if (grub_memcmp (section.name,
FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH,
sizeof(FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH) - 1) == 0)
{
if (read_section_as_short (&section, &font->max_char_width) != 0)
goto fail;
}
FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH,
sizeof (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH)
- 1) == 0)
{
if (read_section_as_short (&section, &font->max_char_width) != 0)
goto fail;
}
else if (grub_memcmp (section.name,
FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT,
sizeof(FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT) - 1) == 0)
{
if (read_section_as_short (&section, &font->max_char_height) != 0)
goto fail;
}
FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT,
sizeof (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT)
- 1) == 0)
{
if (read_section_as_short (&section, &font->max_char_height) != 0)
goto fail;
}
else if (grub_memcmp (section.name,
FONT_FORMAT_SECTION_NAMES_ASCENT,
sizeof(FONT_FORMAT_SECTION_NAMES_ASCENT) - 1) == 0)
{
if (read_section_as_short (&section, &font->ascent) != 0)
goto fail;
}
FONT_FORMAT_SECTION_NAMES_ASCENT,
sizeof (FONT_FORMAT_SECTION_NAMES_ASCENT) - 1)
== 0)
{
if (read_section_as_short (&section, &font->ascent) != 0)
goto fail;
}
else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_DESCENT,
sizeof(FONT_FORMAT_SECTION_NAMES_DESCENT) - 1) == 0)
{
if (read_section_as_short (&section, &font->descent) != 0)
goto fail;
}
sizeof (FONT_FORMAT_SECTION_NAMES_DESCENT) - 1)
== 0)
{
if (read_section_as_short (&section, &font->descent) != 0)
goto fail;
}
else if (grub_memcmp (section.name,
FONT_FORMAT_SECTION_NAMES_CHAR_INDEX,
sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1) == 0)
{
if (load_font_index (file, section.length, font) != 0)
goto fail;
}
FONT_FORMAT_SECTION_NAMES_CHAR_INDEX,
sizeof (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) -
1) == 0)
{
if (load_font_index (file, section.length, font) != 0)
goto fail;
}
else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_DATA,
sizeof(FONT_FORMAT_SECTION_NAMES_DATA) - 1) == 0)
{
/* When the DATA section marker is reached, we stop reading. */
break;
}
sizeof (FONT_FORMAT_SECTION_NAMES_DATA) - 1) == 0)
{
/* When the DATA section marker is reached, we stop reading. */
break;
}
else
{
/* Unhandled section type, simply skip past it. */
{
/* Unhandled section type, simply skip past it. */
#if FONT_DEBUG >= 3
grub_printf("Unhandled section type, skipping.\n");
grub_printf ("Unhandled section type, skipping.\n");
#endif
grub_off_t section_end = grub_file_tell (file) + section.length;
if ((int) grub_file_seek (file, section_end) == -1)
goto fail;
}
grub_off_t section_end = grub_file_tell (file) + section.length;
if ((int) grub_file_seek (file, section_end) == -1)
goto fail;
}
}
if (! font->name)
if (!font->name)
{
grub_printf ("Note: Font has no name.\n");
font->name = grub_strdup ("Unknown");
@ -606,22 +612,19 @@ grub_font_load (const char *filename)
#if FONT_DEBUG >= 1
grub_printf ("Loaded font `%s'.\n"
"Ascent=%d Descent=%d MaxW=%d MaxH=%d Number of characters=%d.\n",
font->name,
font->ascent, font->descent,
font->max_char_width, font->max_char_height,
font->num_chars);
"Ascent=%d Descent=%d MaxW=%d MaxH=%d Number of characters=%d.\n",
font->name,
font->ascent, font->descent,
font->max_char_width, font->max_char_height, font->num_chars);
#endif
if (font->max_char_width == 0
|| font->max_char_height == 0
|| font->num_chars == 0
|| font->char_index == 0
|| font->ascent == 0
|| font->descent == 0)
|| font->char_index == 0 || font->ascent == 0 || font->descent == 0)
{
grub_error (GRUB_ERR_BAD_FONT,
"invalid font file: missing some required data");
"invalid font file: missing some required data");
goto fail;
}
@ -679,18 +682,18 @@ find_glyph (const grub_font_t font, grub_uint32_t code)
lo = 0;
hi = font->num_chars - 1;
if (! table)
if (!table)
return 0;
while (lo <= hi)
{
mid = lo + (hi - lo) / 2;
if (code < table[mid].code)
hi = mid - 1;
hi = mid - 1;
else if (code > table[mid].code)
lo = mid + 1;
lo = mid + 1;
else
return &table[mid];
return &table[mid];
}
return 0;
@ -716,12 +719,12 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
int len;
if (index_entry->glyph)
/* Return cached glyph. */
return index_entry->glyph;
/* Return cached glyph. */
return index_entry->glyph;
if (! font->file)
/* No open file, can't load any glyphs. */
return 0;
if (!font->file)
/* No open file, can't load any glyphs. */
return 0;
/* Make sure we can find glyphs for error messages. Push active
error message to error stack and reset error message. */
@ -730,23 +733,23 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
grub_file_seek (font->file, index_entry->offset);
/* Read the glyph width, height, and baseline. */
if (read_be_uint16(font->file, &width) != 0
|| read_be_uint16(font->file, &height) != 0
|| read_be_int16(font->file, &xoff) != 0
|| read_be_int16(font->file, &yoff) != 0
|| read_be_int16(font->file, &dwidth) != 0)
{
remove_font (font);
return 0;
}
if (read_be_uint16 (font->file, &width) != 0
|| read_be_uint16 (font->file, &height) != 0
|| read_be_int16 (font->file, &xoff) != 0
|| read_be_int16 (font->file, &yoff) != 0
|| read_be_int16 (font->file, &dwidth) != 0)
{
remove_font (font);
return 0;
}
len = (width * height + 7) / 8;
glyph = grub_malloc (sizeof (struct grub_font_glyph) + len);
if (! glyph)
{
remove_font (font);
return 0;
}
if (!glyph)
{
remove_font (font);
return 0;
}
glyph->font = font;
glyph->width = width;
@ -757,13 +760,13 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code)
/* Don't try to read empty bitmaps (e.g., space characters). */
if (len != 0)
{
if (grub_file_read (font->file, glyph->bitmap, len) != len)
{
remove_font (font);
return 0;
}
}
{
if (grub_file_read (font->file, glyph->bitmap, len) != len)
{
remove_font (font);
return 0;
}
}
/* Restore old error message. */
grub_error_pop ();
@ -787,7 +790,7 @@ free_font (grub_font_t font)
if (font)
{
if (font->file)
grub_file_close (font->file);
grub_file_close (font->file);
grub_free (font->name);
grub_free (font->family);
grub_free (font->char_index);
@ -804,7 +807,7 @@ register_font (grub_font_t font)
struct grub_font_node *node = 0;
node = grub_malloc (sizeof (struct grub_font_node));
if (! node)
if (!node)
return 1;
node->value = font;
@ -822,18 +825,17 @@ remove_font (grub_font_t font)
struct grub_font_node **nextp, *cur;
for (nextp = &grub_font_list, cur = *nextp;
cur;
nextp = &cur->next, cur = cur->next)
cur; nextp = &cur->next, cur = cur->next)
{
if (cur->value == font)
{
*nextp = cur->next;
{
*nextp = cur->next;
/* Free the node, but not the font itself. */
grub_free (cur);
/* Free the node, but not the font itself. */
grub_free (cur);
return;
}
return;
}
}
}
@ -850,7 +852,7 @@ grub_font_get (const char *font_name)
{
grub_font_t font = node->value;
if (grub_strcmp (font->name, font_name) == 0)
return font;
return font;
}
/* If no font by that name is found, return the first font in the list
@ -927,7 +929,7 @@ grub_font_get_string_width (grub_font_t font, const char *str)
const grub_uint8_t *ptr;
for (ptr = (const grub_uint8_t *) str, width = 0;
grub_utf8_to_ucs4 (&code, 1, ptr, -1, &ptr) > 0; )
grub_utf8_to_ucs4 (&code, 1, ptr, -1, &ptr) > 0;)
{
glyph = grub_font_get_glyph_with_fallback (font, code);
width += glyph->device_width;
@ -961,7 +963,7 @@ grub_font_get_glyph (grub_font_t font, grub_uint32_t code)
sizes are used so that tiny 8 point glyphs are not mixed into a string
of 24 point text unless there is no other choice. */
static int
get_font_diversity(grub_font_t a, grub_font_t b)
get_font_diversity (grub_font_t a, grub_font_t b)
{
int d;
@ -1011,7 +1013,7 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code)
/* First try to get the glyph from the specified font. */
glyph = grub_font_get_glyph_internal (font, code);
if (glyph)
return glyph;
return glyph;
}
/* Otherwise, search all loaded fonts for the glyph and use the one from
@ -1028,16 +1030,16 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code)
glyph = grub_font_get_glyph_internal (curfont, code);
if (glyph)
{
int d;
{
int d;
d = get_font_diversity (curfont, font);
if (d < best_diversity)
{
best_diversity = d;
best_glyph = glyph;
}
}
d = get_font_diversity (curfont, font);
if (d < best_diversity)
{
best_diversity = d;
best_glyph = glyph;
}
}
}
if (best_glyph)
@ -1052,9 +1054,8 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code)
baseline of the character, while the x coordinate designates the left
side location of the character. */
grub_err_t
grub_font_draw_glyph (struct grub_font_glyph *glyph,
grub_video_color_t color,
int left_x, int baseline_y)
grub_font_draw_glyph (struct grub_font_glyph * glyph,
grub_video_color_t color, int left_x, int baseline_y)
{
struct grub_video_bitmap glyph_bitmap;
@ -1065,8 +1066,7 @@ grub_font_draw_glyph (struct grub_font_glyph *glyph,
glyph_bitmap.mode_info.width = glyph->width;
glyph_bitmap.mode_info.height = glyph->height;
glyph_bitmap.mode_info.mode_type =
(1 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
| GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP;
(1 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS) | GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP;
glyph_bitmap.mode_info.blit_format = GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED;
glyph_bitmap.mode_info.bpp = 1;
@ -1081,11 +1081,11 @@ grub_font_draw_glyph (struct grub_font_glyph *glyph,
glyph_bitmap.mode_info.bg_green = 0;
glyph_bitmap.mode_info.bg_blue = 0;
glyph_bitmap.mode_info.bg_alpha = 0;
grub_video_unmap_color(color,
&glyph_bitmap.mode_info.fg_red,
&glyph_bitmap.mode_info.fg_green,
&glyph_bitmap.mode_info.fg_blue,
&glyph_bitmap.mode_info.fg_alpha);
grub_video_unmap_color (color,
&glyph_bitmap.mode_info.fg_red,
&glyph_bitmap.mode_info.fg_green,
&glyph_bitmap.mode_info.fg_blue,
&glyph_bitmap.mode_info.fg_alpha);
glyph_bitmap.data = glyph->bitmap;
int bitmap_left = left_x + glyph->offset_x;
@ -1093,9 +1093,8 @@ grub_font_draw_glyph (struct grub_font_glyph *glyph,
int bitmap_top = bitmap_bottom - glyph->height;
return grub_video_blit_bitmap (&glyph_bitmap, GRUB_VIDEO_BLIT_BLEND,
bitmap_left, bitmap_top,
0, 0,
glyph->width, glyph->height);
bitmap_left, bitmap_top,
0, 0, glyph->width, glyph->height);
}
/* Draw a UTF-8 string of text on the current video render target.
@ -1105,8 +1104,7 @@ grub_font_draw_glyph (struct grub_font_glyph *glyph,
a glyph from another loaded font may be used instead. */
grub_err_t
grub_font_draw_string (const char *str, grub_font_t font,
grub_video_color_t color,
int left_x, int baseline_y)
grub_video_color_t color, int left_x, int baseline_y)
{
int x;
struct grub_font_glyph *glyph;
@ -1114,15 +1112,13 @@ grub_font_draw_string (const char *str, grub_font_t font,
const grub_uint8_t *ptr;
for (ptr = (const grub_uint8_t *) str, x = left_x;
grub_utf8_to_ucs4 (&code, 1, ptr, -1, &ptr) > 0; )
grub_utf8_to_ucs4 (&code, 1, ptr, -1, &ptr) > 0;)
{
glyph = grub_font_get_glyph_with_fallback (font, code);
if (grub_font_draw_glyph (glyph, color, x, baseline_y)
!= GRUB_ERR_NONE)
return grub_errno;
if (grub_font_draw_glyph (glyph, color, x, baseline_y) != GRUB_ERR_NONE)
return grub_errno;
x += glyph->device_width;
}
return GRUB_ERR_NONE;
}

View file

@ -161,7 +161,7 @@ else
-rm -f $@
-rm -f $@.bin
$(TARGET_CC) $(#{prefix}_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@.bin #{pre_obj} #{mod_obj}
$(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -wd1106 -nu -nd $@.bin $@
$(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -wd1106 -ew2030 -ew2050 -nu -nd $@.bin $@
-rm -f $@.bin
endif
endif

View file

@ -1,7 +1,7 @@
/* Memory allocation on the stack.
Copyright (C) 1995, 1999, 2001-2004, 2006-2008 Free Software
Foundation, Inc.
Copyright (C) 1995, 1999, 2001-2004, 2006-2010 Free Software Foundation,
Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published

34
gnulib/argp-ba.c Normal file
View file

@ -0,0 +1,34 @@
/* Default definition for ARGP_PROGRAM_BUG_ADDRESS.
Copyright (C) 1996, 1997, 1999, 2009, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
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 3 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, see <http://www.gnu.org/licenses/>. */
/* If set by the user program, it should point to string that is the
bug-reporting address for the program. It will be printed by argp_help if
the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help
messages), embedded in a sentence that says something like `Report bugs to
ADDR.'. */
const char *argp_program_bug_address
/* This variable should be zero-initialized. On most systems, putting it into
BSS is sufficient. Not so on MacOS X 10.3 and 10.4, see
<http://lists.gnu.org/archive/html/bug-gnulib/2009-01/msg00329.html>
<http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00096.html>. */
#if defined __ELF__
/* On ELF systems, variables in BSS behave well. */
#else
= (const char *) 0
#endif
;

30
gnulib/argp-eexst.c Normal file
View file

@ -0,0 +1,30 @@
/* Default definition for ARGP_ERR_EXIT_STATUS
Copyright (C) 1997, 2009, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
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 3 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, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sysexits.h>
#include "argp.h"
/* The exit status that argp will use when exiting due to a parsing error.
If not defined or set by the user program, this defaults to EX_USAGE from
<sysexits.h>. */
error_t argp_err_exit_status = EX_USAGE;

435
gnulib/argp-fmtstream.c Normal file
View file

@ -0,0 +1,435 @@
/* Word-wrapping and line-truncating streams
Copyright (C) 1997-1999, 2001-2003, 2005, 2009-2010 Free Software
Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
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 3 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, see <http://www.gnu.org/licenses/>. */
/* This package emulates glibc `line_wrap_stream' semantics for systems that
don't have that. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <ctype.h>
#include "argp-fmtstream.h"
#include "argp-namefrob.h"
#ifndef ARGP_FMTSTREAM_USE_LINEWRAP
#ifndef isblank
#define isblank(ch) ((ch)==' ' || (ch)=='\t')
#endif
#if defined _LIBC && defined USE_IN_LIBIO
# include <wchar.h>
# include <libio/libioP.h>
# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
#endif
#define INIT_BUF_SIZE 200
#define PRINTF_SIZE_GUESS 150
/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
written on it with LMARGIN spaces and limits them to RMARGIN columns
total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
replacing the whitespace before them with a newline and WMARGIN spaces.
Otherwise, chars beyond RMARGIN are simply dropped until a newline.
Returns NULL if there was an error. */
argp_fmtstream_t
__argp_make_fmtstream (FILE *stream,
size_t lmargin, size_t rmargin, ssize_t wmargin)
{
argp_fmtstream_t fs;
fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream));
if (fs != NULL)
{
fs->stream = stream;
fs->lmargin = lmargin;
fs->rmargin = rmargin;
fs->wmargin = wmargin;
fs->point_col = 0;
fs->point_offs = 0;
fs->buf = (char *) malloc (INIT_BUF_SIZE);
if (! fs->buf)
{
free (fs);
fs = 0;
}
else
{
fs->p = fs->buf;
fs->end = fs->buf + INIT_BUF_SIZE;
}
}
return fs;
}
#if 0
/* Not exported. */
#ifdef weak_alias
weak_alias (__argp_make_fmtstream, argp_make_fmtstream)
#endif
#endif
/* Flush FS to its stream, and free it (but don't close the stream). */
void
__argp_fmtstream_free (argp_fmtstream_t fs)
{
__argp_fmtstream_update (fs);
if (fs->p > fs->buf)
{
#ifdef USE_IN_LIBIO
__fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
#else
fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
#endif
}
free (fs->buf);
free (fs);
}
#if 0
/* Not exported. */
#ifdef weak_alias
weak_alias (__argp_fmtstream_free, argp_fmtstream_free)
#endif
#endif
/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the
end of its buffer. This code is mostly from glibc stdio/linewrap.c. */
void
__argp_fmtstream_update (argp_fmtstream_t fs)
{
char *buf, *nl;
size_t len;
/* Scan the buffer for newlines. */
buf = fs->buf + fs->point_offs;
while (buf < fs->p)
{
size_t r;
if (fs->point_col == 0 && fs->lmargin != 0)
{
/* We are starting a new line. Print spaces to the left margin. */
const size_t pad = fs->lmargin;
if (fs->p + pad < fs->end)
{
/* We can fit in them in the buffer by moving the
buffer text up and filling in the beginning. */
memmove (buf + pad, buf, fs->p - buf);
fs->p += pad; /* Compensate for bigger buffer. */
memset (buf, ' ', pad); /* Fill in the spaces. */
buf += pad; /* Don't bother searching them. */
}
else
{
/* No buffer space for spaces. Must flush. */
size_t i;
for (i = 0; i < pad; i++)
{
#ifdef USE_IN_LIBIO
if (_IO_fwide (fs->stream, 0) > 0)
putwc_unlocked (L' ', fs->stream);
else
#endif
putc_unlocked (' ', fs->stream);
}
}
fs->point_col = pad;
}
len = fs->p - buf;
nl = memchr (buf, '\n', len);
if (fs->point_col < 0)
fs->point_col = 0;
if (!nl)
{
/* The buffer ends in a partial line. */
if (fs->point_col + len < fs->rmargin)
{
/* The remaining buffer text is a partial line and fits
within the maximum line width. Advance point for the
characters to be written and stop scanning. */
fs->point_col += len;
break;
}
else
/* Set the end-of-line pointer for the code below to
the end of the buffer. */
nl = fs->p;
}
else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin)
{
/* The buffer contains a full line that fits within the maximum
line width. Reset point and scan the next line. */
fs->point_col = 0;
buf = nl + 1;
continue;
}
/* This line is too long. */
r = fs->rmargin - 1;
if (fs->wmargin < 0)
{
/* Truncate the line by overwriting the excess with the
newline and anything after it in the buffer. */
if (nl < fs->p)
{
memmove (buf + (r - fs->point_col), nl, fs->p - nl);
fs->p -= buf + (r - fs->point_col) - nl;
/* Reset point for the next line and start scanning it. */
fs->point_col = 0;
buf += r + 1; /* Skip full line plus \n. */
}
else
{
/* The buffer ends with a partial line that is beyond the
maximum line width. Advance point for the characters
written, and discard those past the max from the buffer. */
fs->point_col += len;
fs->p -= fs->point_col - r;
break;
}
}
else
{
/* Do word wrap. Go to the column just past the maximum line
width and scan back for the beginning of the word there.
Then insert a line break. */
char *p, *nextline;
int i;
p = buf + (r + 1 - fs->point_col);
while (p >= buf && !isblank ((unsigned char) *p))
--p;
nextline = p + 1; /* This will begin the next line. */
if (nextline > buf)
{
/* Swallow separating blanks. */
if (p >= buf)
do
--p;
while (p >= buf && isblank ((unsigned char) *p));
nl = p + 1; /* The newline will replace the first blank. */
}
else
{
/* A single word that is greater than the maximum line width.
Oh well. Put it on an overlong line by itself. */
p = buf + (r + 1 - fs->point_col);
/* Find the end of the long word. */
if (p < nl)
do
++p;
while (p < nl && !isblank ((unsigned char) *p));
if (p == nl)
{
/* It already ends a line. No fussing required. */
fs->point_col = 0;
buf = nl + 1;
continue;
}
/* We will move the newline to replace the first blank. */
nl = p;
/* Swallow separating blanks. */
do
++p;
while (isblank ((unsigned char) *p));
/* The next line will start here. */
nextline = p;
}
/* Note: There are a bunch of tests below for
NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall
at the end of the buffer, and NEXTLINE is in fact empty (and so
we need not be careful to maintain its contents). */
if ((nextline == buf + len + 1
? fs->end - nl < fs->wmargin + 1
: nextline - (nl + 1) < fs->wmargin)
&& fs->p > nextline)
{
/* The margin needs more blanks than we removed. */
if (fs->end - fs->p > fs->wmargin + 1)
/* Make some space for them. */
{
size_t mv = fs->p - nextline;
memmove (nl + 1 + fs->wmargin, nextline, mv);
nextline = nl + 1 + fs->wmargin;
len = nextline + mv - buf;
*nl++ = '\n';
}
else
/* Output the first line so we can use the space. */
{
#ifdef _LIBC
__fxprintf (fs->stream, "%.*s\n",
(int) (nl - fs->buf), fs->buf);
#else
if (nl > fs->buf)
fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream);
putc_unlocked ('\n', fs->stream);
#endif
len += buf - fs->buf;
nl = buf = fs->buf;
}
}
else
/* We can fit the newline and blanks in before
the next word. */
*nl++ = '\n';
if (nextline - nl >= fs->wmargin
|| (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin))
/* Add blanks up to the wrap margin column. */
for (i = 0; i < fs->wmargin; ++i)
*nl++ = ' ';
else
for (i = 0; i < fs->wmargin; ++i)
#ifdef USE_IN_LIBIO
if (_IO_fwide (fs->stream, 0) > 0)
putwc_unlocked (L' ', fs->stream);
else
#endif
putc_unlocked (' ', fs->stream);
/* Copy the tail of the original buffer into the current buffer
position. */
if (nl < nextline)
memmove (nl, nextline, buf + len - nextline);
len -= nextline - buf;
/* Continue the scan on the remaining lines in the buffer. */
buf = nl;
/* Restore bufp to include all the remaining text. */
fs->p = nl + len;
/* Reset the counter of what has been output this line. If wmargin
is 0, we want to avoid the lmargin getting added, so we set
point_col to a magic value of -1 in that case. */
fs->point_col = fs->wmargin ? fs->wmargin : -1;
}
}
/* Remember that we've scanned as far as the end of the buffer. */
fs->point_offs = fs->p - fs->buf;
}
/* Ensure that FS has space for AMOUNT more bytes in its buffer, either by
growing the buffer, or by flushing it. True is returned iff we succeed. */
int
__argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount)
{
if ((size_t) (fs->end - fs->p) < amount)
{
ssize_t wrote;
/* Flush FS's buffer. */
__argp_fmtstream_update (fs);
#ifdef _LIBC
__fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
wrote = fs->p - fs->buf;
#else
wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
#endif
if (wrote == fs->p - fs->buf)
{
fs->p = fs->buf;
fs->point_offs = 0;
}
else
{
fs->p -= wrote;
fs->point_offs -= wrote;
memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf);
return 0;
}
if ((size_t) (fs->end - fs->buf) < amount)
/* Gotta grow the buffer. */
{
size_t old_size = fs->end - fs->buf;
size_t new_size = old_size + amount;
char *new_buf;
if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size)))
{
__set_errno (ENOMEM);
return 0;
}
fs->buf = new_buf;
fs->end = new_buf + new_size;
fs->p = fs->buf;
}
}
return 1;
}
ssize_t
__argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...)
{
int out;
size_t avail;
size_t size_guess = PRINTF_SIZE_GUESS; /* How much space to reserve. */
do
{
va_list args;
if (! __argp_fmtstream_ensure (fs, size_guess))
return -1;
va_start (args, fmt);
avail = fs->end - fs->p;
out = __vsnprintf (fs->p, avail, fmt, args);
va_end (args);
if ((size_t) out >= avail)
size_guess = out + 1;
}
while ((size_t) out >= avail);
fs->p += out;
return out;
}
#if 0
/* Not exported. */
#ifdef weak_alias
weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf)
#endif
#endif
#endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */

354
gnulib/argp-fmtstream.h Normal file
View file

@ -0,0 +1,354 @@
/* Word-wrapping and line-truncating streams.
Copyright (C) 1997, 2006-2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
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 3 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, see <http://www.gnu.org/licenses/>. */
/* This package emulates glibc `line_wrap_stream' semantics for systems that
don't have that. If the system does have it, it is just a wrapper for
that. This header file is only used internally while compiling argp, and
shouldn't be installed. */
#ifndef _ARGP_FMTSTREAM_H
#define _ARGP_FMTSTREAM_H
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifndef __attribute__
/* The __attribute__ feature is available in gcc versions 2.5 and later.
The __-protected variants of the attributes 'format' and 'printf' are
accepted by gcc versions 2.6.4 (effectively 2.7) and later.
We enable __attribute__ only if these are supported too, because
gnulib and libintl do '#define printf __printf__' when they override
the 'printf' function. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
# define __attribute__(Spec) /* empty */
# endif
#endif
#if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \
|| (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H))
/* line_wrap_stream is available, so use that. */
#define ARGP_FMTSTREAM_USE_LINEWRAP
#endif
#ifdef ARGP_FMTSTREAM_USE_LINEWRAP
/* Just be a simple wrapper for line_wrap_stream; the semantics are
*slightly* different, as line_wrap_stream doesn't actually make a new
object, it just modifies the given stream (reversibly) to do
line-wrapping. Since we control who uses this code, it doesn't matter. */
#include <linewrap.h>
typedef FILE *argp_fmtstream_t;
#define argp_make_fmtstream line_wrap_stream
#define __argp_make_fmtstream line_wrap_stream
#define argp_fmtstream_free line_unwrap_stream
#define __argp_fmtstream_free line_unwrap_stream
#define __argp_fmtstream_putc(fs,ch) putc(ch,fs)
#define argp_fmtstream_putc(fs,ch) putc(ch,fs)
#define __argp_fmtstream_puts(fs,str) fputs(str,fs)
#define argp_fmtstream_puts(fs,str) fputs(str,fs)
#define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
#define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs)
#define __argp_fmtstream_printf fprintf
#define argp_fmtstream_printf fprintf
#define __argp_fmtstream_lmargin line_wrap_lmargin
#define argp_fmtstream_lmargin line_wrap_lmargin
#define __argp_fmtstream_set_lmargin line_wrap_set_lmargin
#define argp_fmtstream_set_lmargin line_wrap_set_lmargin
#define __argp_fmtstream_rmargin line_wrap_rmargin
#define argp_fmtstream_rmargin line_wrap_rmargin
#define __argp_fmtstream_set_rmargin line_wrap_set_rmargin
#define argp_fmtstream_set_rmargin line_wrap_set_rmargin
#define __argp_fmtstream_wmargin line_wrap_wmargin
#define argp_fmtstream_wmargin line_wrap_wmargin
#define __argp_fmtstream_set_wmargin line_wrap_set_wmargin
#define argp_fmtstream_set_wmargin line_wrap_set_wmargin
#define __argp_fmtstream_point line_wrap_point
#define argp_fmtstream_point line_wrap_point
#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */
/* Guess we have to define our own version. */
struct argp_fmtstream
{
FILE *stream; /* The stream we're outputting to. */
size_t lmargin, rmargin; /* Left and right margins. */
ssize_t wmargin; /* Margin to wrap to, or -1 to truncate. */
/* Point in buffer to which we've processed for wrapping, but not output. */
size_t point_offs;
/* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin. */
ssize_t point_col;
char *buf; /* Output buffer. */
char *p; /* Current end of text in BUF. */
char *end; /* Absolute end of BUF. */
};
typedef struct argp_fmtstream *argp_fmtstream_t;
/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines
written on it with LMARGIN spaces and limits them to RMARGIN columns
total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by
replacing the whitespace before them with a newline and WMARGIN spaces.
Otherwise, chars beyond RMARGIN are simply dropped until a newline.
Returns NULL if there was an error. */
extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream,
size_t __lmargin,
size_t __rmargin,
ssize_t __wmargin);
extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream,
size_t __lmargin,
size_t __rmargin,
ssize_t __wmargin);
/* Flush __FS to its stream, and free it (but don't close the stream). */
extern void __argp_fmtstream_free (argp_fmtstream_t __fs);
extern void argp_fmtstream_free (argp_fmtstream_t __fs);
extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs,
const char *__fmt, ...)
__attribute__ ((__format__ (printf, 2, 3)));
extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs,
const char *__fmt, ...)
__attribute__ ((__format__ (printf, 2, 3)));
#if _LIBC || !defined __OPTIMIZE__
extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch);
extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str);
extern int argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str);
extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs,
const char *__str, size_t __len);
extern size_t argp_fmtstream_write (argp_fmtstream_t __fs,
const char *__str, size_t __len);
#endif
/* Access macros for various bits of state. */
#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin)
#define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin)
#define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin)
#define __argp_fmtstream_lmargin argp_fmtstream_lmargin
#define __argp_fmtstream_rmargin argp_fmtstream_rmargin
#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
#if _LIBC || !defined __OPTIMIZE__
/* Set __FS's left margin to LMARGIN and return the old value. */
extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
size_t __lmargin);
extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs,
size_t __lmargin);
/* Set __FS's right margin to __RMARGIN and return the old value. */
extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
size_t __rmargin);
extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs,
size_t __rmargin);
/* Set __FS's wrap margin to __WMARGIN and return the old value. */
extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
size_t __wmargin);
extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs,
size_t __wmargin);
/* Return the column number of the current output point in __FS. */
extern size_t argp_fmtstream_point (argp_fmtstream_t __fs);
extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs);
#endif
/* Internal routines. */
extern void _argp_fmtstream_update (argp_fmtstream_t __fs);
extern void __argp_fmtstream_update (argp_fmtstream_t __fs);
extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount);
#ifdef __OPTIMIZE__
/* Inline versions of above routines. */
#if !_LIBC
#define __argp_fmtstream_putc argp_fmtstream_putc
#define __argp_fmtstream_puts argp_fmtstream_puts
#define __argp_fmtstream_write argp_fmtstream_write
#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
#define __argp_fmtstream_point argp_fmtstream_point
#define __argp_fmtstream_update _argp_fmtstream_update
#define __argp_fmtstream_ensure _argp_fmtstream_ensure
#endif
#ifndef ARGP_FS_EI
# ifdef __GNUC__
/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
inline semantics, unless -fgnu89-inline is used. It defines a macro
__GNUC_STDC_INLINE__ to indicate this situation or a macro
__GNUC_GNU_INLINE__ to indicate the opposite situation.
GCC 4.2 with -std=c99 or -std=gnu99 implements the GNU C inline
semantics but warns, unless -fgnu89-inline is used:
warning: C99 inline functions are not supported; using GNU89
warning: to disable this warning use -fgnu89-inline or the gnu_inline function attribute
It defines a macro __GNUC_GNU_INLINE__ to indicate this situation.
Whereas Apple GCC 4.0.1 build 5479 without -std=c99 or -std=gnu99
implements the GNU C inline semantics and defines the macro
__GNUC_GNU_INLINE__, but it does not warn and does not support
__attribute__ ((__gnu_inline__)).
All in all, these are the possible combinations. For every compiler,
we need to choose ARGP_FS_EI so that the corresponding table cell
contains an "ok".
\ ARGP_FS_EI inline extern extern
\ inline inline
CC \ __attribute__
((gnu_inline))
gcc 4.3.0 error ok ok
gcc 4.3.0 -std=gnu99 -fgnu89-inline error ok ok
gcc 4.3.0 -std=gnu99 ok error ok
gcc 4.2.2 error ok ok
gcc 4.2.2 -std=gnu99 -fgnu89-inline error ok ok
gcc 4.2.2 -std=gnu99 error warning ok
gcc 4.1.2 error ok warning
gcc 4.1.2 -std=gnu99 error ok warning
Apple gcc 4.0.1 error ok warning
Apple gcc 4.0.1 -std=gnu99 ok error warning
*/
# if defined __GNUC_STDC_INLINE__
# define ARGP_FS_EI inline
# elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)
# define ARGP_FS_EI extern inline __attribute__ ((__gnu_inline__))
# else
# define ARGP_FS_EI extern inline
# endif
# else
/* With other compilers, assume the ISO C99 meaning of 'inline', if
the compiler supports 'inline' at all. */
# define ARGP_FS_EI inline
# endif
#endif
ARGP_FS_EI size_t
__argp_fmtstream_write (argp_fmtstream_t __fs,
const char *__str, size_t __len)
{
if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
{
memcpy (__fs->p, __str, __len);
__fs->p += __len;
return __len;
}
else
return 0;
}
ARGP_FS_EI int
__argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str)
{
size_t __len = strlen (__str);
if (__len)
{
size_t __wrote = __argp_fmtstream_write (__fs, __str, __len);
return __wrote == __len ? 0 : -1;
}
else
return 0;
}
ARGP_FS_EI int
__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch)
{
if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1))
return *__fs->p++ = __ch;
else
return EOF;
}
/* Set __FS's left margin to __LMARGIN and return the old value. */
ARGP_FS_EI size_t
__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin)
{
size_t __old;
if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
__argp_fmtstream_update (__fs);
__old = __fs->lmargin;
__fs->lmargin = __lmargin;
return __old;
}
/* Set __FS's right margin to __RMARGIN and return the old value. */
ARGP_FS_EI size_t
__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin)
{
size_t __old;
if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
__argp_fmtstream_update (__fs);
__old = __fs->rmargin;
__fs->rmargin = __rmargin;
return __old;
}
/* Set FS's wrap margin to __WMARGIN and return the old value. */
ARGP_FS_EI size_t
__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin)
{
size_t __old;
if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
__argp_fmtstream_update (__fs);
__old = __fs->wmargin;
__fs->wmargin = __wmargin;
return __old;
}
/* Return the column number of the current output point in __FS. */
ARGP_FS_EI size_t
__argp_fmtstream_point (argp_fmtstream_t __fs)
{
if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs)
__argp_fmtstream_update (__fs);
return __fs->point_col >= 0 ? __fs->point_col : 0;
}
#if !_LIBC
#undef __argp_fmtstream_putc
#undef __argp_fmtstream_puts
#undef __argp_fmtstream_write
#undef __argp_fmtstream_set_lmargin
#undef __argp_fmtstream_set_rmargin
#undef __argp_fmtstream_set_wmargin
#undef __argp_fmtstream_point
#undef __argp_fmtstream_update
#undef __argp_fmtstream_ensure
#endif
#endif /* __OPTIMIZE__ */
#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */
#endif /* argp-fmtstream.h */

42
gnulib/argp-fs-xinl.c Normal file
View file

@ -0,0 +1,42 @@
/* Real definitions for extern inline functions in argp-fmtstream.h
Copyright (C) 1997, 2003, 2004, 2009, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
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 3 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, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#define ARGP_FS_EI
#undef __OPTIMIZE__
#define __OPTIMIZE__ 1
#include "argp-fmtstream.h"
#if 0
/* Not exported. */
/* Add weak aliases. */
#if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias)
weak_alias (__argp_fmtstream_putc, argp_fmtstream_putc)
weak_alias (__argp_fmtstream_puts, argp_fmtstream_puts)
weak_alias (__argp_fmtstream_write, argp_fmtstream_write)
weak_alias (__argp_fmtstream_set_lmargin, argp_fmtstream_set_lmargin)
weak_alias (__argp_fmtstream_set_rmargin, argp_fmtstream_set_rmargin)
weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin)
weak_alias (__argp_fmtstream_point, argp_fmtstream_point)
#endif
#endif

1951
gnulib/argp-help.c Normal file

File diff suppressed because it is too large Load diff

157
gnulib/argp-namefrob.h Normal file
View file

@ -0,0 +1,157 @@
/* Name frobnication for compiling argp outside of glibc
Copyright (C) 1997, 2003, 2007, 2009, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
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 3 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, see <http://www.gnu.org/licenses/>. */
#if !_LIBC
/* This code is written for inclusion in gnu-libc, and uses names in the
namespace reserved for libc. If we're not compiling in libc, define those
names to be the normal ones instead. */
/* argp-parse functions */
#undef __argp_parse
#define __argp_parse argp_parse
#undef __option_is_end
#define __option_is_end _option_is_end
#undef __option_is_short
#define __option_is_short _option_is_short
#undef __argp_input
#define __argp_input _argp_input
/* argp-help functions */
#undef __argp_help
#define __argp_help argp_help
#undef __argp_error
#define __argp_error argp_error
#undef __argp_failure
#define __argp_failure argp_failure
#undef __argp_state_help
#define __argp_state_help argp_state_help
#undef __argp_usage
#define __argp_usage argp_usage
/* argp-fmtstream functions */
#undef __argp_make_fmtstream
#define __argp_make_fmtstream argp_make_fmtstream
#undef __argp_fmtstream_free
#define __argp_fmtstream_free argp_fmtstream_free
#undef __argp_fmtstream_putc
#define __argp_fmtstream_putc argp_fmtstream_putc
#undef __argp_fmtstream_puts
#define __argp_fmtstream_puts argp_fmtstream_puts
#undef __argp_fmtstream_write
#define __argp_fmtstream_write argp_fmtstream_write
#undef __argp_fmtstream_printf
#define __argp_fmtstream_printf argp_fmtstream_printf
#undef __argp_fmtstream_set_lmargin
#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin
#undef __argp_fmtstream_set_rmargin
#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin
#undef __argp_fmtstream_set_wmargin
#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin
#undef __argp_fmtstream_point
#define __argp_fmtstream_point argp_fmtstream_point
#undef __argp_fmtstream_update
#define __argp_fmtstream_update _argp_fmtstream_update
#undef __argp_fmtstream_ensure
#define __argp_fmtstream_ensure _argp_fmtstream_ensure
#undef __argp_fmtstream_lmargin
#define __argp_fmtstream_lmargin argp_fmtstream_lmargin
#undef __argp_fmtstream_rmargin
#define __argp_fmtstream_rmargin argp_fmtstream_rmargin
#undef __argp_fmtstream_wmargin
#define __argp_fmtstream_wmargin argp_fmtstream_wmargin
/* normal libc functions we call */
#undef __flockfile
#define __flockfile flockfile
#undef __funlockfile
#define __funlockfile funlockfile
#undef __mempcpy
#define __mempcpy mempcpy
#undef __sleep
#define __sleep sleep
#undef __strcasecmp
#define __strcasecmp strcasecmp
#undef __strchrnul
#define __strchrnul strchrnul
#undef __strerror_r
#define __strerror_r strerror_r
#undef __strndup
#define __strndup strndup
#undef __vsnprintf
#define __vsnprintf vsnprintf
#if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED
# define clearerr_unlocked(x) clearerr (x)
#endif
#if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED
# define feof_unlocked(x) feof (x)
# endif
#if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED
# define ferror_unlocked(x) ferror (x)
# endif
#if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED
# define fflush_unlocked(x) fflush (x)
# endif
#if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED
# define fgets_unlocked(x,y,z) fgets (x,y,z)
# endif
#if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED
# define fputc_unlocked(x,y) fputc (x,y)
# endif
#if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED
# define fputs_unlocked(x,y) fputs (x,y)
# endif
#if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED
# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
# endif
#if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED
# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
# endif
#if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED
# define getc_unlocked(x) getc (x)
# endif
#if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED
# define getchar_unlocked() getchar ()
# endif
#if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED
# define putc_unlocked(x,y) putc (x,y)
# endif
#if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED
# define putchar_unlocked(x) putchar (x)
# endif
#endif /* !_LIBC */
#ifndef __set_errno
#define __set_errno(e) (errno = (e))
#endif
#if defined GNULIB_ARGP_DISABLE_DIRNAME
# define __argp_base_name(arg) arg
#elif defined GNULIB_ARGP_EXTERN_BASENAME
extern char *__argp_base_name (const char *arg);
#else
# include "dirname.h"
# define __argp_base_name last_component
#endif
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
# define __argp_short_program_name() (program_invocation_short_name)
#else
extern char *__argp_short_program_name (void);
#endif

952
gnulib/argp-parse.c Normal file
View file

@ -0,0 +1,952 @@
/* Hierarchial argument parsing, layered over getopt
Copyright (C) 1995-2000, 2002-2004, 2009-2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
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 3 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, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <alloca.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <getopt.h>
#include <getopt_int.h>
#ifdef _LIBC
# include <libintl.h>
# undef dgettext
# define dgettext(domain, msgid) \
INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
#else
# include "gettext.h"
#endif
#define N_(msgid) msgid
#include "argp.h"
#include "argp-namefrob.h"
#define alignof(type) offsetof (struct { char c; type x; }, x)
#define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d))
/* Getopt return values. */
#define KEY_END (-1) /* The end of the options. */
#define KEY_ARG 1 /* A non-option argument. */
#define KEY_ERR '?' /* An error parsing the options. */
/* The meta-argument used to prevent any further arguments being interpreted
as options. */
#define QUOTE "--"
/* The number of bits we steal in a long-option value for our own use. */
#define GROUP_BITS CHAR_BIT
/* The number of bits available for the user value. */
#define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS)
#define USER_MASK ((1 << USER_BITS) - 1)
/* EZ alias for ARGP_ERR_UNKNOWN. */
#define EBADKEY ARGP_ERR_UNKNOWN
/* Default options. */
/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep
for one second intervals, decrementing _ARGP_HANG until it's zero. Thus
you can force the program to continue by attaching a debugger and setting
it to 0 yourself. */
static volatile int _argp_hang;
#define OPT_PROGNAME -2
#define OPT_USAGE -3
#define OPT_HANG -4
static const struct argp_option argp_default_options[] =
{
{"help", '?', 0, 0, N_("give this help list"), -1},
{"usage", OPT_USAGE, 0, 0, N_("give a short usage message"), 0},
{"program-name",OPT_PROGNAME,N_("NAME"), OPTION_HIDDEN, N_("set the program name"), 0},
{"HANG", OPT_HANG, N_("SECS"), OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
N_("hang for SECS seconds (default 3600)"), 0},
{NULL, 0, 0, 0, NULL, 0}
};
static error_t
argp_default_parser (int key, char *arg, struct argp_state *state)
{
switch (key)
{
case '?':
__argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP);
break;
case OPT_USAGE:
__argp_state_help (state, state->out_stream,
ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
break;
case OPT_PROGNAME: /* Set the program name. */
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_NAME
program_invocation_name = arg;
#endif
/* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka
__PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined
to be that, so we have to be a bit careful here.] */
/* Update what we use for messages. */
state->name = __argp_base_name (arg);
#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
program_invocation_short_name = state->name;
#endif
if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS))
== ARGP_PARSE_ARGV0)
/* Update what getopt uses too. */
state->argv[0] = arg;
break;
case OPT_HANG:
_argp_hang = atoi (arg ? arg : "3600");
while (_argp_hang-- > 0)
__sleep (1);
break;
default:
return EBADKEY;
}
return 0;
}
static const struct argp argp_default_argp =
{argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"};
static const struct argp_option argp_version_options[] =
{
{"version", 'V', 0, 0, N_("print program version"), -1},
{NULL, 0, 0, 0, NULL, 0}
};
static error_t
argp_version_parser (int key, char *arg, struct argp_state *state)
{
switch (key)
{
case 'V':
if (argp_program_version_hook)
(*argp_program_version_hook) (state->out_stream, state);
else if (argp_program_version)
fprintf (state->out_stream, "%s\n", argp_program_version);
else
__argp_error (state, dgettext (state->root_argp->argp_domain,
"(PROGRAM ERROR) No version known!?"));
if (! (state->flags & ARGP_NO_EXIT))
exit (0);
break;
default:
return EBADKEY;
}
return 0;
}
static const struct argp argp_version_argp =
{argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"};
/* Returns the offset into the getopt long options array LONG_OPTIONS of a
long option with called NAME, or -1 if none is found. Passing NULL as
NAME will return the number of options. */
static int
find_long_option (struct option *long_options, const char *name)
{
struct option *l = long_options;
while (l->name != NULL)
if (name != NULL && strcmp (l->name, name) == 0)
return l - long_options;
else
l++;
if (name == NULL)
return l - long_options;
else
return -1;
}
/* The state of a `group' during parsing. Each group corresponds to a
particular argp structure from the tree of such descending from the top
level argp passed to argp_parse. */
struct group
{
/* This group's parsing function. */
argp_parser_t parser;
/* Which argp this group is from. */
const struct argp *argp;
/* Points to the point in SHORT_OPTS corresponding to the end of the short
options for this group. We use it to determine from which group a
particular short options is from. */
char *short_end;
/* The number of non-option args sucessfully handled by this parser. */
unsigned args_processed;
/* This group's parser's parent's group. */
struct group *parent;
unsigned parent_index; /* And the our position in the parent. */
/* These fields are swapped into and out of the state structure when
calling this group's parser. */
void *input, **child_inputs;
void *hook;
};
/* Call GROUP's parser with KEY and ARG, swapping any group-specific info
from STATE before calling, and back into state afterwards. If GROUP has
no parser, EBADKEY is returned. */
static error_t
group_parse (struct group *group, struct argp_state *state, int key, char *arg)
{
if (group->parser)
{
error_t err;
state->hook = group->hook;
state->input = group->input;
state->child_inputs = group->child_inputs;
state->arg_num = group->args_processed;
err = (*group->parser)(key, arg, state);
group->hook = state->hook;
return err;
}
else
return EBADKEY;
}
struct parser
{
const struct argp *argp;
/* SHORT_OPTS is the getopt short options string for the union of all the
groups of options. */
char *short_opts;
/* LONG_OPTS is the array of getop long option structures for the union of
all the groups of options. */
struct option *long_opts;
/* OPT_DATA is the getopt data used for the re-entrant getopt. */
struct _getopt_data opt_data;
/* States of the various parsing groups. */
struct group *groups;
/* The end of the GROUPS array. */
struct group *egroup;
/* An vector containing storage for the CHILD_INPUTS field in all groups. */
void **child_inputs;
/* True if we think using getopt is still useful; if false, then
remaining arguments are just passed verbatim with ARGP_KEY_ARG. This is
cleared whenever getopt returns KEY_END, but may be set again if the user
moves the next argument pointer backwards. */
int try_getopt;
/* State block supplied to parsing routines. */
struct argp_state state;
/* Memory used by this parser. */
void *storage;
};
/* The next usable entries in the various parser tables being filled in by
convert_options. */
struct parser_convert_state
{
struct parser *parser;
char *short_end;
struct option *long_end;
void **child_inputs_end;
};
/* Converts all options in ARGP (which is put in GROUP) and ancestors
into getopt options stored in SHORT_OPTS and LONG_OPTS; SHORT_END and
CVT->LONG_END are the points at which new options are added. Returns the
next unused group entry. CVT holds state used during the conversion. */
static struct group *
convert_options (const struct argp *argp,
struct group *parent, unsigned parent_index,
struct group *group, struct parser_convert_state *cvt)
{
/* REAL is the most recent non-alias value of OPT. */
const struct argp_option *real = argp->options;
const struct argp_child *children = argp->children;
if (real || argp->parser)
{
const struct argp_option *opt;
if (real)
for (opt = real; !__option_is_end (opt); opt++)
{
if (! (opt->flags & OPTION_ALIAS))
/* OPT isn't an alias, so we can use values from it. */
real = opt;
if (! (real->flags & OPTION_DOC))
/* A real option (not just documentation). */
{
if (__option_is_short (opt))
/* OPT can be used as a short option. */
{
*cvt->short_end++ = opt->key;
if (real->arg)
{
*cvt->short_end++ = ':';
if (real->flags & OPTION_ARG_OPTIONAL)
*cvt->short_end++ = ':';
}
*cvt->short_end = '\0'; /* keep 0 terminated */
}
if (opt->name
&& find_long_option (cvt->parser->long_opts, opt->name) < 0)
/* OPT can be used as a long option. */
{
cvt->long_end->name = opt->name;
cvt->long_end->has_arg =
(real->arg
? (real->flags & OPTION_ARG_OPTIONAL
? optional_argument
: required_argument)
: no_argument);
cvt->long_end->flag = 0;
/* we add a disambiguating code to all the user's
values (which is removed before we actually call
the function to parse the value); this means that
the user loses use of the high 8 bits in all his
values (the sign of the lower bits is preserved
however)... */
cvt->long_end->val =
((opt->key ? opt->key : real->key) & USER_MASK)
+ (((group - cvt->parser->groups) + 1) << USER_BITS);
/* Keep the LONG_OPTS list terminated. */
(++cvt->long_end)->name = NULL;
}
}
}
group->parser = argp->parser;
group->argp = argp;
group->short_end = cvt->short_end;
group->args_processed = 0;
group->parent = parent;
group->parent_index = parent_index;
group->input = 0;
group->hook = 0;
group->child_inputs = 0;
if (children)
/* Assign GROUP's CHILD_INPUTS field some space from
CVT->child_inputs_end.*/
{
unsigned num_children = 0;
while (children[num_children].argp)
num_children++;
group->child_inputs = cvt->child_inputs_end;
cvt->child_inputs_end += num_children;
}
parent = group++;
}
else
parent = 0;
if (children)
{
unsigned index = 0;
while (children->argp)
group =
convert_options (children++->argp, parent, index++, group, cvt);
}
return group;
}
/* Find the merged set of getopt options, with keys appropiately prefixed. */
static void
parser_convert (struct parser *parser, const struct argp *argp, int flags)
{
struct parser_convert_state cvt;
cvt.parser = parser;
cvt.short_end = parser->short_opts;
cvt.long_end = parser->long_opts;
cvt.child_inputs_end = parser->child_inputs;
if (flags & ARGP_IN_ORDER)
*cvt.short_end++ = '-';
else if (flags & ARGP_NO_ARGS)
*cvt.short_end++ = '+';
*cvt.short_end = '\0';
cvt.long_end->name = NULL;
parser->argp = argp;
if (argp)
parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt);
else
parser->egroup = parser->groups; /* No parsers at all! */
}
/* Lengths of various parser fields which we will allocated. */
struct parser_sizes
{
size_t short_len; /* Getopt short options string. */
size_t long_len; /* Getopt long options vector. */
size_t num_groups; /* Group structures we allocate. */
size_t num_child_inputs; /* Child input slots. */
};
/* For ARGP, increments the NUM_GROUPS field in SZS by the total number of
argp structures descended from it, and the SHORT_LEN & LONG_LEN fields by
the maximum lengths of the resulting merged getopt short options string and
long-options array, respectively. */
static void
calc_sizes (const struct argp *argp, struct parser_sizes *szs)
{
const struct argp_child *child = argp->children;
const struct argp_option *opt = argp->options;
if (opt || argp->parser)
{
szs->num_groups++;
if (opt)
{
int num_opts = 0;
while (!__option_is_end (opt++))
num_opts++;
szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */
szs->long_len += num_opts;
}
}
if (child)
while (child->argp)
{
calc_sizes ((child++)->argp, szs);
szs->num_child_inputs++;
}
}
/* Initializes PARSER to parse ARGP in a manner described by FLAGS. */
static error_t
parser_init (struct parser *parser, const struct argp *argp,
int argc, char **argv, int flags, void *input)
{
error_t err = 0;
struct group *group;
struct parser_sizes szs;
struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER;
char *storage;
size_t glen, gsum;
size_t clen, csum;
size_t llen, lsum;
size_t slen, ssum;
szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
szs.long_len = 0;
szs.num_groups = 0;
szs.num_child_inputs = 0;
if (argp)
calc_sizes (argp, &szs);
/* Lengths of the various bits of storage used by PARSER. */
glen = (szs.num_groups + 1) * sizeof (struct group);
clen = szs.num_child_inputs * sizeof (void *);
llen = (szs.long_len + 1) * sizeof (struct option);
slen = szs.short_len + 1;
/* Sums of previous lengths, properly aligned. There's no need to
align gsum, since struct group is aligned at least as strictly as
void * (since it contains a void * member). And there's no need
to align lsum, since struct option is aligned at least as
strictly as char. */
gsum = glen;
csum = alignto (gsum + clen, alignof (struct option));
lsum = csum + llen;
ssum = lsum + slen;
parser->storage = malloc (ssum);
if (! parser->storage)
return ENOMEM;
storage = parser->storage;
parser->groups = parser->storage;
parser->child_inputs = (void **) (storage + gsum);
parser->long_opts = (struct option *) (storage + csum);
parser->short_opts = storage + lsum;
parser->opt_data = opt_data;
memset (parser->child_inputs, 0, clen);
parser_convert (parser, argp, flags);
memset (&parser->state, 0, sizeof (struct argp_state));
parser->state.root_argp = parser->argp;
parser->state.argc = argc;
parser->state.argv = argv;
parser->state.flags = flags;
parser->state.err_stream = stderr;
parser->state.out_stream = stdout;
parser->state.next = 0; /* Tell getopt to initialize. */
parser->state.pstate = parser;
parser->try_getopt = 1;
/* Call each parser for the first time, giving it a chance to propagate
values to child parsers. */
if (parser->groups < parser->egroup)
parser->groups->input = input;
for (group = parser->groups;
group < parser->egroup && (!err || err == EBADKEY);
group++)
{
if (group->parent)
/* If a child parser, get the initial input value from the parent. */
group->input = group->parent->child_inputs[group->parent_index];
if (!group->parser
&& group->argp->children && group->argp->children->argp)
/* For the special case where no parsing function is supplied for an
argp, propagate its input to its first child, if any (this just
makes very simple wrapper argps more convenient). */
group->child_inputs[0] = group->input;
err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0);
}
if (err == EBADKEY)
err = 0; /* Some parser didn't understand. */
if (err)
return err;
if (parser->state.flags & ARGP_NO_ERRS)
{
parser->opt_data.opterr = 0;
if (parser->state.flags & ARGP_PARSE_ARGV0)
/* getopt always skips ARGV[0], so we have to fake it out. As long
as OPTERR is 0, then it shouldn't actually try to access it. */
parser->state.argv--, parser->state.argc++;
}
else
parser->opt_data.opterr = 1; /* Print error messages. */
if (parser->state.argv == argv && argv[0])
/* There's an argv[0]; use it for messages. */
parser->state.name = __argp_base_name (argv[0]);
else
parser->state.name = __argp_short_program_name ();
return 0;
}
/* Free any storage consumed by PARSER (but not PARSER itself). */
static error_t
parser_finalize (struct parser *parser,
error_t err, int arg_ebadkey, int *end_index)
{
struct group *group;
if (err == EBADKEY && arg_ebadkey)
/* Suppress errors generated by unparsed arguments. */
err = 0;
if (! err)
{
if (parser->state.next == parser->state.argc)
/* We successfully parsed all arguments! Call all the parsers again,
just a few more times... */
{
for (group = parser->groups;
group < parser->egroup && (!err || err==EBADKEY);
group++)
if (group->args_processed == 0)
err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0);
for (group = parser->egroup - 1;
group >= parser->groups && (!err || err==EBADKEY);
group--)
err = group_parse (group, &parser->state, ARGP_KEY_END, 0);
if (err == EBADKEY)
err = 0; /* Some parser didn't understand. */
/* Tell the user that all arguments are parsed. */
if (end_index)
*end_index = parser->state.next;
}
else if (end_index)
/* Return any remaining arguments to the user. */
*end_index = parser->state.next;
else
/* No way to return the remaining arguments, they must be bogus. */
{
if (!(parser->state.flags & ARGP_NO_ERRS)
&& parser->state.err_stream)
fprintf (parser->state.err_stream,
dgettext (parser->argp->argp_domain,
"%s: Too many arguments\n"),
parser->state.name);
err = EBADKEY;
}
}
/* Okay, we're all done, with either an error or success; call the parsers
to indicate which one. */
if (err)
{
/* Maybe print an error message. */
if (err == EBADKEY)
/* An appropriate message describing what the error was should have
been printed earlier. */
__argp_state_help (&parser->state, parser->state.err_stream,
ARGP_HELP_STD_ERR);
/* Since we didn't exit, give each parser an error indication. */
for (group = parser->groups; group < parser->egroup; group++)
group_parse (group, &parser->state, ARGP_KEY_ERROR, 0);
}
else
/* Notify parsers of success, and propagate back values from parsers. */
{
/* We pass over the groups in reverse order so that child groups are
given a chance to do there processing before passing back a value to
the parent. */
for (group = parser->egroup - 1
; group >= parser->groups && (!err || err == EBADKEY)
; group--)
err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0);
if (err == EBADKEY)
err = 0; /* Some parser didn't understand. */
}
/* Call parsers once more, to do any final cleanup. Errors are ignored. */
for (group = parser->egroup - 1; group >= parser->groups; group--)
group_parse (group, &parser->state, ARGP_KEY_FINI, 0);
if (err == EBADKEY)
err = EINVAL;
free (parser->storage);
return err;
}
/* Call the user parsers to parse the non-option argument VAL, at the current
position, returning any error. The state NEXT pointer is assumed to have
been adjusted (by getopt) to point after this argument; this function will
adjust it correctly to reflect however many args actually end up being
consumed. */
static error_t
parser_parse_arg (struct parser *parser, char *val)
{
/* Save the starting value of NEXT, first adjusting it so that the arg
we're parsing is again the front of the arg vector. */
int index = --parser->state.next;
error_t err = EBADKEY;
struct group *group;
int key = 0; /* Which of ARGP_KEY_ARG[S] we used. */
/* Try to parse the argument in each parser. */
for (group = parser->groups
; group < parser->egroup && err == EBADKEY
; group++)
{
parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */
key = ARGP_KEY_ARG;
err = group_parse (group, &parser->state, key, val);
if (err == EBADKEY)
/* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */
{
parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */
key = ARGP_KEY_ARGS;
err = group_parse (group, &parser->state, key, 0);
}
}
if (! err)
{
if (key == ARGP_KEY_ARGS)
/* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't
changed by the user, *all* arguments should be considered
consumed. */
parser->state.next = parser->state.argc;
if (parser->state.next > index)
/* Remember that we successfully processed a non-option
argument -- but only if the user hasn't gotten tricky and set
the clock back. */
(--group)->args_processed += (parser->state.next - index);
else
/* The user wants to reparse some args, give getopt another try. */
parser->try_getopt = 1;
}
return err;
}
/* Call the user parsers to parse the option OPT, with argument VAL, at the
current position, returning any error. */
static error_t
parser_parse_opt (struct parser *parser, int opt, char *val)
{
/* The group key encoded in the high bits; 0 for short opts or
group_number + 1 for long opts. */
int group_key = opt >> USER_BITS;
error_t err = EBADKEY;
if (group_key == 0)
/* A short option. By comparing OPT's position in SHORT_OPTS to the
various starting positions in each group's SHORT_END field, we can
determine which group OPT came from. */
{
struct group *group;
char *short_index = strchr (parser->short_opts, opt);
if (short_index)
for (group = parser->groups; group < parser->egroup; group++)
if (group->short_end > short_index)
{
err = group_parse (group, &parser->state, opt,
parser->opt_data.optarg);
break;
}
}
else
/* A long option. We use shifts instead of masking for extracting
the user value in order to preserve the sign. */
err =
group_parse (&parser->groups[group_key - 1], &parser->state,
(opt << GROUP_BITS) >> GROUP_BITS,
parser->opt_data.optarg);
if (err == EBADKEY)
/* At least currently, an option not recognized is an error in the
parser, because we pre-compute which parser is supposed to deal
with each option. */
{
static const char bad_key_err[] =
N_("(PROGRAM ERROR) Option should have been recognized!?");
if (group_key == 0)
__argp_error (&parser->state, "-%c: %s", opt,
dgettext (parser->argp->argp_domain, bad_key_err));
else
{
struct option *long_opt = parser->long_opts;
while (long_opt->val != opt && long_opt->name)
long_opt++;
__argp_error (&parser->state, "--%s: %s",
long_opt->name ? long_opt->name : "???",
dgettext (parser->argp->argp_domain, bad_key_err));
}
}
return err;
}
/* Parse the next argument in PARSER (as indicated by PARSER->state.next).
Any error from the parsers is returned, and *ARGP_EBADKEY indicates
whether a value of EBADKEY is due to an unrecognized argument (which is
generally not fatal). */
static error_t
parser_parse_next (struct parser *parser, int *arg_ebadkey)
{
int opt;
error_t err = 0;
if (parser->state.quoted && parser->state.next < parser->state.quoted)
/* The next argument pointer has been moved to before the quoted
region, so pretend we never saw the quoting `--', and give getopt
another chance. If the user hasn't removed it, getopt will just
process it again. */
parser->state.quoted = 0;
if (parser->try_getopt && !parser->state.quoted)
/* Give getopt a chance to parse this. */
{
/* Put it back in OPTIND for getopt. */
parser->opt_data.optind = parser->state.next;
/* Distinguish KEY_ERR from a real option. */
parser->opt_data.optopt = KEY_END;
if (parser->state.flags & ARGP_LONG_ONLY)
opt = _getopt_long_only_r (parser->state.argc, parser->state.argv,
parser->short_opts, parser->long_opts, 0,
&parser->opt_data);
else
opt = _getopt_long_r (parser->state.argc, parser->state.argv,
parser->short_opts, parser->long_opts, 0,
&parser->opt_data);
/* And see what getopt did. */
parser->state.next = parser->opt_data.optind;
if (opt == KEY_END)
/* Getopt says there are no more options, so stop using
getopt; we'll continue if necessary on our own. */
{
parser->try_getopt = 0;
if (parser->state.next > 1
&& strcmp (parser->state.argv[parser->state.next - 1], QUOTE)
== 0)
/* Not only is this the end of the options, but it's a
`quoted' region, which may have args that *look* like
options, so we definitely shouldn't try to use getopt past
here, whatever happens. */
parser->state.quoted = parser->state.next;
}
else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END)
/* KEY_ERR can have the same value as a valid user short
option, but in the case of a real error, getopt sets OPTOPT
to the offending character, which can never be KEY_END. */
{
*arg_ebadkey = 0;
return EBADKEY;
}
}
else
opt = KEY_END;
if (opt == KEY_END)
{
/* We're past what getopt considers the options. */
if (parser->state.next >= parser->state.argc
|| (parser->state.flags & ARGP_NO_ARGS))
/* Indicate that we're done. */
{
*arg_ebadkey = 1;
return EBADKEY;
}
else
/* A non-option arg; simulate what getopt might have done. */
{
opt = KEY_ARG;
parser->opt_data.optarg = parser->state.argv[parser->state.next++];
}
}
if (opt == KEY_ARG)
/* A non-option argument; try each parser in turn. */
err = parser_parse_arg (parser, parser->opt_data.optarg);
else
err = parser_parse_opt (parser, opt, parser->opt_data.optarg);
if (err == EBADKEY)
*arg_ebadkey = (opt == KEY_END || opt == KEY_ARG);
return err;
}
/* Parse the options strings in ARGC & ARGV according to the argp in ARGP.
FLAGS is one of the ARGP_ flags above. If END_INDEX is non-NULL, the
index in ARGV of the first unparsed option is returned in it. If an
unknown option is present, EINVAL is returned; if some parser routine
returned a non-zero value, it is returned; otherwise 0 is returned. */
error_t
__argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags,
int *end_index, void *input)
{
error_t err;
struct parser parser;
/* If true, then err == EBADKEY is a result of a non-option argument failing
to be parsed (which in some cases isn't actually an error). */
int arg_ebadkey = 0;
#ifndef _LIBC
if (!(flags & ARGP_PARSE_ARGV0))
{
#ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME
if (!program_invocation_name)
program_invocation_name = argv[0];
#endif
#ifdef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
if (!program_invocation_short_name)
program_invocation_short_name = __argp_base_name (argv[0]);
#endif
}
#endif
if (! (flags & ARGP_NO_HELP))
/* Add our own options. */
{
struct argp_child *child = alloca (4 * sizeof (struct argp_child));
struct argp *top_argp = alloca (sizeof (struct argp));
/* TOP_ARGP has no options, it just serves to group the user & default
argps. */
memset (top_argp, 0, sizeof (*top_argp));
top_argp->children = child;
memset (child, 0, 4 * sizeof (struct argp_child));
if (argp)
(child++)->argp = argp;
(child++)->argp = &argp_default_argp;
if (argp_program_version || argp_program_version_hook)
(child++)->argp = &argp_version_argp;
child->argp = 0;
argp = top_argp;
}
/* Construct a parser for these arguments. */
err = parser_init (&parser, argp, argc, argv, flags, input);
if (! err)
/* Parse! */
{
while (! err)
err = parser_parse_next (&parser, &arg_ebadkey);
err = parser_finalize (&parser, err, arg_ebadkey, end_index);
}
return err;
}
#ifdef weak_alias
weak_alias (__argp_parse, argp_parse)
#endif
/* Return the input field for ARGP in the parser corresponding to STATE; used
by the help routines. */
void *
__argp_input (const struct argp *argp, const struct argp_state *state)
{
if (state)
{
struct group *group;
struct parser *parser = state->pstate;
for (group = parser->groups; group < parser->egroup; group++)
if (group->argp == argp)
return group->input;
}
return 0;
}
#ifdef weak_alias
weak_alias (__argp_input, _argp_input)
#endif

27
gnulib/argp-pin.c Normal file
View file

@ -0,0 +1,27 @@
/* Full and short program names for argp module
Copyright (C) 2005, 2009, 2010 Free Software Foundation, Inc.
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 3 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, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
char *program_invocation_short_name = 0;
#endif
#ifndef HAVE_PROGRAM_INVOCATION_NAME
char *program_invocation_name = 0;
#endif

34
gnulib/argp-pv.c Normal file
View file

@ -0,0 +1,34 @@
/* Default definition for ARGP_PROGRAM_VERSION.
Copyright (C) 1996, 1997, 1999, 2006, 2009, 2010 Free Software Foundation,
Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
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 3 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, see <http://www.gnu.org/licenses/>. */
/* If set by the user program to a non-zero value, then a default option
--version is added (unless the ARGP_NO_HELP flag is used), which will
print this string followed by a newline and exit (unless the
ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
const char *argp_program_version
/* This variable should be zero-initialized. On most systems, putting it into
BSS is sufficient. Not so on MacOS X 10.3 and 10.4, see
<http://lists.gnu.org/archive/html/bug-gnulib/2009-01/msg00329.html>
<http://lists.gnu.org/archive/html/bug-gnulib/2009-08/msg00096.html>. */
#if defined __ELF__
/* On ELF systems, variables in BSS behave well. */
#else
= (const char *) 0
#endif
;

31
gnulib/argp-pvh.c Normal file
View file

@ -0,0 +1,31 @@
/* Default definition for ARGP_PROGRAM_VERSION_HOOK.
Copyright (C) 1996, 1997, 1999, 2004, 2009, 2010 Free Software Foundation,
Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
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 3 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, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "argp.h"
/* If set by the user program to a non-zero value, then a default option
--version is added (unless the ARGP_NO_HELP flag is used), which calls
this function with a stream to print the version to and a pointer to the
current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
used). This variable takes precedent over ARGP_PROGRAM_VERSION. */
void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = NULL;

38
gnulib/argp-version-etc.c Normal file
View file

@ -0,0 +1,38 @@
/* Version hook for Argp.
Copyright (C) 2009, 2010 Free Software Foundation, Inc.
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 3 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, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <version-etc.h>
#include <argp.h>
#include <argp-version-etc.h>
static const char *program_canonical_name;
static const char * const *program_authors;
static void
version_etc_hook (FILE *stream, struct argp_state *state)
{
version_etc_ar (stream, program_canonical_name, PACKAGE_NAME, VERSION,
program_authors);
}
void
argp_version_setup (const char *name, const char * const *authors)
{
argp_program_version_hook = version_etc_hook;
program_canonical_name = name;
program_authors = authors;
}

40
gnulib/argp-version-etc.h Normal file
View file

@ -0,0 +1,40 @@
/* Version hook for Argp.
Copyright (C) 2009, 2010 Free Software Foundation, Inc.
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 3 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, see <http://www.gnu.org/licenses/>. */
#ifndef _ARGP_VERSION_ETC_H
#define _ARGP_VERSION_ETC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Setup standard display of the version information for the `--version'
option. NAME is the canonical program name, and AUTHORS is a NULL-
terminated array of author names. At least one author name must be
given.
If NAME is NULL, the package name (as given by the PACKAGE macro)
is asumed to be the name of the program.
This function is intended to be called before argp_parse().
*/
extern void argp_version_setup (const char *name, const char * const *authors);
#ifdef __cplusplus
}
#endif
#endif /* _ARGP_VERSION_ETC_H */

42
gnulib/argp-xinl.c Normal file
View file

@ -0,0 +1,42 @@
/* Real definitions for extern inline functions in argp.h
Copyright (C) 1997, 1998, 2004, 2009, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
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 3 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, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#if defined _LIBC || defined HAVE_FEATURES_H
# include <features.h>
#endif
#ifndef __USE_EXTERN_INLINES
# define __USE_EXTERN_INLINES 1
#endif
#define ARGP_EI
#undef __OPTIMIZE__
#define __OPTIMIZE__ 1
#include "argp.h"
/* Add weak aliases. */
#if _LIBC - 0 && defined (weak_alias)
weak_alias (__argp_usage, argp_usage)
weak_alias (__option_is_short, _option_is_short)
weak_alias (__option_is_end, _option_is_end)
#endif

645
gnulib/argp.h Normal file
View file

@ -0,0 +1,645 @@
/* Hierarchial argument parsing, layered over getopt.
Copyright (C) 1995-1999, 2003-2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>.
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 3 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, see <http://www.gnu.org/licenses/>. */
#ifndef _ARGP_H
#define _ARGP_H
#include <stdio.h>
#include <ctype.h>
#include <getopt.h>
#include <limits.h>
#define __need_error_t
#include <errno.h>
#ifndef __THROW
# define __THROW
#endif
#ifndef __NTH
# define __NTH(fct) fct __THROW
#endif
#ifndef __attribute__
/* The __attribute__ feature is available in gcc versions 2.5 and later.
The __-protected variants of the attributes 'format' and 'printf' are
accepted by gcc versions 2.6.4 (effectively 2.7) and later.
We enable __attribute__ only if these are supported too, because
gnulib and libintl do '#define printf __printf__' when they override
the 'printf' function. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
# define __attribute__(Spec) /* empty */
# endif
#endif
/* GCC 2.95 and later have "__restrict"; C99 compilers have
"restrict", and "configure" may have defined "restrict".
Other compilers use __restrict, __restrict__, and _Restrict, and
'configure' might #define 'restrict' to those words. */
#ifndef __restrict
# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))
# if 199901L <= __STDC_VERSION__
# define __restrict restrict
# else
# define __restrict
# endif
# endif
#endif
#ifndef __error_t_defined
typedef int error_t;
# define __error_t_defined
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* A description of a particular option. A pointer to an array of
these is passed in the OPTIONS field of an argp structure. Each option
entry can correspond to one long option and/or one short option; more
names for the same option can be added by following an entry in an option
array with options having the OPTION_ALIAS flag set. */
struct argp_option
{
/* The long option name. For more than one name for the same option, you
can use following options with the OPTION_ALIAS flag set. */
const char *name;
/* What key is returned for this option. If > 0 and printable, then it's
also accepted as a short option. */
int key;
/* If non-NULL, this is the name of the argument associated with this
option, which is required unless the OPTION_ARG_OPTIONAL flag is set. */
const char *arg;
/* OPTION_ flags. */
int flags;
/* The doc string for this option. If both NAME and KEY are 0, This string
will be printed outdented from the normal option column, making it
useful as a group header (it will be the first thing printed in its
group); in this usage, it's conventional to end the string with a `:'.
Write the initial value as N_("TEXT") if you want xgettext to collect
it into a POT file. */
const char *doc;
/* The group this option is in. In a long help message, options are sorted
alphabetically within each group, and the groups presented in the order
0, 1, 2, ..., n, -m, ..., -2, -1. Every entry in an options array with
if this field 0 will inherit the group number of the previous entry, or
zero if it's the first one, unless its a group header (NAME and KEY both
0), in which case, the previous entry + 1 is the default. Automagic
options such as --help are put into group -1. */
int group;
};
/* The argument associated with this option is optional. */
#define OPTION_ARG_OPTIONAL 0x1
/* This option isn't displayed in any help messages. */
#define OPTION_HIDDEN 0x2
/* This option is an alias for the closest previous non-alias option. This
means that it will be displayed in the same help entry, and will inherit
fields other than NAME and KEY from the aliased option. */
#define OPTION_ALIAS 0x4
/* This option isn't actually an option (and so should be ignored by the
actual option parser), but rather an arbitrary piece of documentation that
should be displayed in much the same manner as the options. If this flag
is set, then the option NAME field is displayed unmodified (e.g., no `--'
prefix is added) at the left-margin (where a *short* option would normally
be displayed), and the documentation string in the normal place. The NAME
field will be translated using gettext, unless OPTION_NO_TRANS is set (see
below). For purposes of sorting, any leading whitespace and punctuation is
ignored, except that if the first non-whitespace character is not `-', this
entry is displayed after all options (and OPTION_DOC entries with a leading
`-') in the same group. */
#define OPTION_DOC 0x8
/* This option shouldn't be included in `long' usage messages (but is still
included in help messages). This is mainly intended for options that are
completely documented in an argp's ARGS_DOC field, in which case including
the option in the generic usage list would be redundant. For instance,
if ARGS_DOC is "FOO BAR\n-x BLAH", and the `-x' option's purpose is to
distinguish these two cases, -x should probably be marked
OPTION_NO_USAGE. */
#define OPTION_NO_USAGE 0x10
/* Valid only in conjunction with OPTION_DOC. This option disables translation
of option name. */
#define OPTION_NO_TRANS 0x20
struct argp; /* fwd declare this type */
struct argp_state; /* " */
struct argp_child; /* " */
/* The type of a pointer to an argp parsing function. */
typedef error_t (*argp_parser_t) (int key, char *arg,
struct argp_state *state);
/* What to return for unrecognized keys. For special ARGP_KEY_ keys, such
returns will simply be ignored. For user keys, this error will be turned
into EINVAL (if the call to argp_parse is such that errors are propagated
back to the user instead of exiting); returning EINVAL itself would result
in an immediate stop to parsing in *all* cases. */
#define ARGP_ERR_UNKNOWN E2BIG /* Hurd should never need E2BIG. XXX */
/* Special values for the KEY argument to an argument parsing function.
ARGP_ERR_UNKNOWN should be returned if they aren't understood.
The sequence of keys to a parsing function is either (where each
uppercased word should be prefixed by `ARGP_KEY_' and opt is a user key):
INIT opt... NO_ARGS END SUCCESS -- No non-option arguments at all
or INIT (opt | ARG)... END SUCCESS -- All non-option args parsed
or INIT (opt | ARG)... SUCCESS -- Some non-option arg unrecognized
The third case is where every parser returned ARGP_KEY_UNKNOWN for an
argument, in which case parsing stops at that argument (returning the
unparsed arguments to the caller of argp_parse if requested, or stopping
with an error message if not).
If an error occurs (either detected by argp, or because the parsing
function returned an error value), then the parser is called with
ARGP_KEY_ERROR, and no further calls are made. */
/* This is not an option at all, but rather a command line argument. If a
parser receiving this key returns success, the fact is recorded, and the
ARGP_KEY_NO_ARGS case won't be used. HOWEVER, if while processing the
argument, a parser function decrements the NEXT field of the state it's
passed, the option won't be considered processed; this is to allow you to
actually modify the argument (perhaps into an option), and have it
processed again. */
#define ARGP_KEY_ARG 0
/* There are remaining arguments not parsed by any parser, which may be found
starting at (STATE->argv + STATE->next). If success is returned, but
STATE->next left untouched, it's assumed that all arguments were consume,
otherwise, the parser should adjust STATE->next to reflect any arguments
consumed. */
#define ARGP_KEY_ARGS 0x1000006
/* There are no more command line arguments at all. */
#define ARGP_KEY_END 0x1000001
/* Because it's common to want to do some special processing if there aren't
any non-option args, user parsers are called with this key if they didn't
successfully process any non-option arguments. Called just before
ARGP_KEY_END (where more general validity checks on previously parsed
arguments can take place). */
#define ARGP_KEY_NO_ARGS 0x1000002
/* Passed in before any parsing is done. Afterwards, the values of each
element of the CHILD_INPUT field, if any, in the state structure is
copied to each child's state to be the initial value of the INPUT field. */
#define ARGP_KEY_INIT 0x1000003
/* Use after all other keys, including SUCCESS & END. */
#define ARGP_KEY_FINI 0x1000007
/* Passed in when parsing has successfully been completed (even if there are
still arguments remaining). */
#define ARGP_KEY_SUCCESS 0x1000004
/* Passed in if an error occurs. */
#define ARGP_KEY_ERROR 0x1000005
/* An argp structure contains a set of options declarations, a function to
deal with parsing one, documentation string, a possible vector of child
argp's, and perhaps a function to filter help output. When actually
parsing options, getopt is called with the union of all the argp
structures chained together through their CHILD pointers, with conflicts
being resolved in favor of the first occurrence in the chain. */
struct argp
{
/* An array of argp_option structures, terminated by an entry with both
NAME and KEY having a value of 0. */
const struct argp_option *options;
/* What to do with an option from this structure. KEY is the key
associated with the option, and ARG is any associated argument (NULL if
none was supplied). If KEY isn't understood, ARGP_ERR_UNKNOWN should be
returned. If a non-zero, non-ARGP_ERR_UNKNOWN value is returned, then
parsing is stopped immediately, and that value is returned from
argp_parse(). For special (non-user-supplied) values of KEY, see the
ARGP_KEY_ definitions below. */
argp_parser_t parser;
/* A string describing what other arguments are wanted by this program. It
is only used by argp_usage to print the `Usage:' message. If it
contains newlines, the strings separated by them are considered
alternative usage patterns, and printed on separate lines (lines after
the first are prefix by ` or: ' instead of `Usage:'). */
const char *args_doc;
/* If non-NULL, a string containing extra text to be printed before and
after the options in a long help message (separated by a vertical tab
`\v' character).
Write the initial value as N_("BEFORE-TEXT") "\v" N_("AFTER-TEXT") if
you want xgettext to collect the two pieces of text into a POT file. */
const char *doc;
/* A vector of argp_children structures, terminated by a member with a 0
argp field, pointing to child argps should be parsed with this one. Any
conflicts are resolved in favor of this argp, or early argps in the
CHILDREN list. This field is useful if you use libraries that supply
their own argp structure, which you want to use in conjunction with your
own. */
const struct argp_child *children;
/* If non-zero, this should be a function to filter the output of help
messages. KEY is either a key from an option, in which case TEXT is
that option's help text, or a special key from the ARGP_KEY_HELP_
defines, below, describing which other help text TEXT is. The function
should return either TEXT, if it should be used as-is, a replacement
string, which should be malloced, and will be freed by argp, or NULL,
meaning `print nothing'. The value for TEXT is *after* any translation
has been done, so if any of the replacement text also needs translation,
that should be done by the filter function. INPUT is either the input
supplied to argp_parse, or NULL, if argp_help was called directly. */
char *(*help_filter) (int __key, const char *__text, void *__input);
/* If non-zero the strings used in the argp library are translated using
the domain described by this string. Otherwise the currently installed
default domain is used. */
const char *argp_domain;
};
/* Possible KEY arguments to a help filter function. */
#define ARGP_KEY_HELP_PRE_DOC 0x2000001 /* Help text preceeding options. */
#define ARGP_KEY_HELP_POST_DOC 0x2000002 /* Help text following options. */
#define ARGP_KEY_HELP_HEADER 0x2000003 /* Option header string. */
#define ARGP_KEY_HELP_EXTRA 0x2000004 /* After all other documentation;
TEXT is NULL for this key. */
/* Explanatory note emitted when duplicate option arguments have been
suppressed. */
#define ARGP_KEY_HELP_DUP_ARGS_NOTE 0x2000005
#define ARGP_KEY_HELP_ARGS_DOC 0x2000006 /* Argument doc string. */
/* When an argp has a non-zero CHILDREN field, it should point to a vector of
argp_child structures, each of which describes a subsidiary argp. */
struct argp_child
{
/* The child parser. */
const struct argp *argp;
/* Flags for this child. */
int flags;
/* If non-zero, an optional header to be printed in help output before the
child options. As a side-effect, a non-zero value forces the child
options to be grouped together; to achieve this effect without actually
printing a header string, use a value of "". */
const char *header;
/* Where to group the child options relative to the other (`consolidated')
options in the parent argp; the values are the same as the GROUP field
in argp_option structs, but all child-groupings follow parent options at
a particular group level. If both this field and HEADER are zero, then
they aren't grouped at all, but rather merged with the parent options
(merging the child's grouping levels with the parents). */
int group;
};
/* Parsing state. This is provided to parsing functions called by argp,
which may examine and, as noted, modify fields. */
struct argp_state
{
/* The top level ARGP being parsed. */
const struct argp *root_argp;
/* The argument vector being parsed. May be modified. */
int argc;
char **argv;
/* The index in ARGV of the next arg that to be parsed. May be modified. */
int next;
/* The flags supplied to argp_parse. May be modified. */
unsigned flags;
/* While calling a parsing function with a key of ARGP_KEY_ARG, this is the
number of the current arg, starting at zero, and incremented after each
such call returns. At all other times, this is the number of such
arguments that have been processed. */
unsigned arg_num;
/* If non-zero, the index in ARGV of the first argument following a special
`--' argument (which prevents anything following being interpreted as an
option). Only set once argument parsing has proceeded past this point. */
int quoted;
/* An arbitrary pointer passed in from the user. */
void *input;
/* Values to pass to child parsers. This vector will be the same length as
the number of children for the current parser. */
void **child_inputs;
/* For the parser's use. Initialized to 0. */
void *hook;
/* The name used when printing messages. This is initialized to ARGV[0],
or PROGRAM_INVOCATION_NAME if that is unavailable. */
char *name;
/* Streams used when argp prints something. */
FILE *err_stream; /* For errors; initialized to stderr. */
FILE *out_stream; /* For information; initialized to stdout. */
void *pstate; /* Private, for use by argp. */
};
/* Flags for argp_parse (note that the defaults are those that are
convenient for program command line parsing): */
/* Don't ignore the first element of ARGV. Normally (and always unless
ARGP_NO_ERRS is set) the first element of the argument vector is
skipped for option parsing purposes, as it corresponds to the program name
in a command line. */
#define ARGP_PARSE_ARGV0 0x01
/* Don't print error messages for unknown options to stderr; unless this flag
is set, ARGP_PARSE_ARGV0 is ignored, as ARGV[0] is used as the program
name in the error messages. This flag implies ARGP_NO_EXIT (on the
assumption that silent exiting upon errors is bad behaviour). */
#define ARGP_NO_ERRS 0x02
/* Don't parse any non-option args. Normally non-option args are parsed by
calling the parse functions with a key of ARGP_KEY_ARG, and the actual arg
as the value. Since it's impossible to know which parse function wants to
handle it, each one is called in turn, until one returns 0 or an error
other than ARGP_ERR_UNKNOWN; if an argument is handled by no one, the
argp_parse returns prematurely (but with a return value of 0). If all
args have been parsed without error, all parsing functions are called one
last time with a key of ARGP_KEY_END. This flag needn't normally be set,
as the normal behavior is to stop parsing as soon as some argument can't
be handled. */
#define ARGP_NO_ARGS 0x04
/* Parse options and arguments in the same order they occur on the command
line -- normally they're rearranged so that all options come first. */
#define ARGP_IN_ORDER 0x08
/* Don't provide the standard long option --help, which causes usage and
option help information to be output to stdout, and exit (0) called. */
#define ARGP_NO_HELP 0x10
/* Don't exit on errors (they may still result in error messages). */
#define ARGP_NO_EXIT 0x20
/* Use the gnu getopt `long-only' rules for parsing arguments. */
#define ARGP_LONG_ONLY 0x40
/* Turns off any message-printing/exiting options. */
#define ARGP_SILENT (ARGP_NO_EXIT | ARGP_NO_ERRS | ARGP_NO_HELP)
/* Parse the options strings in ARGC & ARGV according to the options in ARGP.
FLAGS is one of the ARGP_ flags above. If ARG_INDEX is non-NULL, the
index in ARGV of the first unparsed option is returned in it. If an
unknown option is present, ARGP_ERR_UNKNOWN is returned; if some parser
routine returned a non-zero value, it is returned; otherwise 0 is
returned. This function may also call exit unless the ARGP_NO_HELP flag
is set. INPUT is a pointer to a value to be passed in to the parser. */
extern error_t argp_parse (const struct argp *__restrict __argp,
int /*argc*/, char **__restrict /*argv*/,
unsigned __flags, int *__restrict __arg_index,
void *__restrict __input);
extern error_t __argp_parse (const struct argp *__restrict __argp,
int /*argc*/, char **__restrict /*argv*/,
unsigned __flags, int *__restrict __arg_index,
void *__restrict __input);
/* Global variables. */
/* GNULIB makes sure both program_invocation_name and
program_invocation_short_name are available */
#ifdef GNULIB_PROGRAM_INVOCATION_NAME
extern char *program_invocation_name;
# undef HAVE_DECL_PROGRAM_INVOCATION_NAME
# define HAVE_DECL_PROGRAM_INVOCATION_NAME 1
#endif
#ifdef GNULIB_PROGRAM_INVOCATION_SHORT_NAME
extern char *program_invocation_short_name;
# undef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
# define HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME 1
#endif
/* If defined or set by the user program to a non-zero value, then a default
option --version is added (unless the ARGP_NO_HELP flag is used), which
will print this string followed by a newline and exit (unless the
ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */
extern const char *argp_program_version;
/* If defined or set by the user program to a non-zero value, then a default
option --version is added (unless the ARGP_NO_HELP flag is used), which
calls this function with a stream to print the version to and a pointer to
the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is
used). This variable takes precedent over ARGP_PROGRAM_VERSION. */
extern void (*argp_program_version_hook) (FILE *__restrict __stream,
struct argp_state *__restrict
__state);
/* If defined or set by the user program, it should point to string that is
the bug-reporting address for the program. It will be printed by
argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various
standard help messages), embedded in a sentence that says something like
`Report bugs to ADDR.'. */
extern const char *argp_program_bug_address;
/* The exit status that argp will use when exiting due to a parsing error.
If not defined or set by the user program, this defaults to EX_USAGE from
<sysexits.h>. */
extern error_t argp_err_exit_status;
/* Flags for argp_help. */
#define ARGP_HELP_USAGE 0x01 /* a Usage: message. */
#define ARGP_HELP_SHORT_USAGE 0x02 /* " but don't actually print options. */
#define ARGP_HELP_SEE 0x04 /* a `Try ... for more help' message. */
#define ARGP_HELP_LONG 0x08 /* a long help message. */
#define ARGP_HELP_PRE_DOC 0x10 /* doc string preceding long help. */
#define ARGP_HELP_POST_DOC 0x20 /* doc string following long help. */
#define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
#define ARGP_HELP_BUG_ADDR 0x40 /* bug report address */
#define ARGP_HELP_LONG_ONLY 0x80 /* modify output appropriately to
reflect ARGP_LONG_ONLY mode. */
/* These ARGP_HELP flags are only understood by argp_state_help. */
#define ARGP_HELP_EXIT_ERR 0x100 /* Call exit(1) instead of returning. */
#define ARGP_HELP_EXIT_OK 0x200 /* Call exit(0) instead of returning. */
/* The standard thing to do after a program command line parsing error, if an
error message has already been printed. */
#define ARGP_HELP_STD_ERR \
(ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
/* The standard thing to do after a program command line parsing error, if no
more specific error message has been printed. */
#define ARGP_HELP_STD_USAGE \
(ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
/* The standard thing to do in response to a --help option. */
#define ARGP_HELP_STD_HELP \
(ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \
| ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
/* Output a usage message for ARGP to STREAM. FLAGS are from the set
ARGP_HELP_*. */
extern void argp_help (const struct argp *__restrict __argp,
FILE *__restrict __stream,
unsigned __flags, char *__restrict __name);
extern void __argp_help (const struct argp *__restrict __argp,
FILE *__restrict __stream, unsigned __flags,
char *__name);
/* The following routines are intended to be called from within an argp
parsing routine (thus taking an argp_state structure as the first
argument). They may or may not print an error message and exit, depending
on the flags in STATE -- in any case, the caller should be prepared for
them *not* to exit, and should return an appropiate error after calling
them. [argp_usage & argp_error should probably be called argp_state_...,
but they're used often enough that they should be short] */
/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are
from the set ARGP_HELP_*. */
extern void argp_state_help (const struct argp_state *__restrict __state,
FILE *__restrict __stream,
unsigned int __flags);
extern void __argp_state_help (const struct argp_state *__restrict __state,
FILE *__restrict __stream,
unsigned int __flags);
#if _LIBC || !defined __USE_EXTERN_INLINES
/* Possibly output the standard usage message for ARGP to stderr and exit. */
extern void argp_usage (const struct argp_state *__state);
extern void __argp_usage (const struct argp_state *__state);
#endif
/* If appropriate, print the printf string FMT and following args, preceded
by the program name and `:', to stderr, and followed by a `Try ... --help'
message, then exit (1). */
extern void argp_error (const struct argp_state *__restrict __state,
const char *__restrict __fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
extern void __argp_error (const struct argp_state *__restrict __state,
const char *__restrict __fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
/* Similar to the standard gnu error-reporting function error(), but will
respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print
to STATE->err_stream. This is useful for argument parsing code that is
shared between program startup (when exiting is desired) and runtime
option parsing (when typically an error code is returned instead). The
difference between this function and argp_error is that the latter is for
*parsing errors*, and the former is for other problems that occur during
parsing but don't reflect a (syntactic) problem with the input. */
extern void argp_failure (const struct argp_state *__restrict __state,
int __status, int __errnum,
const char *__restrict __fmt, ...)
__attribute__ ((__format__ (__printf__, 4, 5)));
extern void __argp_failure (const struct argp_state *__restrict __state,
int __status, int __errnum,
const char *__restrict __fmt, ...)
__attribute__ ((__format__ (__printf__, 4, 5)));
#if _LIBC || !defined __USE_EXTERN_INLINES
/* Returns true if the option OPT is a valid short option. */
extern int _option_is_short (const struct argp_option *__opt) __THROW;
extern int __option_is_short (const struct argp_option *__opt) __THROW;
/* Returns true if the option OPT is in fact the last (unused) entry in an
options array. */
extern int _option_is_end (const struct argp_option *__opt) __THROW;
extern int __option_is_end (const struct argp_option *__opt) __THROW;
#endif
/* Return the input field for ARGP in the parser corresponding to STATE; used
by the help routines. */
extern void *_argp_input (const struct argp *__restrict __argp,
const struct argp_state *__restrict __state)
__THROW;
extern void *__argp_input (const struct argp *__restrict __argp,
const struct argp_state *__restrict __state)
__THROW;
#ifdef __USE_EXTERN_INLINES
# if !_LIBC
# define __argp_usage argp_usage
# define __argp_state_help argp_state_help
# define __option_is_short _option_is_short
# define __option_is_end _option_is_end
# endif
# ifndef ARGP_EI
# ifdef __GNUC__
/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
inline semantics, unless -fgnu89-inline is used. It defines a macro
__GNUC_STDC_INLINE__ to indicate this situation or a macro
__GNUC_GNU_INLINE__ to indicate the opposite situation.
GCC 4.2 with -std=c99 or -std=gnu99 implements the GNU C inline
semantics but warns, unless -fgnu89-inline is used:
warning: C99 inline functions are not supported; using GNU89
warning: to disable this warning use -fgnu89-inline or the gnu_inline function attribute
It defines a macro __GNUC_GNU_INLINE__ to indicate this situation. */
# if defined __GNUC_STDC_INLINE__
# define ARGP_EI __inline__
# elif defined __GNUC_GNU_INLINE__
# define ARGP_EI extern __inline__ __attribute__ ((__gnu_inline__))
# else
# define ARGP_EI extern __inline__
# endif
# else
/* With other compilers, assume the ISO C99 meaning of 'inline', if
the compiler supports 'inline' at all. */
# define ARGP_EI inline
# endif
# endif
ARGP_EI void
__argp_usage (const struct argp_state *__state)
{
__argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE);
}
ARGP_EI int
__NTH (__option_is_short (const struct argp_option *__opt))
{
if (__opt->flags & OPTION_DOC)
return 0;
else
{
int __key = __opt->key;
return __key > 0 && __key <= UCHAR_MAX && isprint (__key);
}
}
ARGP_EI int
__NTH (__option_is_end (const struct argp_option *__opt))
{
return !__opt->key && !__opt->name && !__opt->doc && !__opt->group;
}
# if !_LIBC
# undef __argp_usage
# undef __argp_state_help
# undef __option_is_short
# undef __option_is_end
# endif
#endif /* Use extern inlines. */
#ifdef __cplusplus
}
#endif
#endif /* argp.h */

View file

@ -1,5 +1,5 @@
/* Error handler for noninteractive utilities
Copyright (C) 1990-1998, 2000-2007, 2009 Free Software Foundation, Inc.
Copyright (C) 1990-1998, 2000-2007, 2009-2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software: you can redistribute it and/or modify
@ -70,8 +70,8 @@ unsigned int error_message_count;
extern void __error (int status, int errnum, const char *message, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
extern void __error_at_line (int status, int errnum, const char *file_name,
unsigned int line_number, const char *message,
...)
unsigned int line_number, const char *message,
...)
__attribute__ ((__format__ (__printf__, 5, 6)));;
# define error __error
# define error_at_line __error_at_line
@ -86,6 +86,7 @@ extern void __error_at_line (int status, int errnum, const char *file_name,
#else /* not _LIBC */
# include <fcntl.h>
# include <unistd.h>
# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
# ifndef HAVE_DECL_STRERROR_R
@ -100,8 +101,33 @@ extern char *program_name;
# if HAVE_STRERROR_R || defined strerror_r
# define __strerror_r strerror_r
# endif /* HAVE_STRERROR_R || defined strerror_r */
#endif /* not _LIBC */
# endif /* HAVE_STRERROR_R || defined strerror_r */
#endif /* not _LIBC */
static inline void
flush_stdout (void)
{
#if !_LIBC && defined F_GETFL
int stdout_fd;
# if GNULIB_FREOPEN_SAFER
/* Use of gnulib's freopen-safer module normally ensures that
fileno (stdout) == 1
whenever stdout is open. */
stdout_fd = STDOUT_FILENO;
# else
/* POSIX states that fileno (stdout) after fclose is unspecified. But in
practice it is not a problem, because stdout is statically allocated and
the fd of a FILE stream is stored as a field in its allocated memory. */
stdout_fd = fileno (stdout);
# endif
/* POSIX states that fflush (stdout) after fclose is unspecified; it
is safe in glibc, but not on all other platforms. fflush (NULL)
is always defined, but too draconian. */
if (0 <= stdout_fd && 0 <= fcntl (stdout_fd, F_GETFL))
#endif
fflush (stdout);
}
static void
print_errno_message (int errnum)
@ -149,58 +175,58 @@ error_tail (int status, int errnum, const char *message, va_list args)
bool use_malloc = false;
while (1)
{
if (__libc_use_alloca (len * sizeof (wchar_t)))
wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
else
{
if (!use_malloc)
wmessage = NULL;
{
if (__libc_use_alloca (len * sizeof (wchar_t)))
wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
else
{
if (!use_malloc)
wmessage = NULL;
wchar_t *p = (wchar_t *) realloc (wmessage,
len * sizeof (wchar_t));
if (p == NULL)
{
free (wmessage);
fputws_unlocked (L"out of memory\n", stderr);
return;
}
wmessage = p;
use_malloc = true;
}
wchar_t *p = (wchar_t *) realloc (wmessage,
len * sizeof (wchar_t));
if (p == NULL)
{
free (wmessage);
fputws_unlocked (L"out of memory\n", stderr);
return;
}
wmessage = p;
use_malloc = true;
}
memset (&st, '\0', sizeof (st));
tmp = message;
memset (&st, '\0', sizeof (st));
tmp = message;
res = mbsrtowcs (wmessage, &tmp, len, &st);
if (res != len)
break;
res = mbsrtowcs (wmessage, &tmp, len, &st);
if (res != len)
break;
if (__builtin_expect (len >= SIZE_MAX / 2, 0))
{
/* This really should not happen if everything is fine. */
res = (size_t) -1;
break;
}
if (__builtin_expect (len >= SIZE_MAX / 2, 0))
{
/* This really should not happen if everything is fine. */
res = (size_t) -1;
break;
}
len *= 2;
}
len *= 2;
}
if (res == (size_t) -1)
{
/* The string cannot be converted. */
if (use_malloc)
{
free (wmessage);
use_malloc = false;
}
wmessage = (wchar_t *) L"???";
}
{
/* The string cannot be converted. */
if (use_malloc)
{
free (wmessage);
use_malloc = false;
}
wmessage = (wchar_t *) L"???";
}
__vfwprintf (stderr, wmessage, args);
if (use_malloc)
free (wmessage);
free (wmessage);
}
else
#endif
@ -235,16 +261,10 @@ error (int status, int errnum, const char *message, ...)
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
__libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
0);
0);
#endif
#if !_LIBC && defined F_GETFL
/* POSIX states that fflush (stdout) after fclose is unspecified; it
is safe in glibc, but not on all other platforms. fflush (NULL)
is always defined, but too draconian. */
if (0 <= fcntl (1, F_GETFL))
#endif
fflush (stdout);
flush_stdout ();
#ifdef _LIBC
_IO_flockfile (stderr);
#endif
@ -276,7 +296,7 @@ int error_one_per_line;
void
error_at_line (int status, int errnum, const char *file_name,
unsigned int line_number, const char *message, ...)
unsigned int line_number, const char *message, ...)
{
va_list args;
@ -286,10 +306,10 @@ error_at_line (int status, int errnum, const char *file_name,
static unsigned int old_line_number;
if (old_line_number == line_number
&& (file_name == old_file_name
|| strcmp (old_file_name, file_name) == 0))
/* Simply return and print nothing. */
return;
&& (file_name == old_file_name
|| strcmp (old_file_name, file_name) == 0))
/* Simply return and print nothing. */
return;
old_file_name = file_name;
old_line_number = line_number;
@ -300,16 +320,10 @@ error_at_line (int status, int errnum, const char *file_name,
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
__libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
0);
0);
#endif
#if !_LIBC && defined F_GETFL
/* POSIX states that fflush (stdout) after fclose is unspecified; it
is safe in glibc, but not on all other platforms. fflush (NULL)
is always defined, but too draconian. */
if (0 <= fcntl (1, F_GETFL))
#endif
fflush (stdout);
flush_stdout ();
#ifdef _LIBC
_IO_flockfile (stderr);
#endif
@ -326,10 +340,10 @@ error_at_line (int status, int errnum, const char *file_name,
#if _LIBC
__fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
file_name, line_number);
file_name, line_number);
#else
fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
file_name, line_number);
file_name, line_number);
#endif
va_start (args, message);

View file

@ -1,5 +1,6 @@
/* Declaration for error-reporting function
Copyright (C) 1995, 1996, 1997, 2003, 2006, 2008 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 2003, 2006, 2008, 2009, 2010 Free Software
Foundation, Inc.
This file is part of the GNU C Library.
This program is free software: you can redistribute it and/or modify
@ -19,19 +20,18 @@
#define _ERROR_H 1
#ifndef __attribute__
/* This feature is available in gcc versions 2.5 and later. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
# define __attribute__(Spec) /* empty */
# endif
/* The __-protected variants of `format' and `printf' attributes
are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
/* The __attribute__ feature is available in gcc versions 2.5 and later.
The __-protected variants of the attributes 'format' and 'printf' are
accepted by gcc versions 2.6.4 (effectively 2.7) and later.
We enable __attribute__ only if these are supported too, because
gnulib and libintl do '#define printf __printf__' when they override
the 'printf' function. */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
# define __format__ format
# define __printf__ printf
# define __attribute__(Spec) /* empty */
# endif
#endif
#ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
@ -43,7 +43,7 @@ extern void error (int __status, int __errnum, const char *__format, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
extern void error_at_line (int __status, int __errnum, const char *__fname,
unsigned int __lineno, const char *__format, ...)
unsigned int __lineno, const char *__format, ...)
__attribute__ ((__format__ (__printf__, 5, 6)));
/* If NULL, error will flush stdout, then print on stderr the program
@ -58,7 +58,7 @@ extern unsigned int error_message_count;
variable controls whether this mode is selected or not. */
extern int error_one_per_line;
#ifdef __cplusplus
#ifdef __cplusplus
}
#endif

View file

@ -1,5 +1,5 @@
/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007
Free Software Foundation, Inc.
/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
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
@ -21,7 +21,7 @@
/* Enable GNU extensions in fnmatch.h. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
# define _GNU_SOURCE 1
#endif
#if ! defined __builtin_expect && __GNUC__ < 3
@ -89,7 +89,7 @@ extern int fnmatch (const char *pattern, const char *string, int flags);
# define isblank(c) ((c) == ' ' || (c) == '\t')
# endif
# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
# define STREQ(s1, s2) (strcmp (s1, s2) == 0)
# if defined _LIBC || WIDE_CHAR_SUPPORT
/* The GNU C library provides support for user-defined character classes
@ -109,25 +109,25 @@ extern int fnmatch (const char *pattern, const char *string, int flags);
# endif
# ifdef _LIBC
# define ISWCTYPE(WC, WT) __iswctype (WC, WT)
# define ISWCTYPE(WC, WT) __iswctype (WC, WT)
# else
# define ISWCTYPE(WC, WT) iswctype (WC, WT)
# define ISWCTYPE(WC, WT) iswctype (WC, WT)
# endif
# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC
/* In this case we are implementing the multibyte character handling. */
# define HANDLE_MULTIBYTE 1
# define HANDLE_MULTIBYTE 1
# endif
# else
# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */
# define IS_CHAR_CLASS(string) \
(STREQ (string, "alpha") || STREQ (string, "upper") \
|| STREQ (string, "lower") || STREQ (string, "digit") \
|| STREQ (string, "alnum") || STREQ (string, "xdigit") \
|| STREQ (string, "space") || STREQ (string, "print") \
|| STREQ (string, "punct") || STREQ (string, "graph") \
# define IS_CHAR_CLASS(string) \
(STREQ (string, "alpha") || STREQ (string, "upper") \
|| STREQ (string, "lower") || STREQ (string, "digit") \
|| STREQ (string, "alnum") || STREQ (string, "xdigit") \
|| STREQ (string, "space") || STREQ (string, "print") \
|| STREQ (string, "punct") || STREQ (string, "graph") \
|| STREQ (string, "cntrl") || STREQ (string, "blank"))
# endif
@ -145,17 +145,17 @@ static int posixly_correct;
/* Note that this evaluates C many times. */
# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
# define CHAR char
# define UCHAR unsigned char
# define INT int
# define FCT internal_fnmatch
# define EXT ext_match
# define END end_pattern
# define L_(CS) CS
# define CHAR char
# define UCHAR unsigned char
# define INT int
# define FCT internal_fnmatch
# define EXT ext_match
# define END end_pattern
# define L_(CS) CS
# ifdef _LIBC
# define BTOWC(C) __btowc (C)
# define BTOWC(C) __btowc (C)
# else
# define BTOWC(C) btowc (C)
# define BTOWC(C) btowc (C)
# endif
# define STRLEN(S) strlen (S)
# define STRCAT(D, S) strcat (D, S)
@ -175,14 +175,14 @@ static int posixly_correct;
# if HANDLE_MULTIBYTE
# define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
# define CHAR wchar_t
# define UCHAR wint_t
# define INT wint_t
# define FCT internal_fnwmatch
# define EXT ext_wmatch
# define END end_wpattern
# define L_(CS) L##CS
# define BTOWC(C) (C)
# define CHAR wchar_t
# define UCHAR wint_t
# define INT wint_t
# define FCT internal_fnwmatch
# define EXT ext_wmatch
# define END end_wpattern
# define L_(CS) L##CS
# define BTOWC(C) (C)
# ifdef _LIBC
# define STRLEN(S) __wcslen (S)
# define STRCAT(D, S) __wcscat (D, S)
@ -218,40 +218,40 @@ is_char_class (const wchar_t *wcs)
/* Test for a printable character from the portable character set. */
# ifdef _LIBC
if (*wcs < 0x20 || *wcs > 0x7e
|| *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
return (wctype_t) 0;
|| *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
return (wctype_t) 0;
# else
switch (*wcs)
{
case L' ': case L'!': case L'"': case L'#': case L'%':
case L'&': case L'\'': case L'(': case L')': case L'*':
case L'+': case L',': case L'-': case L'.': case L'/':
case L'0': case L'1': case L'2': case L'3': case L'4':
case L'5': case L'6': case L'7': case L'8': case L'9':
case L':': case L';': case L'<': case L'=': case L'>':
case L'?':
case L'A': case L'B': case L'C': case L'D': case L'E':
case L'F': case L'G': case L'H': case L'I': case L'J':
case L'K': case L'L': case L'M': case L'N': case L'O':
case L'P': case L'Q': case L'R': case L'S': case L'T':
case L'U': case L'V': case L'W': case L'X': case L'Y':
case L'Z':
case L'[': case L'\\': case L']': case L'^': case L'_':
case L'a': case L'b': case L'c': case L'd': case L'e':
case L'f': case L'g': case L'h': case L'i': case L'j':
case L'k': case L'l': case L'm': case L'n': case L'o':
case L'p': case L'q': case L'r': case L's': case L't':
case L'u': case L'v': case L'w': case L'x': case L'y':
case L'z': case L'{': case L'|': case L'}': case L'~':
break;
default:
return (wctype_t) 0;
}
{
case L' ': case L'!': case L'"': case L'#': case L'%':
case L'&': case L'\'': case L'(': case L')': case L'*':
case L'+': case L',': case L'-': case L'.': case L'/':
case L'0': case L'1': case L'2': case L'3': case L'4':
case L'5': case L'6': case L'7': case L'8': case L'9':
case L':': case L';': case L'<': case L'=': case L'>':
case L'?':
case L'A': case L'B': case L'C': case L'D': case L'E':
case L'F': case L'G': case L'H': case L'I': case L'J':
case L'K': case L'L': case L'M': case L'N': case L'O':
case L'P': case L'Q': case L'R': case L'S': case L'T':
case L'U': case L'V': case L'W': case L'X': case L'Y':
case L'Z':
case L'[': case L'\\': case L']': case L'^': case L'_':
case L'a': case L'b': case L'c': case L'd': case L'e':
case L'f': case L'g': case L'h': case L'i': case L'j':
case L'k': case L'l': case L'm': case L'n': case L'o':
case L'p': case L'q': case L'r': case L's': case L't':
case L'u': case L'v': case L'w': case L'x': case L'y':
case L'z': case L'{': case L'|': case L'}': case L'~':
break;
default:
return (wctype_t) 0;
}
# endif
/* Avoid overrunning the buffer. */
if (cp == s + CHAR_CLASS_MAX_LENGTH)
return (wctype_t) 0;
return (wctype_t) 0;
*cp++ = (char) *wcs++;
}
@ -287,58 +287,58 @@ fnmatch (const char *pattern, const char *string, int flags)
int res;
/* Calculate the size needed to convert the strings to
wide characters. */
wide characters. */
memset (&ps, '\0', sizeof (ps));
patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1;
if (__builtin_expect (patsize != 0, 1))
{
assert (mbsinit (&ps));
strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1;
if (__builtin_expect (strsize != 0, 1))
{
assert (mbsinit (&ps));
totsize = patsize + strsize;
if (__builtin_expect (! (patsize <= totsize
&& totsize <= SIZE_MAX / sizeof (wchar_t)),
0))
{
errno = ENOMEM;
return -1;
}
{
assert (mbsinit (&ps));
strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1;
if (__builtin_expect (strsize != 0, 1))
{
assert (mbsinit (&ps));
totsize = patsize + strsize;
if (__builtin_expect (! (patsize <= totsize
&& totsize <= SIZE_MAX / sizeof (wchar_t)),
0))
{
errno = ENOMEM;
return -1;
}
/* Allocate room for the wide characters. */
if (__builtin_expect (totsize < ALLOCA_LIMIT, 1))
wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t));
else
{
wpattern = malloc (totsize * sizeof (wchar_t));
if (__builtin_expect (! wpattern, 0))
{
errno = ENOMEM;
return -1;
}
}
wstring = wpattern + patsize;
/* Allocate room for the wide characters. */
if (__builtin_expect (totsize < ALLOCA_LIMIT, 1))
wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t));
else
{
wpattern = malloc (totsize * sizeof (wchar_t));
if (__builtin_expect (! wpattern, 0))
{
errno = ENOMEM;
return -1;
}
}
wstring = wpattern + patsize;
/* Convert the strings into wide characters. */
mbsrtowcs (wpattern, &pattern, patsize, &ps);
assert (mbsinit (&ps));
mbsrtowcs (wstring, &string, strsize, &ps);
/* Convert the strings into wide characters. */
mbsrtowcs (wpattern, &pattern, patsize, &ps);
assert (mbsinit (&ps));
mbsrtowcs (wstring, &string, strsize, &ps);
res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1,
flags & FNM_PERIOD, flags);
res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1,
flags & FNM_PERIOD, flags);
if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0))
free (wpattern);
return res;
}
}
if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0))
free (wpattern);
return res;
}
}
}
# endif /* HANDLE_MULTIBYTE */
return internal_fnmatch (pattern, string, string + strlen (string),
flags & FNM_PERIOD, flags);
flags & FNM_PERIOD, flags);
}
# ifdef _LIBC
@ -351,4 +351,4 @@ compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
libc_hidden_ver (__fnmatch, fnmatch)
# endif
#endif /* _LIBC or not __GNU_LIBRARY__. */
#endif /* _LIBC or not __GNU_LIBRARY__. */

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* getdelim.c --- Implementation of replacement getdelim function.
Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005, 2006, 2007,
2008, 2009 Free Software Foundation, Inc.
Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005, 2006, 2007, 2008,
2009, 2010 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@ -21,13 +21,16 @@
#include <config.h>
/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
optimizes away the lineptr == NULL || n == NULL || fp == NULL tests below. */
#define _GL_ARG_NONNULL(params)
#include <stdio.h>
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#ifndef SSIZE_MAX
# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
@ -35,15 +38,15 @@
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
# define getc_maybe_unlocked(fp) getc(fp)
# define getc_maybe_unlocked(fp) getc(fp)
#elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED
# undef flockfile
# undef funlockfile
# define flockfile(x) ((void) 0)
# define funlockfile(x) ((void) 0)
# define getc_maybe_unlocked(fp) getc(fp)
# define getc_maybe_unlocked(fp) getc(fp)
#else
# define getc_maybe_unlocked(fp) getc_unlocked(fp)
# define getc_maybe_unlocked(fp) getc_unlocked(fp)
#endif
/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
@ -72,10 +75,10 @@ getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
*n = 120;
new_lineptr = (char *) realloc (*lineptr, *n);
if (new_lineptr == NULL)
{
result = -1;
goto unlock_return;
}
{
result = -1;
goto unlock_return;
}
*lineptr = new_lineptr;
}
@ -85,44 +88,44 @@ getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
i = getc_maybe_unlocked (fp);
if (i == EOF)
{
result = -1;
break;
}
{
result = -1;
break;
}
/* Make enough space for len+1 (for final NUL) bytes. */
if (cur_len + 1 >= *n)
{
size_t needed_max =
SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
size_t needed = 2 * *n + 1; /* Be generous. */
char *new_lineptr;
{
size_t needed_max =
SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
size_t needed = 2 * *n + 1; /* Be generous. */
char *new_lineptr;
if (needed_max < needed)
needed = needed_max;
if (cur_len + 1 >= needed)
{
result = -1;
errno = EOVERFLOW;
goto unlock_return;
}
if (needed_max < needed)
needed = needed_max;
if (cur_len + 1 >= needed)
{
result = -1;
errno = EOVERFLOW;
goto unlock_return;
}
new_lineptr = (char *) realloc (*lineptr, needed);
if (new_lineptr == NULL)
{
result = -1;
goto unlock_return;
}
new_lineptr = (char *) realloc (*lineptr, needed);
if (new_lineptr == NULL)
{
result = -1;
goto unlock_return;
}
*lineptr = new_lineptr;
*n = needed;
}
*lineptr = new_lineptr;
*n = needed;
}
(*lineptr)[cur_len] = i;
cur_len++;
if (i == delimiter)
break;
break;
}
(*lineptr)[cur_len] = '\0';
result = cur_len ? cur_len : result;

View file

@ -1,5 +1,5 @@
/* getline.c --- Implementation of replacement getline function.
Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004,2006
Free Software Foundation, Inc.
Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997,
1998, 2004, 2006, 2009, 2010 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software: you can redistribute it and/or modify
@ -32,25 +32,25 @@
#include <stdlib.h>
#endif
#ifndef NULL
#ifndef NULL
#define NULL 0
#endif
int
getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
const struct option *long_options, int *opt_index)
const struct option *long_options, int *opt_index)
{
return _getopt_internal (argc, (char **) argv, options, long_options,
opt_index, 0, 0);
opt_index, 0, 0);
}
int
_getopt_long_r (int argc, char **argv, const char *options,
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
{
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
0, 0, d);
0, d, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
@ -60,20 +60,20 @@ _getopt_long_r (int argc, char **argv, const char *options,
int
getopt_long_only (int argc, char *__getopt_argv_const *argv,
const char *options,
const struct option *long_options, int *opt_index)
const char *options,
const struct option *long_options, int *opt_index)
{
return _getopt_internal (argc, (char **) argv, options, long_options,
opt_index, 1, 0);
opt_index, 1, 0);
}
int
_getopt_long_only_r (int argc, char **argv, const char *options,
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
{
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
1, 0, d);
1, d, 0);
}
@ -91,76 +91,76 @@ main (int argc, char **argv)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
static const struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 0, 0, 0},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
long_options, &option_index);
if (c == -1)
break;
break;
switch (c)
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
{
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case 'd':
printf ("option d with value `%s'\n", optarg);
break;
case '?':
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("%s ", argv[optind++]);
printf ("\n");
}

View file

@ -1,6 +1,6 @@
/* Internal declarations for getopt.
Copyright (C) 1989-1994,1996-1999,2001,2003,2004
Free Software Foundation, Inc.
Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2004, 2009-2010 Free Software
Foundation, Inc.
This file is part of the GNU C Library.
This program is free software: you can redistribute it and/or modify
@ -17,12 +17,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef _GETOPT_INT_H
#define _GETOPT_INT_H 1
#define _GETOPT_INT_H 1
#include <getopt.h>
extern int _getopt_internal (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, int __posixly_correct);
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, int __posixly_correct);
/* Reentrant versions which can handle parsing multiple argument
@ -108,23 +110,23 @@ struct _getopt_data
/* The initializer is necessary to set OPTIND and OPTERR to their
default values and to clear the initialization flag. */
#define _GETOPT_DATA_INITIALIZER { 1, 1 }
#define _GETOPT_DATA_INITIALIZER { 1, 1 }
extern int _getopt_internal_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, int __posixly_correct,
struct _getopt_data *__data);
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, struct _getopt_data *__data,
int __posixly_correct);
extern int _getopt_long_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
struct _getopt_data *__data);
const char *__shortopts,
const struct option *__longopts, int *__longind,
struct _getopt_data *__data);
extern int _getopt_long_only_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts,
int *__longind,
struct _getopt_data *__data);
const char *__shortopts,
const struct option *__longopts,
int *__longind,
struct _getopt_data *__data);
#endif /* getopt_int.h */

View file

@ -1,5 +1,6 @@
/* Convenience header for conditional use of GNU <libintl.h>.
Copyright (C) 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc.
Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2010 Free Software
Foundation, Inc.
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
@ -63,21 +64,30 @@
for invalid uses of the value returned from these functions.
On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */
# undef gettext
# define gettext(Msgid) ((const char *) (Msgid))
# undef dgettext
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
# undef dcgettext
# define dcgettext(Domainname, Msgid, Category) \
((void) (Category), dgettext (Domainname, Msgid))
# undef ngettext
# define ngettext(Msgid1, Msgid2, N) \
((N) == 1 \
? ((void) (Msgid2), (const char *) (Msgid1)) \
: ((void) (Msgid1), (const char *) (Msgid2)))
# undef dngettext
# define dngettext(Domainname, Msgid1, Msgid2, N) \
((void) (Domainname), ngettext (Msgid1, Msgid2, N))
# undef dcngettext
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N))
((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N))
# undef textdomain
# define textdomain(Domainname) ((const char *) (Domainname))
# undef bindtextdomain
# define bindtextdomain(Domainname, Dirname) \
((void) (Domainname), (const char *) (Dirname))
# undef bind_textdomain_codeset
# define bind_textdomain_codeset(Domainname, Codeset) \
((void) (Domainname), (const char *) (Codeset))
@ -131,8 +141,8 @@ inline
#endif
static const char *
pgettext_aux (const char *domain,
const char *msg_ctxt_id, const char *msgid,
int category)
const char *msg_ctxt_id, const char *msgid,
int category)
{
const char *translation = dcgettext (domain, msg_ctxt_id, category);
if (translation == msg_ctxt_id)
@ -150,9 +160,9 @@ inline
#endif
static const char *
npgettext_aux (const char *domain,
const char *msg_ctxt_id, const char *msgid,
const char *msgid_plural, unsigned long int n,
int category)
const char *msg_ctxt_id, const char *msgid,
const char *msgid_plural, unsigned long int n,
int category)
{
const char *translation =
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
@ -190,8 +200,8 @@ inline
#endif
static const char *
dcpgettext_expr (const char *domain,
const char *msgctxt, const char *msgid,
int category)
const char *msgctxt, const char *msgid,
int category)
{
size_t msgctxt_len = strlen (msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1;
@ -213,10 +223,10 @@ dcpgettext_expr (const char *domain,
translation = dcgettext (domain, msg_ctxt_id, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf)
free (msg_ctxt_id);
free (msg_ctxt_id);
#endif
if (translation != msg_ctxt_id)
return translation;
return translation;
}
return msgid;
}
@ -235,9 +245,9 @@ inline
#endif
static const char *
dcnpgettext_expr (const char *domain,
const char *msgctxt, const char *msgid,
const char *msgid_plural, unsigned long int n,
int category)
const char *msgctxt, const char *msgid,
const char *msgid_plural, unsigned long int n,
int category)
{
size_t msgctxt_len = strlen (msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1;
@ -259,10 +269,10 @@ dcnpgettext_expr (const char *domain,
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf)
free (msg_ctxt_id);
free (msg_ctxt_id);
#endif
if (!(translation == msg_ctxt_id || translation == msgid_plural))
return translation;
return translation;
}
return (n == 1 ? msgid : msgid_plural);
}

View file

@ -1,6 +1,6 @@
/* Program name management.
Copyright (C) 2001-2003, 2005-2009 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
Copyright (C) 2001-2003, 2005-2010 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2001.
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
@ -23,6 +23,8 @@
#include "progname.h"
#include <errno.h> /* get program_invocation_name declaration */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -30,7 +32,9 @@
To be initialized by main(). */
const char *program_name = NULL;
/* Set program_name, based on argv[0]. */
/* Set program_name, based on argv[0].
argv0 must be a string allocated with indefinite extent, and must not be
modified after this call. */
void
set_program_name (const char *argv0)
{
@ -42,20 +46,30 @@ set_program_name (const char *argv0)
const char *slash;
const char *base;
/* Sanity check. POSIX requires the invoking process to pass a non-NULL
argv[0]. */
if (argv0 == NULL)
{
/* It's a bug in the invoking program. Help diagnosing it. */
fputs ("A NULL argv[0] was passed through an exec system call.\n",
stderr);
abort ();
}
slash = strrchr (argv0, '/');
base = (slash != NULL ? slash + 1 : argv0);
if (base - argv0 >= 7 && strncmp (base - 7, "/.libs/", 7) == 0)
{
argv0 = base;
if (strncmp (base, "lt-", 3) == 0)
{
argv0 = base + 3;
/* On glibc systems, remove the "lt-" prefix from the variable
program_invocation_short_name. */
{
argv0 = base + 3;
/* On glibc systems, remove the "lt-" prefix from the variable
program_invocation_short_name. */
#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
program_invocation_short_name = (char *) argv0;
program_invocation_short_name = (char *) argv0;
#endif
}
}
}
/* But don't strip off a leading <dirname>/ in general, because when the user

View file

@ -1,6 +1,6 @@
/* Program name management.
Copyright (C) 2001-2004, 2006 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
Copyright (C) 2001-2004, 2006, 2009-2010 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2001.
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
@ -31,7 +31,9 @@ extern "C" {
/* String containing name the program is called with. */
extern const char *program_name;
/* Set program_name, based on argv[0]. */
/* Set program_name, based on argv[0].
argv0 must be a string allocated with indefinite extent, and must not be
modified after this call. */
extern void set_program_name (const char *argv0);
#if ENABLE_RELOCATABLE
@ -39,8 +41,8 @@ extern void set_program_name (const char *argv0);
/* Set program_name, based on argv[0], and original installation prefix and
directory, for relocatability. */
extern void set_program_name_and_installdir (const char *argv0,
const char *orig_installprefix,
const char *orig_installdir);
const char *orig_installprefix,
const char *orig_installdir);
#undef set_program_name
#define set_program_name(ARG0) \
set_program_name_and_installdir (ARG0, INSTALLPREFIX, INSTALLDIR)

3877
gnulib/regcomp.c Normal file

File diff suppressed because it is too large Load diff

72
gnulib/regex.c Normal file
View file

@ -0,0 +1,72 @@
/* Extended regular expression matching and search library.
Copyright (C) 2002, 2003, 2005, 2006, 2009, 2010 Free Software Foundation,
Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <config.h>
/* Make sure noone compiles this code with a C++ compiler. */
#if defined __cplusplus && defined _LIBC
# error "This is C code, use a C compiler"
#endif
#ifdef _LIBC
/* We have to keep the namespace clean. */
# define regfree(preg) __regfree (preg)
# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)
# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)
# define regerror(errcode, preg, errbuf, errbuf_size) \
__regerror(errcode, preg, errbuf, errbuf_size)
# define re_set_registers(bu, re, nu, st, en) \
__re_set_registers (bu, re, nu, st, en)
# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \
__re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
# define re_match(bufp, string, size, pos, regs) \
__re_match (bufp, string, size, pos, regs)
# define re_search(bufp, string, size, startpos, range, regs) \
__re_search (bufp, string, size, startpos, range, regs)
# define re_compile_pattern(pattern, length, bufp) \
__re_compile_pattern (pattern, length, bufp)
# define re_set_syntax(syntax) __re_set_syntax (syntax)
# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \
__re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)
# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)
# include "../locale/localeinfo.h"
#endif
/* On some systems, limits.h sets RE_DUP_MAX to a lower value than
GNU regex allows. Include it before <regex.h>, which correctly
#undefs RE_DUP_MAX and sets it to the right value. */
#include <limits.h>
#include <regex.h>
#include "regex_internal.h"
#include "regex_internal.c"
#include "regcomp.c"
#include "regexec.c"
/* Binary backward compatibility. */
#if _LIBC
# include <shlib-compat.h>
# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")
int re_max_failures = 2000;
# endif
#endif

676
gnulib/regex.h Normal file
View file

@ -0,0 +1,676 @@
/* Definitions for data structures and routines for the regular
expression library.
Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993, 1995, 1996, 1997, 1998,
2000, 2001, 2002, 2003, 2005, 2006, 2009, 2010 Free Software Foundation,
Inc.
This file is part of the GNU C Library.
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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef _REGEX_H
#define _REGEX_H 1
#include <sys/types.h>
/* Allow the use in C++ code. */
#ifdef __cplusplus
extern "C" {
#endif
/* Define __USE_GNU_REGEX to declare GNU extensions that violate the
POSIX name space rules. */
#undef __USE_GNU_REGEX
#if (defined _GNU_SOURCE \
|| (!defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE \
&& !defined _XOPEN_SOURCE))
# define __USE_GNU_REGEX 1
#endif
#ifdef _REGEX_LARGE_OFFSETS
/* Use types and values that are wide enough to represent signed and
unsigned byte offsets in memory. This currently works only when
the regex code is used outside of the GNU C library; it is not yet
supported within glibc itself, and glibc users should not define
_REGEX_LARGE_OFFSETS. */
/* The type of the offset of a byte within a string.
For historical reasons POSIX 1003.1-2004 requires that regoff_t be
at least as wide as off_t. However, many common POSIX platforms set
regoff_t to the more-sensible ssize_t and the Open Group has
signalled its intention to change the requirement to be that
regoff_t be at least as wide as ptrdiff_t and ssize_t; see XBD ERN
60 (2005-08-25). We don't know of any hosts where ssize_t or
ptrdiff_t is wider than ssize_t, so ssize_t is safe. */
typedef ssize_t regoff_t;
/* The type of nonnegative object indexes. Traditionally, GNU regex
uses 'int' for these. Code that uses __re_idx_t should work
regardless of whether the type is signed. */
typedef size_t __re_idx_t;
/* The type of object sizes. */
typedef size_t __re_size_t;
/* The type of object sizes, in places where the traditional code
uses unsigned long int. */
typedef size_t __re_long_size_t;
#else
/* Use types that are binary-compatible with the traditional GNU regex
implementation, which mishandles strings longer than INT_MAX. */
typedef int regoff_t;
typedef int __re_idx_t;
typedef unsigned int __re_size_t;
typedef unsigned long int __re_long_size_t;
#endif
/* The following two types have to be signed and unsigned integer type
wide enough to hold a value of a pointer. For most ANSI compilers
ptrdiff_t and size_t should be likely OK. Still size of these two
types is 2 for Microsoft C. Ugh... */
typedef long int s_reg_t;
typedef unsigned long int active_reg_t;
/* The following bits are used to determine the regexp syntax we
recognize. The set/not-set meanings are chosen so that Emacs syntax
remains the value 0. The bits are given in alphabetical order, and
the definitions shifted by one from the previous bit; thus, when we
add or remove a bit, only one other definition need change. */
typedef unsigned long int reg_syntax_t;
#ifdef __USE_GNU_REGEX
/* If this bit is not set, then \ inside a bracket expression is literal.
If set, then such a \ quotes the following character. */
# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)
/* If this bit is not set, then + and ? are operators, and \+ and \? are
literals.
If set, then \+ and \? are operators and + and ? are literals. */
# define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
/* If this bit is set, then character classes are supported. They are:
[:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:],
[:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
If not set, then character classes are not supported. */
# define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
/* If this bit is set, then ^ and $ are always anchors (outside bracket
expressions, of course).
If this bit is not set, then it depends:
^ is an anchor if it is at the beginning of a regular
expression or after an open-group or an alternation operator;
$ is an anchor if it is at the end of a regular expression, or
before a close-group or an alternation operator.
This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
POSIX draft 11.2 says that * etc. in leading positions is undefined.
We already implemented a previous draft which made those constructs
invalid, though, so we haven't changed the code back. */
# define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
/* If this bit is set, then special characters are always special
regardless of where they are in the pattern.
If this bit is not set, then special characters are special only in
some contexts; otherwise they are ordinary. Specifically,
* + ? and intervals are only special when not after the beginning,
open-group, or alternation operator. */
# define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
/* If this bit is set, then *, +, ?, and { cannot be first in an re or
immediately after an alternation or begin-group operator. */
# define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
/* If this bit is set, then . matches newline.
If not set, then it doesn't. */
# define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
/* If this bit is set, then . doesn't match NUL.
If not set, then it does. */
# define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
/* If this bit is set, nonmatching lists [^...] do not match newline.
If not set, they do. */
# define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
/* If this bit is set, either \{...\} or {...} defines an
interval, depending on RE_NO_BK_BRACES.
If not set, \{, \}, {, and } are literals. */
# define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
/* If this bit is set, +, ? and | aren't recognized as operators.
If not set, they are. */
# define RE_LIMITED_OPS (RE_INTERVALS << 1)
/* If this bit is set, newline is an alternation operator.
If not set, newline is literal. */
# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
/* If this bit is set, then `{...}' defines an interval, and \{ and \}
are literals.
If not set, then `\{...\}' defines an interval. */
# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
/* If this bit is set, (...) defines a group, and \( and \) are literals.
If not set, \(...\) defines a group, and ( and ) are literals. */
# define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
/* If this bit is set, then \<digit> matches <digit>.
If not set, then \<digit> is a back-reference. */
# define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
/* If this bit is set, then | is an alternation operator, and \| is literal.
If not set, then \| is an alternation operator, and | is literal. */
# define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
/* If this bit is set, then an ending range point collating higher
than the starting range point, as in [z-a], is invalid.
If not set, then when ending range point collates higher than the
starting range point, the range is ignored. */
# define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
/* If this bit is set, then an unmatched ) is ordinary.
If not set, then an unmatched ) is invalid. */
# define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
/* If this bit is set, succeed as soon as we match the whole pattern,
without further backtracking. */
# define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)
/* If this bit is set, do not process the GNU regex operators.
If not set, then the GNU regex operators are recognized. */
# define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)
/* If this bit is set, turn on internal regex debugging.
If not set, and debugging was on, turn it off.
This only works if regex.c is compiled -DDEBUG.
We define this bit always, so that all that's needed to turn on
debugging is to recompile regex.c; the calling code can always have
this bit set, and it won't affect anything in the normal case. */
# define RE_DEBUG (RE_NO_GNU_OPS << 1)
/* If this bit is set, a syntactically invalid interval is treated as
a string of ordinary characters. For example, the ERE 'a{1' is
treated as 'a\{1'. */
# define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)
/* If this bit is set, then ignore case when matching.
If not set, then case is significant. */
# define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)
/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only
for ^, because it is difficult to scan the regex backwards to find
whether ^ should be special. */
# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1)
/* If this bit is set, then \{ cannot be first in an bre or
immediately after an alternation or begin-group operator. */
# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1)
/* If this bit is set, then no_sub will be set to 1 during
re_compile_pattern. */
# define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)
#endif /* defined __USE_GNU_REGEX */
/* This global variable defines the particular regexp syntax to use (for
some interfaces). When a regexp is compiled, the syntax used is
stored in the pattern buffer, so changing this does not affect
already-compiled regexps. */
extern reg_syntax_t re_syntax_options;
#ifdef __USE_GNU_REGEX
/* Define combinations of the above bits for the standard possibilities.
(The [[[ comments delimit what gets put into the Texinfo file, so
don't delete them!) */
/* [[[begin syntaxes]]] */
# define RE_SYNTAX_EMACS 0
# define RE_SYNTAX_AWK \
(RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \
| RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \
| RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)
# define RE_SYNTAX_GNU_AWK \
((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \
& ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \
| RE_CONTEXT_INVALID_OPS ))
# define RE_SYNTAX_POSIX_AWK \
(RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \
| RE_INTERVALS | RE_NO_GNU_OPS)
# define RE_SYNTAX_GREP \
(RE_BK_PLUS_QM | RE_CHAR_CLASSES \
| RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \
| RE_NEWLINE_ALT)
# define RE_SYNTAX_EGREP \
(RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \
| RE_NEWLINE_ALT | RE_NO_BK_PARENS \
| RE_NO_BK_VBAR)
# define RE_SYNTAX_POSIX_EGREP \
(RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \
| RE_INVALID_INTERVAL_ORD)
/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */
# define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
# define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
/* Syntax bits common to both basic and extended POSIX regex syntax. */
# define _RE_SYNTAX_POSIX_COMMON \
(RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \
| RE_INTERVALS | RE_NO_EMPTY_RANGES)
# define RE_SYNTAX_POSIX_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)
/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this
isn't minimal, since other operators, such as \`, aren't disabled. */
# define RE_SYNTAX_POSIX_MINIMAL_BASIC \
(_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
# define RE_SYNTAX_POSIX_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_VBAR \
| RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)
/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is
removed and RE_NO_BK_REFS is added. */
# define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \
(_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \
| RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \
| RE_NO_BK_PARENS | RE_NO_BK_REFS \
| RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD)
/* [[[end syntaxes]]] */
#endif /* defined __USE_GNU_REGEX */
#ifdef __USE_GNU_REGEX
/* Maximum number of duplicates an interval can allow. POSIX-conforming
systems might define this in <limits.h>, but we want our
value, so remove any previous define. */
# ifdef RE_DUP_MAX
# undef RE_DUP_MAX
# endif
/* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored
the counter as a 2-byte signed integer. This is no longer true, so
RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to
((SIZE_MAX - 2) / 10 - 1) if _REGEX_LARGE_OFFSETS is defined.
However, there would be a huge performance problem if someone
actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains
its historical value. */
# define RE_DUP_MAX (0x7fff)
#endif /* defined __USE_GNU_REGEX */
/* POSIX `cflags' bits (i.e., information for `regcomp'). */
/* If this bit is set, then use extended regular expression syntax.
If not set, then use basic regular expression syntax. */
#define REG_EXTENDED 1
/* If this bit is set, then ignore case when matching.
If not set, then case is significant. */
#define REG_ICASE (1 << 1)
/* If this bit is set, then anchors do not match at newline
characters in the string.
If not set, then anchors do match at newlines. */
#define REG_NEWLINE (1 << 2)
/* If this bit is set, then report only success or fail in regexec.
If not set, then returns differ between not matching and errors. */
#define REG_NOSUB (1 << 3)
/* POSIX `eflags' bits (i.e., information for regexec). */
/* If this bit is set, then the beginning-of-line operator doesn't match
the beginning of the string (presumably because it's not the
beginning of a line).
If not set, then the beginning-of-line operator does match the
beginning of the string. */
#define REG_NOTBOL 1
/* Like REG_NOTBOL, except for the end-of-line. */
#define REG_NOTEOL (1 << 1)
/* Use PMATCH[0] to delimit the start and end of the search in the
buffer. */
#define REG_STARTEND (1 << 2)
/* If any error codes are removed, changed, or added, update the
`__re_error_msgid' table in regcomp.c. */
typedef enum
{
_REG_ENOSYS = -1, /* This will never happen for this implementation. */
_REG_NOERROR = 0, /* Success. */
_REG_NOMATCH, /* Didn't find a match (for regexec). */
/* POSIX regcomp return error codes. (In the order listed in the
standard.) */
_REG_BADPAT, /* Invalid pattern. */
_REG_ECOLLATE, /* Invalid collating element. */
_REG_ECTYPE, /* Invalid character class name. */
_REG_EESCAPE, /* Trailing backslash. */
_REG_ESUBREG, /* Invalid back reference. */
_REG_EBRACK, /* Unmatched left bracket. */
_REG_EPAREN, /* Parenthesis imbalance. */
_REG_EBRACE, /* Unmatched \{. */
_REG_BADBR, /* Invalid contents of \{\}. */
_REG_ERANGE, /* Invalid range end. */
_REG_ESPACE, /* Ran out of memory. */
_REG_BADRPT, /* No preceding re for repetition op. */
/* Error codes we've added. */
_REG_EEND, /* Premature end. */
_REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */
_REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */
} reg_errcode_t;
#ifdef _XOPEN_SOURCE
# define REG_ENOSYS _REG_ENOSYS
#endif
#define REG_NOERROR _REG_NOERROR
#define REG_NOMATCH _REG_NOMATCH
#define REG_BADPAT _REG_BADPAT
#define REG_ECOLLATE _REG_ECOLLATE
#define REG_ECTYPE _REG_ECTYPE
#define REG_EESCAPE _REG_EESCAPE
#define REG_ESUBREG _REG_ESUBREG
#define REG_EBRACK _REG_EBRACK
#define REG_EPAREN _REG_EPAREN
#define REG_EBRACE _REG_EBRACE
#define REG_BADBR _REG_BADBR
#define REG_ERANGE _REG_ERANGE
#define REG_ESPACE _REG_ESPACE
#define REG_BADRPT _REG_BADRPT
#define REG_EEND _REG_EEND
#define REG_ESIZE _REG_ESIZE
#define REG_ERPAREN _REG_ERPAREN
/* struct re_pattern_buffer normally uses member names like `buffer'
that POSIX does not allow. In POSIX mode these members have names
with leading `re_' (e.g., `re_buffer'). */
#ifdef __USE_GNU_REGEX
# define _REG_RE_NAME(id) id
# define _REG_RM_NAME(id) id
#else
# define _REG_RE_NAME(id) re_##id
# define _REG_RM_NAME(id) rm_##id
#endif
/* The user can specify the type of the re_translate member by
defining the macro RE_TRANSLATE_TYPE, which defaults to unsigned
char *. This pollutes the POSIX name space, so in POSIX mode just
use unsigned char *. */
#ifdef __USE_GNU_REGEX
# ifndef RE_TRANSLATE_TYPE
# define RE_TRANSLATE_TYPE unsigned char *
# endif
# define REG_TRANSLATE_TYPE RE_TRANSLATE_TYPE
#else
# define REG_TRANSLATE_TYPE unsigned char *
#endif
/* This data structure represents a compiled pattern. Before calling
the pattern compiler, the fields `buffer', `allocated', `fastmap',
`translate', and `no_sub' can be set. After the pattern has been
compiled, the `re_nsub' field is available. All other fields are
private to the regex routines. */
struct re_pattern_buffer
{
/* Space that holds the compiled pattern. It is declared as
`unsigned char *' because its elements are sometimes used as
array indexes. */
unsigned char *_REG_RE_NAME (buffer);
/* Number of bytes to which `buffer' points. */
__re_long_size_t _REG_RE_NAME (allocated);
/* Number of bytes actually used in `buffer'. */
__re_long_size_t _REG_RE_NAME (used);
/* Syntax setting with which the pattern was compiled. */
reg_syntax_t _REG_RE_NAME (syntax);
/* Pointer to a fastmap, if any, otherwise zero. re_search uses the
fastmap, if there is one, to skip over impossible starting points
for matches. */
char *_REG_RE_NAME (fastmap);
/* Either a translate table to apply to all characters before
comparing them, or zero for no translation. The translation is
applied to a pattern when it is compiled and to a string when it
is matched. */
REG_TRANSLATE_TYPE _REG_RE_NAME (translate);
/* Number of subexpressions found by the compiler. */
size_t re_nsub;
/* Zero if this pattern cannot match the empty string, one else.
Well, in truth it's used only in `re_search_2', to see whether or
not we should use the fastmap, so we don't set this absolutely
perfectly; see `re_compile_fastmap' (the `duplicate' case). */
unsigned int _REG_RE_NAME (can_be_null) : 1;
/* If REGS_UNALLOCATED, allocate space in the `regs' structure
for `max (RE_NREGS, re_nsub + 1)' groups.
If REGS_REALLOCATE, reallocate space if necessary.
If REGS_FIXED, use what's there. */
#ifdef __USE_GNU_REGEX
# define REGS_UNALLOCATED 0
# define REGS_REALLOCATE 1
# define REGS_FIXED 2
#endif
unsigned int _REG_RE_NAME (regs_allocated) : 2;
/* Set to zero when `regex_compile' compiles a pattern; set to one
by `re_compile_fastmap' if it updates the fastmap. */
unsigned int _REG_RE_NAME (fastmap_accurate) : 1;
/* If set, `re_match_2' does not return information about
subexpressions. */
unsigned int _REG_RE_NAME (no_sub) : 1;
/* If set, a beginning-of-line anchor doesn't match at the beginning
of the string. */
unsigned int _REG_RE_NAME (not_bol) : 1;
/* Similarly for an end-of-line anchor. */
unsigned int _REG_RE_NAME (not_eol) : 1;
/* If true, an anchor at a newline matches. */
unsigned int _REG_RE_NAME (newline_anchor) : 1;
/* [[[end pattern_buffer]]] */
};
typedef struct re_pattern_buffer regex_t;
/* This is the structure we store register match data in. See
regex.texinfo for a full description of what registers match. */
struct re_registers
{
__re_size_t _REG_RM_NAME (num_regs);
regoff_t *_REG_RM_NAME (start);
regoff_t *_REG_RM_NAME (end);
};
/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
`re_match_2' returns information about at least this many registers
the first time a `regs' structure is passed. */
#if !defined RE_NREGS && defined __USE_GNU_REGEX
# define RE_NREGS 30
#endif
/* POSIX specification for registers. Aside from the different names than
`re_registers', POSIX uses an array of structures, instead of a
structure of arrays. */
typedef struct
{
regoff_t rm_so; /* Byte offset from string's start to substring's start. */
regoff_t rm_eo; /* Byte offset from string's start to substring's end. */
} regmatch_t;
/* Declarations for routines. */
/* Sets the current default syntax to SYNTAX, and return the old syntax.
You can also simply assign to the `re_syntax_options' variable. */
extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax);
/* Compile the regular expression PATTERN, with length LENGTH
and syntax given by the global `re_syntax_options', into the buffer
BUFFER. Return NULL if successful, and an error string if not. */
extern const char *re_compile_pattern (const char *__pattern, size_t __length,
struct re_pattern_buffer *__buffer);
/* Compile a fastmap for the compiled pattern in BUFFER; used to
accelerate searches. Return 0 if successful and -2 if was an
internal error. */
extern int re_compile_fastmap (struct re_pattern_buffer *__buffer);
/* Search in the string STRING (with length LENGTH) for the pattern
compiled into BUFFER. Start searching at position START, for RANGE
characters. Return the starting position of the match, -1 for no
match, or -2 for an internal error. Also return register
information in REGS (if REGS and BUFFER->no_sub are nonzero). */
extern regoff_t re_search (struct re_pattern_buffer *__buffer,
const char *__string, __re_idx_t __length,
__re_idx_t __start, regoff_t __range,
struct re_registers *__regs);
/* Like `re_search', but search in the concatenation of STRING1 and
STRING2. Also, stop searching at index START + STOP. */
extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer,
const char *__string1, __re_idx_t __length1,
const char *__string2, __re_idx_t __length2,
__re_idx_t __start, regoff_t __range,
struct re_registers *__regs,
__re_idx_t __stop);
/* Like `re_search', but return how many characters in STRING the regexp
in BUFFER matched, starting at position START. */
extern regoff_t re_match (struct re_pattern_buffer *__buffer,
const char *__string, __re_idx_t __length,
__re_idx_t __start, struct re_registers *__regs);
/* Relates to `re_match' as `re_search_2' relates to `re_search'. */
extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer,
const char *__string1, __re_idx_t __length1,
const char *__string2, __re_idx_t __length2,
__re_idx_t __start, struct re_registers *__regs,
__re_idx_t __stop);
/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
ENDS. Subsequent matches using BUFFER and REGS will use this memory
for recording register information. STARTS and ENDS must be
allocated with malloc, and must each be at least `NUM_REGS * sizeof
(regoff_t)' bytes long.
If NUM_REGS == 0, then subsequent matches should allocate their own
register data.
Unless this function is called, the first search or match using
PATTERN_BUFFER will allocate its own register data, without
freeing the old data. */
extern void re_set_registers (struct re_pattern_buffer *__buffer,
struct re_registers *__regs,
__re_size_t __num_regs,
regoff_t *__starts, regoff_t *__ends);
#if defined _REGEX_RE_COMP || defined _LIBC
# ifndef _CRAY
/* 4.2 bsd compatibility. */
extern char *re_comp (const char *);
extern int re_exec (const char *);
# endif
#endif
/* GCC 2.95 and later have "__restrict"; C99 compilers have
"restrict", and "configure" may have defined "restrict".
Other compilers use __restrict, __restrict__, and _Restrict, and
'configure' might #define 'restrict' to those words, so pick a
different name. */
#ifndef _Restrict_
# if 199901L <= __STDC_VERSION__
# define _Restrict_ restrict
# elif 2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)
# define _Restrict_ __restrict
# else
# define _Restrict_
# endif
#endif
/* gcc 3.1 and up support the [restrict] syntax. Don't trust
sys/cdefs.h's definition of __restrict_arr, though, as it
mishandles gcc -ansi -pedantic. */
#ifndef _Restrict_arr_
# if ((199901L <= __STDC_VERSION__ \
|| ((3 < __GNUC__ || (3 == __GNUC__ && 1 <= __GNUC_MINOR__)) \
&& !__STRICT_ANSI__)) \
&& !defined __GNUG__)
# define _Restrict_arr_ _Restrict_
# else
# define _Restrict_arr_
# endif
#endif
/* POSIX compatibility. */
extern int regcomp (regex_t *_Restrict_ __preg,
const char *_Restrict_ __pattern,
int __cflags);
extern int regexec (const regex_t *_Restrict_ __preg,
const char *_Restrict_ __string, size_t __nmatch,
regmatch_t __pmatch[_Restrict_arr_],
int __eflags);
extern size_t regerror (int __errcode, const regex_t *_Restrict_ __preg,
char *_Restrict_ __errbuf, size_t __errbuf_size);
extern void regfree (regex_t *__preg);
#ifdef __cplusplus
}
#endif /* C++ */
#endif /* regex.h */

1740
gnulib/regex_internal.c Normal file

File diff suppressed because it is too large Load diff

871
gnulib/regex_internal.h Normal file
View file

@ -0,0 +1,871 @@
/* Extended regular expression matching and search library.
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef _REGEX_INTERNAL_H
#define _REGEX_INTERNAL_H 1
#include <assert.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <langinfo.h>
#ifndef _LIBC
# include "localcharset.h"
#endif
#if defined HAVE_LOCALE_H || defined _LIBC
# include <locale.h>
#endif
#include <wchar.h>
#include <wctype.h>
#include <stdint.h>
#if defined _LIBC
# include <bits/libc-lock.h>
#else
# define __libc_lock_init(NAME) do { } while (0)
# define __libc_lock_lock(NAME) do { } while (0)
# define __libc_lock_unlock(NAME) do { } while (0)
#endif
/* In case that the system doesn't have isblank(). */
#if !defined _LIBC && ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK))
# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
#endif
#ifdef _LIBC
# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
# define _RE_DEFINE_LOCALE_FUNCTIONS 1
# include <locale/localeinfo.h>
# include <locale/elem-hash.h>
# include <locale/coll-lookup.h>
# endif
#endif
/* This is for other GNU distributions with internationalized messages. */
#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
# include <libintl.h>
# ifdef _LIBC
# undef gettext
# define gettext(msgid) \
INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES)
# endif
#else
# define gettext(msgid) (msgid)
#endif
#ifndef gettext_noop
/* This define is so xgettext can find the internationalizable
strings. */
# define gettext_noop(String) String
#endif
/* For loser systems without the definition. */
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_ISWCTYPE && HAVE_WCSCOLL) || _LIBC
# define RE_ENABLE_I18N
#endif
#if __GNUC__ >= 3
# define BE(expr, val) __builtin_expect (expr, val)
#else
# define BE(expr, val) (expr)
# ifdef _LIBC
# define inline
# endif
#endif
/* Number of ASCII characters. */
#define ASCII_CHARS 0x80
/* Number of single byte characters. */
#define SBC_MAX (UCHAR_MAX + 1)
#define COLL_ELEM_LEN_MAX 8
/* The character which represents newline. */
#define NEWLINE_CHAR '\n'
#define WIDE_NEWLINE_CHAR L'\n'
/* Rename to standard API for using out of glibc. */
#ifndef _LIBC
# define __wctype wctype
# define __iswctype iswctype
# define __btowc btowc
# define __wcrtomb wcrtomb
# define __mbrtowc mbrtowc
# define __regfree regfree
# define attribute_hidden
#endif /* not _LIBC */
#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
# define __attribute(arg) __attribute__ (arg)
#else
# define __attribute(arg)
#endif
typedef __re_idx_t Idx;
/* Special return value for failure to match. */
#define REG_MISSING ((Idx) -1)
/* Special return value for internal error. */
#define REG_ERROR ((Idx) -2)
/* Test whether N is a valid index, and is not one of the above. */
#ifdef _REGEX_LARGE_OFFSETS
# define REG_VALID_INDEX(n) ((Idx) (n) < REG_ERROR)
#else
# define REG_VALID_INDEX(n) (0 <= (n))
#endif
/* Test whether N is a valid nonzero index. */
#ifdef _REGEX_LARGE_OFFSETS
# define REG_VALID_NONZERO_INDEX(n) ((Idx) ((n) - 1) < (Idx) (REG_ERROR - 1))
#else
# define REG_VALID_NONZERO_INDEX(n) (0 < (n))
#endif
/* A hash value, suitable for computing hash tables. */
typedef __re_size_t re_hashval_t;
/* An integer used to represent a set of bits. It must be unsigned,
and must be at least as wide as unsigned int. */
typedef unsigned long int bitset_word_t;
/* All bits set in a bitset_word_t. */
#define BITSET_WORD_MAX ULONG_MAX
/* Number of bits in a bitset_word_t. For portability to hosts with
padding bits, do not use '(sizeof (bitset_word_t) * CHAR_BIT)';
instead, deduce it directly from BITSET_WORD_MAX. Avoid
greater-than-32-bit integers and unconditional shifts by more than
31 bits, as they're not portable. */
#if BITSET_WORD_MAX == 0xffffffffUL
# define BITSET_WORD_BITS 32
#elif BITSET_WORD_MAX >> 31 >> 4 == 1
# define BITSET_WORD_BITS 36
#elif BITSET_WORD_MAX >> 31 >> 16 == 1
# define BITSET_WORD_BITS 48
#elif BITSET_WORD_MAX >> 31 >> 28 == 1
# define BITSET_WORD_BITS 60
#elif BITSET_WORD_MAX >> 31 >> 31 >> 1 == 1
# define BITSET_WORD_BITS 64
#elif BITSET_WORD_MAX >> 31 >> 31 >> 9 == 1
# define BITSET_WORD_BITS 72
#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 3 == 1
# define BITSET_WORD_BITS 128
#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 == 1
# define BITSET_WORD_BITS 256
#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 > 1
# define BITSET_WORD_BITS 257 /* any value > SBC_MAX will do here */
# if BITSET_WORD_BITS <= SBC_MAX
# error "Invalid SBC_MAX"
# endif
#else
# error "Add case for new bitset_word_t size"
#endif
/* Number of bitset_word_t values in a bitset_t. */
#define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
typedef bitset_word_t bitset_t[BITSET_WORDS];
typedef bitset_word_t *re_bitset_ptr_t;
typedef const bitset_word_t *re_const_bitset_ptr_t;
#define PREV_WORD_CONSTRAINT 0x0001
#define PREV_NOTWORD_CONSTRAINT 0x0002
#define NEXT_WORD_CONSTRAINT 0x0004
#define NEXT_NOTWORD_CONSTRAINT 0x0008
#define PREV_NEWLINE_CONSTRAINT 0x0010
#define NEXT_NEWLINE_CONSTRAINT 0x0020
#define PREV_BEGBUF_CONSTRAINT 0x0040
#define NEXT_ENDBUF_CONSTRAINT 0x0080
#define WORD_DELIM_CONSTRAINT 0x0100
#define NOT_WORD_DELIM_CONSTRAINT 0x0200
typedef enum
{
INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,
WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,
LINE_FIRST = PREV_NEWLINE_CONSTRAINT,
LINE_LAST = NEXT_NEWLINE_CONSTRAINT,
BUF_FIRST = PREV_BEGBUF_CONSTRAINT,
BUF_LAST = NEXT_ENDBUF_CONSTRAINT,
WORD_DELIM = WORD_DELIM_CONSTRAINT,
NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT
} re_context_type;
typedef struct
{
Idx alloc;
Idx nelem;
Idx *elems;
} re_node_set;
typedef enum
{
NON_TYPE = 0,
/* Node type, These are used by token, node, tree. */
CHARACTER = 1,
END_OF_RE = 2,
SIMPLE_BRACKET = 3,
OP_BACK_REF = 4,
OP_PERIOD = 5,
#ifdef RE_ENABLE_I18N
COMPLEX_BRACKET = 6,
OP_UTF8_PERIOD = 7,
#endif /* RE_ENABLE_I18N */
/* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used
when the debugger shows values of this enum type. */
#define EPSILON_BIT 8
OP_OPEN_SUBEXP = EPSILON_BIT | 0,
OP_CLOSE_SUBEXP = EPSILON_BIT | 1,
OP_ALT = EPSILON_BIT | 2,
OP_DUP_ASTERISK = EPSILON_BIT | 3,
ANCHOR = EPSILON_BIT | 4,
/* Tree type, these are used only by tree. */
CONCAT = 16,
SUBEXP = 17,
/* Token type, these are used only by token. */
OP_DUP_PLUS = 18,
OP_DUP_QUESTION,
OP_OPEN_BRACKET,
OP_CLOSE_BRACKET,
OP_CHARSET_RANGE,
OP_OPEN_DUP_NUM,
OP_CLOSE_DUP_NUM,
OP_NON_MATCH_LIST,
OP_OPEN_COLL_ELEM,
OP_CLOSE_COLL_ELEM,
OP_OPEN_EQUIV_CLASS,
OP_CLOSE_EQUIV_CLASS,
OP_OPEN_CHAR_CLASS,
OP_CLOSE_CHAR_CLASS,
OP_WORD,
OP_NOTWORD,
OP_SPACE,
OP_NOTSPACE,
BACK_SLASH
} re_token_type_t;
#ifdef RE_ENABLE_I18N
typedef struct
{
/* Multibyte characters. */
wchar_t *mbchars;
/* Collating symbols. */
# ifdef _LIBC
int32_t *coll_syms;
# endif
/* Equivalence classes. */
# ifdef _LIBC
int32_t *equiv_classes;
# endif
/* Range expressions. */
# ifdef _LIBC
uint32_t *range_starts;
uint32_t *range_ends;
# else /* not _LIBC */
wchar_t *range_starts;
wchar_t *range_ends;
# endif /* not _LIBC */
/* Character classes. */
wctype_t *char_classes;
/* If this character set is the non-matching list. */
unsigned int non_match : 1;
/* # of multibyte characters. */
Idx nmbchars;
/* # of collating symbols. */
Idx ncoll_syms;
/* # of equivalence classes. */
Idx nequiv_classes;
/* # of range expressions. */
Idx nranges;
/* # of character classes. */
Idx nchar_classes;
} re_charset_t;
#endif /* RE_ENABLE_I18N */
typedef struct
{
union
{
unsigned char c; /* for CHARACTER */
re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */
#ifdef RE_ENABLE_I18N
re_charset_t *mbcset; /* for COMPLEX_BRACKET */
#endif /* RE_ENABLE_I18N */
Idx idx; /* for BACK_REF */
re_context_type ctx_type; /* for ANCHOR */
} opr;
#if __GNUC__ >= 2 && !__STRICT_ANSI__
re_token_type_t type : 8;
#else
re_token_type_t type;
#endif
unsigned int constraint : 10; /* context constraint */
unsigned int duplicated : 1;
unsigned int opt_subexp : 1;
#ifdef RE_ENABLE_I18N
unsigned int accept_mb : 1;
/* These 2 bits can be moved into the union if needed (e.g. if running out
of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */
unsigned int mb_partial : 1;
#endif
unsigned int word_char : 1;
} re_token_t;
#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT)
struct re_string_t
{
/* Indicate the raw buffer which is the original string passed as an
argument of regexec(), re_search(), etc.. */
const unsigned char *raw_mbs;
/* Store the multibyte string. In case of "case insensitive mode" like
REG_ICASE, upper cases of the string are stored, otherwise MBS points
the same address that RAW_MBS points. */
unsigned char *mbs;
#ifdef RE_ENABLE_I18N
/* Store the wide character string which is corresponding to MBS. */
wint_t *wcs;
Idx *offsets;
mbstate_t cur_state;
#endif
/* Index in RAW_MBS. Each character mbs[i] corresponds to
raw_mbs[raw_mbs_idx + i]. */
Idx raw_mbs_idx;
/* The length of the valid characters in the buffers. */
Idx valid_len;
/* The corresponding number of bytes in raw_mbs array. */
Idx valid_raw_len;
/* The length of the buffers MBS and WCS. */
Idx bufs_len;
/* The index in MBS, which is updated by re_string_fetch_byte. */
Idx cur_idx;
/* length of RAW_MBS array. */
Idx raw_len;
/* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */
Idx len;
/* End of the buffer may be shorter than its length in the cases such
as re_match_2, re_search_2. Then, we use STOP for end of the buffer
instead of LEN. */
Idx raw_stop;
/* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */
Idx stop;
/* The context of mbs[0]. We store the context independently, since
the context of mbs[0] may be different from raw_mbs[0], which is
the beginning of the input string. */
unsigned int tip_context;
/* The translation passed as a part of an argument of re_compile_pattern. */
RE_TRANSLATE_TYPE trans;
/* Copy of re_dfa_t's word_char. */
re_const_bitset_ptr_t word_char;
/* true if REG_ICASE. */
unsigned char icase;
unsigned char is_utf8;
unsigned char map_notascii;
unsigned char mbs_allocated;
unsigned char offsets_needed;
unsigned char newline_anchor;
unsigned char word_ops_used;
int mb_cur_max;
};
typedef struct re_string_t re_string_t;
struct re_dfa_t;
typedef struct re_dfa_t re_dfa_t;
#ifndef _LIBC
# if defined __i386__ && !defined __EMX__
# define internal_function __attribute ((regparm (3), stdcall))
# else
# define internal_function
# endif
#endif
static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
Idx new_buf_len)
internal_function;
#ifdef RE_ENABLE_I18N
static void build_wcs_buffer (re_string_t *pstr) internal_function;
static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr)
internal_function;
#endif /* RE_ENABLE_I18N */
static void build_upper_buffer (re_string_t *pstr) internal_function;
static void re_string_translate_buffer (re_string_t *pstr) internal_function;
static unsigned int re_string_context_at (const re_string_t *input, Idx idx,
int eflags)
internal_function __attribute ((pure));
#define re_string_peek_byte(pstr, offset) \
((pstr)->mbs[(pstr)->cur_idx + offset])
#define re_string_fetch_byte(pstr) \
((pstr)->mbs[(pstr)->cur_idx++])
#define re_string_first_byte(pstr, idx) \
((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF)
#define re_string_is_single_byte_char(pstr, idx) \
((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \
|| (pstr)->wcs[(idx) + 1] != WEOF))
#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx)
#define re_string_cur_idx(pstr) ((pstr)->cur_idx)
#define re_string_get_buffer(pstr) ((pstr)->mbs)
#define re_string_length(pstr) ((pstr)->len)
#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])
#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
#include <alloca.h>
#ifndef _LIBC
# if HAVE_ALLOCA
/* The OS usually guarantees only one guard page at the bottom of the stack,
and a page size can be as small as 4096 bytes. So we cannot safely
allocate anything larger than 4096 bytes. Also care for the possibility
of a few compiler-allocated temporary stack slots. */
# define __libc_use_alloca(n) ((n) < 4032)
# else
/* alloca is implemented with malloc, so just use malloc. */
# define __libc_use_alloca(n) 0
# endif
#endif
#ifndef MAX
# define MAX(a,b) ((a) < (b) ? (b) : (a))
#endif
#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))
#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))
#define re_free(p) free (p)
struct bin_tree_t
{
struct bin_tree_t *parent;
struct bin_tree_t *left;
struct bin_tree_t *right;
struct bin_tree_t *first;
struct bin_tree_t *next;
re_token_t token;
/* `node_idx' is the index in dfa->nodes, if `type' == 0.
Otherwise `type' indicate the type of this node. */
Idx node_idx;
};
typedef struct bin_tree_t bin_tree_t;
#define BIN_TREE_STORAGE_SIZE \
((1024 - sizeof (void *)) / sizeof (bin_tree_t))
struct bin_tree_storage_t
{
struct bin_tree_storage_t *next;
bin_tree_t data[BIN_TREE_STORAGE_SIZE];
};
typedef struct bin_tree_storage_t bin_tree_storage_t;
#define CONTEXT_WORD 1
#define CONTEXT_NEWLINE (CONTEXT_WORD << 1)
#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1)
#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1)
#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD)
#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE)
#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF)
#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF)
#define IS_ORDINARY_CONTEXT(c) ((c) == 0)
#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_')
#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR)
#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_')
#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR)
#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \
((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
|| ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
|| ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\
|| ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context)))
#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \
((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \
|| (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \
|| (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \
|| (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context)))
struct re_dfastate_t
{
re_hashval_t hash;
re_node_set nodes;
re_node_set non_eps_nodes;
re_node_set inveclosure;
re_node_set *entrance_nodes;
struct re_dfastate_t **trtable, **word_trtable;
unsigned int context : 4;
unsigned int halt : 1;
/* If this state can accept `multi byte'.
Note that we refer to multibyte characters, and multi character
collating elements as `multi byte'. */
unsigned int accept_mb : 1;
/* If this state has backreference node(s). */
unsigned int has_backref : 1;
unsigned int has_constraint : 1;
};
typedef struct re_dfastate_t re_dfastate_t;
struct re_state_table_entry
{
Idx num;
Idx alloc;
re_dfastate_t **array;
};
/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */
typedef struct
{
Idx next_idx;
Idx alloc;
re_dfastate_t **array;
} state_array_t;
/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */
typedef struct
{
Idx node;
Idx str_idx; /* The position NODE match at. */
state_array_t path;
} re_sub_match_last_t;
/* Store information about the node NODE whose type is OP_OPEN_SUBEXP.
And information about the node, whose type is OP_CLOSE_SUBEXP,
corresponding to NODE is stored in LASTS. */
typedef struct
{
Idx str_idx;
Idx node;
state_array_t *path;
Idx alasts; /* Allocation size of LASTS. */
Idx nlasts; /* The number of LASTS. */
re_sub_match_last_t **lasts;
} re_sub_match_top_t;
struct re_backref_cache_entry
{
Idx node;
Idx str_idx;
Idx subexp_from;
Idx subexp_to;
char more;
char unused;
unsigned short int eps_reachable_subexps_map;
};
typedef struct
{
/* The string object corresponding to the input string. */
re_string_t input;
#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
const re_dfa_t *const dfa;
#else
const re_dfa_t *dfa;
#endif
/* EFLAGS of the argument of regexec. */
int eflags;
/* Where the matching ends. */
Idx match_last;
Idx last_node;
/* The state log used by the matcher. */
re_dfastate_t **state_log;
Idx state_log_top;
/* Back reference cache. */
Idx nbkref_ents;
Idx abkref_ents;
struct re_backref_cache_entry *bkref_ents;
int max_mb_elem_len;
Idx nsub_tops;
Idx asub_tops;
re_sub_match_top_t **sub_tops;
} re_match_context_t;
typedef struct
{
re_dfastate_t **sifted_states;
re_dfastate_t **limited_states;
Idx last_node;
Idx last_str_idx;
re_node_set limits;
} re_sift_context_t;
struct re_fail_stack_ent_t
{
Idx idx;
Idx node;
regmatch_t *regs;
re_node_set eps_via_nodes;
};
struct re_fail_stack_t
{
Idx num;
Idx alloc;
struct re_fail_stack_ent_t *stack;
};
struct re_dfa_t
{
re_token_t *nodes;
size_t nodes_alloc;
size_t nodes_len;
Idx *nexts;
Idx *org_indices;
re_node_set *edests;
re_node_set *eclosures;
re_node_set *inveclosures;
struct re_state_table_entry *state_table;
re_dfastate_t *init_state;
re_dfastate_t *init_state_word;
re_dfastate_t *init_state_nl;
re_dfastate_t *init_state_begbuf;
bin_tree_t *str_tree;
bin_tree_storage_t *str_tree_storage;
re_bitset_ptr_t sb_char;
int str_tree_storage_idx;
/* number of subexpressions `re_nsub' is in regex_t. */
re_hashval_t state_hash_mask;
Idx init_node;
Idx nbackref; /* The number of backreference in this dfa. */
/* Bitmap expressing which backreference is used. */
bitset_word_t used_bkref_map;
bitset_word_t completed_bkref_map;
unsigned int has_plural_match : 1;
/* If this dfa has "multibyte node", which is a backreference or
a node which can accept multibyte character or multi character
collating element. */
unsigned int has_mb_node : 1;
unsigned int is_utf8 : 1;
unsigned int map_notascii : 1;
unsigned int word_ops_used : 1;
int mb_cur_max;
bitset_t word_char;
reg_syntax_t syntax;
Idx *subexp_map;
#ifdef DEBUG
char* re_str;
#endif
#ifdef _LIBC
__libc_lock_define (, lock)
#endif
};
#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))
#define re_node_set_remove(set,id) \
(re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))
#define re_node_set_empty(p) ((p)->nelem = 0)
#define re_node_set_free(set) re_free ((set)->elems)
typedef enum
{
SB_CHAR,
MB_CHAR,
EQUIV_CLASS,
COLL_SYM,
CHAR_CLASS
} bracket_elem_type;
typedef struct
{
bracket_elem_type type;
union
{
unsigned char ch;
unsigned char *name;
wchar_t wch;
} opr;
} bracket_elem_t;
/* Inline functions for bitset_t operation. */
static inline void
bitset_set (bitset_t set, Idx i)
{
set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS;
}
static inline void
bitset_clear (bitset_t set, Idx i)
{
set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS);
}
static inline bool
bitset_contain (const bitset_t set, Idx i)
{
return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1;
}
static inline void
bitset_empty (bitset_t set)
{
memset (set, '\0', sizeof (bitset_t));
}
static inline void
bitset_set_all (bitset_t set)
{
memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS));
if (SBC_MAX % BITSET_WORD_BITS != 0)
set[BITSET_WORDS - 1] =
((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1;
}
static inline void
bitset_copy (bitset_t dest, const bitset_t src)
{
memcpy (dest, src, sizeof (bitset_t));
}
static inline void
bitset_not (bitset_t set)
{
int bitset_i;
for (bitset_i = 0; bitset_i < SBC_MAX / BITSET_WORD_BITS; ++bitset_i)
set[bitset_i] = ~set[bitset_i];
if (SBC_MAX % BITSET_WORD_BITS != 0)
set[BITSET_WORDS - 1] =
((((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1)
& ~set[BITSET_WORDS - 1]);
}
static inline void
bitset_merge (bitset_t dest, const bitset_t src)
{
int bitset_i;
for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
dest[bitset_i] |= src[bitset_i];
}
static inline void
bitset_mask (bitset_t dest, const bitset_t src)
{
int bitset_i;
for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)
dest[bitset_i] &= src[bitset_i];
}
#ifdef RE_ENABLE_I18N
/* Inline functions for re_string. */
static inline int
internal_function __attribute ((pure))
re_string_char_size_at (const re_string_t *pstr, Idx idx)
{
int byte_idx;
if (pstr->mb_cur_max == 1)
return 1;
for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)
if (pstr->wcs[idx + byte_idx] != WEOF)
break;
return byte_idx;
}
static inline wint_t
internal_function __attribute ((pure))
re_string_wchar_at (const re_string_t *pstr, Idx idx)
{
if (pstr->mb_cur_max == 1)
return (wint_t) pstr->mbs[idx];
return (wint_t) pstr->wcs[idx];
}
static int
internal_function __attribute ((pure))
re_string_elem_size_at (const re_string_t *pstr, Idx idx)
{
# ifdef _LIBC
const unsigned char *p, *extra;
const int32_t *table, *indirect;
int32_t tmp;
# include <locale/weight.h>
uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
if (nrules != 0)
{
table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
extra = (const unsigned char *)
_NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);
indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
_NL_COLLATE_INDIRECTMB);
p = pstr->mbs + idx;
tmp = findidx (&p);
return p - pstr->mbs - idx;
}
else
# endif /* _LIBC */
return 1;
}
#endif /* RE_ENABLE_I18N */
#ifndef __GNUC_PREREQ
# if defined __GNUC__ && defined __GNUC_MINOR__
# define __GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
# else
# define __GNUC_PREREQ(maj, min) 0
# endif
#endif
#if __GNUC_PREREQ (3,4)
# undef __attribute_warn_unused_result__
# define __attribute_warn_unused_result__ \
__attribute__ ((__warn_unused_result__))
#else
# define __attribute_warn_unused_result__ /* empty */
#endif
#endif /* _REGEX_INTERNAL_H */

4416
gnulib/regexec.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,7 @@
extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s);
/* NLS can be disabled through the configure --disable-nls option. */
#if ENABLE_NLS
#if (defined(ENABLE_NLS) && ENABLE_NLS)
# ifdef GRUB_UTIL
@ -34,7 +34,7 @@ extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s);
# endif /* GRUB_UTIL */
#else /* ! ENABLE_NLS */
#else /* ! (defined(ENABLE_NLS) && ENABLE_NLS) */
/* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings
@ -47,7 +47,7 @@ extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s);
# define grub_gettext(str) ((const char *) (str))
# endif /* GRUB_UTIL */
#endif /* ENABLE_NLS */
#endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */
#ifdef GRUB_UTIL
# define _(str) gettext(str)

View file

@ -19,17 +19,23 @@
#ifndef GRUB_MULTIBOOT_CPU_HEADER
#define GRUB_MULTIBOOT_CPU_HEADER 1
/* The asm part of the multiboot loader. */
void grub_multiboot_real_boot (grub_addr_t entry,
struct multiboot_info *mbi)
__attribute__ ((noreturn));
void grub_multiboot2_real_boot (grub_addr_t entry,
struct multiboot_info *mbi)
__attribute__ ((noreturn));
extern grub_uint32_t grub_multiboot_payload_eip;
extern char *grub_multiboot_payload_orig;
extern grub_addr_t grub_multiboot_payload_dest;
extern grub_size_t grub_multiboot_payload_size;
#define MULTIBOOT_INITIAL_STATE { .eax = MULTIBOOT_BOOTLOADER_MAGIC, \
.ecx = 0, \
.edx = 0, \
/* Set esp to some random location in low memory to avoid breaking */ \
/* non-compliant kernels. */ \
.esp = 0x7ff00 \
}
#define MULTIBOOT_ENTRY_REGISTER eip
#define MULTIBOOT_MBI_REGISTER ebx
#define MULTIBOOT_ARCHITECTURE_CURRENT MULTIBOOT_ARCHITECTURE_I386
#define MULTIBOOT_ELF32_MACHINE EM_386
#define MULTIBOOT_ELF64_MACHINE EM_X86_64
#endif /* ! GRUB_MULTIBOOT_CPU_HEADER */

View file

@ -33,7 +33,7 @@ grub_uint32_t grub_get_eisa_mmap (void);
/* Get a memory map entry. Return next continuation value. Zero means
the end. */
grub_uint32_t EXPORT_FUNC(grub_get_mmap_entry) (struct grub_machine_mmap_entry *entry,
grub_uint32_t grub_get_mmap_entry (struct grub_machine_mmap_entry *entry,
grub_uint32_t cont);
/* Turn on/off Gate A20. */

View file

@ -28,7 +28,4 @@
/* Set the video mode to MODE and return the previous mode. */
unsigned char EXPORT_FUNC(grub_vga_set_mode) (unsigned char mode);
/* Return a pointer to the ROM font table. */
unsigned char *EXPORT_FUNC(grub_vga_get_font) (void);
#endif /* ! GRUB_VGA_MACHINE_HEADER */

View file

@ -0,0 +1,36 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2004,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/>.
*/
#ifndef GRUB_MULTIBOOT_CPU_HEADER
#define GRUB_MULTIBOOT_CPU_HEADER 1
extern grub_uint32_t grub_multiboot_payload_eip;
extern char *grub_multiboot_payload_orig;
extern grub_addr_t grub_multiboot_payload_dest;
extern grub_size_t grub_multiboot_payload_size;
#define MULTIBOOT_INITIAL_STATE { .gpr[4] = MULTIBOOT_BOOTLOADER_MAGIC, \
.jumpreg = 1 }
#define MULTIBOOT_ENTRY_REGISTER gpr[1]
#define MULTIBOOT_MBI_REGISTER gpr[5]
#define MULTIBOOT_ARCHITECTURE_CURRENT MULTIBOOT_ARCHITECTURE_MIPS32
#define MULTIBOOT_ELF32_MACHINE EM_MIPS
#define MULTIBOOT_ELF64_MACHINE EM_MIPS
#endif /* ! GRUB_MULTIBOOT_CPU_HEADER */

View file

@ -261,7 +261,7 @@ grub_size_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest,
grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
grub_uint32_t d, grub_uint32_t *r);
#ifdef NEED_ENABLE_EXECUTE_STACK
#if defined(NEED_ENABLE_EXECUTE_STACK) && !defined(GRUB_UTIL)
void EXPORT_FUNC(__enable_execute_stack) (void *addr);
#endif

View file

@ -20,6 +20,8 @@
#ifndef GRUB_MULTIBOOT_HEADER
#define GRUB_MULTIBOOT_HEADER 1
#include <grub/file.h>
#ifdef GRUB_USE_MULTIBOOT2
#include <multiboot2.h>
/* Same thing as far as our loader is concerned. */
@ -35,8 +37,6 @@
void grub_multiboot (int argc, char *argv[]);
void grub_module (int argc, char *argv[]);
void grub_multiboot_set_accepts_video (int val);
grub_size_t grub_multiboot_get_mbi_size (void);
grub_err_t grub_multiboot_make_mbi (void *orig, grub_uint32_t dest,
grub_off_t buf_off, grub_size_t bufsize);
@ -46,5 +46,29 @@ grub_err_t grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
int argc, char *argv[]);
void grub_multiboot_set_bootdev (void);
grub_uint32_t grub_get_multiboot_mmap_count (void);
grub_err_t grub_multiboot_set_video_mode (void);
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
#include <grub/i386/pc/vbe.h>
#define GRUB_MACHINE_HAS_VGA_TEXT 1
#else
#define GRUB_MACHINE_HAS_VGA_TEXT 0
#endif
#define GRUB_MULTIBOOT_CONSOLE_EGA_TEXT 1
#define GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER 2
grub_err_t
grub_multiboot_set_console (int console_type, int accepted_consoles,
int width, int height, int depth,
int console_required);
grub_err_t
grub_multiboot_load (grub_file_t file);
/* Load ELF32 or ELF64. */
grub_err_t
grub_multiboot_load_elf (grub_file_t file, void *buffer);
extern grub_size_t grub_multiboot_pure_size;
extern grub_size_t grub_multiboot_alloc_mbi;
#endif /* ! GRUB_MULTIBOOT_HEADER */

View file

@ -96,17 +96,17 @@ void read_handler_list (void);
void free_handler_list (void);
/* Defined in `dyncmd.c'. */
void read_command_list (void);
void read_command_list (const char *prefix);
/* Defined in `autofs.c'. */
void read_fs_list (void);
void read_fs_list (const char *prefix);
void grub_context_init (void);
void grub_context_fini (void);
void read_crypto_list (void);
void read_crypto_list (const char *prefix);
void read_terminal_list (void);
void read_terminal_list (const char *prefix);
void grub_set_more (int onoff);

View file

@ -121,6 +121,21 @@ struct grub_script_cmdfor
struct grub_script_cmd *list;
};
/* A while/until command. */
struct grub_script_cmdwhile
{
struct grub_script_cmd cmd;
/* The command list used as condition. */
struct grub_script_cmd *cond;
/* The command list executed in each loop. */
struct grub_script_cmd *list;
/* The flag to indicate this as "until" loop. */
int until;
};
/* A menu entry generate statement. */
struct grub_script_cmd_menuentry
{
@ -234,6 +249,12 @@ grub_script_create_cmdfor (struct grub_parser_param *state,
struct grub_script_arglist *words,
struct grub_script_cmd *list);
struct grub_script_cmd *
grub_script_create_cmdwhile (struct grub_parser_param *state,
struct grub_script_cmd *cond,
struct grub_script_cmd *list,
int is_an_until_loop);
struct grub_script_cmd *
grub_script_create_cmdmenu (struct grub_parser_param *state,
struct grub_script_arglist *arglist,
@ -283,6 +304,7 @@ grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd);
grub_err_t grub_script_execute_cmdblock (struct grub_script_cmd *cmd);
grub_err_t grub_script_execute_cmdif (struct grub_script_cmd *cmd);
grub_err_t grub_script_execute_cmdfor (struct grub_script_cmd *cmd);
grub_err_t grub_script_execute_cmdwhile (struct grub_script_cmd *cmd);
grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd);
/* Execute any GRUB pre-parsed command or script. */

View file

@ -181,7 +181,8 @@ typedef enum grub_video_driver_id
GRUB_VIDEO_DRIVER_NONE,
GRUB_VIDEO_DRIVER_VBE,
GRUB_VIDEO_DRIVER_EFI_UGA,
GRUB_VIDEO_DRIVER_EFI_GOP
GRUB_VIDEO_DRIVER_EFI_GOP,
GRUB_VIDEO_DRIVER_SM712
} grub_video_driver_id_t;
struct grub_video_adapter
@ -289,7 +290,7 @@ grub_err_t EXPORT_FUNC (grub_video_get_info) (struct grub_video_mode_info *mode_
sure that framebuffer address doesn't change. To ensure this abstraction
grub_video_get_info_and_fini is the only function supplying framebuffer
address. */
grub_err_t grub_video_get_info_and_fini (struct grub_video_mode_info *mode_info,
grub_err_t EXPORT_FUNC (grub_video_get_info_and_fini) (struct grub_video_mode_info *mode_info,
void **framebuffer);
enum grub_video_blit_format grub_video_get_blit_format (struct grub_video_mode_info *mode_info);
@ -297,8 +298,9 @@ enum grub_video_blit_format grub_video_get_blit_format (struct grub_video_mode_i
grub_err_t grub_video_set_palette (unsigned int start, unsigned int count,
struct grub_video_palette_data *palette_data);
grub_err_t grub_video_get_palette (unsigned int start, unsigned int count,
struct grub_video_palette_data *palette_data);
grub_err_t EXPORT_FUNC (grub_video_get_palette) (unsigned int start,
unsigned int count,
struct grub_video_palette_data *palette_data);
grub_err_t EXPORT_FUNC (grub_video_set_viewport) (unsigned int x,
unsigned int y,
@ -373,7 +375,6 @@ grub_video_check_mode_flag (unsigned int flags, unsigned int mask,
return (flag & mask) ? !! (flags & flag) : def;
}
grub_video_driver_id_t
grub_video_get_driver_id (void);
grub_video_driver_id_t EXPORT_FUNC (grub_video_get_driver_id) (void);
#endif /* ! GRUB_VIDEO_HEADER */

View file

@ -24,6 +24,7 @@
/* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 8192
#define MULTIBOOT_HEADER_ALIGN 4
/* The magic field should contain this. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002

View file

@ -23,7 +23,8 @@
#define MULTIBOOT_HEADER 1
/* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 8192
#define MULTIBOOT_SEARCH 32768
#define MULTIBOOT_HEADER_ALIGN 8
/* The magic field should contain this. */
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
@ -35,58 +36,37 @@
#define MULTIBOOT_MOD_ALIGN 0x00001000
/* Alignment of the multiboot info structure. */
#define MULTIBOOT_INFO_ALIGN 0x00000004
#define MULTIBOOT_INFO_ALIGN 0x00000008
/* Flags set in the 'flags' member of the multiboot header. */
/* Align all boot modules on i386 page (4KB) boundaries. */
#define MULTIBOOT_PAGE_ALIGN 0x00000001
#define MULTIBOOT_TAG_ALIGN 8
#define MULTIBOOT_TAG_TYPE_END 0
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
#define MULTIBOOT_TAG_TYPE_MODULE 3
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
#define MULTIBOOT_TAG_TYPE_MMAP 6
#define MULTIBOOT_TAG_TYPE_VBE 7
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
#define MULTIBOOT_TAG_TYPE_APM 10
/* Must pass memory information to OS. */
#define MULTIBOOT_MEMORY_INFO 0x00000002
#define MULTIBOOT_HEADER_TAG_END 0
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
/* Must pass video information to OS. */
#define MULTIBOOT_VIDEO_MODE 0x00000004
#define MULTIBOOT_ARCHITECTURE_I386 0
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
/* This flag indicates the use of the address fields in the header. */
#define MULTIBOOT_AOUT_KLUDGE 0x00010000
/* Flags to be set in the 'flags' member of the multiboot info structure. */
/* is there basic lower/upper memory information? */
#define MULTIBOOT_INFO_MEMORY 0x00000001
/* is there a boot device set? */
#define MULTIBOOT_INFO_BOOTDEV 0x00000002
/* is the command-line defined? */
#define MULTIBOOT_INFO_CMDLINE 0x00000004
/* are there modules to do something with? */
#define MULTIBOOT_INFO_MODS 0x00000008
/* These next two are mutually exclusive */
/* is there a symbol table loaded? */
#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
/* is there an ELF section header table? */
#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
/* is there a full memory map? */
#define MULTIBOOT_INFO_MEM_MAP 0x00000040
/* Is there drive info? */
#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
/* Is there a config table? */
#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
/* Is there a boot loader name? */
#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
/* Is there a APM table? */
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
/* Is there video information? */
#define MULTIBOOT_INFO_VBE_INFO 0x00000800
#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
#ifndef ASM_FILE
@ -100,96 +80,175 @@ struct multiboot_header
/* Must be MULTIBOOT_MAGIC - see above. */
multiboot_uint32_t magic;
/* Feature flags. */
multiboot_uint32_t flags;
/* ISA */
multiboot_uint32_t architecture;
/* Total header length. */
multiboot_uint32_t header_length;
/* The above fields plus this one must equal 0 mod 2^32. */
multiboot_uint32_t checksum;
};
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
struct multiboot_header_tag
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
};
struct multiboot_header_tag_information_request
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t requests[0];
};
struct multiboot_header_tag_address
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t header_addr;
multiboot_uint32_t load_addr;
multiboot_uint32_t load_end_addr;
multiboot_uint32_t bss_end_addr;
multiboot_uint32_t entry_addr;
};
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
multiboot_uint32_t mode_type;
struct multiboot_header_tag_entry_address
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t entry_addr;
};
struct multiboot_header_tag_console_flags
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t console_flags;
};
struct multiboot_header_tag_framebuffer
{
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t width;
multiboot_uint32_t height;
multiboot_uint32_t depth;
};
/* The symbol table for a.out. */
struct multiboot_aout_symbol_table
struct multiboot_header_tag_module_align
{
multiboot_uint32_t tabsize;
multiboot_uint32_t strsize;
multiboot_uint32_t addr;
multiboot_uint32_t reserved;
};
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
/* The section header table for ELF. */
struct multiboot_elf_section_header_table
{
multiboot_uint32_t num;
multiboot_uint16_t type;
multiboot_uint16_t flags;
multiboot_uint32_t size;
multiboot_uint32_t addr;
multiboot_uint32_t shndx;
multiboot_uint32_t width;
multiboot_uint32_t height;
multiboot_uint32_t depth;
};
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
struct multiboot_info
struct multiboot_color
{
/* Multiboot info version number */
multiboot_uint32_t flags;
multiboot_uint8_t red;
multiboot_uint8_t green;
multiboot_uint8_t blue;
};
/* Available memory from BIOS */
struct multiboot_mmap_entry
{
multiboot_uint64_t addr;
multiboot_uint64_t len;
#define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4
multiboot_uint32_t type;
multiboot_uint32_t zero;
} __attribute__((packed));
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
struct multiboot_tag
{
multiboot_uint32_t type;
multiboot_uint32_t size;
};
struct multiboot_tag_string
{
multiboot_uint32_t type;
multiboot_uint32_t size;
char string[0];
};
struct multiboot_tag_module
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end;
char cmdline[0];
};
struct multiboot_tag_basic_meminfo
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t mem_lower;
multiboot_uint32_t mem_upper;
};
/* "root" partition */
multiboot_uint32_t boot_device;
struct multiboot_tag_bootdev
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t biosdev;
multiboot_uint32_t slice;
multiboot_uint32_t part;
};
/* Kernel command line */
multiboot_uint32_t cmdline;
struct multiboot_tag_mmap
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint32_t entry_size;
multiboot_uint32_t entry_version;
struct multiboot_mmap_entry entries[0];
};
/* Boot-Module list */
multiboot_uint32_t mods_count;
multiboot_uint32_t mods_addr;
struct multiboot_vbe_info_block
{
multiboot_uint8_t external_specification[512];
};
union
{
multiboot_aout_symbol_table_t aout_sym;
multiboot_elf_section_header_table_t elf_sec;
} u;
struct multiboot_vbe_mode_info_block
{
multiboot_uint8_t external_specification[256];
};
/* Memory Mapping buffer */
multiboot_uint32_t mmap_length;
multiboot_uint32_t mmap_addr;
struct multiboot_tag_vbe
{
multiboot_uint32_t type;
multiboot_uint32_t size;
/* Drive Info buffer */
multiboot_uint32_t drives_length;
multiboot_uint32_t drives_addr;
/* ROM configuration table */
multiboot_uint32_t config_table;
/* Boot Loader Name */
multiboot_uint32_t boot_loader_name;
/* APM table */
multiboot_uint32_t apm_table;
/* Video */
multiboot_uint32_t vbe_control_info;
multiboot_uint32_t vbe_mode_info;
multiboot_uint16_t vbe_mode;
multiboot_uint16_t vbe_interface_seg;
multiboot_uint16_t vbe_interface_off;
multiboot_uint16_t vbe_interface_len;
struct multiboot_vbe_info_block vbe_control_info;
struct multiboot_vbe_mode_info_block vbe_mode_info;
};
struct multiboot_tag_framebuffer_common
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint64_t framebuffer_addr;
multiboot_uint32_t framebuffer_pitch;
multiboot_uint32_t framebuffer_width;
@ -199,12 +258,19 @@ struct multiboot_info
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
multiboot_uint8_t framebuffer_type;
multiboot_uint16_t reserved;
};
struct multiboot_tag_framebuffer
{
struct multiboot_tag_framebuffer_common common;
union
{
struct
{
multiboot_uint32_t framebuffer_palette_addr;
multiboot_uint16_t framebuffer_palette_num_colors;
struct multiboot_color framebuffer_palette[0];
};
struct
{
@ -217,41 +283,31 @@ struct multiboot_info
};
};
};
typedef struct multiboot_info multiboot_info_t;
struct multiboot_color
struct multiboot_tag_elf_sections
{
multiboot_uint8_t red;
multiboot_uint8_t green;
multiboot_uint8_t blue;
};
struct multiboot_mmap_entry
{
multiboot_uint32_t size;
multiboot_uint64_t addr;
multiboot_uint64_t len;
#define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4
multiboot_uint32_t type;
} __attribute__((packed));
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
struct multiboot_mod_list
{
/* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end;
/* Module command line */
multiboot_uint32_t cmdline;
/* padding to take it to 16 bytes (must be zero) */
multiboot_uint32_t pad;
multiboot_uint32_t size;
multiboot_uint32_t num;
multiboot_uint32_t entsize;
multiboot_uint32_t shndx;
char sections[0];
};
struct multiboot_tag_apm
{
multiboot_uint32_t type;
multiboot_uint32_t size;
multiboot_uint16_t version;
multiboot_uint16_t cseg;
multiboot_uint32_t offset;
multiboot_uint16_t cseg_16;
multiboot_uint16_t dseg;
multiboot_uint16_t flags;
multiboot_uint16_t cseg_len;
multiboot_uint16_t cseg_16_len;
multiboot_uint16_t dseg_len;
};
typedef struct multiboot_mod_list multiboot_module_t;
#endif /* ! ASM_FILE */

View file

@ -98,7 +98,10 @@ grub_device_iterate (int (*hook) (const char *name))
dev = grub_device_open (disk_name);
if (! dev)
return 0;
{
grub_errno = GRUB_ERR_NONE;
return 0;
}
if (dev->disk && dev->disk->has_partitions)
{

View file

@ -53,7 +53,7 @@
#include <multiboot.h>
#include <multiboot2.h>
#define ABS(x) ((x) - _start + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
.file "startup.S"
@ -66,16 +66,15 @@
.globl start, _start
start:
_start:
LOCAL (base):
/*
* Guarantee that "main" is loaded at 0x0:0x8200.
*/
#ifdef APPLE_CC
codestart_abs = ABS(codestart) - 0x10000
ljmp $0, $(codestart_abs)
#ifdef __APPLE__
ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000)
#else
ljmp $0, $ABS(codestart)
ljmp $0, $ABS(LOCAL (codestart))
#endif
/*
* Compatibility version number
*
@ -183,7 +182,7 @@ multiboot_trampoline:
.code16
/* the real mode code continues... */
codestart:
LOCAL (codestart):
cli /* we're not safe here! */
/* set up %ds, %ss, and %es */
@ -1156,7 +1155,7 @@ FUNCTION(grub_console_real_putchar)
*/
/* this table is used in translate_keycode below */
translation_table:
LOCAL (translation_table):
.word GRUB_CONSOLE_KEY_LEFT, GRUB_TERM_LEFT
.word GRUB_CONSOLE_KEY_RIGHT, GRUB_TERM_RIGHT
.word GRUB_CONSOLE_KEY_UP, GRUB_TERM_UP
@ -1178,11 +1177,10 @@ translate_keycode:
pushw %bx
pushw %si
#ifdef APPLE_CC
translation_table_abs = ABS (translation_table) - 0x10000
movw $(translation_table_abs), %si
#ifdef __APPLE__
movw $(ABS(LOCAL (translation_table)) - 0x10000), %si
#else
movw $ABS(translation_table), %si
movw $ABS(LOCAL (translation_table)), %si
#endif
1: lodsw
@ -1446,47 +1444,6 @@ FUNCTION(grub_console_setcursor)
popl %ebp
ret
/*
* grub_getrtsecs()
* if a seconds value can be read, read it and return it (BCD),
* otherwise return 0xFF
* BIOS call "INT 1AH Function 02H" to check whether a character is pending
* Call with %ah = 0x2
* Return:
* If RT Clock can give correct values
* %ch = hour (BCD)
* %cl = minutes (BCD)
* %dh = seconds (BCD)
* %dl = daylight savings time (00h std, 01h daylight)
* Carry flag = clear
* else
* Carry flag = set
* (this indicates that the clock is updating, or
* that it isn't running)
*/
FUNCTION(grub_getrtsecs)
pushl %ebp
call prot_to_real /* enter real mode */
.code16
clc
movb $0x2, %ah
int $0x1a
DATA32 jnc gottime
movb $0xff, %dh
gottime:
DATA32 call real_to_prot
.code32
movb %dh, %al
popl %ebp
ret
/*
* grub_get_rtc()
* return the real time in ticks, of which there are about
@ -1541,33 +1498,6 @@ FUNCTION(grub_vga_set_mode)
popl %ebp
ret
/*
* unsigned char *grub_vga_get_font (void)
*/
FUNCTION(grub_vga_get_font)
pushl %ebp
pushl %ebx
call prot_to_real
.code16
movw $0x1130, %ax
movb $0x06, %bh
int $0x10
movw %es, %bx
movw %bp, %dx
DATA32 call real_to_prot
.code32
movzwl %bx, %ecx
shll $4, %ecx
movw %dx, %ax
addl %ecx, %eax
popl %ebx
popl %ebp
ret
/*
* grub_vbe_bios_status_t grub_vbe_get_controller_info (struct grub_vbe_info_block *controller_info)
*

View file

@ -73,10 +73,16 @@ grub_children_iterate (char *devpath,
IEEE1275_MAX_PROP_LEN, &actual))
childtype[0] = 0;
if (dev == child)
continue;
if (grub_ieee1275_package_to_path (child, childpath,
IEEE1275_MAX_PATH_LEN, &actual))
continue;
if (grub_strcmp (devpath, childpath) == 0)
continue;
if (grub_ieee1275_get_property (child, "name", childname,
IEEE1275_MAX_PROP_LEN, &actual))
continue;

View file

@ -1058,7 +1058,7 @@ grub_abort (void)
void abort (void) __attribute__ ((alias ("grub_abort")));
#endif
#ifdef NEED_ENABLE_EXECUTE_STACK
#if defined(NEED_ENABLE_EXECUTE_STACK) && !defined(GRUB_UTIL)
/* Some gcc versions generate a call to this function
in trampolines for nested functions. */
void __enable_execute_stack (void *addr __attribute__ ((unused)))

33
lib/posix_wrap/assert.h Normal file
View file

@ -0,0 +1,33 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009, 2010 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_POSIX_ASSERT_H
#define GRUB_POSIX_ASSERT_H 1
#include <grub/misc.h>
#define assert(x) assert_real(__FILE__, __LINE__, x)
static inline void
assert_real (const char *file, int line, int cond)
{
if (!cond)
grub_fatal ("Assertion failed at %s:%d\n", file, line);
}
#endif

103
lib/posix_wrap/ctype.h Normal file
View file

@ -0,0 +1,103 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009, 2010 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_POSIX_CTYPE_H
#define GRUB_POSIX_CTYPE_H 1
#include <grub/misc.h>
static inline int
toupper (int c)
{
return grub_toupper (c);
}
static inline int
isspace (int c)
{
return grub_isspace (c);
}
static inline int
isdigit (int c)
{
return grub_isdigit (c);
}
static inline int
islower (int c)
{
return (c >= 'a' && c <= 'z');
}
static inline int
isupper (int c)
{
return (c >= 'A' && c <= 'Z');
}
static inline int
isxdigit (int c)
{
return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')
|| (c >= '0' && c <= '9');
}
static inline int
isprint (int c)
{
return grub_isprint (c);
}
static inline int
iscntrl (int c)
{
return !grub_isprint (c);
}
static inline int
isgraph (int c)
{
return grub_isprint (c) && !grub_isspace (c);
}
static inline int
isalnum (int c)
{
return grub_isalpha (c) || grub_isdigit (c);
}
static inline int
ispunct (int c)
{
return grub_isprint (c) && !grub_isspace (c) && !isalnum (c);
}
static inline int
isalpha (int c)
{
return grub_isalpha (c);
}
static inline int
tolower (int c)
{
return grub_tolower (c);
}
#endif

28
lib/posix_wrap/errno.h Normal file
View file

@ -0,0 +1,28 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009, 2010 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_POSIX_ERRNO_H
#define GRUB_POSIX_ERRNO_H 1
#include <grub/err.h>
#define errno grub_errno
#define EINVAL GRUB_ERR_BAD_NUMBER
#define ENOMEM GRUB_ERR_OUT_OF_MEMORY
#endif

38
lib/posix_wrap/langinfo.h Normal file
View file

@ -0,0 +1,38 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009, 2010 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_POSIX_LANGINFO_H
#define GRUB_POSIX_LANGINFO_H 1
#include <localcharset.h>
typedef enum { CODESET } nl_item;
static inline char *
nl_langinfo (nl_item item)
{
switch (item)
{
case CODESET:
return locale_charset ();
default:
return "";
}
}
#endif

0
lib/posix_wrap/limits.h Normal file
View file

View file

@ -0,0 +1,28 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009, 2010 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_POSIX_LOCALCHARSET_H
#define GRUB_POSIX_LOCALCHARSET_H 1
static inline char *
locale_charset (void)
{
return "UTF-8";
}
#endif

1
lib/posix_wrap/stdint.h Normal file
View file

@ -0,0 +1 @@
#include <sys/types.h>

29
lib/posix_wrap/stdio.h Normal file
View file

@ -0,0 +1,29 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009, 2010 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_POSIX_STDIO_H
#define GRUB_POSIX_STDIO_H 1
#include <grub/misc.h>
#include <grub/file.h>
typedef struct grub_file FILE;
#define EOF -1
#endif

56
lib/posix_wrap/stdlib.h Normal file
View file

@ -0,0 +1,56 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009, 2010 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_POSIX_STDLIB_H
#define GRUB_POSIX_STDLIB_H 1
#include <grub/mm.h>
static inline void
free (void *ptr)
{
grub_free (ptr);
}
static inline void *
malloc (grub_size_t size)
{
return grub_malloc (size);
}
static inline void *
calloc (grub_size_t size, grub_size_t nelem)
{
return grub_zalloc (size * nelem);
}
static inline void *
realloc (void *ptr, grub_size_t size)
{
return grub_realloc (ptr, size);
}
static inline void
abort (void)
{
grub_abort ();
}
#define MB_CUR_MAX 6
#endif

40
lib/posix_wrap/string.h Normal file
View file

@ -0,0 +1,40 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009, 2010 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_POSIX_STRING_H
#define GRUB_POSIX_STRING_H 1
static inline grub_size_t
strlen (const char *s)
{
return grub_strlen (s);
}
static inline int
strcmp (const char *s1, const char *s2)
{
return grub_strcmp (s1, s2);
}
static inline int
strcasecmp (const char *s1, const char *s2)
{
return grub_strcasecmp (s1, s2);
}
#endif

View file

@ -0,0 +1,32 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009, 2010 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_POSIX_SYS_TYPES_H
#define GRUB_POSIX_SYS_TYPES_H 1
#include <grub/misc.h>
typedef grub_size_t size_t;
typedef int bool;
static const bool true = 1;
static const bool false = 0;
#define ULONG_MAX GRUB_ULONG_MAX
#define UCHAR_MAX 0xff
#endif

0
lib/posix_wrap/unistd.h Normal file
View file

25
lib/posix_wrap/wchar.h Normal file
View file

@ -0,0 +1,25 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009, 2010 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_POSIX_WCHAR_H
#define GRUB_POSIX_WCHAR_H 1
/* UCS-4. */
typedef grub_uint32_t wchar_t;
#endif

0
lib/posix_wrap/wctype.h Normal file
View file

View file

@ -1,334 +0,0 @@
/* multiboot.c - boot a multiboot OS image. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 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/>.
*/
/*
* FIXME: The following features from the Multiboot specification still
* need to be implemented:
* - VBE support
* - symbol table
* - drives table
* - ROM configuration table
* - APM table
*/
/* The bits in the required part of flags field we don't support. */
#define UNSUPPORTED_FLAGS 0x0000fff8
#include <grub/loader.h>
#include <grub/machine/loader.h>
#include <grub/multiboot.h>
#include <grub/cpu/multiboot.h>
#include <grub/elf.h>
#include <grub/aout.h>
#include <grub/file.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/env.h>
#include <grub/i386/relocator.h>
#include <grub/video.h>
#ifdef GRUB_MACHINE_EFI
#include <grub/efi/efi.h>
#endif
extern grub_dl_t my_mod;
static grub_size_t code_size, alloc_mbi;
char *grub_multiboot_payload_orig;
grub_addr_t grub_multiboot_payload_dest;
grub_size_t grub_multiboot_pure_size;
grub_uint32_t grub_multiboot_payload_eip;
static grub_err_t
grub_multiboot_boot (void)
{
grub_size_t mbi_size;
grub_err_t err;
struct grub_relocator32_state state =
{
.eax = MULTIBOOT_BOOTLOADER_MAGIC,
.ecx = 0,
.edx = 0,
.eip = grub_multiboot_payload_eip,
/* Set esp to some random location in low memory to avoid breaking
non-compliant kernels. */
.esp = 0x7ff00
};
mbi_size = grub_multiboot_get_mbi_size ();
if (alloc_mbi < mbi_size)
{
grub_multiboot_payload_orig
= grub_relocator32_realloc (grub_multiboot_payload_orig,
grub_multiboot_pure_size + mbi_size);
if (!grub_multiboot_payload_orig)
return grub_errno;
alloc_mbi = mbi_size;
}
state.ebx = grub_multiboot_payload_dest + grub_multiboot_pure_size;
err = grub_multiboot_make_mbi (grub_multiboot_payload_orig,
grub_multiboot_payload_dest,
grub_multiboot_pure_size, mbi_size);
if (err)
return err;
#ifdef GRUB_MACHINE_EFI
if (! grub_efi_finish_boot_services ())
grub_fatal ("cannot exit boot services");
#endif
grub_relocator32_boot (grub_multiboot_payload_orig,
grub_multiboot_payload_dest,
state);
/* Not reached. */
return GRUB_ERR_NONE;
}
static grub_err_t
grub_multiboot_unload (void)
{
grub_multiboot_free_mbi ();
grub_relocator32_free (grub_multiboot_payload_orig);
alloc_mbi = 0;
grub_multiboot_payload_orig = NULL;
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
#define MULTIBOOT_LOAD_ELF64
#include "multiboot_elfxx.c"
#undef MULTIBOOT_LOAD_ELF64
#define MULTIBOOT_LOAD_ELF32
#include "multiboot_elfxx.c"
#undef MULTIBOOT_LOAD_ELF32
/* Load ELF32 or ELF64. */
static grub_err_t
grub_multiboot_load_elf (grub_file_t file, void *buffer)
{
if (grub_multiboot_is_elf32 (buffer))
return grub_multiboot_load_elf32 (file, buffer);
else if (grub_multiboot_is_elf64 (buffer))
return grub_multiboot_load_elf64 (file, buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
}
void
grub_multiboot (int argc, char *argv[])
{
grub_file_t file = 0;
char buffer[MULTIBOOT_SEARCH];
struct multiboot_header *header;
grub_ssize_t len;
grub_loader_unset ();
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
goto fail;
}
file = grub_gzfile_open (argv[0], 1);
if (! file)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
goto fail;
}
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
{
grub_error (GRUB_ERR_BAD_OS, "file too small");
goto fail;
}
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + 4))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->flags + header->checksum))
break;
}
if (header == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
goto fail;
}
if (header->flags & UNSUPPORTED_FLAGS)
{
grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported flag: 0x%x", header->flags);
goto fail;
}
grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_payload_orig = NULL;
/* Skip filename. */
grub_multiboot_init_mbi (argc - 1, argv + 1);
if (header->flags & MULTIBOOT_AOUT_KLUDGE)
{
int offset = ((char *) header - buffer -
(header->header_addr - header->load_addr));
int load_size = ((header->load_end_addr == 0) ? file->size - offset :
header->load_end_addr - header->load_addr);
if (header->bss_end_addr)
code_size = (header->bss_end_addr - header->load_addr);
else
code_size = load_size;
grub_multiboot_payload_dest = header->load_addr;
grub_multiboot_pure_size += code_size;
/* Allocate a bit more to avoid relocations in most cases. */
alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + alloc_mbi);
if (! grub_multiboot_payload_orig)
goto fail;
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
goto fail;
grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
if (grub_errno)
goto fail;
if (header->bss_end_addr)
grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
header->bss_end_addr - header->load_addr - load_size);
grub_multiboot_payload_eip = header->entry_addr;
}
else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE)
goto fail;
if (header->flags & MULTIBOOT_VIDEO_MODE)
{
switch (header->mode_type)
{
case 1:
grub_env_set ("gfxpayload", "text");
break;
case 0:
{
char *buf;
if (header->depth && header->width && header->height)
buf = grub_xasprintf ("%dx%dx%d,%dx%d,auto", header->width,
header->height, header->depth, header->width,
header->height);
else if (header->width && header->height)
buf = grub_xasprintf ("%dx%d,auto", header->width, header->height);
else
buf = grub_strdup ("auto");
if (!buf)
goto fail;
grub_env_set ("gfxpayload", buf);
grub_free (buf);
break;
}
}
}
grub_multiboot_set_accepts_video (!!(header->flags & MULTIBOOT_VIDEO_MODE));
grub_multiboot_set_bootdev ();
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
fail:
if (file)
grub_file_close (file);
if (grub_errno != GRUB_ERR_NONE)
{
grub_relocator32_free (grub_multiboot_payload_orig);
grub_dl_unref (my_mod);
}
}
void
grub_module (int argc, char *argv[])
{
grub_file_t file = 0;
grub_ssize_t size;
char *module = 0;
grub_err_t err;
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
goto fail;
}
if (!grub_multiboot_payload_orig)
{
grub_error (GRUB_ERR_BAD_ARGUMENT,
"you need to load the multiboot kernel first");
goto fail;
}
file = grub_gzfile_open (argv[0], 1);
if (! file)
goto fail;
size = grub_file_size (file);
module = grub_memalign (MULTIBOOT_MOD_ALIGN, size);
if (! module)
goto fail;
err = grub_multiboot_add_module ((grub_addr_t) module, size,
argc - 1, argv + 1);
if (err)
goto fail;
if (grub_file_read (file, module, size) != size)
{
grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file");
goto fail;
}
fail:
if (file)
grub_file_close (file);
}

View file

@ -23,6 +23,7 @@
#endif
#include <grub/multiboot.h>
#include <grub/cpu/multiboot.h>
#include <grub/cpu/relocator.h>
#include <grub/disk.h>
#include <grub/device.h>
#include <grub/partition.h>
@ -30,15 +31,10 @@
#include <grub/misc.h>
#include <grub/env.h>
#include <grub/video.h>
#include <grub/file.h>
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
#include <grub/i386/pc/vbe.h>
#define DEFAULT_VIDEO_MODE "text"
#define HAS_VGA_TEXT 1
#else
#define DEFAULT_VIDEO_MODE "auto"
#define HAS_VGA_TEXT 0
#endif
/* The bits in the required part of flags field we don't support. */
#define UNSUPPORTED_FLAGS 0x0000fff8
struct module
{
@ -56,33 +52,136 @@ static unsigned modcnt;
static char *cmdline = NULL;
static grub_uint32_t bootdev;
static int bootdev_set;
static int accepts_video;
void
grub_multiboot_set_accepts_video (int val)
grub_err_t
grub_multiboot_load (grub_file_t file)
{
accepts_video = val;
}
char *buffer;
grub_ssize_t len;
struct multiboot_header *header;
grub_err_t err;
/* Return the length of the Multiboot mmap that will be needed to allocate
our platform's map. */
static grub_uint32_t
grub_get_multiboot_mmap_len (void)
{
grub_size_t count = 0;
buffer = grub_malloc (MULTIBOOT_SEARCH);
if (!buffer)
return grub_errno;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)),
grub_uint64_t size __attribute__ ((unused)),
grub_uint32_t type __attribute__ ((unused)))
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
{
count++;
return 0;
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_OS, "file too small");
}
grub_mmap_iterate (hook);
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->flags + header->checksum))
break;
}
return count * sizeof (struct multiboot_mmap_entry);
if (header == 0)
{
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
}
if (header->flags & UNSUPPORTED_FLAGS)
{
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported flag: 0x%x", header->flags);
}
if (header->flags & MULTIBOOT_AOUT_KLUDGE)
{
int offset = ((char *) header - buffer -
(header->header_addr - header->load_addr));
int load_size = ((header->load_end_addr == 0) ? file->size - offset :
header->load_end_addr - header->load_addr);
grub_size_t code_size;
if (header->bss_end_addr)
code_size = (header->bss_end_addr - header->load_addr);
else
code_size = load_size;
grub_multiboot_payload_dest = header->load_addr;
grub_multiboot_pure_size += code_size;
/* Allocate a bit more to avoid relocations in most cases. */
grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
if (! grub_multiboot_payload_orig)
{
grub_free (buffer);
return grub_errno;
}
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
{
grub_free (buffer);
return grub_errno;
}
grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
if (grub_errno)
{
grub_free (buffer);
return grub_errno;
}
if (header->bss_end_addr)
grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
header->bss_end_addr - header->load_addr - load_size);
grub_multiboot_payload_eip = header->entry_addr;
}
else
{
err = grub_multiboot_load_elf (file, buffer);
if (err)
{
grub_free (buffer);
return err;
}
}
if (header->flags & MULTIBOOT_VIDEO_MODE)
{
switch (header->mode_type)
{
case 1:
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
| GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
0, 0, 0, 0);
break;
case 0:
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
GRUB_MULTIBOOT_CONSOLE_EGA_TEXT
| GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
header->width, header->height,
header->depth, 0);
break;
default:
err = grub_error (GRUB_ERR_BAD_OS,
"unsupported graphical mode type %d",
header->mode_type);
break;
}
}
else
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
0, 0, 0, 0);
return err;
}
grub_size_t
@ -90,7 +189,8 @@ grub_multiboot_get_mbi_size (void)
{
return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4)
+ modcnt * sizeof (struct multiboot_mod_list) + total_modcmd
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len ()
+ ALIGN_UP (sizeof(PACKAGE_STRING), 4)
+ grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)
+ 256 * sizeof (struct multiboot_color);
}
@ -136,33 +236,6 @@ grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry)
grub_mmap_iterate (hook);
}
static grub_err_t
set_video_mode (void)
{
grub_err_t err;
const char *modevar;
if (accepts_video || !HAS_VGA_TEXT)
{
modevar = grub_env_get ("gfxpayload");
if (! modevar || *modevar == 0)
err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
else
{
char *tmp;
tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
if (! tmp)
return grub_errno;
err = grub_video_set_mode (tmp, 0, 0);
grub_free (tmp);
}
}
else
err = grub_video_set_mode ("text", 0, 0);
return err;
}
static grub_err_t
retrieve_video_parameters (struct multiboot_info *mbi,
grub_uint8_t *ptrorig, grub_uint32_t ptrdest)
@ -173,7 +246,7 @@ retrieve_video_parameters (struct multiboot_info *mbi,
grub_video_driver_id_t driv_id;
struct grub_video_palette_data palette[256];
err = set_video_mode ();
err = grub_multiboot_set_video_mode ();
if (err)
{
grub_print_error ();
@ -293,7 +366,8 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off,
mbi->mods_count = 0;
}
mmap_size = grub_get_multiboot_mmap_len ();
mmap_size = grub_get_multiboot_mmap_count ()
* sizeof (struct multiboot_mmap_entry);
grub_fill_multiboot_mmap ((struct multiboot_mmap_entry *) ptrorig);
mbi->mmap_length = mmap_size;
mbi->mmap_addr = ptrdest;
@ -444,6 +518,9 @@ grub_multiboot_set_bootdev (void)
biosdev = 0xffffffff;
#endif
if (biosdev == 0xffffffff)
return;
dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->partition)
{

354
loader/multiboot.c Normal file
View file

@ -0,0 +1,354 @@
/* multiboot.c - boot a multiboot OS image. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 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/>.
*/
/*
* FIXME: The following features from the Multiboot specification still
* need to be implemented:
* - VBE support
* - symbol table
* - drives table
* - ROM configuration table
* - APM table
*/
#include <grub/loader.h>
#include <grub/command.h>
#include <grub/machine/loader.h>
#include <grub/multiboot.h>
#include <grub/cpu/multiboot.h>
#include <grub/elf.h>
#include <grub/aout.h>
#include <grub/file.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/env.h>
#include <grub/cpu/relocator.h>
#include <grub/video.h>
#include <grub/memory.h>
#include <grub/i18n.h>
#ifdef GRUB_MACHINE_EFI
#include <grub/efi/efi.h>
#endif
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
#define DEFAULT_VIDEO_MODE "text"
#else
#define DEFAULT_VIDEO_MODE "auto"
#endif
grub_size_t grub_multiboot_alloc_mbi;
char *grub_multiboot_payload_orig;
grub_addr_t grub_multiboot_payload_dest;
grub_size_t grub_multiboot_pure_size;
grub_uint32_t grub_multiboot_payload_eip;
static int accepts_video;
static int accepts_ega_text;
static int console_required;
static grub_dl_t my_mod;
/* Return the length of the Multiboot mmap that will be needed to allocate
our platform's map. */
grub_uint32_t
grub_get_multiboot_mmap_count (void)
{
grub_size_t count = 0;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)),
grub_uint64_t size __attribute__ ((unused)),
grub_uint32_t type __attribute__ ((unused)))
{
count++;
return 0;
}
grub_mmap_iterate (hook);
return count;
}
grub_err_t
grub_multiboot_set_video_mode (void)
{
grub_err_t err;
const char *modevar;
if (accepts_video || !GRUB_MACHINE_HAS_VGA_TEXT)
{
modevar = grub_env_get ("gfxpayload");
if (! modevar || *modevar == 0)
err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
else
{
char *tmp;
tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
if (! tmp)
return grub_errno;
err = grub_video_set_mode (tmp, 0, 0);
grub_free (tmp);
}
}
else
err = grub_video_set_mode ("text", 0, 0);
return err;
}
static grub_err_t
grub_multiboot_boot (void)
{
grub_size_t mbi_size;
grub_err_t err;
struct grub_relocator32_state state = MULTIBOOT_INITIAL_STATE;
state.MULTIBOOT_ENTRY_REGISTER = grub_multiboot_payload_eip;
mbi_size = grub_multiboot_get_mbi_size ();
if (grub_multiboot_alloc_mbi < mbi_size)
{
grub_multiboot_payload_orig
= grub_relocator32_realloc (grub_multiboot_payload_orig,
grub_multiboot_pure_size + mbi_size);
if (!grub_multiboot_payload_orig)
return grub_errno;
grub_multiboot_alloc_mbi = mbi_size;
}
state.MULTIBOOT_MBI_REGISTER = grub_multiboot_payload_dest
+ grub_multiboot_pure_size;
err = grub_multiboot_make_mbi (grub_multiboot_payload_orig,
grub_multiboot_payload_dest,
grub_multiboot_pure_size, mbi_size);
if (err)
return err;
#ifdef GRUB_MACHINE_EFI
if (! grub_efi_finish_boot_services ())
grub_fatal ("cannot exit boot services");
#endif
grub_relocator32_boot (grub_multiboot_payload_orig,
grub_multiboot_payload_dest,
state);
/* Not reached. */
return GRUB_ERR_NONE;
}
static grub_err_t
grub_multiboot_unload (void)
{
grub_multiboot_free_mbi ();
grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_alloc_mbi = 0;
grub_multiboot_payload_orig = NULL;
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
#define MULTIBOOT_LOAD_ELF64
#include "multiboot_elfxx.c"
#undef MULTIBOOT_LOAD_ELF64
#define MULTIBOOT_LOAD_ELF32
#include "multiboot_elfxx.c"
#undef MULTIBOOT_LOAD_ELF32
/* Load ELF32 or ELF64. */
grub_err_t
grub_multiboot_load_elf (grub_file_t file, void *buffer)
{
if (grub_multiboot_is_elf32 (buffer))
return grub_multiboot_load_elf32 (file, buffer);
else if (grub_multiboot_is_elf64 (buffer))
return grub_multiboot_load_elf64 (file, buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class");
}
grub_err_t
grub_multiboot_set_console (int console_type, int accepted_consoles,
int width, int height, int depth,
int console_req)
{
console_required = console_req;
if (!(accepted_consoles
& (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER
| (GRUB_MACHINE_HAS_VGA_TEXT ? GRUB_MULTIBOOT_CONSOLE_EGA_TEXT : 0))))
{
if (console_required)
return grub_error (GRUB_ERR_BAD_OS,
"OS requires a console but none is available");
grub_printf ("WARNING: no console will be available to OS");
accepts_video = 0;
accepts_ega_text = 0;
return GRUB_ERR_NONE;
}
if (console_type == GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER)
{
char *buf;
if (depth && width && height)
buf = grub_xasprintf ("%dx%dx%d,%dx%d,auto", width,
height, depth, width, height);
else if (width && height)
buf = grub_xasprintf ("%dx%d,auto", width, height);
else
buf = grub_strdup ("auto");
if (!buf)
return grub_errno;
grub_env_set ("gfxpayload", buf);
grub_free (buf);
}
else
grub_env_set ("gfxpayload", "text");
accepts_video = !!(accepted_consoles & GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER);
accepts_ega_text = !!(accepted_consoles & GRUB_MULTIBOOT_CONSOLE_EGA_TEXT);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
grub_err_t err;
grub_loader_unset ();
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
file = grub_gzfile_open (argv[0], 1);
if (! file)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
grub_dl_ref (my_mod);
/* Skip filename. */
grub_multiboot_init_mbi (argc - 1, argv + 1);
grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_payload_orig = NULL;
err = grub_multiboot_load (file);
if (err)
goto fail;
grub_multiboot_set_bootdev ();
grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0);
fail:
if (file)
grub_file_close (file);
if (grub_errno != GRUB_ERR_NONE)
{
grub_relocator32_free (grub_multiboot_payload_orig);
grub_multiboot_free_mbi ();
grub_dl_unref (my_mod);
}
return grub_errno;
}
static grub_err_t
grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
grub_ssize_t size;
char *module = 0;
grub_err_t err;
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
if (!grub_multiboot_payload_orig)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"you need to load the multiboot kernel first");
file = grub_gzfile_open (argv[0], 1);
if (! file)
return grub_errno;
size = grub_file_size (file);
module = grub_memalign (MULTIBOOT_MOD_ALIGN, size);
if (! module)
{
grub_file_close (file);
return grub_errno;
}
err = grub_multiboot_add_module ((grub_addr_t) module, size,
argc - 1, argv + 1);
if (err)
{
grub_file_close (file);
return err;
}
if (grub_file_read (file, module, size) != size)
{
grub_file_close (file);
return grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file");
}
grub_file_close (file);
return GRUB_ERR_NONE;;
}
static grub_command_t cmd_multiboot, cmd_module;
GRUB_MOD_INIT(multiboot)
{
cmd_multiboot =
#ifdef GRUB_USE_MULTIBOOT2
grub_register_command ("multiboot2", grub_cmd_multiboot,
0, N_("Load a multiboot 2 kernel."));
#else
grub_register_command ("multiboot", grub_cmd_multiboot,
0, N_("Load a multiboot kernel."));
#endif
cmd_module =
grub_register_command ("module", grub_cmd_module,
0, N_("Load a multiboot module."));
my_mod = mod;
}
GRUB_MOD_FINI(multiboot)
{
grub_unregister_command (cmd_multiboot);
grub_unregister_command (cmd_module);
}

View file

@ -18,13 +18,13 @@
#if defined(MULTIBOOT_LOAD_ELF32)
# define XX 32
# define E_MACHINE EM_386
# define E_MACHINE MULTIBOOT_ELF32_MACHINE
# define ELFCLASSXX ELFCLASS32
# define Elf_Ehdr Elf32_Ehdr
# define Elf_Phdr Elf32_Phdr
#elif defined(MULTIBOOT_LOAD_ELF64)
# define XX 64
# define E_MACHINE EM_X86_64
# define E_MACHINE MULTIBOOT_ELF64_MACHINE
# define ELFCLASSXX ELFCLASS64
# define Elf_Ehdr Elf64_Ehdr
# define Elf_Phdr Elf64_Phdr
@ -53,6 +53,7 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer)
char *phdr_base;
int lowest_segment = -1, highest_segment = -1;
int i;
grub_size_t code_size;
if (ehdr->e_ident[EI_CLASS] != ELFCLASSXX)
return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class");
@ -102,9 +103,9 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer)
grub_multiboot_pure_size += code_size;
alloc_mbi = grub_multiboot_get_mbi_size ();
grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + alloc_mbi + 65536);
= grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
if (!grub_multiboot_payload_orig)
return grub_errno;

View file

@ -1,150 +0,0 @@
/* multiboot_loader.c - boot multiboot kernel image */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007,2008,2009,2010 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/multiboot.h>
#include <grub/elf.h>
#include <grub/file.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/command.h>
#include <grub/i18n.h>
grub_dl_t my_mod;
static int
find_multi_boot1_header (grub_file_t file)
{
struct multiboot_header *header;
char buffer[MULTIBOOT_SEARCH];
int found_status = 0;
grub_ssize_t len;
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
return found_status;
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + 4))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->flags + header->checksum))
{
found_status = 1;
break;
}
}
return found_status;
}
static grub_err_t
grub_cmd_multiboot_loader (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file = 0;
int header_multi_ver_found = 0;
grub_dl_ref (my_mod);
if (argc == 0)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
goto fail;
}
file = grub_gzfile_open (argv[0], 1);
if (! file)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file");
goto fail;
}
/* find which header is in the file */
if (find_multi_boot1_header (file))
header_multi_ver_found = 1;
else
{
grub_error (GRUB_ERR_BAD_OS, "multiboot header not found");
goto fail;
}
/* close file before calling functions */
if (file)
grub_file_close (file);
/* Launch multi boot with header */
grub_dprintf ("multiboot_loader",
"Launching multiboot 1 grub_multiboot() function\n");
grub_multiboot (argc, argv);
return grub_errno;
fail:
if (file)
grub_file_close (file);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_cmd_module_loader (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_dprintf("multiboot_loader",
"Launching multiboot 1 grub_module() function\n");
grub_module (argc, argv);
return grub_errno;
}
static grub_command_t cmd_multiboot, cmd_module;
GRUB_MOD_INIT(multiboot)
{
cmd_multiboot =
#ifdef GRUB_USE_MULTIBOOT2
grub_register_command ("multiboot2", grub_cmd_multiboot_loader,
0, N_("Load a multiboot 2 kernel."));
#else
grub_register_command ("multiboot", grub_cmd_multiboot_loader,
0, N_("Load a multiboot kernel."));
#endif
cmd_module =
grub_register_command ("module", grub_cmd_module_loader,
0, N_("Load a multiboot module."));
my_mod = mod;
}
GRUB_MOD_FINI(multiboot)
{
grub_unregister_command (cmd_multiboot);
grub_unregister_command (cmd_module);
}

701
loader/multiboot_mbi2.c Normal file
View file

@ -0,0 +1,701 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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/machine/memory.h>
#include <grub/memory.h>
#ifdef GRUB_MACHINE_PCBIOS
#include <grub/machine/biosnum.h>
#endif
#include <grub/multiboot.h>
#include <grub/cpu/multiboot.h>
#include <grub/cpu/relocator.h>
#include <grub/disk.h>
#include <grub/device.h>
#include <grub/partition.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/env.h>
#include <grub/video.h>
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
#include <grub/i386/pc/vbe.h>
#define HAS_VGA_TEXT 1
#else
#define HAS_VGA_TEXT 0
#endif
struct module
{
struct module *next;
grub_addr_t start;
grub_size_t size;
char *cmdline;
int cmdline_size;
};
struct module *modules, *modules_last;
static grub_size_t cmdline_size;
static grub_size_t total_modcmd;
static unsigned modcnt;
static char *cmdline = NULL;
static int bootdev_set;
static grub_uint32_t biosdev, slice, part;
grub_err_t
grub_multiboot_load (grub_file_t file)
{
char *buffer;
grub_ssize_t len;
struct multiboot_header *header;
grub_err_t err;
struct multiboot_header_tag *tag;
struct multiboot_header_tag_address *addr_tag = NULL;
int entry_specified = 0;
grub_addr_t entry = 0;
grub_uint32_t console_required = 0;
struct multiboot_header_tag_framebuffer *fbtag = NULL;
int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
buffer = grub_malloc (MULTIBOOT_SEARCH);
if (!buffer)
return grub_errno;
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
if (len < 32)
{
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_OS, "file too small");
}
/* Look for the multiboot header in the buffer. The header should
be at least 12 bytes and aligned on a 4-byte boundary. */
for (header = (struct multiboot_header *) buffer;
((char *) header <= buffer + len - 12) || (header = 0);
header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
{
if (header->magic == MULTIBOOT_HEADER_MAGIC
&& !(header->magic + header->architecture
+ header->header_length + header->checksum)
&& header->architecture == MULTIBOOT_ARCHITECTURE_CURRENT)
break;
}
if (header == 0)
{
grub_free (buffer);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
}
for (tag = (struct multiboot_header_tag *) (header + 1);
tag->type != MULTIBOOT_TAG_TYPE_END;
tag = (struct multiboot_header_tag *) ((char *) tag + tag->size))
switch (tag->type)
{
case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST:
{
unsigned i;
struct multiboot_header_tag_information_request *request_tag
= (struct multiboot_header_tag_information_request *) tag;
if (request_tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)
break;
for (i = 0; i < (request_tag->size - sizeof (request_tag))
/ sizeof (request_tag->requests[0]); i++)
switch (request_tag->requests[i])
{
case MULTIBOOT_TAG_TYPE_END:
case MULTIBOOT_TAG_TYPE_CMDLINE:
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
case MULTIBOOT_TAG_TYPE_MODULE:
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
case MULTIBOOT_TAG_TYPE_BOOTDEV:
case MULTIBOOT_TAG_TYPE_MMAP:
case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
break;
case MULTIBOOT_TAG_TYPE_VBE:
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
case MULTIBOOT_TAG_TYPE_APM:
default:
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported information tag: 0x%x",
request_tag->requests[i]);
}
break;
}
case MULTIBOOT_HEADER_TAG_ADDRESS:
addr_tag = (struct multiboot_header_tag_address *) tag;
break;
case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS:
entry_specified = 1;
entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
break;
case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
& MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
accepted_consoles &= ~GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
if (((struct multiboot_header_tag_console_flags *) tag)->console_flags
& MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED)
console_required = 1;
break;
case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
fbtag = (struct multiboot_header_tag_framebuffer *) tag;
accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER;
break;
/* GRUB always page-aligns modules. */
case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
break;
default:
if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL))
{
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported tag: 0x%x", tag->type);
}
break;
}
if (addr_tag && !entry_specified)
{
grub_free (buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS,
"load address tag without entry address tag");
}
if (addr_tag)
{
int offset = ((char *) header - buffer -
(addr_tag->header_addr - addr_tag->load_addr));
int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset :
addr_tag->load_end_addr - addr_tag->load_addr);
grub_size_t code_size;
if (addr_tag->bss_end_addr)
code_size = (addr_tag->bss_end_addr - addr_tag->load_addr);
else
code_size = load_size;
grub_multiboot_payload_dest = addr_tag->load_addr;
grub_multiboot_pure_size += code_size;
/* Allocate a bit more to avoid relocations in most cases. */
grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
grub_multiboot_payload_orig
= grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
if (! grub_multiboot_payload_orig)
{
grub_free (buffer);
return grub_errno;
}
if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
{
grub_free (buffer);
return grub_errno;
}
grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
if (grub_errno)
{
grub_free (buffer);
return grub_errno;
}
if (addr_tag->bss_end_addr)
grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
addr_tag->bss_end_addr - addr_tag->load_addr - load_size);
}
else
{
err = grub_multiboot_load_elf (file, buffer);
if (err)
{
grub_free (buffer);
return err;
}
}
if (entry_specified)
grub_multiboot_payload_eip = entry;
if (fbtag)
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
accepted_consoles,
fbtag->width, fbtag->height,
fbtag->depth, console_required);
else
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
accepted_consoles,
0, 0, 0, console_required);
return err;
}
grub_size_t
grub_multiboot_get_mbi_size (void)
{
return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag)
+ (sizeof (struct multiboot_tag_string)
+ ALIGN_UP (cmdline_size, MULTIBOOT_TAG_ALIGN))
+ (sizeof (struct multiboot_tag_string)
+ ALIGN_UP (sizeof (PACKAGE_STRING), MULTIBOOT_TAG_ALIGN))
+ (modcnt * sizeof (struct multiboot_tag_module) + total_modcmd)
+ sizeof (struct multiboot_tag_basic_meminfo)
+ ALIGN_UP (sizeof (struct multiboot_tag_bootdev), MULTIBOOT_TAG_ALIGN)
+ (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count ()
* sizeof (struct multiboot_mmap_entry))
+ sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1;
}
/* Fill previously allocated Multiboot mmap. */
static void
grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag)
{
struct multiboot_mmap_entry *mmap_entry = tag->entries;
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
{
mmap_entry->addr = addr;
mmap_entry->len = size;
switch (type)
{
case GRUB_MACHINE_MEMORY_AVAILABLE:
mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE;
break;
#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE
case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE:
mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE;
break;
#endif
#ifdef GRUB_MACHINE_MEMORY_NVS
case GRUB_MACHINE_MEMORY_NVS:
mmap_entry->type = MULTIBOOT_MEMORY_NVS;
break;
#endif
default:
mmap_entry->type = MULTIBOOT_MEMORY_RESERVED;
break;
}
mmap_entry++;
return 0;
}
tag->type = MULTIBOOT_TAG_TYPE_MMAP;
tag->size = sizeof (struct multiboot_tag_mmap)
+ sizeof (struct multiboot_mmap_entry) * grub_get_multiboot_mmap_count ();
tag->entry_size = sizeof (struct multiboot_mmap_entry);
tag->entry_version = 0;
grub_mmap_iterate (hook);
}
static grub_err_t
retrieve_video_parameters (grub_uint8_t **ptrorig)
{
grub_err_t err;
struct grub_video_mode_info mode_info;
void *framebuffer;
grub_video_driver_id_t driv_id;
struct grub_video_palette_data palette[256];
struct multiboot_tag_framebuffer *tag
= (struct multiboot_tag_framebuffer *) *ptrorig;
err = grub_multiboot_set_video_mode ();
if (err)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
driv_id = grub_video_get_driver_id ();
#if HAS_VGA_TEXT
if (driv_id == GRUB_VIDEO_DRIVER_NONE)
{
struct grub_vbe_mode_info_block vbe_mode_info;
grub_uint32_t vbe_mode;
#if defined (GRUB_MACHINE_PCBIOS)
{
grub_vbe_status_t status;
void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
status = grub_vbe_bios_get_mode (scratch);
vbe_mode = *(grub_uint32_t *) scratch;
if (status != GRUB_VBE_STATUS_OK)
return GRUB_ERR_NONE;
}
#else
vbe_mode = 3;
#endif
/* get_mode_info isn't available for mode 3. */
if (vbe_mode == 3)
{
grub_memset (&vbe_mode_info, 0,
sizeof (struct grub_vbe_mode_info_block));
vbe_mode_info.memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
vbe_mode_info.x_resolution = 80;
vbe_mode_info.y_resolution = 25;
}
#if defined (GRUB_MACHINE_PCBIOS)
else
{
grub_vbe_status_t status;
void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
status = grub_vbe_bios_get_mode_info (vbe_mode, scratch);
if (status != GRUB_VBE_STATUS_OK)
return GRUB_ERR_NONE;
grub_memcpy (&vbe_mode_info, scratch,
sizeof (struct grub_vbe_mode_info_block));
}
#endif
if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
{
tag = (struct multiboot_tag_framebuffer *) *ptrorig;
tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
tag->common.size = 0;
tag->common.framebuffer_addr = 0xb8000;
tag->common.framebuffer_pitch = 2 * vbe_mode_info.x_resolution;
tag->common.framebuffer_width = vbe_mode_info.x_resolution;
tag->common.framebuffer_height = vbe_mode_info.y_resolution;
tag->common.framebuffer_bpp = 16;
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
tag->common.size = sizeof (tag->common);
tag->common.reserved = 0;
*ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN);
}
return GRUB_ERR_NONE;
}
#else
if (driv_id == GRUB_VIDEO_DRIVER_NONE)
return GRUB_ERR_NONE;
#endif
err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
if (err)
return err;
tag = (struct multiboot_tag_framebuffer *) *ptrorig;
tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
tag->common.size = 0;
tag->common.framebuffer_addr = (grub_addr_t) framebuffer;
tag->common.framebuffer_pitch = mode_info.pitch;
tag->common.framebuffer_width = mode_info.width;
tag->common.framebuffer_height = mode_info.height;
tag->common.framebuffer_bpp = mode_info.bpp;
tag->common.reserved = 0;
if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
{
unsigned i;
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
tag->framebuffer_palette_num_colors = mode_info.number_of_colors;
if (tag->framebuffer_palette_num_colors > ARRAY_SIZE (palette))
tag->framebuffer_palette_num_colors = ARRAY_SIZE (palette);
tag->common.size = sizeof (struct multiboot_tag_framebuffer_common)
+ sizeof (multiboot_uint16_t) + tag->framebuffer_palette_num_colors
* sizeof (struct multiboot_color);
for (i = 0; i < tag->framebuffer_palette_num_colors; i++)
{
tag->framebuffer_palette[i].red = palette[i].r;
tag->framebuffer_palette[i].green = palette[i].g;
tag->framebuffer_palette[i].blue = palette[i].b;
}
}
else
{
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
tag->framebuffer_red_field_position = mode_info.green_field_pos;
tag->framebuffer_red_mask_size = mode_info.green_mask_size;
tag->framebuffer_green_field_position = mode_info.green_field_pos;
tag->framebuffer_green_mask_size = mode_info.green_mask_size;
tag->framebuffer_blue_field_position = mode_info.blue_field_pos;
tag->framebuffer_blue_mask_size = mode_info.blue_mask_size;
tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + 6;
}
*ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN);
return GRUB_ERR_NONE;
}
grub_err_t
grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off,
grub_size_t bufsize)
{
grub_uint8_t *ptrorig;
grub_uint8_t *mbistart = (grub_uint8_t *) orig + buf_off
+ (ALIGN_UP (dest + buf_off, MULTIBOOT_TAG_ALIGN) - (dest + buf_off));
grub_err_t err;
if (bufsize < grub_multiboot_get_mbi_size ())
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small");
ptrorig = mbistart + 2 * sizeof (grub_uint32_t);
{
struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_CMDLINE;
tag->size = sizeof (struct multiboot_tag_string) + cmdline_size;
grub_memcpy (tag->string, cmdline, cmdline_size);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
{
struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME;
tag->size = sizeof (struct multiboot_tag_string) + sizeof (PACKAGE_STRING);
grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING));
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
{
unsigned i;
struct module *cur;
for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
{
struct multiboot_tag_module *tag
= (struct multiboot_tag_module *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_MODULE;
tag->size = sizeof (struct multiboot_tag_module) + cur->cmdline_size;
tag->mod_start = dest + cur->start;
tag->mod_end = tag->mod_start + cur->size;
grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
}
{
struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
grub_fill_multiboot_mmap (tag);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
{
struct multiboot_tag_basic_meminfo *tag
= (struct multiboot_tag_basic_meminfo *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
tag->size = sizeof (struct multiboot_tag_basic_meminfo);
/* Convert from bytes to kilobytes. */
tag->mem_lower = grub_mmap_get_lower () / 1024;
tag->mem_upper = grub_mmap_get_upper () / 1024;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
if (bootdev_set)
{
struct multiboot_tag_bootdev *tag
= (struct multiboot_tag_bootdev *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_BOOTDEV;
tag->size = sizeof (struct multiboot_tag_bootdev);
tag->biosdev = biosdev;
tag->slice = slice;
tag->part = part;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
{
err = retrieve_video_parameters (&ptrorig);
if (err)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
}
{
struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_END;
tag->size = sizeof (struct multiboot_tag);
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
}
((grub_uint32_t *) mbistart)[0] = ptrorig - mbistart;
((grub_uint32_t *) mbistart)[1] = 0;
return GRUB_ERR_NONE;
}
void
grub_multiboot_free_mbi (void)
{
struct module *cur, *next;
cmdline_size = 0;
total_modcmd = 0;
modcnt = 0;
grub_free (cmdline);
cmdline = NULL;
bootdev_set = 0;
for (cur = modules; cur; cur = next)
{
next = cur->next;
grub_free (cur->cmdline);
grub_free (cur);
}
modules = NULL;
modules_last = NULL;
}
grub_err_t
grub_multiboot_init_mbi (int argc, char *argv[])
{
grub_ssize_t len = 0;
char *p;
int i;
grub_multiboot_free_mbi ();
for (i = 0; i < argc; i++)
len += grub_strlen (argv[i]) + 1;
if (len == 0)
len = 1;
cmdline = p = grub_malloc (len);
if (! cmdline)
return grub_errno;
cmdline_size = len;
for (i = 0; i < argc; i++)
{
p = grub_stpcpy (p, argv[i]);
*(p++) = ' ';
}
/* Remove the space after the last word. */
if (p != cmdline)
p--;
*p = '\0';
return GRUB_ERR_NONE;
}
grub_err_t
grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
int argc, char *argv[])
{
struct module *newmod;
char *p;
grub_ssize_t len = 0;
int i;
newmod = grub_malloc (sizeof (*newmod));
if (!newmod)
return grub_errno;
newmod->start = start;
newmod->size = size;
for (i = 0; i < argc; i++)
len += grub_strlen (argv[i]) + 1;
if (len == 0)
len = 1;
newmod->cmdline = p = grub_malloc (len);
if (! newmod->cmdline)
{
grub_free (newmod);
return grub_errno;
}
newmod->cmdline_size = len;
total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN);
for (i = 0; i < argc; i++)
{
p = grub_stpcpy (p, argv[i]);
*(p++) = ' ';
}
/* Remove the space after the last word. */
if (p != newmod->cmdline)
p--;
*p = '\0';
if (modules_last)
modules_last->next = newmod;
else
{
modules = newmod;
modules_last->next = NULL;
}
modules_last = newmod;
modcnt++;
return GRUB_ERR_NONE;
}
void
grub_multiboot_set_bootdev (void)
{
grub_device_t dev;
slice = ~0;
part = ~0;
#ifdef GRUB_MACHINE_PCBIOS
biosdev = grub_get_root_biosnumber ();
#else
biosdev = 0xffffffff;
#endif
if (biosdev == 0xffffffff)
return;
dev = grub_device_open (0);
if (dev && dev->disk && dev->disk->partition)
{
if (dev->disk->partition->parent)
{
part = dev->disk->partition->number;
slice = dev->disk->partition->parent->number;
}
else
slice = dev->disk->partition->number;
}
if (dev)
grub_device_close (dev);
bootdev_set = 1;
}

View file

@ -19,32 +19,27 @@
#include <grub/symbol.h>
#define DS(x) ((x) - segstart)
#define DS(x) ((x) - LOCAL (segstart))
segstart:
LOCAL (segstart):
VARIABLE(grub_machine_mmaphook_start)
.code16
VARIABLE(grub_machine_mmaphook_int12)
push %ds
push %cs
pop %ds
#ifdef APPLE_CC
grub_machine_mmaphook_kblow_rel = DS (EXT_C (grub_machine_mmaphook_kblow))
movw (grub_machine_mmaphook_kblow_rel), %ax
#else
movw DS (EXT_C (grub_machine_mmaphook_kblow)), %ax
#endif
movw DS (LOCAL (kblow)), %ax
pop %ds
iret
VARIABLE(grub_machine_mmaphook_int15)
pushf
cmpw $0xe801, %ax
jz e801
jz LOCAL (e801)
cmpw $0xe820, %ax
jz e820
jz LOCAL (e820)
cmpb $0x88, %ah
jz h88
jz LOCAL (h88)
popf
/* ljmp */
.byte 0xea
@ -53,67 +48,44 @@ VARIABLE (grub_machine_mmaphook_int15offset)
VARIABLE (grub_machine_mmaphook_int15segment)
.word 0
e801:
LOCAL (e801):
popf
push %ds
push %cs
pop %ds
#ifdef APPLE_CC
grub_machine_mmaphook_kbin16mb_rel = DS (EXT_C (grub_machine_mmaphook_kbin16mb))
grub_machine_mmaphook_64kbin4gb_rel = DS (EXT_C (grub_machine_mmaphook_64kbin4gb))
movw (grub_machine_mmaphook_kbin16mb_rel), %ax
movw (grub_machine_mmaphook_64kbin4gb_rel), %bx
#else
movw DS (EXT_C (grub_machine_mmaphook_kbin16mb)), %ax
movw DS (EXT_C (grub_machine_mmaphook_64kbin4gb)), %bx
#endif
movw DS (LOCAL (kbin16mb)), %ax
movw DS (LOCAL (m64kbin4gb)), %bx
movw %ax, %cx
movw %bx, %dx
pop %ds
clc
iret
h88:
LOCAL (h88):
popf
push %ds
push %cs
pop %ds
#ifdef APPLE_CC
movw (grub_machine_mmaphook_kbin16mb_rel), %ax
#else
movw DS (EXT_C (grub_machine_mmaphook_kbin16mb)), %ax
#endif
movw DS (LOCAL (kbin16mb)), %ax
pop %ds
clc
iret
e820:
#ifdef APPLE_CC
mmaphook_mmap_rel = DS(mmaphook_mmap)
mmaphook_mmap_num_rel = DS(EXT_C(grub_machine_mmaphook_mmap_num))
#endif
LOCAL (e820):
popf
push %ds
push %cs
pop %ds
cmpw $20, %cx
jb errexit
#ifdef APPLE_CC
cmpw (mmaphook_mmap_num_rel), %bx
#else
cmpw DS (EXT_C (grub_machine_mmaphook_mmap_num)), %bx
#endif
jae errexit
jb LOCAL (errexit)
cmpw DS (LOCAL (mmap_num)), %bx
jae LOCAL (errexit)
cmp $0x534d4150, %edx
jne errexit
jne LOCAL (errexit)
push %si
push %di
movw $20, %cx
#ifdef APPLE_CC
movl $(mmaphook_mmap_rel), %esi
#else
movw $(DS(mmaphook_mmap)), %si
#endif
movw $(DS(LOCAL (mmaphook_mmap))), %si
mov %bx, %ax
imul $20, %ax
add %ax, %si
@ -122,19 +94,15 @@ e820:
pop %si
movl $20, %ecx
inc %bx
#ifdef APPLE_CC
cmpw (mmaphook_mmap_num_rel), %bx
#else
cmpw DS(EXT_C(grub_machine_mmaphook_mmap_num)), %bx
#endif
jb noclean
cmpw DS(LOCAL (mmap_num)), %bx
jb LOCAL (noclean)
xor %bx, %bx
noclean:
LOCAL (noclean):
mov $0x534d4150, %eax
pop %ds
clc
iret
errexit:
LOCAL (errexit):
mov $0x534d4150, %eax
pop %ds
stc
@ -142,13 +110,18 @@ errexit:
iret
VARIABLE(grub_machine_mmaphook_mmap_num)
LOCAL (mmap_num):
.word 0
VARIABLE(grub_machine_mmaphook_kblow)
LOCAL (kblow):
.word 0
VARIABLE (grub_machine_mmaphook_kbin16mb)
LOCAL (kbin16mb):
.word 0
VARIABLE (grub_machine_mmaphook_64kbin4gb)
LOCAL (m64kbin4gb):
.word 0
mmaphook_mmap:
LOCAL (mmaphook_mmap):
/* Memory map is placed just after the interrupt handlers. */
VARIABLE(grub_machine_mmaphook_end)
.byte 0

View file

@ -51,11 +51,8 @@ autoload_fs_module (void)
/* Read the file fs.lst for auto-loading. */
void
read_fs_list (void)
read_fs_list (const char *prefix)
{
const char *prefix;
prefix = grub_env_get ("prefix");
if (prefix)
{
char *filename;

View file

@ -66,14 +66,12 @@ grub_crypto_spec_free (void)
/* Read the file crypto.lst for auto-loading. */
void
read_crypto_list (void)
read_crypto_list (const char *prefix)
{
const char *prefix;
char *filename;
grub_file_t file;
char *buf = NULL;
prefix = grub_env_get ("prefix");
if (!prefix)
{
grub_errno = GRUB_ERR_NONE;

View file

@ -60,11 +60,8 @@ grub_dyncmd_dispatcher (struct grub_command *cmd,
/* Read the file command.lst for auto-loading. */
void
read_command_list (void)
read_command_list (const char *prefix)
{
const char *prefix;
prefix = grub_env_get ("prefix");
if (prefix)
{
char *filename;

View file

@ -402,14 +402,20 @@ grub_normal_init_page (struct grub_term_output *term)
grub_free (unicode_msg);
}
static char *
read_lists (struct grub_env_var *var __attribute__ ((unused)),
const char *val)
static void
read_lists (const char *val)
{
read_command_list ();
read_fs_list ();
read_crypto_list ();
read_terminal_list ();
read_command_list (val);
read_fs_list (val);
read_crypto_list (val);
read_terminal_list (val);
}
static char *
read_lists_hook (struct grub_env_var *var __attribute__ ((unused)),
const char *val)
{
read_lists (val);
return val ? grub_strdup (val) : NULL;
}
@ -419,9 +425,10 @@ void
grub_normal_execute (const char *config, int nested, int batch)
{
grub_menu_t menu = 0;
const char *prefix = grub_env_get ("prefix");
read_lists (NULL, NULL);
grub_register_variable_hook ("prefix", NULL, read_lists);
read_lists (prefix);
grub_register_variable_hook ("prefix", NULL, read_lists_hook);
grub_command_execute ("parser.grub", 0, 0);
if (config)

View file

@ -176,10 +176,17 @@ print_message (int nested, int edit, struct grub_term_output *term)
if (edit)
{
grub_putcode ('\n', term);
#ifdef GRUB_MACHINE_EFI
grub_print_message_indented (_("Minimum Emacs-like screen editing is \
supported. TAB lists completions. Press F1 to boot, F2=Ctrl-a, F3=Ctrl-e, \
F4 for a command-line or ESC to discard edits and return to the GRUB menu."),
STANDARD_MARGIN, STANDARD_MARGIN, term);
#else
grub_print_message_indented (_("Minimum Emacs-like screen editing is \
supported. TAB lists completions. Press Ctrl-x to boot, Ctrl-c for a \
command-line or ESC to return menu."), STANDARD_MARGIN, STANDARD_MARGIN,
term);
command-line or ESC to discard edits and return to the GRUB menu."),
STANDARD_MARGIN, STANDARD_MARGIN, term);
#endif
}
else
{

View file

@ -167,14 +167,12 @@ grub_terminal_autoload_free (void)
/* Read the file terminal.lst for auto-loading. */
void
read_terminal_list (void)
read_terminal_list (const char *prefix)
{
const char *prefix;
char *filename;
grub_file_t file;
char *buf = NULL;
prefix = grub_env_get ("prefix");
if (!prefix)
{
grub_errno = GRUB_ERR_NONE;

View file

@ -26,13 +26,24 @@
#include <grub/lib/arg.h>
#include <grub/normal.h>
/* Max digits for a char is 3 (0xFF is 255), similarly for an int it
is sizeof (int) * 3, and one extra for a possible -ve sign. */
#define ERRNO_DIGITS_MAX (sizeof (int) * 3 + 1)
static grub_err_t
grub_script_execute_cmd (struct grub_script_cmd *cmd)
{
int ret;
char errnobuf[ERRNO_DIGITS_MAX + 1];
if (cmd == 0)
return 0;
return cmd->exec (cmd);
ret = cmd->exec (cmd);
grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret);
grub_env_set ("?", errnobuf);
return ret;
}
#define ARG_ALLOCATION_UNIT (32 * sizeof (char))
@ -260,13 +271,14 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
grub_err_t
grub_script_execute_cmdblock (struct grub_script_cmd *cmd)
{
int ret = 0;
struct grub_script_cmdblock *cmdblock = (struct grub_script_cmdblock *) cmd;
/* Loop over every command and execute it. */
for (cmd = cmdblock->cmdlist; cmd; cmd = cmd->next)
grub_script_execute_cmd (cmd);
ret = grub_script_execute_cmd (cmd);
return 0;
return ret;
}
/* Execute an if statement. */
@ -317,6 +329,26 @@ grub_script_execute_cmdfor (struct grub_script_cmd *cmd)
return result;
}
/* Execute a "while" or "until" command. */
grub_err_t
grub_script_execute_cmdwhile (struct grub_script_cmd *cmd)
{
int cond;
int result;
struct grub_script_cmdwhile *cmdwhile = (struct grub_script_cmdwhile *) cmd;
result = 0;
do {
cond = grub_script_execute_cmd (cmdwhile->cond);
if (cmdwhile->until ? !cond : cond)
break;
result = grub_script_execute_cmd (cmdwhile->list);
} while (1); /* XXX Put a check for ^C here */
return result;
}
/* Execute the menu entry generate statement. */
grub_err_t
grub_script_execute_menuentry (struct grub_script_cmd *cmd)

View file

@ -74,8 +74,10 @@
%token <arg> GRUB_PARSER_TOKEN_WORD "word"
%type <arglist> word argument arguments0 arguments1
%type <cmd> script_init script grubcmd ifcmd forcmd command
%type <cmd> commands1 menuentry statement
%type <cmd> script_init script
%type <cmd> grubcmd ifclause ifcmd forcmd whilecmd untilcmd
%type <cmd> command commands1 menuentry statement
%pure-parser
%lex-param { struct grub_parser_param *state };
@ -92,7 +94,7 @@ script: newlines0
{
$$ = 0;
}
| script statement delimiter
| script statement delimiter newlines0
{
struct grub_script_cmdblock *cmdblock;
cmdblock = (struct grub_script_cmdblock *) $1;
@ -171,9 +173,11 @@ grubcmd: word arguments0
;
/* A single command. */
command: grubcmd { $$ = $1; }
| ifcmd { $$ = $1; }
| forcmd { $$ = $1; }
command: grubcmd { $$ = $1; }
| ifcmd { $$ = $1; }
| forcmd { $$ = $1; }
| whilecmd { $$ = $1; }
| untilcmd { $$ = $1; }
;
/* A list of commands. */
@ -224,18 +228,28 @@ menuentry: "menuentry"
}
;
if: "if" { grub_script_lexer_ref (state->lexerstate); }
ifcmd: "if"
{
grub_script_lexer_ref (state->lexerstate);
}
ifclause "fi"
{
$$ = $3;
grub_script_lexer_deref (state->lexerstate);
}
;
ifcmd: if commands1 delimiters1 "then" commands1 delimiters1 "fi"
{
$$ = grub_script_create_cmdif (state, $2, $5, 0);
grub_script_lexer_deref (state->lexerstate);
}
| if commands1 delimiters1 "then" commands1 delimiters1 "else" commands1 delimiters1 "fi"
{
$$ = grub_script_create_cmdif (state, $2, $5, $8);
grub_script_lexer_deref (state->lexerstate);
}
ifclause: commands1 delimiters1 "then" commands1 delimiters1
{
$$ = grub_script_create_cmdif (state, $1, $4, 0);
}
| commands1 delimiters1 "then" commands1 delimiters1 "else" commands1 delimiters1
{
$$ = grub_script_create_cmdif (state, $1, $4, $7);
}
| commands1 delimiters1 "then" commands1 delimiters1 "elif" ifclause
{
$$ = grub_script_create_cmdif (state, $1, $4, $7);
}
;
forcmd: "for" "name"
@ -248,3 +262,25 @@ forcmd: "for" "name"
grub_script_lexer_deref (state->lexerstate);
}
;
whilecmd: "while"
{
grub_script_lexer_ref (state->lexerstate);
}
commands1 delimiters1 "do" commands1 delimiters1 "done"
{
$$ = grub_script_create_cmdwhile (state, $3, $6, 0);
grub_script_lexer_deref (state->lexerstate);
}
;
untilcmd: "until"
{
grub_script_lexer_ref (state->lexerstate);
}
commands1 delimiters1 "do" commands1 delimiters1 "done"
{
$$ = grub_script_create_cmdwhile (state, $3, $6, 1);
grub_script_lexer_deref (state->lexerstate);
}
;

View file

@ -245,6 +245,28 @@ grub_script_create_cmdfor (struct grub_parser_param *state,
return (struct grub_script_cmd *) cmd;
}
/* Create a "while" or "until" command. */
struct grub_script_cmd *
grub_script_create_cmdwhile (struct grub_parser_param *state,
struct grub_script_cmd *cond,
struct grub_script_cmd *list,
int is_an_until_loop)
{
struct grub_script_cmdwhile *cmd;
cmd = grub_script_malloc (state, sizeof (*cmd));
if (! cmd)
return 0;
cmd->cmd.exec = grub_script_execute_cmdwhile;
cmd->cmd.next = 0;
cmd->cond = cond;
cmd->list = list;
cmd->until = is_an_until_loop;
return (struct grub_script_cmd *) cmd;
}
/* Create a command that adds a menu entry to the menu. Title is an
argument that is parsed to generate a string that can be used as
the title. The sourcecode for this entry is passed in SOURCECODE.

View file

@ -68,31 +68,23 @@ static void copy_string (struct grub_parser_param *, const char *,
%top{
#include <sys/types.h>
typedef size_t yy_size_t;
#define YY_TYPEDEF_YY_SIZE_T 1
/*
* Some flex hacks for -nostdinc; XXX We need to fix these when libc
* support becomes availble in GRUB.
*/
#include <grub/types.h>
typedef grub_size_t size_t;
typedef grub_size_t yy_size_t;
#define YY_TYPEDEF_YY_SIZE_T 1
#define FILE void
#ifndef GRUB_UTIL
#define stdin 0
#define stdout 0
#define EOF 0
#define errno grub_errno
#define EINVAL GRUB_ERR_BAD_NUMBER
#define ENOMEM GRUB_ERR_OUT_OF_MEMORY
#define strlen grub_strlen
#define memset grub_memset
#define fprintf(...) 0
#define exit(...)
#endif
#pragma GCC diagnostic warning "-Wunused-variable"
#pragma GCC diagnostic warning "-Wunused-function"

View file

@ -159,27 +159,27 @@ grub_console_checkkey (void)
read_key = key.unicode_char;
break;
case 0x01:
read_key = 16;
read_key = GRUB_TERM_UP;
break;
case 0x02:
read_key = 14;
read_key = GRUB_TERM_DOWN;
break;
case 0x03:
read_key = 6;
read_key = GRUB_TERM_RIGHT;
break;
case 0x04:
read_key = 2;
read_key = GRUB_TERM_LEFT;
break;
case 0x05:
read_key = 1;
read_key = GRUB_TERM_HOME;
break;
case 0x06:
read_key = 5;
read_key = GRUB_TERM_END;
break;
case 0x07:
break;
case 0x08:
read_key = 4;
read_key = GRUB_TERM_DC;
break;
case 0x09:
break;
@ -194,6 +194,9 @@ grub_console_checkkey (void)
case 0x0d:
read_key = 5;
break;
case 0x0e:
read_key = 3;
break;
case 0x17:
read_key = '\e';
break;

View file

@ -0,0 +1,14 @@
#! /bin/sh -e
@builddir@/grub-script-check <<EOF
# comment 1
command1 arg1
command2 arg2
last command
# comment 2
EOF

View file

@ -0,0 +1,10 @@
#! /bin/sh -e
@builddir@/grub-script-check <<EOF
echo one;
echo one; echo two
echo one; echo two;
echo one ; echo two ;
echo one ; echo two ; echo three
echo one; echo two ; echo three;
EOF

31
tests/grub_script_if.in Normal file
View file

@ -0,0 +1,31 @@
#! @builddir@/grub-shell-tester
#basic if, execute
if true; then echo yes; fi
#basic if, no execution
if false; then echo no; fi
#if else, execute if path
if true; then echo yes; else echo no; fi
#if else, execute else path
if false; then echo no; else echo yes; fi
#if elif, execute elif
if false; then echo no; elif true; then echo yes; fi
#if elif else, execute else
if false; then echo no; elif false; then echo no; else echo yes; fi
#if elif(1) elif(2), execute elif(2)
if false; then echo no; elif false; then echo no; elif true; then echo yes; fi
#if elif(1) elif(2) else, execute else
if false; then echo no; elif false; then echo no; elif false; then echo no; else echo yes; fi
#if {if elif else}, execute elif
if true; then if false; then echo no; elif true; then echo yes; else echo no; fi; fi
#if {if elif} else, execute elif. ofcourse no dangling-else problem due to "fi"
if true; then if false; then echo no; elif true; then echo yes; fi; else echo no; fi

View file

@ -0,0 +1,32 @@
#! @builddir@/grub-shell-tester
echo one
foo=""
while test "$foo" != "1111"; do foo="${foo}1"; echo "$foo"; done
echo two
foo=""
while test "$foo" != "aaaa"
do
foo="${foo}a"
echo $foo
done
foo=""
until test "$foo" = "1111"; do foo="${foo}1"; echo $foo; done
foo=""
until test "$foo" = "aaaa"
do
foo="${foo}a"
echo $foo
done
# check "$?" in condition gets its value from while body commands
foo=""
false
while test "$?" != "0"
do
echo $foo
foo="${foo}1"
test "$foo" = "111111"
done

View file

@ -135,7 +135,7 @@ fdafile=`mktemp`
cp ${isofile} ${fdafile}
outfile=`mktemp`
qemu-system-i386 ${qemuopts} -nographic -serial stdio -hda ${hdafile} -fda ${fdafile} -cdrom ${isofile} -boot ${bootdev} | tr -d "\r" >${outfile}
qemu-system-i386 ${qemuopts} -nographic -hda ${hdafile} -fda ${fdafile} -cdrom ${isofile} -boot ${bootdev} | tr -d "\r" >${outfile}
cat $outfile

View file

@ -219,8 +219,7 @@ else
fi
# Create the GRUB directory if it is not present.
test -d "$bootdir" || mkdir "$bootdir" || exit 1
test -d "$grubdir" || mkdir "$grubdir" || exit 1
mkdir -p "$grubdir" || exit 1
# If --recheck is specified, remove the device map, if present.
if test $recheck = yes; then
@ -271,7 +270,7 @@ for dir in ${localedir}/*; do
done
# Write device to a variable so we don't have to traverse /dev every time.
grub_device=`$grub_probe --target=device ${grubdir}`
grub_device=`$grub_probe --target=device ${grubdir}` || exit 1
if ! test -f ${grubdir}/grubenv; then
$grub_editenv ${grubdir}/grubenv create
@ -313,11 +312,11 @@ if [ "x${devabstraction_module}" = "x" ] ; then
if echo "${install_device}" | grep -qx "(.*)" ; then
install_drive="${install_device}"
else
install_drive="`$grub_probe --target=drive --device ${install_device}`"
install_drive="`$grub_probe --target=drive --device ${install_device}`" || exit 1
fi
install_drive="`echo ${install_drive} | sed -e s/,[0-9]*[a-z]*//g`"
fi
grub_drive="`$grub_probe --target=drive --device ${grub_device}`"
grub_drive="`$grub_probe --target=drive --device ${grub_device}`" || exit 1
# Strip partition number
grub_drive="`echo ${grub_drive} | sed -e s/,[0-9]*[a-z]*//g`"
@ -344,7 +343,7 @@ if [ "x${devabstraction_module}" = "x" ] ; then
modules="$modules search_fs_uuid"
fi
else
prefix_drive=`$grub_probe --target=drive --device ${grub_device}`
prefix_drive=`$grub_probe --target=drive --device ${grub_device}` || exit 1
fi
if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then

View file

@ -140,60 +140,73 @@ if [ "x${GRUB_TERMINAL}" != "x" ] ; then
GRUB_TERMINAL_OUTPUT="${GRUB_TERMINAL}"
fi
case x${GRUB_TERMINAL_OUTPUT} in
x | xgfxterm)
# If this platform supports gfxterm, try to use it.
if test -e ${grub_prefix}/gfxterm.mod ; then
# FIXME: this should do something smarter than just loading first
# video backend.
GRUB_VIDEO_BACKEND=$(head -n 1 ${grub_prefix}/video.lst || true)
if [ -n "${GRUB_VIDEO_BACKEND}" ] ; then
GRUB_TERMINAL_OUTPUT=gfxterm
elif [ "${GRUB_TERMINAL_OUTPUT}" = "gfxterm" ] ; then
echo "No suitable backend could be found for gfxterm." >&2 ; exit 1
fi
fi
;;
xconsole | xserial | xofconsole) ;;
*) echo "Invalid output terminal \"${GRUB_TERMINAL_OUTPUT}\"" >&2 ; exit 1 ;;
esac
termoutdefault=0
if [ "x${GRUB_TERMINAL_OUTPUT}" == x ]; then
GRUB_TERMINAL_OUTPUT=gfxterm;
termoutdefault=1;
fi
# check for terminals that require fonts
case ${GRUB_TERMINAL_OUTPUT} in
gfxterm)
if [ -n "$GRUB_FONT" ] ; then
if is_path_readable_by_grub ${GRUB_FONT} > /dev/null ; then
GRUB_FONT_PATH=${GRUB_FONT}
else
echo "No such font or not readable by grub: ${GRUB_FONT}" >&2
exit 1
for x in ${GRUB_TERMINAL_OUTPUT}; do
if [ x${x} == xgfxterm ]; then
# If this platform supports gfxterm, try to use it.
if ! test -e ${grub_prefix}/gfxterm.mod ; then
if [ "x$termoutdefault" != "x1" ]; then
echo "gfxterm isn't available on your platform" >&2 ; exit 1
fi
GRUB_TERMINAL_OUTPUT=
break;
fi
# FIXME: this should do something smarter than just loading first
# video backend.
GRUB_VIDEO_BACKEND=$(head -n 1 ${grub_prefix}/video.lst || true)
if [ -z "${GRUB_VIDEO_BACKEND}" ] ; then
if [ "x$termoutdefault" != "x1" ]; then
echo "No suitable backend could be found for gfxterm." >&2 ; exit 1
fi
GRUB_TERMINAL_OUTPUT=
fi
if [ -n "$GRUB_FONT" ] ; then
if is_path_readable_by_grub ${GRUB_FONT} > /dev/null ; then
GRUB_FONT_PATH=${GRUB_FONT}
else
echo "No such font or not readable by grub: ${GRUB_FONT}" >&2
exit 1
fi
else
for dir in ${pkgdatadir} /boot/grub /usr/share/grub ; do
for basename in unicode unifont ascii; do
path="${dir}/${basename}.pf2"
if is_path_readable_by_grub ${path} > /dev/null ; then
GRUB_FONT_PATH=${path}
else
continue
fi
if [ "${basename}" = "ascii" ] ; then
# make sure all our children behave in conformance with ascii..
export LANG=C
fi
break 2
done
done
fi
if [ -z "${GRUB_FONT_PATH}" ] ; then
if [ "x$termoutdefault" != "x1" ]; then
echo "No font for gfxterm found." >&2 ; exit 1
fi
GRUB_TERMINAL_OUTPUT=
fi
else
for dir in ${pkgdatadir} /boot/grub /usr/share/grub ; do
for basename in unicode unifont ascii; do
path="${dir}/${basename}.pf2"
if is_path_readable_by_grub ${path} > /dev/null ; then
GRUB_FONT_PATH=${path}
else
continue
fi
if [ "${basename}" = "ascii" ] ; then
# make sure all our children behave in conformance with ascii..
export LANG=C
fi
break 2
done
done
fi
if [ -z "${GRUB_FONT_PATH}" ] ; then
# fallback to the native terminal for this platform
unset GRUB_TERMINAL_OUTPUT
fi
;;
*)
# make sure all our children behave in conformance with ascii..
export LANG=C
esac
done
for x in ${GRUB_TERMINAL_OUTPUT}; do
case "x${x}" in
xgfxterm) ;;
xconsole | xserial | xofconsole)
# make sure all our children behave in conformance with ascii..
export LANG=C;;
*) echo "Invalid output terminal \"${GRUB_TERMINAL_OUTPUT}\"" >&2 ; exit 1 ;;
esac
done
# These are defined in this script, export them here so that user can
# override them.
@ -220,6 +233,7 @@ export GRUB_DEFAULT \
GRUB_DISABLE_LINUX_UUID \
GRUB_DISABLE_LINUX_RECOVERY \
GRUB_GFXMODE \
GRUB_BACKGROUND \
GRUB_THEME \
GRUB_GFXPAYLOAD_LINUX \
GRUB_DISABLE_OS_PROBER \

Some files were not shown because too many files have changed in this diff Show more