From 9b3f8365713e8636f5ed97bb263c90f47ea0caa6 Mon Sep 17 00:00:00 2001 From: fzielcke Date: Wed, 23 Sep 2009 09:26:34 +0000 Subject: [PATCH 001/165] 2009-09-23 Felix Zielcke * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Add support for `*.dpkg-new'. --- ChangeLog | 5 +++++ util/grub-mkconfig_lib.in | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 22aeb6feb..1ac4b4b3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-09-23 Felix Zielcke + + * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Add support + for `*.dpkg-new'. + 2009-09-21 Colin Watson Build info documentation. Some code borrowed from Automake. diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 2385b0878..a4db096f8 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -157,7 +157,7 @@ grub_file_is_not_garbage () { if test -f "$1" ; then case "$1" in - *.dpkg-dist|*.dpkg-old|*.dpkg-tmp) return 1 ;; # debian dpkg + *.dpkg-dist|*.dpkg-old|*.dpkg-tmp|*.dpkg-new) return 1 ;; # debian dpkg esac else return 1 From d96875df6ebec0cb890758ba70c878b016a6e49f Mon Sep 17 00:00:00 2001 From: fzielcke Date: Wed, 23 Sep 2009 09:46:08 +0000 Subject: [PATCH 002/165] 2009-09-23 Felix Zielcke * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Cope with `*.dpkg-*' --- ChangeLog | 4 ++++ util/grub-mkconfig_lib.in | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1ac4b4b3f..bfdbc5a43 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-09-23 Felix Zielcke + + * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Cope with `*.dpkg-*' + 2009-09-23 Felix Zielcke * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Add support diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index a4db096f8..bb30cc475 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -157,7 +157,7 @@ grub_file_is_not_garbage () { if test -f "$1" ; then case "$1" in - *.dpkg-dist|*.dpkg-old|*.dpkg-tmp|*.dpkg-new) return 1 ;; # debian dpkg + *.dpkg-*) return 1 ;; # debian dpkg esac else return 1 From ff4202239622d4cce8dceb67d02401f602b14640 Mon Sep 17 00:00:00 2001 From: cjwatson Date: Wed, 23 Sep 2009 17:18:06 +0000 Subject: [PATCH 003/165] 2009-09-23 Colin Watson * configure.ac: Call AC_PROG_MKDIR_P. * Makefile.in (docs/stamp-vti): Create docs directory. Create version.texi in $(builddir) rather than $(srcdir). (docs/grub.info): Create docs directory. Prepend $(builddir)/docs to makeinfo's @include search path. --- ChangeLog | 8 ++++++++ Makefile.in | 13 ++++++++----- configure.ac | 1 + 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index bfdbc5a43..dc343d1d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-09-23 Colin Watson + + * configure.ac: Call AC_PROG_MKDIR_P. + * Makefile.in (docs/stamp-vti): Create docs directory. Create + version.texi in $(builddir) rather than $(srcdir). + (docs/grub.info): Create docs directory. Prepend $(builddir)/docs + to makeinfo's @include search path. + 2009-09-23 Felix Zielcke * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Cope with `*.dpkg-*' diff --git a/Makefile.in b/Makefile.in index ee4589a78..363d696f1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -59,6 +59,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +MKDIR_P = @MKDIR_P@ mkinstalldirs = $(srcdir)/mkinstalldirs @@ -179,20 +180,22 @@ MOSTLYCLEANFILES += vti.tmp MAINTAINER_CLEANFILES += docs/stamp-vti docs/version.texi docs/version.texi: docs/stamp-vti docs/stamp-vti: docs/grub.texi + $(MKDIR_P) docs (set `$(SHELL) $(srcdir)/docs/mdate-sh $<`; \ echo "@set UPDATED $$1 $$2 $$3"; \ echo "@set UPDATED-MONTH $$2 $$3"; \ echo "@set EDITION $(PACKAGE_VERSION)"; \ echo "@set VERSION $(PACKAGE_VERSION)") > vti.tmp - @cmp -s vti.tmp $(srcdir)/docs/version.texi \ - || (echo "Updating $(srcdir)/docs/version.texi"; \ - cp vti.tmp $(srcdir)/docs/version.texi) + @cmp -s vti.tmp $(builddir)/docs/version.texi \ + || (echo "Updating $(builddir)/docs/version.texi"; \ + cp vti.tmp $(builddir)/docs/version.texi) -@rm -f vti.tmp - @cp $(srcdir)/docs/version.texi $@ + @cp $(builddir)/docs/version.texi $@ # Use --force until such time as the documentation is cleaned up. docs/grub.info: docs/grub.texi docs/version.texi docs/fdl.texi - $(MAKEINFO) --no-split --force $< -o $@ || : + $(MKDIR_P) docs + $(MAKEINFO) -P $(builddir)/docs --no-split --force $< -o $@ || : ifeq (, $(UNIFONT_BDF)) else diff --git a/configure.ac b/configure.ac index e827a32c2..4d221b4d6 100644 --- a/configure.ac +++ b/configure.ac @@ -144,6 +144,7 @@ done AC_PROG_INSTALL AC_PROG_AWK AC_PROG_MAKE_SET +AC_PROG_MKDIR_P # These are not a "must". AC_PATH_PROG(RUBY, ruby) From 74c958b18075e0e4e7c02f1356b45756f3381e08 Mon Sep 17 00:00:00 2001 From: robertmh Date: Thu, 24 Sep 2009 13:15:51 +0000 Subject: [PATCH 004/165] 2009-09-24 Robert Millan * include/grub/i386/at_keyboard.h (KEYBOARD_ISREADY): Negate return value. * term/i386/pc/at_keyboard.c (grub_keyboard_getkey): Negate KEYBOARD_ISREADY check. (grub_at_keyboard_checkkey): Rename to ... (grub_at_keyboard_getkey_noblock): ... this. Update all users. Remove gratuitous cast. --- ChangeLog | 10 ++++++++++ include/grub/i386/at_keyboard.h | 2 +- term/i386/pc/at_keyboard.c | 13 +++++++------ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index dc343d1d9..b5315fa70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-09-24 Robert Millan + + * include/grub/i386/at_keyboard.h (KEYBOARD_ISREADY): Negate + return value. + * term/i386/pc/at_keyboard.c (grub_keyboard_getkey): Negate + KEYBOARD_ISREADY check. + (grub_at_keyboard_checkkey): Rename to ... + (grub_at_keyboard_getkey_noblock): ... this. Update all users. + Remove gratuitous cast. + 2009-09-23 Colin Watson * configure.ac: Call AC_PROG_MKDIR_P. diff --git a/include/grub/i386/at_keyboard.h b/include/grub/i386/at_keyboard.h index 5c15ef344..96b21627f 100644 --- a/include/grub/i386/at_keyboard.h +++ b/include/grub/i386/at_keyboard.h @@ -39,7 +39,7 @@ #define KEYBOARD_SCANCODE_SET1 0x40 #define KEYBOARD_ISMAKE(x) !((x) & 0x80) -#define KEYBOARD_ISREADY(x) (((x) & 0x01) == 0) +#define KEYBOARD_ISREADY(x) ((x) & 0x01) #define KEYBOARD_SCANCODE(x) ((x) & 0x7f) #ifdef GRUB_MACHINE_IEEE1275 diff --git a/term/i386/pc/at_keyboard.c b/term/i386/pc/at_keyboard.c index 0b2a06d46..1ab41d8fd 100644 --- a/term/i386/pc/at_keyboard.c +++ b/term/i386/pc/at_keyboard.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2007,2008 Free Software Foundation, Inc. + * Copyright (C) 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 @@ -135,7 +135,7 @@ static int grub_keyboard_getkey (void) { grub_uint8_t key; - if (KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) return -1; key = grub_inb (KEYBOARD_REG_DATA); /* FIXME */ grub_keyboard_isr (key); @@ -146,7 +146,7 @@ grub_keyboard_getkey (void) /* If there is a character pending, return it; otherwise return -1. */ static int -grub_at_keyboard_checkkey (void) +grub_at_keyboard_getkey_noblock (void) { int code, key; code = grub_keyboard_getkey (); @@ -186,7 +186,7 @@ grub_at_keyboard_checkkey (void) key += 'a' - 'A'; } } - return (int) key; + return key; } static int @@ -195,7 +195,7 @@ grub_at_keyboard_getkey (void) int key; do { - key = grub_at_keyboard_checkkey (); + key = grub_at_keyboard_getkey_noblock (); } while (key == -1); return key; } @@ -220,7 +220,8 @@ static struct grub_term_input grub_at_keyboard_term = .name = "at_keyboard", .init = grub_keyboard_controller_init, .fini = grub_keyboard_controller_fini, - .checkkey = grub_at_keyboard_checkkey, + /* FIXME: This routine flushes input buffer, and it shouldn't. */ + .checkkey = grub_at_keyboard_getkey_noblock, .getkey = grub_at_keyboard_getkey, }; From c6dcedf6b2846ea6018b404e098fad1d87d097b7 Mon Sep 17 00:00:00 2001 From: robertmh Date: Thu, 24 Sep 2009 13:22:19 +0000 Subject: [PATCH 005/165] 2009-09-24 Robert Millan * util/i386/pc/grub-mkimage.c (generate_image): Enclose BIOS-specific size check within GRUB_MACHINE_PCBIOS section. --- ChangeLog | 5 +++++ util/i386/pc/grub-mkimage.c | 45 ++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index b5315fa70..797b50874 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-09-24 Robert Millan + + * util/i386/pc/grub-mkimage.c (generate_image): Enclose BIOS-specific + size check within GRUB_MACHINE_PCBIOS section. + 2009-09-24 Robert Millan * include/grub/i386/at_keyboard.h (KEYBOARD_ISREADY): Negate diff --git a/util/i386/pc/grub-mkimage.c b/util/i386/pc/grub-mkimage.c index b81392ce8..c8fe02e13 100644 --- a/util/i386/pc/grub-mkimage.c +++ b/util/i386/pc/grub-mkimage.c @@ -97,7 +97,6 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], size_t kernel_size, boot_size, total_module_size, core_size; size_t memdisk_size = 0, config_size = 0; char *kernel_path, *boot_path; - unsigned num; size_t offset; struct grub_util_path_list *path_list, *p, *next; struct grub_module_info *modinfo; @@ -196,30 +195,30 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], grub_util_info ("the core size is 0x%x", core_size); - num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); - if (num > 0xffff) - grub_util_error ("the core image is too big"); - #if defined(GRUB_MACHINE_PCBIOS) - - boot_path = grub_util_get_path (dir, "diskboot.img"); - boot_size = grub_util_get_image_size (boot_path); - if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("diskboot.img is not one sector size"); - - boot_img = grub_util_read_image (boot_path); - - /* i386 is a little endian architecture. */ - *((grub_uint16_t *) (boot_img + GRUB_DISK_SECTOR_SIZE - - GRUB_BOOT_MACHINE_LIST_SIZE + 8)) - = grub_cpu_to_le16 (num); - - grub_util_write_image (boot_img, boot_size, out); - free (boot_img); - free (boot_path); - + { + unsigned num; + num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); + if (num > 0xffff) + grub_util_error ("the core image is too big"); + + boot_path = grub_util_get_path (dir, "diskboot.img"); + boot_size = grub_util_get_image_size (boot_path); + if (boot_size != GRUB_DISK_SECTOR_SIZE) + grub_util_error ("diskboot.img is not one sector size"); + + boot_img = grub_util_read_image (boot_path); + + /* i386 is a little endian architecture. */ + *((grub_uint16_t *) (boot_img + GRUB_DISK_SECTOR_SIZE + - GRUB_BOOT_MACHINE_LIST_SIZE + 8)) + = grub_cpu_to_le16 (num); + + grub_util_write_image (boot_img, boot_size, out); + free (boot_img); + free (boot_path); + } #elif defined(GRUB_MACHINE_QEMU) - { char *rom_img; size_t rom_size; From 4e5a02a7baa27d8d36fde17808225322e8170263 Mon Sep 17 00:00:00 2001 From: robertmh Date: Thu, 24 Sep 2009 13:25:07 +0000 Subject: [PATCH 006/165] 2009-09-24 Robert Millan Fix "lost keypress" bug in at_keyboard. * term/i386/pc/at_keyboard.c (grub_at_keyboard_checkkey): New function. Checks for readyness of input buffer (without flushing it). (grub_at_keyboard_term): Use grub_at_keyboard_checkkey() rather than grub_at_keyboard_getkey_noblock() for `checkkey' struct member. --- ChangeLog | 9 +++++++++ term/i386/pc/at_keyboard.c | 10 ++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 797b50874..1c29001a4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-09-24 Robert Millan + + Fix "lost keypress" bug in at_keyboard. + + * term/i386/pc/at_keyboard.c (grub_at_keyboard_checkkey): New function. + Checks for readyness of input buffer (without flushing it). + (grub_at_keyboard_term): Use grub_at_keyboard_checkkey() rather + than grub_at_keyboard_getkey_noblock() for `checkkey' struct member. + 2009-09-24 Robert Millan * util/i386/pc/grub-mkimage.c (generate_image): Enclose BIOS-specific diff --git a/term/i386/pc/at_keyboard.c b/term/i386/pc/at_keyboard.c index 1ab41d8fd..cf30e7242 100644 --- a/term/i386/pc/at_keyboard.c +++ b/term/i386/pc/at_keyboard.c @@ -189,6 +189,13 @@ grub_at_keyboard_getkey_noblock (void) return key; } +static int +grub_at_keyboard_checkkey (void) +{ + /* FIXME: this will be triggered by BREAK events. */ + return KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)) ? 1 : -1; +} + static int grub_at_keyboard_getkey (void) { @@ -220,8 +227,7 @@ static struct grub_term_input grub_at_keyboard_term = .name = "at_keyboard", .init = grub_keyboard_controller_init, .fini = grub_keyboard_controller_fini, - /* FIXME: This routine flushes input buffer, and it shouldn't. */ - .checkkey = grub_at_keyboard_getkey_noblock, + .checkkey = grub_at_keyboard_checkkey, .getkey = grub_at_keyboard_getkey, }; From 6b9b6276d441db3d79de53c6f366844f277e71f0 Mon Sep 17 00:00:00 2001 From: robertmh Date: Thu, 24 Sep 2009 13:40:40 +0000 Subject: [PATCH 007/165] 2009-09-24 Pavel Roskin * include/grub/kernel.h (struct grub_module_header): Remove `grub_module_header_types'. Make `type' unsigned. Make `size' 32-bit on all platforms. * util/elf/grub-mkimage.c (load_modules): Treat `type' as an 8-bit field. Use grub_host_to_target32() for `size'. * util/i386/efi/grub-mkimage.c (make_mods_section): Likewise. * util/i386/pc/grub-mkimage.c (generate_image): Likewise. * util/sparc64/ieee1275/grub-mkimage.c (generate_image): Likewise. --- ChangeLog | 11 +++++++++++ include/grub/kernel.h | 18 +++++++++--------- util/elf/grub-mkimage.c | 6 +++--- util/i386/efi/grub-mkimage.c | 4 ++-- util/i386/pc/grub-mkimage.c | 12 ++++++------ util/sparc64/ieee1275/grub-mkimage.c | 8 ++++---- 6 files changed, 35 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1c29001a4..fd9865440 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2009-09-24 Pavel Roskin + + * include/grub/kernel.h (struct grub_module_header): Remove + `grub_module_header_types'. Make `type' unsigned. Make `size' + 32-bit on all platforms. + * util/elf/grub-mkimage.c (load_modules): Treat `type' as an + 8-bit field. Use grub_host_to_target32() for `size'. + * util/i386/efi/grub-mkimage.c (make_mods_section): Likewise. + * util/i386/pc/grub-mkimage.c (generate_image): Likewise. + * util/sparc64/ieee1275/grub-mkimage.c (generate_image): Likewise. + 2009-09-24 Robert Millan Fix "lost keypress" bug in at_keyboard. diff --git a/include/grub/kernel.h b/include/grub/kernel.h index 02bc2765a..75ec77c2a 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -22,20 +22,20 @@ #include #include +enum +{ + OBJ_TYPE_ELF, + OBJ_TYPE_MEMDISK, + OBJ_TYPE_CONFIG +}; + /* The module header. */ struct grub_module_header { /* The type of object. */ - grub_int8_t type; - enum - { - OBJ_TYPE_ELF, - OBJ_TYPE_MEMDISK, - OBJ_TYPE_CONFIG - } grub_module_header_types; - + grub_uint8_t type; /* The size of object (including this header). */ - grub_target_size_t size; + grub_uint32_t size; }; /* "gmim" (GRUB Module Info Magic). */ diff --git a/util/elf/grub-mkimage.c b/util/elf/grub-mkimage.c index 52bb6397d..535427208 100644 --- a/util/elf/grub-mkimage.c +++ b/util/elf/grub-mkimage.c @@ -144,7 +144,7 @@ load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir, mod_size = grub_util_get_image_size (p->name); header = (struct grub_module_header *) (module_img + offset); - header->type = grub_host_to_target32 (OBJ_TYPE_ELF); + header->type = OBJ_TYPE_ELF; header->size = grub_host_to_target32 (mod_size + sizeof (*header)); grub_util_load_image (p->name, module_img + offset + sizeof (*header)); @@ -157,8 +157,8 @@ load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir, struct grub_module_header *header; header = (struct grub_module_header *) (module_img + offset); - header->type = grub_cpu_to_le32 (OBJ_TYPE_MEMDISK); - header->size = grub_cpu_to_le32 (memdisk_size + sizeof (*header)); + header->type = OBJ_TYPE_MEMDISK; + header->size = grub_host_to_target32 (memdisk_size + sizeof (*header)); offset += sizeof (*header); grub_util_load_image (memdisk_path, module_img + offset); diff --git a/util/i386/efi/grub-mkimage.c b/util/i386/efi/grub-mkimage.c index 466aa9f87..29a823e58 100644 --- a/util/i386/efi/grub-mkimage.c +++ b/util/i386/efi/grub-mkimage.c @@ -683,8 +683,8 @@ make_mods_section (FILE *out, Elf_Addr current_address, grub_util_info ("adding module %s", p->name); mod_size = grub_util_get_image_size (p->name); - header.type = grub_cpu_to_le32 (OBJ_TYPE_ELF); - header.size = grub_cpu_to_le32 (mod_size + sizeof (header)); + header.type = OBJ_TYPE_ELF; + header.size = grub_host_to_target32 (mod_size + sizeof (header)); mod_image = grub_util_read_image (p->name); diff --git a/util/i386/pc/grub-mkimage.c b/util/i386/pc/grub-mkimage.c index c8fe02e13..15168f8fa 100644 --- a/util/i386/pc/grub-mkimage.c +++ b/util/i386/pc/grub-mkimage.c @@ -152,8 +152,8 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], header = (struct grub_module_header *) (kernel_img + offset); memset (header, 0, sizeof (struct grub_module_header)); - header->type = grub_cpu_to_le32 (OBJ_TYPE_ELF); - header->size = grub_cpu_to_le32 (mod_size + sizeof (*header)); + header->type = OBJ_TYPE_ELF; + header->size = grub_host_to_target32 (mod_size + sizeof (*header)); offset += sizeof (*header); grub_util_load_image (p->name, kernel_img + offset); @@ -166,8 +166,8 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], header = (struct grub_module_header *) (kernel_img + offset); memset (header, 0, sizeof (struct grub_module_header)); - header->type = grub_cpu_to_le32 (OBJ_TYPE_MEMDISK); - header->size = grub_cpu_to_le32 (memdisk_size + sizeof (*header)); + header->type = OBJ_TYPE_MEMDISK; + header->size = grub_host_to_target32 (memdisk_size + sizeof (*header)); offset += sizeof (*header); grub_util_load_image (memdisk_path, kernel_img + offset); @@ -180,8 +180,8 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], header = (struct grub_module_header *) (kernel_img + offset); memset (header, 0, sizeof (struct grub_module_header)); - header->type = grub_cpu_to_le32 (OBJ_TYPE_CONFIG); - header->size = grub_cpu_to_le32 (config_size + sizeof (*header)); + header->type = OBJ_TYPE_CONFIG; + header->size = grub_host_to_target32 (config_size + sizeof (*header)); offset += sizeof (*header); grub_util_load_image (config_path, kernel_img + offset); diff --git a/util/sparc64/ieee1275/grub-mkimage.c b/util/sparc64/ieee1275/grub-mkimage.c index 247f13846..0a611da8f 100644 --- a/util/sparc64/ieee1275/grub-mkimage.c +++ b/util/sparc64/ieee1275/grub-mkimage.c @@ -98,8 +98,8 @@ generate_image (const char *dir, const char *prefix, FILE *out, char *mods[], ch mod_size = grub_util_get_image_size (p->name); header = (struct grub_module_header *) (kernel_img + offset); - header->type = grub_cpu_to_be32 (OBJ_TYPE_ELF); - header->size = grub_cpu_to_be32 (mod_size + sizeof (*header)); + header->type = OBJ_TYPE_ELF; + header->size = grub_host_to_target32 (mod_size + sizeof (*header)); offset += sizeof (*header); grub_util_load_image (p->name, kernel_img + offset); @@ -111,8 +111,8 @@ generate_image (const char *dir, const char *prefix, FILE *out, char *mods[], ch struct grub_module_header *header; header = (struct grub_module_header *) (kernel_img + offset); - header->type = grub_cpu_to_be32 (OBJ_TYPE_MEMDISK); - header->size = grub_cpu_to_be32 (memdisk_size + sizeof (*header)); + header->type = OBJ_TYPE_MEMDISK; + header->size = grub_host_to_target32 (memdisk_size + sizeof (*header)); offset += sizeof (*header); grub_util_load_image (memdisk_path, kernel_img + offset); From cb8a2c382e70d3b6924120c86e944297cd8d0dce Mon Sep 17 00:00:00 2001 From: cjwatson Date: Fri, 25 Sep 2009 23:43:46 +0000 Subject: [PATCH 008/165] 2009-09-26 Colin Watson * docs/grub.texi (Command-line and menu entry commands): Document date and echo commands. --- ChangeLog | 5 +++++ docs/grub.texi | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/ChangeLog b/ChangeLog index fd9865440..fdca53d01 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-09-26 Colin Watson + + * docs/grub.texi (Command-line and menu entry commands): Document + date and echo commands. + 2009-09-24 Pavel Roskin * include/grub/kernel.h (struct grub_module_header): Remove diff --git a/docs/grub.texi b/docs/grub.texi index 06059df4d..4fa44462e 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1118,6 +1118,8 @@ you forget a command, you can run the command @command{help} * cmp:: Compare two files * configfile:: Load a configuration file * crc:: Calculate CRC32 checksums +* date:: Display or set current date and time +* echo:: Display a line of text * export:: Export an environment variable * halt:: Shut down your computer * help:: Show help messages @@ -1234,6 +1236,62 @@ Display the CRC32 checksum of @var{file}. @end deffn +@node date +@subsection date + +@deffn Command date [[year-]month-day] [hour:minute[:second]] +With no arguments, print the current date and time. + +Otherwise, take the current date and time, change any elements specified as +arguments, and set the result as the new date and time. For example, `date +01-01' will set the current month and day to January 1, but leave the year, +hour, minute, and second unchanged. +@end deffn + + +@node echo +@subsection echo + +@deffn Command echo [@option{-n}] [@option{-e}] string @dots{} +Display the requested text and, unless the @option{-n} option is used, a +trailing new line. If there is more than one string, they are separated by +spaces in the output. As usual in GRUB commands, variables may be +substituted using @samp{$@{var@}}. + +The @option{-e} option enables interpretation of backslash escapes. The +following sequences are recognised: + +@table @code +@item \\ +backslash + +@item \a +alert (BEL) + +@item \c +suppress trailing new line + +@item \f +form feed + +@item \n +new line + +@item \r +carriage return + +@item \t +horizontal tab + +@item \v +vertical tab +@end table + +When interpreting backslash escapes, backslash followed by any other +character will print that character. +@end deffn + + @node export @subsection export From 31299a9556499ac65cc387e293a6d3744ccb622a Mon Sep 17 00:00:00 2001 From: robertmh Date: Sat, 26 Sep 2009 11:48:55 +0000 Subject: [PATCH 009/165] 2009-09-26 Robert Millan * conf/common.rmk (pkglib_MODULES): Remove `lua.mod'. (lua_mod_SOURCES, lua_mod_CFLAGS, lua_mod_LDFLAGS): Remove. * util/osdetect.lua: Remove. * script/lua/lauxlib.c: Likewise. * script/lua/ldebug.c: Likewise. * script/lua/grub_main.c: Likewise. * script/lua/lauxlib.h: Likewise. * script/lua/ldebug.h: Likewise. * script/lua/ltablib.c: Likewise. * script/lua/liolib.c: Likewise. * script/lua/lstrlib.c: Likewise. * script/lua/lualib.h: Likewise. * script/lua/ldo.c: Likewise. * script/lua/ldump.c: Likewise. * script/lua/ldo.h: Likewise. * script/lua/loslib.c: Likewise. * script/lua/lundump.c: Likewise. * script/lua/grub_lib.c: Likewise. * script/lua/ldblib.c: Likewise. * script/lua/lundump.h: Likewise. * script/lua/lmem.c: Likewise. * script/lua/grub_lib.h: Likewise. * script/lua/lmathlib.c: Likewise. * script/lua/lstate.c: Likewise. * script/lua/ltm.c: Likewise. * script/lua/lvm.c: Likewise. * script/lua/lmem.h: Likewise. * script/lua/lstate.h: Likewise. * script/lua/ltm.h: Likewise. * script/lua/ltable.c: Likewise. * script/lua/lvm.h: Likewise. * script/lua/llex.c: Likewise. * script/lua/lgc.c: Likewise. * script/lua/grub_lua.h: Likewise. * script/lua/loadlib.c: Likewise. * script/lua/lfunc.c: Likewise. * script/lua/lopcodes.c: Likewise. * script/lua/lparser.c: Likewise. * script/lua/ltable.h: Likewise. * script/lua/llex.h: Likewise. * script/lua/lgc.h: Likewise. * script/lua/lfunc.h: Likewise. * script/lua/lbaselib.c: Likewise. * script/lua/lopcodes.h: Likewise. * script/lua/lparser.h: Likewise. * script/lua/lzio.c: Likewise. * script/lua/linit.c: Likewise. * script/lua/lobject.c: Likewise. * script/lua/llimits.h: Likewise. * script/lua/lstring.c: Likewise. * script/lua/lzio.h: Likewise. * script/lua/lapi.c: Likewise. * script/lua/lcode.c: Likewise. * script/lua/lua.h: Likewise. * script/lua/lobject.h: Likewise. * script/lua/lstring.h: Likewise. * script/lua/lapi.h: Likewise. * script/lua/lcode.h: Likewise. * script/lua/luaconf.h: Likewise. --- ChangeLog | 63 ++ conf/common.rmk | 19 +- script/lua/grub_lib.c | 438 ------------- script/lua/grub_lib.h | 24 - script/lua/grub_lua.h | 114 ---- script/lua/grub_main.c | 209 ------- script/lua/lapi.c | 1088 -------------------------------- script/lua/lapi.h | 16 - script/lua/lauxlib.c | 668 -------------------- script/lua/lauxlib.h | 175 ------ script/lua/lbaselib.c | 652 ------------------- script/lua/lcode.c | 848 ------------------------- script/lua/lcode.h | 76 --- script/lua/ldblib.c | 398 ------------ script/lua/ldebug.c | 638 ------------------- script/lua/ldebug.h | 33 - script/lua/ldo.c | 519 ---------------- script/lua/ldo.h | 57 -- script/lua/ldump.c | 164 ----- script/lua/lfunc.c | 174 ------ script/lua/lfunc.h | 34 - script/lua/lgc.c | 713 --------------------- script/lua/lgc.h | 110 ---- script/lua/linit.c | 38 -- script/lua/liolib.c | 553 ----------------- script/lua/llex.c | 467 -------------- script/lua/llex.h | 81 --- script/lua/llimits.h | 128 ---- script/lua/lmathlib.c | 263 -------- script/lua/lmem.c | 86 --- script/lua/lmem.h | 50 -- script/lua/loadlib.c | 665 -------------------- script/lua/lobject.c | 216 ------- script/lua/lobject.h | 380 ------------ script/lua/lopcodes.c | 102 --- script/lua/lopcodes.h | 268 -------- script/lua/loslib.c | 243 -------- script/lua/lparser.c | 1340 ---------------------------------------- script/lua/lparser.h | 82 --- script/lua/lstate.c | 213 ------- script/lua/lstate.h | 169 ----- script/lua/lstring.c | 112 ---- script/lua/lstring.h | 31 - script/lua/lstrlib.c | 870 -------------------------- script/lua/ltable.c | 594 ------------------ script/lua/ltable.h | 40 -- script/lua/ltablib.c | 288 --------- script/lua/ltm.c | 76 --- script/lua/ltm.h | 54 -- script/lua/lua.h | 388 ------------ script/lua/luaconf.h | 811 ------------------------ script/lua/lualib.h | 53 -- script/lua/lundump.c | 229 ------- script/lua/lundump.h | 36 -- script/lua/lvm.c | 764 ----------------------- script/lua/lvm.h | 36 -- script/lua/lzio.c | 83 --- script/lua/lzio.h | 67 -- util/osdetect.lua | 111 ---- 59 files changed, 64 insertions(+), 17153 deletions(-) delete mode 100644 script/lua/grub_lib.c delete mode 100644 script/lua/grub_lib.h delete mode 100644 script/lua/grub_lua.h delete mode 100644 script/lua/grub_main.c delete mode 100644 script/lua/lapi.c delete mode 100644 script/lua/lapi.h delete mode 100644 script/lua/lauxlib.c delete mode 100644 script/lua/lauxlib.h delete mode 100644 script/lua/lbaselib.c delete mode 100644 script/lua/lcode.c delete mode 100644 script/lua/lcode.h delete mode 100644 script/lua/ldblib.c delete mode 100644 script/lua/ldebug.c delete mode 100644 script/lua/ldebug.h delete mode 100644 script/lua/ldo.c delete mode 100644 script/lua/ldo.h delete mode 100644 script/lua/ldump.c delete mode 100644 script/lua/lfunc.c delete mode 100644 script/lua/lfunc.h delete mode 100644 script/lua/lgc.c delete mode 100644 script/lua/lgc.h delete mode 100644 script/lua/linit.c delete mode 100644 script/lua/liolib.c delete mode 100644 script/lua/llex.c delete mode 100644 script/lua/llex.h delete mode 100644 script/lua/llimits.h delete mode 100644 script/lua/lmathlib.c delete mode 100644 script/lua/lmem.c delete mode 100644 script/lua/lmem.h delete mode 100644 script/lua/loadlib.c delete mode 100644 script/lua/lobject.c delete mode 100644 script/lua/lobject.h delete mode 100644 script/lua/lopcodes.c delete mode 100644 script/lua/lopcodes.h delete mode 100644 script/lua/loslib.c delete mode 100644 script/lua/lparser.c delete mode 100644 script/lua/lparser.h delete mode 100644 script/lua/lstate.c delete mode 100644 script/lua/lstate.h delete mode 100644 script/lua/lstring.c delete mode 100644 script/lua/lstring.h delete mode 100644 script/lua/lstrlib.c delete mode 100644 script/lua/ltable.c delete mode 100644 script/lua/ltable.h delete mode 100644 script/lua/ltablib.c delete mode 100644 script/lua/ltm.c delete mode 100644 script/lua/ltm.h delete mode 100644 script/lua/lua.h delete mode 100644 script/lua/luaconf.h delete mode 100644 script/lua/lualib.h delete mode 100644 script/lua/lundump.c delete mode 100644 script/lua/lundump.h delete mode 100644 script/lua/lvm.c delete mode 100644 script/lua/lvm.h delete mode 100644 script/lua/lzio.c delete mode 100644 script/lua/lzio.h delete mode 100644 util/osdetect.lua diff --git a/ChangeLog b/ChangeLog index fdca53d01..aca4ef788 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,66 @@ +2009-09-26 Robert Millan + + * conf/common.rmk (pkglib_MODULES): Remove `lua.mod'. + (lua_mod_SOURCES, lua_mod_CFLAGS, lua_mod_LDFLAGS): Remove. + + * util/osdetect.lua: Remove. + * script/lua/lauxlib.c: Likewise. + * script/lua/ldebug.c: Likewise. + * script/lua/grub_main.c: Likewise. + * script/lua/lauxlib.h: Likewise. + * script/lua/ldebug.h: Likewise. + * script/lua/ltablib.c: Likewise. + * script/lua/liolib.c: Likewise. + * script/lua/lstrlib.c: Likewise. + * script/lua/lualib.h: Likewise. + * script/lua/ldo.c: Likewise. + * script/lua/ldump.c: Likewise. + * script/lua/ldo.h: Likewise. + * script/lua/loslib.c: Likewise. + * script/lua/lundump.c: Likewise. + * script/lua/grub_lib.c: Likewise. + * script/lua/ldblib.c: Likewise. + * script/lua/lundump.h: Likewise. + * script/lua/lmem.c: Likewise. + * script/lua/grub_lib.h: Likewise. + * script/lua/lmathlib.c: Likewise. + * script/lua/lstate.c: Likewise. + * script/lua/ltm.c: Likewise. + * script/lua/lvm.c: Likewise. + * script/lua/lmem.h: Likewise. + * script/lua/lstate.h: Likewise. + * script/lua/ltm.h: Likewise. + * script/lua/ltable.c: Likewise. + * script/lua/lvm.h: Likewise. + * script/lua/llex.c: Likewise. + * script/lua/lgc.c: Likewise. + * script/lua/grub_lua.h: Likewise. + * script/lua/loadlib.c: Likewise. + * script/lua/lfunc.c: Likewise. + * script/lua/lopcodes.c: Likewise. + * script/lua/lparser.c: Likewise. + * script/lua/ltable.h: Likewise. + * script/lua/llex.h: Likewise. + * script/lua/lgc.h: Likewise. + * script/lua/lfunc.h: Likewise. + * script/lua/lbaselib.c: Likewise. + * script/lua/lopcodes.h: Likewise. + * script/lua/lparser.h: Likewise. + * script/lua/lzio.c: Likewise. + * script/lua/linit.c: Likewise. + * script/lua/lobject.c: Likewise. + * script/lua/llimits.h: Likewise. + * script/lua/lstring.c: Likewise. + * script/lua/lzio.h: Likewise. + * script/lua/lapi.c: Likewise. + * script/lua/lcode.c: Likewise. + * script/lua/lua.h: Likewise. + * script/lua/lobject.h: Likewise. + * script/lua/lstring.h: Likewise. + * script/lua/lapi.h: Likewise. + * script/lua/lcode.h: Likewise. + * script/lua/luaconf.h: Likewise. + 2009-09-26 Colin Watson * docs/grub.texi (Command-line and menu entry commands): Document diff --git a/conf/common.rmk b/conf/common.rmk index e18dd1052..26407d06b 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -367,7 +367,7 @@ pkglib_MODULES += minicmd.mod extcmd.mod hello.mod handler.mod \ fs_file.mod fs_uuid.mod configfile.mod echo.mod \ terminfo.mod test.mod blocklist.mod hexdump.mod \ read.mod sleep.mod loadenv.mod crc.mod parttool.mod \ - msdospart.mod memrw.mod normal.mod sh.mod lua.mod \ + msdospart.mod memrw.mod normal.mod sh.mod \ gptsync.mod true.mod probe.mod password.mod \ keystatus.mod @@ -536,23 +536,6 @@ sh_mod_SOURCES = script/sh/main.c script/sh/script.c script/sh/execute.c \ sh_mod_CFLAGS = $(COMMON_CFLAGS) sh_mod_LDFLAGS = $(COMMON_LDFLAGS) -# For lua.mod. -lua_mod_SOURCES = script/lua/lapi.c script/lua/lcode.c script/lua/ldebug.c \ - script/lua/ldo.c script/lua/ldump.c script/lua/lfunc.c \ - script/lua/lgc.c script/lua/llex.c script/lua/lmem.c \ - script/lua/lobject.c script/lua/lopcodes.c script/lua/lparser.c \ - script/lua/lstate.c script/lua/lstring.c script/lua/ltable.c \ - script/lua/ltm.c script/lua/lundump.c script/lua/lvm.c \ - script/lua/lzio.c script/lua/lauxlib.c script/lua/lbaselib.c \ - script/lua/linit.c script/lua/ltablib.c script/lua/lstrlib.c \ - script/lua/grub_main.c script/lua/grub_lib.c -lua_mod_CFLAGS = $(COMMON_CFLAGS) -lua_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# Extra libraries for lua -# script/lua/lmathlib.c script/lua/loslib.c script/lua/liolib.c -# script/lua/ldblib.c script/lua/loadlib.c - # Common Video Subsystem specific modules. pkglib_MODULES += video.mod videotest.mod bitmap.mod tga.mod jpeg.mod \ png.mod font.mod gfxterm.mod video_fb.mod diff --git a/script/lua/grub_lib.c b/script/lua/grub_lib.c deleted file mode 100644 index d26f19337..000000000 --- a/script/lua/grub_lib.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 . - */ - -#include "lua.h" -#include "lauxlib.h" -#include "lualib.h" -#include "grub_lib.h" - -#include -#include -#include -#include -#include -#include - -static int -save_errno (lua_State *state) -{ - int saved_errno; - - saved_errno = grub_errno; - grub_errno = 0; - - lua_pushinteger (state, saved_errno); - lua_setfield (state, LUA_GLOBALSINDEX, "grub_errno"); - - if (saved_errno) - lua_pushstring (state, grub_errmsg); - else - lua_pushnil (state); - - lua_setfield (state, LUA_GLOBALSINDEX, "grub_errmsg"); - - return saved_errno; -} - -static int -push_result (lua_State *state) -{ - lua_pushinteger (state, save_errno (state)); - return 1; -} - -static int -grub_lua_run (lua_State *state) -{ - int n; - char **args; - const char *s; - - s = luaL_checkstring (state, 1); - if ((! grub_parser_split_cmdline (s, 0, &n, &args)) - && (n >= 0)) - { - grub_command_t cmd; - - cmd = grub_command_find (args[0]); - if (cmd) - (cmd->func) (cmd, n, &args[1]); - else - grub_error (GRUB_ERR_FILE_NOT_FOUND, "command not found"); - - grub_free (args[0]); - grub_free (args); - } - - return push_result (state); -} - -static int -grub_lua_getenv (lua_State *state) -{ - int n, i; - - n = lua_gettop (state); - for (i = 1; i <= n; i++) - { - const char *name, *value; - - name = luaL_checkstring (state, i); - value = grub_env_get (name); - if (value) - lua_pushstring (state, value); - else - lua_pushnil (state); - } - - return n; -} - -static int -grub_lua_setenv (lua_State *state) -{ - const char *name, *value; - - name = luaL_checkstring (state, 1); - value = luaL_checkstring (state, 2); - - if (name[0]) - grub_env_set (name, value); - - return 0; -} - -static int -grub_lua_enum_device (lua_State *state) -{ - auto int enum_device (const char *name); - int enum_device (const char *name) - { - int result; - grub_device_t dev; - - result = 0; - dev = grub_device_open (name); - if (dev) - { - grub_fs_t fs; - - fs = grub_fs_probe (dev); - if (fs) - { - lua_pushvalue (state, 1); - lua_pushstring (state, name); - lua_pushstring (state, fs->name); - if (! fs->uuid) - lua_pushnil (state); - else - { - int err; - char *uuid; - - err = fs->uuid (dev, &uuid); - if (err) - { - grub_errno = 0; - lua_pushnil (state); - } - else - { - lua_pushstring (state, uuid); - grub_free (uuid); - } - } - - lua_call (state, 3, 1); - result = lua_tointeger (state, -1); - lua_pop (state, 1); - } - else - grub_errno = 0; - grub_device_close (dev); - } - else - grub_errno = 0; - - return result; - } - - luaL_checktype (state, 1, LUA_TFUNCTION); - grub_device_iterate (enum_device); - return push_result (state); -} - -static int -grub_lua_enum_file (lua_State *state) -{ - char *device_name; - const char *arg; - grub_device_t dev; - - auto int enum_file (const char *name, const struct grub_dirhook_info *info); - int enum_file (const char *name, const struct grub_dirhook_info *info) - { - int result; - - lua_pushvalue (state, 1); - lua_pushstring (state, name); - lua_pushinteger (state, info->dir != 0); - lua_call (state, 2, 1); - result = lua_tointeger (state, -1); - lua_pop (state, 1); - - return result; - } - - luaL_checktype (state, 1, LUA_TFUNCTION); - arg = luaL_checkstring (state, 2); - device_name = grub_file_get_device_name (arg); - dev = grub_device_open (device_name); - if (dev) - { - grub_fs_t fs; - const char *path; - - fs = grub_fs_probe (dev); - path = grub_strchr (arg, ')'); - if (! path) - path = arg; - else - path++; - - if (fs) - { - (fs->dir) (dev, path, enum_file); - } - - grub_device_close (dev); - } - - grub_free (device_name); - - return push_result (state); -} - -static int -grub_lua_file_open (lua_State *state) -{ - grub_file_t file; - const char *name; - - name = luaL_checkstring (state, 1); - file = grub_file_open (name); - save_errno (state); - - if (! file) - return 0; - - lua_pushlightuserdata (state, file); - return 1; -} - -static int -grub_lua_file_close (lua_State *state) -{ - grub_file_t file; - - luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); - file = lua_touserdata (state, 1); - grub_file_close (file); - - return push_result (state); -} - -static int -grub_lua_file_seek (lua_State *state) -{ - grub_file_t file; - grub_off_t offset; - - luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); - file = lua_touserdata (state, 1); - offset = luaL_checkinteger (state, 2); - - offset = grub_file_seek (file, offset); - save_errno (state); - - lua_pushinteger (state, offset); - return 1; -} - -static int -grub_lua_file_read (lua_State *state) -{ - grub_file_t file; - luaL_Buffer b; - int n; - - luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); - file = lua_touserdata (state, 1); - n = luaL_checkinteger (state, 2); - - luaL_buffinit (state, &b); - while (n) - { - char *p; - int nr; - - nr = (n > LUAL_BUFFERSIZE) ? LUAL_BUFFERSIZE : n; - p = luaL_prepbuffer (&b); - - nr = grub_file_read (file, p, nr); - if (nr <= 0) - break; - - luaL_addsize (&b, nr); - n -= nr; - } - - save_errno (state); - luaL_pushresult (&b); - return 1; -} - -static int -grub_lua_file_getline (lua_State *state) -{ - grub_file_t file; - char *line; - - luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); - file = lua_touserdata (state, 1); - - line = grub_file_getline (file); - save_errno (state); - - if (! line) - return 0; - - lua_pushstring (state, line); - grub_free (line); - return 1; -} - -static int -grub_lua_file_getsize (lua_State *state) -{ - grub_file_t file; - - luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); - file = lua_touserdata (state, 1); - - lua_pushinteger (state, file->size); - return 1; -} - -static int -grub_lua_file_getpos (lua_State *state) -{ - grub_file_t file; - - luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); - file = lua_touserdata (state, 1); - - lua_pushinteger (state, file->offset); - return 1; -} - -static int -grub_lua_file_eof (lua_State *state) -{ - grub_file_t file; - - luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); - file = lua_touserdata (state, 1); - - lua_pushboolean (state, file->offset >= file->size); - return 1; -} - -static int -grub_lua_file_exist (lua_State *state) -{ - grub_file_t file; - const char *name; - int result; - - result = 0; - name = luaL_checkstring (state, 1); - file = grub_file_open (name); - if (file) - { - result++; - grub_file_close (file); - } - else - grub_errno = 0; - - lua_pushboolean (state, result); - return 1; -} - -static int -grub_lua_add_menu (lua_State *state) -{ - int n; - const char *source; - - source = luaL_checklstring (state, 1, 0); - n = lua_gettop (state) - 1; - if (n > 0) - { - const char *args[sizeof (char *) * n]; - char *p; - int i; - - for (i = 0; i < n; i++) - args[i] = luaL_checkstring (state, 2 + i); - - p = grub_strdup (source); - if (! p) - return push_result (state); - - grub_normal_add_menu_entry (n, args, p); - } - else - { - lua_pushstring (state, "not enough parameter"); - lua_error (state); - } - - return push_result (state); -} - -luaL_Reg grub_lua_lib[] = - { - {"run", grub_lua_run}, - {"getenv", grub_lua_getenv}, - {"setenv", grub_lua_setenv}, - {"enum_device", grub_lua_enum_device}, - {"enum_file", grub_lua_enum_file}, - {"file_open", grub_lua_file_open}, - {"file_close", grub_lua_file_close}, - {"file_seek", grub_lua_file_seek}, - {"file_read", grub_lua_file_read}, - {"file_getline", grub_lua_file_getline}, - {"file_getsize", grub_lua_file_getsize}, - {"file_getpos", grub_lua_file_getpos}, - {"file_eof", grub_lua_file_eof}, - {"file_exist", grub_lua_file_exist}, - {"add_menu", grub_lua_add_menu}, - {0, 0} - }; diff --git a/script/lua/grub_lib.h b/script/lua/grub_lib.h deleted file mode 100644 index 2253a4145..000000000 --- a/script/lua/grub_lib.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 . - */ - -#ifndef GRUB_LUA_LIB_HEADER -#define GRUB_LUA_LIB_HEADER 1 - -extern luaL_Reg grub_lua_lib[]; - -#endif diff --git a/script/lua/grub_lua.h b/script/lua/grub_lua.h deleted file mode 100644 index 78e6546c7..000000000 --- a/script/lua/grub_lua.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 . - */ - -#ifndef GRUB_LUA_HEADER -#define GRUB_LUA_HEADER 1 - -#include -#include -#include -#include -#include - -#define INT_MAX GRUB_LONG_MAX -#define UCHAR_MAX 255 -#define SHRT_MAX 32767 - -#undef UNUSED -#define UNUSED (void) - -#define memcpy grub_memcpy -#define memcmp grub_memcmp -#define strcpy grub_strcpy -#define strstr grub_strstr -#define strchr grub_strchr -#define strlen grub_strlen -#define strtoul grub_strtoul -#define strtod(s,e) grub_strtoul(s,e,0) -#define sprintf grub_sprintf -#define strncpy grub_strncpy -#define strcat grub_strcat -#define strncat grub_strncat -#define strcoll grub_strcmp -#define strcmp grub_strcmp -#define tolower grub_tolower -#define toupper grub_toupper - -#define malloc grub_malloc -#define realloc grub_realloc -#define free grub_free - -#define exit(a) grub_exit() -#define jmp_buf grub_jmp_buf -#define setjmp grub_setjmp -#define longjmp grub_longjmp - -#define fputs(s,f) grub_printf("%s", s) - -#define isdigit grub_isdigit -#define isalpha grub_isalpha -#define isspace grub_isspace - -static inline int -isalnum (int c) -{ - return (isalpha (c) || isdigit (c)); -} - -static inline int -iscntrl (int c) -{ - return ((c <= 0x1f) || (c == 0x7f)); -} - -static inline int -isupper (int c) -{ - return ((c >= 'A') && (c <= 'Z')); -} - -static inline int -islower (int c) -{ - return ((c >= 'a') && (c <= 'z')); -} - -static inline int -ispunct (int c) -{ - return ((! isspace (c)) && (! isalnum (c))); -} - -static inline int -isxdigit (int c) -{ - return (isdigit (c) || ((c >= 'a') && (c <= 'f')) || - ((c >= 'A') && (c <= 'F'))); -} - -static inline int -abs (int c) -{ - return (c >= 0) ? : -c; -} - -int strcspn (const char *s1, const char *s2); -char *strpbrk (const char *s1, const char *s2); -void *memchr (const void *s, int c, size_t n); - -#endif diff --git a/script/lua/grub_main.c b/script/lua/grub_main.c deleted file mode 100644 index b39141f75..000000000 --- a/script/lua/grub_main.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 . - */ - -#include "lua.h" -#include "lauxlib.h" -#include "lualib.h" -#include "grub_lib.h" - -#include -#include - -static const char * -scan_str (const char *s1, const char *s2) -{ - while (*s1) - { - const char *p = s2; - - while (*p) - { - if (*s1 == *p) - return s1; - p++; - } - - s1++; - } - - return s1; -} - -int -strcspn (const char *s1, const char *s2) -{ - const char *r; - - r = scan_str (s1, s2); - return r - s1; -} - -char * -strpbrk (const char *s1, const char *s2) -{ - const char *r; - - r = scan_str (s1, s2); - return (*r) ? (char *) r : 0; -} - -void * -memchr (const void *s, int c, size_t n) -{ - const unsigned char *p = s; - - while (n) - { - if (*p == c) - return (void *) p; - - n--; - p++; - } - - return 0; -} - -static lua_State *state; - -/* Call `grub_error' to report a Lua error. The error message string must be - on the top of the Lua stack (at index -1). The error message is popped off - the Lua stack before this function returns. */ -static void -handle_lua_error (const char *error_type) -{ - const char *error_msg; - error_msg = lua_tostring (state, -1); - if (error_msg == NULL) - error_msg = "(error message not a string)"; - grub_error (GRUB_ERR_BAD_ARGUMENT, "%s: %s", error_type, error_msg); - /* Pop the error message. */ - lua_pop (state, 1); -} - -static grub_err_t -grub_lua_parse_line (char *line, grub_reader_getline_t getline) -{ - int r; - char *old_line = 0; - - lua_settop(state, 0); - while (1) - { - r = luaL_loadbuffer (state, line, grub_strlen (line), "=grub"); - if (! r) - { - /* No error: Execute the statement. */ - r = lua_pcall (state, 0, 0, 0); - if (r) - { - handle_lua_error ("Lua"); - break; - } - else - { - grub_free (old_line); - return grub_errno; - } - } - - if (r == LUA_ERRSYNTAX) - { - /* Check whether the syntax error is a result of an incomplete - statement. If it is, then try to complete the statement by - reading more lines. */ - size_t lmsg; - const char *msg = lua_tolstring (state, -1, &lmsg); - const char *tp = msg + lmsg - (sizeof (LUA_QL ("")) - 1); - if (grub_strstr (msg, LUA_QL ("")) == tp) - { - char *n, *t; - int len; - - /* Discard the error message. */ - lua_pop (state, 1); - /* Try to read another line to complete the statement. */ - if ((getline (&n, 1)) || (! n)) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "incomplete command"); - break; - } - - /* More input was available: Add it to the current statement - contents. */ - len = grub_strlen (line); - t = grub_malloc (len + grub_strlen (n) + 2); - if (! t) - break; - - grub_strcpy (t, line); - t[len] = '\n'; - grub_strcpy (t + len + 1, n); - grub_free (old_line); - line = old_line = t; - /* Try again to execute the statement now that more input has - been appended. */ - continue; - } - /* The syntax error was not the result of an incomplete line. */ - handle_lua_error ("Lua syntax error"); - } - else - { - /* Handle errors other than syntax errors (out of memory, etc.). */ - handle_lua_error ("Lua parser failed"); - } - - break; - } - - grub_free (old_line); - lua_gc (state, LUA_GCCOLLECT, 0); - - return grub_errno; -} - -static struct grub_parser grub_lua_parser = - { - .name = "lua", - .parse_line = grub_lua_parse_line - }; - -GRUB_MOD_INIT(lua) -{ - (void) mod; - - state = lua_open (); - if (state) - { - lua_gc (state, LUA_GCSTOP, 0); - luaL_openlibs (state); - luaL_register (state, "grub", grub_lua_lib); - lua_gc (state, LUA_GCRESTART, 0); - grub_parser_register ("lua", &grub_lua_parser); - } -} - -GRUB_MOD_FINI(lua) -{ - if (state) - { - grub_parser_unregister (&grub_lua_parser); - lua_close (state); - } -} diff --git a/script/lua/lapi.c b/script/lua/lapi.c deleted file mode 100644 index 2eaf45c66..000000000 --- a/script/lua/lapi.c +++ /dev/null @@ -1,1088 +0,0 @@ -/* -** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ -** Lua API -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#include -#include -#include -#endif - -#define lapi_c -#define LUA_CORE - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" - - - -const char lua_ident[] = - "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" - "$Authors: " LUA_AUTHORS " $\n" - "$URL: www.lua.org $\n"; - - - -#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) - -#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) - -#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} - - - -static TValue *index2adr (lua_State *L, int idx) { - if (idx > 0) { - TValue *o = L->base + (idx - 1); - api_check(L, idx <= L->ci->top - L->base); - if (o >= L->top) return cast(TValue *, luaO_nilobject); - else return o; - } - else if (idx > LUA_REGISTRYINDEX) { - api_check(L, idx != 0 && -idx <= L->top - L->base); - return L->top + idx; - } - else switch (idx) { /* pseudo-indices */ - case LUA_REGISTRYINDEX: return registry(L); - case LUA_ENVIRONINDEX: { - Closure *func = curr_func(L); - sethvalue(L, &L->env, func->c.env); - return &L->env; - } - case LUA_GLOBALSINDEX: return gt(L); - default: { - Closure *func = curr_func(L); - idx = LUA_GLOBALSINDEX - idx; - return (idx <= func->c.nupvalues) - ? &func->c.upvalue[idx-1] - : cast(TValue *, luaO_nilobject); - } - } -} - - -static Table *getcurrenv (lua_State *L) { - if (L->ci == L->base_ci) /* no enclosing function? */ - return hvalue(gt(L)); /* use global table as environment */ - else { - Closure *func = curr_func(L); - return func->c.env; - } -} - - -void luaA_pushobject (lua_State *L, const TValue *o) { - setobj2s(L, L->top, o); - api_incr_top(L); -} - - -LUA_API int lua_checkstack (lua_State *L, int size) { - int res = 1; - lua_lock(L); - if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) - res = 0; /* stack overflow */ - else if (size > 0) { - luaD_checkstack(L, size); - if (L->ci->top < L->top + size) - L->ci->top = L->top + size; - } - lua_unlock(L); - return res; -} - - -LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { - int i; - if (from == to) return; - lua_lock(to); - api_checknelems(from, n); - api_check(from, G(from) == G(to)); - api_check(from, to->ci->top - to->top >= n); - from->top -= n; - for (i = 0; i < n; i++) { - setobj2s(to, to->top++, from->top + i); - } - lua_unlock(to); -} - - -LUA_API void lua_setlevel (lua_State *from, lua_State *to) { - to->nCcalls = from->nCcalls; -} - - -LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { - lua_CFunction old; - lua_lock(L); - old = G(L)->panic; - G(L)->panic = panicf; - lua_unlock(L); - return old; -} - - -LUA_API lua_State *lua_newthread (lua_State *L) { - lua_State *L1; - lua_lock(L); - luaC_checkGC(L); - L1 = luaE_newthread(L); - setthvalue(L, L->top, L1); - api_incr_top(L); - lua_unlock(L); - luai_userstatethread(L, L1); - return L1; -} - - - -/* -** basic stack manipulation -*/ - - -LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top - L->base); -} - - -LUA_API void lua_settop (lua_State *L, int idx) { - lua_lock(L); - if (idx >= 0) { - api_check(L, idx <= L->stack_last - L->base); - while (L->top < L->base + idx) - setnilvalue(L->top++); - L->top = L->base + idx; - } - else { - api_check(L, -(idx+1) <= (L->top - L->base)); - L->top += idx+1; /* `subtract' index (index is negative) */ - } - lua_unlock(L); -} - - -LUA_API void lua_remove (lua_State *L, int idx) { - StkId p; - lua_lock(L); - p = index2adr(L, idx); - api_checkvalidindex(L, p); - while (++p < L->top) setobjs2s(L, p-1, p); - L->top--; - lua_unlock(L); -} - - -LUA_API void lua_insert (lua_State *L, int idx) { - StkId p; - StkId q; - lua_lock(L); - p = index2adr(L, idx); - api_checkvalidindex(L, p); - for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); - setobjs2s(L, p, L->top); - lua_unlock(L); -} - - -LUA_API void lua_replace (lua_State *L, int idx) { - StkId o; - lua_lock(L); - /* explicit test for incompatible code */ - if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) - luaG_runerror(L, "no calling environment"); - api_checknelems(L, 1); - o = index2adr(L, idx); - api_checkvalidindex(L, o); - if (idx == LUA_ENVIRONINDEX) { - Closure *func = curr_func(L); - api_check(L, ttistable(L->top - 1)); - func->c.env = hvalue(L->top - 1); - luaC_barrier(L, func, L->top - 1); - } - else { - setobj(L, o, L->top - 1); - if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ - luaC_barrier(L, curr_func(L), L->top - 1); - } - L->top--; - lua_unlock(L); -} - - -LUA_API void lua_pushvalue (lua_State *L, int idx) { - lua_lock(L); - setobj2s(L, L->top, index2adr(L, idx)); - api_incr_top(L); - lua_unlock(L); -} - - - -/* -** access functions (stack -> C) -*/ - - -LUA_API int lua_type (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); -} - - -LUA_API const char *lua_typename (lua_State *L, int t) { - UNUSED(L); - return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; -} - - -LUA_API int lua_iscfunction (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return iscfunction(o); -} - - -LUA_API int lua_isnumber (lua_State *L, int idx) { - TValue n; - const TValue *o = index2adr(L, idx); - return tonumber(o, &n); -} - - -LUA_API int lua_isstring (lua_State *L, int idx) { - int t = lua_type(L, idx); - return (t == LUA_TSTRING || t == LUA_TNUMBER); -} - - -LUA_API int lua_isuserdata (lua_State *L, int idx) { - const TValue *o = index2adr(L, idx); - return (ttisuserdata(o) || ttislightuserdata(o)); -} - - -LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { - StkId o1 = index2adr(L, index1); - StkId o2 = index2adr(L, index2); - return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 - : luaO_rawequalObj(o1, o2); -} - - -LUA_API int lua_equal (lua_State *L, int index1, int index2) { - StkId o1, o2; - int i; - lua_lock(L); /* may call tag method */ - o1 = index2adr(L, index1); - o2 = index2adr(L, index2); - i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); - lua_unlock(L); - return i; -} - - -LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { - StkId o1, o2; - int i; - lua_lock(L); /* may call tag method */ - o1 = index2adr(L, index1); - o2 = index2adr(L, index2); - i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 - : luaV_lessthan(L, o1, o2); - lua_unlock(L); - return i; -} - - - -LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { - TValue n; - const TValue *o = index2adr(L, idx); - if (tonumber(o, &n)) - return nvalue(o); - else - return 0; -} - - -LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { - TValue n; - const TValue *o = index2adr(L, idx); - if (tonumber(o, &n)) { - lua_Integer res; - lua_Number num = nvalue(o); - lua_number2integer(res, num); - return res; - } - else - return 0; -} - - -LUA_API int lua_toboolean (lua_State *L, int idx) { - const TValue *o = index2adr(L, idx); - return !l_isfalse(o); -} - - -LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { - StkId o = index2adr(L, idx); - if (!ttisstring(o)) { - lua_lock(L); /* `luaV_tostring' may create a new string */ - if (!luaV_tostring(L, o)) { /* conversion failed? */ - if (len != NULL) *len = 0; - lua_unlock(L); - return NULL; - } - luaC_checkGC(L); - o = index2adr(L, idx); /* previous call may reallocate the stack */ - lua_unlock(L); - } - if (len != NULL) *len = tsvalue(o)->len; - return svalue(o); -} - - -LUA_API size_t lua_objlen (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - switch (ttype(o)) { - case LUA_TSTRING: return tsvalue(o)->len; - case LUA_TUSERDATA: return uvalue(o)->len; - case LUA_TTABLE: return luaH_getn(hvalue(o)); - case LUA_TNUMBER: { - size_t l; - lua_lock(L); /* `luaV_tostring' may create a new string */ - l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); - lua_unlock(L); - return l; - } - default: return 0; - } -} - - -LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; -} - - -LUA_API void *lua_touserdata (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - switch (ttype(o)) { - case LUA_TUSERDATA: return (rawuvalue(o) + 1); - case LUA_TLIGHTUSERDATA: return pvalue(o); - default: return NULL; - } -} - - -LUA_API lua_State *lua_tothread (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return (!ttisthread(o)) ? NULL : thvalue(o); -} - - -LUA_API const void *lua_topointer (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - switch (ttype(o)) { - case LUA_TTABLE: return hvalue(o); - case LUA_TFUNCTION: return clvalue(o); - case LUA_TTHREAD: return thvalue(o); - case LUA_TUSERDATA: - case LUA_TLIGHTUSERDATA: - return lua_touserdata(L, idx); - default: return NULL; - } -} - - - -/* -** push functions (C -> stack) -*/ - - -LUA_API void lua_pushnil (lua_State *L) { - lua_lock(L); - setnilvalue(L->top); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { - lua_lock(L); - setnvalue(L->top, n); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { - lua_lock(L); - setnvalue(L->top, cast_num(n)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { - lua_lock(L); - luaC_checkGC(L); - setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushstring (lua_State *L, const char *s) { - if (s == NULL) - lua_pushnil(L); - else - lua_pushlstring(L, s, strlen(s)); -} - - -LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, - va_list argp) { - const char *ret; - lua_lock(L); - luaC_checkGC(L); - ret = luaO_pushvfstring(L, fmt, argp); - lua_unlock(L); - return ret; -} - - -LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { - const char *ret; - va_list argp; - lua_lock(L); - luaC_checkGC(L); - va_start(argp, fmt); - ret = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - lua_unlock(L); - return ret; -} - - -LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { - Closure *cl; - lua_lock(L); - luaC_checkGC(L); - api_checknelems(L, n); - cl = luaF_newCclosure(L, n, getcurrenv(L)); - cl->c.f = fn; - L->top -= n; - while (n--) - setobj2n(L, &cl->c.upvalue[n], L->top+n); - setclvalue(L, L->top, cl); - lua_assert(iswhite(obj2gco(cl))); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushboolean (lua_State *L, int b) { - lua_lock(L); - setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { - lua_lock(L); - setpvalue(L->top, p); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API int lua_pushthread (lua_State *L) { - lua_lock(L); - setthvalue(L, L->top, L); - api_incr_top(L); - lua_unlock(L); - return (G(L)->mainthread == L); -} - - - -/* -** get functions (Lua -> stack) -*/ - - -LUA_API void lua_gettable (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2adr(L, idx); - api_checkvalidindex(L, t); - luaV_gettable(L, t, L->top - 1, L->top - 1); - lua_unlock(L); -} - - -LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { - StkId t; - TValue key; - lua_lock(L); - t = index2adr(L, idx); - api_checkvalidindex(L, t); - setsvalue(L, &key, luaS_new(L, k)); - luaV_gettable(L, t, &key, L->top); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_rawget (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2adr(L, idx); - api_check(L, ttistable(t)); - setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); - lua_unlock(L); -} - - -LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { - StkId o; - lua_lock(L); - o = index2adr(L, idx); - api_check(L, ttistable(o)); - setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { - lua_lock(L); - luaC_checkGC(L); - sethvalue(L, L->top, luaH_new(L, narray, nrec)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API int lua_getmetatable (lua_State *L, int objindex) { - const TValue *obj; - Table *mt = NULL; - int res; - lua_lock(L); - obj = index2adr(L, objindex); - switch (ttype(obj)) { - case LUA_TTABLE: - mt = hvalue(obj)->metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(obj)->metatable; - break; - default: - mt = G(L)->mt[ttype(obj)]; - break; - } - if (mt == NULL) - res = 0; - else { - sethvalue(L, L->top, mt); - api_incr_top(L); - res = 1; - } - lua_unlock(L); - return res; -} - - -LUA_API void lua_getfenv (lua_State *L, int idx) { - StkId o; - lua_lock(L); - o = index2adr(L, idx); - api_checkvalidindex(L, o); - switch (ttype(o)) { - case LUA_TFUNCTION: - sethvalue(L, L->top, clvalue(o)->c.env); - break; - case LUA_TUSERDATA: - sethvalue(L, L->top, uvalue(o)->env); - break; - case LUA_TTHREAD: - setobj2s(L, L->top, gt(thvalue(o))); - break; - default: - setnilvalue(L->top); - break; - } - api_incr_top(L); - lua_unlock(L); -} - - -/* -** set functions (stack -> Lua) -*/ - - -LUA_API void lua_settable (lua_State *L, int idx) { - StkId t; - lua_lock(L); - api_checknelems(L, 2); - t = index2adr(L, idx); - api_checkvalidindex(L, t); - luaV_settable(L, t, L->top - 2, L->top - 1); - L->top -= 2; /* pop index and value */ - lua_unlock(L); -} - - -LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { - StkId t; - TValue key; - lua_lock(L); - api_checknelems(L, 1); - t = index2adr(L, idx); - api_checkvalidindex(L, t); - setsvalue(L, &key, luaS_new(L, k)); - luaV_settable(L, t, &key, L->top - 1); - L->top--; /* pop value */ - lua_unlock(L); -} - - -LUA_API void lua_rawset (lua_State *L, int idx) { - StkId t; - lua_lock(L); - api_checknelems(L, 2); - t = index2adr(L, idx); - api_check(L, ttistable(t)); - setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); - luaC_barriert(L, hvalue(t), L->top-1); - L->top -= 2; - lua_unlock(L); -} - - -LUA_API void lua_rawseti (lua_State *L, int idx, int n) { - StkId o; - lua_lock(L); - api_checknelems(L, 1); - o = index2adr(L, idx); - api_check(L, ttistable(o)); - setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); - luaC_barriert(L, hvalue(o), L->top-1); - L->top--; - lua_unlock(L); -} - - -LUA_API int lua_setmetatable (lua_State *L, int objindex) { - TValue *obj; - Table *mt; - lua_lock(L); - api_checknelems(L, 1); - obj = index2adr(L, objindex); - api_checkvalidindex(L, obj); - if (ttisnil(L->top - 1)) - mt = NULL; - else { - api_check(L, ttistable(L->top - 1)); - mt = hvalue(L->top - 1); - } - switch (ttype(obj)) { - case LUA_TTABLE: { - hvalue(obj)->metatable = mt; - if (mt) - luaC_objbarriert(L, hvalue(obj), mt); - break; - } - case LUA_TUSERDATA: { - uvalue(obj)->metatable = mt; - if (mt) - luaC_objbarrier(L, rawuvalue(obj), mt); - break; - } - default: { - G(L)->mt[ttype(obj)] = mt; - break; - } - } - L->top--; - lua_unlock(L); - return 1; -} - - -LUA_API int lua_setfenv (lua_State *L, int idx) { - StkId o; - int res = 1; - lua_lock(L); - api_checknelems(L, 1); - o = index2adr(L, idx); - api_checkvalidindex(L, o); - api_check(L, ttistable(L->top - 1)); - switch (ttype(o)) { - case LUA_TFUNCTION: - clvalue(o)->c.env = hvalue(L->top - 1); - break; - case LUA_TUSERDATA: - uvalue(o)->env = hvalue(L->top - 1); - break; - case LUA_TTHREAD: - sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); - break; - default: - res = 0; - break; - } - if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); - L->top--; - lua_unlock(L); - return res; -} - - -/* -** `load' and `call' functions (run Lua code) -*/ - - -#define adjustresults(L,nres) \ - { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } - - -#define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) - - -LUA_API void lua_call (lua_State *L, int nargs, int nresults) { - StkId func; - lua_lock(L); - api_checknelems(L, nargs+1); - checkresults(L, nargs, nresults); - func = L->top - (nargs+1); - luaD_call(L, func, nresults); - adjustresults(L, nresults); - lua_unlock(L); -} - - - -/* -** Execute a protected call. -*/ -struct CallS { /* data to `f_call' */ - StkId func; - int nresults; -}; - - -static void f_call (lua_State *L, void *ud) { - struct CallS *c = cast(struct CallS *, ud); - luaD_call(L, c->func, c->nresults); -} - - - -LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { - struct CallS c; - int status; - ptrdiff_t func; - lua_lock(L); - api_checknelems(L, nargs+1); - checkresults(L, nargs, nresults); - if (errfunc == 0) - func = 0; - else { - StkId o = index2adr(L, errfunc); - api_checkvalidindex(L, o); - func = savestack(L, o); - } - c.func = L->top - (nargs+1); /* function to be called */ - c.nresults = nresults; - status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); - adjustresults(L, nresults); - lua_unlock(L); - return status; -} - - -/* -** Execute a protected C call. -*/ -struct CCallS { /* data to `f_Ccall' */ - lua_CFunction func; - void *ud; -}; - - -static void f_Ccall (lua_State *L, void *ud) { - struct CCallS *c = cast(struct CCallS *, ud); - Closure *cl; - cl = luaF_newCclosure(L, 0, getcurrenv(L)); - cl->c.f = c->func; - setclvalue(L, L->top, cl); /* push function */ - api_incr_top(L); - setpvalue(L->top, c->ud); /* push only argument */ - api_incr_top(L); - luaD_call(L, L->top - 2, 0); -} - - -LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { - struct CCallS c; - int status; - lua_lock(L); - c.func = func; - c.ud = ud; - status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); - lua_unlock(L); - return status; -} - - -LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, - const char *chunkname) { - ZIO z; - int status; - lua_lock(L); - if (!chunkname) chunkname = "?"; - luaZ_init(L, &z, reader, data); - status = luaD_protectedparser(L, &z, chunkname); - lua_unlock(L); - return status; -} - - -LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { - int status; - TValue *o; - lua_lock(L); - api_checknelems(L, 1); - o = L->top - 1; - if (isLfunction(o)) - status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); - else - status = 1; - lua_unlock(L); - return status; -} - - -LUA_API int lua_status (lua_State *L) { - return L->status; -} - - -/* -** Garbage-collection function -*/ - -LUA_API int lua_gc (lua_State *L, int what, int data) { - int res = 0; - global_State *g; - lua_lock(L); - g = G(L); - switch (what) { - case LUA_GCSTOP: { - g->GCthreshold = MAX_LUMEM; - break; - } - case LUA_GCRESTART: { - g->GCthreshold = g->totalbytes; - break; - } - case LUA_GCCOLLECT: { - luaC_fullgc(L); - break; - } - case LUA_GCCOUNT: { - /* GC values are expressed in Kbytes: #bytes/2^10 */ - res = cast_int(g->totalbytes >> 10); - break; - } - case LUA_GCCOUNTB: { - res = cast_int(g->totalbytes & 0x3ff); - break; - } - case LUA_GCSTEP: { - lu_mem a = (cast(lu_mem, data) << 10); - if (a <= g->totalbytes) - g->GCthreshold = g->totalbytes - a; - else - g->GCthreshold = 0; - while (g->GCthreshold <= g->totalbytes) { - luaC_step(L); - if (g->gcstate == GCSpause) { /* end of cycle? */ - res = 1; /* signal it */ - break; - } - } - break; - } - case LUA_GCSETPAUSE: { - res = g->gcpause; - g->gcpause = data; - break; - } - case LUA_GCSETSTEPMUL: { - res = g->gcstepmul; - g->gcstepmul = data; - break; - } - default: res = -1; /* invalid option */ - } - lua_unlock(L); - return res; -} - - - -/* -** miscellaneous functions -*/ - - -LUA_API int lua_error (lua_State *L) { - lua_lock(L); - api_checknelems(L, 1); - luaG_errormsg(L); - lua_unlock(L); - return 0; /* to avoid warnings */ -} - - -LUA_API int lua_next (lua_State *L, int idx) { - StkId t; - int more; - lua_lock(L); - t = index2adr(L, idx); - api_check(L, ttistable(t)); - more = luaH_next(L, hvalue(t), L->top - 1); - if (more) { - api_incr_top(L); - } - else /* no more elements */ - L->top -= 1; /* remove key */ - lua_unlock(L); - return more; -} - - -LUA_API void lua_concat (lua_State *L, int n) { - lua_lock(L); - api_checknelems(L, n); - if (n >= 2) { - luaC_checkGC(L); - luaV_concat(L, n, cast_int(L->top - L->base) - 1); - L->top -= (n-1); - } - else if (n == 0) { /* push empty string */ - setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); - api_incr_top(L); - } - /* else n == 1; nothing to do */ - lua_unlock(L); -} - - -LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { - lua_Alloc f; - lua_lock(L); - if (ud) *ud = G(L)->ud; - f = G(L)->frealloc; - lua_unlock(L); - return f; -} - - -LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { - lua_lock(L); - G(L)->ud = ud; - G(L)->frealloc = f; - lua_unlock(L); -} - - -LUA_API void *lua_newuserdata (lua_State *L, size_t size) { - Udata *u; - lua_lock(L); - luaC_checkGC(L); - u = luaS_newudata(L, size, getcurrenv(L)); - setuvalue(L, L->top, u); - api_incr_top(L); - lua_unlock(L); - return u + 1; -} - - - - -static const char *aux_upvalue (StkId fi, int n, TValue **val) { - Closure *f; - if (!ttisfunction(fi)) return NULL; - f = clvalue(fi); - if (f->c.isC) { - if (!(1 <= n && n <= f->c.nupvalues)) return NULL; - *val = &f->c.upvalue[n-1]; - return ""; - } - else { - Proto *p = f->l.p; - if (!(1 <= n && n <= p->sizeupvalues)) return NULL; - *val = f->l.upvals[n-1]->v; - return getstr(p->upvalues[n-1]); - } -} - - -LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val; - lua_lock(L); - name = aux_upvalue(index2adr(L, funcindex), n, &val); - if (name) { - setobj2s(L, L->top, val); - api_incr_top(L); - } - lua_unlock(L); - return name; -} - - -LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val; - StkId fi; - lua_lock(L); - fi = index2adr(L, funcindex); - api_checknelems(L, 1); - name = aux_upvalue(fi, n, &val); - if (name) { - L->top--; - setobj(L, val, L->top); - luaC_barrier(L, clvalue(fi), L->top); - } - lua_unlock(L); - return name; -} - diff --git a/script/lua/lapi.h b/script/lua/lapi.h deleted file mode 100644 index 2c3fab244..000000000 --- a/script/lua/lapi.h +++ /dev/null @@ -1,16 +0,0 @@ -/* -** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ -** Auxiliary functions from Lua API -** See Copyright Notice in lua.h -*/ - -#ifndef lapi_h -#define lapi_h - - -#include "lobject.h" - - -LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); - -#endif diff --git a/script/lua/lauxlib.c b/script/lua/lauxlib.c deleted file mode 100644 index f61e028d3..000000000 --- a/script/lua/lauxlib.c +++ /dev/null @@ -1,668 +0,0 @@ -/* -** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#include -#include -#include -#include -#include -#endif - -/* This file uses only the official API of Lua. -** Any function declared here could be written as an application function. -*/ - -#define lauxlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" - - -#define FREELIST_REF 0 /* free list of references */ - - -/* convert a stack index to positive */ -#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ - lua_gettop(L) + (i) + 1) - - -/* -** {====================================================== -** Error-report functions -** ======================================================= -*/ - - -LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { - lua_Debug ar; - if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ - return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); - lua_getinfo(L, "n", &ar); - if (strcmp(ar.namewhat, "method") == 0) { - narg--; /* do not count `self' */ - if (narg == 0) /* error is in the self argument itself? */ - return luaL_error(L, "calling " LUA_QS " on bad self (%s)", - ar.name, extramsg); - } - if (ar.name == NULL) - ar.name = "?"; - return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", - narg, ar.name, extramsg); -} - - -LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { - const char *msg = lua_pushfstring(L, "%s expected, got %s", - tname, luaL_typename(L, narg)); - return luaL_argerror(L, narg, msg); -} - - -static void tag_error (lua_State *L, int narg, int tag) { - luaL_typerror(L, narg, lua_typename(L, tag)); -} - - -LUALIB_API void luaL_where (lua_State *L, int level) { - lua_Debug ar; - if (lua_getstack(L, level, &ar)) { /* check function at level */ - lua_getinfo(L, "Sl", &ar); /* get info about it */ - if (ar.currentline > 0) { /* is there info? */ - lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); - return; - } - } - lua_pushliteral(L, ""); /* else, no information available... */ -} - - -LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - luaL_where(L, 1); - lua_pushvfstring(L, fmt, argp); - va_end(argp); - lua_concat(L, 2); - return lua_error(L); -} - -/* }====================================================== */ - - -LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, - const char *const lst[]) { - const char *name = (def) ? luaL_optstring(L, narg, def) : - luaL_checkstring(L, narg); - int i; - for (i=0; lst[i]; i++) - if (strcmp(lst[i], name) == 0) - return i; - return luaL_argerror(L, narg, - lua_pushfstring(L, "invalid option " LUA_QS, name)); -} - - -LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { - lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ - if (!lua_isnil(L, -1)) /* name already in use? */ - return 0; /* leave previous value on top, but return 0 */ - lua_pop(L, 1); - lua_newtable(L); /* create metatable */ - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ - return 1; -} - - -LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ - if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } - } - } - luaL_typerror(L, ud, tname); /* else error */ - return NULL; /* to avoid warnings */ -} - - -LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { - if (!lua_checkstack(L, space)) - luaL_error(L, "stack overflow (%s)", mes); -} - - -LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { - if (lua_type(L, narg) != t) - tag_error(L, narg, t); -} - - -LUALIB_API void luaL_checkany (lua_State *L, int narg) { - if (lua_type(L, narg) == LUA_TNONE) - luaL_argerror(L, narg, "value expected"); -} - - -LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { - const char *s = lua_tolstring(L, narg, len); - if (!s) tag_error(L, narg, LUA_TSTRING); - return s; -} - - -LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, - const char *def, size_t *len) { - if (lua_isnoneornil(L, narg)) { - if (len) - *len = (def ? strlen(def) : 0); - return def; - } - else return luaL_checklstring(L, narg, len); -} - - -LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { - lua_Number d = lua_tonumber(L, narg); - if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ - tag_error(L, narg, LUA_TNUMBER); - return d; -} - - -LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { - return luaL_opt(L, luaL_checknumber, narg, def); -} - - -LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { - lua_Integer d = lua_tointeger(L, narg); - if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ - tag_error(L, narg, LUA_TNUMBER); - return d; -} - - -LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, - lua_Integer def) { - return luaL_opt(L, luaL_checkinteger, narg, def); -} - - -LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { - if (!lua_getmetatable(L, obj)) /* no metatable? */ - return 0; - lua_pushstring(L, event); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { - lua_pop(L, 2); /* remove metatable and metafield */ - return 0; - } - else { - lua_remove(L, -2); /* remove only metatable */ - return 1; - } -} - - -LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { - obj = abs_index(L, obj); - if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ - return 0; - lua_pushvalue(L, obj); - lua_call(L, 1, 1); - return 1; -} - - -LUALIB_API void (luaL_register) (lua_State *L, const char *libname, - const luaL_Reg *l) { - luaI_openlib(L, libname, l, 0); -} - - -static int libsize (const luaL_Reg *l) { - int size = 0; - for (; l->name; l++) size++; - return size; -} - - -LUALIB_API void luaI_openlib (lua_State *L, const char *libname, - const luaL_Reg *l, int nup) { - if (libname) { - int size = libsize(l); - /* check whether lib already exists */ - luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); - lua_getfield(L, -1, libname); /* get _LOADED[libname] */ - if (!lua_istable(L, -1)) { /* not found? */ - lua_pop(L, 1); /* remove previous result */ - /* try global variable (and create one if it does not exist) */ - if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) - luaL_error(L, "name conflict for module " LUA_QS, libname); - lua_pushvalue(L, -1); - lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ - } - lua_remove(L, -2); /* remove _LOADED table */ - lua_insert(L, -(nup+1)); /* move library table to below upvalues */ - } - for (; l->name; l++) { - int i; - for (i=0; ifunc, nup); - lua_setfield(L, -(nup+2), l->name); - } - lua_pop(L, nup); /* remove upvalues */ -} - - - -/* -** {====================================================== -** getn-setn: size for arrays -** ======================================================= -*/ - -#if defined(LUA_COMPAT_GETN) - -static int checkint (lua_State *L, int topop) { - int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; - lua_pop(L, topop); - return n; -} - - -static void getsizes (lua_State *L) { - lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); - if (lua_isnil(L, -1)) { /* no `size' table? */ - lua_pop(L, 1); /* remove nil */ - lua_newtable(L); /* create it */ - lua_pushvalue(L, -1); /* `size' will be its own metatable */ - lua_setmetatable(L, -2); - lua_pushliteral(L, "kv"); - lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ - } -} - - -LUALIB_API void luaL_setn (lua_State *L, int t, int n) { - t = abs_index(L, t); - lua_pushliteral(L, "n"); - lua_rawget(L, t); - if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ - lua_pushliteral(L, "n"); /* use it */ - lua_pushinteger(L, n); - lua_rawset(L, t); - } - else { /* use `sizes' */ - getsizes(L); - lua_pushvalue(L, t); - lua_pushinteger(L, n); - lua_rawset(L, -3); /* sizes[t] = n */ - lua_pop(L, 1); /* remove `sizes' */ - } -} - - -LUALIB_API int luaL_getn (lua_State *L, int t) { - int n; - t = abs_index(L, t); - lua_pushliteral(L, "n"); /* try t.n */ - lua_rawget(L, t); - if ((n = checkint(L, 1)) >= 0) return n; - getsizes(L); /* else try sizes[t] */ - lua_pushvalue(L, t); - lua_rawget(L, -2); - if ((n = checkint(L, 2)) >= 0) return n; - return (int)lua_objlen(L, t); -} - -#endif - -/* }====================================================== */ - - - -LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, - const char *r) { - const char *wild; - size_t l = strlen(p); - luaL_Buffer b; - luaL_buffinit(L, &b); - while ((wild = strstr(s, p)) != NULL) { - luaL_addlstring(&b, s, wild - s); /* push prefix */ - luaL_addstring(&b, r); /* push replacement in place of pattern */ - s = wild + l; /* continue after `p' */ - } - luaL_addstring(&b, s); /* push last suffix */ - luaL_pushresult(&b); - return lua_tostring(L, -1); -} - - -LUALIB_API const char *luaL_findtable (lua_State *L, int idx, - const char *fname, int szhint) { - const char *e; - lua_pushvalue(L, idx); - do { - e = strchr(fname, '.'); - if (e == NULL) e = fname + strlen(fname); - lua_pushlstring(L, fname, e - fname); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { /* no such field? */ - lua_pop(L, 1); /* remove this nil */ - lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ - lua_pushlstring(L, fname, e - fname); - lua_pushvalue(L, -2); - lua_settable(L, -4); /* set new table into field */ - } - else if (!lua_istable(L, -1)) { /* field has a non-table value? */ - lua_pop(L, 2); /* remove table and value */ - return fname; /* return problematic part of the name */ - } - lua_remove(L, -2); /* remove previous table */ - fname = e + 1; - } while (*e == '.'); - return NULL; -} - - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - - -#define bufflen(B) ((B)->p - (B)->buffer) -#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) - -#define LIMIT (LUA_MINSTACK/2) - - -static int emptybuffer (luaL_Buffer *B) { - size_t l = bufflen(B); - if (l == 0) return 0; /* put nothing on stack */ - else { - lua_pushlstring(B->L, B->buffer, l); - B->p = B->buffer; - B->lvl++; - return 1; - } -} - - -static void adjuststack (luaL_Buffer *B) { - if (B->lvl > 1) { - lua_State *L = B->L; - int toget = 1; /* number of levels to concat */ - size_t toplen = lua_strlen(L, -1); - do { - size_t l = lua_strlen(L, -(toget+1)); - if (B->lvl - toget + 1 >= LIMIT || toplen > l) { - toplen += l; - toget++; - } - else break; - } while (toget < B->lvl); - lua_concat(L, toget); - B->lvl = B->lvl - toget + 1; - } -} - - -LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { - if (emptybuffer(B)) - adjuststack(B); - return B->buffer; -} - - -LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { - while (l--) - luaL_addchar(B, *s++); -} - - -LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { - luaL_addlstring(B, s, strlen(s)); -} - - -LUALIB_API void luaL_pushresult (luaL_Buffer *B) { - emptybuffer(B); - lua_concat(B->L, B->lvl); - B->lvl = 1; -} - - -LUALIB_API void luaL_addvalue (luaL_Buffer *B) { - lua_State *L = B->L; - size_t vl; - const char *s = lua_tolstring(L, -1, &vl); - if (vl <= bufffree(B)) { /* fit into buffer? */ - memcpy(B->p, s, vl); /* put it there */ - B->p += vl; - lua_pop(L, 1); /* remove from stack */ - } - else { - if (emptybuffer(B)) - lua_insert(L, -2); /* put buffer before new value */ - B->lvl++; /* add new value into B stack */ - adjuststack(B); - } -} - - -LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { - B->L = L; - B->p = B->buffer; - B->lvl = 0; -} - -/* }====================================================== */ - - -LUALIB_API int luaL_ref (lua_State *L, int t) { - int ref; - t = abs_index(L, t); - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* remove from stack */ - return LUA_REFNIL; /* `nil' has a unique fixed reference */ - } - lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ - ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ - lua_pop(L, 1); /* remove it from stack */ - if (ref != 0) { /* any free element? */ - lua_rawgeti(L, t, ref); /* remove it from list */ - lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ - } - else { /* no free elements */ - ref = (int)lua_objlen(L, t); - ref++; /* create new reference */ - } - lua_rawseti(L, t, ref); - return ref; -} - - -LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { - if (ref >= 0) { - t = abs_index(L, t); - lua_rawgeti(L, t, FREELIST_REF); - lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ - lua_pushinteger(L, ref); - lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ - } -} - - - -/* -** {====================================================== -** Load functions -** ======================================================= -*/ - -#if 0 - -typedef struct LoadF { - int extraline; - FILE *f; - char buff[LUAL_BUFFERSIZE]; -} LoadF; - - -static const char *getF (lua_State *L, void *ud, size_t *size) { - LoadF *lf = (LoadF *)ud; - (void)L; - if (lf->extraline) { - lf->extraline = 0; - *size = 1; - return "\n"; - } - if (feof(lf->f)) return NULL; - *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); - return (*size > 0) ? lf->buff : NULL; -} - - -static int errfile (lua_State *L, const char *what, int fnameindex) { - const char *serr = strerror(errno); - const char *filename = lua_tostring(L, fnameindex) + 1; - lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); - lua_remove(L, fnameindex); - return LUA_ERRFILE; -} - - -LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { - LoadF lf; - int status, readstatus; - int c; - int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ - lf.extraline = 0; - if (filename == NULL) { - lua_pushliteral(L, "=stdin"); - lf.f = stdin; - } - else { - lua_pushfstring(L, "@%s", filename); - lf.f = fopen(filename, "r"); - if (lf.f == NULL) return errfile(L, "open", fnameindex); - } - c = getc(lf.f); - if (c == '#') { /* Unix exec. file? */ - lf.extraline = 1; - while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ - if (c == '\n') c = getc(lf.f); - } - if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ - lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ - if (lf.f == NULL) return errfile(L, "reopen", fnameindex); - /* skip eventual `#!...' */ - while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; - lf.extraline = 0; - } - ungetc(c, lf.f); - status = lua_load(L, getF, &lf, lua_tostring(L, -1)); - readstatus = ferror(lf.f); - if (filename) fclose(lf.f); /* close file (even in case of errors) */ - if (readstatus) { - lua_settop(L, fnameindex); /* ignore results from `lua_load' */ - return errfile(L, "read", fnameindex); - } - lua_remove(L, fnameindex); - return status; -} - -#else -LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { - (void) L; - (void) filename; - - return LUA_ERRFILE; -} - -#endif - -typedef struct LoadS { - const char *s; - size_t size; -} LoadS; - - -static const char *getS (lua_State *L, void *ud, size_t *size) { - LoadS *ls = (LoadS *)ud; - (void)L; - if (ls->size == 0) return NULL; - *size = ls->size; - ls->size = 0; - return ls->s; -} - - -LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, - const char *name) { - LoadS ls; - ls.s = buff; - ls.size = size; - return lua_load(L, getS, &ls, name); -} - - -LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { - return luaL_loadbuffer(L, s, strlen(s), s); -} - - - -/* }====================================================== */ - - -static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { - (void)ud; - (void)osize; - if (nsize == 0) { - free(ptr); - return NULL; - } - else - return realloc(ptr, nsize); -} - - -static int panic (lua_State *L) { - (void)L; /* to avoid warnings */ -#if 0 - fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", - lua_tostring(L, -1)); -#else - grub_fatal ("PANIC: unprotected error in call to Lua API (%s)\n", - lua_tostring(L, -1)); -#endif - return 0; -} - - -LUALIB_API lua_State *luaL_newstate (void) { - lua_State *L = lua_newstate(l_alloc, NULL); - if (L) lua_atpanic(L, &panic); - return L; -} - diff --git a/script/lua/lauxlib.h b/script/lua/lauxlib.h deleted file mode 100644 index f18864d6c..000000000 --- a/script/lua/lauxlib.h +++ /dev/null @@ -1,175 +0,0 @@ -/* -** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lauxlib_h -#define lauxlib_h - -#if 0 -#include -#include -#endif - -#include "lua.h" - - -#if defined(LUA_COMPAT_GETN) -LUALIB_API int (luaL_getn) (lua_State *L, int t); -LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); -#else -#define luaL_getn(L,i) ((int)lua_objlen(L, i)) -#define luaL_setn(L,i,j) ((void)0) /* no op! */ -#endif - -#if defined(LUA_COMPAT_OPENLIB) -#define luaI_openlib luaL_openlib -#endif - - -/* extra error code for `luaL_load' */ -#define LUA_ERRFILE (LUA_ERRERR+1) - - -typedef struct luaL_Reg { - const char *name; - lua_CFunction func; -} luaL_Reg; - - - -LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, - const luaL_Reg *l, int nup); -LUALIB_API void (luaL_register) (lua_State *L, const char *libname, - const luaL_Reg *l); -LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); -LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); -LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); -LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); -LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, - size_t *l); -LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, - const char *def, size_t *l); -LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); -LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); - -LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); -LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, - lua_Integer def); - -LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); -LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); -LUALIB_API void (luaL_checkany) (lua_State *L, int narg); - -LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); -LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); - -LUALIB_API void (luaL_where) (lua_State *L, int lvl); -LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); - -LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, - const char *const lst[]); - -LUALIB_API int (luaL_ref) (lua_State *L, int t); -LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); - -LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); -LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, - const char *name); -LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); - -LUALIB_API lua_State *(luaL_newstate) (void); - - -LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, - const char *r); - -LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, - const char *fname, int szhint); - - - - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - -#define luaL_argcheck(L, cond,numarg,extramsg) \ - ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) -#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) -#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) -#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) -#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) -#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) -#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) - -#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) - -#define luaL_dofile(L, fn) \ - (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) - -#define luaL_dostring(L, s) \ - (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) - -#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) - -#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - - - -typedef struct luaL_Buffer { - char *p; /* current position in buffer */ - int lvl; /* number of strings in the stack (level) */ - lua_State *L; - char buffer[LUAL_BUFFERSIZE]; -} luaL_Buffer; - -#define luaL_addchar(B,c) \ - ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ - (*(B)->p++ = (char)(c))) - -/* compatibility only */ -#define luaL_putchar(B,c) luaL_addchar(B,c) - -#define luaL_addsize(B,n) ((B)->p += (n)) - -LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); -LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); -LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); -LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); -LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); -LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); - - -/* }====================================================== */ - - -/* compatibility with ref system */ - -/* pre-defined references */ -#define LUA_NOREF (-2) -#define LUA_REFNIL (-1) - -#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ - (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) - -#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) - -#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) - - -#define luaL_reg luaL_Reg - -#endif - - diff --git a/script/lua/lbaselib.c b/script/lua/lbaselib.c deleted file mode 100644 index 1bbb126c9..000000000 --- a/script/lua/lbaselib.c +++ /dev/null @@ -1,652 +0,0 @@ -/* -** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ -** Basic library -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#include -#include -#include -#endif - -#define lbaselib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - - -/* -** If your system does not support `stdout', you can just remove this function. -** If you need, you can define your own `print' function, following this -** model but changing `fputs' to put the strings at a proper place -** (a console window or a log file, for instance). -*/ -static int luaB_print (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int i; - lua_getglobal(L, "tostring"); - for (i=1; i<=n; i++) { - const char *s; - lua_pushvalue(L, -1); /* function to be called */ - lua_pushvalue(L, i); /* value to print */ - lua_call(L, 1, 1); - s = lua_tostring(L, -1); /* get result */ - if (s == NULL) - return luaL_error(L, LUA_QL("tostring") " must return a string to " - LUA_QL("print")); - if (i>1) fputs("\t", stdout); - fputs(s, stdout); - lua_pop(L, 1); /* pop result */ - } - fputs("\n", stdout); - return 0; -} - - -static int luaB_tonumber (lua_State *L) { - int base = luaL_optint(L, 2, 10); - if (base == 10) { /* standard conversion */ - luaL_checkany(L, 1); - if (lua_isnumber(L, 1)) { - lua_pushnumber(L, lua_tonumber(L, 1)); - return 1; - } - } - else { - const char *s1 = luaL_checkstring(L, 1); - char *s2; - unsigned long n; - luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - n = strtoul(s1, &s2, base); - if (s1 != s2) { /* at least one valid digit? */ - while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ - if (*s2 == '\0') { /* no invalid trailing characters? */ - lua_pushnumber(L, (lua_Number)n); - return 1; - } - } - } - lua_pushnil(L); /* else not a number */ - return 1; -} - - -static int luaB_error (lua_State *L) { - int level = luaL_optint(L, 2, 1); - lua_settop(L, 1); - if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ - luaL_where(L, level); - lua_pushvalue(L, 1); - lua_concat(L, 2); - } - return lua_error(L); -} - - -static int luaB_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); - return 1; /* no metatable */ - } - luaL_getmetafield(L, 1, "__metatable"); - return 1; /* returns either __metatable field (if present) or metatable */ -} - - -static int luaB_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - if (luaL_getmetafield(L, 1, "__metatable")) - luaL_error(L, "cannot change a protected metatable"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; -} - - -static void getfunc (lua_State *L, int opt) { - if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); - else { - lua_Debug ar; - int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); - luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); - if (lua_getstack(L, level, &ar) == 0) - luaL_argerror(L, 1, "invalid level"); - lua_getinfo(L, "f", &ar); - if (lua_isnil(L, -1)) - luaL_error(L, "no function environment for tail call at level %d", - level); - } -} - - -static int luaB_getfenv (lua_State *L) { - getfunc(L, 1); - if (lua_iscfunction(L, -1)) /* is a C function? */ - lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ - else - lua_getfenv(L, -1); - return 1; -} - - -static int luaB_setfenv (lua_State *L) { - luaL_checktype(L, 2, LUA_TTABLE); - getfunc(L, 0); - lua_pushvalue(L, 2); - if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { - /* change environment of current thread */ - lua_pushthread(L); - lua_insert(L, -2); - lua_setfenv(L, -2); - return 0; - } - else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) - luaL_error(L, - LUA_QL("setfenv") " cannot change environment of given object"); - return 1; -} - - -static int luaB_rawequal (lua_State *L) { - luaL_checkany(L, 1); - luaL_checkany(L, 2); - lua_pushboolean(L, lua_rawequal(L, 1, 2)); - return 1; -} - - -static int luaB_rawget (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_rawget(L, 1); - return 1; -} - -static int luaB_rawset (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - luaL_checkany(L, 3); - lua_settop(L, 3); - lua_rawset(L, 1); - return 1; -} - - -static int luaB_gcinfo (lua_State *L) { - lua_pushinteger(L, lua_getgccount(L)); - return 1; -} - - -static int luaB_collectgarbage (lua_State *L) { - static const char *const opts[] = {"stop", "restart", "collect", - "count", "step", "setpause", "setstepmul", NULL}; - static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, - LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; - int o = luaL_checkoption(L, 1, "collect", opts); - int ex = luaL_optint(L, 2, 0); - int res = lua_gc(L, optsnum[o], ex); - switch (optsnum[o]) { - case LUA_GCCOUNT: { - int b = lua_gc(L, LUA_GCCOUNTB, 0); - lua_pushnumber(L, res + ((lua_Number)b/1024)); - return 1; - } - case LUA_GCSTEP: { - lua_pushboolean(L, res); - return 1; - } - default: { - lua_pushnumber(L, res); - return 1; - } - } -} - - -static int luaB_type (lua_State *L) { - luaL_checkany(L, 1); - lua_pushstring(L, luaL_typename(L, 1)); - return 1; -} - - -static int luaB_next (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 2); /* create a 2nd argument if there isn't one */ - if (lua_next(L, 1)) - return 2; - else { - lua_pushnil(L); - return 1; - } -} - - -static int luaB_pairs (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ - lua_pushvalue(L, 1); /* state, */ - lua_pushnil(L); /* and initial value */ - return 3; -} - - -static int ipairsaux (lua_State *L) { - int i = luaL_checkint(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - i++; /* next value */ - lua_pushinteger(L, i); - lua_rawgeti(L, 1, i); - return (lua_isnil(L, -1)) ? 0 : 2; -} - - -static int luaB_ipairs (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ - lua_pushvalue(L, 1); /* state, */ - lua_pushinteger(L, 0); /* and initial value */ - return 3; -} - - -static int load_aux (lua_State *L, int status) { - if (status == 0) /* OK? */ - return 1; - else { - lua_pushnil(L); - lua_insert(L, -2); /* put before error message */ - return 2; /* return nil plus error message */ - } -} - - -static int luaB_loadstring (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - const char *chunkname = luaL_optstring(L, 2, s); - return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); -} - - -static int luaB_loadfile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - return load_aux(L, luaL_loadfile(L, fname)); -} - - -/* -** Reader for generic `load' function: `lua_load' uses the -** stack for internal stuff, so the reader cannot change the -** stack top. Instead, it keeps its resulting string in a -** reserved slot inside the stack. -*/ -static const char *generic_reader (lua_State *L, void *ud, size_t *size) { - (void)ud; /* to avoid warnings */ - luaL_checkstack(L, 2, "too many nested functions"); - lua_pushvalue(L, 1); /* get function */ - lua_call(L, 0, 1); /* call it */ - if (lua_isnil(L, -1)) { - *size = 0; - return NULL; - } - else if (lua_isstring(L, -1)) { - lua_replace(L, 3); /* save string in a reserved stack slot */ - return lua_tolstring(L, 3, size); - } - else luaL_error(L, "reader function must return a string"); - return NULL; /* to avoid warnings */ -} - - -static int luaB_load (lua_State *L) { - int status; - const char *cname = luaL_optstring(L, 2, "=(load)"); - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ - status = lua_load(L, generic_reader, NULL, cname); - return load_aux(L, status); -} - - -static int luaB_dofile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - int n = lua_gettop(L); - if (luaL_loadfile(L, fname) != 0) lua_error(L); - lua_call(L, 0, LUA_MULTRET); - return lua_gettop(L) - n; -} - - -static int luaB_assert (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_toboolean(L, 1)) - return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); - return lua_gettop(L); -} - - -static int luaB_unpack (lua_State *L) { - int i, e, n; - luaL_checktype(L, 1, LUA_TTABLE); - i = luaL_optint(L, 2, 1); - e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); - if (i > e) return 0; /* empty range */ - n = e - i + 1; /* number of elements */ - if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ - return luaL_error(L, "too many results to unpack"); - lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ - while (i++ < e) /* push arg[i + 1...e] */ - lua_rawgeti(L, 1, i); - return n; -} - - -static int luaB_select (lua_State *L) { - int n = lua_gettop(L); - if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { - lua_pushinteger(L, n-1); - return 1; - } - else { - int i = luaL_checkint(L, 1); - if (i < 0) i = n + i; - else if (i > n) i = n; - luaL_argcheck(L, 1 <= i, 1, "index out of range"); - return n - i; - } -} - - -static int luaB_pcall (lua_State *L) { - int status; - luaL_checkany(L, 1); - status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); - lua_pushboolean(L, (status == 0)); - lua_insert(L, 1); - return lua_gettop(L); /* return status + all results */ -} - - -static int luaB_xpcall (lua_State *L) { - int status; - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_insert(L, 1); /* put error function under function to be called */ - status = lua_pcall(L, 0, LUA_MULTRET, 1); - lua_pushboolean(L, (status == 0)); - lua_replace(L, 1); - return lua_gettop(L); /* return status + all results */ -} - -static int luaB_tostring (lua_State *L) { - luaL_checkany(L, 1); - if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ - return 1; /* use its value */ - switch (lua_type(L, 1)) { - case LUA_TNUMBER: - lua_pushstring(L, lua_tostring(L, 1)); - break; - case LUA_TSTRING: - lua_pushvalue(L, 1); - break; - case LUA_TBOOLEAN: - lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); - break; - case LUA_TNIL: - lua_pushliteral(L, "nil"); - break; - default: - lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); - break; - } - return 1; -} - - -static int luaB_newproxy (lua_State *L) { - lua_settop(L, 1); - lua_newuserdata(L, 0); /* create proxy */ - if (lua_toboolean(L, 1) == 0) - return 1; /* no metatable */ - else if (lua_isboolean(L, 1)) { - lua_newtable(L); /* create a new metatable `m' ... */ - lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ - lua_pushboolean(L, 1); - lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ - } - else { - int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ - if (lua_getmetatable(L, 1)) { - lua_rawget(L, lua_upvalueindex(1)); - validproxy = lua_toboolean(L, -1); - lua_pop(L, 1); /* remove value */ - } - luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); - lua_getmetatable(L, 1); /* metatable is valid; get it */ - } - lua_setmetatable(L, 2); - return 1; -} - - -static const luaL_Reg base_funcs[] = { - {"assert", luaB_assert}, - {"collectgarbage", luaB_collectgarbage}, - {"dofile", luaB_dofile}, - {"error", luaB_error}, - {"gcinfo", luaB_gcinfo}, - {"getfenv", luaB_getfenv}, - {"getmetatable", luaB_getmetatable}, - {"loadfile", luaB_loadfile}, - {"load", luaB_load}, - {"loadstring", luaB_loadstring}, - {"next", luaB_next}, - {"pcall", luaB_pcall}, - {"print", luaB_print}, - {"rawequal", luaB_rawequal}, - {"rawget", luaB_rawget}, - {"rawset", luaB_rawset}, - {"select", luaB_select}, - {"setfenv", luaB_setfenv}, - {"setmetatable", luaB_setmetatable}, - {"tonumber", luaB_tonumber}, - {"tostring", luaB_tostring}, - {"type", luaB_type}, - {"unpack", luaB_unpack}, - {"xpcall", luaB_xpcall}, - {NULL, NULL} -}; - - -/* -** {====================================================== -** Coroutine library -** ======================================================= -*/ - -#define CO_RUN 0 /* running */ -#define CO_SUS 1 /* suspended */ -#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ -#define CO_DEAD 3 - -static const char *const statnames[] = - {"running", "suspended", "normal", "dead"}; - -static int costatus (lua_State *L, lua_State *co) { - if (L == co) return CO_RUN; - switch (lua_status(co)) { - case LUA_YIELD: - return CO_SUS; - case 0: { - lua_Debug ar; - if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ - return CO_NOR; /* it is running */ - else if (lua_gettop(co) == 0) - return CO_DEAD; - else - return CO_SUS; /* initial state */ - } - default: /* some error occured */ - return CO_DEAD; - } -} - - -static int luaB_costatus (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - luaL_argcheck(L, co, 1, "coroutine expected"); - lua_pushstring(L, statnames[costatus(L, co)]); - return 1; -} - - -static int auxresume (lua_State *L, lua_State *co, int narg) { - int status = costatus(L, co); - if (!lua_checkstack(co, narg)) - luaL_error(L, "too many arguments to resume"); - if (status != CO_SUS) { - lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); - return -1; /* error flag */ - } - lua_xmove(L, co, narg); - lua_setlevel(L, co); - status = lua_resume(co, narg); - if (status == 0 || status == LUA_YIELD) { - int nres = lua_gettop(co); - if (!lua_checkstack(L, nres + 1)) - luaL_error(L, "too many results to resume"); - lua_xmove(co, L, nres); /* move yielded values */ - return nres; - } - else { - lua_xmove(co, L, 1); /* move error message */ - return -1; /* error flag */ - } -} - - -static int luaB_coresume (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - int r; - luaL_argcheck(L, co, 1, "coroutine expected"); - r = auxresume(L, co, lua_gettop(L) - 1); - if (r < 0) { - lua_pushboolean(L, 0); - lua_insert(L, -2); - return 2; /* return false + error message */ - } - else { - lua_pushboolean(L, 1); - lua_insert(L, -(r + 1)); - return r + 1; /* return true + `resume' returns */ - } -} - - -static int luaB_auxwrap (lua_State *L) { - lua_State *co = lua_tothread(L, lua_upvalueindex(1)); - int r = auxresume(L, co, lua_gettop(L)); - if (r < 0) { - if (lua_isstring(L, -1)) { /* error object is a string? */ - luaL_where(L, 1); /* add extra info */ - lua_insert(L, -2); - lua_concat(L, 2); - } - lua_error(L); /* propagate error */ - } - return r; -} - - -static int luaB_cocreate (lua_State *L) { - lua_State *NL = lua_newthread(L); - luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, - "Lua function expected"); - lua_pushvalue(L, 1); /* move function to top */ - lua_xmove(L, NL, 1); /* move function from L to NL */ - return 1; -} - - -static int luaB_cowrap (lua_State *L) { - luaB_cocreate(L); - lua_pushcclosure(L, luaB_auxwrap, 1); - return 1; -} - - -static int luaB_yield (lua_State *L) { - return lua_yield(L, lua_gettop(L)); -} - - -static int luaB_corunning (lua_State *L) { - if (lua_pushthread(L)) - lua_pushnil(L); /* main thread is not a coroutine */ - return 1; -} - - -static const luaL_Reg co_funcs[] = { - {"create", luaB_cocreate}, - {"resume", luaB_coresume}, - {"running", luaB_corunning}, - {"status", luaB_costatus}, - {"wrap", luaB_cowrap}, - {"yield", luaB_yield}, - {NULL, NULL} -}; - -/* }====================================================== */ - - -static void auxopen (lua_State *L, const char *name, - lua_CFunction f, lua_CFunction u) { - lua_pushcfunction(L, u); - lua_pushcclosure(L, f, 1); - lua_setfield(L, -2, name); -} - - -static void base_open (lua_State *L) { - /* set global _G */ - lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_setglobal(L, "_G"); - /* open lib into global table */ - luaL_register(L, "_G", base_funcs); - lua_pushliteral(L, LUA_VERSION); - lua_setglobal(L, "_VERSION"); /* set global _VERSION */ - /* `ipairs' and `pairs' need auxliliary functions as upvalues */ - auxopen(L, "ipairs", luaB_ipairs, ipairsaux); - auxopen(L, "pairs", luaB_pairs, luaB_next); - /* `newproxy' needs a weaktable as upvalue */ - lua_createtable(L, 0, 1); /* new table `w' */ - lua_pushvalue(L, -1); /* `w' will be its own metatable */ - lua_setmetatable(L, -2); - lua_pushliteral(L, "kv"); - lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ - lua_pushcclosure(L, luaB_newproxy, 1); - lua_setglobal(L, "newproxy"); /* set global `newproxy' */ -} - - -LUALIB_API int luaopen_base (lua_State *L) { - base_open(L); - luaL_register(L, LUA_COLIBNAME, co_funcs); - return 2; -} - diff --git a/script/lua/lcode.c b/script/lua/lcode.c deleted file mode 100644 index 64f726b48..000000000 --- a/script/lua/lcode.c +++ /dev/null @@ -1,848 +0,0 @@ -/* -** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#endif - -#define lcode_c -#define LUA_CORE - -#include "lua.h" - -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "ltable.h" - - -#define hasjumps(e) ((e)->t != (e)->f) - - -static int isnumeral(expdesc *e) { - return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); -} - - -void luaK_nil (FuncState *fs, int from, int n) { - Instruction *previous; - if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ - if (fs->pc == 0) { /* function start? */ - if (from >= fs->nactvar) - return; /* positions are already clean */ - } - else { - previous = &fs->f->code[fs->pc-1]; - if (GET_OPCODE(*previous) == OP_LOADNIL) { - int pfrom = GETARG_A(*previous); - int pto = GETARG_B(*previous); - if (pfrom <= from && from <= pto+1) { /* can connect both? */ - if (from+n-1 > pto) - SETARG_B(*previous, from+n-1); - return; - } - } - } - } - luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ -} - - -int luaK_jump (FuncState *fs) { - int jpc = fs->jpc; /* save list of jumps to here */ - int j; - fs->jpc = NO_JUMP; - j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); - luaK_concat(fs, &j, jpc); /* keep them on hold */ - return j; -} - - -void luaK_ret (FuncState *fs, int first, int nret) { - luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); -} - - -static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { - luaK_codeABC(fs, op, A, B, C); - return luaK_jump(fs); -} - - -static void fixjump (FuncState *fs, int pc, int dest) { - Instruction *jmp = &fs->f->code[pc]; - int offset = dest-(pc+1); - lua_assert(dest != NO_JUMP); - if (abs(offset) > MAXARG_sBx) - luaX_syntaxerror(fs->ls, "control structure too long"); - SETARG_sBx(*jmp, offset); -} - - -/* -** returns current `pc' and marks it as a jump target (to avoid wrong -** optimizations with consecutive instructions not in the same basic block). -*/ -int luaK_getlabel (FuncState *fs) { - fs->lasttarget = fs->pc; - return fs->pc; -} - - -static int getjump (FuncState *fs, int pc) { - int offset = GETARG_sBx(fs->f->code[pc]); - if (offset == NO_JUMP) /* point to itself represents end of list */ - return NO_JUMP; /* end of list */ - else - return (pc+1)+offset; /* turn offset into absolute position */ -} - - -static Instruction *getjumpcontrol (FuncState *fs, int pc) { - Instruction *pi = &fs->f->code[pc]; - if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) - return pi-1; - else - return pi; -} - - -/* -** check whether list has any jump that do not produce a value -** (or produce an inverted value) -*/ -static int need_value (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) { - Instruction i = *getjumpcontrol(fs, list); - if (GET_OPCODE(i) != OP_TESTSET) return 1; - } - return 0; /* not found */ -} - - -static int patchtestreg (FuncState *fs, int node, int reg) { - Instruction *i = getjumpcontrol(fs, node); - if (GET_OPCODE(*i) != OP_TESTSET) - return 0; /* cannot patch other instructions */ - if (reg != NO_REG && reg != GETARG_B(*i)) - SETARG_A(*i, reg); - else /* no register to put value or register already has the value */ - *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); - - return 1; -} - - -static void removevalues (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) - patchtestreg(fs, list, NO_REG); -} - - -static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, - int dtarget) { - while (list != NO_JUMP) { - int next = getjump(fs, list); - if (patchtestreg(fs, list, reg)) - fixjump(fs, list, vtarget); - else - fixjump(fs, list, dtarget); /* jump to default target */ - list = next; - } -} - - -static void dischargejpc (FuncState *fs) { - patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); - fs->jpc = NO_JUMP; -} - - -void luaK_patchlist (FuncState *fs, int list, int target) { - if (target == fs->pc) - luaK_patchtohere(fs, list); - else { - lua_assert(target < fs->pc); - patchlistaux(fs, list, target, NO_REG, target); - } -} - - -void luaK_patchtohere (FuncState *fs, int list) { - luaK_getlabel(fs); - luaK_concat(fs, &fs->jpc, list); -} - - -void luaK_concat (FuncState *fs, int *l1, int l2) { - if (l2 == NO_JUMP) return; - else if (*l1 == NO_JUMP) - *l1 = l2; - else { - int list = *l1; - int next; - while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ - list = next; - fixjump(fs, list, l2); - } -} - - -void luaK_checkstack (FuncState *fs, int n) { - int newstack = fs->freereg + n; - if (newstack > fs->f->maxstacksize) { - if (newstack >= MAXSTACK) - luaX_syntaxerror(fs->ls, "function or expression too complex"); - fs->f->maxstacksize = cast_byte(newstack); - } -} - - -void luaK_reserveregs (FuncState *fs, int n) { - luaK_checkstack(fs, n); - fs->freereg += n; -} - - -static void freereg (FuncState *fs, int reg) { - if (!ISK(reg) && reg >= fs->nactvar) { - fs->freereg--; - lua_assert(reg == fs->freereg); - } -} - - -static void freeexp (FuncState *fs, expdesc *e) { - if (e->k == VNONRELOC) - freereg(fs, e->u.s.info); -} - - -static int addk (FuncState *fs, TValue *k, TValue *v) { - lua_State *L = fs->L; - TValue *idx = luaH_set(L, fs->h, k); - Proto *f = fs->f; - int oldsize = f->sizek; - if (ttisnumber(idx)) { - lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); - return cast_int(nvalue(idx)); - } - else { /* constant not found; create a new entry */ - setnvalue(idx, cast_num(fs->nk)); - luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, - MAXARG_Bx, "constant table overflow"); - while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); - setobj(L, &f->k[fs->nk], v); - luaC_barrier(L, f, v); - return fs->nk++; - } -} - - -int luaK_stringK (FuncState *fs, TString *s) { - TValue o; - setsvalue(fs->L, &o, s); - return addk(fs, &o, &o); -} - - -int luaK_numberK (FuncState *fs, lua_Number r) { - TValue o; - setnvalue(&o, r); - return addk(fs, &o, &o); -} - - -static int boolK (FuncState *fs, int b) { - TValue o; - setbvalue(&o, b); - return addk(fs, &o, &o); -} - - -static int nilK (FuncState *fs) { - TValue k, v; - setnilvalue(&v); - /* cannot use nil as key; instead use table itself to represent nil */ - sethvalue(fs->L, &k, fs->h); - return addk(fs, &k, &v); -} - - -void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { - if (e->k == VCALL) { /* expression is an open function call? */ - SETARG_C(getcode(fs, e), nresults+1); - } - else if (e->k == VVARARG) { - SETARG_B(getcode(fs, e), nresults+1); - SETARG_A(getcode(fs, e), fs->freereg); - luaK_reserveregs(fs, 1); - } -} - - -void luaK_setoneret (FuncState *fs, expdesc *e) { - if (e->k == VCALL) { /* expression is an open function call? */ - e->k = VNONRELOC; - e->u.s.info = GETARG_A(getcode(fs, e)); - } - else if (e->k == VVARARG) { - SETARG_B(getcode(fs, e), 2); - e->k = VRELOCABLE; /* can relocate its simple result */ - } -} - - -void luaK_dischargevars (FuncState *fs, expdesc *e) { - switch (e->k) { - case VLOCAL: { - e->k = VNONRELOC; - break; - } - case VUPVAL: { - e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); - e->k = VRELOCABLE; - break; - } - case VGLOBAL: { - e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); - e->k = VRELOCABLE; - break; - } - case VINDEXED: { - freereg(fs, e->u.s.aux); - freereg(fs, e->u.s.info); - e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); - e->k = VRELOCABLE; - break; - } - case VVARARG: - case VCALL: { - luaK_setoneret(fs, e); - break; - } - default: break; /* there is one value available (somewhere) */ - } -} - - -static int code_label (FuncState *fs, int A, int b, int jump) { - luaK_getlabel(fs); /* those instructions may be jump targets */ - return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); -} - - -static void discharge2reg (FuncState *fs, expdesc *e, int reg) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: { - luaK_nil(fs, reg, 1); - break; - } - case VFALSE: case VTRUE: { - luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); - break; - } - case VK: { - luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); - break; - } - case VKNUM: { - luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); - break; - } - case VRELOCABLE: { - Instruction *pc = &getcode(fs, e); - SETARG_A(*pc, reg); - break; - } - case VNONRELOC: { - if (reg != e->u.s.info) - luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); - break; - } - default: { - lua_assert(e->k == VVOID || e->k == VJMP); - return; /* nothing to do... */ - } - } - e->u.s.info = reg; - e->k = VNONRELOC; -} - - -static void discharge2anyreg (FuncState *fs, expdesc *e) { - if (e->k != VNONRELOC) { - luaK_reserveregs(fs, 1); - discharge2reg(fs, e, fs->freereg-1); - } -} - - -static void exp2reg (FuncState *fs, expdesc *e, int reg) { - discharge2reg(fs, e, reg); - if (e->k == VJMP) - luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ - if (hasjumps(e)) { - int final; /* position after whole expression */ - int p_f = NO_JUMP; /* position of an eventual LOAD false */ - int p_t = NO_JUMP; /* position of an eventual LOAD true */ - if (need_value(fs, e->t) || need_value(fs, e->f)) { - int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); - p_f = code_label(fs, reg, 0, 1); - p_t = code_label(fs, reg, 1, 0); - luaK_patchtohere(fs, fj); - } - final = luaK_getlabel(fs); - patchlistaux(fs, e->f, final, reg, p_f); - patchlistaux(fs, e->t, final, reg, p_t); - } - e->f = e->t = NO_JUMP; - e->u.s.info = reg; - e->k = VNONRELOC; -} - - -void luaK_exp2nextreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - freeexp(fs, e); - luaK_reserveregs(fs, 1); - exp2reg(fs, e, fs->freereg - 1); -} - - -int luaK_exp2anyreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - if (e->k == VNONRELOC) { - if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ - if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ - exp2reg(fs, e, e->u.s.info); /* put value on it */ - return e->u.s.info; - } - } - luaK_exp2nextreg(fs, e); /* default */ - return e->u.s.info; -} - - -void luaK_exp2val (FuncState *fs, expdesc *e) { - if (hasjumps(e)) - luaK_exp2anyreg(fs, e); - else - luaK_dischargevars(fs, e); -} - - -int luaK_exp2RK (FuncState *fs, expdesc *e) { - luaK_exp2val(fs, e); - switch (e->k) { - case VKNUM: - case VTRUE: - case VFALSE: - case VNIL: { - if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ - e->u.s.info = (e->k == VNIL) ? nilK(fs) : - (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : - boolK(fs, (e->k == VTRUE)); - e->k = VK; - return RKASK(e->u.s.info); - } - else break; - } - case VK: { - if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ - return RKASK(e->u.s.info); - else break; - } - default: break; - } - /* not a constant in the right range: put it in a register */ - return luaK_exp2anyreg(fs, e); -} - - -void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { - switch (var->k) { - case VLOCAL: { - freeexp(fs, ex); - exp2reg(fs, ex, var->u.s.info); - return; - } - case VUPVAL: { - int e = luaK_exp2anyreg(fs, ex); - luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); - break; - } - case VGLOBAL: { - int e = luaK_exp2anyreg(fs, ex); - luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); - break; - } - case VINDEXED: { - int e = luaK_exp2RK(fs, ex); - luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); - break; - } - default: { - lua_assert(0); /* invalid var kind to store */ - break; - } - } - freeexp(fs, ex); -} - - -void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { - int func; - luaK_exp2anyreg(fs, e); - freeexp(fs, e); - func = fs->freereg; - luaK_reserveregs(fs, 2); - luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); - freeexp(fs, key); - e->u.s.info = func; - e->k = VNONRELOC; -} - - -static void invertjump (FuncState *fs, expdesc *e) { - Instruction *pc = getjumpcontrol(fs, e->u.s.info); - lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && - GET_OPCODE(*pc) != OP_TEST); - SETARG_A(*pc, !(GETARG_A(*pc))); -} - - -static int jumponcond (FuncState *fs, expdesc *e, int cond) { - if (e->k == VRELOCABLE) { - Instruction ie = getcode(fs, e); - if (GET_OPCODE(ie) == OP_NOT) { - fs->pc--; /* remove previous OP_NOT */ - return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); - } - /* else go through */ - } - discharge2anyreg(fs, e); - freeexp(fs, e); - return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); -} - - -void luaK_goiftrue (FuncState *fs, expdesc *e) { - int pc; /* pc of last jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VK: case VKNUM: case VTRUE: { - pc = NO_JUMP; /* always true; do nothing */ - break; - } - case VFALSE: { - pc = luaK_jump(fs); /* always jump */ - break; - } - case VJMP: { - invertjump(fs, e); - pc = e->u.s.info; - break; - } - default: { - pc = jumponcond(fs, e, 0); - break; - } - } - luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ - luaK_patchtohere(fs, e->t); - e->t = NO_JUMP; -} - - -static void luaK_goiffalse (FuncState *fs, expdesc *e) { - int pc; /* pc of last jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: case VFALSE: { - pc = NO_JUMP; /* always false; do nothing */ - break; - } - case VTRUE: { - pc = luaK_jump(fs); /* always jump */ - break; - } - case VJMP: { - pc = e->u.s.info; - break; - } - default: { - pc = jumponcond(fs, e, 1); - break; - } - } - luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ - luaK_patchtohere(fs, e->f); - e->f = NO_JUMP; -} - - -static void codenot (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: case VFALSE: { - e->k = VTRUE; - break; - } - case VK: case VKNUM: case VTRUE: { - e->k = VFALSE; - break; - } - case VJMP: { - invertjump(fs, e); - break; - } - case VRELOCABLE: - case VNONRELOC: { - discharge2anyreg(fs, e); - freeexp(fs, e); - e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); - e->k = VRELOCABLE; - break; - } - default: { - lua_assert(0); /* cannot happen */ - break; - } - } - /* interchange true and false lists */ - { int temp = e->f; e->f = e->t; e->t = temp; } - removevalues(fs, e->f); - removevalues(fs, e->t); -} - - -void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { - t->u.s.aux = luaK_exp2RK(fs, k); - t->k = VINDEXED; -} - - -static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { - lua_Number v1, v2, r; - if (!isnumeral(e1) || !isnumeral(e2)) return 0; - v1 = e1->u.nval; - v2 = e2->u.nval; - switch (op) { - case OP_ADD: r = luai_numadd(v1, v2); break; - case OP_SUB: r = luai_numsub(v1, v2); break; - case OP_MUL: r = luai_nummul(v1, v2); break; - case OP_DIV: - if (v2 == 0) return 0; /* do not attempt to divide by 0 */ - r = luai_numdiv(v1, v2); break; - case OP_MOD: - if (v2 == 0) return 0; /* do not attempt to divide by 0 */ - r = luai_nummod(v1, v2); break; - case OP_POW: r = luai_numpow(v1, v2); break; - case OP_UNM: r = luai_numunm(v1); break; - case OP_LEN: return 0; /* no constant folding for 'len' */ - default: lua_assert(0); r = 0; break; - } - if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ - e1->u.nval = r; - return 1; -} - - -static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { - if (constfolding(op, e1, e2)) - return; - else { - int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; - int o1 = luaK_exp2RK(fs, e1); - if (o1 > o2) { - freeexp(fs, e1); - freeexp(fs, e2); - } - else { - freeexp(fs, e2); - freeexp(fs, e1); - } - e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); - e1->k = VRELOCABLE; - } -} - - -static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, - expdesc *e2) { - int o1 = luaK_exp2RK(fs, e1); - int o2 = luaK_exp2RK(fs, e2); - freeexp(fs, e2); - freeexp(fs, e1); - if (cond == 0 && op != OP_EQ) { - int temp; /* exchange args to replace by `<' or `<=' */ - temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ - cond = 1; - } - e1->u.s.info = condjump(fs, op, cond, o1, o2); - e1->k = VJMP; -} - - -void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { - expdesc e2; - e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; - switch (op) { - case OPR_MINUS: { - if (!isnumeral(e)) - luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ - codearith(fs, OP_UNM, e, &e2); - break; - } - case OPR_NOT: codenot(fs, e); break; - case OPR_LEN: { - luaK_exp2anyreg(fs, e); /* cannot operate on constants */ - codearith(fs, OP_LEN, e, &e2); - break; - } - default: lua_assert(0); - } -} - - -void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { - switch (op) { - case OPR_AND: { - luaK_goiftrue(fs, v); - break; - } - case OPR_OR: { - luaK_goiffalse(fs, v); - break; - } - case OPR_CONCAT: { - luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ - break; - } - case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: - case OPR_MOD: case OPR_POW: { - if (!isnumeral(v)) luaK_exp2RK(fs, v); - break; - } - default: { - luaK_exp2RK(fs, v); - break; - } - } -} - - -void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { - switch (op) { - case OPR_AND: { - lua_assert(e1->t == NO_JUMP); /* list must be closed */ - luaK_dischargevars(fs, e2); - luaK_concat(fs, &e2->f, e1->f); -#if 0 - *e1 = *e2; -#else - memcpy (e1, e2, sizeof (*e1)); -#endif - break; - } - case OPR_OR: { - lua_assert(e1->f == NO_JUMP); /* list must be closed */ - luaK_dischargevars(fs, e2); - luaK_concat(fs, &e2->t, e1->t); -#if 0 - *e1 = *e2; -#else - memcpy (e1, e2, sizeof (*e1)); -#endif - break; - } - case OPR_CONCAT: { - luaK_exp2val(fs, e2); - if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { - lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); - freeexp(fs, e1); - SETARG_B(getcode(fs, e2), e1->u.s.info); - e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; - } - else { - luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ - codearith(fs, OP_CONCAT, e1, e2); - } - break; - } - case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; - case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; - case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; - case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; - case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; - case OPR_POW: codearith(fs, OP_POW, e1, e2); break; - case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; - case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; - case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; - case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; - case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; - case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; - default: lua_assert(0); - } -} - - -void luaK_fixline (FuncState *fs, int line) { - fs->f->lineinfo[fs->pc - 1] = line; -} - - -static int luaK_code (FuncState *fs, Instruction i, int line) { - Proto *f = fs->f; - dischargejpc(fs); /* `pc' will change */ - /* put new instruction in code array */ - luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, - MAX_INT, "code size overflow"); - f->code[fs->pc] = i; - /* save corresponding line information */ - luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, - MAX_INT, "code size overflow"); - f->lineinfo[fs->pc] = line; - return fs->pc++; -} - - -int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { - lua_assert(getOpMode(o) == iABC); - lua_assert(getBMode(o) != OpArgN || b == 0); - lua_assert(getCMode(o) != OpArgN || c == 0); - return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); -} - - -int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { - lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); - lua_assert(getCMode(o) == OpArgN); - return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); -} - - -void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { - int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; - int b = (tostore == LUA_MULTRET) ? 0 : tostore; - lua_assert(tostore != 0); - if (c <= MAXARG_C) - luaK_codeABC(fs, OP_SETLIST, base, b, c); - else { - luaK_codeABC(fs, OP_SETLIST, base, b, 0); - luaK_code(fs, cast(Instruction, c), fs->ls->lastline); - } - fs->freereg = base + 1; /* free registers with list values */ -} - diff --git a/script/lua/lcode.h b/script/lua/lcode.h deleted file mode 100644 index b941c6072..000000000 --- a/script/lua/lcode.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - -#ifndef lcode_h -#define lcode_h - -#include "llex.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" - - -/* -** Marks the end of a patch list. It is an invalid value both as an absolute -** address, and as a list link (would link an element to itself). -*/ -#define NO_JUMP (-1) - - -/* -** grep "ORDER OPR" if you change these enums -*/ -typedef enum BinOpr { - OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, - OPR_CONCAT, - OPR_NE, OPR_EQ, - OPR_LT, OPR_LE, OPR_GT, OPR_GE, - OPR_AND, OPR_OR, - OPR_NOBINOPR -} BinOpr; - - -typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; - - -#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) - -#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) - -#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) - -LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); -LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); -LUAI_FUNC void luaK_fixline (FuncState *fs, int line); -LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); -LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); -LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); -LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); -LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); -LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); -LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); -LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); -LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); -LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_jump (FuncState *fs); -LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); -LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); -LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); -LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); -LUAI_FUNC int luaK_getlabel (FuncState *fs); -LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); -LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); -LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); -LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); - - -#endif diff --git a/script/lua/ldblib.c b/script/lua/ldblib.c deleted file mode 100644 index c1c2d89db..000000000 --- a/script/lua/ldblib.c +++ /dev/null @@ -1,398 +0,0 @@ -/* -** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $ -** Interface from Lua to its debug API -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#include -#include -#endif - -#define ldblib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - -static int db_getregistry (lua_State *L) { - lua_pushvalue(L, LUA_REGISTRYINDEX); - return 1; -} - - -static int db_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); /* no metatable */ - } - return 1; -} - - -static int db_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - lua_settop(L, 2); - lua_pushboolean(L, lua_setmetatable(L, 1)); - return 1; -} - - -static int db_getfenv (lua_State *L) { - lua_getfenv(L, 1); - return 1; -} - - -static int db_setfenv (lua_State *L) { - luaL_checktype(L, 2, LUA_TTABLE); - lua_settop(L, 2); - if (lua_setfenv(L, 1) == 0) - luaL_error(L, LUA_QL("setfenv") - " cannot change environment of given object"); - return 1; -} - - -static void settabss (lua_State *L, const char *i, const char *v) { - lua_pushstring(L, v); - lua_setfield(L, -2, i); -} - - -static void settabsi (lua_State *L, const char *i, int v) { - lua_pushinteger(L, v); - lua_setfield(L, -2, i); -} - - -static lua_State *getthread (lua_State *L, int *arg) { - if (lua_isthread(L, 1)) { - *arg = 1; - return lua_tothread(L, 1); - } - else { - *arg = 0; - return L; - } -} - - -static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { - if (L == L1) { - lua_pushvalue(L, -2); - lua_remove(L, -3); - } - else - lua_xmove(L1, L, 1); - lua_setfield(L, -2, fname); -} - - -static int db_getinfo (lua_State *L) { - lua_Debug ar; - int arg; - lua_State *L1 = getthread(L, &arg); - const char *options = luaL_optstring(L, arg+2, "flnSu"); - if (lua_isnumber(L, arg+1)) { - if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { - lua_pushnil(L); /* level out of range */ - return 1; - } - } - else if (lua_isfunction(L, arg+1)) { - lua_pushfstring(L, ">%s", options); - options = lua_tostring(L, -1); - lua_pushvalue(L, arg+1); - lua_xmove(L, L1, 1); - } - else - return luaL_argerror(L, arg+1, "function or level expected"); - if (!lua_getinfo(L1, options, &ar)) - return luaL_argerror(L, arg+2, "invalid option"); - lua_createtable(L, 0, 2); - if (strchr(options, 'S')) { - settabss(L, "source", ar.source); - settabss(L, "short_src", ar.short_src); - settabsi(L, "linedefined", ar.linedefined); - settabsi(L, "lastlinedefined", ar.lastlinedefined); - settabss(L, "what", ar.what); - } - if (strchr(options, 'l')) - settabsi(L, "currentline", ar.currentline); - if (strchr(options, 'u')) - settabsi(L, "nups", ar.nups); - if (strchr(options, 'n')) { - settabss(L, "name", ar.name); - settabss(L, "namewhat", ar.namewhat); - } - if (strchr(options, 'L')) - treatstackoption(L, L1, "activelines"); - if (strchr(options, 'f')) - treatstackoption(L, L1, "func"); - return 1; /* return table */ -} - - -static int db_getlocal (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - const char *name; - if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); - if (name) { - lua_xmove(L1, L, 1); - lua_pushstring(L, name); - lua_pushvalue(L, -2); - return 2; - } - else { - lua_pushnil(L); - return 1; - } -} - - -static int db_setlocal (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - luaL_checkany(L, arg+3); - lua_settop(L, arg+3); - lua_xmove(L, L1, 1); - lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); - return 1; -} - - -static int auxupvalue (lua_State *L, int get) { - const char *name; - int n = luaL_checkint(L, 2); - luaL_checktype(L, 1, LUA_TFUNCTION); - if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ - name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); - if (name == NULL) return 0; - lua_pushstring(L, name); - lua_insert(L, -(get+1)); - return get + 1; -} - - -static int db_getupvalue (lua_State *L) { - return auxupvalue(L, 1); -} - - -static int db_setupvalue (lua_State *L) { - luaL_checkany(L, 3); - return auxupvalue(L, 0); -} - - - -static const char KEY_HOOK = 'h'; - - -static void hookf (lua_State *L, lua_Debug *ar) { - static const char *const hooknames[] = - {"call", "return", "line", "count", "tail return"}; - lua_pushlightuserdata(L, (void *)&KEY_HOOK); - lua_rawget(L, LUA_REGISTRYINDEX); - lua_pushlightuserdata(L, L); - lua_rawget(L, -2); - if (lua_isfunction(L, -1)) { - lua_pushstring(L, hooknames[(int)ar->event]); - if (ar->currentline >= 0) - lua_pushinteger(L, ar->currentline); - else lua_pushnil(L); - lua_assert(lua_getinfo(L, "lS", ar)); - lua_call(L, 2, 0); - } -} - - -static int makemask (const char *smask, int count) { - int mask = 0; - if (strchr(smask, 'c')) mask |= LUA_MASKCALL; - if (strchr(smask, 'r')) mask |= LUA_MASKRET; - if (strchr(smask, 'l')) mask |= LUA_MASKLINE; - if (count > 0) mask |= LUA_MASKCOUNT; - return mask; -} - - -static char *unmakemask (int mask, char *smask) { - int i = 0; - if (mask & LUA_MASKCALL) smask[i++] = 'c'; - if (mask & LUA_MASKRET) smask[i++] = 'r'; - if (mask & LUA_MASKLINE) smask[i++] = 'l'; - smask[i] = '\0'; - return smask; -} - - -static void gethooktable (lua_State *L) { - lua_pushlightuserdata(L, (void *)&KEY_HOOK); - lua_rawget(L, LUA_REGISTRYINDEX); - if (!lua_istable(L, -1)) { - lua_pop(L, 1); - lua_createtable(L, 0, 1); - lua_pushlightuserdata(L, (void *)&KEY_HOOK); - lua_pushvalue(L, -2); - lua_rawset(L, LUA_REGISTRYINDEX); - } -} - - -static int db_sethook (lua_State *L) { - int arg, mask, count; - lua_Hook func; - lua_State *L1 = getthread(L, &arg); - if (lua_isnoneornil(L, arg+1)) { - lua_settop(L, arg+1); - func = NULL; mask = 0; count = 0; /* turn off hooks */ - } - else { - const char *smask = luaL_checkstring(L, arg+2); - luaL_checktype(L, arg+1, LUA_TFUNCTION); - count = luaL_optint(L, arg+3, 0); - func = hookf; mask = makemask(smask, count); - } - gethooktable(L); - lua_pushlightuserdata(L, L1); - lua_pushvalue(L, arg+1); - lua_rawset(L, -3); /* set new hook */ - lua_pop(L, 1); /* remove hook table */ - lua_sethook(L1, func, mask, count); /* set hooks */ - return 0; -} - - -static int db_gethook (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - char buff[5]; - int mask = lua_gethookmask(L1); - lua_Hook hook = lua_gethook(L1); - if (hook != NULL && hook != hookf) /* external hook? */ - lua_pushliteral(L, "external hook"); - else { - gethooktable(L); - lua_pushlightuserdata(L, L1); - lua_rawget(L, -2); /* get hook */ - lua_remove(L, -2); /* remove hook table */ - } - lua_pushstring(L, unmakemask(mask, buff)); - lua_pushinteger(L, lua_gethookcount(L1)); - return 3; -} - - -static int db_debug (lua_State *L) { - for (;;) { - char buffer[250]; - fputs("lua_debug> ", stderr); - if (fgets(buffer, sizeof(buffer), stdin) == 0 || - strcmp(buffer, "cont\n") == 0) - return 0; - if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || - lua_pcall(L, 0, 0, 0)) { - fputs(lua_tostring(L, -1), stderr); - fputs("\n", stderr); - } - lua_settop(L, 0); /* remove eventual returns */ - } -} - - -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ - -static int db_errorfb (lua_State *L) { - int level; - int firstpart = 1; /* still before eventual `...' */ - int arg; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - if (lua_isnumber(L, arg+2)) { - level = (int)lua_tointeger(L, arg+2); - lua_pop(L, 1); - } - else - level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ - if (lua_gettop(L) == arg) - lua_pushliteral(L, ""); - else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ - else lua_pushliteral(L, "\n"); - lua_pushliteral(L, "stack traceback:"); - while (lua_getstack(L1, level++, &ar)) { - if (level > LEVELS1 && firstpart) { - /* no more than `LEVELS2' more levels? */ - if (!lua_getstack(L1, level+LEVELS2, &ar)) - level--; /* keep going */ - else { - lua_pushliteral(L, "\n\t..."); /* too many levels */ - while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ - level++; - } - firstpart = 0; - continue; - } - lua_pushliteral(L, "\n\t"); - lua_getinfo(L1, "Snl", &ar); - lua_pushfstring(L, "%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - if (*ar.namewhat != '\0') /* is there a name? */ - lua_pushfstring(L, " in function " LUA_QS, ar.name); - else { - if (*ar.what == 'm') /* main? */ - lua_pushfstring(L, " in main chunk"); - else if (*ar.what == 'C' || *ar.what == 't') - lua_pushliteral(L, " ?"); /* C function or tail call */ - else - lua_pushfstring(L, " in function <%s:%d>", - ar.short_src, ar.linedefined); - } - lua_concat(L, lua_gettop(L) - arg); - } - lua_concat(L, lua_gettop(L) - arg); - return 1; -} - - -static const luaL_Reg dblib[] = { - {"debug", db_debug}, - {"getfenv", db_getfenv}, - {"gethook", db_gethook}, - {"getinfo", db_getinfo}, - {"getlocal", db_getlocal}, - {"getregistry", db_getregistry}, - {"getmetatable", db_getmetatable}, - {"getupvalue", db_getupvalue}, - {"setfenv", db_setfenv}, - {"sethook", db_sethook}, - {"setlocal", db_setlocal}, - {"setmetatable", db_setmetatable}, - {"setupvalue", db_setupvalue}, - {"traceback", db_errorfb}, - {NULL, NULL} -}; - - -LUALIB_API int luaopen_debug (lua_State *L) { - luaL_register(L, LUA_DBLIBNAME, dblib); - return 1; -} - diff --git a/script/lua/ldebug.c b/script/lua/ldebug.c deleted file mode 100644 index 25e790c4d..000000000 --- a/script/lua/ldebug.c +++ /dev/null @@ -1,638 +0,0 @@ -/* -** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ -** Debug Interface -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#include -#include -#endif - -#define ldebug_c -#define LUA_CORE - -#include "lua.h" - -#include "lapi.h" -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - - -static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); - - -static int currentpc (lua_State *L, CallInfo *ci) { - if (!isLua(ci)) return -1; /* function is not a Lua function? */ - if (ci == L->ci) - ci->savedpc = L->savedpc; - return pcRel(ci->savedpc, ci_func(ci)->l.p); -} - - -static int currentline (lua_State *L, CallInfo *ci) { - int pc = currentpc(L, ci); - if (pc < 0) - return -1; /* only active lua functions have current-line information */ - else - return getline(ci_func(ci)->l.p, pc); -} - - -/* -** this function can be called asynchronous (e.g. during a signal) -*/ -LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { - if (func == NULL || mask == 0) { /* turn off hooks? */ - mask = 0; - func = NULL; - } - L->hook = func; - L->basehookcount = count; - resethookcount(L); - L->hookmask = cast_byte(mask); - return 1; -} - - -LUA_API lua_Hook lua_gethook (lua_State *L) { - return L->hook; -} - - -LUA_API int lua_gethookmask (lua_State *L) { - return L->hookmask; -} - - -LUA_API int lua_gethookcount (lua_State *L) { - return L->basehookcount; -} - - -LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { - int status; - CallInfo *ci; - lua_lock(L); - for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { - level--; - if (f_isLua(ci)) /* Lua function? */ - level -= ci->tailcalls; /* skip lost tail calls */ - } - if (level == 0 && ci > L->base_ci) { /* level found? */ - status = 1; - ar->i_ci = cast_int(ci - L->base_ci); - } - else if (level < 0) { /* level is of a lost tail call? */ - status = 1; - ar->i_ci = 0; - } - else status = 0; /* no such level */ - lua_unlock(L); - return status; -} - - -static Proto *getluaproto (CallInfo *ci) { - return (isLua(ci) ? ci_func(ci)->l.p : NULL); -} - - -static const char *findlocal (lua_State *L, CallInfo *ci, int n) { - const char *name; - Proto *fp = getluaproto(ci); - if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) - return name; /* is a local variable in a Lua function */ - else { - StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; - if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ - return "(*temporary)"; - else - return NULL; - } -} - - -LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { - CallInfo *ci = L->base_ci + ar->i_ci; - const char *name = findlocal(L, ci, n); - lua_lock(L); - if (name) - luaA_pushobject(L, ci->base + (n - 1)); - lua_unlock(L); - return name; -} - - -LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { - CallInfo *ci = L->base_ci + ar->i_ci; - const char *name = findlocal(L, ci, n); - lua_lock(L); - if (name) - setobjs2s(L, ci->base + (n - 1), L->top - 1); - L->top--; /* pop value */ - lua_unlock(L); - return name; -} - - -static void funcinfo (lua_Debug *ar, Closure *cl) { - if (cl->c.isC) { - ar->source = "=[C]"; - ar->linedefined = -1; - ar->lastlinedefined = -1; - ar->what = "C"; - } - else { - ar->source = getstr(cl->l.p->source); - ar->linedefined = cl->l.p->linedefined; - ar->lastlinedefined = cl->l.p->lastlinedefined; - ar->what = (ar->linedefined == 0) ? "main" : "Lua"; - } - luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); -} - - -static void info_tailcall (lua_Debug *ar) { - ar->name = ar->namewhat = ""; - ar->what = "tail"; - ar->lastlinedefined = ar->linedefined = ar->currentline = -1; - ar->source = "=(tail call)"; - luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); - ar->nups = 0; -} - - -static void collectvalidlines (lua_State *L, Closure *f) { - if (f == NULL || f->c.isC) { - setnilvalue(L->top); - } - else { - Table *t = luaH_new(L, 0, 0); - int *lineinfo = f->l.p->lineinfo; - int i; - for (i=0; il.p->sizelineinfo; i++) - setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); - sethvalue(L, L->top, t); - } - incr_top(L); -} - - -static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, - Closure *f, CallInfo *ci) { - int status = 1; - if (f == NULL) { - info_tailcall(ar); - return status; - } - for (; *what; what++) { - switch (*what) { - case 'S': { - funcinfo(ar, f); - break; - } - case 'l': { - ar->currentline = (ci) ? currentline(L, ci) : -1; - break; - } - case 'u': { - ar->nups = f->c.nupvalues; - break; - } - case 'n': { - ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; - if (ar->namewhat == NULL) { - ar->namewhat = ""; /* not found */ - ar->name = NULL; - } - break; - } - case 'L': - case 'f': /* handled by lua_getinfo */ - break; - default: status = 0; /* invalid option */ - } - } - return status; -} - - -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { - int status; - Closure *f = NULL; - CallInfo *ci = NULL; - lua_lock(L); - if (*what == '>') { - StkId func = L->top - 1; - luai_apicheck(L, ttisfunction(func)); - what++; /* skip the '>' */ - f = clvalue(func); - L->top--; /* pop function */ - } - else if (ar->i_ci != 0) { /* no tail call? */ - ci = L->base_ci + ar->i_ci; - lua_assert(ttisfunction(ci->func)); - f = clvalue(ci->func); - } - status = auxgetinfo(L, what, ar, f, ci); - if (strchr(what, 'f')) { - if (f == NULL) setnilvalue(L->top); - else setclvalue(L, L->top, f); - incr_top(L); - } - if (strchr(what, 'L')) - collectvalidlines(L, f); - lua_unlock(L); - return status; -} - - -/* -** {====================================================== -** Symbolic Execution and code checker -** ======================================================= -*/ - -#define check(x) if (!(x)) return 0; - -#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) - -#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) - - - -static int precheck (const Proto *pt) { - check(pt->maxstacksize <= MAXSTACK); - check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); - check(!(pt->is_vararg & VARARG_NEEDSARG) || - (pt->is_vararg & VARARG_HASARG)); - check(pt->sizeupvalues <= pt->nups); - check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); - check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); - return 1; -} - - -#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) - -int luaG_checkopenop (Instruction i) { - switch (GET_OPCODE(i)) { - case OP_CALL: - case OP_TAILCALL: - case OP_RETURN: - case OP_SETLIST: { - check(GETARG_B(i) == 0); - return 1; - } - default: return 0; /* invalid instruction after an open call */ - } -} - - -static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { - switch (mode) { - case OpArgN: check(r == 0); break; - case OpArgU: break; - case OpArgR: checkreg(pt, r); break; - case OpArgK: - check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); - break; - } - return 1; -} - - -static Instruction symbexec (const Proto *pt, int lastpc, int reg) { - int pc; - int last; /* stores position of last instruction that changed `reg' */ - last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ - check(precheck(pt)); - for (pc = 0; pc < lastpc; pc++) { - Instruction i = pt->code[pc]; - OpCode op = GET_OPCODE(i); - int a = GETARG_A(i); - int b = 0; - int c = 0; - check(op < NUM_OPCODES); - checkreg(pt, a); - switch (getOpMode(op)) { - case iABC: { - b = GETARG_B(i); - c = GETARG_C(i); - check(checkArgMode(pt, b, getBMode(op))); - check(checkArgMode(pt, c, getCMode(op))); - break; - } - case iABx: { - b = GETARG_Bx(i); - if (getBMode(op) == OpArgK) check(b < pt->sizek); - break; - } - case iAsBx: { - b = GETARG_sBx(i); - if (getBMode(op) == OpArgR) { - int dest = pc+1+b; - check(0 <= dest && dest < pt->sizecode); - if (dest > 0) { - int j; - /* check that it does not jump to a setlist count; this - is tricky, because the count from a previous setlist may - have the same value of an invalid setlist; so, we must - go all the way back to the first of them (if any) */ - for (j = 0; j < dest; j++) { - Instruction d = pt->code[dest-1-j]; - if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; - } - /* if 'j' is even, previous value is not a setlist (even if - it looks like one) */ - check((j&1) == 0); - } - } - break; - } - } - if (testAMode(op)) { - if (a == reg) last = pc; /* change register `a' */ - } - if (testTMode(op)) { - check(pc+2 < pt->sizecode); /* check skip */ - check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); - } - switch (op) { - case OP_LOADBOOL: { - if (c == 1) { /* does it jump? */ - check(pc+2 < pt->sizecode); /* check its jump */ - check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || - GETARG_C(pt->code[pc+1]) != 0); - } - break; - } - case OP_LOADNIL: { - if (a <= reg && reg <= b) - last = pc; /* set registers from `a' to `b' */ - break; - } - case OP_GETUPVAL: - case OP_SETUPVAL: { - check(b < pt->nups); - break; - } - case OP_GETGLOBAL: - case OP_SETGLOBAL: { - check(ttisstring(&pt->k[b])); - break; - } - case OP_SELF: { - checkreg(pt, a+1); - if (reg == a+1) last = pc; - break; - } - case OP_CONCAT: { - check(b < c); /* at least two operands */ - break; - } - case OP_TFORLOOP: { - check(c >= 1); /* at least one result (control variable) */ - checkreg(pt, a+2+c); /* space for results */ - if (reg >= a+2) last = pc; /* affect all regs above its base */ - break; - } - case OP_FORLOOP: - case OP_FORPREP: - checkreg(pt, a+3); - /* go through */ - case OP_JMP: { - int dest = pc+1+b; - /* not full check and jump is forward and do not skip `lastpc'? */ - if (reg != NO_REG && pc < dest && dest <= lastpc) - pc += b; /* do the jump */ - break; - } - case OP_CALL: - case OP_TAILCALL: { - if (b != 0) { - checkreg(pt, a+b-1); - } - c--; /* c = num. returns */ - if (c == LUA_MULTRET) { - check(checkopenop(pt, pc)); - } - else if (c != 0) - checkreg(pt, a+c-1); - if (reg >= a) last = pc; /* affect all registers above base */ - break; - } - case OP_RETURN: { - b--; /* b = num. returns */ - if (b > 0) checkreg(pt, a+b-1); - break; - } - case OP_SETLIST: { - if (b > 0) checkreg(pt, a + b); - if (c == 0) { - pc++; - check(pc < pt->sizecode - 1); - } - break; - } - case OP_CLOSURE: { - int nup, j; - check(b < pt->sizep); - nup = pt->p[b]->nups; - check(pc + nup < pt->sizecode); - for (j = 1; j <= nup; j++) { - OpCode op1 = GET_OPCODE(pt->code[pc + j]); - check(op1 == OP_GETUPVAL || op1 == OP_MOVE); - } - if (reg != NO_REG) /* tracing? */ - pc += nup; /* do not 'execute' these pseudo-instructions */ - break; - } - case OP_VARARG: { - check((pt->is_vararg & VARARG_ISVARARG) && - !(pt->is_vararg & VARARG_NEEDSARG)); - b--; - if (b == LUA_MULTRET) check(checkopenop(pt, pc)); - checkreg(pt, a+b-1); - break; - } - default: break; - } - } - return pt->code[last]; -} - -#undef check -#undef checkjump -#undef checkreg - -/* }====================================================== */ - - -int luaG_checkcode (const Proto *pt) { - return (symbexec(pt, pt->sizecode, NO_REG) != 0); -} - - -static const char *kname (Proto *p, int c) { - if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) - return svalue(&p->k[INDEXK(c)]); - else - return "?"; -} - - -static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, - const char **name) { - if (isLua(ci)) { /* a Lua function? */ - Proto *p = ci_func(ci)->l.p; - int pc = currentpc(L, ci); - Instruction i; - *name = luaF_getlocalname(p, stackpos+1, pc); - if (*name) /* is a local? */ - return "local"; - i = symbexec(p, pc, stackpos); /* try symbolic execution */ - lua_assert(pc != -1); - switch (GET_OPCODE(i)) { - case OP_GETGLOBAL: { - int g = GETARG_Bx(i); /* global index */ - lua_assert(ttisstring(&p->k[g])); - *name = svalue(&p->k[g]); - return "global"; - } - case OP_MOVE: { - int a = GETARG_A(i); - int b = GETARG_B(i); /* move from `b' to `a' */ - if (b < a) - return getobjname(L, ci, b, name); /* get name for `b' */ - break; - } - case OP_GETTABLE: { - int k = GETARG_C(i); /* key index */ - *name = kname(p, k); - return "field"; - } - case OP_GETUPVAL: { - int u = GETARG_B(i); /* upvalue index */ - *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; - return "upvalue"; - } - case OP_SELF: { - int k = GETARG_C(i); /* key index */ - *name = kname(p, k); - return "method"; - } - default: break; - } - } - return NULL; /* no useful name found */ -} - - -static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { - Instruction i; - if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) - return NULL; /* calling function is not Lua (or is unknown) */ - ci--; /* calling function */ - i = ci_func(ci)->l.p->code[currentpc(L, ci)]; - if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || - GET_OPCODE(i) == OP_TFORLOOP) - return getobjname(L, ci, GETARG_A(i), name); - else - return NULL; /* no useful name can be found */ -} - - -/* only ANSI way to check whether a pointer points to an array */ -static int isinstack (CallInfo *ci, const TValue *o) { - StkId p; - for (p = ci->base; p < ci->top; p++) - if (o == p) return 1; - return 0; -} - - -void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { - const char *name = NULL; - const char *t = luaT_typenames[ttype(o)]; - const char *kind = (isinstack(L->ci, o)) ? - getobjname(L, L->ci, cast_int(o - L->base), &name) : - NULL; - if (kind) - luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", - op, kind, name, t); - else - luaG_runerror(L, "attempt to %s a %s value", op, t); -} - - -void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { - if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; - lua_assert(!ttisstring(p1) && !ttisnumber(p1)); - luaG_typeerror(L, p1, "concatenate"); -} - - -void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { - TValue temp; - if (luaV_tonumber(p1, &temp) == NULL) - p2 = p1; /* first operand is wrong */ - luaG_typeerror(L, p2, "perform arithmetic on"); -} - - -int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { - const char *t1 = luaT_typenames[ttype(p1)]; - const char *t2 = luaT_typenames[ttype(p2)]; - if (t1[2] == t2[2]) - luaG_runerror(L, "attempt to compare two %s values", t1); - else - luaG_runerror(L, "attempt to compare %s with %s", t1, t2); - return 0; -} - - -static void addinfo (lua_State *L, const char *msg) { - CallInfo *ci = L->ci; - if (isLua(ci)) { /* is Lua code? */ - char buff[LUA_IDSIZE]; /* add file:line information */ - int line = currentline(L, ci); - luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); - luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); - } -} - - -void luaG_errormsg (lua_State *L) { - if (L->errfunc != 0) { /* is there an error handling function? */ - StkId errfunc = restorestack(L, L->errfunc); - if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); - setobjs2s(L, L->top, L->top - 1); /* move argument */ - setobjs2s(L, L->top - 1, errfunc); /* push function */ - incr_top(L); - luaD_call(L, L->top - 2, 1); /* call it */ - } - luaD_throw(L, LUA_ERRRUN); -} - - -void luaG_runerror (lua_State *L, const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - addinfo(L, luaO_pushvfstring(L, fmt, argp)); - va_end(argp); - luaG_errormsg(L); -} - diff --git a/script/lua/ldebug.h b/script/lua/ldebug.h deleted file mode 100644 index ba28a9724..000000000 --- a/script/lua/ldebug.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ -** Auxiliary functions from Debug Interface module -** See Copyright Notice in lua.h -*/ - -#ifndef ldebug_h -#define ldebug_h - - -#include "lstate.h" - - -#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) - -#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) - -#define resethookcount(L) (L->hookcount = L->basehookcount) - - -LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, - const char *opname); -LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); -LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); -LUAI_FUNC void luaG_errormsg (lua_State *L); -LUAI_FUNC int luaG_checkcode (const Proto *pt); -LUAI_FUNC int luaG_checkopenop (Instruction i); - -#endif diff --git a/script/lua/ldo.c b/script/lua/ldo.c deleted file mode 100644 index a267e7bfe..000000000 --- a/script/lua/ldo.c +++ /dev/null @@ -1,519 +0,0 @@ -/* -** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#include -#include -#endif - -#define ldo_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" -#include "lzio.h" - - - - -/* -** {====================================================== -** Error-recovery functions -** ======================================================= -*/ - - -/* chain list of long jump buffers */ -struct lua_longjmp { - struct lua_longjmp *previous; - luai_jmpbuf b; - volatile int status; /* error code */ -}; - - -void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { - switch (errcode) { - case LUA_ERRMEM: { - setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); - break; - } - case LUA_ERRERR: { - setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); - break; - } - case LUA_ERRSYNTAX: - case LUA_ERRRUN: { - setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ - break; - } - } - L->top = oldtop + 1; -} - - -static void restore_stack_limit (lua_State *L) { - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); - if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ - int inuse = cast_int(L->ci - L->base_ci); - if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ - luaD_reallocCI(L, LUAI_MAXCALLS); - } -} - - -static void resetstack (lua_State *L, int status) { - L->ci = L->base_ci; - L->base = L->ci->base; - luaF_close(L, L->base); /* close eventual pending closures */ - luaD_seterrorobj(L, status, L->base); - L->nCcalls = L->baseCcalls; - L->allowhook = 1; - restore_stack_limit(L); - L->errfunc = 0; - L->errorJmp = NULL; -} - - -void luaD_throw (lua_State *L, int errcode) { - if (L->errorJmp) { - L->errorJmp->status = errcode; - LUAI_THROW(L, L->errorJmp); - } - else { - L->status = cast_byte(errcode); - if (G(L)->panic) { - resetstack(L, errcode); - lua_unlock(L); - G(L)->panic(L); - } - exit(EXIT_FAILURE); - } -} - - -int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { - struct lua_longjmp lj; - lj.status = 0; - lj.previous = L->errorJmp; /* chain new error handler */ - L->errorJmp = &lj; - LUAI_TRY(L, &lj, - (*f)(L, ud); - ); - L->errorJmp = lj.previous; /* restore old error handler */ - return lj.status; -} - -/* }====================================================== */ - - -static void correctstack (lua_State *L, TValue *oldstack) { - CallInfo *ci; - GCObject *up; - L->top = (L->top - oldstack) + L->stack; - for (up = L->openupval; up != NULL; up = up->gch.next) - gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; - for (ci = L->base_ci; ci <= L->ci; ci++) { - ci->top = (ci->top - oldstack) + L->stack; - ci->base = (ci->base - oldstack) + L->stack; - ci->func = (ci->func - oldstack) + L->stack; - } - L->base = (L->base - oldstack) + L->stack; -} - - -void luaD_reallocstack (lua_State *L, int newsize) { - TValue *oldstack = L->stack; - int realsize = newsize + 1 + EXTRA_STACK; - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); - luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); - L->stacksize = realsize; - L->stack_last = L->stack+newsize; - correctstack(L, oldstack); -} - - -void luaD_reallocCI (lua_State *L, int newsize) { - CallInfo *oldci = L->base_ci; - luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); - L->size_ci = newsize; - L->ci = (L->ci - oldci) + L->base_ci; - L->end_ci = L->base_ci + L->size_ci - 1; -} - - -void luaD_growstack (lua_State *L, int n) { - if (n <= L->stacksize) /* double size is enough? */ - luaD_reallocstack(L, 2*L->stacksize); - else - luaD_reallocstack(L, L->stacksize + n); -} - - -static CallInfo *growCI (lua_State *L) { - if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ - luaD_throw(L, LUA_ERRERR); - else { - luaD_reallocCI(L, 2*L->size_ci); - if (L->size_ci > LUAI_MAXCALLS) - luaG_runerror(L, "stack overflow"); - } - return ++L->ci; -} - - -void luaD_callhook (lua_State *L, int event, int line) { - lua_Hook hook = L->hook; - if (hook && L->allowhook) { - ptrdiff_t top = savestack(L, L->top); - ptrdiff_t ci_top = savestack(L, L->ci->top); - lua_Debug ar; - ar.event = event; - ar.currentline = line; - if (event == LUA_HOOKTAILRET) - ar.i_ci = 0; /* tail call; no debug information about it */ - else - ar.i_ci = cast_int(L->ci - L->base_ci); - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - L->ci->top = L->top + LUA_MINSTACK; - lua_assert(L->ci->top <= L->stack_last); - L->allowhook = 0; /* cannot call hooks inside a hook */ - lua_unlock(L); - (*hook)(L, &ar); - lua_lock(L); - lua_assert(!L->allowhook); - L->allowhook = 1; - L->ci->top = restorestack(L, ci_top); - L->top = restorestack(L, top); - } -} - - -static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { - int i; - int nfixargs = p->numparams; - Table *htab = NULL; - StkId base, fixed; - for (; actual < nfixargs; ++actual) - setnilvalue(L->top++); -#if defined(LUA_COMPAT_VARARG) - if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ - int nvar = actual - nfixargs; /* number of extra arguments */ - lua_assert(p->is_vararg & VARARG_HASARG); - luaC_checkGC(L); - htab = luaH_new(L, nvar, 1); /* create `arg' table */ - for (i=0; itop - nvar + i); - /* store counter in field `n' */ - setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); - } -#endif - /* move fixed parameters to final position */ - fixed = L->top - actual; /* first fixed argument */ - base = L->top; /* final position of first argument */ - for (i=0; itop++, fixed+i); - setnilvalue(fixed+i); - } - /* add `arg' parameter */ - if (htab) { - sethvalue(L, L->top++, htab); - lua_assert(iswhite(obj2gco(htab))); - } - return base; -} - - -static StkId tryfuncTM (lua_State *L, StkId func) { - const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); - StkId p; - ptrdiff_t funcr = savestack(L, func); - if (!ttisfunction(tm)) - luaG_typeerror(L, func, "call"); - /* Open a hole inside the stack at `func' */ - for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); - incr_top(L); - func = restorestack(L, funcr); /* previous call may change stack */ - setobj2s(L, func, tm); /* tag method is the new function to be called */ - return func; -} - - - -#define inc_ci(L) \ - ((L->ci == L->end_ci) ? growCI(L) : \ - (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) - - -int luaD_precall (lua_State *L, StkId func, int nresults) { - LClosure *cl; - ptrdiff_t funcr; - if (!ttisfunction(func)) /* `func' is not a function? */ - func = tryfuncTM(L, func); /* check the `function' tag method */ - funcr = savestack(L, func); - cl = &clvalue(func)->l; - L->ci->savedpc = L->savedpc; - if (!cl->isC) { /* Lua function? prepare its call */ - CallInfo *ci; - StkId st, base; - Proto *p = cl->p; - luaD_checkstack(L, p->maxstacksize); - func = restorestack(L, funcr); - if (!p->is_vararg) { /* no varargs? */ - base = func + 1; - if (L->top > base + p->numparams) - L->top = base + p->numparams; - } - else { /* vararg function */ - int nargs = cast_int(L->top - func) - 1; - base = adjust_varargs(L, p, nargs); - func = restorestack(L, funcr); /* previous call may change the stack */ - } - ci = inc_ci(L); /* now `enter' new function */ - ci->func = func; - L->base = ci->base = base; - ci->top = L->base + p->maxstacksize; - lua_assert(ci->top <= L->stack_last); - L->savedpc = p->code; /* starting point */ - ci->tailcalls = 0; - ci->nresults = nresults; - for (st = L->top; st < ci->top; st++) - setnilvalue(st); - L->top = ci->top; - if (L->hookmask & LUA_MASKCALL) { - L->savedpc++; /* hooks assume 'pc' is already incremented */ - luaD_callhook(L, LUA_HOOKCALL, -1); - L->savedpc--; /* correct 'pc' */ - } - return PCRLUA; - } - else { /* if is a C function, call it */ - CallInfo *ci; - int n; - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci = inc_ci(L); /* now `enter' new function */ - ci->func = restorestack(L, funcr); - L->base = ci->base = ci->func + 1; - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - ci->nresults = nresults; - if (L->hookmask & LUA_MASKCALL) - luaD_callhook(L, LUA_HOOKCALL, -1); - lua_unlock(L); - n = (*curr_func(L)->c.f)(L); /* do the actual call */ - lua_lock(L); - if (n < 0) /* yielding? */ - return PCRYIELD; - else { - luaD_poscall(L, L->top - n); - return PCRC; - } - } -} - - -static StkId callrethooks (lua_State *L, StkId firstResult) { - ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ - luaD_callhook(L, LUA_HOOKRET, -1); - if (f_isLua(L->ci)) { /* Lua function? */ - while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ - luaD_callhook(L, LUA_HOOKTAILRET, -1); - } - return restorestack(L, fr); -} - - -int luaD_poscall (lua_State *L, StkId firstResult) { - StkId res; - int wanted, i; - CallInfo *ci; - if (L->hookmask & LUA_MASKRET) - firstResult = callrethooks(L, firstResult); - ci = L->ci--; - res = ci->func; /* res == final position of 1st result */ - wanted = ci->nresults; - L->base = (ci - 1)->base; /* restore base */ - L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ - /* move results to correct place */ - for (i = wanted; i != 0 && firstResult < L->top; i--) - setobjs2s(L, res++, firstResult++); - while (i-- > 0) - setnilvalue(res++); - L->top = res; - return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ -} - - -/* -** Call a function (C or Lua). The function to be called is at *func. -** The arguments are on the stack, right after the function. -** When returns, all the results are on the stack, starting at the original -** function position. -*/ -void luaD_call (lua_State *L, StkId func, int nResults) { - if (++L->nCcalls >= LUAI_MAXCCALLS) { - if (L->nCcalls == LUAI_MAXCCALLS) - luaG_runerror(L, "C stack overflow"); - else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) - luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ - } - if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ - luaV_execute(L, 1); /* call it */ - L->nCcalls--; - luaC_checkGC(L); -} - - -static void resume (lua_State *L, void *ud) { - StkId firstArg = cast(StkId, ud); - CallInfo *ci = L->ci; - if (L->status == 0) { /* start coroutine? */ - lua_assert(ci == L->base_ci && firstArg > L->base); - if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) - return; - } - else { /* resuming from previous yield */ - lua_assert(L->status == LUA_YIELD); - L->status = 0; - if (!f_isLua(ci)) { /* `common' yield? */ - /* finish interrupted execution of `OP_CALL' */ - lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || - GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); - if (luaD_poscall(L, firstArg)) /* complete it... */ - L->top = L->ci->top; /* and correct top if not multiple results */ - } - else /* yielded inside a hook: just continue its execution */ - L->base = L->ci->base; - } - luaV_execute(L, cast_int(L->ci - L->base_ci)); -} - - -static int resume_error (lua_State *L, const char *msg) { - L->top = L->ci->base; - setsvalue2s(L, L->top, luaS_new(L, msg)); - incr_top(L); - lua_unlock(L); - return LUA_ERRRUN; -} - - -LUA_API int lua_resume (lua_State *L, int nargs) { - int status; - lua_lock(L); - if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) - return resume_error(L, "cannot resume non-suspended coroutine"); - if (L->nCcalls >= LUAI_MAXCCALLS) - return resume_error(L, "C stack overflow"); - luai_userstateresume(L, nargs); - lua_assert(L->errfunc == 0); - L->baseCcalls = ++L->nCcalls; - status = luaD_rawrunprotected(L, resume, L->top - nargs); - if (status != 0) { /* error? */ - L->status = cast_byte(status); /* mark thread as `dead' */ - luaD_seterrorobj(L, status, L->top); - L->ci->top = L->top; - } - else { - lua_assert(L->nCcalls == L->baseCcalls); - status = L->status; - } - --L->nCcalls; - lua_unlock(L); - return status; -} - - -LUA_API int lua_yield (lua_State *L, int nresults) { - luai_userstateyield(L, nresults); - lua_lock(L); - if (L->nCcalls > L->baseCcalls) - luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); - L->base = L->top - nresults; /* protect stack slots below */ - L->status = LUA_YIELD; - lua_unlock(L); - return -1; -} - - -int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t old_top, ptrdiff_t ef) { - int status; - unsigned short oldnCcalls = L->nCcalls; - ptrdiff_t old_ci = saveci(L, L->ci); - lu_byte old_allowhooks = L->allowhook; - ptrdiff_t old_errfunc = L->errfunc; - L->errfunc = ef; - status = luaD_rawrunprotected(L, func, u); - if (status != 0) { /* an error occurred? */ - StkId oldtop = restorestack(L, old_top); - luaF_close(L, oldtop); /* close eventual pending closures */ - luaD_seterrorobj(L, status, oldtop); - L->nCcalls = oldnCcalls; - L->ci = restoreci(L, old_ci); - L->base = L->ci->base; - L->savedpc = L->ci->savedpc; - L->allowhook = old_allowhooks; - restore_stack_limit(L); - } - L->errfunc = old_errfunc; - return status; -} - - - -/* -** Execute a protected parser. -*/ -struct SParser { /* data to `f_parser' */ - ZIO *z; - Mbuffer buff; /* buffer to be used by the scanner */ - const char *name; -}; - -static void f_parser (lua_State *L, void *ud) { - int i; - Proto *tf; - Closure *cl; - struct SParser *p = cast(struct SParser *, ud); - int c = luaZ_lookahead(p->z); - luaC_checkGC(L); - tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, - &p->buff, p->name); - cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); - cl->l.p = tf; - for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ - cl->l.upvals[i] = luaF_newupval(L); - setclvalue(L, L->top, cl); - incr_top(L); -} - - -int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { - struct SParser p; - int status; - p.z = z; p.name = name; - luaZ_initbuffer(L, &p.buff); - status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); - luaZ_freebuffer(L, &p.buff); - return status; -} - - diff --git a/script/lua/ldo.h b/script/lua/ldo.h deleted file mode 100644 index 98fddac59..000000000 --- a/script/lua/ldo.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - -#ifndef ldo_h -#define ldo_h - - -#include "lobject.h" -#include "lstate.h" -#include "lzio.h" - - -#define luaD_checkstack(L,n) \ - if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ - luaD_growstack(L, n); \ - else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); - - -#define incr_top(L) {luaD_checkstack(L,1); L->top++;} - -#define savestack(L,p) ((char *)(p) - (char *)L->stack) -#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) - -#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) -#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) - - -/* results from luaD_precall */ -#define PCRLUA 0 /* initiated a call to a Lua function */ -#define PCRC 1 /* did a call to a C function */ -#define PCRYIELD 2 /* C funtion yielded */ - - -/* type of protected functions, to be ran by `runprotected' */ -typedef void (*Pfunc) (lua_State *L, void *ud); - -LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); -LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); -LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); -LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); -LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t oldtop, ptrdiff_t ef); -LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); -LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); -LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); -LUAI_FUNC void luaD_growstack (lua_State *L, int n); - -LUAI_FUNC void luaD_throw (lua_State *L, int errcode); -LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); - -LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); - -#endif - diff --git a/script/lua/ldump.c b/script/lua/ldump.c deleted file mode 100644 index c9d3d4870..000000000 --- a/script/lua/ldump.c +++ /dev/null @@ -1,164 +0,0 @@ -/* -** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ -** save precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#include - -#define ldump_c -#define LUA_CORE - -#include "lua.h" - -#include "lobject.h" -#include "lstate.h" -#include "lundump.h" - -typedef struct { - lua_State* L; - lua_Writer writer; - void* data; - int strip; - int status; -} DumpState; - -#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) -#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) - -static void DumpBlock(const void* b, size_t size, DumpState* D) -{ - if (D->status==0) - { - lua_unlock(D->L); - D->status=(*D->writer)(D->L,b,size,D->data); - lua_lock(D->L); - } -} - -static void DumpChar(int y, DumpState* D) -{ - char x=(char)y; - DumpVar(x,D); -} - -static void DumpInt(int x, DumpState* D) -{ - DumpVar(x,D); -} - -static void DumpNumber(lua_Number x, DumpState* D) -{ - DumpVar(x,D); -} - -static void DumpVector(const void* b, int n, size_t size, DumpState* D) -{ - DumpInt(n,D); - DumpMem(b,n,size,D); -} - -static void DumpString(const TString* s, DumpState* D) -{ - if (s==NULL || getstr(s)==NULL) - { - size_t size=0; - DumpVar(size,D); - } - else - { - size_t size=s->tsv.len+1; /* include trailing '\0' */ - DumpVar(size,D); - DumpBlock(getstr(s),size,D); - } -} - -#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) - -static void DumpFunction(const Proto* f, const TString* p, DumpState* D); - -static void DumpConstants(const Proto* f, DumpState* D) -{ - int i,n=f->sizek; - DumpInt(n,D); - for (i=0; ik[i]; - DumpChar(ttype(o),D); - switch (ttype(o)) - { - case LUA_TNIL: - break; - case LUA_TBOOLEAN: - DumpChar(bvalue(o),D); - break; - case LUA_TNUMBER: - DumpNumber(nvalue(o),D); - break; - case LUA_TSTRING: - DumpString(rawtsvalue(o),D); - break; - default: - lua_assert(0); /* cannot happen */ - break; - } - } - n=f->sizep; - DumpInt(n,D); - for (i=0; ip[i],f->source,D); -} - -static void DumpDebug(const Proto* f, DumpState* D) -{ - int i,n; - n= (D->strip) ? 0 : f->sizelineinfo; - DumpVector(f->lineinfo,n,sizeof(int),D); - n= (D->strip) ? 0 : f->sizelocvars; - DumpInt(n,D); - for (i=0; ilocvars[i].varname,D); - DumpInt(f->locvars[i].startpc,D); - DumpInt(f->locvars[i].endpc,D); - } - n= (D->strip) ? 0 : f->sizeupvalues; - DumpInt(n,D); - for (i=0; iupvalues[i],D); -} - -static void DumpFunction(const Proto* f, const TString* p, DumpState* D) -{ - DumpString((f->source==p || D->strip) ? NULL : f->source,D); - DumpInt(f->linedefined,D); - DumpInt(f->lastlinedefined,D); - DumpChar(f->nups,D); - DumpChar(f->numparams,D); - DumpChar(f->is_vararg,D); - DumpChar(f->maxstacksize,D); - DumpCode(f,D); - DumpConstants(f,D); - DumpDebug(f,D); -} - -static void DumpHeader(DumpState* D) -{ - char h[LUAC_HEADERSIZE]; - luaU_header(h); - DumpBlock(h,LUAC_HEADERSIZE,D); -} - -/* -** dump Lua function as precompiled chunk -*/ -int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) -{ - DumpState D; - D.L=L; - D.writer=w; - D.data=data; - D.strip=strip; - D.status=0; - DumpHeader(&D); - DumpFunction(f,NULL,&D); - return D.status; -} diff --git a/script/lua/lfunc.c b/script/lua/lfunc.c deleted file mode 100644 index 813e88f58..000000000 --- a/script/lua/lfunc.c +++ /dev/null @@ -1,174 +0,0 @@ -/* -** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - - -#include - -#define lfunc_c -#define LUA_CORE - -#include "lua.h" - -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { - Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); - luaC_link(L, obj2gco(c), LUA_TFUNCTION); - c->c.isC = 1; - c->c.env = e; - c->c.nupvalues = cast_byte(nelems); - return c; -} - - -Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { - Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); - luaC_link(L, obj2gco(c), LUA_TFUNCTION); - c->l.isC = 0; - c->l.env = e; - c->l.nupvalues = cast_byte(nelems); - while (nelems--) c->l.upvals[nelems] = NULL; - return c; -} - - -UpVal *luaF_newupval (lua_State *L) { - UpVal *uv = luaM_new(L, UpVal); - luaC_link(L, obj2gco(uv), LUA_TUPVAL); - uv->v = &uv->u.value; - setnilvalue(uv->v); - return uv; -} - - -UpVal *luaF_findupval (lua_State *L, StkId level) { - global_State *g = G(L); - GCObject **pp = &L->openupval; - UpVal *p; - UpVal *uv; - while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { - lua_assert(p->v != &p->u.value); - if (p->v == level) { /* found a corresponding upvalue? */ - if (isdead(g, obj2gco(p))) /* is it dead? */ - changewhite(obj2gco(p)); /* ressurect it */ - return p; - } - pp = &p->next; - } - uv = luaM_new(L, UpVal); /* not found: create a new one */ - uv->tt = LUA_TUPVAL; - uv->marked = luaC_white(g); - uv->v = level; /* current value lives in the stack */ - uv->next = *pp; /* chain it in the proper position */ - *pp = obj2gco(uv); - uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ - uv->u.l.next = g->uvhead.u.l.next; - uv->u.l.next->u.l.prev = uv; - g->uvhead.u.l.next = uv; - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - return uv; -} - - -static void unlinkupval (UpVal *uv) { - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ - uv->u.l.prev->u.l.next = uv->u.l.next; -} - - -void luaF_freeupval (lua_State *L, UpVal *uv) { - if (uv->v != &uv->u.value) /* is it open? */ - unlinkupval(uv); /* remove from open list */ - luaM_free(L, uv); /* free upvalue */ -} - - -void luaF_close (lua_State *L, StkId level) { - UpVal *uv; - global_State *g = G(L); - while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { - GCObject *o = obj2gco(uv); - lua_assert(!isblack(o) && uv->v != &uv->u.value); - L->openupval = uv->next; /* remove from `open' list */ - if (isdead(g, o)) - luaF_freeupval(L, uv); /* free upvalue */ - else { - unlinkupval(uv); - setobj(L, &uv->u.value, uv->v); - uv->v = &uv->u.value; /* now current value lives here */ - luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ - } - } -} - - -Proto *luaF_newproto (lua_State *L) { - Proto *f = luaM_new(L, Proto); - luaC_link(L, obj2gco(f), LUA_TPROTO); - f->k = NULL; - f->sizek = 0; - f->p = NULL; - f->sizep = 0; - f->code = NULL; - f->sizecode = 0; - f->sizelineinfo = 0; - f->sizeupvalues = 0; - f->nups = 0; - f->upvalues = NULL; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->lineinfo = NULL; - f->sizelocvars = 0; - f->locvars = NULL; - f->linedefined = 0; - f->lastlinedefined = 0; - f->source = NULL; - return f; -} - - -void luaF_freeproto (lua_State *L, Proto *f) { - luaM_freearray(L, f->code, f->sizecode, Instruction); - luaM_freearray(L, f->p, f->sizep, Proto *); - luaM_freearray(L, f->k, f->sizek, TValue); - luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); - luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); - luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); - luaM_free(L, f); -} - - -void luaF_freeclosure (lua_State *L, Closure *c) { - int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : - sizeLclosure(c->l.nupvalues); - luaM_freemem(L, c, size); -} - - -/* -** Look for n-th local variable at line `line' in function `func'. -** Returns NULL if not found. -*/ -const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { - int i; - for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { - if (pc < f->locvars[i].endpc) { /* is variable active? */ - local_number--; - if (local_number == 0) - return getstr(f->locvars[i].varname); - } - } - return NULL; /* not found */ -} - diff --git a/script/lua/lfunc.h b/script/lua/lfunc.h deleted file mode 100644 index a68cf5151..000000000 --- a/script/lua/lfunc.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - -#ifndef lfunc_h -#define lfunc_h - - -#include "lobject.h" - - -#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ - cast(int, sizeof(TValue)*((n)-1))) - -#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ - cast(int, sizeof(TValue *)*((n)-1))) - - -LUAI_FUNC Proto *luaF_newproto (lua_State *L); -LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); -LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); -LUAI_FUNC UpVal *luaF_newupval (lua_State *L); -LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); -LUAI_FUNC void luaF_close (lua_State *L, StkId level); -LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); -LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); -LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); -LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, - int pc); - - -#endif diff --git a/script/lua/lgc.c b/script/lua/lgc.c deleted file mode 100644 index 1d62975ad..000000000 --- a/script/lua/lgc.c +++ /dev/null @@ -1,713 +0,0 @@ -/* -** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#endif - -#define lgc_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -#define GCSTEPSIZE 1024u -#define GCSWEEPMAX 40 -#define GCSWEEPCOST 10 -#define GCFINALIZECOST 100 - - -#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) - -#define makewhite(g,x) \ - ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) - -#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) - -#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) - - -#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) -#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) - - -#define KEYWEAK bitmask(KEYWEAKBIT) -#define VALUEWEAK bitmask(VALUEWEAKBIT) - - - -#define markvalue(g,o) { checkconsistency(o); \ - if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } - -#define markobject(g,t) { if (iswhite(obj2gco(t))) \ - reallymarkobject(g, obj2gco(t)); } - - -#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) - - -static void removeentry (Node *n) { - lua_assert(ttisnil(gval(n))); - if (iscollectable(gkey(n))) - setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ -} - - -static void reallymarkobject (global_State *g, GCObject *o) { - lua_assert(iswhite(o) && !isdead(g, o)); - white2gray(o); - switch (o->gch.tt) { - case LUA_TSTRING: { - return; - } - case LUA_TUSERDATA: { - Table *mt = gco2u(o)->metatable; - gray2black(o); /* udata are never gray */ - if (mt) markobject(g, mt); - markobject(g, gco2u(o)->env); - return; - } - case LUA_TUPVAL: { - UpVal *uv = gco2uv(o); - markvalue(g, uv->v); - if (uv->v == &uv->u.value) /* closed? */ - gray2black(o); /* open upvalues are never black */ - return; - } - case LUA_TFUNCTION: { - gco2cl(o)->c.gclist = g->gray; - g->gray = o; - break; - } - case LUA_TTABLE: { - gco2h(o)->gclist = g->gray; - g->gray = o; - break; - } - case LUA_TTHREAD: { - gco2th(o)->gclist = g->gray; - g->gray = o; - break; - } - case LUA_TPROTO: { - gco2p(o)->gclist = g->gray; - g->gray = o; - break; - } - default: lua_assert(0); - } -} - - -static void marktmu (global_State *g) { - GCObject *u = g->tmudata; - if (u) { - do { - u = u->gch.next; - makewhite(g, u); /* may be marked, if left from previous GC */ - reallymarkobject(g, u); - } while (u != g->tmudata); - } -} - - -/* move `dead' udata that need finalization to list `tmudata' */ -size_t luaC_separateudata (lua_State *L, int all) { - global_State *g = G(L); - size_t deadmem = 0; - GCObject **p = &g->mainthread->next; - GCObject *curr; - while ((curr = *p) != NULL) { - if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) - p = &curr->gch.next; /* don't bother with them */ - else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { - markfinalized(gco2u(curr)); /* don't need finalization */ - p = &curr->gch.next; - } - else { /* must call its gc method */ - deadmem += sizeudata(gco2u(curr)); - markfinalized(gco2u(curr)); - *p = curr->gch.next; - /* link `curr' at the end of `tmudata' list */ - if (g->tmudata == NULL) /* list is empty? */ - g->tmudata = curr->gch.next = curr; /* creates a circular list */ - else { - curr->gch.next = g->tmudata->gch.next; - g->tmudata->gch.next = curr; - g->tmudata = curr; - } - } - } - return deadmem; -} - - -static int traversetable (global_State *g, Table *h) { - int i; - int weakkey = 0; - int weakvalue = 0; - const TValue *mode; - if (h->metatable) - markobject(g, h->metatable); - mode = gfasttm(g, h->metatable, TM_MODE); - if (mode && ttisstring(mode)) { /* is there a weak mode? */ - weakkey = (strchr(svalue(mode), 'k') != NULL); - weakvalue = (strchr(svalue(mode), 'v') != NULL); - if (weakkey || weakvalue) { /* is really weak? */ - h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ - h->marked |= cast_byte((weakkey << KEYWEAKBIT) | - (weakvalue << VALUEWEAKBIT)); - h->gclist = g->weak; /* must be cleared after GC, ... */ - g->weak = obj2gco(h); /* ... so put in the appropriate list */ - } - } - if (weakkey && weakvalue) return 1; - if (!weakvalue) { - i = h->sizearray; - while (i--) - markvalue(g, &h->array[i]); - } - i = sizenode(h); - while (i--) { - Node *n = gnode(h, i); - lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); - if (ttisnil(gval(n))) - removeentry(n); /* remove empty entries */ - else { - lua_assert(!ttisnil(gkey(n))); - if (!weakkey) markvalue(g, gkey(n)); - if (!weakvalue) markvalue(g, gval(n)); - } - } - return weakkey || weakvalue; -} - - -/* -** All marks are conditional because a GC may happen while the -** prototype is still being created -*/ -static void traverseproto (global_State *g, Proto *f) { - int i; - if (f->source) stringmark(f->source); - for (i=0; isizek; i++) /* mark literals */ - markvalue(g, &f->k[i]); - for (i=0; isizeupvalues; i++) { /* mark upvalue names */ - if (f->upvalues[i]) - stringmark(f->upvalues[i]); - } - for (i=0; isizep; i++) { /* mark nested protos */ - if (f->p[i]) - markobject(g, f->p[i]); - } - for (i=0; isizelocvars; i++) { /* mark local-variable names */ - if (f->locvars[i].varname) - stringmark(f->locvars[i].varname); - } -} - - - -static void traverseclosure (global_State *g, Closure *cl) { - markobject(g, cl->c.env); - if (cl->c.isC) { - int i; - for (i=0; ic.nupvalues; i++) /* mark its upvalues */ - markvalue(g, &cl->c.upvalue[i]); - } - else { - int i; - lua_assert(cl->l.nupvalues == cl->l.p->nups); - markobject(g, cl->l.p); - for (i=0; il.nupvalues; i++) /* mark its upvalues */ - markobject(g, cl->l.upvals[i]); - } -} - - -static void checkstacksizes (lua_State *L, StkId max) { - int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ - int s_used = cast_int(max - L->stack); /* part of stack in use */ - if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ - return; /* do not touch the stacks */ - if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) - luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ - condhardstacktests(luaD_reallocCI(L, ci_used + 1)); - if (4*s_used < L->stacksize && - 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) - luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ - condhardstacktests(luaD_reallocstack(L, s_used)); -} - - -static void traversestack (global_State *g, lua_State *l) { - StkId o, lim; - CallInfo *ci; - markvalue(g, gt(l)); - lim = l->top; - for (ci = l->base_ci; ci <= l->ci; ci++) { - lua_assert(ci->top <= l->stack_last); - if (lim < ci->top) lim = ci->top; - } - for (o = l->stack; o < l->top; o++) - markvalue(g, o); - for (; o <= lim; o++) - setnilvalue(o); - checkstacksizes(l, lim); -} - - -/* -** traverse one gray object, turning it to black. -** Returns `quantity' traversed. -*/ -static l_mem propagatemark (global_State *g) { - GCObject *o = g->gray; - lua_assert(isgray(o)); - gray2black(o); - switch (o->gch.tt) { - case LUA_TTABLE: { - Table *h = gco2h(o); - g->gray = h->gclist; - if (traversetable(g, h)) /* table is weak? */ - black2gray(o); /* keep it gray */ - return sizeof(Table) + sizeof(TValue) * h->sizearray + - sizeof(Node) * sizenode(h); - } - case LUA_TFUNCTION: { - Closure *cl = gco2cl(o); - g->gray = cl->c.gclist; - traverseclosure(g, cl); - return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : - sizeLclosure(cl->l.nupvalues); - } - case LUA_TTHREAD: { - lua_State *th = gco2th(o); - g->gray = th->gclist; - th->gclist = g->grayagain; - g->grayagain = o; - black2gray(o); - traversestack(g, th); - return sizeof(lua_State) + sizeof(TValue) * th->stacksize + - sizeof(CallInfo) * th->size_ci; - } - case LUA_TPROTO: { - Proto *p = gco2p(o); - g->gray = p->gclist; - traverseproto(g, p); - return sizeof(Proto) + sizeof(Instruction) * p->sizecode + - sizeof(Proto *) * p->sizep + - sizeof(TValue) * p->sizek + - sizeof(int) * p->sizelineinfo + - sizeof(LocVar) * p->sizelocvars + - sizeof(TString *) * p->sizeupvalues; - } - default: lua_assert(0); return 0; - } -} - - -static size_t propagateall (global_State *g) { - size_t m = 0; - while (g->gray) m += propagatemark(g); - return m; -} - - -/* -** The next function tells whether a key or value can be cleared from -** a weak table. Non-collectable objects are never removed from weak -** tables. Strings behave as `values', so are never removed too. for -** other objects: if really collected, cannot keep them; for userdata -** being finalized, keep them in keys, but not in values -*/ -static int iscleared (const TValue *o, int iskey) { - if (!iscollectable(o)) return 0; - if (ttisstring(o)) { - stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ - return 0; - } - return iswhite(gcvalue(o)) || - (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); -} - - -/* -** clear collected entries from weaktables -*/ -static void cleartable (GCObject *l) { - while (l) { - Table *h = gco2h(l); - int i = h->sizearray; - lua_assert(testbit(h->marked, VALUEWEAKBIT) || - testbit(h->marked, KEYWEAKBIT)); - if (testbit(h->marked, VALUEWEAKBIT)) { - while (i--) { - TValue *o = &h->array[i]; - if (iscleared(o, 0)) /* value was collected? */ - setnilvalue(o); /* remove value */ - } - } - i = sizenode(h); - while (i--) { - Node *n = gnode(h, i); - if (!ttisnil(gval(n)) && /* non-empty entry? */ - (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { - setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* remove entry from table */ - } - } - l = h->gclist; - } -} - - -static void freeobj (lua_State *L, GCObject *o) { - switch (o->gch.tt) { - case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; - case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; - case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; - case LUA_TTABLE: luaH_free(L, gco2h(o)); break; - case LUA_TTHREAD: { - lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); - luaE_freethread(L, gco2th(o)); - break; - } - case LUA_TSTRING: { - G(L)->strt.nuse--; - luaM_freemem(L, o, sizestring(gco2ts(o))); - break; - } - case LUA_TUSERDATA: { - luaM_freemem(L, o, sizeudata(gco2u(o))); - break; - } - default: lua_assert(0); - } -} - - - -#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) - - -static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { - GCObject *curr; - global_State *g = G(L); - int deadmask = otherwhite(g); - while ((curr = *p) != NULL && count-- > 0) { - if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ - sweepwholelist(L, &gco2th(curr)->openupval); - if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ - lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); - makewhite(g, curr); /* make it white (for next cycle) */ - p = &curr->gch.next; - } - else { /* must erase `curr' */ - lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); - *p = curr->gch.next; - if (curr == g->rootgc) /* is the first element of the list? */ - g->rootgc = curr->gch.next; /* adjust first */ - freeobj(L, curr); - } - } - return p; -} - - -static void checkSizes (lua_State *L) { - global_State *g = G(L); - /* check size of string hash */ - if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && - g->strt.size > MINSTRTABSIZE*2) - luaS_resize(L, g->strt.size/2); /* table is too big */ - /* check size of buffer */ - if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ - size_t newsize = luaZ_sizebuffer(&g->buff) / 2; - luaZ_resizebuffer(L, &g->buff, newsize); - } -} - - -static void GCTM (lua_State *L) { - global_State *g = G(L); - GCObject *o = g->tmudata->gch.next; /* get first element */ - Udata *udata = rawgco2u(o); - const TValue *tm; - /* remove udata from `tmudata' */ - if (o == g->tmudata) /* last element? */ - g->tmudata = NULL; - else - g->tmudata->gch.next = udata->uv.next; - udata->uv.next = g->mainthread->next; /* return it to `root' list */ - g->mainthread->next = o; - makewhite(g, o); - tm = fasttm(L, udata->uv.metatable, TM_GC); - if (tm != NULL) { - lu_byte oldah = L->allowhook; - lu_mem oldt = g->GCthreshold; - L->allowhook = 0; /* stop debug hooks during GC tag method */ - g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ - setobj2s(L, L->top, tm); - setuvalue(L, L->top+1, udata); - L->top += 2; - luaD_call(L, L->top - 2, 0); - L->allowhook = oldah; /* restore hooks */ - g->GCthreshold = oldt; /* restore threshold */ - } -} - - -/* -** Call all GC tag methods -*/ -void luaC_callGCTM (lua_State *L) { - while (G(L)->tmudata) - GCTM(L); -} - - -void luaC_freeall (lua_State *L) { - global_State *g = G(L); - int i; - g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ - sweepwholelist(L, &g->rootgc); - for (i = 0; i < g->strt.size; i++) /* free all string lists */ - sweepwholelist(L, &g->strt.hash[i]); -} - - -static void markmt (global_State *g) { - int i; - for (i=0; imt[i]) markobject(g, g->mt[i]); -} - - -/* mark root set */ -static void markroot (lua_State *L) { - global_State *g = G(L); - g->gray = NULL; - g->grayagain = NULL; - g->weak = NULL; - markobject(g, g->mainthread); - /* make global table be traversed before main stack */ - markvalue(g, gt(g->mainthread)); - markvalue(g, registry(L)); - markmt(g); - g->gcstate = GCSpropagate; -} - - -static void remarkupvals (global_State *g) { - UpVal *uv; - for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - if (isgray(obj2gco(uv))) - markvalue(g, uv->v); - } -} - - -static void atomic (lua_State *L) { - global_State *g = G(L); - size_t udsize; /* total size of userdata to be finalized */ - /* remark occasional upvalues of (maybe) dead threads */ - remarkupvals(g); - /* traverse objects cautch by write barrier and by 'remarkupvals' */ - propagateall(g); - /* remark weak tables */ - g->gray = g->weak; - g->weak = NULL; - lua_assert(!iswhite(obj2gco(g->mainthread))); - markobject(g, L); /* mark running thread */ - markmt(g); /* mark basic metatables (again) */ - propagateall(g); - /* remark gray again */ - g->gray = g->grayagain; - g->grayagain = NULL; - propagateall(g); - udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ - marktmu(g); /* mark `preserved' userdata */ - udsize += propagateall(g); /* remark, to propagate `preserveness' */ - cleartable(g->weak); /* remove collected objects from weak tables */ - /* flip current white */ - g->currentwhite = cast_byte(otherwhite(g)); - g->sweepstrgc = 0; - g->sweepgc = &g->rootgc; - g->gcstate = GCSsweepstring; - g->estimate = g->totalbytes - udsize; /* first estimate */ -} - - -static l_mem singlestep (lua_State *L) { - global_State *g = G(L); - /*lua_checkmemory(L);*/ - switch (g->gcstate) { - case GCSpause: { - markroot(L); /* start a new collection */ - return 0; - } - case GCSpropagate: { - if (g->gray) - return propagatemark(g); - else { /* no more `gray' objects */ - atomic(L); /* finish mark phase */ - return 0; - } - } - case GCSsweepstring: { - lu_mem old = g->totalbytes; - sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); - if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ - g->gcstate = GCSsweep; /* end sweep-string phase */ - lua_assert(old >= g->totalbytes); - g->estimate -= old - g->totalbytes; - return GCSWEEPCOST; - } - case GCSsweep: { - lu_mem old = g->totalbytes; - g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); - if (*g->sweepgc == NULL) { /* nothing more to sweep? */ - checkSizes(L); - g->gcstate = GCSfinalize; /* end sweep phase */ - } - lua_assert(old >= g->totalbytes); - g->estimate -= old - g->totalbytes; - return GCSWEEPMAX*GCSWEEPCOST; - } - case GCSfinalize: { - if (g->tmudata) { - GCTM(L); - if (g->estimate > GCFINALIZECOST) - g->estimate -= GCFINALIZECOST; - return GCFINALIZECOST; - } - else { - g->gcstate = GCSpause; /* end collection */ - g->gcdept = 0; - return 0; - } - } - default: lua_assert(0); return 0; - } -} - - -void luaC_step (lua_State *L) { - global_State *g = G(L); - l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; - if (lim == 0) - lim = (MAX_LUMEM-1)/2; /* no limit */ - g->gcdept += g->totalbytes - g->GCthreshold; - do { - lim -= singlestep(L); - if (g->gcstate == GCSpause) - break; - } while (lim > 0); - if (g->gcstate != GCSpause) { - if (g->gcdept < GCSTEPSIZE) - g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ - else { - g->gcdept -= GCSTEPSIZE; - g->GCthreshold = g->totalbytes; - } - } - else { - lua_assert(g->totalbytes >= g->estimate); - setthreshold(g); - } -} - - -void luaC_fullgc (lua_State *L) { - global_State *g = G(L); - if (g->gcstate <= GCSpropagate) { - /* reset sweep marks to sweep all elements (returning them to white) */ - g->sweepstrgc = 0; - g->sweepgc = &g->rootgc; - /* reset other collector lists */ - g->gray = NULL; - g->grayagain = NULL; - g->weak = NULL; - g->gcstate = GCSsweepstring; - } - lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); - /* finish any pending sweep phase */ - while (g->gcstate != GCSfinalize) { - lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); - singlestep(L); - } - markroot(L); - while (g->gcstate != GCSpause) { - singlestep(L); - } - setthreshold(g); -} - - -void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { - global_State *g = G(L); - lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); - lua_assert(ttype(&o->gch) != LUA_TTABLE); - /* must keep invariant? */ - if (g->gcstate == GCSpropagate) - reallymarkobject(g, v); /* restore invariant */ - else /* don't mind */ - makewhite(g, o); /* mark as white just to avoid other barriers */ -} - - -void luaC_barrierback (lua_State *L, Table *t) { - global_State *g = G(L); - GCObject *o = obj2gco(t); - lua_assert(isblack(o) && !isdead(g, o)); - lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); - black2gray(o); /* make table gray (again) */ - t->gclist = g->grayagain; - g->grayagain = o; -} - - -void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { - global_State *g = G(L); - o->gch.next = g->rootgc; - g->rootgc = o; - o->gch.marked = luaC_white(g); - o->gch.tt = tt; -} - - -void luaC_linkupval (lua_State *L, UpVal *uv) { - global_State *g = G(L); - GCObject *o = obj2gco(uv); - o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ - g->rootgc = o; - if (isgray(o)) { - if (g->gcstate == GCSpropagate) { - gray2black(o); /* closed upvalues need barrier */ - luaC_barrier(L, uv, uv->v); - } - else { /* sweep phase: sweep it (turning it into white) */ - makewhite(g, o); - lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); - } - } -} - diff --git a/script/lua/lgc.h b/script/lua/lgc.h deleted file mode 100644 index 5a8dc605b..000000000 --- a/script/lua/lgc.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#ifndef lgc_h -#define lgc_h - - -#include "lobject.h" - - -/* -** Possible states of the Garbage Collector -*/ -#define GCSpause 0 -#define GCSpropagate 1 -#define GCSsweepstring 2 -#define GCSsweep 3 -#define GCSfinalize 4 - - -/* -** some userful bit tricks -*/ -#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) -#define setbits(x,m) ((x) |= (m)) -#define testbits(x,m) ((x) & (m)) -#define bitmask(b) (1<<(b)) -#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) -#define l_setbit(x,b) setbits(x, bitmask(b)) -#define resetbit(x,b) resetbits(x, bitmask(b)) -#define testbit(x,b) testbits(x, bitmask(b)) -#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) -#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) -#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) - - - -/* -** Layout for bit use in `marked' field: -** bit 0 - object is white (type 0) -** bit 1 - object is white (type 1) -** bit 2 - object is black -** bit 3 - for userdata: has been finalized -** bit 3 - for tables: has weak keys -** bit 4 - for tables: has weak values -** bit 5 - object is fixed (should not be collected) -** bit 6 - object is "super" fixed (only the main thread) -*/ - - -#define WHITE0BIT 0 -#define WHITE1BIT 1 -#define BLACKBIT 2 -#define FINALIZEDBIT 3 -#define KEYWEAKBIT 3 -#define VALUEWEAKBIT 4 -#define FIXEDBIT 5 -#define SFIXEDBIT 6 -#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) - - -#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -#define isblack(x) testbit((x)->gch.marked, BLACKBIT) -#define isgray(x) (!isblack(x) && !iswhite(x)) - -#define otherwhite(g) (g->currentwhite ^ WHITEBITS) -#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) - -#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) -#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) - -#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) - -#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) - - -#define luaC_checkGC(L) { \ - condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ - if (G(L)->totalbytes >= G(L)->GCthreshold) \ - luaC_step(L); } - - -#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrierf(L,obj2gco(p),gcvalue(v)); } - -#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ - luaC_barrierback(L,t); } - -#define luaC_objbarrier(L,p,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ - luaC_barrierf(L,obj2gco(p),obj2gco(o)); } - -#define luaC_objbarriert(L,t,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } - -LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); -LUAI_FUNC void luaC_callGCTM (lua_State *L); -LUAI_FUNC void luaC_freeall (lua_State *L); -LUAI_FUNC void luaC_step (lua_State *L); -LUAI_FUNC void luaC_fullgc (lua_State *L); -LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); -LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); -LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); -LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); - - -#endif diff --git a/script/lua/linit.c b/script/lua/linit.c deleted file mode 100644 index f920a0b08..000000000 --- a/script/lua/linit.c +++ /dev/null @@ -1,38 +0,0 @@ -/* -** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ -** Initialization of libraries for lua.c -** See Copyright Notice in lua.h -*/ - - -#define linit_c -#define LUA_LIB - -#include "lua.h" - -#include "lualib.h" -#include "lauxlib.h" - - -static const luaL_Reg lualibs[] = { - {"", luaopen_base}, -// {LUA_LOADLIBNAME, luaopen_package}, - {LUA_TABLIBNAME, luaopen_table}, -// {LUA_IOLIBNAME, luaopen_io}, -// {LUA_OSLIBNAME, luaopen_os}, - {LUA_STRLIBNAME, luaopen_string}, -// {LUA_MATHLIBNAME, luaopen_math}, -// {LUA_DBLIBNAME, luaopen_debug}, - {NULL, NULL} -}; - - -LUALIB_API void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib = lualibs; - for (; lib->func; lib++) { - lua_pushcfunction(L, lib->func); - lua_pushstring(L, lib->name); - lua_call(L, 1, 0); - } -} - diff --git a/script/lua/liolib.c b/script/lua/liolib.c deleted file mode 100644 index e79ed1cb2..000000000 --- a/script/lua/liolib.c +++ /dev/null @@ -1,553 +0,0 @@ -/* -** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ -** Standard I/O (and system) library -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include - -#define liolib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - -#define IO_INPUT 1 -#define IO_OUTPUT 2 - - -static const char *const fnames[] = {"input", "output"}; - - -static int pushresult (lua_State *L, int i, const char *filename) { - int en = errno; /* calls to Lua API may change this value */ - if (i) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushnil(L); - if (filename) - lua_pushfstring(L, "%s: %s", filename, strerror(en)); - else - lua_pushfstring(L, "%s", strerror(en)); - lua_pushinteger(L, en); - return 3; - } -} - - -static void fileerror (lua_State *L, int arg, const char *filename) { - lua_pushfstring(L, "%s: %s", filename, strerror(errno)); - luaL_argerror(L, arg, lua_tostring(L, -1)); -} - - -#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) - - -static int io_type (lua_State *L) { - void *ud; - luaL_checkany(L, 1); - ud = lua_touserdata(L, 1); - lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); - if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) - lua_pushnil(L); /* not a file */ - else if (*((FILE **)ud) == NULL) - lua_pushliteral(L, "closed file"); - else - lua_pushliteral(L, "file"); - return 1; -} - - -static FILE *tofile (lua_State *L) { - FILE **f = tofilep(L); - if (*f == NULL) - luaL_error(L, "attempt to use a closed file"); - return *f; -} - - - -/* -** When creating file handles, always creates a `closed' file handle -** before opening the actual file; so, if there is a memory error, the -** file is not left opened. -*/ -static FILE **newfile (lua_State *L) { - FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); - *pf = NULL; /* file handle is currently `closed' */ - luaL_getmetatable(L, LUA_FILEHANDLE); - lua_setmetatable(L, -2); - return pf; -} - - -/* -** function to (not) close the standard files stdin, stdout, and stderr -*/ -static int io_noclose (lua_State *L) { - lua_pushnil(L); - lua_pushliteral(L, "cannot close standard file"); - return 2; -} - - -/* -** function to close 'popen' files -*/ -static int io_pclose (lua_State *L) { - FILE **p = tofilep(L); - int ok = lua_pclose(L, *p); - *p = NULL; - return pushresult(L, ok, NULL); -} - - -/* -** function to close regular files -*/ -static int io_fclose (lua_State *L) { - FILE **p = tofilep(L); - int ok = (fclose(*p) == 0); - *p = NULL; - return pushresult(L, ok, NULL); -} - - -static int aux_close (lua_State *L) { - lua_getfenv(L, 1); - lua_getfield(L, -1, "__close"); - return (lua_tocfunction(L, -1))(L); -} - - -static int io_close (lua_State *L) { - if (lua_isnone(L, 1)) - lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); - tofile(L); /* make sure argument is a file */ - return aux_close(L); -} - - -static int io_gc (lua_State *L) { - FILE *f = *tofilep(L); - /* ignore closed files */ - if (f != NULL) - aux_close(L); - return 0; -} - - -static int io_tostring (lua_State *L) { - FILE *f = *tofilep(L); - if (f == NULL) - lua_pushliteral(L, "file (closed)"); - else - lua_pushfstring(L, "file (%p)", f); - return 1; -} - - -static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = fopen(filename, mode); - return (*pf == NULL) ? pushresult(L, 0, filename) : 1; -} - - -/* -** this function has a separated environment, which defines the -** correct __close for 'popen' files -*/ -static int io_popen (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - FILE **pf = newfile(L); - *pf = lua_popen(L, filename, mode); - return (*pf == NULL) ? pushresult(L, 0, filename) : 1; -} - - -static int io_tmpfile (lua_State *L) { - FILE **pf = newfile(L); - *pf = tmpfile(); - return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; -} - - -static FILE *getiofile (lua_State *L, int findex) { - FILE *f; - lua_rawgeti(L, LUA_ENVIRONINDEX, findex); - f = *(FILE **)lua_touserdata(L, -1); - if (f == NULL) - luaL_error(L, "standard %s file is closed", fnames[findex - 1]); - return f; -} - - -static int g_iofile (lua_State *L, int f, const char *mode) { - if (!lua_isnoneornil(L, 1)) { - const char *filename = lua_tostring(L, 1); - if (filename) { - FILE **pf = newfile(L); - *pf = fopen(filename, mode); - if (*pf == NULL) - fileerror(L, 1, filename); - } - else { - tofile(L); /* check that it's a valid file handle */ - lua_pushvalue(L, 1); - } - lua_rawseti(L, LUA_ENVIRONINDEX, f); - } - /* return current value */ - lua_rawgeti(L, LUA_ENVIRONINDEX, f); - return 1; -} - - -static int io_input (lua_State *L) { - return g_iofile(L, IO_INPUT, "r"); -} - - -static int io_output (lua_State *L) { - return g_iofile(L, IO_OUTPUT, "w"); -} - - -static int io_readline (lua_State *L); - - -static void aux_lines (lua_State *L, int idx, int toclose) { - lua_pushvalue(L, idx); - lua_pushboolean(L, toclose); /* close/not close file when finished */ - lua_pushcclosure(L, io_readline, 2); -} - - -static int f_lines (lua_State *L) { - tofile(L); /* check that it's a valid file handle */ - aux_lines(L, 1, 0); - return 1; -} - - -static int io_lines (lua_State *L) { - if (lua_isnoneornil(L, 1)) { /* no arguments? */ - /* will iterate over default input */ - lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); - return f_lines(L); - } - else { - const char *filename = luaL_checkstring(L, 1); - FILE **pf = newfile(L); - *pf = fopen(filename, "r"); - if (*pf == NULL) - fileerror(L, 1, filename); - aux_lines(L, lua_gettop(L), 1); - return 1; - } -} - - -/* -** {====================================================== -** READ -** ======================================================= -*/ - - -static int read_number (lua_State *L, FILE *f) { - lua_Number d; - if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { - lua_pushnumber(L, d); - return 1; - } - else return 0; /* read fails */ -} - - -static int test_eof (lua_State *L, FILE *f) { - int c = getc(f); - ungetc(c, f); - lua_pushlstring(L, NULL, 0); - return (c != EOF); -} - - -static int read_line (lua_State *L, FILE *f) { - luaL_Buffer b; - luaL_buffinit(L, &b); - for (;;) { - size_t l; - char *p = luaL_prepbuffer(&b); - if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ - luaL_pushresult(&b); /* close buffer */ - return (lua_objlen(L, -1) > 0); /* check whether read something */ - } - l = strlen(p); - if (l == 0 || p[l-1] != '\n') - luaL_addsize(&b, l); - else { - luaL_addsize(&b, l - 1); /* do not include `eol' */ - luaL_pushresult(&b); /* close buffer */ - return 1; /* read at least an `eol' */ - } - } -} - - -static int read_chars (lua_State *L, FILE *f, size_t n) { - size_t rlen; /* how much to read */ - size_t nr; /* number of chars actually read */ - luaL_Buffer b; - luaL_buffinit(L, &b); - rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ - do { - char *p = luaL_prepbuffer(&b); - if (rlen > n) rlen = n; /* cannot read more than asked */ - nr = fread(p, sizeof(char), rlen, f); - luaL_addsize(&b, nr); - n -= nr; /* still have to read `n' chars */ - } while (n > 0 && nr == rlen); /* until end of count or eof */ - luaL_pushresult(&b); /* close buffer */ - return (n == 0 || lua_objlen(L, -1) > 0); -} - - -static int g_read (lua_State *L, FILE *f, int first) { - int nargs = lua_gettop(L) - 1; - int success; - int n; - clearerr(f); - if (nargs == 0) { /* no arguments? */ - success = read_line(L, f); - n = first+1; /* to return 1 result */ - } - else { /* ensure stack space for all results and for auxlib's buffer */ - luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); - success = 1; - for (n = first; nargs-- && success; n++) { - if (lua_type(L, n) == LUA_TNUMBER) { - size_t l = (size_t)lua_tointeger(L, n); - success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); - } - else { - const char *p = lua_tostring(L, n); - luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); - switch (p[1]) { - case 'n': /* number */ - success = read_number(L, f); - break; - case 'l': /* line */ - success = read_line(L, f); - break; - case 'a': /* file */ - read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ - success = 1; /* always success */ - break; - default: - return luaL_argerror(L, n, "invalid format"); - } - } - } - } - if (ferror(f)) - return pushresult(L, 0, NULL); - if (!success) { - lua_pop(L, 1); /* remove last result */ - lua_pushnil(L); /* push nil instead */ - } - return n - first; -} - - -static int io_read (lua_State *L) { - return g_read(L, getiofile(L, IO_INPUT), 1); -} - - -static int f_read (lua_State *L) { - return g_read(L, tofile(L), 2); -} - - -static int io_readline (lua_State *L) { - FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); - int sucess; - if (f == NULL) /* file is already closed? */ - luaL_error(L, "file is already closed"); - sucess = read_line(L, f); - if (ferror(f)) - return luaL_error(L, "%s", strerror(errno)); - if (sucess) return 1; - else { /* EOF */ - if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ - lua_settop(L, 0); - lua_pushvalue(L, lua_upvalueindex(1)); - aux_close(L); /* close it */ - } - return 0; - } -} - -/* }====================================================== */ - - -static int g_write (lua_State *L, FILE *f, int arg) { - int nargs = lua_gettop(L) - 1; - int status = 1; - for (; nargs--; arg++) { - if (lua_type(L, arg) == LUA_TNUMBER) { - /* optimization: could be done exactly as for strings */ - status = status && - fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; - } - else { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - status = status && (fwrite(s, sizeof(char), l, f) == l); - } - } - return pushresult(L, status, NULL); -} - - -static int io_write (lua_State *L) { - return g_write(L, getiofile(L, IO_OUTPUT), 1); -} - - -static int f_write (lua_State *L) { - return g_write(L, tofile(L), 2); -} - - -static int f_seek (lua_State *L) { - static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; - static const char *const modenames[] = {"set", "cur", "end", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, "cur", modenames); - long offset = luaL_optlong(L, 3, 0); - op = fseek(f, offset, mode[op]); - if (op) - return pushresult(L, 0, NULL); /* error */ - else { - lua_pushinteger(L, ftell(f)); - return 1; - } -} - - -static int f_setvbuf (lua_State *L) { - static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; - static const char *const modenames[] = {"no", "full", "line", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, NULL, modenames); - lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); - int res = setvbuf(f, NULL, mode[op], sz); - return pushresult(L, res == 0, NULL); -} - - - -static int io_flush (lua_State *L) { - return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); -} - - -static int f_flush (lua_State *L) { - return pushresult(L, fflush(tofile(L)) == 0, NULL); -} - - -static const luaL_Reg iolib[] = { - {"close", io_close}, - {"flush", io_flush}, - {"input", io_input}, - {"lines", io_lines}, - {"open", io_open}, - {"output", io_output}, - {"popen", io_popen}, - {"read", io_read}, - {"tmpfile", io_tmpfile}, - {"type", io_type}, - {"write", io_write}, - {NULL, NULL} -}; - - -static const luaL_Reg flib[] = { - {"close", io_close}, - {"flush", f_flush}, - {"lines", f_lines}, - {"read", f_read}, - {"seek", f_seek}, - {"setvbuf", f_setvbuf}, - {"write", f_write}, - {"__gc", io_gc}, - {"__tostring", io_tostring}, - {NULL, NULL} -}; - - -static void createmeta (lua_State *L) { - luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_register(L, NULL, flib); /* file methods */ -} - - -static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { - *newfile(L) = f; - if (k > 0) { - lua_pushvalue(L, -1); - lua_rawseti(L, LUA_ENVIRONINDEX, k); - } - lua_pushvalue(L, -2); /* copy environment */ - lua_setfenv(L, -2); /* set it */ - lua_setfield(L, -3, fname); -} - - -static void newfenv (lua_State *L, lua_CFunction cls) { - lua_createtable(L, 0, 1); - lua_pushcfunction(L, cls); - lua_setfield(L, -2, "__close"); -} - - -LUALIB_API int luaopen_io (lua_State *L) { - createmeta(L); - /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ - newfenv(L, io_fclose); - lua_replace(L, LUA_ENVIRONINDEX); - /* open library */ - luaL_register(L, LUA_IOLIBNAME, iolib); - /* create (and set) default files */ - newfenv(L, io_noclose); /* close function for default files */ - createstdfile(L, stdin, IO_INPUT, "stdin"); - createstdfile(L, stdout, IO_OUTPUT, "stdout"); - createstdfile(L, stderr, 0, "stderr"); - lua_pop(L, 1); /* pop environment for default files */ - lua_getfield(L, -1, "popen"); - newfenv(L, io_pclose); /* create environment for 'popen' */ - lua_setfenv(L, -2); /* set fenv for 'popen' */ - lua_pop(L, 1); /* pop 'popen' */ - return 1; -} - diff --git a/script/lua/llex.c b/script/lua/llex.c deleted file mode 100644 index cb08e8928..000000000 --- a/script/lua/llex.c +++ /dev/null @@ -1,467 +0,0 @@ -/* -** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#include -#include -#endif - -#define llex_c -#define LUA_CORE - -#include "lua.h" - -#include "ldo.h" -#include "llex.h" -#include "lobject.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lzio.h" - - - -#define next(ls) (ls->current = zgetc(ls->z)) - - - - -#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') - - -/* ORDER RESERVED */ -const char *const luaX_tokens [] = { - "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "if", - "in", "local", "nil", "not", "or", "repeat", - "return", "then", "true", "until", "while", - "..", "...", "==", ">=", "<=", "~=", - "", "", "", "", - NULL -}; - - -#define save_and_next(ls) (save(ls, ls->current), next(ls)) - - -static void save (LexState *ls, int c) { - Mbuffer *b = ls->buff; - if (b->n + 1 > b->buffsize) { - size_t newsize; - if (b->buffsize >= MAX_SIZET/2) - luaX_lexerror(ls, "lexical element too long", 0); - newsize = b->buffsize * 2; - luaZ_resizebuffer(ls->L, b, newsize); - } - b->buffer[b->n++] = cast(char, c); -} - - -void luaX_init (lua_State *L) { - int i; - for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ - } -} - - -#define MAXSRC 80 - - -const char *luaX_token2str (LexState *ls, int token) { - if (token < FIRST_RESERVED) { - lua_assert(token == cast(unsigned char, token)); - return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : - luaO_pushfstring(ls->L, "%c", token); - } - else - return luaX_tokens[token-FIRST_RESERVED]; -} - - -static const char *txtToken (LexState *ls, int token) { - switch (token) { - case TK_NAME: - case TK_STRING: - case TK_NUMBER: - save(ls, '\0'); - return luaZ_buffer(ls->buff); - default: - return luaX_token2str(ls, token); - } -} - - -void luaX_lexerror (LexState *ls, const char *msg, int token) { - char buff[MAXSRC]; - luaO_chunkid(buff, getstr(ls->source), MAXSRC); - msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); - if (token) - luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); - luaD_throw(ls->L, LUA_ERRSYNTAX); -} - - -void luaX_syntaxerror (LexState *ls, const char *msg) { - luaX_lexerror(ls, msg, ls->t.token); -} - - -TString *luaX_newstring (LexState *ls, const char *str, size_t l) { - lua_State *L = ls->L; - TString *ts = luaS_newlstr(L, str, l); - TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ - if (ttisnil(o)) - setbvalue(o, 1); /* make sure `str' will not be collected */ - return ts; -} - - -static void inclinenumber (LexState *ls) { - int old = ls->current; - lua_assert(currIsNewline(ls)); - next(ls); /* skip `\n' or `\r' */ - if (currIsNewline(ls) && ls->current != old) - next(ls); /* skip `\n\r' or `\r\n' */ - if (++ls->linenumber >= MAX_INT) - luaX_syntaxerror(ls, "chunk has too many lines"); -} - - -void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { - ls->decpoint = '.'; - ls->L = L; - ls->lookahead.token = TK_EOS; /* no look-ahead token */ - ls->z = z; - ls->fs = NULL; - ls->linenumber = 1; - ls->lastline = 1; - ls->source = source; - luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ - next(ls); /* read first char */ -} - - - -/* -** ======================================================= -** LEXICAL ANALYZER -** ======================================================= -*/ - - - -static int check_next (LexState *ls, const char *set) { - if (!strchr(set, ls->current)) - return 0; - save_and_next(ls); - return 1; -} - - -static void buffreplace (LexState *ls, char from, char to) { - size_t n = luaZ_bufflen(ls->buff); - char *p = luaZ_buffer(ls->buff); - while (n--) - if (p[n] == from) p[n] = to; -} - - -static void trydecpoint (LexState *ls, SemInfo *seminfo) { - /* format error: try to update decimal point separator */ -#if 0 - struct lconv *cv = localeconv(); - char old = ls->decpoint; - ls->decpoint = (cv ? cv->decimal_point[0] : '.'); -#else - char old = ls->decpoint; - ls->decpoint = '.'; -#endif - buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ - if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { - /* format error with correct decimal point: no more options */ - buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ - luaX_lexerror(ls, "malformed number", TK_NUMBER); - } -} - - -/* LUA_NUMBER */ -static void read_numeral (LexState *ls, SemInfo *seminfo) { - lua_assert(isdigit(ls->current)); - do { - save_and_next(ls); - } while (isdigit(ls->current) || ls->current == '.'); - if (check_next(ls, "Ee")) /* `E'? */ - check_next(ls, "+-"); /* optional exponent sign */ - while (isalnum(ls->current) || ls->current == '_') - save_and_next(ls); - save(ls, '\0'); - buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ - if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ - trydecpoint(ls, seminfo); /* try to update decimal point separator */ -} - - -static int skip_sep (LexState *ls) { - int count = 0; - int s = ls->current; - lua_assert(s == '[' || s == ']'); - save_and_next(ls); - while (ls->current == '=') { - save_and_next(ls); - count++; - } - return (ls->current == s) ? count : (-count) - 1; -} - - -static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { - int cont = 0; - (void)(cont); /* avoid warnings when `cont' is not used */ - save_and_next(ls); /* skip 2nd `[' */ - if (currIsNewline(ls)) /* string starts with a newline? */ - inclinenumber(ls); /* skip it */ - for (;;) { - switch (ls->current) { - case EOZ: - luaX_lexerror(ls, (seminfo) ? "unfinished long string" : - "unfinished long comment", TK_EOS); - break; /* to avoid warnings */ -#if defined(LUA_COMPAT_LSTR) - case '[': { - if (skip_sep(ls) == sep) { - save_and_next(ls); /* skip 2nd `[' */ - cont++; -#if LUA_COMPAT_LSTR == 1 - if (sep == 0) - luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); -#endif - } - break; - } -#endif - case ']': { - if (skip_sep(ls) == sep) { - save_and_next(ls); /* skip 2nd `]' */ -#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 - cont--; - if (sep == 0 && cont >= 0) break; -#endif - goto endloop; - } - break; - } - case '\n': - case '\r': { - save(ls, '\n'); - inclinenumber(ls); - if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ - break; - } - default: { - if (seminfo) save_and_next(ls); - else next(ls); - } - } - } endloop: - if (seminfo) - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), - luaZ_bufflen(ls->buff) - 2*(2 + sep)); -} - - -static void read_string (LexState *ls, int del, SemInfo *seminfo) { - save_and_next(ls); - while (ls->current != del) { - switch (ls->current) { - case EOZ: - luaX_lexerror(ls, "unfinished string", TK_EOS); - continue; /* to avoid warnings */ - case '\n': - case '\r': - luaX_lexerror(ls, "unfinished string", TK_STRING); - continue; /* to avoid warnings */ - case '\\': { - int c; - next(ls); /* do not save the `\' */ - switch (ls->current) { - case 'a': c = '\a'; break; - case 'b': c = '\b'; break; - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'v': c = '\v'; break; - case '\n': /* go through */ - case '\r': save(ls, '\n'); inclinenumber(ls); continue; - case EOZ: continue; /* will raise an error next loop */ - default: { - if (!isdigit(ls->current)) - save_and_next(ls); /* handles \\, \", \', and \? */ - else { /* \xxx */ - int i = 0; - c = 0; - do { - c = 10*c + (ls->current-'0'); - next(ls); - } while (++i<3 && isdigit(ls->current)); - if (c > UCHAR_MAX) - luaX_lexerror(ls, "escape sequence too large", TK_STRING); - save(ls, c); - } - continue; - } - } - save(ls, c); - next(ls); - continue; - } - default: - save_and_next(ls); - } - } - save_and_next(ls); /* skip delimiter */ - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, - luaZ_bufflen(ls->buff) - 2); -} - - -static int llex (LexState *ls, SemInfo *seminfo) { - luaZ_resetbuffer(ls->buff); - for (;;) { - switch (ls->current) { - case '\n': - case '\r': { - inclinenumber(ls); - continue; - } - case '-': { - next(ls); - if (ls->current != '-') return '-'; - /* else is a comment */ - next(ls); - if (ls->current == '[') { - int sep = skip_sep(ls); - luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ - if (sep >= 0) { - read_long_string(ls, NULL, sep); /* long comment */ - luaZ_resetbuffer(ls->buff); - continue; - } - } - /* else short comment */ - while (!currIsNewline(ls) && ls->current != EOZ) - next(ls); - continue; - } - case '[': { - int sep = skip_sep(ls); - if (sep >= 0) { - read_long_string(ls, seminfo, sep); - return TK_STRING; - } - else if (sep == -1) return '['; - else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); - } - case '=': { - next(ls); - if (ls->current != '=') return '='; - else { next(ls); return TK_EQ; } - } - case '<': { - next(ls); - if (ls->current != '=') return '<'; - else { next(ls); return TK_LE; } - } - case '>': { - next(ls); - if (ls->current != '=') return '>'; - else { next(ls); return TK_GE; } - } - case '~': { - next(ls); - if (ls->current != '=') return '~'; - else { next(ls); return TK_NE; } - } - case '"': - case '\'': { - read_string(ls, ls->current, seminfo); - return TK_STRING; - } - case '.': { - save_and_next(ls); - if (check_next(ls, ".")) { - if (check_next(ls, ".")) - return TK_DOTS; /* ... */ - else return TK_CONCAT; /* .. */ - } - else if (!isdigit(ls->current)) return '.'; - else { - read_numeral(ls, seminfo); - return TK_NUMBER; - } - } - case EOZ: { - return TK_EOS; - } - default: { - if (isspace(ls->current)) { - lua_assert(!currIsNewline(ls)); - next(ls); - continue; - } - else if (isdigit(ls->current)) { - read_numeral(ls, seminfo); - return TK_NUMBER; - } - else if (isalpha(ls->current) || ls->current == '_') { - /* identifier or reserved word */ - TString *ts; - do { - save_and_next(ls); - } while (isalnum(ls->current) || ls->current == '_'); - ts = luaX_newstring(ls, luaZ_buffer(ls->buff), - luaZ_bufflen(ls->buff)); - if (ts->tsv.reserved > 0) /* reserved word? */ - return ts->tsv.reserved - 1 + FIRST_RESERVED; - else { - seminfo->ts = ts; - return TK_NAME; - } - } - else { - int c = ls->current; - next(ls); - return c; /* single-char tokens (+ - / ...) */ - } - } - } - } -} - - -void luaX_next (LexState *ls) { - ls->lastline = ls->linenumber; - if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ - ls->t = ls->lookahead; /* use this one */ - ls->lookahead.token = TK_EOS; /* and discharge it */ - } - else - ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ -} - - -void luaX_lookahead (LexState *ls) { - lua_assert(ls->lookahead.token == TK_EOS); - ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); -} - diff --git a/script/lua/llex.h b/script/lua/llex.h deleted file mode 100644 index a9201cee4..000000000 --- a/script/lua/llex.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - -#ifndef llex_h -#define llex_h - -#include "lobject.h" -#include "lzio.h" - - -#define FIRST_RESERVED 257 - -/* maximum length of a reserved word */ -#define TOKEN_LEN (sizeof("function")/sizeof(char)) - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER RESERVED" -*/ -enum RESERVED { - /* terminal symbols denoted by reserved words */ - TK_AND = FIRST_RESERVED, TK_BREAK, - TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, - TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, - TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, - /* other terminal symbols */ - TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, - TK_NAME, TK_STRING, TK_EOS -}; - -/* number of reserved words */ -#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) - - -/* array with token `names' */ -LUAI_DATA const char *const luaX_tokens []; - - -typedef union { - lua_Number r; - TString *ts; -} SemInfo; /* semantics information */ - - -typedef struct Token { - int token; - SemInfo seminfo; -} Token; - - -typedef struct LexState { - int current; /* current character (charint) */ - int linenumber; /* input line counter */ - int lastline; /* line of last token `consumed' */ - Token t; /* current token */ - Token lookahead; /* look ahead token */ - struct FuncState *fs; /* `FuncState' is private to the parser */ - struct lua_State *L; - ZIO *z; /* input stream */ - Mbuffer *buff; /* buffer for tokens */ - TString *source; /* current source name */ - char decpoint; /* locale decimal point */ -} LexState; - - -LUAI_FUNC void luaX_init (lua_State *L); -LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, - TString *source); -LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); -LUAI_FUNC void luaX_next (LexState *ls); -LUAI_FUNC void luaX_lookahead (LexState *ls); -LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); -LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); -LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); - - -#endif diff --git a/script/lua/llimits.h b/script/lua/llimits.h deleted file mode 100644 index 5612e8a42..000000000 --- a/script/lua/llimits.h +++ /dev/null @@ -1,128 +0,0 @@ -/* -** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ -** Limits, basic types, and some other `installation-dependent' definitions -** See Copyright Notice in lua.h -*/ - -#ifndef llimits_h -#define llimits_h - -#if 0 -#include -#include -#endif - -#include "lua.h" - - -typedef LUAI_UINT32 lu_int32; - -typedef LUAI_UMEM lu_mem; - -typedef LUAI_MEM l_mem; - - - -/* chars used as small naturals (so that `char' is reserved for characters) */ -typedef unsigned char lu_byte; - - -#define MAX_SIZET ((size_t)(~(size_t)0)-2) - -#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) - - -#define MAX_INT (int)(INT_MAX-2) /* maximum value of an int (-2 for safety) */ - -/* -** conversion of pointer to integer -** this is for hashing only; there is no problem if the integer -** cannot hold the whole pointer value -*/ -#define IntPoint(p) ((unsigned int)(lu_mem)(p)) - - - -/* type to ensure maximum alignment */ -typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; - - -/* result of a `usual argument conversion' over lua_Number */ -typedef LUAI_UACNUMBER l_uacNumber; - - -/* internal assertions for in-house debugging */ -#ifdef lua_assert - -#define check_exp(c,e) (lua_assert(c), (e)) -#define api_check(l,e) lua_assert(e) - -#else - -#define lua_assert(c) ((void)0) -#define check_exp(c,e) (e) -#define api_check luai_apicheck - -#endif - - -#ifndef UNUSED -#define UNUSED(x) ((void)(x)) /* to avoid warnings */ -#endif - - -#ifndef cast -#define cast(t, exp) ((t)(exp)) -#endif - -#define cast_byte(i) cast(lu_byte, (i)) -#define cast_num(i) cast(lua_Number, (i)) -#define cast_int(i) cast(int, (i)) - - - -/* -** type for virtual-machine instructions -** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) -*/ -typedef lu_int32 Instruction; - - - -/* maximum stack for a Lua function */ -#define MAXSTACK 250 - - - -/* minimum size for the string table (must be power of 2) */ -#ifndef MINSTRTABSIZE -#define MINSTRTABSIZE 32 -#endif - - -/* minimum size for string buffer */ -#ifndef LUA_MINBUFFER -#define LUA_MINBUFFER 32 -#endif - - -#ifndef lua_lock -#define lua_lock(L) ((void) 0) -#define lua_unlock(L) ((void) 0) -#endif - -#ifndef luai_threadyield -#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} -#endif - - -/* -** macro to control inclusion of some hard tests on stack reallocation -*/ -#ifndef HARDSTACKTESTS -#define condhardstacktests(x) ((void)0) -#else -#define condhardstacktests(x) x -#endif - -#endif diff --git a/script/lua/lmathlib.c b/script/lua/lmathlib.c deleted file mode 100644 index 441fbf736..000000000 --- a/script/lua/lmathlib.c +++ /dev/null @@ -1,263 +0,0 @@ -/* -** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $ -** Standard mathematical library -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#define lmathlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#undef PI -#define PI (3.14159265358979323846) -#define RADIANS_PER_DEGREE (PI/180.0) - - - -static int math_abs (lua_State *L) { - lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sin (lua_State *L) { - lua_pushnumber(L, sin(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sinh (lua_State *L) { - lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cos (lua_State *L) { - lua_pushnumber(L, cos(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cosh (lua_State *L) { - lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tan (lua_State *L) { - lua_pushnumber(L, tan(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tanh (lua_State *L) { - lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); - return 1; -} - -static int math_asin (lua_State *L) { - lua_pushnumber(L, asin(luaL_checknumber(L, 1))); - return 1; -} - -static int math_acos (lua_State *L) { - lua_pushnumber(L, acos(luaL_checknumber(L, 1))); - return 1; -} - -static int math_atan (lua_State *L) { - lua_pushnumber(L, atan(luaL_checknumber(L, 1))); - return 1; -} - -static int math_atan2 (lua_State *L) { - lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); - return 1; -} - -static int math_ceil (lua_State *L) { - lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); - return 1; -} - -static int math_floor (lua_State *L) { - lua_pushnumber(L, floor(luaL_checknumber(L, 1))); - return 1; -} - -static int math_fmod (lua_State *L) { - lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); - return 1; -} - -static int math_modf (lua_State *L) { - double ip; - double fp = modf(luaL_checknumber(L, 1), &ip); - lua_pushnumber(L, ip); - lua_pushnumber(L, fp); - return 2; -} - -static int math_sqrt (lua_State *L) { - lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); - return 1; -} - -static int math_pow (lua_State *L) { - lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); - return 1; -} - -static int math_log (lua_State *L) { - lua_pushnumber(L, log(luaL_checknumber(L, 1))); - return 1; -} - -static int math_log10 (lua_State *L) { - lua_pushnumber(L, log10(luaL_checknumber(L, 1))); - return 1; -} - -static int math_exp (lua_State *L) { - lua_pushnumber(L, exp(luaL_checknumber(L, 1))); - return 1; -} - -static int math_deg (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); - return 1; -} - -static int math_rad (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); - return 1; -} - -static int math_frexp (lua_State *L) { - int e; - lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); - lua_pushinteger(L, e); - return 2; -} - -static int math_ldexp (lua_State *L) { - lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); - return 1; -} - - - -static int math_min (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - lua_Number dmin = luaL_checknumber(L, 1); - int i; - for (i=2; i<=n; i++) { - lua_Number d = luaL_checknumber(L, i); - if (d < dmin) - dmin = d; - } - lua_pushnumber(L, dmin); - return 1; -} - - -static int math_max (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - lua_Number dmax = luaL_checknumber(L, 1); - int i; - for (i=2; i<=n; i++) { - lua_Number d = luaL_checknumber(L, i); - if (d > dmax) - dmax = d; - } - lua_pushnumber(L, dmax); - return 1; -} - - -static int math_random (lua_State *L) { - /* the `%' avoids the (rare) case of r==1, and is needed also because on - some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ - lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; - switch (lua_gettop(L)) { /* check number of arguments */ - case 0: { /* no arguments */ - lua_pushnumber(L, r); /* Number between 0 and 1 */ - break; - } - case 1: { /* only upper limit */ - int u = luaL_checkint(L, 1); - luaL_argcheck(L, 1<=u, 1, "interval is empty"); - lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ - break; - } - case 2: { /* lower and upper limits */ - int l = luaL_checkint(L, 1); - int u = luaL_checkint(L, 2); - luaL_argcheck(L, l<=u, 2, "interval is empty"); - lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ - break; - } - default: return luaL_error(L, "wrong number of arguments"); - } - return 1; -} - - -static int math_randomseed (lua_State *L) { - srand(luaL_checkint(L, 1)); - return 0; -} - - -static const luaL_Reg mathlib[] = { - {"abs", math_abs}, - {"acos", math_acos}, - {"asin", math_asin}, - {"atan2", math_atan2}, - {"atan", math_atan}, - {"ceil", math_ceil}, - {"cosh", math_cosh}, - {"cos", math_cos}, - {"deg", math_deg}, - {"exp", math_exp}, - {"floor", math_floor}, - {"fmod", math_fmod}, - {"frexp", math_frexp}, - {"ldexp", math_ldexp}, - {"log10", math_log10}, - {"log", math_log}, - {"max", math_max}, - {"min", math_min}, - {"modf", math_modf}, - {"pow", math_pow}, - {"rad", math_rad}, - {"random", math_random}, - {"randomseed", math_randomseed}, - {"sinh", math_sinh}, - {"sin", math_sin}, - {"sqrt", math_sqrt}, - {"tanh", math_tanh}, - {"tan", math_tan}, - {NULL, NULL} -}; - - -/* -** Open math library -*/ -LUALIB_API int luaopen_math (lua_State *L) { - luaL_register(L, LUA_MATHLIBNAME, mathlib); - lua_pushnumber(L, PI); - lua_setfield(L, -2, "pi"); - lua_pushnumber(L, HUGE_VAL); - lua_setfield(L, -2, "huge"); -#if defined(LUA_COMPAT_MOD) - lua_getfield(L, -1, "fmod"); - lua_setfield(L, -2, "mod"); -#endif - return 1; -} - diff --git a/script/lua/lmem.c b/script/lua/lmem.c deleted file mode 100644 index ae7d8c965..000000000 --- a/script/lua/lmem.c +++ /dev/null @@ -1,86 +0,0 @@ -/* -** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - - -#include - -#define lmem_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -/* -** About the realloc function: -** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); -** (`osize' is the old size, `nsize' is the new size) -** -** Lua ensures that (ptr == NULL) iff (osize == 0). -** -** * frealloc(ud, NULL, 0, x) creates a new block of size `x' -** -** * frealloc(ud, p, x, 0) frees the block `p' -** (in this specific case, frealloc must return NULL). -** particularly, frealloc(ud, NULL, 0, 0) does nothing -** (which is equivalent to free(NULL) in ANSI C) -** -** frealloc returns NULL if it cannot create or reallocate the area -** (any reallocation to an equal or smaller size cannot fail!) -*/ - - - -#define MINSIZEARRAY 4 - - -void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, - int limit, const char *errormsg) { - void *newblock; - int newsize; - if (*size >= limit/2) { /* cannot double it? */ - if (*size >= limit) /* cannot grow even a little? */ - luaG_runerror(L, errormsg); - newsize = limit; /* still have at least one free place */ - } - else { - newsize = (*size)*2; - if (newsize < MINSIZEARRAY) - newsize = MINSIZEARRAY; /* minimum size */ - } - newblock = luaM_reallocv(L, block, *size, newsize, size_elems); - *size = newsize; /* update only when everything else is OK */ - return newblock; -} - - -void *luaM_toobig (lua_State *L) { - luaG_runerror(L, "memory allocation error: block too big"); - return NULL; /* to avoid warnings */ -} - - - -/* -** generic allocation routine. -*/ -void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { - global_State *g = G(L); - lua_assert((osize == 0) == (block == NULL)); - block = (*g->frealloc)(g->ud, block, osize, nsize); - if (block == NULL && nsize > 0) - luaD_throw(L, LUA_ERRMEM); - lua_assert((nsize == 0) == (block == NULL)); - g->totalbytes = (g->totalbytes - osize) + nsize; - return block; -} - diff --git a/script/lua/lmem.h b/script/lua/lmem.h deleted file mode 100644 index d33084d16..000000000 --- a/script/lua/lmem.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - -#ifndef lmem_h -#define lmem_h - -#if 0 -#include -#endif - -#include "llimits.h" -#include "lua.h" - -#define MEMERRMSG "not enough memory" - - -#define luaM_reallocv(L,b,on,n,e) \ - ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ - luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ - luaM_toobig(L)) - -#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) -#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) -#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) - -#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) -#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) -#define luaM_newvector(L,n,t) \ - cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) - -#define luaM_growvector(L,v,nelems,size,t,limit,e) \ - if ((nelems)+1 > (size)) \ - ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) - -#define luaM_reallocvector(L, v,oldn,n,t) \ - ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) - - -LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, - size_t size); -LUAI_FUNC void *luaM_toobig (lua_State *L); -LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, - size_t size_elem, int limit, - const char *errormsg); - -#endif - diff --git a/script/lua/loadlib.c b/script/lua/loadlib.c deleted file mode 100644 index 25e07d1bc..000000000 --- a/script/lua/loadlib.c +++ /dev/null @@ -1,665 +0,0 @@ -/* -** $Id: loadlib.c,v 1.52.1.3 2008/08/06 13:29:28 roberto Exp $ -** Dynamic library loader for Lua -** See Copyright Notice in lua.h -** -** This module contains an implementation of loadlib for Unix systems -** that have dlfcn, an implementation for Darwin (Mac OS X), an -** implementation for Windows, and a stub for other systems. -*/ - - -#include -#include - - -#define loadlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* prefix for open functions in C libraries */ -#define LUA_POF "luaopen_" - -/* separator for open functions in C libraries */ -#define LUA_OFSEP "_" - - -#define LIBPREFIX "LOADLIB: " - -#define POF LUA_POF -#define LIB_FAIL "open" - - -/* error codes for ll_loadfunc */ -#define ERRLIB 1 -#define ERRFUNC 2 - -#define setprogdir(L) ((void)0) - - -static void ll_unloadlib (void *lib); -static void *ll_load (lua_State *L, const char *path); -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); - - - -#if defined(LUA_DL_DLOPEN) -/* -** {======================================================================== -** This is an implementation of loadlib based on the dlfcn interface. -** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, -** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least -** as an emulation layer on top of native functions. -** ========================================================================= -*/ - -#include - -static void ll_unloadlib (void *lib) { - dlclose(lib); -} - - -static void *ll_load (lua_State *L, const char *path) { - void *lib = dlopen(path, RTLD_NOW); - if (lib == NULL) lua_pushstring(L, dlerror()); - return lib; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)dlsym(lib, sym); - if (f == NULL) lua_pushstring(L, dlerror()); - return f; -} - -/* }====================================================== */ - - - -#elif defined(LUA_DL_DLL) -/* -** {====================================================================== -** This is an implementation of loadlib for Windows using native functions. -** ======================================================================= -*/ - -#include - - -#undef setprogdir - -static void setprogdir (lua_State *L) { - char buff[MAX_PATH + 1]; - char *lb; - DWORD nsize = sizeof(buff)/sizeof(char); - DWORD n = GetModuleFileNameA(NULL, buff, nsize); - if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) - luaL_error(L, "unable to get ModuleFileName"); - else { - *lb = '\0'; - luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); - lua_remove(L, -2); /* remove original string */ - } -} - - -static void pusherror (lua_State *L) { - int error = GetLastError(); - char buffer[128]; - if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, error, 0, buffer, sizeof(buffer), NULL)) - lua_pushstring(L, buffer); - else - lua_pushfstring(L, "system error %d\n", error); -} - -static void ll_unloadlib (void *lib) { - FreeLibrary((HINSTANCE)lib); -} - - -static void *ll_load (lua_State *L, const char *path) { - HINSTANCE lib = LoadLibraryA(path); - if (lib == NULL) pusherror(L); - return lib; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym); - if (f == NULL) pusherror(L); - return f; -} - -/* }====================================================== */ - - - -#elif defined(LUA_DL_DYLD) -/* -** {====================================================================== -** Native Mac OS X / Darwin Implementation -** ======================================================================= -*/ - -#include - - -/* Mac appends a `_' before C function names */ -#undef POF -#define POF "_" LUA_POF - - -static void pusherror (lua_State *L) { - const char *err_str; - const char *err_file; - NSLinkEditErrors err; - int err_num; - NSLinkEditError(&err, &err_num, &err_file, &err_str); - lua_pushstring(L, err_str); -} - - -static const char *errorfromcode (NSObjectFileImageReturnCode ret) { - switch (ret) { - case NSObjectFileImageInappropriateFile: - return "file is not a bundle"; - case NSObjectFileImageArch: - return "library is for wrong CPU type"; - case NSObjectFileImageFormat: - return "bad format"; - case NSObjectFileImageAccess: - return "cannot access file"; - case NSObjectFileImageFailure: - default: - return "unable to load library"; - } -} - - -static void ll_unloadlib (void *lib) { - NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); -} - - -static void *ll_load (lua_State *L, const char *path) { - NSObjectFileImage img; - NSObjectFileImageReturnCode ret; - /* this would be a rare case, but prevents crashing if it happens */ - if(!_dyld_present()) { - lua_pushliteral(L, "dyld not present"); - return NULL; - } - ret = NSCreateObjectFileImageFromFile(path, &img); - if (ret == NSObjectFileImageSuccess) { - NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE | - NSLINKMODULE_OPTION_RETURN_ON_ERROR); - NSDestroyObjectFileImage(img); - if (mod == NULL) pusherror(L); - return mod; - } - lua_pushstring(L, errorfromcode(ret)); - return NULL; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym); - if (nss == NULL) { - lua_pushfstring(L, "symbol " LUA_QS " not found", sym); - return NULL; - } - return (lua_CFunction)NSAddressOfSymbol(nss); -} - -/* }====================================================== */ - - - -#else -/* -** {====================================================== -** Fallback for other systems -** ======================================================= -*/ - -#undef LIB_FAIL -#define LIB_FAIL "absent" - - -#define DLMSG "dynamic libraries not enabled; check your Lua installation" - - -static void ll_unloadlib (void *lib) { - (void)lib; /* to avoid warnings */ -} - - -static void *ll_load (lua_State *L, const char *path) { - (void)path; /* to avoid warnings */ - lua_pushliteral(L, DLMSG); - return NULL; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - (void)lib; (void)sym; /* to avoid warnings */ - lua_pushliteral(L, DLMSG); - return NULL; -} - -/* }====================================================== */ -#endif - - - -static void **ll_register (lua_State *L, const char *path) { - void **plib; - lua_pushfstring(L, "%s%s", LIBPREFIX, path); - lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ - if (!lua_isnil(L, -1)) /* is there an entry? */ - plib = (void **)lua_touserdata(L, -1); - else { /* no entry yet; create one */ - lua_pop(L, 1); - plib = (void **)lua_newuserdata(L, sizeof(const void *)); - *plib = NULL; - luaL_getmetatable(L, "_LOADLIB"); - lua_setmetatable(L, -2); - lua_pushfstring(L, "%s%s", LIBPREFIX, path); - lua_pushvalue(L, -2); - lua_settable(L, LUA_REGISTRYINDEX); - } - return plib; -} - - -/* -** __gc tag method: calls library's `ll_unloadlib' function with the lib -** handle -*/ -static int gctm (lua_State *L) { - void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); - if (*lib) ll_unloadlib(*lib); - *lib = NULL; /* mark library as closed */ - return 0; -} - - -static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { - void **reg = ll_register(L, path); - if (*reg == NULL) *reg = ll_load(L, path); - if (*reg == NULL) - return ERRLIB; /* unable to load library */ - else { - lua_CFunction f = ll_sym(L, *reg, sym); - if (f == NULL) - return ERRFUNC; /* unable to find function */ - lua_pushcfunction(L, f); - return 0; /* return function */ - } -} - - -static int ll_loadlib (lua_State *L) { - const char *path = luaL_checkstring(L, 1); - const char *init = luaL_checkstring(L, 2); - int stat = ll_loadfunc(L, path, init); - if (stat == 0) /* no errors? */ - return 1; /* return the loaded function */ - else { /* error; error message is on stack top */ - lua_pushnil(L); - lua_insert(L, -2); - lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); - return 3; /* return nil, error message, and where */ - } -} - - - -/* -** {====================================================== -** 'require' function -** ======================================================= -*/ - - -static int readable (const char *filename) { - FILE *f = fopen(filename, "r"); /* try to open file */ - if (f == NULL) return 0; /* open failed */ - fclose(f); - return 1; -} - - -static const char *pushnexttemplate (lua_State *L, const char *path) { - const char *l; - while (*path == *LUA_PATHSEP) path++; /* skip separators */ - if (*path == '\0') return NULL; /* no more templates */ - l = strchr(path, *LUA_PATHSEP); /* find next separator */ - if (l == NULL) l = path + strlen(path); - lua_pushlstring(L, path, l - path); /* template */ - return l; -} - - -static const char *findfile (lua_State *L, const char *name, - const char *pname) { - const char *path; - name = luaL_gsub(L, name, ".", LUA_DIRSEP); - lua_getfield(L, LUA_ENVIRONINDEX, pname); - path = lua_tostring(L, -1); - if (path == NULL) - luaL_error(L, LUA_QL("package.%s") " must be a string", pname); - lua_pushliteral(L, ""); /* error accumulator */ - while ((path = pushnexttemplate(L, path)) != NULL) { - const char *filename; - filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); - lua_remove(L, -2); /* remove path template */ - if (readable(filename)) /* does file exist and is readable? */ - return filename; /* return that file name */ - lua_pushfstring(L, "\n\tno file " LUA_QS, filename); - lua_remove(L, -2); /* remove file name */ - lua_concat(L, 2); /* add entry to possible error message */ - } - return NULL; /* not found */ -} - - -static void loaderror (lua_State *L, const char *filename) { - luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", - lua_tostring(L, 1), filename, lua_tostring(L, -1)); -} - - -static int loader_Lua (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - filename = findfile(L, name, "path"); - if (filename == NULL) return 1; /* library not found in this path */ - if (luaL_loadfile(L, filename) != 0) - loaderror(L, filename); - return 1; /* library loaded successfully */ -} - - -static const char *mkfuncname (lua_State *L, const char *modname) { - const char *funcname; - const char *mark = strchr(modname, *LUA_IGMARK); - if (mark) modname = mark + 1; - funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); - funcname = lua_pushfstring(L, POF"%s", funcname); - lua_remove(L, -2); /* remove 'gsub' result */ - return funcname; -} - - -static int loader_C (lua_State *L) { - const char *funcname; - const char *name = luaL_checkstring(L, 1); - const char *filename = findfile(L, name, "cpath"); - if (filename == NULL) return 1; /* library not found in this path */ - funcname = mkfuncname(L, name); - if (ll_loadfunc(L, filename, funcname) != 0) - loaderror(L, filename); - return 1; /* library loaded successfully */ -} - - -static int loader_Croot (lua_State *L) { - const char *funcname; - const char *filename; - const char *name = luaL_checkstring(L, 1); - const char *p = strchr(name, '.'); - int stat; - if (p == NULL) return 0; /* is root */ - lua_pushlstring(L, name, p - name); - filename = findfile(L, lua_tostring(L, -1), "cpath"); - if (filename == NULL) return 1; /* root not found */ - funcname = mkfuncname(L, name); - if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { - if (stat != ERRFUNC) loaderror(L, filename); /* real error */ - lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, - name, filename); - return 1; /* function not found */ - } - return 1; -} - - -static int loader_preload (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - lua_getfield(L, LUA_ENVIRONINDEX, "preload"); - if (!lua_istable(L, -1)) - luaL_error(L, LUA_QL("package.preload") " must be a table"); - lua_getfield(L, -1, name); - if (lua_isnil(L, -1)) /* not found? */ - lua_pushfstring(L, "\n\tno field package.preload['%s']", name); - return 1; -} - - -static const int sentinel_ = 0; -#define sentinel ((void *)&sentinel_) - - -static int ll_require (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - int i; - lua_settop(L, 1); /* _LOADED table will be at index 2 */ - lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_getfield(L, 2, name); - if (lua_toboolean(L, -1)) { /* is it there? */ - if (lua_touserdata(L, -1) == sentinel) /* check loops */ - luaL_error(L, "loop or previous error loading module " LUA_QS, name); - return 1; /* package is already loaded */ - } - /* else must load it; iterate over available loaders */ - lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); - if (!lua_istable(L, -1)) - luaL_error(L, LUA_QL("package.loaders") " must be a table"); - lua_pushliteral(L, ""); /* error message accumulator */ - for (i=1; ; i++) { - lua_rawgeti(L, -2, i); /* get a loader */ - if (lua_isnil(L, -1)) - luaL_error(L, "module " LUA_QS " not found:%s", - name, lua_tostring(L, -2)); - lua_pushstring(L, name); - lua_call(L, 1, 1); /* call it */ - if (lua_isfunction(L, -1)) /* did it find module? */ - break; /* module loaded successfully */ - else if (lua_isstring(L, -1)) /* loader returned error message? */ - lua_concat(L, 2); /* accumulate it */ - else - lua_pop(L, 1); - } - lua_pushlightuserdata(L, sentinel); - lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ - lua_pushstring(L, name); /* pass name as argument to module */ - lua_call(L, 1, 1); /* run loaded module */ - if (!lua_isnil(L, -1)) /* non-nil return? */ - lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ - lua_getfield(L, 2, name); - if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ - lua_pushboolean(L, 1); /* use true as result */ - lua_pushvalue(L, -1); /* extra copy to be returned */ - lua_setfield(L, 2, name); /* _LOADED[name] = true */ - } - return 1; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** 'module' function -** ======================================================= -*/ - - -static void setfenv (lua_State *L) { - lua_Debug ar; - if (lua_getstack(L, 1, &ar) == 0 || - lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ - lua_iscfunction(L, -1)) - luaL_error(L, LUA_QL("module") " not called from a Lua function"); - lua_pushvalue(L, -2); - lua_setfenv(L, -2); - lua_pop(L, 1); -} - - -static void dooptions (lua_State *L, int n) { - int i; - for (i = 2; i <= n; i++) { - lua_pushvalue(L, i); /* get option (a function) */ - lua_pushvalue(L, -2); /* module */ - lua_call(L, 1, 0); - } -} - - -static void modinit (lua_State *L, const char *modname) { - const char *dot; - lua_pushvalue(L, -1); - lua_setfield(L, -2, "_M"); /* module._M = module */ - lua_pushstring(L, modname); - lua_setfield(L, -2, "_NAME"); - dot = strrchr(modname, '.'); /* look for last dot in module name */ - if (dot == NULL) dot = modname; - else dot++; - /* set _PACKAGE as package name (full module name minus last part) */ - lua_pushlstring(L, modname, dot - modname); - lua_setfield(L, -2, "_PACKAGE"); -} - - -static int ll_module (lua_State *L) { - const char *modname = luaL_checkstring(L, 1); - int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ - lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ - if (!lua_istable(L, -1)) { /* not found? */ - lua_pop(L, 1); /* remove previous result */ - /* try global variable (and create one if it does not exist) */ - if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL) - return luaL_error(L, "name conflict for module " LUA_QS, modname); - lua_pushvalue(L, -1); - lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ - } - /* check whether table already has a _NAME field */ - lua_getfield(L, -1, "_NAME"); - if (!lua_isnil(L, -1)) /* is table an initialized module? */ - lua_pop(L, 1); - else { /* no; initialize it */ - lua_pop(L, 1); - modinit(L, modname); - } - lua_pushvalue(L, -1); - setfenv(L); - dooptions(L, loaded - 1); - return 0; -} - - -static int ll_seeall (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - if (!lua_getmetatable(L, 1)) { - lua_createtable(L, 0, 1); /* create new metatable */ - lua_pushvalue(L, -1); - lua_setmetatable(L, 1); - } - lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_setfield(L, -2, "__index"); /* mt.__index = _G */ - return 0; -} - - -/* }====================================================== */ - - - -/* auxiliary mark (for internal use) */ -#define AUXMARK "\1" - -static void setpath (lua_State *L, const char *fieldname, const char *envname, - const char *def) { - const char *path = getenv(envname); - if (path == NULL) /* no environment variable? */ - lua_pushstring(L, def); /* use default */ - else { - /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ - path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, - LUA_PATHSEP AUXMARK LUA_PATHSEP); - luaL_gsub(L, path, AUXMARK, def); - lua_remove(L, -2); - } - setprogdir(L); - lua_setfield(L, -2, fieldname); -} - - -static const luaL_Reg pk_funcs[] = { - {"loadlib", ll_loadlib}, - {"seeall", ll_seeall}, - {NULL, NULL} -}; - - -static const luaL_Reg ll_funcs[] = { - {"module", ll_module}, - {"require", ll_require}, - {NULL, NULL} -}; - - -static const lua_CFunction loaders[] = - {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; - - -LUALIB_API int luaopen_package (lua_State *L) { - int i; - /* create new type _LOADLIB */ - luaL_newmetatable(L, "_LOADLIB"); - lua_pushcfunction(L, gctm); - lua_setfield(L, -2, "__gc"); - /* create `package' table */ - luaL_register(L, LUA_LOADLIBNAME, pk_funcs); -#if defined(LUA_COMPAT_LOADLIB) - lua_getfield(L, -1, "loadlib"); - lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); -#endif - lua_pushvalue(L, -1); - lua_replace(L, LUA_ENVIRONINDEX); - /* create `loaders' table */ - lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1); - /* fill it with pre-defined loaders */ - for (i=0; loaders[i] != NULL; i++) { - lua_pushcfunction(L, loaders[i]); - lua_rawseti(L, -2, i+1); - } - lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ - setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ - setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ - /* store config information */ - lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" - LUA_EXECDIR "\n" LUA_IGMARK); - lua_setfield(L, -2, "config"); - /* set field `loaded' */ - luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); - lua_setfield(L, -2, "loaded"); - /* set field `preload' */ - lua_newtable(L); - lua_setfield(L, -2, "preload"); - lua_pushvalue(L, LUA_GLOBALSINDEX); - luaL_register(L, NULL, ll_funcs); /* open lib into global table */ - lua_pop(L, 1); - return 1; /* return 'package' table */ -} diff --git a/script/lua/lobject.c b/script/lua/lobject.c deleted file mode 100644 index 1e181d284..000000000 --- a/script/lua/lobject.c +++ /dev/null @@ -1,216 +0,0 @@ -/* -** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ -** Some generic functions over Lua objects -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#include -#include -#include -#include -#endif - -#define lobject_c -#define LUA_CORE - -#include "lua.h" - -#include "ldo.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "lvm.h" - - - -const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; - - -/* -** converts an integer to a "floating point byte", represented as -** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if -** eeeee != 0 and (xxx) otherwise. -*/ -int luaO_int2fb (unsigned int x) { - int e = 0; /* expoent */ - while (x >= 16) { - x = (x+1) >> 1; - e++; - } - if (x < 8) return x; - else return ((e+1) << 3) | (cast_int(x) - 8); -} - - -/* converts back */ -int luaO_fb2int (int x) { - int e = (x >> 3) & 31; - if (e == 0) return x; - else return ((x & 7)+8) << (e - 1); -} - - -int luaO_log2 (unsigned int x) { - static const lu_byte log_2[256] = { - 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - }; - int l = -1; - while (x >= 256) { l += 8; x >>= 8; } - return l + log_2[x]; - -} - - -int luaO_rawequalObj (const TValue *t1, const TValue *t2) { - if (ttype(t1) != ttype(t2)) return 0; - else switch (ttype(t1)) { - case LUA_TNIL: - return 1; - case LUA_TNUMBER: - return luai_numeq(nvalue(t1), nvalue(t2)); - case LUA_TBOOLEAN: - return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ - case LUA_TLIGHTUSERDATA: - return pvalue(t1) == pvalue(t2); - default: - lua_assert(iscollectable(t1)); - return gcvalue(t1) == gcvalue(t2); - } -} - - -int luaO_str2d (const char *s, lua_Number *result) { - char *endptr; - *result = lua_str2number(s, &endptr); - if (endptr == s) return 0; /* conversion failed */ - if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ - *result = cast_num(strtoul(s, &endptr, 16)); - if (*endptr == '\0') return 1; /* most common case */ - while (isspace(cast(unsigned char, *endptr))) endptr++; - if (*endptr != '\0') return 0; /* invalid trailing characters? */ - return 1; -} - - - -static void pushstr (lua_State *L, const char *str) { - setsvalue2s(L, L->top, luaS_new(L, str)); - incr_top(L); -} - - -/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ -const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { - int n = 1; - pushstr(L, ""); - for (;;) { - const char *e = strchr(fmt, '%'); - if (e == NULL) break; - setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); - incr_top(L); - switch (*(e+1)) { - case 's': { - const char *s = va_arg(argp, char *); - if (s == NULL) s = "(null)"; - pushstr(L, s); - break; - } - case 'c': { - char buff[2]; - buff[0] = cast(char, va_arg(argp, int)); - buff[1] = '\0'; - pushstr(L, buff); - break; - } - case 'd': { - setnvalue(L->top, cast_num(va_arg(argp, int))); - incr_top(L); - break; - } - case 'f': { - setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); - incr_top(L); - break; - } - case 'p': { - char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ - sprintf(buff, "%p", va_arg(argp, void *)); - pushstr(L, buff); - break; - } - case '%': { - pushstr(L, "%"); - break; - } - default: { - char buff[3]; - buff[0] = '%'; - buff[1] = *(e+1); - buff[2] = '\0'; - pushstr(L, buff); - break; - } - } - n += 2; - fmt = e+2; - } - pushstr(L, fmt); - luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); - L->top -= n; - return svalue(L->top - 1); -} - - -const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { - const char *msg; - va_list argp; - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - return msg; -} - - -void luaO_chunkid (char *out, const char *source, size_t bufflen) { - if (*source == '=') { - strncpy(out, source+1, bufflen); /* remove first char */ - out[bufflen-1] = '\0'; /* ensures null termination */ - } - else { /* out = "source", or "...source" */ - if (*source == '@') { - size_t l; - source++; /* skip the `@' */ - bufflen -= sizeof(" '...' "); - l = strlen(source); - strcpy(out, ""); - if (l > bufflen) { - source += (l-bufflen); /* get last part of file name */ - strcat(out, "..."); - } - strcat(out, source); - } - else { /* out = [string "string"] */ - size_t len = strcspn(source, "\n\r"); /* stop at first newline */ - bufflen -= sizeof(" [string \"...\"] "); - if (len > bufflen) len = bufflen; - strcpy(out, "[string \""); - if (source[len] != '\0') { /* must truncate? */ - strncat(out, source, len); - strcat(out, "..."); - } - else - strcat(out, source); - strcat(out, "\"]"); - } - } -} diff --git a/script/lua/lobject.h b/script/lua/lobject.h deleted file mode 100644 index 6234d507c..000000000 --- a/script/lua/lobject.h +++ /dev/null @@ -1,380 +0,0 @@ -/* -** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ -** Type definitions for Lua objects -** See Copyright Notice in lua.h -*/ - - -#ifndef lobject_h -#define lobject_h - - -#include - - -#include "llimits.h" -#include "lua.h" - - -/* tags for values visible from Lua */ -#define LAST_TAG LUA_TTHREAD - -#define NUM_TAGS (LAST_TAG+1) - - -/* -** Extra tags for non-values -*/ -#define LUA_TPROTO (LAST_TAG+1) -#define LUA_TUPVAL (LAST_TAG+2) -#define LUA_TDEADKEY (LAST_TAG+3) - - -/* -** Union of all collectable objects -*/ -typedef union GCObject GCObject; - - -/* -** Common Header for all collectable objects (in macro form, to be -** included in other objects) -*/ -#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked - - -/* -** Common header in struct form -*/ -typedef struct GCheader { - CommonHeader; -} GCheader; - - - - -/* -** Union of all Lua values -*/ -typedef union { - GCObject *gc; - void *p; - lua_Number n; - int b; -} Value; - - -/* -** Tagged Values -*/ - -#define TValuefields Value value; int tt - -typedef struct lua_TValue { - TValuefields; -} TValue; - - -/* Macros to test type */ -#define ttisnil(o) (ttype(o) == LUA_TNIL) -#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) -#define ttisstring(o) (ttype(o) == LUA_TSTRING) -#define ttistable(o) (ttype(o) == LUA_TTABLE) -#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) -#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) -#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) -#define ttisthread(o) (ttype(o) == LUA_TTHREAD) -#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) - -/* Macros to access values */ -#define ttype(o) ((o)->tt) -#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) -#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) -#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) -#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) -#define tsvalue(o) (&rawtsvalue(o)->tsv) -#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) -#define uvalue(o) (&rawuvalue(o)->uv) -#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) -#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) -#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) -#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) - -#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) - -/* -** for internal debug only -*/ -#define checkconsistency(obj) \ - lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) - -#define checkliveness(g,obj) \ - lua_assert(!iscollectable(obj) || \ - ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) - - -/* Macros to set values */ -#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) - -#define setnvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } - -#define setpvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } - -#define setbvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } - -#define setsvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ - checkliveness(G(L),i_o); } - -#define setuvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ - checkliveness(G(L),i_o); } - -#define setthvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ - checkliveness(G(L),i_o); } - -#define setclvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ - checkliveness(G(L),i_o); } - -#define sethvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ - checkliveness(G(L),i_o); } - -#define setptvalue(L,obj,x) \ - { TValue *i_o=(obj); \ - i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ - checkliveness(G(L),i_o); } - - - - -#define setobj(L,obj1,obj2) \ - { const TValue *o2=(obj2); TValue *o1=(obj1); \ - o1->value = o2->value; o1->tt=o2->tt; \ - checkliveness(G(L),o1); } - - -/* -** different types of sets, according to destination -*/ - -/* from stack to (same) stack */ -#define setobjs2s setobj -/* to stack (not from same stack) */ -#define setobj2s setobj -#define setsvalue2s setsvalue -#define sethvalue2s sethvalue -#define setptvalue2s setptvalue -/* from table to same table */ -#define setobjt2t setobj -/* to table */ -#define setobj2t setobj -/* to new object */ -#define setobj2n setobj -#define setsvalue2n setsvalue - -#define setttype(obj, tt) (ttype(obj) = (tt)) - - -#define iscollectable(o) (ttype(o) >= LUA_TSTRING) - - - -typedef TValue *StkId; /* index to stack elements */ - - -/* -** String headers for string table -*/ -typedef union TString { - L_Umaxalign dummy; /* ensures maximum alignment for strings */ - struct { - CommonHeader; - lu_byte reserved; - unsigned int hash; - size_t len; - } tsv; -} TString; - - -#define getstr(ts) cast(const char *, (ts) + 1) -#define svalue(o) getstr(rawtsvalue(o)) - - - -typedef union Udata { - L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ - struct { - CommonHeader; - struct Table *metatable; - struct Table *env; - size_t len; - } uv; -} Udata; - - - - -/* -** Function Prototypes -*/ -typedef struct Proto { - CommonHeader; - TValue *k; /* constants used by the function */ - Instruction *code; - struct Proto **p; /* functions defined inside the function */ - int *lineinfo; /* map from opcodes to source lines */ - struct LocVar *locvars; /* information about local variables */ - TString **upvalues; /* upvalue names */ - TString *source; - int sizeupvalues; - int sizek; /* size of `k' */ - int sizecode; - int sizelineinfo; - int sizep; /* size of `p' */ - int sizelocvars; - int linedefined; - int lastlinedefined; - GCObject *gclist; - lu_byte nups; /* number of upvalues */ - lu_byte numparams; - lu_byte is_vararg; - lu_byte maxstacksize; -} Proto; - - -/* masks for new-style vararg */ -#define VARARG_HASARG 1 -#define VARARG_ISVARARG 2 -#define VARARG_NEEDSARG 4 - - -typedef struct LocVar { - TString *varname; - int startpc; /* first point where variable is active */ - int endpc; /* first point where variable is dead */ -} LocVar; - - - -/* -** Upvalues -*/ - -typedef struct UpVal { - CommonHeader; - TValue *v; /* points to stack or to its own value */ - union { - TValue value; /* the value (when closed) */ - struct { /* double linked list (when open) */ - struct UpVal *prev; - struct UpVal *next; - } l; - } u; -} UpVal; - - -/* -** Closures -*/ - -#define ClosureHeader \ - CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ - struct Table *env - -typedef struct CClosure { - ClosureHeader; - lua_CFunction f; - TValue upvalue[1]; -} CClosure; - - -typedef struct LClosure { - ClosureHeader; - struct Proto *p; - UpVal *upvals[1]; -} LClosure; - - -typedef union Closure { - CClosure c; - LClosure l; -} Closure; - - -#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) -#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) - - -/* -** Tables -*/ - -typedef union TKey { - struct { - TValuefields; - struct Node *next; /* for chaining */ - } nk; - TValue tvk; -} TKey; - - -typedef struct Node { - TValue i_val; - TKey i_key; -} Node; - - -typedef struct Table { - CommonHeader; - lu_byte flags; /* 1<

lsizenode)) - - -#define luaO_nilobject (&luaO_nilobject_) - -LUAI_DATA const TValue luaO_nilobject_; - -#define ceillog2(x) (luaO_log2((x)-1) + 1) - -LUAI_FUNC int luaO_log2 (unsigned int x); -LUAI_FUNC int luaO_int2fb (unsigned int x); -LUAI_FUNC int luaO_fb2int (int x); -LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); -LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); -LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, - va_list argp); -LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); -LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); - - -#endif diff --git a/script/lua/lopcodes.c b/script/lua/lopcodes.c deleted file mode 100644 index 4cc745230..000000000 --- a/script/lua/lopcodes.c +++ /dev/null @@ -1,102 +0,0 @@ -/* -** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ -** See Copyright Notice in lua.h -*/ - - -#define lopcodes_c -#define LUA_CORE - - -#include "lopcodes.h" - - -/* ORDER OP */ - -const char *const luaP_opnames[NUM_OPCODES+1] = { - "MOVE", - "LOADK", - "LOADBOOL", - "LOADNIL", - "GETUPVAL", - "GETGLOBAL", - "GETTABLE", - "SETGLOBAL", - "SETUPVAL", - "SETTABLE", - "NEWTABLE", - "SELF", - "ADD", - "SUB", - "MUL", - "DIV", - "MOD", - "POW", - "UNM", - "NOT", - "LEN", - "CONCAT", - "JMP", - "EQ", - "LT", - "LE", - "TEST", - "TESTSET", - "CALL", - "TAILCALL", - "RETURN", - "FORLOOP", - "FORPREP", - "TFORLOOP", - "SETLIST", - "CLOSE", - "CLOSURE", - "VARARG", - NULL -}; - - -#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) - -const lu_byte luaP_opmodes[NUM_OPCODES] = { -/* T A B C mode opcode */ - opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ - ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ - ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ - ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ - ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ - ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ - ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ - ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ -}; - diff --git a/script/lua/lopcodes.h b/script/lua/lopcodes.h deleted file mode 100644 index ad66eea98..000000000 --- a/script/lua/lopcodes.h +++ /dev/null @@ -1,268 +0,0 @@ -/* -** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ -** Opcodes for Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lopcodes_h -#define lopcodes_h - -#include "llimits.h" - - -/*=========================================================================== - We assume that instructions are unsigned numbers. - All instructions have an opcode in the first 6 bits. - Instructions can have the following fields: - `A' : 8 bits - `B' : 9 bits - `C' : 9 bits - `Bx' : 18 bits (`B' and `C' together) - `sBx' : signed Bx - - A signed argument is represented in excess K; that is, the number - value is the unsigned value minus K. K is exactly the maximum value - for that argument (so that -max is represented by 0, and +max is - represented by 2*max), which is half the maximum for the corresponding - unsigned argument. -===========================================================================*/ - - -enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ - - -/* -** size and position of opcode arguments. -*/ -#define SIZE_C 9 -#define SIZE_B 9 -#define SIZE_Bx (SIZE_C + SIZE_B) -#define SIZE_A 8 - -#define SIZE_OP 6 - -#define POS_OP 0 -#define POS_A (POS_OP + SIZE_OP) -#define POS_C (POS_A + SIZE_A) -#define POS_B (POS_C + SIZE_C) -#define POS_Bx POS_C - - -/* -** limits for opcode arguments. -** we use (signed) int to manipulate most arguments, -** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) -*/ -#if SIZE_Bx < LUAI_BITSINT-1 -#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ -#else -#define MAXARG_Bx MAX_INT -#define MAXARG_sBx MAX_INT -#endif - - -#define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0))) -#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ - ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) -#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ - ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) -#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ - ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) -#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ - ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) -#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ - ((cast(Instruction, b)< C) then pc++ */ -OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ - -OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ - -OP_FORLOOP,/* A sBx R(A)+=R(A+2); - if R(A) =) R(A)*/ -OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ - -OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ -} OpCode; - - -#define NUM_OPCODES (cast(int, OP_VARARG) + 1) - - - -/*=========================================================================== - Notes: - (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, - and can be 0: OP_CALL then sets `top' to last_result+1, so - next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. - - (*) In OP_VARARG, if (B == 0) then use actual number of varargs and - set top (like in OP_CALL with C == 0). - - (*) In OP_RETURN, if (B == 0) then return up to `top' - - (*) In OP_SETLIST, if (B == 0) then B = `top'; - if (C == 0) then next `instruction' is real C - - (*) For comparisons, A specifies what condition the test should accept - (true or false). - - (*) All `skips' (pc++) assume that next instruction is a jump -===========================================================================*/ - - -/* -** masks for instruction properties. The format is: -** bits 0-1: op mode -** bits 2-3: C arg mode -** bits 4-5: B arg mode -** bit 6: instruction set register A -** bit 7: operator is a test -*/ - -enum OpArgMask { - OpArgN, /* argument is not used */ - OpArgU, /* argument is used */ - OpArgR, /* argument is a register or a jump offset */ - OpArgK /* argument is a constant or register/constant */ -}; - -LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; - -#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) -#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) -#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) -#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) -#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) - - -LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ - - -/* number of list items to accumulate before a SETLIST instruction */ -#define LFIELDS_PER_FLUSH 50 - - -#endif diff --git a/script/lua/loslib.c b/script/lua/loslib.c deleted file mode 100644 index da06a572a..000000000 --- a/script/lua/loslib.c +++ /dev/null @@ -1,243 +0,0 @@ -/* -** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ -** Standard Operating System library -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - -#define loslib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -static int os_pushresult (lua_State *L, int i, const char *filename) { - int en = errno; /* calls to Lua API may change this value */ - if (i) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushnil(L); - lua_pushfstring(L, "%s: %s", filename, strerror(en)); - lua_pushinteger(L, en); - return 3; - } -} - - -static int os_execute (lua_State *L) { - lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); - return 1; -} - - -static int os_remove (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - return os_pushresult(L, remove(filename) == 0, filename); -} - - -static int os_rename (lua_State *L) { - const char *fromname = luaL_checkstring(L, 1); - const char *toname = luaL_checkstring(L, 2); - return os_pushresult(L, rename(fromname, toname) == 0, fromname); -} - - -static int os_tmpname (lua_State *L) { - char buff[LUA_TMPNAMBUFSIZE]; - int err; - lua_tmpnam(buff, err); - if (err) - return luaL_error(L, "unable to generate a unique filename"); - lua_pushstring(L, buff); - return 1; -} - - -static int os_getenv (lua_State *L) { - lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ - return 1; -} - - -static int os_clock (lua_State *L) { - lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); - return 1; -} - - -/* -** {====================================================== -** Time/Date operations -** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, -** wday=%w+1, yday=%j, isdst=? } -** ======================================================= -*/ - -static void setfield (lua_State *L, const char *key, int value) { - lua_pushinteger(L, value); - lua_setfield(L, -2, key); -} - -static void setboolfield (lua_State *L, const char *key, int value) { - if (value < 0) /* undefined? */ - return; /* does not set field */ - lua_pushboolean(L, value); - lua_setfield(L, -2, key); -} - -static int getboolfield (lua_State *L, const char *key) { - int res; - lua_getfield(L, -1, key); - res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); - lua_pop(L, 1); - return res; -} - - -static int getfield (lua_State *L, const char *key, int d) { - int res; - lua_getfield(L, -1, key); - if (lua_isnumber(L, -1)) - res = (int)lua_tointeger(L, -1); - else { - if (d < 0) - return luaL_error(L, "field " LUA_QS " missing in date table", key); - res = d; - } - lua_pop(L, 1); - return res; -} - - -static int os_date (lua_State *L) { - const char *s = luaL_optstring(L, 1, "%c"); - time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); - struct tm *stm; - if (*s == '!') { /* UTC? */ - stm = gmtime(&t); - s++; /* skip `!' */ - } - else - stm = localtime(&t); - if (stm == NULL) /* invalid date? */ - lua_pushnil(L); - else if (strcmp(s, "*t") == 0) { - lua_createtable(L, 0, 9); /* 9 = number of fields */ - setfield(L, "sec", stm->tm_sec); - setfield(L, "min", stm->tm_min); - setfield(L, "hour", stm->tm_hour); - setfield(L, "day", stm->tm_mday); - setfield(L, "month", stm->tm_mon+1); - setfield(L, "year", stm->tm_year+1900); - setfield(L, "wday", stm->tm_wday+1); - setfield(L, "yday", stm->tm_yday+1); - setboolfield(L, "isdst", stm->tm_isdst); - } - else { - char cc[3]; - luaL_Buffer b; - cc[0] = '%'; cc[2] = '\0'; - luaL_buffinit(L, &b); - for (; *s; s++) { - if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ - luaL_addchar(&b, *s); - else { - size_t reslen; - char buff[200]; /* should be big enough for any conversion result */ - cc[1] = *(++s); - reslen = strftime(buff, sizeof(buff), cc, stm); - luaL_addlstring(&b, buff, reslen); - } - } - luaL_pushresult(&b); - } - return 1; -} - - -static int os_time (lua_State *L) { - time_t t; - if (lua_isnoneornil(L, 1)) /* called without args? */ - t = time(NULL); /* get current time */ - else { - struct tm ts; - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 1); /* make sure table is at the top */ - ts.tm_sec = getfield(L, "sec", 0); - ts.tm_min = getfield(L, "min", 0); - ts.tm_hour = getfield(L, "hour", 12); - ts.tm_mday = getfield(L, "day", -1); - ts.tm_mon = getfield(L, "month", -1) - 1; - ts.tm_year = getfield(L, "year", -1) - 1900; - ts.tm_isdst = getboolfield(L, "isdst"); - t = mktime(&ts); - } - if (t == (time_t)(-1)) - lua_pushnil(L); - else - lua_pushnumber(L, (lua_Number)t); - return 1; -} - - -static int os_difftime (lua_State *L) { - lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), - (time_t)(luaL_optnumber(L, 2, 0)))); - return 1; -} - -/* }====================================================== */ - - -static int os_setlocale (lua_State *L) { - static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, - LC_NUMERIC, LC_TIME}; - static const char *const catnames[] = {"all", "collate", "ctype", "monetary", - "numeric", "time", NULL}; - const char *l = luaL_optstring(L, 1, NULL); - int op = luaL_checkoption(L, 2, "all", catnames); - lua_pushstring(L, setlocale(cat[op], l)); - return 1; -} - - -static int os_exit (lua_State *L) { - exit(luaL_optint(L, 1, EXIT_SUCCESS)); -} - -static const luaL_Reg syslib[] = { - {"clock", os_clock}, - {"date", os_date}, - {"difftime", os_difftime}, - {"execute", os_execute}, - {"exit", os_exit}, - {"getenv", os_getenv}, - {"remove", os_remove}, - {"rename", os_rename}, - {"setlocale", os_setlocale}, - {"time", os_time}, - {"tmpname", os_tmpname}, - {NULL, NULL} -}; - -/* }====================================================== */ - - - -LUALIB_API int luaopen_os (lua_State *L) { - luaL_register(L, LUA_OSLIBNAME, syslib); - return 1; -} - diff --git a/script/lua/lparser.c b/script/lua/lparser.c deleted file mode 100644 index 309f51891..000000000 --- a/script/lua/lparser.c +++ /dev/null @@ -1,1340 +0,0 @@ -/* -** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ -** Lua Parser -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#endif - -#define lparser_c -#define LUA_CORE - -#include "lua.h" - -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" - - - -#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) - -#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) - -#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) - - -/* -** nodes for block list (list of active blocks) -*/ -typedef struct BlockCnt { - struct BlockCnt *previous; /* chain */ - int breaklist; /* list of jumps out of this loop */ - lu_byte nactvar; /* # active locals outside the breakable structure */ - lu_byte upval; /* true if some variable in the block is an upvalue */ - lu_byte isbreakable; /* true if `block' is a loop */ -} BlockCnt; - - - -/* -** prototypes for recursive non-terminal functions -*/ -static void chunk (LexState *ls); -static void expr (LexState *ls, expdesc *v); - - -static void anchor_token (LexState *ls) { - if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { - TString *ts = ls->t.seminfo.ts; - luaX_newstring(ls, getstr(ts), ts->tsv.len); - } -} - - -static void error_expected (LexState *ls, int token) { - luaX_syntaxerror(ls, - luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); -} - - -static void errorlimit (FuncState *fs, int limit, const char *what) { - const char *msg = (fs->f->linedefined == 0) ? - luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : - luaO_pushfstring(fs->L, "function at line %d has more than %d %s", - fs->f->linedefined, limit, what); - luaX_lexerror(fs->ls, msg, 0); -} - - -static int testnext (LexState *ls, int c) { - if (ls->t.token == c) { - luaX_next(ls); - return 1; - } - else return 0; -} - - -static void check (LexState *ls, int c) { - if (ls->t.token != c) - error_expected(ls, c); -} - -static void checknext (LexState *ls, int c) { - check(ls, c); - luaX_next(ls); -} - - -#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } - - - -static void check_match (LexState *ls, int what, int who, int where) { - if (!testnext(ls, what)) { - if (where == ls->linenumber) - error_expected(ls, what); - else { - luaX_syntaxerror(ls, luaO_pushfstring(ls->L, - LUA_QS " expected (to close " LUA_QS " at line %d)", - luaX_token2str(ls, what), luaX_token2str(ls, who), where)); - } - } -} - - -static TString *str_checkname (LexState *ls) { - TString *ts; - check(ls, TK_NAME); - ts = ls->t.seminfo.ts; - luaX_next(ls); - return ts; -} - - -static void init_exp (expdesc *e, expkind k, int i) { - e->f = e->t = NO_JUMP; - e->k = k; - e->u.s.info = i; -} - - -static void codestring (LexState *ls, expdesc *e, TString *s) { - init_exp(e, VK, luaK_stringK(ls->fs, s)); -} - - -static void checkname(LexState *ls, expdesc *e) { - codestring(ls, e, str_checkname(ls)); -} - - -static int registerlocalvar (LexState *ls, TString *varname) { - FuncState *fs = ls->fs; - Proto *f = fs->f; - int oldsize = f->sizelocvars; - luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, - LocVar, SHRT_MAX, "too many local variables"); - while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; - f->locvars[fs->nlocvars].varname = varname; - luaC_objbarrier(ls->L, f, varname); - return fs->nlocvars++; -} - - -#define new_localvarliteral(ls,v,n) \ - new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) - - -static void new_localvar (LexState *ls, TString *name, int n) { - FuncState *fs = ls->fs; - luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); - fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); -} - - -static void adjustlocalvars (LexState *ls, int nvars) { - FuncState *fs = ls->fs; - fs->nactvar = cast_byte(fs->nactvar + nvars); - for (; nvars; nvars--) { - getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; - } -} - - -static void removevars (LexState *ls, int tolevel) { - FuncState *fs = ls->fs; - while (fs->nactvar > tolevel) - getlocvar(fs, --fs->nactvar).endpc = fs->pc; -} - - -static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { - int i; - Proto *f = fs->f; - int oldsize = f->sizeupvalues; - for (i=0; inups; i++) { - if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { - lua_assert(f->upvalues[i] == name); - return i; - } - } - /* new one */ - luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); - luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, - TString *, MAX_INT, ""); - while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; - f->upvalues[f->nups] = name; - luaC_objbarrier(fs->L, f, name); - lua_assert(v->k == VLOCAL || v->k == VUPVAL); - fs->upvalues[f->nups].k = cast_byte(v->k); - fs->upvalues[f->nups].info = cast_byte(v->u.s.info); - return f->nups++; -} - - -static int searchvar (FuncState *fs, TString *n) { - int i; - for (i=fs->nactvar-1; i >= 0; i--) { - if (n == getlocvar(fs, i).varname) - return i; - } - return -1; /* not found */ -} - - -static void markupval (FuncState *fs, int level) { - BlockCnt *bl = fs->bl; - while (bl && bl->nactvar > level) bl = bl->previous; - if (bl) bl->upval = 1; -} - - -static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { - if (fs == NULL) { /* no more levels? */ - init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ - return VGLOBAL; - } - else { - int v = searchvar(fs, n); /* look up at current level */ - if (v >= 0) { - init_exp(var, VLOCAL, v); - if (!base) - markupval(fs, v); /* local will be used as an upval */ - return VLOCAL; - } - else { /* not found at current level; try upper one */ - if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) - return VGLOBAL; - var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ - var->k = VUPVAL; /* upvalue in this level */ - return VUPVAL; - } - } -} - - -static void singlevar (LexState *ls, expdesc *var) { - TString *varname = str_checkname(ls); - FuncState *fs = ls->fs; - if (singlevaraux(fs, varname, var, 1) == VGLOBAL) - var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ -} - - -static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { - FuncState *fs = ls->fs; - int extra = nvars - nexps; - if (hasmultret(e->k)) { - extra++; /* includes call itself */ - if (extra < 0) extra = 0; - luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ - if (extra > 1) luaK_reserveregs(fs, extra-1); - } - else { - if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ - if (extra > 0) { - int reg = fs->freereg; - luaK_reserveregs(fs, extra); - luaK_nil(fs, reg, extra); - } - } -} - - -static void enterlevel (LexState *ls) { - if (++ls->L->nCcalls > LUAI_MAXCCALLS) - luaX_lexerror(ls, "chunk has too many syntax levels", 0); -} - - -#define leavelevel(ls) ((ls)->L->nCcalls--) - - -static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { - bl->breaklist = NO_JUMP; - bl->isbreakable = isbreakable; - bl->nactvar = fs->nactvar; - bl->upval = 0; - bl->previous = fs->bl; - fs->bl = bl; - lua_assert(fs->freereg == fs->nactvar); -} - - -static void leaveblock (FuncState *fs) { - BlockCnt *bl = fs->bl; - fs->bl = bl->previous; - removevars(fs->ls, bl->nactvar); - if (bl->upval) - luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); - /* a block either controls scope or breaks (never both) */ - lua_assert(!bl->isbreakable || !bl->upval); - lua_assert(bl->nactvar == fs->nactvar); - fs->freereg = fs->nactvar; /* free registers */ - luaK_patchtohere(fs, bl->breaklist); -} - - -static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { - FuncState *fs = ls->fs; - Proto *f = fs->f; - int oldsize = f->sizep; - int i; - luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, - MAXARG_Bx, "constant table overflow"); - while (oldsize < f->sizep) f->p[oldsize++] = NULL; - f->p[fs->np++] = func->f; - luaC_objbarrier(ls->L, f, func->f); - init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); - for (i=0; if->nups; i++) { - OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; - luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); - } -} - - -static void open_func (LexState *ls, FuncState *fs) { - lua_State *L = ls->L; - Proto *f = luaF_newproto(L); - fs->f = f; - fs->prev = ls->fs; /* linked list of funcstates */ - fs->ls = ls; - fs->L = L; - ls->fs = fs; - fs->pc = 0; - fs->lasttarget = -1; - fs->jpc = NO_JUMP; - fs->freereg = 0; - fs->nk = 0; - fs->np = 0; - fs->nlocvars = 0; - fs->nactvar = 0; - fs->bl = NULL; - f->source = ls->source; - f->maxstacksize = 2; /* registers 0/1 are always valid */ - fs->h = luaH_new(L, 0, 0); - /* anchor table of constants and prototype (to avoid being collected) */ - sethvalue2s(L, L->top, fs->h); - incr_top(L); - setptvalue2s(L, L->top, f); - incr_top(L); -} - - -static void close_func (LexState *ls) { - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; - removevars(ls, 0); - luaK_ret(fs, 0, 0); /* final return */ - luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); - f->sizecode = fs->pc; - luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); - f->sizelineinfo = fs->pc; - luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); - f->sizek = fs->nk; - luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); - f->sizep = fs->np; - luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); - f->sizelocvars = fs->nlocvars; - luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); - f->sizeupvalues = f->nups; - lua_assert(luaG_checkcode(f)); - lua_assert(fs->bl == NULL); - ls->fs = fs->prev; - L->top -= 2; /* remove table and prototype from the stack */ - /* last token read was anchored in defunct function; must reanchor it */ - if (fs) anchor_token(ls); -} - - -Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { - struct LexState lexstate; - struct FuncState funcstate; - lexstate.buff = buff; - luaX_setinput(L, &lexstate, z, luaS_new(L, name)); - open_func(&lexstate, &funcstate); - funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ - luaX_next(&lexstate); /* read first token */ - chunk(&lexstate); - check(&lexstate, TK_EOS); - close_func(&lexstate); - lua_assert(funcstate.prev == NULL); - lua_assert(funcstate.f->nups == 0); - lua_assert(lexstate.fs == NULL); - return funcstate.f; -} - - - -/*============================================================*/ -/* GRAMMAR RULES */ -/*============================================================*/ - - -static void field (LexState *ls, expdesc *v) { - /* field -> ['.' | ':'] NAME */ - FuncState *fs = ls->fs; - expdesc key; - luaK_exp2anyreg(fs, v); - luaX_next(ls); /* skip the dot or colon */ - checkname(ls, &key); - luaK_indexed(fs, v, &key); -} - - -static void yindex (LexState *ls, expdesc *v) { - /* index -> '[' expr ']' */ - luaX_next(ls); /* skip the '[' */ - expr(ls, v); - luaK_exp2val(ls->fs, v); - checknext(ls, ']'); -} - - -/* -** {====================================================================== -** Rules for Constructors -** ======================================================================= -*/ - - -struct ConsControl { - expdesc v; /* last list item read */ - expdesc *t; /* table descriptor */ - int nh; /* total number of `record' elements */ - int na; /* total number of array elements */ - int tostore; /* number of array elements pending to be stored */ -}; - - -static void recfield (LexState *ls, struct ConsControl *cc) { - /* recfield -> (NAME | `['exp1`]') = exp1 */ - FuncState *fs = ls->fs; - int reg = ls->fs->freereg; - expdesc key, val; - int rkkey; - if (ls->t.token == TK_NAME) { - luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); - checkname(ls, &key); - } - else /* ls->t.token == '[' */ - yindex(ls, &key); - cc->nh++; - checknext(ls, '='); - rkkey = luaK_exp2RK(fs, &key); - expr(ls, &val); - luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); - fs->freereg = reg; /* free registers */ -} - - -static void closelistfield (FuncState *fs, struct ConsControl *cc) { - if (cc->v.k == VVOID) return; /* there is no list item */ - luaK_exp2nextreg(fs, &cc->v); - cc->v.k = VVOID; - if (cc->tostore == LFIELDS_PER_FLUSH) { - luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ - cc->tostore = 0; /* no more items pending */ - } -} - - -static void lastlistfield (FuncState *fs, struct ConsControl *cc) { - if (cc->tostore == 0) return; - if (hasmultret(cc->v.k)) { - luaK_setmultret(fs, &cc->v); - luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); - cc->na--; /* do not count last expression (unknown number of elements) */ - } - else { - if (cc->v.k != VVOID) - luaK_exp2nextreg(fs, &cc->v); - luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); - } -} - - -static void listfield (LexState *ls, struct ConsControl *cc) { - expr(ls, &cc->v); - luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); - cc->na++; - cc->tostore++; -} - - -static void constructor (LexState *ls, expdesc *t) { - /* constructor -> ?? */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); - struct ConsControl cc; - cc.na = cc.nh = cc.tostore = 0; - cc.t = t; - init_exp(t, VRELOCABLE, pc); - init_exp(&cc.v, VVOID, 0); /* no value (yet) */ - luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ - checknext(ls, '{'); - do { - lua_assert(cc.v.k == VVOID || cc.tostore > 0); - if (ls->t.token == '}') break; - closelistfield(fs, &cc); - switch(ls->t.token) { - case TK_NAME: { /* may be listfields or recfields */ - luaX_lookahead(ls); - if (ls->lookahead.token != '=') /* expression? */ - listfield(ls, &cc); - else - recfield(ls, &cc); - break; - } - case '[': { /* constructor_item -> recfield */ - recfield(ls, &cc); - break; - } - default: { /* constructor_part -> listfield */ - listfield(ls, &cc); - break; - } - } - } while (testnext(ls, ',') || testnext(ls, ';')); - check_match(ls, '}', '{', line); - lastlistfield(fs, &cc); - SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ - SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ -} - -/* }====================================================================== */ - - - -static void parlist (LexState *ls) { - /* parlist -> [ param { `,' param } ] */ - FuncState *fs = ls->fs; - Proto *f = fs->f; - int nparams = 0; - f->is_vararg = 0; - if (ls->t.token != ')') { /* is `parlist' not empty? */ - do { - switch (ls->t.token) { - case TK_NAME: { /* param -> NAME */ - new_localvar(ls, str_checkname(ls), nparams++); - break; - } - case TK_DOTS: { /* param -> `...' */ - luaX_next(ls); -#if defined(LUA_COMPAT_VARARG) - /* use `arg' as default name */ - new_localvarliteral(ls, "arg", nparams++); - f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; -#endif - f->is_vararg |= VARARG_ISVARARG; - break; - } - default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); - } - } while (!f->is_vararg && testnext(ls, ',')); - } - adjustlocalvars(ls, nparams); - f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); - luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ -} - - -static void body (LexState *ls, expdesc *e, int needself, int line) { - /* body -> `(' parlist `)' chunk END */ - FuncState new_fs; - open_func(ls, &new_fs); - new_fs.f->linedefined = line; - checknext(ls, '('); - if (needself) { - new_localvarliteral(ls, "self", 0); - adjustlocalvars(ls, 1); - } - parlist(ls); - checknext(ls, ')'); - chunk(ls); - new_fs.f->lastlinedefined = ls->linenumber; - check_match(ls, TK_END, TK_FUNCTION, line); - close_func(ls); - pushclosure(ls, &new_fs, e); -} - - -static int explist1 (LexState *ls, expdesc *v) { - /* explist1 -> expr { `,' expr } */ - int n = 1; /* at least one expression */ - expr(ls, v); - while (testnext(ls, ',')) { - luaK_exp2nextreg(ls->fs, v); - expr(ls, v); - n++; - } - return n; -} - - -static void funcargs (LexState *ls, expdesc *f) { - FuncState *fs = ls->fs; - expdesc args; - int base, nparams; - int line = ls->linenumber; - switch (ls->t.token) { - case '(': { /* funcargs -> `(' [ explist1 ] `)' */ - if (line != ls->lastline) - luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); - luaX_next(ls); - if (ls->t.token == ')') /* arg list is empty? */ - args.k = VVOID; - else { - explist1(ls, &args); - luaK_setmultret(fs, &args); - } - check_match(ls, ')', '(', line); - break; - } - case '{': { /* funcargs -> constructor */ - constructor(ls, &args); - break; - } - case TK_STRING: { /* funcargs -> STRING */ - codestring(ls, &args, ls->t.seminfo.ts); - luaX_next(ls); /* must use `seminfo' before `next' */ - break; - } - default: { - luaX_syntaxerror(ls, "function arguments expected"); - return; - } - } - lua_assert(f->k == VNONRELOC); - base = f->u.s.info; /* base register for call */ - if (hasmultret(args.k)) - nparams = LUA_MULTRET; /* open call */ - else { - if (args.k != VVOID) - luaK_exp2nextreg(fs, &args); /* close last argument */ - nparams = fs->freereg - (base+1); - } - init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); - luaK_fixline(fs, line); - fs->freereg = base+1; /* call remove function and arguments and leaves - (unless changed) one result */ -} - - - - -/* -** {====================================================================== -** Expression parsing -** ======================================================================= -*/ - - -static void prefixexp (LexState *ls, expdesc *v) { - /* prefixexp -> NAME | '(' expr ')' */ - switch (ls->t.token) { - case '(': { - int line = ls->linenumber; - luaX_next(ls); - expr(ls, v); - check_match(ls, ')', '(', line); - luaK_dischargevars(ls->fs, v); - return; - } - case TK_NAME: { - singlevar(ls, v); - return; - } - default: { - luaX_syntaxerror(ls, "unexpected symbol"); - return; - } - } -} - - -static void primaryexp (LexState *ls, expdesc *v) { - /* primaryexp -> - prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ - FuncState *fs = ls->fs; - prefixexp(ls, v); - for (;;) { - switch (ls->t.token) { - case '.': { /* field */ - field(ls, v); - break; - } - case '[': { /* `[' exp1 `]' */ - expdesc key; - luaK_exp2anyreg(fs, v); - yindex(ls, &key); - luaK_indexed(fs, v, &key); - break; - } - case ':': { /* `:' NAME funcargs */ - expdesc key; - luaX_next(ls); - checkname(ls, &key); - luaK_self(fs, v, &key); - funcargs(ls, v); - break; - } - case '(': case TK_STRING: case '{': { /* funcargs */ - luaK_exp2nextreg(fs, v); - funcargs(ls, v); - break; - } - default: return; - } - } -} - - -static void simpleexp (LexState *ls, expdesc *v) { - /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | - constructor | FUNCTION body | primaryexp */ - switch (ls->t.token) { - case TK_NUMBER: { - init_exp(v, VKNUM, 0); - v->u.nval = ls->t.seminfo.r; - break; - } - case TK_STRING: { - codestring(ls, v, ls->t.seminfo.ts); - break; - } - case TK_NIL: { - init_exp(v, VNIL, 0); - break; - } - case TK_TRUE: { - init_exp(v, VTRUE, 0); - break; - } - case TK_FALSE: { - init_exp(v, VFALSE, 0); - break; - } - case TK_DOTS: { /* vararg */ - FuncState *fs = ls->fs; - check_condition(ls, fs->f->is_vararg, - "cannot use " LUA_QL("...") " outside a vararg function"); - fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ - init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); - break; - } - case '{': { /* constructor */ - constructor(ls, v); - return; - } - case TK_FUNCTION: { - luaX_next(ls); - body(ls, v, 0, ls->linenumber); - return; - } - default: { - primaryexp(ls, v); - return; - } - } - luaX_next(ls); -} - - -static UnOpr getunopr (int op) { - switch (op) { - case TK_NOT: return OPR_NOT; - case '-': return OPR_MINUS; - case '#': return OPR_LEN; - default: return OPR_NOUNOPR; - } -} - - -static BinOpr getbinopr (int op) { - switch (op) { - case '+': return OPR_ADD; - case '-': return OPR_SUB; - case '*': return OPR_MUL; - case '/': return OPR_DIV; - case '%': return OPR_MOD; - case '^': return OPR_POW; - case TK_CONCAT: return OPR_CONCAT; - case TK_NE: return OPR_NE; - case TK_EQ: return OPR_EQ; - case '<': return OPR_LT; - case TK_LE: return OPR_LE; - case '>': return OPR_GT; - case TK_GE: return OPR_GE; - case TK_AND: return OPR_AND; - case TK_OR: return OPR_OR; - default: return OPR_NOBINOPR; - } -} - - -static const struct { - lu_byte left; /* left priority for each binary operator */ - lu_byte right; /* right priority */ -} priority[] = { /* ORDER OPR */ - {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ - {10, 9}, {5, 4}, /* power and concat (right associative) */ - {3, 3}, {3, 3}, /* equality and inequality */ - {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ - {2, 2}, {1, 1} /* logical (and/or) */ -}; - -#define UNARY_PRIORITY 8 /* priority for unary operators */ - - -/* -** subexpr -> (simpleexp | unop subexpr) { binop subexpr } -** where `binop' is any binary operator with a priority higher than `limit' -*/ -static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { - BinOpr op; - UnOpr uop; - enterlevel(ls); - uop = getunopr(ls->t.token); - if (uop != OPR_NOUNOPR) { - luaX_next(ls); - subexpr(ls, v, UNARY_PRIORITY); - luaK_prefix(ls->fs, uop, v); - } - else simpleexp(ls, v); - /* expand while operators have priorities higher than `limit' */ - op = getbinopr(ls->t.token); - while (op != OPR_NOBINOPR && priority[op].left > limit) { - expdesc v2; - BinOpr nextop; - luaX_next(ls); - luaK_infix(ls->fs, op, v); - /* read sub-expression with higher priority */ - nextop = subexpr(ls, &v2, priority[op].right); - luaK_posfix(ls->fs, op, v, &v2); - op = nextop; - } - leavelevel(ls); - return op; /* return first untreated operator */ -} - - -static void expr (LexState *ls, expdesc *v) { - subexpr(ls, v, 0); -} - -/* }==================================================================== */ - - - -/* -** {====================================================================== -** Rules for Statements -** ======================================================================= -*/ - - -static int block_follow (int token) { - switch (token) { - case TK_ELSE: case TK_ELSEIF: case TK_END: - case TK_UNTIL: case TK_EOS: - return 1; - default: return 0; - } -} - - -static void block (LexState *ls) { - /* block -> chunk */ - FuncState *fs = ls->fs; - BlockCnt bl; - enterblock(fs, &bl, 0); - chunk(ls); - lua_assert(bl.breaklist == NO_JUMP); - leaveblock(fs); -} - - -/* -** structure to chain all variables in the left-hand side of an -** assignment -*/ -struct LHS_assign { - struct LHS_assign *prev; - expdesc v; /* variable (global, local, upvalue, or indexed) */ -}; - - -/* -** check whether, in an assignment to a local variable, the local variable -** is needed in a previous assignment (to a table). If so, save original -** local value in a safe place and use this safe copy in the previous -** assignment. -*/ -static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { - FuncState *fs = ls->fs; - int extra = fs->freereg; /* eventual position to save local variable */ - int conflict = 0; - for (; lh; lh = lh->prev) { - if (lh->v.k == VINDEXED) { - if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ - conflict = 1; - lh->v.u.s.info = extra; /* previous assignment will use safe copy */ - } - if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ - conflict = 1; - lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ - } - } - } - if (conflict) { - luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ - luaK_reserveregs(fs, 1); - } -} - - -static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { - expdesc e; - check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, - "syntax error"); - if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ - struct LHS_assign nv; - nv.prev = lh; - primaryexp(ls, &nv.v); - if (nv.v.k == VLOCAL) - check_conflict(ls, lh, &nv.v); - luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, - "variables in assignment"); - assignment(ls, &nv, nvars+1); - } - else { /* assignment -> `=' explist1 */ - int nexps; - checknext(ls, '='); - nexps = explist1(ls, &e); - if (nexps != nvars) { - adjust_assign(ls, nvars, nexps, &e); - if (nexps > nvars) - ls->fs->freereg -= nexps - nvars; /* remove extra values */ - } - else { - luaK_setoneret(ls->fs, &e); /* close last expression */ - luaK_storevar(ls->fs, &lh->v, &e); - return; /* avoid default */ - } - } - init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ - luaK_storevar(ls->fs, &lh->v, &e); -} - - -static int cond (LexState *ls) { - /* cond -> exp */ - expdesc v; - expr(ls, &v); /* read condition */ - if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ - luaK_goiftrue(ls->fs, &v); - return v.f; -} - - -static void breakstat (LexState *ls) { - FuncState *fs = ls->fs; - BlockCnt *bl = fs->bl; - int upval = 0; - while (bl && !bl->isbreakable) { - upval |= bl->upval; - bl = bl->previous; - } - if (!bl) - luaX_syntaxerror(ls, "no loop to break"); - if (upval) - luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); - luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); -} - - -static void whilestat (LexState *ls, int line) { - /* whilestat -> WHILE cond DO block END */ - FuncState *fs = ls->fs; - int whileinit; - int condexit; - BlockCnt bl; - luaX_next(ls); /* skip WHILE */ - whileinit = luaK_getlabel(fs); - condexit = cond(ls); - enterblock(fs, &bl, 1); - checknext(ls, TK_DO); - block(ls); - luaK_patchlist(fs, luaK_jump(fs), whileinit); - check_match(ls, TK_END, TK_WHILE, line); - leaveblock(fs); - luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ -} - - -static void repeatstat (LexState *ls, int line) { - /* repeatstat -> REPEAT block UNTIL cond */ - int condexit; - FuncState *fs = ls->fs; - int repeat_init = luaK_getlabel(fs); - BlockCnt bl1, bl2; - enterblock(fs, &bl1, 1); /* loop block */ - enterblock(fs, &bl2, 0); /* scope block */ - luaX_next(ls); /* skip REPEAT */ - chunk(ls); - check_match(ls, TK_UNTIL, TK_REPEAT, line); - condexit = cond(ls); /* read condition (inside scope block) */ - if (!bl2.upval) { /* no upvalues? */ - leaveblock(fs); /* finish scope */ - luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ - } - else { /* complete semantics when there are upvalues */ - breakstat(ls); /* if condition then break */ - luaK_patchtohere(ls->fs, condexit); /* else... */ - leaveblock(fs); /* finish scope... */ - luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ - } - leaveblock(fs); /* finish loop */ -} - - -static int exp1 (LexState *ls) { - expdesc e; - int k; - expr(ls, &e); - k = e.k; - luaK_exp2nextreg(ls->fs, &e); - return k; -} - - -static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { - /* forbody -> DO block */ - BlockCnt bl; - FuncState *fs = ls->fs; - int prep, endfor; - adjustlocalvars(ls, 3); /* control variables */ - checknext(ls, TK_DO); - prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); - enterblock(fs, &bl, 0); /* scope for declared variables */ - adjustlocalvars(ls, nvars); - luaK_reserveregs(fs, nvars); - block(ls); - leaveblock(fs); /* end of scope for declared variables */ - luaK_patchtohere(fs, prep); - endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : - luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); - luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ - luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); -} - - -static void fornum (LexState *ls, TString *varname, int line) { - /* fornum -> NAME = exp1,exp1[,exp1] forbody */ - FuncState *fs = ls->fs; - int base = fs->freereg; - new_localvarliteral(ls, "(for index)", 0); - new_localvarliteral(ls, "(for limit)", 1); - new_localvarliteral(ls, "(for step)", 2); - new_localvar(ls, varname, 3); - checknext(ls, '='); - exp1(ls); /* initial value */ - checknext(ls, ','); - exp1(ls); /* limit */ - if (testnext(ls, ',')) - exp1(ls); /* optional step */ - else { /* default step = 1 */ - luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); - luaK_reserveregs(fs, 1); - } - forbody(ls, base, line, 1, 1); -} - - -static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME {,NAME} IN explist1 forbody */ - FuncState *fs = ls->fs; - expdesc e; - int nvars = 0; - int line; - int base = fs->freereg; - /* create control variables */ - new_localvarliteral(ls, "(for generator)", nvars++); - new_localvarliteral(ls, "(for state)", nvars++); - new_localvarliteral(ls, "(for control)", nvars++); - /* create declared variables */ - new_localvar(ls, indexname, nvars++); - while (testnext(ls, ',')) - new_localvar(ls, str_checkname(ls), nvars++); - checknext(ls, TK_IN); - line = ls->linenumber; - adjust_assign(ls, 3, explist1(ls, &e), &e); - luaK_checkstack(fs, 3); /* extra space to call generator */ - forbody(ls, base, line, nvars - 3, 0); -} - - -static void forstat (LexState *ls, int line) { - /* forstat -> FOR (fornum | forlist) END */ - FuncState *fs = ls->fs; - TString *varname; - BlockCnt bl; - enterblock(fs, &bl, 1); /* scope for loop and control variables */ - luaX_next(ls); /* skip `for' */ - varname = str_checkname(ls); /* first variable name */ - switch (ls->t.token) { - case '=': fornum(ls, varname, line); break; - case ',': case TK_IN: forlist(ls, varname); break; - default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); - } - check_match(ls, TK_END, TK_FOR, line); - leaveblock(fs); /* loop scope (`break' jumps to this point) */ -} - - -static int test_then_block (LexState *ls) { - /* test_then_block -> [IF | ELSEIF] cond THEN block */ - int condexit; - luaX_next(ls); /* skip IF or ELSEIF */ - condexit = cond(ls); - checknext(ls, TK_THEN); - block(ls); /* `then' part */ - return condexit; -} - - -static void ifstat (LexState *ls, int line) { - /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ - FuncState *fs = ls->fs; - int flist; - int escapelist = NO_JUMP; - flist = test_then_block(ls); /* IF cond THEN block */ - while (ls->t.token == TK_ELSEIF) { - luaK_concat(fs, &escapelist, luaK_jump(fs)); - luaK_patchtohere(fs, flist); - flist = test_then_block(ls); /* ELSEIF cond THEN block */ - } - if (ls->t.token == TK_ELSE) { - luaK_concat(fs, &escapelist, luaK_jump(fs)); - luaK_patchtohere(fs, flist); - luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ - block(ls); /* `else' part */ - } - else - luaK_concat(fs, &escapelist, flist); - luaK_patchtohere(fs, escapelist); - check_match(ls, TK_END, TK_IF, line); -} - - -static void localfunc (LexState *ls) { - expdesc v, b; - FuncState *fs = ls->fs; - new_localvar(ls, str_checkname(ls), 0); - init_exp(&v, VLOCAL, fs->freereg); - luaK_reserveregs(fs, 1); - adjustlocalvars(ls, 1); - body(ls, &b, 0, ls->linenumber); - luaK_storevar(fs, &v, &b); - /* debug information will only see the variable after this point! */ - getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; -} - - -static void localstat (LexState *ls) { - /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ - int nvars = 0; - int nexps; - expdesc e; - do { - new_localvar(ls, str_checkname(ls), nvars++); - } while (testnext(ls, ',')); - if (testnext(ls, '=')) - nexps = explist1(ls, &e); - else { - e.k = VVOID; - nexps = 0; - } - adjust_assign(ls, nvars, nexps, &e); - adjustlocalvars(ls, nvars); -} - - -static int funcname (LexState *ls, expdesc *v) { - /* funcname -> NAME {field} [`:' NAME] */ - int needself = 0; - singlevar(ls, v); - while (ls->t.token == '.') - field(ls, v); - if (ls->t.token == ':') { - needself = 1; - field(ls, v); - } - return needself; -} - - -static void funcstat (LexState *ls, int line) { - /* funcstat -> FUNCTION funcname body */ - int needself; - expdesc v, b; - luaX_next(ls); /* skip FUNCTION */ - needself = funcname(ls, &v); - body(ls, &b, needself, line); - luaK_storevar(ls->fs, &v, &b); - luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ -} - - -static void exprstat (LexState *ls) { - /* stat -> func | assignment */ - FuncState *fs = ls->fs; - struct LHS_assign v; - primaryexp(ls, &v.v); - if (v.v.k == VCALL) /* stat -> func */ - SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ - else { /* stat -> assignment */ - v.prev = NULL; - assignment(ls, &v, 1); - } -} - - -static void retstat (LexState *ls) { - /* stat -> RETURN explist */ - FuncState *fs = ls->fs; - expdesc e; - int first, nret; /* registers with returned values */ - luaX_next(ls); /* skip RETURN */ - if (block_follow(ls->t.token) || ls->t.token == ';') - first = nret = 0; /* return no values */ - else { - nret = explist1(ls, &e); /* optional return values */ - if (hasmultret(e.k)) { - luaK_setmultret(fs, &e); - if (e.k == VCALL && nret == 1) { /* tail call? */ - SET_OPCODE(getcode(fs,&e), OP_TAILCALL); - lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); - } - first = fs->nactvar; - nret = LUA_MULTRET; /* return all values */ - } - else { - if (nret == 1) /* only one single value? */ - first = luaK_exp2anyreg(fs, &e); - else { - luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ - first = fs->nactvar; /* return all `active' values */ - lua_assert(nret == fs->freereg - first); - } - } - } - luaK_ret(fs, first, nret); -} - - -static int statement (LexState *ls) { - int line = ls->linenumber; /* may be needed for error messages */ - switch (ls->t.token) { - case TK_IF: { /* stat -> ifstat */ - ifstat(ls, line); - return 0; - } - case TK_WHILE: { /* stat -> whilestat */ - whilestat(ls, line); - return 0; - } - case TK_DO: { /* stat -> DO block END */ - luaX_next(ls); /* skip DO */ - block(ls); - check_match(ls, TK_END, TK_DO, line); - return 0; - } - case TK_FOR: { /* stat -> forstat */ - forstat(ls, line); - return 0; - } - case TK_REPEAT: { /* stat -> repeatstat */ - repeatstat(ls, line); - return 0; - } - case TK_FUNCTION: { - funcstat(ls, line); /* stat -> funcstat */ - return 0; - } - case TK_LOCAL: { /* stat -> localstat */ - luaX_next(ls); /* skip LOCAL */ - if (testnext(ls, TK_FUNCTION)) /* local function? */ - localfunc(ls); - else - localstat(ls); - return 0; - } - case TK_RETURN: { /* stat -> retstat */ - retstat(ls); - return 1; /* must be last statement */ - } - case TK_BREAK: { /* stat -> breakstat */ - luaX_next(ls); /* skip BREAK */ - breakstat(ls); - return 1; /* must be last statement */ - } - default: { - exprstat(ls); - return 0; /* to avoid warnings */ - } - } -} - - -static void chunk (LexState *ls) { - /* chunk -> { stat [`;'] } */ - int islast = 0; - enterlevel(ls); - while (!islast && !block_follow(ls->t.token)) { - islast = statement(ls); - testnext(ls, ';'); - lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && - ls->fs->freereg >= ls->fs->nactvar); - ls->fs->freereg = ls->fs->nactvar; /* free registers */ - } - leavelevel(ls); -} - -/* }====================================================================== */ diff --git a/script/lua/lparser.h b/script/lua/lparser.h deleted file mode 100644 index 18836afd1..000000000 --- a/script/lua/lparser.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ -** Lua Parser -** See Copyright Notice in lua.h -*/ - -#ifndef lparser_h -#define lparser_h - -#include "llimits.h" -#include "lobject.h" -#include "lzio.h" - - -/* -** Expression descriptor -*/ - -typedef enum { - VVOID, /* no value */ - VNIL, - VTRUE, - VFALSE, - VK, /* info = index of constant in `k' */ - VKNUM, /* nval = numerical value */ - VLOCAL, /* info = local register */ - VUPVAL, /* info = index of upvalue in `upvalues' */ - VGLOBAL, /* info = index of table; aux = index of global name in `k' */ - VINDEXED, /* info = table register; aux = index register (or `k') */ - VJMP, /* info = instruction pc */ - VRELOCABLE, /* info = instruction pc */ - VNONRELOC, /* info = result register */ - VCALL, /* info = instruction pc */ - VVARARG /* info = instruction pc */ -} expkind; - -typedef struct expdesc { - expkind k; - union { - struct { int info, aux; } s; - lua_Number nval; - } u; - int t; /* patch list of `exit when true' */ - int f; /* patch list of `exit when false' */ -} expdesc; - - -typedef struct upvaldesc { - lu_byte k; - lu_byte info; -} upvaldesc; - - -struct BlockCnt; /* defined in lparser.c */ - - -/* state needed to generate code for a given function */ -typedef struct FuncState { - Proto *f; /* current function header */ - Table *h; /* table to find (and reuse) elements in `k' */ - struct FuncState *prev; /* enclosing function */ - struct LexState *ls; /* lexical state */ - struct lua_State *L; /* copy of the Lua state */ - struct BlockCnt *bl; /* chain of current blocks */ - int pc; /* next position to code (equivalent to `ncode') */ - int lasttarget; /* `pc' of last `jump target' */ - int jpc; /* list of pending jumps to `pc' */ - int freereg; /* first free register */ - int nk; /* number of elements in `k' */ - int np; /* number of elements in `p' */ - short nlocvars; /* number of elements in `locvars' */ - lu_byte nactvar; /* number of active local variables */ - upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ - unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ -} FuncState; - - -LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - const char *name); - - -#endif diff --git a/script/lua/lstate.c b/script/lua/lstate.c deleted file mode 100644 index 0c1b97f19..000000000 --- a/script/lua/lstate.c +++ /dev/null @@ -1,213 +0,0 @@ -/* -** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ -** Global State -** See Copyright Notice in lua.h -*/ - - -#include - -#define lstate_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) -#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) -#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) - - -/* -** Main thread combines a thread state and the global state -*/ -typedef struct LG { - lua_State l; - global_State g; -} LG; - - - -static void stack_init (lua_State *L1, lua_State *L) { - /* initialize CallInfo array */ - L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); - L1->ci = L1->base_ci; - L1->size_ci = BASIC_CI_SIZE; - L1->end_ci = L1->base_ci + L1->size_ci - 1; - /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); - L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; - L1->top = L1->stack; - L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; - /* initialize first ci */ - L1->ci->func = L1->top; - setnilvalue(L1->top++); /* `function' entry for this `ci' */ - L1->base = L1->ci->base = L1->top; - L1->ci->top = L1->top + LUA_MINSTACK; -} - - -static void freestack (lua_State *L, lua_State *L1) { - luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); - luaM_freearray(L, L1->stack, L1->stacksize, TValue); -} - - -/* -** open parts that may cause memory-allocation errors -*/ -static void f_luaopen (lua_State *L, void *ud) { - global_State *g = G(L); - UNUSED(ud); - stack_init(L, L); /* init stack */ - sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ - sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ - luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ - luaT_init(L); - luaX_init(L); - luaS_fix(luaS_newliteral(L, MEMERRMSG)); - g->GCthreshold = 4*g->totalbytes; -} - - -static void preinit_state (lua_State *L, global_State *g) { - G(L) = g; - L->stack = NULL; - L->stacksize = 0; - L->errorJmp = NULL; - L->hook = NULL; - L->hookmask = 0; - L->basehookcount = 0; - L->allowhook = 1; - resethookcount(L); - L->openupval = NULL; - L->size_ci = 0; - L->nCcalls = L->baseCcalls = 0; - L->status = 0; - L->base_ci = L->ci = NULL; - L->savedpc = NULL; - L->errfunc = 0; - setnilvalue(gt(L)); -} - - -static void close_state (lua_State *L) { - global_State *g = G(L); - luaF_close(L, L->stack); /* close all upvalues for this thread */ - luaC_freeall(L); /* collect all objects */ - lua_assert(g->rootgc == obj2gco(L)); - lua_assert(g->strt.nuse == 0); - luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); - luaZ_freebuffer(L, &g->buff); - freestack(L, L); - lua_assert(g->totalbytes == sizeof(LG)); - (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); -} - - -lua_State *luaE_newthread (lua_State *L) { - lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); - luaC_link(L, obj2gco(L1), LUA_TTHREAD); - preinit_state(L1, G(L)); - stack_init(L1, L); /* init stack */ - setobj2n(L, gt(L1), gt(L)); /* share table of globals */ - L1->hookmask = L->hookmask; - L1->basehookcount = L->basehookcount; - L1->hook = L->hook; - resethookcount(L1); - lua_assert(iswhite(obj2gco(L1))); - return L1; -} - - -void luaE_freethread (lua_State *L, lua_State *L1) { - luaF_close(L1, L1->stack); /* close all upvalues for this thread */ - lua_assert(L1->openupval == NULL); - luai_userstatefree(L1); - freestack(L, L1); - luaM_freemem(L, fromstate(L1), state_size(lua_State)); -} - - -LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { - int i; - lua_State *L; - global_State *g; - void *l = (*f)(ud, NULL, 0, state_size(LG)); - if (l == NULL) return NULL; - L = tostate(l); - g = &((LG *)L)->g; - L->next = NULL; - L->tt = LUA_TTHREAD; - g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); - L->marked = luaC_white(g); - set2bits(L->marked, FIXEDBIT, SFIXEDBIT); - preinit_state(L, g); - g->frealloc = f; - g->ud = ud; - g->mainthread = L; - g->uvhead.u.l.prev = &g->uvhead; - g->uvhead.u.l.next = &g->uvhead; - g->GCthreshold = 0; /* mark it as unfinished state */ - g->strt.size = 0; - g->strt.nuse = 0; - g->strt.hash = NULL; - setnilvalue(registry(L)); - luaZ_initbuffer(L, &g->buff); - g->panic = NULL; - g->gcstate = GCSpause; - g->rootgc = obj2gco(L); - g->sweepstrgc = 0; - g->sweepgc = &g->rootgc; - g->gray = NULL; - g->grayagain = NULL; - g->weak = NULL; - g->tmudata = NULL; - g->totalbytes = sizeof(LG); - g->gcpause = LUAI_GCPAUSE; - g->gcstepmul = LUAI_GCMUL; - g->gcdept = 0; - for (i=0; imt[i] = NULL; - if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { - /* memory allocation error: free partial state */ - close_state(L); - L = NULL; - } - else - luai_userstateopen(L); - return L; -} - - -static void callallgcTM (lua_State *L, void *ud) { - UNUSED(ud); - luaC_callGCTM(L); /* call GC metamethods for all udata */ -} - - -LUA_API void lua_close (lua_State *L) { - L = G(L)->mainthread; /* only the main thread can be closed */ - lua_lock(L); - luaF_close(L, L->stack); /* close all upvalues for this thread */ - luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ - L->errfunc = 0; /* no error function during GC metamethods */ - do { /* repeat until no more errors */ - L->ci = L->base_ci; - L->base = L->top = L->ci->base; - L->nCcalls = L->baseCcalls = 0; - } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); - lua_assert(G(L)->tmudata == NULL); - luai_userstateclose(L); - close_state(L); -} diff --git a/script/lua/lstate.h b/script/lua/lstate.h deleted file mode 100644 index 3bc575b6b..000000000 --- a/script/lua/lstate.h +++ /dev/null @@ -1,169 +0,0 @@ -/* -** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ -** Global State -** See Copyright Notice in lua.h -*/ - -#ifndef lstate_h -#define lstate_h - -#include "lua.h" - -#include "lobject.h" -#include "ltm.h" -#include "lzio.h" - - - -struct lua_longjmp; /* defined in ldo.c */ - - -/* table of globals */ -#define gt(L) (&L->l_gt) - -/* registry */ -#define registry(L) (&G(L)->l_registry) - - -/* extra stack space to handle TM calls and some other extras */ -#define EXTRA_STACK 5 - - -#define BASIC_CI_SIZE 8 - -#define BASIC_STACK_SIZE (2*LUA_MINSTACK) - - - -typedef struct stringtable { - GCObject **hash; - lu_int32 nuse; /* number of elements */ - int size; -} stringtable; - - -/* -** informations about a call -*/ -typedef struct CallInfo { - StkId base; /* base for this function */ - StkId func; /* function index in the stack */ - StkId top; /* top for this function */ - const Instruction *savedpc; - int nresults; /* expected number of results from this function */ - int tailcalls; /* number of tail calls lost under this entry */ -} CallInfo; - - - -#define curr_func(L) (clvalue(L->ci->func)) -#define ci_func(ci) (clvalue((ci)->func)) -#define f_isLua(ci) (!ci_func(ci)->c.isC) -#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) - - -/* -** `global state', shared by all threads of this state -*/ -typedef struct global_State { - stringtable strt; /* hash table for strings */ - lua_Alloc frealloc; /* function to reallocate memory */ - void *ud; /* auxiliary data to `frealloc' */ - lu_byte currentwhite; - lu_byte gcstate; /* state of garbage collector */ - int sweepstrgc; /* position of sweep in `strt' */ - GCObject *rootgc; /* list of all collectable objects */ - GCObject **sweepgc; /* position of sweep in `rootgc' */ - GCObject *gray; /* list of gray objects */ - GCObject *grayagain; /* list of objects to be traversed atomically */ - GCObject *weak; /* list of weak tables (to be cleared) */ - GCObject *tmudata; /* last element of list of userdata to be GC */ - Mbuffer buff; /* temporary buffer for string concatentation */ - lu_mem GCthreshold; - lu_mem totalbytes; /* number of bytes currently allocated */ - lu_mem estimate; /* an estimate of number of bytes actually in use */ - lu_mem gcdept; /* how much GC is `behind schedule' */ - int gcpause; /* size of pause between successive GCs */ - int gcstepmul; /* GC `granularity' */ - lua_CFunction panic; /* to be called in unprotected errors */ - TValue l_registry; - struct lua_State *mainthread; - UpVal uvhead; /* head of double-linked list of all open upvalues */ - struct Table *mt[NUM_TAGS]; /* metatables for basic types */ - TString *tmname[TM_N]; /* array with tag-method names */ -} global_State; - - -/* -** `per thread' state -*/ -struct lua_State { - CommonHeader; - lu_byte status; - StkId top; /* first free slot in the stack */ - StkId base; /* base of current function */ - global_State *l_G; - CallInfo *ci; /* call info for current function */ - const Instruction *savedpc; /* `savedpc' of current function */ - StkId stack_last; /* last free slot in the stack */ - StkId stack; /* stack base */ - CallInfo *end_ci; /* points after end of ci array*/ - CallInfo *base_ci; /* array of CallInfo's */ - int stacksize; - int size_ci; /* size of array `base_ci' */ - unsigned short nCcalls; /* number of nested C calls */ - unsigned short baseCcalls; /* nested C calls when resuming coroutine */ - lu_byte hookmask; - lu_byte allowhook; - int basehookcount; - int hookcount; - lua_Hook hook; - TValue l_gt; /* table of globals */ - TValue env; /* temporary place for environments */ - GCObject *openupval; /* list of open upvalues in this stack */ - GCObject *gclist; - struct lua_longjmp *errorJmp; /* current error recover point */ - ptrdiff_t errfunc; /* current error handling function (stack index) */ -}; - - -#define G(L) (L->l_G) - - -/* -** Union of all collectable objects -*/ -union GCObject { - GCheader gch; - union TString ts; - union Udata u; - union Closure cl; - struct Table h; - struct Proto p; - struct UpVal uv; - struct lua_State th; /* thread */ -}; - - -/* macros to convert a GCObject into a specific value */ -#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) -#define gco2ts(o) (&rawgco2ts(o)->tsv) -#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) -#define gco2u(o) (&rawgco2u(o)->uv) -#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) -#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) -#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) -#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -#define ngcotouv(o) \ - check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) - -/* macro to convert any Lua object into a GCObject */ -#define obj2gco(v) (cast(GCObject *, (v))) - - -LUAI_FUNC lua_State *luaE_newthread (lua_State *L); -LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); - -#endif - diff --git a/script/lua/lstring.c b/script/lua/lstring.c deleted file mode 100644 index bfdf1908a..000000000 --- a/script/lua/lstring.c +++ /dev/null @@ -1,112 +0,0 @@ -/* -** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ -** String table (keeps all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#endif - -#define lstring_c -#define LUA_CORE - -#include "lua.h" - -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" - - - -void luaS_resize (lua_State *L, int newsize) { - GCObject **newhash; - stringtable *tb; - int i; - if (G(L)->gcstate == GCSsweepstring) - return; /* cannot resize during GC traverse */ - newhash = luaM_newvector(L, newsize, GCObject *); - tb = &G(L)->strt; - for (i=0; isize; i++) { - GCObject *p = tb->hash[i]; - while (p) { /* for each node in the list */ - GCObject *next = p->gch.next; /* save next */ - unsigned int h = gco2ts(p)->hash; - int h1 = lmod(h, newsize); /* new position */ - lua_assert(cast_int(h%newsize) == lmod(h, newsize)); - p->gch.next = newhash[h1]; /* chain it */ - newhash[h1] = p; - p = next; - } - } - luaM_freearray(L, tb->hash, tb->size, TString *); - tb->size = newsize; - tb->hash = newhash; -} - - -static TString *newlstr (lua_State *L, const char *str, size_t l, - unsigned int h) { - TString *ts; - stringtable *tb; - if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) - luaM_toobig(L); - ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); - ts->tsv.len = l; - ts->tsv.hash = h; - ts->tsv.marked = luaC_white(G(L)); - ts->tsv.tt = LUA_TSTRING; - ts->tsv.reserved = 0; - memcpy(ts+1, str, l*sizeof(char)); - ((char *)(ts+1))[l] = '\0'; /* ending 0 */ - tb = &G(L)->strt; - h = lmod(h, tb->size); - ts->tsv.next = tb->hash[h]; /* chain new entry */ - tb->hash[h] = obj2gco(ts); - tb->nuse++; - if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) - luaS_resize(L, tb->size*2); /* too crowded */ - return ts; -} - - -TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { - GCObject *o; - unsigned int h = cast(unsigned int, l); /* seed */ - size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ - size_t l1; - for (l1=l; l1>=step; l1-=step) /* compute hash */ - h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); - for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; - o != NULL; - o = o->gch.next) { - TString *ts = rawgco2ts(o); - if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { - /* string may be dead */ - if (isdead(G(L), o)) changewhite(o); - return ts; - } - } - return newlstr(L, str, l, h); /* not found */ -} - - -Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { - Udata *u; - if (s > MAX_SIZET - sizeof(Udata)) - luaM_toobig(L); - u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); - u->uv.marked = luaC_white(G(L)); /* is not finalized */ - u->uv.tt = LUA_TUSERDATA; - u->uv.len = s; - u->uv.metatable = NULL; - u->uv.env = e; - /* chain it on udata list (after main thread) */ - u->uv.next = G(L)->mainthread->next; - G(L)->mainthread->next = obj2gco(u); - return u; -} - diff --git a/script/lua/lstring.h b/script/lua/lstring.h deleted file mode 100644 index 73a2ff8b3..000000000 --- a/script/lua/lstring.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ -** String table (keep all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - -#ifndef lstring_h -#define lstring_h - - -#include "lgc.h" -#include "lobject.h" -#include "lstate.h" - - -#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) - -#define sizeudata(u) (sizeof(union Udata)+(u)->len) - -#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) -#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ - (sizeof(s)/sizeof(char))-1)) - -#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) - -LUAI_FUNC void luaS_resize (lua_State *L, int newsize); -LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); -LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); - - -#endif diff --git a/script/lua/lstrlib.c b/script/lua/lstrlib.c deleted file mode 100644 index a9abb493e..000000000 --- a/script/lua/lstrlib.c +++ /dev/null @@ -1,870 +0,0 @@ -/* -** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ -** Standard library for string operations and pattern-matching -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#include -#include -#include -#include -#endif - -#define lstrlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* macro to `unsign' a character */ -#define uchar(c) ((unsigned char)(c)) - - - -static int str_len (lua_State *L) { - size_t l; - luaL_checklstring(L, 1, &l); - lua_pushinteger(L, l); - return 1; -} - - -static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { - /* relative string position: negative means back from end */ - if (pos < 0) pos += (ptrdiff_t)len + 1; - return (pos >= 0) ? pos : 0; -} - - -static int str_sub (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); - ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); - if (start < 1) start = 1; - if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; - if (start <= end) - lua_pushlstring(L, s+start-1, end-start+1); - else lua_pushliteral(L, ""); - return 1; -} - - -static int str_reverse (lua_State *L) { - size_t l; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - luaL_buffinit(L, &b); - while (l--) luaL_addchar(&b, s[l]); - luaL_pushresult(&b); - return 1; -} - - -static int str_lower (lua_State *L) { - size_t l; - size_t i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - luaL_buffinit(L, &b); - for (i=0; i 0) - luaL_addlstring(&b, s, l); - luaL_pushresult(&b); - return 1; -} - - -static int str_byte (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); - ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); - int n, i; - if (posi <= 0) posi = 1; - if ((size_t)pose > l) pose = l; - if (posi > pose) return 0; /* empty interval; return no values */ - n = (int)(pose - posi + 1); - if (posi + n <= pose) /* overflow? */ - luaL_error(L, "string slice too long"); - luaL_checkstack(L, n, "string slice too long"); - for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) - return luaL_error(ms->L, "invalid capture index"); - return l; -} - - -static int capture_to_close (MatchState *ms) { - int level = ms->level; - for (level--; level>=0; level--) - if (ms->capture[level].len == CAP_UNFINISHED) return level; - return luaL_error(ms->L, "invalid pattern capture"); -} - - -static const char *classend (MatchState *ms, const char *p) { - switch (*p++) { - case L_ESC: { - if (*p == '\0') - luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); - return p+1; - } - case '[': { - if (*p == '^') p++; - do { /* look for a `]' */ - if (*p == '\0') - luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); - if (*(p++) == L_ESC && *p != '\0') - p++; /* skip escapes (e.g. `%]') */ - } while (*p != ']'); - return p+1; - } - default: { - return p; - } - } -} - - -static int match_class (int c, int cl) { - int res; - switch (tolower(cl)) { - case 'a' : res = isalpha(c); break; - case 'c' : res = iscntrl(c); break; - case 'd' : res = isdigit(c); break; - case 'l' : res = islower(c); break; - case 'p' : res = ispunct(c); break; - case 's' : res = isspace(c); break; - case 'u' : res = isupper(c); break; - case 'w' : res = isalnum(c); break; - case 'x' : res = isxdigit(c); break; - case 'z' : res = (c == 0); break; - default: return (cl == c); - } - return (islower(cl) ? res : !res); -} - - -static int matchbracketclass (int c, const char *p, const char *ec) { - int sig = 1; - if (*(p+1) == '^') { - sig = 0; - p++; /* skip the `^' */ - } - while (++p < ec) { - if (*p == L_ESC) { - p++; - if (match_class(c, uchar(*p))) - return sig; - } - else if ((*(p+1) == '-') && (p+2 < ec)) { - p+=2; - if (uchar(*(p-2)) <= c && c <= uchar(*p)) - return sig; - } - else if (uchar(*p) == c) return sig; - } - return !sig; -} - - -static int singlematch (int c, const char *p, const char *ep) { - switch (*p) { - case '.': return 1; /* matches any char */ - case L_ESC: return match_class(c, uchar(*(p+1))); - case '[': return matchbracketclass(c, p, ep-1); - default: return (uchar(*p) == c); - } -} - - -static const char *match (MatchState *ms, const char *s, const char *p); - - -static const char *matchbalance (MatchState *ms, const char *s, - const char *p) { - if (*p == 0 || *(p+1) == 0) - luaL_error(ms->L, "unbalanced pattern"); - if (*s != *p) return NULL; - else { - int b = *p; - int e = *(p+1); - int cont = 1; - while (++s < ms->src_end) { - if (*s == e) { - if (--cont == 0) return s+1; - } - else if (*s == b) cont++; - } - } - return NULL; /* string ends out of balance */ -} - - -static const char *max_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - ptrdiff_t i = 0; /* counts maximum expand for item */ - while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) - i++; - /* keeps trying to match with the maximum repetitions */ - while (i>=0) { - const char *res = match(ms, (s+i), ep+1); - if (res) return res; - i--; /* else didn't match; reduce 1 repetition to try again */ - } - return NULL; -} - - -static const char *min_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - for (;;) { - const char *res = match(ms, s, ep+1); - if (res != NULL) - return res; - else if (ssrc_end && singlematch(uchar(*s), p, ep)) - s++; /* try with one more repetition */ - else return NULL; - } -} - - -static const char *start_capture (MatchState *ms, const char *s, - const char *p, int what) { - const char *res; - int level = ms->level; - if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); - ms->capture[level].init = s; - ms->capture[level].len = what; - ms->level = level+1; - if ((res=match(ms, s, p)) == NULL) /* match failed? */ - ms->level--; /* undo capture */ - return res; -} - - -static const char *end_capture (MatchState *ms, const char *s, - const char *p) { - int l = capture_to_close(ms); - const char *res; - ms->capture[l].len = s - ms->capture[l].init; /* close capture */ - if ((res = match(ms, s, p)) == NULL) /* match failed? */ - ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ - return res; -} - - -static const char *match_capture (MatchState *ms, const char *s, int l) { - size_t len; - l = check_capture(ms, l); - len = ms->capture[l].len; - if ((size_t)(ms->src_end-s) >= len && - memcmp(ms->capture[l].init, s, len) == 0) - return s+len; - else return NULL; -} - - -static const char *match (MatchState *ms, const char *s, const char *p) { - init: /* using goto's to optimize tail recursion */ - switch (*p) { - case '(': { /* start capture */ - if (*(p+1) == ')') /* position capture? */ - return start_capture(ms, s, p+2, CAP_POSITION); - else - return start_capture(ms, s, p+1, CAP_UNFINISHED); - } - case ')': { /* end capture */ - return end_capture(ms, s, p+1); - } - case L_ESC: { - switch (*(p+1)) { - case 'b': { /* balanced string? */ - s = matchbalance(ms, s, p+2); - if (s == NULL) return NULL; - p+=4; goto init; /* else return match(ms, s, p+4); */ - } - case 'f': { /* frontier? */ - const char *ep; char previous; - p += 2; - if (*p != '[') - luaL_error(ms->L, "missing " LUA_QL("[") " after " - LUA_QL("%%f") " in pattern"); - ep = classend(ms, p); /* points to what is next */ - previous = (s == ms->src_init) ? '\0' : *(s-1); - if (matchbracketclass(uchar(previous), p, ep-1) || - !matchbracketclass(uchar(*s), p, ep-1)) return NULL; - p=ep; goto init; /* else return match(ms, s, ep); */ - } - default: { - if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ - s = match_capture(ms, s, uchar(*(p+1))); - if (s == NULL) return NULL; - p+=2; goto init; /* else return match(ms, s, p+2) */ - } - goto dflt; /* case default */ - } - } - } - case '\0': { /* end of pattern */ - return s; /* match succeeded */ - } - case '$': { - if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ - return (s == ms->src_end) ? s : NULL; /* check end of string */ - else goto dflt; - } - default: dflt: { /* it is a pattern item */ - const char *ep = classend(ms, p); /* points to what is next */ - int m = ssrc_end && singlematch(uchar(*s), p, ep); - switch (*ep) { - case '?': { /* optional */ - const char *res; - if (m && ((res=match(ms, s+1, ep+1)) != NULL)) - return res; - p=ep+1; goto init; /* else return match(ms, s, ep+1); */ - } - case '*': { /* 0 or more repetitions */ - return max_expand(ms, s, p, ep); - } - case '+': { /* 1 or more repetitions */ - return (m ? max_expand(ms, s+1, p, ep) : NULL); - } - case '-': { /* 0 or more repetitions (minimum) */ - return min_expand(ms, s, p, ep); - } - default: { - if (!m) return NULL; - s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ - } - } - } - } -} - - - -static const char *lmemfind (const char *s1, size_t l1, - const char *s2, size_t l2) { - if (l2 == 0) return s1; /* empty strings are everywhere */ - else if (l2 > l1) return NULL; /* avoids a negative `l1' */ - else { - const char *init; /* to search for a `*s2' inside `s1' */ - l2--; /* 1st char will be checked by `memchr' */ - l1 = l1-l2; /* `s2' cannot be found after that */ - while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { - init++; /* 1st char is already checked */ - if (memcmp(init, s2+1, l2) == 0) - return init-1; - else { /* correct `l1' and `s1' to try again */ - l1 -= init-s1; - s1 = init; - } - } - return NULL; /* not found */ - } -} - - -static void push_onecapture (MatchState *ms, int i, const char *s, - const char *e) { - if (i >= ms->level) { - if (i == 0) /* ms->level == 0, too */ - lua_pushlstring(ms->L, s, e - s); /* add whole match */ - else - luaL_error(ms->L, "invalid capture index"); - } - else { - ptrdiff_t l = ms->capture[i].len; - if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); - if (l == CAP_POSITION) - lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); - else - lua_pushlstring(ms->L, ms->capture[i].init, l); - } -} - - -static int push_captures (MatchState *ms, const char *s, const char *e) { - int i; - int nlevels = (ms->level == 0 && s) ? 1 : ms->level; - luaL_checkstack(ms->L, nlevels, "too many captures"); - for (i = 0; i < nlevels; i++) - push_onecapture(ms, i, s, e); - return nlevels; /* number of strings pushed */ -} - - -static int str_find_aux (lua_State *L, int find) { - size_t l1, l2; - const char *s = luaL_checklstring(L, 1, &l1); - const char *p = luaL_checklstring(L, 2, &l2); - ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; - if (init < 0) init = 0; - else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; - if (find && (lua_toboolean(L, 4) || /* explicit request? */ - strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ - /* do a plain search */ - const char *s2 = lmemfind(s+init, l1-init, p, l2); - if (s2) { - lua_pushinteger(L, s2-s+1); - lua_pushinteger(L, s2-s+l2); - return 2; - } - } - else { - MatchState ms; - int anchor = (*p == '^') ? (p++, 1) : 0; - const char *s1=s+init; - ms.L = L; - ms.src_init = s; - ms.src_end = s+l1; - do { - const char *res; - ms.level = 0; - if ((res=match(&ms, s1, p)) != NULL) { - if (find) { - lua_pushinteger(L, s1-s+1); /* start */ - lua_pushinteger(L, res-s); /* end */ - return push_captures(&ms, NULL, 0) + 2; - } - else - return push_captures(&ms, s1, res); - } - } while (s1++ < ms.src_end && !anchor); - } - lua_pushnil(L); /* not found */ - return 1; -} - - -static int str_find (lua_State *L) { - return str_find_aux(L, 1); -} - - -static int str_match (lua_State *L) { - return str_find_aux(L, 0); -} - - -static int gmatch_aux (lua_State *L) { - MatchState ms; - size_t ls; - const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); - const char *p = lua_tostring(L, lua_upvalueindex(2)); - const char *src; - ms.L = L; - ms.src_init = s; - ms.src_end = s+ls; - for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); - src <= ms.src_end; - src++) { - const char *e; - ms.level = 0; - if ((e = match(&ms, src, p)) != NULL) { - lua_Integer newstart = e-s; - if (e == src) newstart++; /* empty match? go at least one position */ - lua_pushinteger(L, newstart); - lua_replace(L, lua_upvalueindex(3)); - return push_captures(&ms, src, e); - } - } - return 0; /* not found */ -} - - -static int gmatch (lua_State *L) { - luaL_checkstring(L, 1); - luaL_checkstring(L, 2); - lua_settop(L, 2); - lua_pushinteger(L, 0); - lua_pushcclosure(L, gmatch_aux, 3); - return 1; -} - - -static int gfind_nodef (lua_State *L) { - return luaL_error(L, LUA_QL("string.gfind") " was renamed to " - LUA_QL("string.gmatch")); -} - - -static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e) { - size_t l, i; - const char *news = lua_tolstring(ms->L, 3, &l); - for (i = 0; i < l; i++) { - if (news[i] != L_ESC) - luaL_addchar(b, news[i]); - else { - i++; /* skip ESC */ - if (!isdigit(uchar(news[i]))) - luaL_addchar(b, news[i]); - else if (news[i] == '0') - luaL_addlstring(b, s, e - s); - else { - push_onecapture(ms, news[i] - '1', s, e); - luaL_addvalue(b); /* add capture to accumulated result */ - } - } - } -} - - -static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e) { - lua_State *L = ms->L; - switch (lua_type(L, 3)) { - case LUA_TNUMBER: - case LUA_TSTRING: { - add_s(ms, b, s, e); - return; - } - case LUA_TFUNCTION: { - int n; - lua_pushvalue(L, 3); - n = push_captures(ms, s, e); - lua_call(L, n, 1); - break; - } - case LUA_TTABLE: { - push_onecapture(ms, 0, s, e); - lua_gettable(L, 3); - break; - } - } - if (!lua_toboolean(L, -1)) { /* nil or false? */ - lua_pop(L, 1); - lua_pushlstring(L, s, e - s); /* keep original text */ - } - else if (!lua_isstring(L, -1)) - luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); - luaL_addvalue(b); /* add result to accumulator */ -} - - -static int str_gsub (lua_State *L) { - size_t srcl; - const char *src = luaL_checklstring(L, 1, &srcl); - const char *p = luaL_checkstring(L, 2); - int tr = lua_type(L, 3); - int max_s = luaL_optint(L, 4, srcl+1); - int anchor = (*p == '^') ? (p++, 1) : 0; - int n = 0; - MatchState ms; - luaL_Buffer b; - luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || - tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, - "string/function/table expected"); - luaL_buffinit(L, &b); - ms.L = L; - ms.src_init = src; - ms.src_end = src+srcl; - while (n < max_s) { - const char *e; - ms.level = 0; - e = match(&ms, src, p); - if (e) { - n++; - add_value(&ms, &b, src, e); - } - if (e && e>src) /* non empty match? */ - src = e; /* skip it */ - else if (src < ms.src_end) - luaL_addchar(&b, *src++); - else break; - if (anchor) break; - } - luaL_addlstring(&b, src, ms.src_end-src); - luaL_pushresult(&b); - lua_pushinteger(L, n); /* number of substitutions */ - return 2; -} - -/* }====================================================== */ - - -/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -#define MAX_ITEM 512 -/* valid flags in a format specification */ -#define FLAGS "-+ #0" -/* -** maximum size of each format specification (such as '%-099.99d') -** (+10 accounts for %99.99x plus margin of error) -*/ -#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) - - -static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - luaL_addchar(b, '"'); - while (l--) { - switch (*s) { - case '"': case '\\': case '\n': { - luaL_addchar(b, '\\'); - luaL_addchar(b, *s); - break; - } - case '\r': { - luaL_addlstring(b, "\\r", 2); - break; - } - case '\0': { - luaL_addlstring(b, "\\000", 4); - break; - } - default: { - luaL_addchar(b, *s); - break; - } - } - s++; - } - luaL_addchar(b, '"'); -} - -static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { - const char *p = strfrmt; - while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ - if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) - luaL_error(L, "invalid format (repeated flags)"); - if (isdigit(uchar(*p))) p++; /* skip width */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - if (*p == '.') { - p++; - if (isdigit(uchar(*p))) p++; /* skip precision */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - } - if (isdigit(uchar(*p))) - luaL_error(L, "invalid format (width or precision too long)"); - *(form++) = '%'; - strncpy(form, strfrmt, p - strfrmt + 1); - form += p - strfrmt + 1; - *form = '\0'; - return p; -} - - -static void addintlen (char *form) { - size_t l = strlen(form); - char spec = form[l - 1]; - strcpy(form + l - 1, LUA_INTFRMLEN); - form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; - form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; -} - - -static int str_format (lua_State *L) { - int arg = 1; - size_t sfl; - const char *strfrmt = luaL_checklstring(L, arg, &sfl); - const char *strfrmt_end = strfrmt+sfl; - luaL_Buffer b; - luaL_buffinit(L, &b); - while (strfrmt < strfrmt_end) { - if (*strfrmt != L_ESC) - luaL_addchar(&b, *strfrmt++); - else if (*++strfrmt == L_ESC) - luaL_addchar(&b, *strfrmt++); /* %% */ - else { /* format item */ - char form[MAX_FORMAT]; /* to store the format (`%...') */ - char buff[MAX_ITEM]; /* to store the formatted item */ - arg++; - strfrmt = scanformat(L, strfrmt, form); - switch (*strfrmt++) { - case 'c': { - sprintf(buff, form, (int)luaL_checknumber(L, arg)); - break; - } - case 'd': case 'i': { - addintlen(form); - sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); - break; - } - case 'o': case 'u': case 'x': case 'X': { - addintlen(form); - sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); - break; - } - case 'e': case 'E': case 'f': - case 'g': case 'G': { - sprintf(buff, form, (double)luaL_checknumber(L, arg)); - break; - } - case 'q': { - addquoted(L, &b, arg); - continue; /* skip the 'addsize' at the end */ - } - case 's': { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - if (!strchr(form, '.') && l >= 100) { - /* no precision and string is too long to be formatted; - keep original string */ - lua_pushvalue(L, arg); - luaL_addvalue(&b); - continue; /* skip the `addsize' at the end */ - } - else { - sprintf(buff, form, s); - break; - } - } - default: { /* also treat cases `pnLlh' */ - return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " - LUA_QL("format"), *(strfrmt - 1)); - } - } - luaL_addlstring(&b, buff, strlen(buff)); - } - } - luaL_pushresult(&b); - return 1; -} - - -static const luaL_Reg strlib[] = { - {"byte", str_byte}, - {"char", str_char}, - {"dump", str_dump}, - {"find", str_find}, - {"format", str_format}, - {"gfind", gfind_nodef}, - {"gmatch", gmatch}, - {"gsub", str_gsub}, - {"len", str_len}, - {"lower", str_lower}, - {"match", str_match}, - {"rep", str_rep}, - {"reverse", str_reverse}, - {"sub", str_sub}, - {"upper", str_upper}, - {NULL, NULL} -}; - - -static void createmetatable (lua_State *L) { - lua_createtable(L, 0, 1); /* create metatable for strings */ - lua_pushliteral(L, ""); /* dummy string */ - lua_pushvalue(L, -2); - lua_setmetatable(L, -2); /* set string metatable */ - lua_pop(L, 1); /* pop dummy string */ - lua_pushvalue(L, -2); /* string library... */ - lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ - lua_pop(L, 1); /* pop metatable */ -} - - -/* -** Open string library -*/ -LUALIB_API int luaopen_string (lua_State *L) { - luaL_register(L, LUA_STRLIBNAME, strlib); -#if defined(LUA_COMPAT_GFIND) - lua_getfield(L, -1, "gmatch"); - lua_setfield(L, -2, "gfind"); -#endif - createmetatable(L); - return 1; -} - diff --git a/script/lua/ltable.c b/script/lua/ltable.c deleted file mode 100644 index f6501f8d5..000000000 --- a/script/lua/ltable.c +++ /dev/null @@ -1,594 +0,0 @@ -/* -** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - - -/* -** Implementation of tables (aka arrays, objects, or hash tables). -** Tables keep its elements in two parts: an array part and a hash part. -** Non-negative integer keys are all candidates to be kept in the array -** part. The actual size of the array is the largest `n' such that at -** least half the slots between 0 and n are in use. -** Hash uses a mix of chained scatter table with Brent's variation. -** A main invariant of these tables is that, if an element is not -** in its main position (i.e. the `original' position that its hash gives -** to it), then the colliding element is in its own main position. -** Hence even when the load factor reaches 100%, performance remains good. -*/ - -#if 0 -#include -#include -#endif - -#define ltable_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "ltable.h" - - -/* -** max size of array part is 2^MAXBITS -*/ -#if LUAI_BITSINT > 26 -#define MAXBITS 26 -#else -#define MAXBITS (LUAI_BITSINT-2) -#endif - -#define MAXASIZE (1 << MAXBITS) - - -#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) - -#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) -#define hashboolean(t,p) hashpow2(t, p) - - -/* -** for some types, it is better to avoid modulus by power of 2, as -** they tend to have many 2 factors. -*/ -#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) - - -#define hashpointer(t,p) hashmod(t, IntPoint(p)) - - -/* -** number of ints inside a lua_Number -*/ -#define numints cast_int(sizeof(lua_Number)/sizeof(int)) - - - -#define dummynode (&dummynode_) - -static const Node dummynode_ = { - {{NULL}, LUA_TNIL}, /* value */ - {{{NULL}, LUA_TNIL, NULL}} /* key */ -}; - - -/* -** hash for lua_Numbers -*/ -static Node *hashnum (const Table *t, lua_Number n) { - unsigned int a[numints]; - int i; - if (luai_numeq(n, 0)) /* avoid problems with -0 */ - return gnode(t, 0); - memcpy(a, &n, sizeof(a)); - for (i = 1; i < numints; i++) a[0] += a[i]; - return hashmod(t, a[0]); -} - - - -/* -** returns the `main' position of an element in a table (that is, the index -** of its hash value) -*/ -static Node *mainposition (const Table *t, const TValue *key) { - switch (ttype(key)) { - case LUA_TNUMBER: - return hashnum(t, nvalue(key)); - case LUA_TSTRING: - return hashstr(t, rawtsvalue(key)); - case LUA_TBOOLEAN: - return hashboolean(t, bvalue(key)); - case LUA_TLIGHTUSERDATA: - return hashpointer(t, pvalue(key)); - default: - return hashpointer(t, gcvalue(key)); - } -} - - -/* -** returns the index for `key' if `key' is an appropriate key to live in -** the array part of the table, -1 otherwise. -*/ -static int arrayindex (const TValue *key) { - if (ttisnumber(key)) { - lua_Number n = nvalue(key); - int k; - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) - return k; - } - return -1; /* `key' did not match some condition */ -} - - -/* -** returns the index of a `key' for table traversals. First goes all -** elements in the array part, then elements in the hash part. The -** beginning of a traversal is signalled by -1. -*/ -static int findindex (lua_State *L, Table *t, StkId key) { - int i; - if (ttisnil(key)) return -1; /* first iteration */ - i = arrayindex(key); - if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ - return i-1; /* yes; that's the index (corrected to C) */ - else { - Node *n = mainposition(t, key); - do { /* check whether `key' is somewhere in the chain */ - /* key may be dead already, but it is ok to use it in `next' */ - if (luaO_rawequalObj(key2tval(n), key) || - (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && - gcvalue(gkey(n)) == gcvalue(key))) { - i = cast_int(n - gnode(t, 0)); /* key index in hash table */ - /* hash elements are numbered after array ones */ - return i + t->sizearray; - } - else n = gnext(n); - } while (n); - luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ - return 0; /* to avoid warnings */ - } -} - - -int luaH_next (lua_State *L, Table *t, StkId key) { - int i = findindex(L, t, key); /* find original element */ - for (i++; i < t->sizearray; i++) { /* try first array part */ - if (!ttisnil(&t->array[i])) { /* a non-nil value? */ - setnvalue(key, cast_num(i+1)); - setobj2s(L, key+1, &t->array[i]); - return 1; - } - } - for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ - if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ - setobj2s(L, key, key2tval(gnode(t, i))); - setobj2s(L, key+1, gval(gnode(t, i))); - return 1; - } - } - return 0; /* no more elements */ -} - - -/* -** {============================================================= -** Rehash -** ============================================================== -*/ - - -static int computesizes (int nums[], int *narray) { - int i; - int twotoi; /* 2^i */ - int a = 0; /* number of elements smaller than 2^i */ - int na = 0; /* number of elements to go to array part */ - int n = 0; /* optimal size for array part */ - for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { - if (nums[i] > 0) { - a += nums[i]; - if (a > twotoi/2) { /* more than half elements present? */ - n = twotoi; /* optimal size (till now) */ - na = a; /* all elements smaller than n will go to array part */ - } - } - if (a == *narray) break; /* all elements already counted */ - } - *narray = n; - lua_assert(*narray/2 <= na && na <= *narray); - return na; -} - - -static int countint (const TValue *key, int *nums) { - int k = arrayindex(key); - if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ - nums[ceillog2(k)]++; /* count as such */ - return 1; - } - else - return 0; -} - - -static int numusearray (const Table *t, int *nums) { - int lg; - int ttlg; /* 2^lg */ - int ause = 0; /* summation of `nums' */ - int i = 1; /* count to traverse all array keys */ - for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ - int lc = 0; /* counter */ - int lim = ttlg; - if (lim > t->sizearray) { - lim = t->sizearray; /* adjust upper limit */ - if (i > lim) - break; /* no more elements to count */ - } - /* count elements in range (2^(lg-1), 2^lg] */ - for (; i <= lim; i++) { - if (!ttisnil(&t->array[i-1])) - lc++; - } - nums[lg] += lc; - ause += lc; - } - return ause; -} - - -static int numusehash (const Table *t, int *nums, int *pnasize) { - int totaluse = 0; /* total number of elements */ - int ause = 0; /* summation of `nums' */ - int i = sizenode(t); - while (i--) { - Node *n = &t->node[i]; - if (!ttisnil(gval(n))) { - ause += countint(key2tval(n), nums); - totaluse++; - } - } - *pnasize += ause; - return totaluse; -} - - -static void setarrayvector (lua_State *L, Table *t, int size) { - int i; - luaM_reallocvector(L, t->array, t->sizearray, size, TValue); - for (i=t->sizearray; iarray[i]); - t->sizearray = size; -} - - -static void setnodevector (lua_State *L, Table *t, int size) { - int lsize; - if (size == 0) { /* no elements to hash part? */ - t->node = cast(Node *, dummynode); /* use common `dummynode' */ - lsize = 0; - } - else { - int i; - lsize = ceillog2(size); - if (lsize > MAXBITS) - luaG_runerror(L, "table overflow"); - size = twoto(lsize); - t->node = luaM_newvector(L, size, Node); - for (i=0; ilsizenode = cast_byte(lsize); - t->lastfree = gnode(t, size); /* all positions are free */ -} - - -static void resize (lua_State *L, Table *t, int nasize, int nhsize) { - int i; - int oldasize = t->sizearray; - int oldhsize = t->lsizenode; - Node *nold = t->node; /* save old hash ... */ - if (nasize > oldasize) /* array part must grow? */ - setarrayvector(L, t, nasize); - /* create new hash part with appropriate size */ - setnodevector(L, t, nhsize); - if (nasize < oldasize) { /* array part must shrink? */ - t->sizearray = nasize; - /* re-insert elements from vanishing slice */ - for (i=nasize; iarray[i])) - setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); - } - /* shrink array */ - luaM_reallocvector(L, t->array, oldasize, nasize, TValue); - } - /* re-insert elements from hash part */ - for (i = twoto(oldhsize) - 1; i >= 0; i--) { - Node *old = nold+i; - if (!ttisnil(gval(old))) - setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); - } - if (nold != dummynode) - luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ -} - - -void luaH_resizearray (lua_State *L, Table *t, int nasize) { - int nsize = (t->node == dummynode) ? 0 : sizenode(t); - resize(L, t, nasize, nsize); -} - - -static void rehash (lua_State *L, Table *t, const TValue *ek) { - int nasize, na; - int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ - int i; - int totaluse; - for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ - nasize = numusearray(t, nums); /* count keys in array part */ - totaluse = nasize; /* all those keys are integer keys */ - totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ - /* count extra key */ - nasize += countint(ek, nums); - totaluse++; - /* compute new size for array part */ - na = computesizes(nums, &nasize); - /* resize the table to new computed sizes */ - resize(L, t, nasize, totaluse - na); -} - - - -/* -** }============================================================= -*/ - - -Table *luaH_new (lua_State *L, int narray, int nhash) { - Table *t = luaM_new(L, Table); - luaC_link(L, obj2gco(t), LUA_TTABLE); - t->metatable = NULL; - t->flags = cast_byte(~0); - /* temporary values (kept only if some malloc fails) */ - t->array = NULL; - t->sizearray = 0; - t->lsizenode = 0; - t->node = cast(Node *, dummynode); - setarrayvector(L, t, narray); - setnodevector(L, t, nhash); - return t; -} - - -void luaH_free (lua_State *L, Table *t) { - if (t->node != dummynode) - luaM_freearray(L, t->node, sizenode(t), Node); - luaM_freearray(L, t->array, t->sizearray, TValue); - luaM_free(L, t); -} - - -static Node *getfreepos (Table *t) { - while (t->lastfree-- > t->node) { - if (ttisnil(gkey(t->lastfree))) - return t->lastfree; - } - return NULL; /* could not find a free place */ -} - - - -/* -** inserts a new key into a hash table; first, check whether key's main -** position is free. If not, check whether colliding node is in its main -** position or not: if it is not, move colliding node to an empty place and -** put new key in its main position; otherwise (colliding node is in its main -** position), new key goes to an empty position. -*/ -static TValue *newkey (lua_State *L, Table *t, const TValue *key) { - Node *mp = mainposition(t, key); - if (!ttisnil(gval(mp)) || mp == dummynode) { - Node *othern; - Node *n = getfreepos(t); /* get a free place */ - if (n == NULL) { /* cannot find a free place? */ - rehash(L, t, key); /* grow table */ - return luaH_set(L, t, key); /* re-insert key into grown table */ - } - lua_assert(n != dummynode); - othern = mainposition(t, key2tval(mp)); - if (othern != mp) { /* is colliding node out of its main position? */ - /* yes; move colliding node into free position */ - while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ - gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ -#if 0 - *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ -#else - memcpy (n, mp, sizeof (*n)); -#endif - gnext(mp) = NULL; /* now `mp' is free */ - setnilvalue(gval(mp)); - } - else { /* colliding node is in its own main position */ - /* new node will go into free position */ - gnext(n) = gnext(mp); /* chain new position */ - gnext(mp) = n; - mp = n; - } - } - gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; - luaC_barriert(L, t, key); - lua_assert(ttisnil(gval(mp))); - return gval(mp); -} - - -/* -** search function for integers -*/ -const TValue *luaH_getnum (Table *t, int key) { - /* (1 <= key && key <= t->sizearray) */ - if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) - return &t->array[key-1]; - else { - lua_Number nk = cast_num(key); - Node *n = hashnum(t, nk); - do { /* check whether `key' is somewhere in the chain */ - if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; - } -} - - -/* -** search function for strings -*/ -const TValue *luaH_getstr (Table *t, TString *key) { - Node *n = hashstr(t, key); - do { /* check whether `key' is somewhere in the chain */ - if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; -} - - -/* -** main search function -*/ -const TValue *luaH_get (Table *t, const TValue *key) { - switch (ttype(key)) { - case LUA_TNIL: return luaO_nilobject; - case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); - case LUA_TNUMBER: { - int k; - lua_Number n = nvalue(key); - lua_number2int(k, n); - if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ - return luaH_getnum(t, k); /* use specialized version */ - /* else go through */ - } - default: { - Node *n = mainposition(t, key); - do { /* check whether `key' is somewhere in the chain */ - if (luaO_rawequalObj(key2tval(n), key)) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; - } - } -} - - -TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { - const TValue *p = luaH_get(t, key); - t->flags = 0; - if (p != luaO_nilobject) - return cast(TValue *, p); - else { - if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisnumber(key) && luai_numisnan(nvalue(key))) - luaG_runerror(L, "table index is NaN"); - return newkey(L, t, key); - } -} - - -TValue *luaH_setnum (lua_State *L, Table *t, int key) { - const TValue *p = luaH_getnum(t, key); - if (p != luaO_nilobject) - return cast(TValue *, p); - else { - TValue k; - setnvalue(&k, cast_num(key)); - return newkey(L, t, &k); - } -} - - -TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { - const TValue *p = luaH_getstr(t, key); - if (p != luaO_nilobject) - return cast(TValue *, p); - else { - TValue k; - setsvalue(L, &k, key); - return newkey(L, t, &k); - } -} - - -static int unbound_search (Table *t, unsigned int j) { - unsigned int i = j; /* i is zero or a present index */ - j++; - /* find `i' and `j' such that i is present and j is not */ - while (!ttisnil(luaH_getnum(t, j))) { - i = j; - j *= 2; - if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ - /* table was built with bad purposes: resort to linear search */ - i = 1; - while (!ttisnil(luaH_getnum(t, i))) i++; - return i - 1; - } - } - /* now do a binary search between them */ - while (j - i > 1) { - unsigned int m = (i+j)/2; - if (ttisnil(luaH_getnum(t, m))) j = m; - else i = m; - } - return i; -} - - -/* -** Try to find a boundary in table `t'. A `boundary' is an integer index -** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). -*/ -int luaH_getn (Table *t) { - unsigned int j = t->sizearray; - if (j > 0 && ttisnil(&t->array[j - 1])) { - /* there is a boundary in the array part: (binary) search for it */ - unsigned int i = 0; - while (j - i > 1) { - unsigned int m = (i+j)/2; - if (ttisnil(&t->array[m - 1])) j = m; - else i = m; - } - return i; - } - /* else must find a boundary in hash part */ - else if (t->node == dummynode) /* hash part is empty? */ - return j; /* that is easy... */ - else return unbound_search(t, j); -} - - - -#if defined(LUA_DEBUG) - -Node *luaH_mainposition (const Table *t, const TValue *key) { - return mainposition(t, key); -} - -int luaH_isdummy (Node *n) { return n == dummynode; } - -#endif diff --git a/script/lua/ltable.h b/script/lua/ltable.h deleted file mode 100644 index f5b9d5ead..000000000 --- a/script/lua/ltable.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - -#ifndef ltable_h -#define ltable_h - -#include "lobject.h" - - -#define gnode(t,i) (&(t)->node[i]) -#define gkey(n) (&(n)->i_key.nk) -#define gval(n) (&(n)->i_val) -#define gnext(n) ((n)->i_key.nk.next) - -#define key2tval(n) (&(n)->i_key.tvk) - - -LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); -LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); -LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); -LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); -LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); -LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); -LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); -LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); -LUAI_FUNC void luaH_free (lua_State *L, Table *t); -LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); -LUAI_FUNC int luaH_getn (Table *t); - - -#if defined(LUA_DEBUG) -LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); -LUAI_FUNC int luaH_isdummy (Node *n); -#endif - - -#endif diff --git a/script/lua/ltablib.c b/script/lua/ltablib.c deleted file mode 100644 index 34a346744..000000000 --- a/script/lua/ltablib.c +++ /dev/null @@ -1,288 +0,0 @@ -/* -** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ -** Library for Table Manipulation -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#endif - -#define ltablib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) - - -static int foreachi (lua_State *L) { - int i; - int n = aux_getn(L, 1); - luaL_checktype(L, 2, LUA_TFUNCTION); - for (i=1; i <= n; i++) { - lua_pushvalue(L, 2); /* function */ - lua_pushinteger(L, i); /* 1st argument */ - lua_rawgeti(L, 1, i); /* 2nd argument */ - lua_call(L, 2, 1); - if (!lua_isnil(L, -1)) - return 1; - lua_pop(L, 1); /* remove nil result */ - } - return 0; -} - - -static int foreach (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checktype(L, 2, LUA_TFUNCTION); - lua_pushnil(L); /* first key */ - while (lua_next(L, 1)) { - lua_pushvalue(L, 2); /* function */ - lua_pushvalue(L, -3); /* key */ - lua_pushvalue(L, -3); /* value */ - lua_call(L, 2, 1); - if (!lua_isnil(L, -1)) - return 1; - lua_pop(L, 2); /* remove value and result */ - } - return 0; -} - - -static int maxn (lua_State *L) { - lua_Number max = 0; - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushnil(L); /* first key */ - while (lua_next(L, 1)) { - lua_pop(L, 1); /* remove value */ - if (lua_type(L, -1) == LUA_TNUMBER) { - lua_Number v = lua_tonumber(L, -1); - if (v > max) max = v; - } - } - lua_pushnumber(L, max); - return 1; -} - - -static int getn (lua_State *L) { - lua_pushinteger(L, aux_getn(L, 1)); - return 1; -} - - -static int setn (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); -#ifndef luaL_setn - luaL_setn(L, 1, luaL_checkint(L, 2)); -#else - luaL_error(L, LUA_QL("setn") " is obsolete"); -#endif - lua_pushvalue(L, 1); - return 1; -} - - -static int tinsert (lua_State *L) { - int e = aux_getn(L, 1) + 1; /* first empty element */ - int pos; /* where to insert new element */ - switch (lua_gettop(L)) { - case 2: { /* called with only 2 arguments */ - pos = e; /* insert new element at the end */ - break; - } - case 3: { - int i; - pos = luaL_checkint(L, 2); /* 2nd argument is the position */ - if (pos > e) e = pos; /* `grow' array if necessary */ - for (i = e; i > pos; i--) { /* move up elements */ - lua_rawgeti(L, 1, i-1); - lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ - } - break; - } - default: { - return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); - } - } - luaL_setn(L, 1, e); /* new size */ - lua_rawseti(L, 1, pos); /* t[pos] = v */ - return 0; -} - - -static int tremove (lua_State *L) { - int e = aux_getn(L, 1); - int pos = luaL_optint(L, 2, e); - if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ - return 0; /* nothing to remove */ - luaL_setn(L, 1, e - 1); /* t.n = n-1 */ - lua_rawgeti(L, 1, pos); /* result = t[pos] */ - for ( ;pos= P */ - while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { - if (i>u) luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[i] */ - } - /* repeat --j until a[j] <= P */ - while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { - if (j -#endif - -#define ltm_c -#define LUA_CORE - -#include "lua.h" - -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - - -const char *const luaT_typenames[] = { - "nil", "boolean", "userdata", "number", - "string", "table", "function", "userdata", "thread", - "proto", "upval" -}; - - -void luaT_init (lua_State *L) { - static const char *const luaT_eventname[] = { /* ORDER TM */ - "__index", "__newindex", - "__gc", "__mode", "__eq", - "__add", "__sub", "__mul", "__div", "__mod", - "__pow", "__unm", "__len", "__lt", "__le", - "__concat", "__call" - }; - int i; - for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); - luaS_fix(G(L)->tmname[i]); /* never collect these names */ - } -} - - -/* -** function to be used with macro "fasttm": optimized for absence of -** tag methods -*/ -const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaH_getstr(events, ename); - lua_assert(event <= TM_EQ); - if (ttisnil(tm)) { /* no tag method? */ - events->flags |= cast_byte(1u<metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(o)->metatable; - break; - default: - mt = G(L)->mt[ttype(o)]; - } - return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); -} - diff --git a/script/lua/ltm.h b/script/lua/ltm.h deleted file mode 100644 index 64343b781..000000000 --- a/script/lua/ltm.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ -** Tag methods -** See Copyright Notice in lua.h -*/ - -#ifndef ltm_h -#define ltm_h - - -#include "lobject.h" - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER TM" -*/ -typedef enum { - TM_INDEX, - TM_NEWINDEX, - TM_GC, - TM_MODE, - TM_EQ, /* last tag method with `fast' access */ - TM_ADD, - TM_SUB, - TM_MUL, - TM_DIV, - TM_MOD, - TM_POW, - TM_UNM, - TM_LEN, - TM_LT, - TM_LE, - TM_CONCAT, - TM_CALL, - TM_N /* number of elements in the enum */ -} TMS; - - - -#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ - ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) - -#define fasttm(l,et,e) gfasttm(G(l), et, e) - -LUAI_DATA const char *const luaT_typenames[]; - - -LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); -LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, - TMS event); -LUAI_FUNC void luaT_init (lua_State *L); - -#endif diff --git a/script/lua/lua.h b/script/lua/lua.h deleted file mode 100644 index 91aa410e8..000000000 --- a/script/lua/lua.h +++ /dev/null @@ -1,388 +0,0 @@ -/* -** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ -** Lua - An Extensible Extension Language -** Lua.org, PUC-Rio, Brazil (http://www.lua.org) -** See Copyright Notice at the end of this file -*/ - - -#ifndef lua_h -#define lua_h - -#include -#include - - -#include "luaconf.h" - - -#define LUA_VERSION "Lua 5.1" -#define LUA_RELEASE "Lua 5.1.4" -#define LUA_VERSION_NUM 501 -#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" -#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" - - -/* mark for precompiled code (`Lua') */ -#define LUA_SIGNATURE "\033Lua" - -/* option for multiple returns in `lua_pcall' and `lua_call' */ -#define LUA_MULTRET (-1) - - -/* -** pseudo-indices -*/ -#define LUA_REGISTRYINDEX (-10000) -#define LUA_ENVIRONINDEX (-10001) -#define LUA_GLOBALSINDEX (-10002) -#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) - - -/* thread status; 0 is OK */ -#define LUA_YIELD 1 -#define LUA_ERRRUN 2 -#define LUA_ERRSYNTAX 3 -#define LUA_ERRMEM 4 -#define LUA_ERRERR 5 - - -typedef struct lua_State lua_State; - -typedef int (*lua_CFunction) (lua_State *L); - - -/* -** functions that read/write blocks when loading/dumping Lua chunks -*/ -typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); - -typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); - - -/* -** prototype for memory-allocation functions -*/ -typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); - - -/* -** basic types -*/ -#define LUA_TNONE (-1) - -#define LUA_TNIL 0 -#define LUA_TBOOLEAN 1 -#define LUA_TLIGHTUSERDATA 2 -#define LUA_TNUMBER 3 -#define LUA_TSTRING 4 -#define LUA_TTABLE 5 -#define LUA_TFUNCTION 6 -#define LUA_TUSERDATA 7 -#define LUA_TTHREAD 8 - - - -/* minimum Lua stack available to a C function */ -#define LUA_MINSTACK 20 - - -/* -** generic extra include file -*/ -#if defined(LUA_USER_H) -#include LUA_USER_H -#endif - - -/* type of numbers in Lua */ -typedef LUA_NUMBER lua_Number; - - -/* type for integer functions */ -typedef LUA_INTEGER lua_Integer; - - - -/* -** state manipulation -*/ -LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); -LUA_API void (lua_close) (lua_State *L); -LUA_API lua_State *(lua_newthread) (lua_State *L); - -LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); - - -/* -** basic stack manipulation -*/ -LUA_API int (lua_gettop) (lua_State *L); -LUA_API void (lua_settop) (lua_State *L, int idx); -LUA_API void (lua_pushvalue) (lua_State *L, int idx); -LUA_API void (lua_remove) (lua_State *L, int idx); -LUA_API void (lua_insert) (lua_State *L, int idx); -LUA_API void (lua_replace) (lua_State *L, int idx); -LUA_API int (lua_checkstack) (lua_State *L, int sz); - -LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); - - -/* -** access functions (stack -> C) -*/ - -LUA_API int (lua_isnumber) (lua_State *L, int idx); -LUA_API int (lua_isstring) (lua_State *L, int idx); -LUA_API int (lua_iscfunction) (lua_State *L, int idx); -LUA_API int (lua_isuserdata) (lua_State *L, int idx); -LUA_API int (lua_type) (lua_State *L, int idx); -LUA_API const char *(lua_typename) (lua_State *L, int tp); - -LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); -LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); -LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); - -LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); -LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); -LUA_API int (lua_toboolean) (lua_State *L, int idx); -LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); -LUA_API size_t (lua_objlen) (lua_State *L, int idx); -LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); -LUA_API void *(lua_touserdata) (lua_State *L, int idx); -LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); -LUA_API const void *(lua_topointer) (lua_State *L, int idx); - - -/* -** push functions (C -> stack) -*/ -LUA_API void (lua_pushnil) (lua_State *L); -LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); -LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); -LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); -LUA_API void (lua_pushstring) (lua_State *L, const char *s); -LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, - va_list argp); -LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); -LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); -LUA_API void (lua_pushboolean) (lua_State *L, int b); -LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); -LUA_API int (lua_pushthread) (lua_State *L); - - -/* -** get functions (Lua -> stack) -*/ -LUA_API void (lua_gettable) (lua_State *L, int idx); -LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); -LUA_API void (lua_rawget) (lua_State *L, int idx); -LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); -LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); -LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); -LUA_API int (lua_getmetatable) (lua_State *L, int objindex); -LUA_API void (lua_getfenv) (lua_State *L, int idx); - - -/* -** set functions (stack -> Lua) -*/ -LUA_API void (lua_settable) (lua_State *L, int idx); -LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); -LUA_API void (lua_rawset) (lua_State *L, int idx); -LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); -LUA_API int (lua_setmetatable) (lua_State *L, int objindex); -LUA_API int (lua_setfenv) (lua_State *L, int idx); - - -/* -** `load' and `call' functions (load and run Lua code) -*/ -LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); -LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); -LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); -LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, - const char *chunkname); - -LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); - - -/* -** coroutine functions -*/ -LUA_API int (lua_yield) (lua_State *L, int nresults); -LUA_API int (lua_resume) (lua_State *L, int narg); -LUA_API int (lua_status) (lua_State *L); - -/* -** garbage-collection function and options -*/ - -#define LUA_GCSTOP 0 -#define LUA_GCRESTART 1 -#define LUA_GCCOLLECT 2 -#define LUA_GCCOUNT 3 -#define LUA_GCCOUNTB 4 -#define LUA_GCSTEP 5 -#define LUA_GCSETPAUSE 6 -#define LUA_GCSETSTEPMUL 7 - -LUA_API int (lua_gc) (lua_State *L, int what, int data); - - -/* -** miscellaneous functions -*/ - -LUA_API int (lua_error) (lua_State *L); - -LUA_API int (lua_next) (lua_State *L, int idx); - -LUA_API void (lua_concat) (lua_State *L, int n); - -LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); -LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); - - - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - -#define lua_pop(L,n) lua_settop(L, -(n)-1) - -#define lua_newtable(L) lua_createtable(L, 0, 0) - -#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) - -#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) - -#define lua_strlen(L,i) lua_objlen(L, (i)) - -#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) -#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) -#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) -#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) -#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) -#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) -#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) -#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) - -#define lua_pushliteral(L, s) \ - lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) - -#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) -#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) - -#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) - - - -/* -** compatibility macros and functions -*/ - -#define lua_open() luaL_newstate() - -#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) - -#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) - -#define lua_Chunkreader lua_Reader -#define lua_Chunkwriter lua_Writer - - -/* hack */ -LUA_API void lua_setlevel (lua_State *from, lua_State *to); - - -/* -** {====================================================================== -** Debug API -** ======================================================================= -*/ - - -/* -** Event codes -*/ -#define LUA_HOOKCALL 0 -#define LUA_HOOKRET 1 -#define LUA_HOOKLINE 2 -#define LUA_HOOKCOUNT 3 -#define LUA_HOOKTAILRET 4 - - -/* -** Event masks -*/ -#define LUA_MASKCALL (1 << LUA_HOOKCALL) -#define LUA_MASKRET (1 << LUA_HOOKRET) -#define LUA_MASKLINE (1 << LUA_HOOKLINE) -#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) - -typedef struct lua_Debug lua_Debug; /* activation record */ - - -/* Functions to be called by the debuger in specific events */ -typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); - - -LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); -LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); -LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); - -LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); -LUA_API lua_Hook lua_gethook (lua_State *L); -LUA_API int lua_gethookmask (lua_State *L); -LUA_API int lua_gethookcount (lua_State *L); - - -struct lua_Debug { - int event; - const char *name; /* (n) */ - const char *namewhat; /* (n) `global', `local', `field', `method' */ - const char *what; /* (S) `Lua', `C', `main', `tail' */ - const char *source; /* (S) */ - int currentline; /* (l) */ - int nups; /* (u) number of upvalues */ - int linedefined; /* (S) */ - int lastlinedefined; /* (S) */ - char short_src[LUA_IDSIZE]; /* (S) */ - /* private part */ - int i_ci; /* active function */ -}; - -/* }====================================================================== */ - - -/****************************************************************************** -* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -******************************************************************************/ - - -#endif diff --git a/script/lua/luaconf.h b/script/lua/luaconf.h deleted file mode 100644 index c7f73c3c8..000000000 --- a/script/lua/luaconf.h +++ /dev/null @@ -1,811 +0,0 @@ -/* -** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ -** Configuration file for Lua -** See Copyright Notice in lua.h -*/ - - -#ifndef lconfig_h -#define lconfig_h - -#if 0 -#include -#include -#endif - -#include "grub_lua.h" - -/* -** ================================================================== -** Search for "@@" to find all configurable definitions. -** =================================================================== -*/ - - -/* -@@ LUA_ANSI controls the use of non-ansi features. -** CHANGE it (define it) if you want Lua to avoid the use of any -** non-ansi feature or library. -*/ -#if defined(__STRICT_ANSI__) -#define LUA_ANSI -#endif - - -#if !defined(LUA_ANSI) && defined(_WIN32) -#define LUA_WIN -#endif - -#if defined(LUA_USE_LINUX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ -#define LUA_USE_READLINE /* needs some extra libraries */ -#endif - -#if defined(LUA_USE_MACOSX) -#define LUA_USE_POSIX -#define LUA_DL_DYLD /* does not need extra library */ -#endif - - - -/* -@@ LUA_USE_POSIX includes all functionallity listed as X/Open System -@* Interfaces Extension (XSI). -** CHANGE it (define it) if your system is XSI compatible. -*/ -#if 0 -#if defined(LUA_USE_POSIX) -#define LUA_USE_MKSTEMP -#define LUA_USE_ISATTY -#define LUA_USE_POPEN -#define LUA_USE_ULONGJMP -#endif -#endif - -/* -@@ LUA_PATH and LUA_CPATH are the names of the environment variables that -@* Lua check to set its paths. -@@ LUA_INIT is the name of the environment variable that Lua -@* checks for initialization code. -** CHANGE them if you want different names. -*/ -#define LUA_PATH "LUA_PATH" -#define LUA_CPATH "LUA_CPATH" -#define LUA_INIT "LUA_INIT" - - -/* -@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for -@* Lua libraries. -@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for -@* C libraries. -** CHANGE them if your machine has a non-conventional directory -** hierarchy or if you want to install your libraries in -** non-conventional directories. -*/ -#if defined(_WIN32) -/* -** In Windows, any exclamation mark ('!') in the path is replaced by the -** path of the directory of the executable file of the current process. -*/ -#define LUA_LDIR "!\\lua\\" -#define LUA_CDIR "!\\" -#define LUA_PATH_DEFAULT \ - ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" -#define LUA_CPATH_DEFAULT \ - ".\\?.dll;" ".\\?51.dll;" LUA_CDIR"?.dll;" LUA_CDIR"?51.dll;" LUA_CDIR"clibs\\?.dll;" LUA_CDIR"clibs\\?51.dll;" LUA_CDIR"loadall.dll;" LUA_CDIR"clibs\\loadall.dll" - -#else -#define LUA_ROOT "/usr/local/" -#define LUA_LDIR LUA_ROOT "share/lua/5.1/" -#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" -#define LUA_PATH_DEFAULT \ - "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" -#define LUA_CPATH_DEFAULT \ - "./?.so;" "./lib?51.so;" LUA_CDIR"?.so;" LUA_CDIR"lib?51.so;" LUA_CDIR"loadall.so" -#endif - - -/* -@@ LUA_DIRSEP is the directory separator (for submodules). -** CHANGE it if your machine does not use "/" as the directory separator -** and is not Windows. (On Windows Lua automatically uses "\".) -*/ -#if defined(_WIN32) -#define LUA_DIRSEP "\\" -#else -#define LUA_DIRSEP "/" -#endif - - -/* -@@ LUA_PATHSEP is the character that separates templates in a path. -@@ LUA_PATH_MARK is the string that marks the substitution points in a -@* template. -@@ LUA_EXECDIR in a Windows path is replaced by the executable's -@* directory. -@@ LUA_IGMARK is a mark to ignore all before it when bulding the -@* luaopen_ function name. -** CHANGE them if for some reason your system cannot use those -** characters. (E.g., if one of those characters is a common character -** in file/directory names.) Probably you do not need to change them. -*/ -#define LUA_PATHSEP ";" -#define LUA_PATH_MARK "?" -#define LUA_EXECDIR "!" -#define LUA_IGMARK "-" - - -/* -@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. -** CHANGE that if ptrdiff_t is not adequate on your machine. (On most -** machines, ptrdiff_t gives a good choice between int or long.) -*/ -#define LUA_INTEGER ptrdiff_t - - -/* -@@ LUA_API is a mark for all core API functions. -@@ LUALIB_API is a mark for all standard library functions. -** CHANGE them if you need to define those functions in some special way. -** For instance, if you want to create one Windows DLL with the core and -** the libraries, you may want to use the following definition (define -** LUA_BUILD_AS_DLL to get it). -*/ -#if defined(LUA_BUILD_AS_DLL) - -#if defined(LUA_CORE) || defined(LUA_LIB) -#define LUA_API __declspec(dllexport) -#else -#define LUA_API __declspec(dllimport) -#endif - -#else - -#define LUA_API extern - -#endif - -/* more often than not the libs go together with the core */ -#define LUALIB_API LUA_API - - -/* -@@ LUAI_FUNC is a mark for all extern functions that are not to be -@* exported to outside modules. -@@ LUAI_DATA is a mark for all extern (const) variables that are not to -@* be exported to outside modules. -** CHANGE them if you need to mark them in some special way. Elf/gcc -** (versions 3.2 and later) mark them as "hidden" to optimize access -** when Lua is compiled as a shared library. -*/ -#if defined(luaall_c) -#define LUAI_FUNC static -#define LUAI_DATA /* empty */ - -#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ - defined(__ELF__) -#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#define LUAI_DATA LUAI_FUNC - -#else -#define LUAI_FUNC extern -#define LUAI_DATA extern -#endif - - - -/* -@@ LUA_QL describes how error messages quote program elements. -** CHANGE it if you want a different appearance. -*/ -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") - - -/* -@@ LUA_IDSIZE gives the maximum size for the description of the source -@* of a function in debug information. -** CHANGE it if you want a different size. -*/ -#define LUA_IDSIZE 60 - - -/* -** {================================================================== -** Stand-alone configuration -** =================================================================== -*/ - -#if defined(lua_c) || defined(luaall_c) - -/* -@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that -@* is, whether we're running lua interactively). -** CHANGE it if you have a better definition for non-POSIX/non-Windows -** systems. -*/ -#if defined(LUA_USE_ISATTY) -#include -#define lua_stdin_is_tty() isatty(0) -#elif defined(LUA_WIN) -#include -#include -#define lua_stdin_is_tty() _isatty(_fileno(stdin)) -#else -#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ -#endif - - -/* -@@ LUA_PROMPT is the default prompt used by stand-alone Lua. -@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. -** CHANGE them if you want different prompts. (You can also change the -** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) -*/ -#define LUA_PROMPT "> " -#define LUA_PROMPT2 ">> " - - -/* -@@ LUA_PROGNAME is the default name for the stand-alone Lua program. -** CHANGE it if your stand-alone interpreter has a different name and -** your system is not able to detect that name automatically. -*/ -#define LUA_PROGNAME "lua" - - -/* -@@ LUA_MAXINPUT is the maximum length for an input line in the -@* stand-alone interpreter. -** CHANGE it if you need longer lines. -*/ -#define LUA_MAXINPUT 512 - - -/* -@@ lua_readline defines how to show a prompt and then read a line from -@* the standard input. -@@ lua_saveline defines how to "save" a read line in a "history". -@@ lua_freeline defines how to free a line read by lua_readline. -** CHANGE them if you want to improve this functionality (e.g., by using -** GNU readline and history facilities). -*/ -#if defined(LUA_USE_READLINE) -#include -#include -#include -#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) -#define lua_saveline(L,idx) \ - if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ - add_history(lua_tostring(L, idx)); /* add it to history */ -#define lua_freeline(L,b) ((void)L, free(b)) -#else -#define lua_readline(L,b,p) \ - ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ - fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -#define lua_saveline(L,idx) { (void)L; (void)idx; } -#define lua_freeline(L,b) { (void)L; (void)b; } -#endif - -#endif - -/* }================================================================== */ - - -/* -@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles -@* as a percentage. -** CHANGE it if you want the GC to run faster or slower (higher values -** mean larger pauses which mean slower collection.) You can also change -** this value dynamically. -*/ -#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ - - -/* -@@ LUAI_GCMUL defines the default speed of garbage collection relative to -@* memory allocation as a percentage. -** CHANGE it if you want to change the granularity of the garbage -** collection. (Higher values mean coarser collections. 0 represents -** infinity, where each step performs a full collection.) You can also -** change this value dynamically. -*/ -#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ - - - -/* -@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. -** CHANGE it (define it) if you want exact compatibility with the -** behavior of setn/getn in Lua 5.0. -*/ -#undef LUA_COMPAT_GETN - -/* -@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. -** CHANGE it to undefined as soon as you do not need a global 'loadlib' -** function (the function is still available as 'package.loadlib'). -*/ -#undef LUA_COMPAT_LOADLIB - -/* -@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. -** CHANGE it to undefined as soon as your programs use only '...' to -** access vararg parameters (instead of the old 'arg' table). -*/ -#define LUA_COMPAT_VARARG - -/* -@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. -** CHANGE it to undefined as soon as your programs use 'math.fmod' or -** the new '%' operator instead of 'math.mod'. -*/ -#define LUA_COMPAT_MOD - -/* -@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting -@* facility. -** CHANGE it to 2 if you want the old behaviour, or undefine it to turn -** off the advisory error when nesting [[...]]. -*/ -#define LUA_COMPAT_LSTR 1 - -/* -@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. -** CHANGE it to undefined as soon as you rename 'string.gfind' to -** 'string.gmatch'. -*/ -#define LUA_COMPAT_GFIND - -/* -@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' -@* behavior. -** CHANGE it to undefined as soon as you replace to 'luaL_register' -** your uses of 'luaL_openlib' -*/ -#define LUA_COMPAT_OPENLIB - - - -/* -@@ luai_apicheck is the assert macro used by the Lua-C API. -** CHANGE luai_apicheck if you want Lua to perform some checks in the -** parameters it gets from API calls. This may slow down the interpreter -** a bit, but may be quite useful when debugging C code that interfaces -** with Lua. A useful redefinition is to use assert.h. -*/ -#if defined(LUA_USE_APICHECK) -#include -#define luai_apicheck(L,o) { (void)L; assert(o); } -#else -#define luai_apicheck(L,o) { (void)L; } -#endif - - -/* -@@ LUAI_BITSINT defines the number of bits in an int. -** CHANGE here if Lua cannot automatically detect the number of bits of -** your machine. Probably you do not need to change this. -*/ -/* avoid overflows in comparison */ -#if INT_MAX-20 < 32760 -#define LUAI_BITSINT 16 -#elif INT_MAX > 2147483640L -/* int has at least 32 bits */ -#define LUAI_BITSINT 32 -#else -#error "you must define LUA_BITSINT with number of bits in an integer" -#endif - - -/* -@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. -@@ LUAI_INT32 is an signed integer with at least 32 bits. -@@ LUAI_UMEM is an unsigned integer big enough to count the total -@* memory used by Lua. -@@ LUAI_MEM is a signed integer big enough to count the total memory -@* used by Lua. -** CHANGE here if for some weird reason the default definitions are not -** good enough for your machine. (The definitions in the 'else' -** part always works, but may waste space on machines with 64-bit -** longs.) Probably you do not need to change this. -*/ -#if LUAI_BITSINT >= 32 -#define LUAI_UINT32 unsigned int -#define LUAI_INT32 int -#define LUAI_MAXINT32 INT_MAX -#define LUAI_UMEM size_t -#define LUAI_MEM ptrdiff_t -#else -/* 16-bit ints */ -#define LUAI_UINT32 unsigned long -#define LUAI_INT32 long -#define LUAI_MAXINT32 LONG_MAX -#define LUAI_UMEM unsigned long -#define LUAI_MEM long -#endif - - -/* -@@ LUAI_MAXCALLS limits the number of nested calls. -** CHANGE it if you need really deep recursive calls. This limit is -** arbitrary; its only purpose is to stop infinite recursion before -** exhausting memory. -*/ -#define LUAI_MAXCALLS 20000 - - -/* -@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function -@* can use. -** CHANGE it if you need lots of (Lua) stack space for your C -** functions. This limit is arbitrary; its only purpose is to stop C -** functions to consume unlimited stack space. (must be smaller than -** -LUA_REGISTRYINDEX) -*/ -#define LUAI_MAXCSTACK 8000 - - - -/* -** {================================================================== -** CHANGE (to smaller values) the following definitions if your system -** has a small C stack. (Or you may want to change them to larger -** values if your system has a large C stack and these limits are -** too rigid for you.) Some of these constants control the size of -** stack-allocated arrays used by the compiler or the interpreter, while -** others limit the maximum number of recursive calls that the compiler -** or the interpreter can perform. Values too large may cause a C stack -** overflow for some forms of deep constructs. -** =================================================================== -*/ - - -/* -@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and -@* syntactical nested non-terminals in a program. -*/ -#define LUAI_MAXCCALLS 200 - - -/* -@@ LUAI_MAXVARS is the maximum number of local variables per function -@* (must be smaller than 250). -*/ -#define LUAI_MAXVARS 200 - - -/* -@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function -@* (must be smaller than 250). -*/ -#define LUAI_MAXUPVALUES 60 - - -/* -@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. -*/ -#if 0 -#define LUAL_BUFFERSIZE BUFSIZ -#else -#define LUAL_BUFFERSIZE 512 -#endif - -/* }================================================================== */ - - - - -/* -** {================================================================== -@@ LUA_NUMBER is the type of numbers in Lua. -** CHANGE the following definitions only if you want to build Lua -** with a number type different from double. You may also need to -** change lua_number2int & lua_number2integer. -** =================================================================== -*/ - -#if 0 -#define LUA_NUMBER_DOUBLE -#define LUA_NUMBER double - -/* -@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' -@* over a number. -*/ -#define LUAI_UACNUMBER double -#else - -#define LUA_NUMBER int -#define LUAI_UACNUMBER int - -#endif - -/* -@@ LUA_NUMBER_SCAN is the format for reading numbers. -@@ LUA_NUMBER_FMT is the format for writing numbers. -@@ lua_number2str converts a number to a string. -@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. -@@ lua_str2number converts a string to a number. -*/ -#if 0 -#define LUA_NUMBER_SCAN "%lf" -#define LUA_NUMBER_FMT "%.14g" -#else -#define LUA_NUMBER_SCAN "%d" -#define LUA_NUMBER_FMT "%d" -#endif -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) -#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ -#define lua_str2number(s,p) strtod((s), (p)) - - -/* -@@ The luai_num* macros define the primitive operations over numbers. -*/ -#if defined(LUA_CORE) -#if 0 -#include -#endif -#define luai_numadd(a,b) ((a)+(b)) -#define luai_numsub(a,b) ((a)-(b)) -#define luai_nummul(a,b) ((a)*(b)) -#define luai_numdiv(a,b) ((a)/(b)) -#if 0 -#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) -#define luai_numpow(a,b) (pow(a,b)) -#else - -#define luai_nummod(a,b) ((a) % (b)) - -static inline LUA_NUMBER -luai_numpow (LUA_NUMBER a, LUA_NUMBER b) -{ - LUA_NUMBER c; - - c = 1; - while (b > 0) - { - c *= a; - b--; - } - - return c; -} - -#endif -#define luai_numunm(a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(a,b) ((a)<(b)) -#define luai_numle(a,b) ((a)<=(b)) -#define luai_numisnan(a) (!luai_numeq((a), (a))) -#endif - - -/* -@@ lua_number2int is a macro to convert lua_Number to int. -@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. -** CHANGE them if you know a faster way to convert a lua_Number to -** int (with any rounding method and without throwing errors) in your -** system. In Pentium machines, a naive typecast from double to int -** in C is extremely slow, so any alternative is worth trying. -*/ - -#if 0 -/* On a Pentium, resort to a trick */ -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ - (defined(__i386) || defined (_M_IX86) || defined(__i386__)) - -/* On a Microsoft compiler, use assembler */ -#if defined(_MSC_VER) - -#define lua_number2int(i,d) __asm fld d __asm fistp i -#define lua_number2integer(i,n) lua_number2int(i, n) - -/* the next trick should work on any Pentium, but sometimes clashes - with a DirectX idiosyncrasy */ -#else - -union luai_Cast { double l_d; long l_l; }; -#define lua_number2int(i,d) \ - { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } -#define lua_number2integer(i,n) lua_number2int(i, n) - -#endif - - -/* this option always works, but may be slow */ -#else -#define lua_number2int(i,d) ((i)=(int)(d)) -#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) - -#endif - -#else -#define lua_number2int(i,d) ((i)=(int)(d)) -#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) -#endif - -/* }================================================================== */ - - -/* -@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. -** CHANGE it if your system requires alignments larger than double. (For -** instance, if your system supports long doubles and they must be -** aligned in 16-byte boundaries, then you should add long double in the -** union.) Probably you do not need to change this. -*/ -#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } - - -/* -@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. -** CHANGE them if you prefer to use longjmp/setjmp even with C++ -** or if want/don't to use _longjmp/_setjmp instead of regular -** longjmp/setjmp. By default, Lua handles errors with exceptions when -** compiling as C++ code, with _longjmp/_setjmp when asked to use them, -** and with longjmp/setjmp otherwise. -*/ -#if defined(__cplusplus) -/* C++ exceptions */ -#define LUAI_THROW(L,c) throw(c) -#define LUAI_TRY(L,c,a) try { a } catch(...) \ - { if ((c)->status == 0) (c)->status = -1; } -#define luai_jmpbuf int /* dummy variable */ - -#elif defined(LUA_USE_ULONGJMP) -/* in Unix, try _longjmp/_setjmp (more efficient) */ -#define LUAI_THROW(L,c) _longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - -#else -/* default handling with long jumps */ -#define LUAI_THROW(L,c) longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - -#endif - - -/* -@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern -@* can do during pattern-matching. -** CHANGE it if you need more captures. This limit is arbitrary. -*/ -#define LUA_MAXCAPTURES 32 - - -/* -@@ lua_tmpnam is the function that the OS library uses to create a -@* temporary name. -@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. -** CHANGE them if you have an alternative to tmpnam (which is considered -** insecure) or if you want the original tmpnam anyway. By default, Lua -** uses tmpnam except when POSIX is available, where it uses mkstemp. -*/ -#if defined(loslib_c) || defined(luaall_c) - -#if defined(LUA_USE_MKSTEMP) -#include -#define LUA_TMPNAMBUFSIZE 32 -#define lua_tmpnam(b,e) { \ - strcpy(b, "/tmp/lua_XXXXXX"); \ - e = mkstemp(b); \ - if (e != -1) close(e); \ - e = (e == -1); } - -#else -#define LUA_TMPNAMBUFSIZE L_tmpnam -#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } -#endif - -#endif - - -/* -@@ lua_popen spawns a new process connected to the current one through -@* the file streams. -** CHANGE it if you have a way to implement it in your system. -*/ -#if defined(LUA_USE_POPEN) - -#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) -#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) - -#elif defined(LUA_WIN) - -#define lua_popen(L,c,m) ((void)L, _popen(c,m)) -#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) - -#else - -#define lua_popen(L,c,m) ((void)((void)c, m), \ - luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) -#define lua_pclose(L,file) ((void)((void)L, file), 0) - -#endif - -/* -@@ LUA_DL_* define which dynamic-library system Lua should use. -** CHANGE here if Lua has problems choosing the appropriate -** dynamic-library system for your platform (either Windows' DLL, Mac's -** dyld, or Unix's dlopen). If your system is some kind of Unix, there -** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for -** it. To use dlopen you also need to adapt the src/Makefile (probably -** adding -ldl to the linker options), so Lua does not select it -** automatically. (When you change the makefile to add -ldl, you must -** also add -DLUA_USE_DLOPEN.) -** If you do not want any kind of dynamic library, undefine all these -** options. -** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. -*/ -#if 0 -#if defined(LUA_USE_DLOPEN) -#define LUA_DL_DLOPEN -#endif - -#if defined(LUA_WIN) -#define LUA_DL_DLL -#endif -#endif - -/* -@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State -@* (the data goes just *before* the lua_State pointer). -** CHANGE (define) this if you really need that. This value must be -** a multiple of the maximum alignment required for your machine. -*/ -#define LUAI_EXTRASPACE 0 - - -/* -@@ luai_userstate* allow user-specific actions on threads. -** CHANGE them if you defined LUAI_EXTRASPACE and need to do something -** extra when a thread is created/deleted/resumed/yielded. -*/ -#define luai_userstateopen(L) ((void)L) -#define luai_userstateclose(L) ((void)L) -#define luai_userstatethread(L,L1) ((void)L) -#define luai_userstatefree(L) ((void)L) -#define luai_userstateresume(L,n) ((void)L) -#define luai_userstateyield(L,n) ((void)L) - - -/* -@@ LUA_INTFRMLEN is the length modifier for integer conversions -@* in 'string.format'. -@@ LUA_INTFRM_T is the integer type correspoding to the previous length -@* modifier. -** CHANGE them if your system supports long long or does not support long. -*/ - -#if defined(LUA_USELONGLONG) - -#define LUA_INTFRMLEN "ll" -#define LUA_INTFRM_T long long - -#else - -#define LUA_INTFRMLEN "l" -#define LUA_INTFRM_T long - -#endif - - - -/* =================================================================== */ - -/* -** Local configuration. You can use this space to add your redefinitions -** without modifying the main part of the file. -*/ - - - -#endif diff --git a/script/lua/lualib.h b/script/lua/lualib.h deleted file mode 100644 index e9ff9ba97..000000000 --- a/script/lua/lualib.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ -** Lua standard libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lualib_h -#define lualib_h - -#include "lua.h" - - -/* Key to file-handle type */ -#define LUA_FILEHANDLE "FILE*" - - -#define LUA_COLIBNAME "coroutine" -LUALIB_API int (luaopen_base) (lua_State *L); - -#define LUA_TABLIBNAME "table" -LUALIB_API int (luaopen_table) (lua_State *L); - -#define LUA_IOLIBNAME "io" -LUALIB_API int (luaopen_io) (lua_State *L); - -#define LUA_OSLIBNAME "os" -LUALIB_API int (luaopen_os) (lua_State *L); - -#define LUA_STRLIBNAME "string" -LUALIB_API int (luaopen_string) (lua_State *L); - -#define LUA_MATHLIBNAME "math" -LUALIB_API int (luaopen_math) (lua_State *L); - -#define LUA_DBLIBNAME "debug" -LUALIB_API int (luaopen_debug) (lua_State *L); - -#define LUA_LOADLIBNAME "package" -LUALIB_API int (luaopen_package) (lua_State *L); - - -/* open all previous libraries */ -LUALIB_API void (luaL_openlibs) (lua_State *L); - - - -#ifndef lua_assert -#define lua_assert(x) ((void)0) -#endif - - -#endif diff --git a/script/lua/lundump.c b/script/lua/lundump.c deleted file mode 100644 index 637d84237..000000000 --- a/script/lua/lundump.c +++ /dev/null @@ -1,229 +0,0 @@ -/* -** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#endif - -#define lundump_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstring.h" -#include "lundump.h" -#include "lzio.h" - -typedef struct { - lua_State* L; - ZIO* Z; - Mbuffer* b; - const char* name; -} LoadState; - -#ifdef LUAC_TRUST_BINARIES -#define IF(c,s) -#define error(S,s) -#else -#define IF(c,s) if (c) error(S,s) - -static void error(LoadState* S, const char* why) -{ - luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); - luaD_throw(S->L,LUA_ERRSYNTAX); -} -#endif - -#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) -#define LoadByte(S) (lu_byte)LoadChar(S) -#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) -#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) - -static void LoadBlock(LoadState* S, void* b, size_t size) -{ - size_t r=luaZ_read(S->Z,b,size); - IF (r!=0, "unexpected end"); -} - -static int LoadChar(LoadState* S) -{ - char x; - LoadVar(S,x); - return x; -} - -static int LoadInt(LoadState* S) -{ - int x; - LoadVar(S,x); - IF (x<0, "bad integer"); - return x; -} - -static lua_Number LoadNumber(LoadState* S) -{ - lua_Number x; - LoadVar(S,x); - return x; -} - -static TString* LoadString(LoadState* S) -{ - size_t size; - LoadVar(S,size); - if (size==0) - return NULL; - else - { - char* s=luaZ_openspace(S->L,S->b,size); - LoadBlock(S,s,size); - return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ - } -} - -static void LoadCode(LoadState* S, Proto* f) -{ - int n=LoadInt(S); - f->code=luaM_newvector(S->L,n,Instruction); - f->sizecode=n; - LoadVector(S,f->code,n,sizeof(Instruction)); -} - -static Proto* LoadFunction(LoadState* S, TString* p); - -static void LoadConstants(LoadState* S, Proto* f) -{ - int i,n; - n=LoadInt(S); - f->k=luaM_newvector(S->L,n,TValue); - f->sizek=n; - for (i=0; ik[i]); - for (i=0; ik[i]; - int t=LoadChar(S); - switch (t) - { - case LUA_TNIL: - setnilvalue(o); - break; - case LUA_TBOOLEAN: - setbvalue(o,LoadChar(S)!=0); - break; - case LUA_TNUMBER: - setnvalue(o,LoadNumber(S)); - break; - case LUA_TSTRING: - setsvalue2n(S->L,o,LoadString(S)); - break; - default: - error(S,"bad constant"); - break; - } - } - n=LoadInt(S); - f->p=luaM_newvector(S->L,n,Proto*); - f->sizep=n; - for (i=0; ip[i]=NULL; - for (i=0; ip[i]=LoadFunction(S,f->source); -} - -static void LoadDebug(LoadState* S, Proto* f) -{ - int i,n; - n=LoadInt(S); - f->lineinfo=luaM_newvector(S->L,n,int); - f->sizelineinfo=n; - LoadVector(S,f->lineinfo,n,sizeof(int)); - n=LoadInt(S); - f->locvars=luaM_newvector(S->L,n,LocVar); - f->sizelocvars=n; - for (i=0; ilocvars[i].varname=NULL; - for (i=0; ilocvars[i].varname=LoadString(S); - f->locvars[i].startpc=LoadInt(S); - f->locvars[i].endpc=LoadInt(S); - } - n=LoadInt(S); - f->upvalues=luaM_newvector(S->L,n,TString*); - f->sizeupvalues=n; - for (i=0; iupvalues[i]=NULL; - for (i=0; iupvalues[i]=LoadString(S); -} - -static Proto* LoadFunction(LoadState* S, TString* p) -{ - Proto* f; - if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); - f=luaF_newproto(S->L); - setptvalue2s(S->L,S->L->top,f); incr_top(S->L); - f->source=LoadString(S); if (f->source==NULL) f->source=p; - f->linedefined=LoadInt(S); - f->lastlinedefined=LoadInt(S); - f->nups=LoadByte(S); - f->numparams=LoadByte(S); - f->is_vararg=LoadByte(S); - f->maxstacksize=LoadByte(S); - LoadCode(S,f); - LoadConstants(S,f); - LoadDebug(S,f); - IF (!luaG_checkcode(f), "bad code"); - S->L->top--; - S->L->nCcalls--; - return f; -} - -static void LoadHeader(LoadState* S) -{ - char h[LUAC_HEADERSIZE]; - char s[LUAC_HEADERSIZE]; - luaU_header(h); - LoadBlock(S,s,LUAC_HEADERSIZE); - IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); -} - -/* -** load precompiled chunk -*/ -Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) -{ - LoadState S; - if (*name=='@' || *name=='=') - S.name=name+1; - else if (*name==LUA_SIGNATURE[0]) - S.name="binary string"; - else - S.name=name; - S.L=L; - S.Z=Z; - S.b=buff; - LoadHeader(&S); - return LoadFunction(&S,luaS_newliteral(L,"=?")); -} - -/* -* make header -*/ -void luaU_header (char* h) -{ - int x=1; - memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); - h+=sizeof(LUA_SIGNATURE)-1; - *h++=(char)LUAC_VERSION; - *h++=(char)LUAC_FORMAT; - *h++=(char)*(char*)&x; /* endianness */ - *h++=(char)sizeof(int); - *h++=(char)sizeof(size_t); - *h++=(char)sizeof(Instruction); - *h++=(char)sizeof(lua_Number); - *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ -} diff --git a/script/lua/lundump.h b/script/lua/lundump.h deleted file mode 100644 index c80189dbf..000000000 --- a/script/lua/lundump.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#ifndef lundump_h -#define lundump_h - -#include "lobject.h" -#include "lzio.h" - -/* load one chunk; from lundump.c */ -LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); - -/* make header; from lundump.c */ -LUAI_FUNC void luaU_header (char* h); - -/* dump one chunk; from ldump.c */ -LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); - -#ifdef luac_c -/* print one chunk; from print.c */ -LUAI_FUNC void luaU_print (const Proto* f, int full); -#endif - -/* for header of binary files -- this is Lua 5.1 */ -#define LUAC_VERSION 0x51 - -/* for header of binary files -- this is the official format */ -#define LUAC_FORMAT 0 - -/* size of header of binary files */ -#define LUAC_HEADERSIZE 12 - -#endif diff --git a/script/lua/lvm.c b/script/lua/lvm.c deleted file mode 100644 index 0ff1fa048..000000000 --- a/script/lua/lvm.c +++ /dev/null @@ -1,764 +0,0 @@ -/* -** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#include -#include -#endif - -#define lvm_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - - -/* limit for table tag-method chains (to avoid loops) */ -#define MAXTAGLOOP 100 - - -const TValue *luaV_tonumber (const TValue *obj, TValue *n) { - lua_Number num; - if (ttisnumber(obj)) return obj; - if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { - setnvalue(n, num); - return n; - } - else - return NULL; -} - - -int luaV_tostring (lua_State *L, StkId obj) { - if (!ttisnumber(obj)) - return 0; - else { - char s[LUAI_MAXNUMBER2STR]; - lua_Number n = nvalue(obj); - lua_number2str(s, n); - setsvalue2s(L, obj, luaS_new(L, s)); - return 1; - } -} - - -static void traceexec (lua_State *L, const Instruction *pc) { - lu_byte mask = L->hookmask; - const Instruction *oldpc = L->savedpc; - L->savedpc = pc; - if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { - resethookcount(L); - luaD_callhook(L, LUA_HOOKCOUNT, -1); - } - if (mask & LUA_MASKLINE) { - Proto *p = ci_func(L->ci)->l.p; - int npc = pcRel(pc, p); - int newline = getline(p, npc); - /* call linehook when enter a new function, when jump back (loop), - or when enter a new line */ - if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) - luaD_callhook(L, LUA_HOOKLINE, newline); - } -} - - -static void callTMres (lua_State *L, StkId res, const TValue *f, - const TValue *p1, const TValue *p2) { - ptrdiff_t result = savestack(L, res); - setobj2s(L, L->top, f); /* push function */ - setobj2s(L, L->top+1, p1); /* 1st argument */ - setobj2s(L, L->top+2, p2); /* 2nd argument */ - luaD_checkstack(L, 3); - L->top += 3; - luaD_call(L, L->top - 3, 1); - res = restorestack(L, result); - L->top--; - setobjs2s(L, res, L->top); -} - - - -static void callTM (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, const TValue *p3) { - setobj2s(L, L->top, f); /* push function */ - setobj2s(L, L->top+1, p1); /* 1st argument */ - setobj2s(L, L->top+2, p2); /* 2nd argument */ - setobj2s(L, L->top+3, p3); /* 3th argument */ - luaD_checkstack(L, 4); - L->top += 4; - luaD_call(L, L->top - 4, 0); -} - - -void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { - int loop; - for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t)) { /* `t' is a table? */ - Table *h = hvalue(t); - const TValue *res = luaH_get(h, key); /* do a primitive get */ - if (!ttisnil(res) || /* result is no nil? */ - (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ - setobj2s(L, val, res); - return; - } - /* else will try the tag method */ - } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) - luaG_typeerror(L, t, "index"); - if (ttisfunction(tm)) { - callTMres(L, val, tm, t, key); - return; - } - t = tm; /* else repeat with `tm' */ - } - luaG_runerror(L, "loop in gettable"); -} - - -void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { - int loop; - for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t)) { /* `t' is a table? */ - Table *h = hvalue(t); - TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ - if (!ttisnil(oldval) || /* result is no nil? */ - (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ - setobj2t(L, oldval, val); - luaC_barriert(L, h, val); - return; - } - /* else will try the tag method */ - } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) - luaG_typeerror(L, t, "index"); - if (ttisfunction(tm)) { - callTM(L, tm, t, key, val); - return; - } - t = tm; /* else repeat with `tm' */ - } - luaG_runerror(L, "loop in settable"); -} - - -static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event) { - const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ - if (ttisnil(tm)) - tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ - if (ttisnil(tm)) return 0; - callTMres(L, res, tm, p1, p2); - return 1; -} - - -static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, - TMS event) { - const TValue *tm1 = fasttm(L, mt1, event); - const TValue *tm2; - if (tm1 == NULL) return NULL; /* no metamethod */ - if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ - tm2 = fasttm(L, mt2, event); - if (tm2 == NULL) return NULL; /* no metamethod */ - if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ - return tm1; - return NULL; -} - - -static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, - TMS event) { - const TValue *tm1 = luaT_gettmbyobj(L, p1, event); - const TValue *tm2; - if (ttisnil(tm1)) return -1; /* no metamethod? */ - tm2 = luaT_gettmbyobj(L, p2, event); - if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ - return -1; - callTMres(L, L->top, tm1, p1, p2); - return !l_isfalse(L->top); -} - - -static int l_strcmp (const TString *ls, const TString *rs) { - const char *l = getstr(ls); - size_t ll = ls->tsv.len; - const char *r = getstr(rs); - size_t lr = rs->tsv.len; - for (;;) { - int temp = strcoll(l, r); - if (temp != 0) return temp; - else { /* strings are equal up to a `\0' */ - size_t len = strlen(l); /* index of first `\0' in both strings */ - if (len == lr) /* r is finished? */ - return (len == ll) ? 0 : 1; - else if (len == ll) /* l is finished? */ - return -1; /* l is smaller than r (because r is not finished) */ - /* both strings longer than `len'; go on comparing (after the `\0') */ - len++; - l += len; ll -= len; r += len; lr -= len; - } - } -} - - -int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { - int res; - if (ttype(l) != ttype(r)) - return luaG_ordererror(L, l, r); - else if (ttisnumber(l)) - return luai_numlt(nvalue(l), nvalue(r)); - else if (ttisstring(l)) - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; - else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) - return res; - return luaG_ordererror(L, l, r); -} - - -static int lessequal (lua_State *L, const TValue *l, const TValue *r) { - int res; - if (ttype(l) != ttype(r)) - return luaG_ordererror(L, l, r); - else if (ttisnumber(l)) - return luai_numle(nvalue(l), nvalue(r)); - else if (ttisstring(l)) - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; - else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ - return res; - else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ - return !res; - return luaG_ordererror(L, l, r); -} - - -int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { - const TValue *tm; - lua_assert(ttype(t1) == ttype(t2)); - switch (ttype(t1)) { - case LUA_TNIL: return 1; - case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); - case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ - case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); - case LUA_TUSERDATA: { - if (uvalue(t1) == uvalue(t2)) return 1; - tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, - TM_EQ); - break; /* will try TM */ - } - case LUA_TTABLE: { - if (hvalue(t1) == hvalue(t2)) return 1; - tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); - break; /* will try TM */ - } - default: return gcvalue(t1) == gcvalue(t2); - } - if (tm == NULL) return 0; /* no TM? */ - callTMres(L, L->top, tm, t1, t2); /* call TM */ - return !l_isfalse(L->top); -} - - -void luaV_concat (lua_State *L, int total, int last) { - do { - StkId top = L->base + last + 1; - int n = 2; /* number of elements handled in this pass (at least 2) */ - if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { - if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) - luaG_concaterror(L, top-2, top-1); - } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ - (void)tostring(L, top - 2); /* result is first op (as string) */ - else { - /* at least two string values; get as many as possible */ - size_t tl = tsvalue(top-1)->len; - char *buffer; - int i; - /* collect total length */ - for (n = 1; n < total && tostring(L, top-n-1); n++) { - size_t l = tsvalue(top-n-1)->len; - if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); - tl += l; - } - buffer = luaZ_openspace(L, &G(L)->buff, tl); - tl = 0; - for (i=n; i>0; i--) { /* concat all strings */ - size_t l = tsvalue(top-i)->len; - memcpy(buffer+tl, svalue(top-i), l); - tl += l; - } - setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); - } - total -= n-1; /* got `n' strings to create 1 new */ - last -= n-1; - } while (total > 1); /* repeat until only 1 result left */ -} - - -static void Arith (lua_State *L, StkId ra, const TValue *rb, - const TValue *rc, TMS op) { - TValue tempb, tempc; - const TValue *b, *c; - if ((b = luaV_tonumber(rb, &tempb)) != NULL && - (c = luaV_tonumber(rc, &tempc)) != NULL) { - lua_Number nb = nvalue(b), nc = nvalue(c); - switch (op) { - case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; - case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; - case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; - case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; - case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; - case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; - case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; - default: lua_assert(0); break; - } - } - else if (!call_binTM(L, rb, rc, ra, op)) - luaG_aritherror(L, rb, rc); -} - - - -/* -** some macros for common tasks in `luaV_execute' -*/ - -#define runtime_check(L, c) { if (!(c)) break; } - -#define RA(i) (base+GETARG_A(i)) -/* to be used after possible stack reallocation */ -#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) -#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) -#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) -#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) -#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) - - -#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} - - -#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } - - -#define arith_op(op,tm) { \ - TValue *rb = RKB(i); \ - TValue *rc = RKC(i); \ - if (ttisnumber(rb) && ttisnumber(rc)) { \ - lua_Number nb = nvalue(rb), nc = nvalue(rc); \ - setnvalue(ra, op(nb, nc)); \ - } \ - else \ - Protect(Arith(L, ra, rb, rc, tm)); \ - } - - - -void luaV_execute (lua_State *L, int nexeccalls) { - LClosure *cl; - StkId base; - TValue *k; - const Instruction *pc; - reentry: /* entry point */ - lua_assert(isLua(L->ci)); - pc = L->savedpc; - cl = &clvalue(L->ci->func)->l; - base = L->base; - k = cl->p->k; - /* main loop of interpreter */ - for (;;) { - const Instruction i = *pc++; - StkId ra; - if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && - (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { - traceexec(L, pc); - if (L->status == LUA_YIELD) { /* did hook yield? */ - L->savedpc = pc - 1; - return; - } - base = L->base; - } - /* warning!! several calls may realloc the stack and invalidate `ra' */ - ra = RA(i); - lua_assert(base == L->base && L->base == L->ci->base); - lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); - lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); - switch (GET_OPCODE(i)) { - case OP_MOVE: { - setobjs2s(L, ra, RB(i)); - continue; - } - case OP_LOADK: { - setobj2s(L, ra, KBx(i)); - continue; - } - case OP_LOADBOOL: { - setbvalue(ra, GETARG_B(i)); - if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ - continue; - } - case OP_LOADNIL: { - TValue *rb = RB(i); - do { - setnilvalue(rb--); - } while (rb >= ra); - continue; - } - case OP_GETUPVAL: { - int b = GETARG_B(i); - setobj2s(L, ra, cl->upvals[b]->v); - continue; - } - case OP_GETGLOBAL: { - TValue g; - TValue *rb = KBx(i); - sethvalue(L, &g, cl->env); - lua_assert(ttisstring(rb)); - Protect(luaV_gettable(L, &g, rb, ra)); - continue; - } - case OP_GETTABLE: { - Protect(luaV_gettable(L, RB(i), RKC(i), ra)); - continue; - } - case OP_SETGLOBAL: { - TValue g; - sethvalue(L, &g, cl->env); - lua_assert(ttisstring(KBx(i))); - Protect(luaV_settable(L, &g, KBx(i), ra)); - continue; - } - case OP_SETUPVAL: { - UpVal *uv = cl->upvals[GETARG_B(i)]; - setobj(L, uv->v, ra); - luaC_barrier(L, uv, ra); - continue; - } - case OP_SETTABLE: { - Protect(luaV_settable(L, ra, RKB(i), RKC(i))); - continue; - } - case OP_NEWTABLE: { - int b = GETARG_B(i); - int c = GETARG_C(i); - sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); - Protect(luaC_checkGC(L)); - continue; - } - case OP_SELF: { - StkId rb = RB(i); - setobjs2s(L, ra+1, rb); - Protect(luaV_gettable(L, rb, RKC(i), ra)); - continue; - } - case OP_ADD: { - arith_op(luai_numadd, TM_ADD); - continue; - } - case OP_SUB: { - arith_op(luai_numsub, TM_SUB); - continue; - } - case OP_MUL: { - arith_op(luai_nummul, TM_MUL); - continue; - } - case OP_DIV: { - arith_op(luai_numdiv, TM_DIV); - continue; - } - case OP_MOD: { - arith_op(luai_nummod, TM_MOD); - continue; - } - case OP_POW: { - arith_op(luai_numpow, TM_POW); - continue; - } - case OP_UNM: { - TValue *rb = RB(i); - if (ttisnumber(rb)) { - lua_Number nb = nvalue(rb); - setnvalue(ra, luai_numunm(nb)); - } - else { - Protect(Arith(L, ra, rb, rb, TM_UNM)); - } - continue; - } - case OP_NOT: { - int res = l_isfalse(RB(i)); /* next assignment may change this value */ - setbvalue(ra, res); - continue; - } - case OP_LEN: { - const TValue *rb = RB(i); - switch (ttype(rb)) { - case LUA_TTABLE: { - setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); - break; - } - case LUA_TSTRING: { - setnvalue(ra, cast_num(tsvalue(rb)->len)); - break; - } - default: { /* try metamethod */ - Protect( - if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) - luaG_typeerror(L, rb, "get length of"); - ) - } - } - continue; - } - case OP_CONCAT: { - int b = GETARG_B(i); - int c = GETARG_C(i); - Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); - setobjs2s(L, RA(i), base+b); - continue; - } - case OP_JMP: { - dojump(L, pc, GETARG_sBx(i)); - continue; - } - case OP_EQ: { - TValue *rb = RKB(i); - TValue *rc = RKC(i); - Protect( - if (equalobj(L, rb, rc) == GETARG_A(i)) - dojump(L, pc, GETARG_sBx(*pc)); - ) - pc++; - continue; - } - case OP_LT: { - Protect( - if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) - dojump(L, pc, GETARG_sBx(*pc)); - ) - pc++; - continue; - } - case OP_LE: { - Protect( - if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) - dojump(L, pc, GETARG_sBx(*pc)); - ) - pc++; - continue; - } - case OP_TEST: { - if (l_isfalse(ra) != GETARG_C(i)) - dojump(L, pc, GETARG_sBx(*pc)); - pc++; - continue; - } - case OP_TESTSET: { - TValue *rb = RB(i); - if (l_isfalse(rb) != GETARG_C(i)) { - setobjs2s(L, ra, rb); - dojump(L, pc, GETARG_sBx(*pc)); - } - pc++; - continue; - } - case OP_CALL: { - int b = GETARG_B(i); - int nresults = GETARG_C(i) - 1; - if (b != 0) L->top = ra+b; /* else previous instruction set top */ - L->savedpc = pc; - switch (luaD_precall(L, ra, nresults)) { - case PCRLUA: { - nexeccalls++; - goto reentry; /* restart luaV_execute over new Lua function */ - } - case PCRC: { - /* it was a C function (`precall' called it); adjust results */ - if (nresults >= 0) L->top = L->ci->top; - base = L->base; - continue; - } - default: { - return; /* yield */ - } - } - } - case OP_TAILCALL: { - int b = GETARG_B(i); - if (b != 0) L->top = ra+b; /* else previous instruction set top */ - L->savedpc = pc; - lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); - switch (luaD_precall(L, ra, LUA_MULTRET)) { - case PCRLUA: { - /* tail call: put new frame in place of previous one */ - CallInfo *ci = L->ci - 1; /* previous frame */ - int aux; - StkId func = ci->func; - StkId pfunc = (ci+1)->func; /* previous function index */ - if (L->openupval) luaF_close(L, ci->base); - L->base = ci->base = ci->func + ((ci+1)->base - pfunc); - for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ - setobjs2s(L, func+aux, pfunc+aux); - ci->top = L->top = func+aux; /* correct top */ - lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); - ci->savedpc = L->savedpc; - ci->tailcalls++; /* one more call lost */ - L->ci--; /* remove new frame */ - goto reentry; - } - case PCRC: { /* it was a C function (`precall' called it) */ - base = L->base; - continue; - } - default: { - return; /* yield */ - } - } - } - case OP_RETURN: { - int b = GETARG_B(i); - if (b != 0) L->top = ra+b-1; - if (L->openupval) luaF_close(L, base); - L->savedpc = pc; - b = luaD_poscall(L, ra); - if (--nexeccalls == 0) /* was previous function running `here'? */ - return; /* no: return */ - else { /* yes: continue its execution */ - if (b) L->top = L->ci->top; - lua_assert(isLua(L->ci)); - lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); - goto reentry; - } - } - case OP_FORLOOP: { - lua_Number step = nvalue(ra+2); - lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ - lua_Number limit = nvalue(ra+1); - if (luai_numlt(0, step) ? luai_numle(idx, limit) - : luai_numle(limit, idx)) { - dojump(L, pc, GETARG_sBx(i)); /* jump back */ - setnvalue(ra, idx); /* update internal index... */ - setnvalue(ra+3, idx); /* ...and external index */ - } - continue; - } - case OP_FORPREP: { - const TValue *init = ra; - const TValue *plimit = ra+1; - const TValue *pstep = ra+2; - L->savedpc = pc; /* next steps may throw errors */ - if (!tonumber(init, ra)) - luaG_runerror(L, LUA_QL("for") " initial value must be a number"); - else if (!tonumber(plimit, ra+1)) - luaG_runerror(L, LUA_QL("for") " limit must be a number"); - else if (!tonumber(pstep, ra+2)) - luaG_runerror(L, LUA_QL("for") " step must be a number"); - setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); - dojump(L, pc, GETARG_sBx(i)); - continue; - } - case OP_TFORLOOP: { - StkId cb = ra + 3; /* call base */ - setobjs2s(L, cb+2, ra+2); - setobjs2s(L, cb+1, ra+1); - setobjs2s(L, cb, ra); - L->top = cb+3; /* func. + 2 args (state and index) */ - Protect(luaD_call(L, cb, GETARG_C(i))); - L->top = L->ci->top; - cb = RA(i) + 3; /* previous call may change the stack */ - if (!ttisnil(cb)) { /* continue loop? */ - setobjs2s(L, cb-1, cb); /* save control variable */ - dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ - } - pc++; - continue; - } - case OP_SETLIST: { - int n = GETARG_B(i); - int c = GETARG_C(i); - int last; - Table *h; - if (n == 0) { - n = cast_int(L->top - ra) - 1; - L->top = L->ci->top; - } - if (c == 0) c = cast_int(*pc++); - runtime_check(L, ttistable(ra)); - h = hvalue(ra); - last = ((c-1)*LFIELDS_PER_FLUSH) + n; - if (last > h->sizearray) /* needs more space? */ - luaH_resizearray(L, h, last); /* pre-alloc it at once */ - for (; n > 0; n--) { - TValue *val = ra+n; - setobj2t(L, luaH_setnum(L, h, last--), val); - luaC_barriert(L, h, val); - } - continue; - } - case OP_CLOSE: { - luaF_close(L, ra); - continue; - } - case OP_CLOSURE: { - Proto *p; - Closure *ncl; - int nup, j; - p = cl->p->p[GETARG_Bx(i)]; - nup = p->nups; - ncl = luaF_newLclosure(L, nup, cl->env); - ncl->l.p = p; - for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; - else { - lua_assert(GET_OPCODE(*pc) == OP_MOVE); - ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); - } - } - setclvalue(L, ra, ncl); - Protect(luaC_checkGC(L)); - continue; - } - case OP_VARARG: { - int b = GETARG_B(i) - 1; - int j; - CallInfo *ci = L->ci; - int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; - if (b == LUA_MULTRET) { - Protect(luaD_checkstack(L, n)); - ra = RA(i); /* previous call may change the stack */ - b = n; - L->top = ra + n; - } - for (j = 0; j < b; j++) { - if (j < n) { - setobjs2s(L, ra + j, ci->base - n + j); - } - else { - setnilvalue(ra + j); - } - } - continue; - } - } - } -} - diff --git a/script/lua/lvm.h b/script/lua/lvm.h deleted file mode 100644 index bfe4f5678..000000000 --- a/script/lua/lvm.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lvm_h -#define lvm_h - - -#include "ldo.h" -#include "lobject.h" -#include "ltm.h" - - -#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) - -#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ - (((o) = luaV_tonumber(o,n)) != NULL)) - -#define equalobj(L,o1,o2) \ - (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) - - -LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); -LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); -LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); -LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, - StkId val); -LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, - StkId val); -LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); -LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); - -#endif diff --git a/script/lua/lzio.c b/script/lua/lzio.c deleted file mode 100644 index 3ccba193c..000000000 --- a/script/lua/lzio.c +++ /dev/null @@ -1,83 +0,0 @@ -/* -** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ -** a generic input stream interface -** See Copyright Notice in lua.h -*/ - -#if 0 -#include -#endif - -#define lzio_c -#define LUA_CORE - -#include "lua.h" - -#include "llimits.h" -#include "lmem.h" -#include "lstate.h" -#include "lzio.h" - - -int luaZ_fill (ZIO *z) { - size_t size; - lua_State *L = z->L; - const char *buff; - lua_unlock(L); - buff = z->reader(L, z->data, &size); - lua_lock(L); - if (buff == NULL || size == 0) return EOZ; - z->n = size - 1; - z->p = buff; - return char2int(*(z->p++)); -} - - -int luaZ_lookahead (ZIO *z) { - if (z->n == 0) { - if (luaZ_fill(z) == EOZ) - return EOZ; - else { - z->n++; /* luaZ_fill removed first byte; put back it */ - z->p--; - } - } - return char2int(*z->p); -} - - -void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { - z->L = L; - z->reader = reader; - z->data = data; - z->n = 0; - z->p = NULL; -} - - -/* --------------------------------------------------------------- read --- */ -size_t luaZ_read (ZIO *z, void *b, size_t n) { - while (n) { - size_t m; - if (luaZ_lookahead(z) == EOZ) - return n; /* return number of missing bytes */ - m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ - memcpy(b, z->p, m); - z->n -= m; - z->p += m; - b = (char *)b + m; - n -= m; - } - return 0; -} - -/* ------------------------------------------------------------------------ */ -char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { - if (n > buff->buffsize) { - if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; - luaZ_resizebuffer(L, buff, n); - } - return buff->buffer; -} - - diff --git a/script/lua/lzio.h b/script/lua/lzio.h deleted file mode 100644 index 51d695d8c..000000000 --- a/script/lua/lzio.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ -** Buffered streams -** See Copyright Notice in lua.h -*/ - - -#ifndef lzio_h -#define lzio_h - -#include "lua.h" - -#include "lmem.h" - - -#define EOZ (-1) /* end of stream */ - -typedef struct Zio ZIO; - -#define char2int(c) cast(int, cast(unsigned char, (c))) - -#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) - -typedef struct Mbuffer { - char *buffer; - size_t n; - size_t buffsize; -} Mbuffer; - -#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) - -#define luaZ_buffer(buff) ((buff)->buffer) -#define luaZ_sizebuffer(buff) ((buff)->buffsize) -#define luaZ_bufflen(buff) ((buff)->n) - -#define luaZ_resetbuffer(buff) ((buff)->n = 0) - - -#define luaZ_resizebuffer(L, buff, size) \ - (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ - (buff)->buffsize = size) - -#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) - - -LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); -LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, - void *data); -LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ -LUAI_FUNC int luaZ_lookahead (ZIO *z); - - - -/* --------- Private Part ------------------ */ - -struct Zio { - size_t n; /* bytes still unread */ - const char *p; /* current position in buffer */ - lua_Reader reader; - void* data; /* additional data */ - lua_State *L; /* Lua state (for reader) */ -}; - - -LUAI_FUNC int luaZ_fill (ZIO *z); - -#endif diff --git a/util/osdetect.lua b/util/osdetect.lua deleted file mode 100644 index 38a90993d..000000000 --- a/util/osdetect.lua +++ /dev/null @@ -1,111 +0,0 @@ -#!lua --- --- Copyright (C) 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 . --- - -function enum_device (device, fs, uuid) - local root - local title - local source - local kernels = {} - local kernel_num = 0 - - local function enum_file (name) - local version - - version = string.match (name, "vmlinuz%-(.*)") - if (version ~= nil) then - table.insert (kernels, version) - kernel_num = kernel_num + 1 - end - end - - local function sort_kernel (first, second) - local a1, a2, a3, a4, b1, b2, b3, b4 - - a1, a2, a3, a4 = string.match (first, "(%d+)%.?(%d*).?(%d*)%-?(%d*)") - b1, b2, b3, b4 = string.match (second, "(%d+)%.?(%d*).?(%d*)%-?(%d*)") - return (a1 > b1) or (a2 > b2) or (a3 > b3) or (a4 < b4); - end - - root = "(" .. device .. ")/" - source = "root (" .. device .. ")\nchainloader +1" - title = nil - if (grub.file_exist (root .. "bootmgr") and - grub.file_exist (root .. "boot/bcd")) then - title = "Windows Vista bootmgr" - elseif (grub.file_exist (root .. "ntldr") and - grub.file_exist (root .. "ntdetect.com") and - grub.file_exist (root .. "boot.ini")) then - title = "Windows NT/2000/XP loader" - elseif (grub.file_exist (root .. "windows/win.com")) then - title = "Windows 98/ME" - elseif (grub.file_exist (root .. "io.sys") and - grub.file_exist (root .. "command.com")) then - title = "MS-DOS" - elseif (grub.file_exist (root .. "kernel.sys")) then - title = "FreeDOS" - elseif (grub.file_exist (root .. "boot/loader") and - grub.file_exist (root .. "boot/device.hints")) then - source = "root (" .. device .. ")\nfreebsd /boot/loader" .. - "\nfreebsd_loadenv /boot/device.hints" - title = "FreeBSD" - else - grub.enum_file (enum_file, root .. "boot") - if kernel_num ~= 0 then - table.sort (kernels, sort_kernel) - for i = 1, kernel_num do - local initrd - - title = "Linux " .. kernels[i] - source = "root (" .. device .. - ")\nlinux /boot/vmlinuz-" .. kernels[i] .. - " root=UUID=" .. uuid .. " ro" - - if grub.file_exist (root .. "boot/initrd-" .. - kernels[i] .. ".img") then - initrd = "\ninitrd /boot/initrd-" .. kernels[i] .. ".img" - elseif grub.file_exist (root .. "boot/initrd.img-" .. kernels[i]) then - initrd = "\ninitrd /boot/initrd.img-" .. kernels[i] - elseif grub.file_exist (root .. "boot/initrd-" .. kernels[i]) then - initrd = "\ninitrd /boot/initrd-" .. kernels[i] - else - initrd = "" - end - - grub.add_menu (source .. initrd, title) - grub.add_menu (source .. " single" .. initrd, - title .. " (single-user mode)") - end - return 0 - end - end - - if title == nil then - local partition = string.match (device, ".*,(%d+)") - - if (partition ~= nil) and (tonumber (partition) > 4) then - return 0 - end - - title = "Other OS" - end - - grub.add_menu (source, title) - return 0 -end - -grub.enum_device (enum_device) From 0e51c3a7d4d5b9ae0a7caeea1d71440e2714dfe6 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 28 Sep 2009 14:24:43 +0000 Subject: [PATCH 010/165] 2009-09-28 Robert Millan Do not automatically install headers. * Makefile.in (include_DATA): Remove. Update all users. --- ChangeLog | 6 ++++++ Makefile.in | 21 --------------------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index aca4ef788..394470abc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-09-28 Robert Millan + + Do not automatically install headers. + + * Makefile.in (include_DATA): Remove. Update all users. + 2009-09-26 Robert Millan * conf/common.rmk (pkglib_MODULES): Remove `lua.mod'. diff --git a/Makefile.in b/Makefile.in index 363d696f1..0c5d0abb3 100644 --- a/Makefile.in +++ b/Makefile.in @@ -233,8 +233,6 @@ build_env.mk: Makefile echo "COMMON_LDFLAGS=$(COMMON_LDFLAGS)"\ ) > $@ pkglib_BUILDDIR += config.h grub_script.tab.h -include_DATA += $(shell find $(srcdir)/include -name \*.h | sed -e "s,^$(srcdir)/,,g") \ - include/grub/cpu include/grub/machine all-local: $(PROGRAMS) $(PKGLIB) $(PKGDATA) $(SCRIPTS) $(INFOS) $(MKFILES) @@ -249,20 +247,6 @@ install-local: all dest="`echo $$file | sed 's,.*/,,'`"; \ $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(pkglibdir)/$$dest; \ done - $(SHELL) $(mkinstalldirs) $(DESTDIR)$(includedir) - @list='$(include_DATA)'; \ - for file in $$list; do \ - if test -e "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ - dest="`echo $$file | sed 's,include/,,'`"; \ - destdir="`echo $$dest | sed 's,[^/]*$$,,g'`"; \ - $(SHELL) $(mkinstalldirs) $(DESTDIR)$(includedir)/$$destdir; \ - if test -f "$$dir$$file"; then \ - $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(includedir)/$$dest; \ - elif test -L "$$dir$$file"; then \ - rm -rf $(DESTDIR)$(includedir)/$$dest && \ - cp -fR $$dir$$file $(DESTDIR)$(includedir)/$$dest; \ - fi; \ - done $(SHELL) $(mkinstalldirs) $(DESTDIR)$(pkgdatadir) @list='$(PKGDATA)'; \ for file in $$list; do \ @@ -354,11 +338,6 @@ uninstall: dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ rm -f $(DESTDIR)$(sysconfdir)/grub.d/$$dest; \ done - @list='$(include_DATA)'; \ - for file in $$list; do \ - dest="`echo $$file | sed 's,include/,,'`"; \ - rm -f $(DESTDIR)$(includedir)/$$dest; \ - done @list='$(lib_SCRIPTS)'; \ for file in $$list; do \ dest="`echo $$file | sed 's,.*/,,'`"; \ From 50dcabcf9485c83aef80226ccdd1bb8ebb6d0d04 Mon Sep 17 00:00:00 2001 From: cjwatson Date: Thu, 1 Oct 2009 18:22:43 +0000 Subject: [PATCH 011/165] 2009-10-01 Colin Watson * util/grub-editenv.c (create_envblk_file): Write new block with a .new suffix and then rename it into place, to ensure atomic creation. --- ChangeLog | 6 ++++++ util/grub-editenv.c | 12 +++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 394470abc..b2d1a7085 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-01 Colin Watson + + * util/grub-editenv.c (create_envblk_file): Write new block with a + .new suffix and then rename it into place, to ensure atomic + creation. + 2009-09-28 Robert Millan Do not automatically install headers. diff --git a/util/grub-editenv.c b/util/grub-editenv.c index 6d1234050..a8dc137c5 100644 --- a/util/grub-editenv.c +++ b/util/grub-editenv.c @@ -95,25 +95,31 @@ create_envblk_file (const char *name) { FILE *fp; char *buf; + char *namenew; buf = malloc (DEFAULT_ENVBLK_SIZE); if (! buf) grub_util_error ("out of memory"); - fp = fopen (name, "wb"); + asprintf (&namenew, "%s.new", name); + fp = fopen (namenew, "wb"); if (! fp) - grub_util_error ("cannot open the file %s", name); + grub_util_error ("cannot open the file %s", namenew); memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1); memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', DEFAULT_ENVBLK_SIZE - sizeof (GRUB_ENVBLK_SIGNATURE) + 1); if (fwrite (buf, 1, DEFAULT_ENVBLK_SIZE, fp) != DEFAULT_ENVBLK_SIZE) - grub_util_error ("cannot write to the file %s", name); + grub_util_error ("cannot write to the file %s", namenew); fsync (fileno (fp)); free (buf); fclose (fp); + + if (rename (namenew, name) < 0) + grub_util_error ("cannot rename the file %s to %s", namenew, name); + free (namenew); } static grub_envblk_t From e8ee83c046b99c15e9f425be7a37b110ced631fb Mon Sep 17 00:00:00 2001 From: robertmh Date: Fri, 2 Oct 2009 23:13:38 +0000 Subject: [PATCH 012/165] 2009-10-03 Robert Millan Resync grub-mkdevicemap in x86_64-efi. * conf/x86_64-efi.rmk (sbin_UTILITIES): Enable `grub-mkdevicemap'. (grub_mkdevicemap_SOURCES): Add missing `util/deviceiter.c' and `util/devicemap.c'. --- ChangeLog | 8 ++++++++ conf/x86_64-efi.rmk | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b2d1a7085..70adb66fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-10-03 Robert Millan + + Resync grub-mkdevicemap in x86_64-efi. + + * conf/x86_64-efi.rmk (sbin_UTILITIES): Enable `grub-mkdevicemap'. + (grub_mkdevicemap_SOURCES): Add missing `util/deviceiter.c' and + `util/devicemap.c'. + 2009-10-01 Colin Watson * util/grub-editenv.c (create_envblk_file): Write new block with a diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk index 934cd7284..5be1b404f 100644 --- a/conf/x86_64-efi.rmk +++ b/conf/x86_64-efi.rmk @@ -9,7 +9,7 @@ script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Utilities. bin_UTILITIES = grub-mkimage -#sbin_UTILITIES = grub-mkdevicemap +sbin_UTILITIES = grub-mkdevicemap #ifeq ($(enable_grub_emu), yes) #sbin_UTILITIES += grub-emu #endif @@ -27,7 +27,8 @@ grub_mkimage_SOURCES = util/i386/efi/grub-mkimage.c util/misc.c \ # kern/fs.c kern/env.c fs/fshelp.c # For grub-mkdevicemap. -grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/misc.c +grub_mkdevicemap_SOURCES = util/grub-mkdevicemap.c util/deviceiter.c \ + util/devicemap.c util/misc.c # For grub-emu. util/grub-emu.c_DEPENDENCIES = grub_emu_init.h From da25306d46d783810487d6663bcbfcacf1ef5d74 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 5 Oct 2009 17:56:33 +0000 Subject: [PATCH 013/165] 2009-10-05 Robert Millan * configure.ac: Bump version to 1.97~beta4. --- ChangeLog | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 70adb66fb..e27246856 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-05 Robert Millan + + * configure.ac: Bump version to 1.97~beta4. + 2009-10-03 Robert Millan Resync grub-mkdevicemap in x86_64-efi. diff --git a/configure.ac b/configure.ac index 4d221b4d6..3e4da66c8 100644 --- a/configure.ac +++ b/configure.ac @@ -31,7 +31,7 @@ dnl (such as TARGET_CC, TARGET_CFLAGS, etc.) are used for the target dnl type. -AC_INIT([GRUB],[1.97~beta3],[bug-grub@gnu.org]) +AC_INIT([GRUB],[1.97~beta4],[bug-grub@gnu.org]) AC_PREREQ(2.59) AC_CONFIG_SRCDIR([include/grub/dl.h]) AC_CONFIG_HEADER([config.h]) From d244281ce6eb84ff0978c0457624f43ad6cced2e Mon Sep 17 00:00:00 2001 From: cjwatson Date: Mon, 5 Oct 2009 23:33:36 +0000 Subject: [PATCH 014/165] 2009-10-06 Colin Watson * util/i386/pc/grub-install.in: Source ${libdir}/grub/grub-mkconfig_lib before option processing, in order that the --grub-probe option will work. * util/sparc64/ieee1275/grub-install.in: Likewise. --- ChangeLog | 7 +++++++ util/i386/pc/grub-install.in | 6 +++--- util/sparc64/ieee1275/grub-install.in | 6 +++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index e27246856..a07270342 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-10-06 Colin Watson + + * util/i386/pc/grub-install.in: Source + ${libdir}/grub/grub-mkconfig_lib before option processing, in order + that the --grub-probe option will work. + * util/sparc64/ieee1275/grub-install.in: Likewise. + 2009-10-05 Robert Millan * configure.ac: Bump version to 1.97~beta4. diff --git a/util/i386/pc/grub-install.in b/util/i386/pc/grub-install.in index 8ceb811dd..69028b662 100644 --- a/util/i386/pc/grub-install.in +++ b/util/i386/pc/grub-install.in @@ -31,6 +31,9 @@ target_cpu=@target_cpu@ platform=@platform@ pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` +# for make_system_path_relative_to_its_root() +. ${libdir}/grub/grub-mkconfig_lib + grub_setup=${sbindir}/`echo grub-setup | sed ${transform}` if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` @@ -141,9 +144,6 @@ for option in "$@"; do esac done -# for make_system_path_relative_to_its_root() -. ${libdir}/grub/grub-mkconfig_lib - if test "x$install_device" = x; then echo "install_device not specified." 1>&2 usage diff --git a/util/sparc64/ieee1275/grub-install.in b/util/sparc64/ieee1275/grub-install.in index 5cfb858d7..a03869cb3 100644 --- a/util/sparc64/ieee1275/grub-install.in +++ b/util/sparc64/ieee1275/grub-install.in @@ -31,6 +31,9 @@ target_cpu=@target_cpu@ platform=@platform@ pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` +# for make_system_path_relative_to_its_root() +. ${libdir}/grub/grub-mkconfig_lib + grub_setup=${sbindir}/`echo grub-setup | sed ${transform}` grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` @@ -117,9 +120,6 @@ for option in "$@"; do esac done -# for make_system_path_relative_to_its_root() -. ${libdir}/grub/grub-mkconfig_lib - if test "x$install_device" = x; then echo "install_device not specified." 1>&2 usage From 83b65c4afb32b41d22155d1410b1e94737b47c99 Mon Sep 17 00:00:00 2001 From: cjwatson Date: Mon, 5 Oct 2009 23:55:48 +0000 Subject: [PATCH 015/165] 2009-10-06 Colin Watson * Makefile.in: Don't set info_INFOS unless makeinfo was found. Fixes bug #27602. --- ChangeLog | 5 +++++ Makefile.in | 2 ++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index a07270342..a829dd77e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-10-06 Colin Watson + + * Makefile.in: Don't set info_INFOS unless makeinfo was found. + Fixes bug #27602. + 2009-10-06 Colin Watson * util/i386/pc/grub-install.in: Source diff --git a/Makefile.in b/Makefile.in index 0c5d0abb3..304d1c7fd 100644 --- a/Makefile.in +++ b/Makefile.in @@ -174,7 +174,9 @@ handler.lst: $(HANDLERFILES) parttool.lst: $(PARTTOOLFILES) cat $^ /dev/null | sort | uniq > $@ +ifneq (true, $(MAKEINFO)) info_INFOS += docs/grub.info +endif MOSTLYCLEANFILES += vti.tmp MAINTAINER_CLEANFILES += docs/stamp-vti docs/version.texi From 186e7cf23b2b38e469a28149e46172f3904d49d8 Mon Sep 17 00:00:00 2001 From: cjwatson Date: Tue, 6 Oct 2009 00:04:32 +0000 Subject: [PATCH 016/165] 2009-10-06 Colin Watson * Makefile.in (docs/stamp-vti): Depend on configure.ac as well, so that version.texi is rebuilt on version number changes. --- ChangeLog | 5 +++++ Makefile.in | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a829dd77e..c02e3a6e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-10-06 Colin Watson + + * Makefile.in (docs/stamp-vti): Depend on configure.ac as well, so + that version.texi is rebuilt on version number changes. + 2009-10-06 Colin Watson * Makefile.in: Don't set info_INFOS unless makeinfo was found. diff --git a/Makefile.in b/Makefile.in index 304d1c7fd..e0edbdb04 100644 --- a/Makefile.in +++ b/Makefile.in @@ -181,7 +181,7 @@ endif MOSTLYCLEANFILES += vti.tmp MAINTAINER_CLEANFILES += docs/stamp-vti docs/version.texi docs/version.texi: docs/stamp-vti -docs/stamp-vti: docs/grub.texi +docs/stamp-vti: docs/grub.texi configure.ac $(MKDIR_P) docs (set `$(SHELL) $(srcdir)/docs/mdate-sh $<`; \ echo "@set UPDATED $$1 $$2 $$3"; \ From 5c936493d314daa5721c150b67c1e1e01c9297a7 Mon Sep 17 00:00:00 2001 From: robertmh Date: Fri, 9 Oct 2009 17:57:02 +0000 Subject: [PATCH 017/165] 2009-10-09 Robert Millan Fail gracefuly when attempting to load 64-bit kFreeBSD on IA32 CPU. * include/grub/i386/cpuid.h: New file. * commands/i386/cpuid.c: Include `'. (has_longmode): Rename to ... (grub_cpuid_has_longmode): ... this. Update all users. Remove `static' attribute. * loader/i386/bsd.c: Include `'. (grub_bsd_load_elf): Fail if load of 64-bit kernel was requested on a CPU that doesn't implement AMD64 instruction set. --- ChangeLog | 13 +++++++++++++ commands/i386/cpuid.c | 11 ++++++----- include/grub/i386/cpuid.h | 19 +++++++++++++++++++ loader/i386/bsd.c | 4 ++++ 4 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 include/grub/i386/cpuid.h diff --git a/ChangeLog b/ChangeLog index c02e3a6e2..6c89eaad6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2009-10-09 Robert Millan + + Fail gracefuly when attempting to load 64-bit kFreeBSD on IA32 CPU. + + * include/grub/i386/cpuid.h: New file. + * commands/i386/cpuid.c: Include `'. + (has_longmode): Rename to ... + (grub_cpuid_has_longmode): ... this. Update all users. Remove + `static' attribute. + * loader/i386/bsd.c: Include `'. + (grub_bsd_load_elf): Fail if load of 64-bit kernel was requested + on a CPU that doesn't implement AMD64 instruction set. + 2009-10-06 Colin Watson * Makefile.in (docs/stamp-vti): Depend on configure.ac as well, so diff --git a/commands/i386/cpuid.c b/commands/i386/cpuid.c index 71f33efb3..a8bbfe69b 100644 --- a/commands/i386/cpuid.c +++ b/commands/i386/cpuid.c @@ -1,7 +1,7 @@ /* cpuid.c - test for CPU features */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006, 2007 Free Software Foundation, Inc. + * Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc. * Based on gcc/gcc/config/i386/driver-i386.c * * GRUB is free software: you can redistribute it and/or modify @@ -24,6 +24,7 @@ #include #include #include +#include #define cpuid(num,a,b,c,d) \ asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ @@ -38,14 +39,14 @@ static const struct grub_arg_option options[] = #define bit_LM (1 << 29) -static unsigned char has_longmode = 0; +unsigned char grub_cpuid_has_longmode = 0; static grub_err_t grub_cmd_cpuid (grub_extcmd_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - return has_longmode ? GRUB_ERR_NONE + return grub_cpuid_has_longmode ? GRUB_ERR_NONE : grub_error (GRUB_ERR_TEST_FAILURE, "false"); } @@ -55,7 +56,7 @@ GRUB_MOD_INIT(cpuid) { #ifdef __x86_64__ /* grub-emu */ - has_longmode = 1; + grub_cpuid_has_longmode = 1; #else unsigned int eax, ebx, ecx, edx; unsigned int max_level; @@ -82,7 +83,7 @@ GRUB_MOD_INIT(cpuid) goto done; cpuid (0x80000001, eax, ebx, ecx, edx); - has_longmode = !!(edx & bit_LM); + grub_cpuid_has_longmode = !!(edx & bit_LM); done: #endif diff --git a/include/grub/i386/cpuid.h b/include/grub/i386/cpuid.h new file mode 100644 index 000000000..f6ae20f38 --- /dev/null +++ b/include/grub/i386/cpuid.h @@ -0,0 +1,19 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +extern unsigned char grub_cpuid_has_longmode; diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c index 1accfb660..afe1825a5 100644 --- a/loader/i386/bsd.c +++ b/loader/i386/bsd.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -871,6 +872,9 @@ grub_bsd_load_elf (grub_elf_t elf) { is_64bit = 1; + if (! grub_cpuid_has_longmode) + return grub_error (GRUB_ERR_BAD_OS, "Your CPU does not implement AMD64 architecture."); + /* FreeBSD has 64-bit entry point. */ if (kernel_type == KERNEL_TYPE_FREEBSD) { From 86564c267a823d7dd84e3eb070913e648984f05c Mon Sep 17 00:00:00 2001 From: robertmh Date: Fri, 9 Oct 2009 18:23:48 +0000 Subject: [PATCH 018/165] 2009-10-09 Robert Millan * include/grub/i386/cpuid.h: Add header protection. --- ChangeLog | 4 ++++ include/grub/i386/cpuid.h | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/ChangeLog b/ChangeLog index 6c89eaad6..8640249ba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-09 Robert Millan + + * include/grub/i386/cpuid.h: Add header protection. + 2009-10-09 Robert Millan Fail gracefuly when attempting to load 64-bit kFreeBSD on IA32 CPU. diff --git a/include/grub/i386/cpuid.h b/include/grub/i386/cpuid.h index f6ae20f38..09b313bb8 100644 --- a/include/grub/i386/cpuid.h +++ b/include/grub/i386/cpuid.h @@ -16,4 +16,9 @@ * along with GRUB. If not, see . */ +#ifndef GRUB_CPU_CPUID_HEADER +#define GRUB_CPU_CPUID_HEADER 1 + extern unsigned char grub_cpuid_has_longmode; + +#endif From bf7f7a18f45e006fef5cb076b9805f26c5ae22e7 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 12 Oct 2009 21:53:15 +0000 Subject: [PATCH 019/165] 2009-10-12 Robert Millan * term/tparm.c: Switch to GPLv3. --- ChangeLog | 4 ++++ term/tparm.c | 44 +++++++++++++++++--------------------------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8640249ba..bc2a350cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-12 Robert Millan + + * term/tparm.c: Switch to GPLv3. + 2009-10-09 Robert Millan * include/grub/i386/cpuid.h: Add header protection. diff --git a/term/tparm.c b/term/tparm.c index e76cbe723..fa25bd32c 100644 --- a/term/tparm.c +++ b/term/tparm.c @@ -1,30 +1,20 @@ -/**************************************************************************** - * Copyright (c) 1998-2003,2004,2005 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1998-2003,2004,2005 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 . + */ /********************************************************************** * This code is a modification of lib_tparm.c found in ncurses-5.2. The From 9155bc1796e65baff75c36732e7daf34d7aab2c5 Mon Sep 17 00:00:00 2001 From: robertmh Date: Wed, 14 Oct 2009 16:49:22 +0000 Subject: [PATCH 020/165] 2009-10-14 Robert Millan Refer to kernel of FreeBSD "kFreeBSD" to avoid confusion between the Operating System (FreeBSD) and its kernel (kernel of FreeBSD). * loader/i386/bsd.c (grub_freebsd_boot): Read kernel environment from "kFreeBSD" namespace (rather than "FreeBSD"). Update all users. (GRUB_MOD_INIT (bsd)): Rename "freebsd" command to "kfreebsd", "openbsd" to "kopenbsd", "netbsd" to "knetbsd", "freebsd_loadenv" to "kfreebsd_loadenv", "freebsd_module" to "kfreebsd_module", and "freebsd_module_elf" to "kfreebsd_module_elf". Update all users. --- ChangeLog | 15 +++++++++++++++ loader/i386/bsd.c | 26 +++++++++++++------------- util/grub.d/10_freebsd.in | 8 ++++---- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index bc2a350cf..911aa8c5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2009-10-14 Robert Millan + + Refer to kernel of FreeBSD "kFreeBSD" to avoid confusion between + the Operating System (FreeBSD) and its kernel (kernel of FreeBSD). + + * loader/i386/bsd.c (grub_freebsd_boot): Read kernel environment + from "kFreeBSD" namespace (rather than "FreeBSD"). Update all + users. + + (GRUB_MOD_INIT (bsd)): Rename "freebsd" command to "kfreebsd", + "openbsd" to "kopenbsd", "netbsd" to "knetbsd", "freebsd_loadenv" + to "kfreebsd_loadenv", "freebsd_module" to "kfreebsd_module", + and "freebsd_module_elf" to "kfreebsd_module_elf". Update all + users. + 2009-10-12 Robert Millan * term/tparm.c: Switch to GPLv3. diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c index afe1825a5..fc292444f 100644 --- a/loader/i386/bsd.c +++ b/loader/i386/bsd.c @@ -444,9 +444,9 @@ grub_freebsd_boot (void) auto int iterate_env (struct grub_env_var *var); int iterate_env (struct grub_env_var *var) { - if ((!grub_memcmp (var->name, "FreeBSD.", 8)) && (var->name[8])) + if ((!grub_memcmp (var->name, "kFreeBSD.", sizeof("kFreeBSD.") - 1)) && (var->name[sizeof("kFreeBSD.") - 1])) { - grub_strcpy (p, &var->name[8]); + grub_strcpy (p, &var->name[sizeof("kFreeBSD.") - 1]); p += grub_strlen (p); *(p++) = '='; grub_strcpy (p, var->value); @@ -1112,12 +1112,12 @@ grub_cmd_freebsd_loadenv (grub_command_t cmd __attribute__ ((unused)), if (*curr) { - char name[grub_strlen (curr) + 8 + 1]; + char name[grub_strlen (curr) + sizeof("kFreeBSD.")]; if (*p == '"') p++; - grub_sprintf (name, "FreeBSD.%s", curr); + grub_sprintf (name, "kFreeBSD.%s", curr); if (grub_env_set (name, p)) goto fail; } @@ -1252,26 +1252,26 @@ static grub_command_t cmd_freebsd_module_elf; GRUB_MOD_INIT (bsd) { - cmd_freebsd = grub_register_extcmd ("freebsd", grub_cmd_freebsd, + cmd_freebsd = grub_register_extcmd ("kfreebsd", grub_cmd_freebsd, GRUB_COMMAND_FLAG_BOTH, - "freebsd FILE", "Load kernel of FreeBSD.", + "kfreebsd FILE", "Load kernel of FreeBSD.", freebsd_opts); - cmd_openbsd = grub_register_extcmd ("openbsd", grub_cmd_openbsd, + cmd_openbsd = grub_register_extcmd ("kopenbsd", grub_cmd_openbsd, GRUB_COMMAND_FLAG_BOTH, - "openbsd FILE", "Load kernel of OpenBSD.", + "kopenbsd FILE", "Load kernel of OpenBSD.", openbsd_opts); - cmd_netbsd = grub_register_extcmd ("netbsd", grub_cmd_netbsd, + cmd_netbsd = grub_register_extcmd ("knetbsd", grub_cmd_netbsd, GRUB_COMMAND_FLAG_BOTH, - "netbsd FILE", "Load kernel of NetBSD.", + "knetbsd FILE", "Load kernel of NetBSD.", netbsd_opts); cmd_freebsd_loadenv = - grub_register_command ("freebsd_loadenv", grub_cmd_freebsd_loadenv, + grub_register_command ("kfreebsd_loadenv", grub_cmd_freebsd_loadenv, 0, "load FreeBSD env"); cmd_freebsd_module = - grub_register_command ("freebsd_module", grub_cmd_freebsd_module, + grub_register_command ("kfreebsd_module", grub_cmd_freebsd_module, 0, "load FreeBSD kernel module"); cmd_freebsd_module_elf = - grub_register_command ("freebsd_module_elf", grub_cmd_freebsd_module_elf, + grub_register_command ("kfreebsd_module_elf", grub_cmd_freebsd_module_elf, 0, "load FreeBSD kernel module (ELF)"); my_mod = mod; diff --git a/util/grub.d/10_freebsd.in b/util/grub.d/10_freebsd.in index 1e3a0de1f..02694d3e7 100644 --- a/util/grub.d/10_freebsd.in +++ b/util/grub.d/10_freebsd.in @@ -60,17 +60,17 @@ menuentry "${OS}" { EOF prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" cat << EOF - freebsd ${kfreebsd_rel_dirname}/${kfreebsd_basename} + kfreebsd ${kfreebsd_rel_dirname}/${kfreebsd_basename} EOF if [ x"$devices" != "x" ] ; then cat << EOF - freebsd_loadenv ${devices_rel_dirname}/${devices_basename} + kfreebsd_loadenv ${devices_rel_dirname}/${devices_basename} EOF fi cat << EOF - set FreeBSD.vfs.root.mountfrom=${kfreebsd_fs}:${GRUB_DEVICE} - set FreeBSD.vfs.root.mountfrom.options=rw + set kFreeBSD.vfs.root.mountfrom=${kfreebsd_fs}:${GRUB_DEVICE} + set kFreeBSD.vfs.root.mountfrom.options=rw } EOF fi From e9d66f6d6a8f6bf92f3d570747a364b2bd530905 Mon Sep 17 00:00:00 2001 From: robertmh Date: Wed, 14 Oct 2009 18:23:40 +0000 Subject: [PATCH 021/165] 2009-10-14 Robert Millan * conf/common.rmk (grub-dumpbios): Remove rule. (sbin_SCRIPTS, CLEANFILES): Remove `grub-dumpbios'. * util/grub-dumpbios.in: Remove file. --- ChangeLog | 6 +++++ conf/common.rmk | 7 ------ util/grub-dumpbios.in | 58 ------------------------------------------- 3 files changed, 6 insertions(+), 65 deletions(-) delete mode 100644 util/grub-dumpbios.in diff --git a/ChangeLog b/ChangeLog index 911aa8c5b..e7fc70728 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-14 Robert Millan + + * conf/common.rmk (grub-dumpbios): Remove rule. + (sbin_SCRIPTS, CLEANFILES): Remove `grub-dumpbios'. + * util/grub-dumpbios.in: Remove file. + 2009-10-14 Robert Millan Refer to kernel of FreeBSD "kFreeBSD" to avoid confusion between diff --git a/conf/common.rmk b/conf/common.rmk index 26407d06b..c1f0bbdcf 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -161,13 +161,6 @@ CLEANFILES += $(grub-mkconfig_SCRIPTS) grub-mkconfig_DATA += util/grub.d/README -# For grub-dumpbios -grub-dumpbios: util/grub-dumpbios.in config.status - ./config.status --file=$@:$< - chmod +x $@ -sbin_SCRIPTS += grub-dumpbios -CLEANFILES += grub-dumpbios - # Filing systems. pkglib_MODULES += fshelp.mod fat.mod ufs1.mod ufs2.mod ext2.mod ntfs.mod \ ntfscomp.mod minix.mod hfs.mod jfs.mod iso9660.mod xfs.mod \ diff --git a/util/grub-dumpbios.in b/util/grub-dumpbios.in deleted file mode 100644 index 396503936..000000000 --- a/util/grub-dumpbios.in +++ /dev/null @@ -1,58 +0,0 @@ -#! /bin/sh -# -# Copyright (C) 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 . - -# Usage: usage -# Print the usage. -usage () { - cat <. -EOF -} - -# Check the arguments. -for option in "$@"; do - case "$option" in - -h | --help) - usage - exit 0 ;; - -v | --version) - echo "$0 (GNU GRUB @PACKAGE_VERSION@)" - exit 0 ;; - -o) - shift - output_dir=$1 - ;; - --output=) - output_dir=`echo "$option" | sed 's/--output=//'` - ;; - -*) - echo "Unrecognized option \`$option'" 1>&2 - usage - exit 1 - ;; - esac -done - -dd if=/dev/mem of=${output_dir}vbios.bin bs=65536 skip=12 count=1 -dd if=/dev/mem of=${output_dir}int10.bin bs=4 skip=16 count=1 From 6b5886ba66fa9df9a48a68fb27d0f11ca25e97ee Mon Sep 17 00:00:00 2001 From: phcoder Date: Thu, 15 Oct 2009 11:55:06 +0000 Subject: [PATCH 022/165] 2009-10-15 Vladimir Serbinenko Revert 2009-06-10 Pavel Roskin * configure.ac: Put checks for __bswapsi2 and __bswapdi2. * include/grub/powerpc/libgcc.h: Don't use weak attribute for all exports. * include/grub/sparc64/libgcc.h: Likewise. Use preprocessor conditionals. --- ChangeLog | 10 ++++++++++ configure.ac | 3 +++ include/grub/powerpc/libgcc.h | 12 ++++++------ include/grub/sparc64/libgcc.h | 8 ++++++-- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index e7fc70728..f92d8da3a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-10-15 Vladimir Serbinenko + + Revert 2009-06-10 Pavel Roskin + + * configure.ac: Put checks for __bswapsi2 and __bswapdi2. + * include/grub/powerpc/libgcc.h: Don't use weak attribute for all + exports. + * include/grub/sparc64/libgcc.h: Likewise. Use + preprocessor conditionals. + 2009-10-14 Robert Millan * conf/common.rmk (grub-dumpbios): Remove rule. diff --git a/configure.ac b/configure.ac index 3e4da66c8..447f13fcc 100644 --- a/configure.ac +++ b/configure.ac @@ -417,6 +417,9 @@ fi CPPFLAGS="$TARGET_CPPFLAGS" LDFLAGS="$TARGET_LDFLAGS" +# Check for target functions. +AC_CHECK_FUNCS(__bswapsi2 __bswapdi2) + # Defined in aclocal.m4. grub_PROG_TARGET_CC if test "x$TARGET_APPLE_CC" != x1 ; then diff --git a/include/grub/powerpc/libgcc.h b/include/grub/powerpc/libgcc.h index ea4b073a0..0ff8964b7 100644 --- a/include/grub/powerpc/libgcc.h +++ b/include/grub/powerpc/libgcc.h @@ -16,9 +16,9 @@ * along with GRUB. If not, see . */ -void EXPORT_FUNC (memset) (void) __attribute__ ((weak)); -void EXPORT_FUNC (__ashldi3) (void) __attribute__ ((weak)); -void EXPORT_FUNC (__ashrdi3) (void) __attribute__ ((weak)); -void EXPORT_FUNC (__lshrdi3) (void) __attribute__ ((weak)); -void EXPORT_FUNC (__trampoline_setup) (void) __attribute__ ((weak)); -void EXPORT_FUNC (__ucmpdi2) (void) __attribute__ ((weak)); +void EXPORT_FUNC (memset) (void); +void EXPORT_FUNC (__ashldi3) (void); +void EXPORT_FUNC (__ashrdi3) (void); +void EXPORT_FUNC (__lshrdi3) (void); +void EXPORT_FUNC (__trampoline_setup) (void); +void EXPORT_FUNC (__ucmpdi2) (void); diff --git a/include/grub/sparc64/libgcc.h b/include/grub/sparc64/libgcc.h index 5d18c5c81..4a6b6194d 100644 --- a/include/grub/sparc64/libgcc.h +++ b/include/grub/sparc64/libgcc.h @@ -20,8 +20,12 @@ void EXPORT_FUNC (memset) (void); +#ifdef HAVE___BSWAPSI2 typedef int SItype __attribute__ ((mode (SI))); -SItype EXPORT_FUNC (__bswapsi2) (SItype) __attribute__ ((weak)); +SItype EXPORT_FUNC (__bswapsi2) (SItype); +#endif +#ifdef HAVE___BSWAPDI2 typedef int DItype __attribute__ ((mode (DI))); -DItype EXPORT_FUNC (__bswapdi2) (DItype) __attribute__ ((weak)); +DItype EXPORT_FUNC (__bswapdi2) (DItype); +#endif From c6f3b249e46b83ce21f941dd9c4e95d84f748e27 Mon Sep 17 00:00:00 2001 From: phcoder Date: Thu, 15 Oct 2009 12:09:56 +0000 Subject: [PATCH 023/165] 2009-10-15 Vladimir Serbinenko * configure.ac: Add missing dollar. --- ChangeLog | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f92d8da3a..8ad2c0362 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-15 Vladimir Serbinenko + + * configure.ac: Add missing dollar. + 2009-10-15 Vladimir Serbinenko Revert 2009-06-10 Pavel Roskin diff --git a/configure.ac b/configure.ac index 447f13fcc..946179966 100644 --- a/configure.ac +++ b/configure.ac @@ -544,7 +544,7 @@ AC_CHECK_LIB([usb], [usb_claim_interface], [LIBUSB="-lusb"], AC_CHECK_HEADERS([usb.h], [], [grub_emu_usb_excuse=["need libusb headers"]]) [fi] -if test x"enable_grub_emu_usb" = xyes && test x"$grub_emu_usb_excuse" != x ; then +if test x"$enable_grub_emu_usb" = xyes && test x"$grub_emu_usb_excuse" != x ; then AC_MSG_ERROR([USB support for grub-emu was explicitly requested but can't be compiled]) fi if test x"$grub_emu_usb_excuse" = x ; then From cd2851b3dd7d3dcd2a02739ab675d48fc03f527e Mon Sep 17 00:00:00 2001 From: phcoder Date: Thu, 15 Oct 2009 12:26:30 +0000 Subject: [PATCH 024/165] 2009-10-15 Vladimir Serbinenko * commands/xnu_uuid.c (grub_cmd_xnu_uuid): Remove duplicated bitwise operations. --- ChangeLog | 5 +++++ commands/xnu_uuid.c | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8ad2c0362..78a02e592 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-10-15 Vladimir Serbinenko + + * commands/xnu_uuid.c (grub_cmd_xnu_uuid): Remove duplicated bitwise + operations. + 2009-10-15 Vladimir Serbinenko * configure.ac: Add missing dollar. diff --git a/commands/xnu_uuid.c b/commands/xnu_uuid.c index d5c272d03..06e88e560 100644 --- a/commands/xnu_uuid.c +++ b/commands/xnu_uuid.c @@ -349,8 +349,6 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), grub_memcpy (hashme.prefix, hash_prefix, sizeof (hashme.prefix)); md5 ((char *) &hashme, sizeof (hashme), (char *) xnu_uuid); - xnu_uuid[6] = (xnu_uuid[6] & 0xf) | 0x30; - xnu_uuid[8] = (xnu_uuid[8] & 0x3f) | 0x80; grub_sprintf (uuid_string, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", (unsigned int) xnu_uuid[0], (unsigned int) xnu_uuid[1], From 44998e589332535da3ae656285347ce1427da8eb Mon Sep 17 00:00:00 2001 From: phcoder Date: Thu, 15 Oct 2009 12:40:13 +0000 Subject: [PATCH 025/165] 2009-10-15 Vladimir Serbinenko * loader/i386/pc/xnu.c (grub_xnu_set_video): Fix loading splash image. --- ChangeLog | 4 ++++ loader/i386/pc/xnu.c | 50 ++++++++++++++++++++++++-------------------- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 78a02e592..b0864a9b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-15 Vladimir Serbinenko + + * loader/i386/pc/xnu.c (grub_xnu_set_video): Fix loading splash image. + 2009-10-15 Vladimir Serbinenko * commands/xnu_uuid.c (grub_cmd_xnu_uuid): Remove duplicated bitwise diff --git a/loader/i386/pc/xnu.c b/loader/i386/pc/xnu.c index 69a9405c6..ebb176bb4 100644 --- a/loader/i386/pc/xnu.c +++ b/loader/i386/pc/xnu.c @@ -43,7 +43,6 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) { struct grub_video_mode_info mode_info; int ret; - int x,y; char *tmp, *modevar; void *framebuffer; grub_err_t err; @@ -66,32 +65,37 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) if (err) return err; + if (grub_xnu_bitmap) + { + int x, y; + + x = mode_info.width - grub_xnu_bitmap->mode_info.width; + x /= 2; + y = mode_info.height - grub_xnu_bitmap->mode_info.height; + y /= 2; + err = grub_video_blit_bitmap (grub_xnu_bitmap, + GRUB_VIDEO_BLIT_REPLACE, + x > 0 ? x : 0, + y > 0 ? y : 0, + x < 0 ? -x : 0, + y < 0 ? -y : 0, + min (grub_xnu_bitmap->mode_info.width, + mode_info.width), + min (grub_xnu_bitmap->mode_info.height, + mode_info.height)); + if (err) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + grub_xnu_bitmap = 0; + } + err = GRUB_ERR_NONE; + } + ret = grub_video_get_info_and_fini (&mode_info, &framebuffer); if (ret) return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters"); - err = GRUB_ERR_NONE; - x = mode_info.width - grub_xnu_bitmap->mode_info.width; - x /= 2; - y = mode_info.height - grub_xnu_bitmap->mode_info.height; - y /= 2; - err = grub_video_blit_bitmap (grub_xnu_bitmap, - GRUB_VIDEO_BLIT_REPLACE, - x > 0 ? x : 0, - y > 0 ? y : 0, - x < 0 ? -x : 0, - y < 0 ? -y : 0, - min (grub_xnu_bitmap->mode_info.width, - mode_info.width), - min (grub_xnu_bitmap->mode_info.height, - mode_info.height)); - if (err) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - grub_xnu_bitmap = 0; - } - params->lfb_width = mode_info.width; params->lfb_height = mode_info.height; params->lfb_depth = mode_info.bpp; From 035f7122046ca8eaad631f5aa6a3006e464c30c7 Mon Sep 17 00:00:00 2001 From: robertmh Date: Thu, 15 Oct 2009 20:34:27 +0000 Subject: [PATCH 026/165] 2009-10-15 Robert Millan Make entry text a bit more readable. * util/grub.d/10_linux.in: Add `with' before `Linux'. --- ChangeLog | 6 ++++++ util/grub.d/10_linux.in | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b0864a9b9..b90033393 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-15 Robert Millan + + Make entry text a bit more readable. + + * util/grub.d/10_linux.in: Add `with' before `Linux'. + 2009-10-15 Vladimir Serbinenko * loader/i386/pc/xnu.c (grub_xnu_set_video): Fix loading splash image. diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 381a0c3d5..1473a42a2 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -91,10 +91,10 @@ while [ "x$list" != "x" ] ; do linux_root_device_thisversion=${GRUB_DEVICE} fi - linux_entry "${OS}, Linux ${version}" \ + linux_entry "${OS}, with Linux ${version}" \ "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" if [ "x${GRUB_DISABLE_LINUX_RECOVERY}" != "xtrue" ]; then - linux_entry "${OS}, Linux ${version} (recovery mode)" \ + linux_entry "${OS}, with Linux ${version} (recovery mode)" \ "single ${GRUB_CMDLINE_LINUX}" fi From 6f3cd880e9ea91441f4aa318234a8ad590fed9af Mon Sep 17 00:00:00 2001 From: cjwatson Date: Fri, 16 Oct 2009 15:38:42 +0000 Subject: [PATCH 027/165] 2009-10-16 Colin Watson * configure.ac (TARGET_CFLAGS): Add -mno-mmx -mno-sse -mno-sse2 -mno-3dnow on x86 architectures. Some toolchains enable these features by default, but they rely on registers that aren't enabled in GRUB. Thanks to Vladimir Serbinenko for the suggestion. --- ChangeLog | 7 +++++++ configure.ac | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/ChangeLog b/ChangeLog index b90033393..eb874f93e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-10-16 Colin Watson + + * configure.ac (TARGET_CFLAGS): Add -mno-mmx -mno-sse -mno-sse2 + -mno-3dnow on x86 architectures. Some toolchains enable these + features by default, but they rely on registers that aren't enabled + in GRUB. Thanks to Vladimir Serbinenko for the suggestion. + 2009-10-15 Robert Millan Make entry text a bit more readable. diff --git a/configure.ac b/configure.ac index 946179966..f26b92447 100644 --- a/configure.ac +++ b/configure.ac @@ -252,6 +252,10 @@ if test "x$TARGET_CFLAGS" = x; then else TARGET_CFLAGS="$TARGET_CFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1" fi + + # Some toolchains enable these features by default, but they need + # registers that aren't set up properly in GRUB. + TARGET_CFLAGS="$TARGET_CFLAGS -mno-mmx -mno-sse -mno-sse2 -mno-3dnow" fi # By default, GCC 4.4 generates .eh_frame sections containing unwind From f1d29d87ad9ed67346fa78fa12e55f63b875bf7f Mon Sep 17 00:00:00 2001 From: robertmh Date: Fri, 16 Oct 2009 17:43:26 +0000 Subject: [PATCH 028/165] 2009-10-16 Robert Millan * configure.ac: Bump version to 1.97. --- ChangeLog | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index eb874f93e..5f58ef12f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-16 Robert Millan + + * configure.ac: Bump version to 1.97. + 2009-10-16 Colin Watson * configure.ac (TARGET_CFLAGS): Add -mno-mmx -mno-sse -mno-sse2 diff --git a/configure.ac b/configure.ac index f26b92447..ca837b6e5 100644 --- a/configure.ac +++ b/configure.ac @@ -31,7 +31,7 @@ dnl (such as TARGET_CC, TARGET_CFLAGS, etc.) are used for the target dnl type. -AC_INIT([GRUB],[1.97~beta4],[bug-grub@gnu.org]) +AC_INIT([GRUB],[1.97],[bug-grub@gnu.org]) AC_PREREQ(2.59) AC_CONFIG_SRCDIR([include/grub/dl.h]) AC_CONFIG_HEADER([config.h]) From 421bd7ac69dd3caee5806b0b7c5fd81581011150 Mon Sep 17 00:00:00 2001 From: phcoder Date: Fri, 16 Oct 2009 18:11:45 +0000 Subject: [PATCH 029/165] 2009-10-16 Vladimir Serbinenko * NEWS: Mentioned XNU, ACPI, gptsync, password and parttool. --- ChangeLog | 4 ++++ NEWS | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5f58ef12f..f4f2914d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-16 Vladimir Serbinenko + + * NEWS: Mentioned XNU, ACPI, gptsync, password and parttool. + 2009-10-16 Robert Millan * configure.ac: Bump version to 1.97. diff --git a/NEWS b/NEWS index 03ba6a268..e4080de94 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,15 @@ New in 1.97 - : +* Add support for XNU kernels. + +* ACPI override support. + +* Integrated gptsync. + +* Password protection support. + +* Partition manipulation tool. + * Add `keystatus' command. * Unicode fonts are now used by default. From d2b6b7fc9af3dfd958783cdc51de19b15e858721 Mon Sep 17 00:00:00 2001 From: robertmh Date: Fri, 16 Oct 2009 18:46:51 +0000 Subject: [PATCH 030/165] 2009-10-16 Robert Millan * NEWS: Misc adjustments. --- ChangeLog | 4 ++++ NEWS | 12 ++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index f4f2914d8..8eb911eaf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-16 Robert Millan + + * NEWS: Misc adjustments. + 2009-10-16 Vladimir Serbinenko * NEWS: Mentioned XNU, ACPI, gptsync, password and parttool. diff --git a/NEWS b/NEWS index e4080de94..7c29cc948 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ New in 1.97 - : -* Add support for XNU kernels. +* Add support for loading XNU (MacOS X kernel). * ACPI override support. @@ -22,9 +22,7 @@ New in 1.97 - : * Add support for RAID levels 4,6 and 10. -* Add support for lua scripts. - -* update-grub is renamed to grub-mkconfig. +* update-grub is replaced by grub-mkconfig. * When booting from PXE, PXE can be used to load files. @@ -36,8 +34,6 @@ New in 1.97 - : * Add Cygwin support. -* Add grub-pe2elf to convert PE modules to ELF modules. - * Add x86_64 EFI support. * Use LZMA compression instead of LZO. @@ -57,13 +53,13 @@ New in 1.97 - : * grub-mkconfig supports os-prober to add operating systems to the boot menu. -* The ATA driver supports filesystems bigger than 2TB. +* The ATA driver supports devices bigger than 2 TiB. * Add support for the UDF, AFS and EXT4 filesystems. * The ISO9660 filesystem supports the Joliet extension -* Add aout and BSD kernel loaders. +* Add support for loading kernels of FreeBSD, NetBSD and OpenBSD. * Add new command `sleep'. From 46695a62e6b3ffa53f224cf82de871afe36cf2d9 Mon Sep 17 00:00:00 2001 From: phcoder Date: Fri, 16 Oct 2009 20:21:12 +0000 Subject: [PATCH 031/165] 2009-10-16 Vladimir Serbinenko Let user specify OpenBSD root device. * loader/i386/bsd.c (openbsd_root): New variable. (openbsd_opts): New option 'root'. (OPENBSD_ROOT_ARG): New macro. (grub_openbsd_boot): Use 'openbsd_root'. (grub_cmd_openbsd): Fill 'openbsd_root'. --- ChangeLog | 10 ++++++++++ loader/i386/bsd.c | 41 ++++++++++++++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8eb911eaf..960fc067e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-10-16 Vladimir Serbinenko + + Let user specify OpenBSD root device. + + * loader/i386/bsd.c (openbsd_root): New variable. + (openbsd_opts): New option 'root'. + (OPENBSD_ROOT_ARG): New macro. + (grub_openbsd_boot): Use 'openbsd_root'. + (grub_cmd_openbsd): Fill 'openbsd_root'. + 2009-10-16 Robert Millan * NEWS: Misc adjustments. diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c index fc292444f..acc653c9e 100644 --- a/loader/i386/bsd.c +++ b/loader/i386/bsd.c @@ -58,6 +58,7 @@ static char *mod_buf; static grub_uint32_t mod_buf_len, mod_buf_max, kern_end_mdofs; static int is_elf_kernel, is_64bit; static char *netbsd_root = NULL; +static grub_uint32_t openbsd_root; static const struct grub_arg_option freebsd_opts[] = { @@ -94,6 +95,7 @@ static const struct grub_arg_option openbsd_opts[] = {"config", 'c', 0, "Change configured devices.", 0, 0}, {"single", 's', 0, "Boot into single mode.", 0, 0}, {"kdb", 'd', 0, "Enter in KDB on boot.", 0, 0}, + {"root", 'r', 0, "Set root device.", "wdXY", ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -103,6 +105,8 @@ static const grub_uint32_t openbsd_flags[] = OPENBSD_RB_SINGLE, OPENBSD_RB_KDB, 0 }; +#define OPENBSD_ROOT_ARG (ARRAY_SIZE (openbsd_flags) - 1) + static const struct grub_arg_option netbsd_opts[] = { {"no-smp", '1', 0, "Disable SMP.", 0, 0}, @@ -565,7 +569,6 @@ grub_openbsd_boot (void) char *buf = (char *) GRUB_BSD_TEMP_BUFFER; struct grub_openbsd_bios_mmap *pm; struct grub_openbsd_bootargs *pa; - grub_uint32_t bootdev, biosdev, unit, slice, part; 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) @@ -614,11 +617,7 @@ grub_openbsd_boot (void) pa->ba_type = OPENBSD_BOOTARG_END; pa++; - grub_bsd_get_device (&biosdev, &unit, &slice, &part); - bootdev = (OPENBSD_B_DEVMAGIC + (unit << OPENBSD_B_UNITSHIFT) + - (part << OPENBSD_B_PARTSHIFT)); - - grub_unix_real_boot (entry, bootflags, bootdev, OPENBSD_BOOTARG_APIVER, + grub_unix_real_boot (entry, bootflags, openbsd_root, OPENBSD_BOOTARG_APIVER, 0, (grub_uint32_t) (grub_mmap_get_upper () >> 10), (grub_uint32_t) (grub_mmap_get_lower () >> 10), (char *) pa - buf, buf); @@ -1015,11 +1014,39 @@ grub_cmd_freebsd (grub_extcmd_t cmd, int argc, char *argv[]) static grub_err_t grub_cmd_openbsd (grub_extcmd_t cmd, int argc, char *argv[]) { + grub_uint32_t bootdev; + kernel_type = KERNEL_TYPE_OPENBSD; bootflags = grub_bsd_parse_flags (cmd->state, openbsd_flags); + if (cmd->state[OPENBSD_ROOT_ARG].set) + { + const char *arg = cmd->state[OPENBSD_ROOT_ARG].arg; + int unit, part; + if (*(arg++) != 'w' || *(arg++) != 'd') + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Only device specifications of form " + "wd are supported."); + + unit = grub_strtoul (arg, (char **) &arg, 10); + if (! (arg && *arg >= 'a' && *arg <= 'z')) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Only device specifications of form " + "wd are supported."); + + part = *arg - 'a'; + + bootdev = (OPENBSD_B_DEVMAGIC + (unit << OPENBSD_B_UNITSHIFT) + + (part << OPENBSD_B_PARTSHIFT)); + } + else + bootdev = 0; + if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE) - grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 1); + { + grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 1); + openbsd_root = bootdev; + } return grub_errno; } From 3b2fe8c2857f9753ce072639c8a547d6c41bce61 Mon Sep 17 00:00:00 2001 From: robertmh Date: Tue, 20 Oct 2009 11:30:37 +0000 Subject: [PATCH 032/165] 2009-10-20 Robert Millan Fix build on sparc64. * configure.ac: Perform checks for libgcc symbols before adding `-nostdlib' to LDFLAGS. --- ChangeLog | 7 +++++++ configure.ac | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 960fc067e..a14da7a14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-10-20 Robert Millan + + Fix build on sparc64. + + * configure.ac: Perform checks for libgcc symbols before + adding `-nostdlib' to LDFLAGS. + 2009-10-16 Vladimir Serbinenko Let user specify OpenBSD root device. diff --git a/configure.ac b/configure.ac index ca837b6e5..bf113ba68 100644 --- a/configure.ac +++ b/configure.ac @@ -411,6 +411,9 @@ AC_SUBST(TARGET_ASFLAGS) AC_SUBST(TARGET_CPPFLAGS) AC_SUBST(TARGET_LDFLAGS) +# Check for libgcc symbols (must be performed before we add -nostdlib to LDFLAGS) +AC_CHECK_FUNCS(__bswapsi2 __bswapdi2) + # Set them to their new values for the tests below. CC="$TARGET_CC" if test "x$TARGET_APPLE_CC" = x1 ; then @@ -421,9 +424,6 @@ fi CPPFLAGS="$TARGET_CPPFLAGS" LDFLAGS="$TARGET_LDFLAGS" -# Check for target functions. -AC_CHECK_FUNCS(__bswapsi2 __bswapdi2) - # Defined in aclocal.m4. grub_PROG_TARGET_CC if test "x$TARGET_APPLE_CC" != x1 ; then From 0933cdc0ab2789eda662dbd6418f92f21d05bd39 Mon Sep 17 00:00:00 2001 From: fzielcke Date: Wed, 21 Oct 2009 12:22:05 +0000 Subject: [PATCH 033/165] 2009-10-21 Felix Zielcke * config.guess: Update to latest version from config git repository. * config.sub: Likewise. --- ChangeLog | 6 +++ config.guess | 111 +++++++++++++++++---------------------------------- config.sub | 9 +++-- 3 files changed, 47 insertions(+), 79 deletions(-) diff --git a/ChangeLog b/ChangeLog index a14da7a14..2dd370aca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-21 Felix Zielcke + + * config.guess: Update to latest version from config git + repository. + * config.sub: Likewise. + 2009-10-20 Robert Millan Fix build on sparc64. diff --git a/config.guess b/config.guess index bb0b03ea1..e792aac60 100644 --- a/config.guess +++ b/config.guess @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 # Free Software Foundation, Inc. -timestamp='2009-08-19' +timestamp='2009-09-18' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -854,6 +854,20 @@ EOF i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ @@ -876,6 +890,9 @@ EOF frv:Linux:*:*) echo frv-unknown-linux-gnu exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-gnu + exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; @@ -911,29 +928,12 @@ EOF or32:Linux:*:*) echo or32-unknown-linux-gnu exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit ;; padre:Linux:*:*) echo sparc-unknown-linux-gnu exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in @@ -942,8 +942,11 @@ EOF *) echo hppa-unknown-linux-gnu ;; esac exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux @@ -966,58 +969,6 @@ EOF xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - # Set LC_ALL=C to ensure ld outputs messages in English. - ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - esac - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif - #else - #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) - LIBC=gnu - #else - LIBC=gnuaout - #endif - #endif - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^LIBC/{ - s: ::g - p - }'`" - test x"${LIBC}" != x && { - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit - } - test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } - ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both @@ -1247,6 +1198,16 @@ EOF *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} diff --git a/config.sub b/config.sub index 8ca084bf3..5ecc18b6a 100644 --- a/config.sub +++ b/config.sub @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 # Free Software Foundation, Inc. -timestamp='2009-08-19' +timestamp='2009-10-07' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -287,6 +287,7 @@ case $basic_machine in | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ + | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ @@ -300,7 +301,7 @@ case $basic_machine in | z8k | z80) basic_machine=$basic_machine-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12) + m6811 | m68hc11 | m6812 | m68hc12 | picochip) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none @@ -371,7 +372,7 @@ case $basic_machine in | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ - | romp-* | rs6000-* \ + | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ @@ -1296,7 +1297,7 @@ case $os in | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) From f66938909063bff27fc2c3cb5e8e6063f6d0175f Mon Sep 17 00:00:00 2001 From: robertmh Date: Sat, 24 Oct 2009 23:03:02 +0000 Subject: [PATCH 034/165] 2009-10-25 Robert Millan Patch from Samuel Thibault * docs/grub.cfg: Compensate for recent change in multiboot loader (since 2009-08-14 it won't pass filename to payload). * util/grub.d/10_hurd.in: Likewise. --- ChangeLog | 7 +++++++ docs/grub.cfg | 4 ++-- util/grub.d/10_hurd.in | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2dd370aca..26a2c8f7c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-10-25 Robert Millan + + Patch from Samuel Thibault + * docs/grub.cfg: Compensate for recent change in multiboot + loader (since 2009-08-14 it won't pass filename to payload). + * util/grub.d/10_hurd.in: Likewise. + 2009-10-21 Felix Zielcke * config.guess: Update to latest version from config git diff --git a/docs/grub.cfg b/docs/grub.cfg index 4d1582a8e..0a9ab6bc7 100644 --- a/docs/grub.cfg +++ b/docs/grub.cfg @@ -15,13 +15,13 @@ set fallback=1 menuentry "GNU (aka GNU/Hurd)" { set root=(hd0,1) multiboot /boot/gnumach.gz root=device:hd0s1 - module /hurd/ext2fs.static --readonly \ + module /hurd/ext2fs.static ext2fs --readonly \ --multiboot-command-line='${kernel-command-line}' \ --host-priv-port='${host-port}' \ --device-master-port='${device-port}' \ --exec-server-task='${exec-task}' -T typed '${root}' \ '$(task-create)' '$(task-resume)' - module /lib/ld.so.1 /hurd/exec '$(exec-task=task-create)' + module /lib/ld.so.1 exec /hurd/exec '$(exec-task=task-create)' } # For booting GNU/Linux diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index ec78a3532..b52f37498 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -74,12 +74,12 @@ EOF prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/" cat << EOF multiboot ${kernel} root=device:${GRUB_DEVICE} - module /hurd/${hurd_fs}.static --readonly \\ + module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\ --multiboot-command-line='\${kernel-command-line}' \\ --host-priv-port='\${host-port}' \\ --device-master-port='\${device-port}' \\ --exec-server-task='\${exec-task}' -T typed '\${root}' \\ '\$(task-create)' '\$(task-resume)' - module /lib/ld.so.1 /hurd/exec '\$(exec-task=task-create)' + module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)' } EOF From fb26abc22bece052526d65508944dffd0405fa02 Mon Sep 17 00:00:00 2001 From: robertmh Date: Sat, 24 Oct 2009 23:15:48 +0000 Subject: [PATCH 035/165] 2009-10-25 Robert Millan * fs/cpio.c [MODE_USTAR]: Finish `tar' module instead of `cpio'. [! MODE_USTAR]: Finish `cpio' module instead of `tar'. --- ChangeLog | 6 ++++++ fs/cpio.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 26a2c8f7c..51e76499b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-25 Robert Millan + + * fs/cpio.c [MODE_USTAR]: Finish `tar' module instead of + `cpio'. + [! MODE_USTAR]: Finish `cpio' module instead of `tar'. + 2009-10-25 Robert Millan Patch from Samuel Thibault diff --git a/fs/cpio.c b/fs/cpio.c index 1ec4ebeaf..7c6ada9b3 100644 --- a/fs/cpio.c +++ b/fs/cpio.c @@ -362,9 +362,9 @@ GRUB_MOD_INIT (tar) } #ifdef MODE_USTAR -GRUB_MOD_FINI (cpio) -#else GRUB_MOD_FINI (tar) +#else +GRUB_MOD_FINI (cpio) #endif { grub_fs_unregister (&grub_cpio_fs); From cdb308b0e156f2081c77e30b92bad5ebac4fdf11 Mon Sep 17 00:00:00 2001 From: robertmh Date: Sat, 24 Oct 2009 23:26:42 +0000 Subject: [PATCH 036/165] 2009-10-25 Robert Millan * include/grub/powerpc/libgcc.h (memset): Remove function prototype. * include/grub/sparc64/libgcc.h (memset): Likewise. * include/grub/misc.h (memset, memcmp): New function prototypes. --- ChangeLog | 6 ++++++ include/grub/misc.h | 2 ++ include/grub/powerpc/libgcc.h | 1 - include/grub/sparc64/libgcc.h | 2 -- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 51e76499b..9df444755 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-25 Robert Millan + + * include/grub/powerpc/libgcc.h (memset): Remove function prototype. + * include/grub/sparc64/libgcc.h (memset): Likewise. + * include/grub/misc.h (memset, memcmp): New function prototypes. + 2009-10-25 Robert Millan * fs/cpio.c [MODE_USTAR]: Finish `tar' module instead of diff --git a/include/grub/misc.h b/include/grub/misc.h index a63a0b442..c7ff1e2d2 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -76,8 +76,10 @@ grub_strncat (char *dest, const char *src, int c) /* Prototypes for aliases. */ #if !defined (GRUB_UTIL) || !defined (APPLE_CC) +int EXPORT_FUNC(memcmp) (const void *s1, const void *s2, grub_size_t n); void *EXPORT_FUNC(memmove) (void *dest, const void *src, grub_size_t n); void *EXPORT_FUNC(memcpy) (void *dest, const void *src, grub_size_t n); +void EXPORT_FUNC (memset) (void); #endif int EXPORT_FUNC(grub_memcmp) (const void *s1, const void *s2, grub_size_t n); diff --git a/include/grub/powerpc/libgcc.h b/include/grub/powerpc/libgcc.h index 0ff8964b7..c32fcd87f 100644 --- a/include/grub/powerpc/libgcc.h +++ b/include/grub/powerpc/libgcc.h @@ -16,7 +16,6 @@ * along with GRUB. If not, see . */ -void EXPORT_FUNC (memset) (void); void EXPORT_FUNC (__ashldi3) (void); void EXPORT_FUNC (__ashrdi3) (void); void EXPORT_FUNC (__lshrdi3) (void); diff --git a/include/grub/sparc64/libgcc.h b/include/grub/sparc64/libgcc.h index 4a6b6194d..008821d81 100644 --- a/include/grub/sparc64/libgcc.h +++ b/include/grub/sparc64/libgcc.h @@ -18,8 +18,6 @@ #include -void EXPORT_FUNC (memset) (void); - #ifdef HAVE___BSWAPSI2 typedef int SItype __attribute__ ((mode (SI))); SItype EXPORT_FUNC (__bswapsi2) (SItype); From 346e7fbedb8e728aea4c8400e2d94ba24208ed3b Mon Sep 17 00:00:00 2001 From: robertmh Date: Sat, 24 Oct 2009 23:26:53 +0000 Subject: [PATCH 037/165] 2009-10-25 Robert Millan * configure.ac: Check for `__ashldi3', `__ashrdi3', `__lshrdi3', `__trampoline_setup' and `__ucmpdi2'. * include/grub/powerpc/libgcc.h: Only export symbols for functions that libgcc provides. --- ChangeLog | 7 +++++++ configure.ac | 2 +- include/grub/powerpc/libgcc.h | 14 +++++++++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9df444755..ce28aed16 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-10-25 Robert Millan + + * configure.ac: Check for `__ashldi3', `__ashrdi3', `__lshrdi3', + `__trampoline_setup' and `__ucmpdi2'. + * include/grub/powerpc/libgcc.h: Only export symbols for functions + that libgcc provides. + 2009-10-25 Robert Millan * include/grub/powerpc/libgcc.h (memset): Remove function prototype. diff --git a/configure.ac b/configure.ac index bf113ba68..048333ba5 100644 --- a/configure.ac +++ b/configure.ac @@ -412,7 +412,7 @@ AC_SUBST(TARGET_CPPFLAGS) AC_SUBST(TARGET_LDFLAGS) # Check for libgcc symbols (must be performed before we add -nostdlib to LDFLAGS) -AC_CHECK_FUNCS(__bswapsi2 __bswapdi2) +AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2) # Set them to their new values for the tests below. CC="$TARGET_CC" diff --git a/include/grub/powerpc/libgcc.h b/include/grub/powerpc/libgcc.h index c32fcd87f..452ad4366 100644 --- a/include/grub/powerpc/libgcc.h +++ b/include/grub/powerpc/libgcc.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004,2007 Free Software Foundation, Inc. + * Copyright (C) 2004,2007,2009 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,8 +16,20 @@ * along with GRUB. If not, see . */ +#include + +#ifdef HAVE___ASHLDI3 void EXPORT_FUNC (__ashldi3) (void); +#endif +#ifdef HAVE___ASHRDI3 void EXPORT_FUNC (__ashrdi3) (void); +#endif +#ifdef HAVE___LSHRDI3 void EXPORT_FUNC (__lshrdi3) (void); +#endif +#ifdef HAVE___TRAMPOLINE_SETUP void EXPORT_FUNC (__trampoline_setup) (void); +#endif +#ifdef HAVE___UCMPDI2 void EXPORT_FUNC (__ucmpdi2) (void); +#endif From b240e30c478d5665bba66794e9a1c8ccaefbb222 Mon Sep 17 00:00:00 2001 From: robertmh Date: Sat, 24 Oct 2009 23:31:05 +0000 Subject: [PATCH 038/165] 2009-10-25 Robert Millan * fs/cpio.c [MODE_USTAR]: Initialize `tar' module instead of `cpio'. [! MODE_USTAR]: Initialize `cpio' module instead of `tar'. --- ChangeLog | 6 ++++++ fs/cpio.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index ce28aed16..380dacffd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-25 Robert Millan + + * fs/cpio.c [MODE_USTAR]: Initialize `tar' module instead of + `cpio'. + [! MODE_USTAR]: Initialize `cpio' module instead of `tar'. + 2009-10-25 Robert Millan * configure.ac: Check for `__ashldi3', `__ashrdi3', `__lshrdi3', diff --git a/fs/cpio.c b/fs/cpio.c index 7c6ada9b3..3f3a3d1a0 100644 --- a/fs/cpio.c +++ b/fs/cpio.c @@ -352,9 +352,9 @@ static struct grub_fs grub_cpio_fs = { }; #ifdef MODE_USTAR -GRUB_MOD_INIT (cpio) -#else GRUB_MOD_INIT (tar) +#else +GRUB_MOD_INIT (cpio) #endif { grub_fs_register (&grub_cpio_fs); From 508d42ec11bd3197bd6f3783a27f54ed6796eafd Mon Sep 17 00:00:00 2001 From: robertmh Date: Sat, 24 Oct 2009 23:36:00 +0000 Subject: [PATCH 039/165] 2009-10-25 Robert Millan 2009-10-25 Vasily Averin * fs/ext2.c (grub_ext2_iterate_dir): Avoid infinite loop when `dirent.direntlen == 0'. --- ChangeLog | 6 ++++++ fs/ext2.c | 3 +++ 2 files changed, 9 insertions(+) diff --git a/ChangeLog b/ChangeLog index 380dacffd..80c593e4b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-25 Robert Millan +2009-10-25 Vasily Averin + + * fs/ext2.c (grub_ext2_iterate_dir): Avoid infinite loop when + `dirent.direntlen == 0'. + 2009-10-25 Robert Millan * fs/cpio.c [MODE_USTAR]: Initialize `tar' module instead of diff --git a/fs/ext2.c b/fs/ext2.c index 0341680ea..8d8c6939e 100644 --- a/fs/ext2.c +++ b/fs/ext2.c @@ -649,6 +649,9 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir, if (grub_errno) return 0; + if (dirent.direntlen == 0) + return 0; + if (dirent.namelen != 0) { char filename[dirent.namelen + 1]; From d64448a72c4d5015ab07c2197e7f1f11717e382a Mon Sep 17 00:00:00 2001 From: robertmh Date: Sun, 25 Oct 2009 15:14:25 +0000 Subject: [PATCH 040/165] 2009-10-25 Robert Millan * include/grub/misc.h: Fix wrong evaluation of APPLE_CC. (memset): Fix function prototype. --- ChangeLog | 5 +++++ include/grub/misc.h | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 80c593e4b..daee3ea4c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-10-25 Robert Millan + + * include/grub/misc.h: Fix wrong evaluation of APPLE_CC. + (memset): Fix function prototype. + 2009-10-25 Robert Millan 2009-10-25 Vasily Averin diff --git a/include/grub/misc.h b/include/grub/misc.h index c7ff1e2d2..7589f43a2 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -75,11 +75,11 @@ grub_strncat (char *dest, const char *src, int c) } /* Prototypes for aliases. */ -#if !defined (GRUB_UTIL) || !defined (APPLE_CC) +#if !defined (GRUB_UTIL) && !defined (APPLE_CC) int EXPORT_FUNC(memcmp) (const void *s1, const void *s2, grub_size_t n); void *EXPORT_FUNC(memmove) (void *dest, const void *src, grub_size_t n); void *EXPORT_FUNC(memcpy) (void *dest, const void *src, grub_size_t n); -void EXPORT_FUNC (memset) (void); +void *EXPORT_FUNC(memset) (void *s, int c, grub_size_t n); #endif int EXPORT_FUNC(grub_memcmp) (const void *s1, const void *s2, grub_size_t n); From 042484d78e5a12999aa956caa4feb55ac54a2a3a Mon Sep 17 00:00:00 2001 From: robertmh Date: Sun, 25 Oct 2009 15:23:48 +0000 Subject: [PATCH 041/165] 2009-10-25 Robert Millan * include/grub/fs.h [GRUB_UTIL] (struct grub_fs): Add `reserved_first_sector' member. * fs/ext2.c [GRUB_UTIL] (grub_ext2_fs): Initialize `reserved_first_sector' to 1. * fs/fat.c [GRUB_UTIL] (grub_fat_fs): Likewise. * fs/ntfs.c [GRUB_UTIL] (grub_ntfs_fs): Likewise. * fs/hfsplus.c [GRUB_UTIL] (grub_hfsplus_fs): Likewise. * util/i386/pc/grub-setup.c (setup): Add safety check that probes for filesystems which begin at first sector. (options): New option --skip-fs-probe. (main): Handle --skip-fs-probe and pass it to setup(). --- ChangeLog | 14 ++++++++++++++ fs/ext2.c | 3 +++ fs/fat.c | 3 +++ fs/hfsplus.c | 3 +++ fs/ntfs.c | 22 +++++++++++++--------- include/grub/fs.h | 5 +++++ util/i386/pc/grub-setup.c | 29 +++++++++++++++++++++++++---- 7 files changed, 66 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index daee3ea4c..81f3ba601 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2009-10-25 Robert Millan + + * include/grub/fs.h [GRUB_UTIL] (struct grub_fs): Add + `reserved_first_sector' member. + * fs/ext2.c [GRUB_UTIL] (grub_ext2_fs): Initialize + `reserved_first_sector' to 1. + * fs/fat.c [GRUB_UTIL] (grub_fat_fs): Likewise. + * fs/ntfs.c [GRUB_UTIL] (grub_ntfs_fs): Likewise. + * fs/hfsplus.c [GRUB_UTIL] (grub_hfsplus_fs): Likewise. + * util/i386/pc/grub-setup.c (setup): Add safety check that probes for + filesystems which begin at first sector. + (options): New option --skip-fs-probe. + (main): Handle --skip-fs-probe and pass it to setup(). + 2009-10-25 Robert Millan * include/grub/misc.h: Fix wrong evaluation of APPLE_CC. diff --git a/fs/ext2.c b/fs/ext2.c index 8d8c6939e..e7a20a43b 100644 --- a/fs/ext2.c +++ b/fs/ext2.c @@ -927,6 +927,9 @@ static struct grub_fs grub_ext2_fs = .label = grub_ext2_label, .uuid = grub_ext2_uuid, .mtime = grub_ext2_mtime, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, +#endif .next = 0 }; diff --git a/fs/fat.c b/fs/fat.c index 8440e43fa..e7f01629e 100644 --- a/fs/fat.c +++ b/fs/fat.c @@ -855,6 +855,9 @@ static struct grub_fs grub_fat_fs = .close = grub_fat_close, .label = grub_fat_label, .uuid = grub_fat_uuid, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, +#endif .next = 0 }; diff --git a/fs/hfsplus.c b/fs/hfsplus.c index 5e0ab093f..b306e8d6a 100644 --- a/fs/hfsplus.c +++ b/fs/hfsplus.c @@ -1021,6 +1021,9 @@ static struct grub_fs grub_hfsplus_fs = .label = grub_hfsplus_label, .mtime = grub_hfsplus_mtime, .uuid = grub_hfsplus_uuid, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, +#endif .next = 0 }; diff --git a/fs/ntfs.c b/fs/ntfs.c index f1d0a374e..163f3e0a8 100644 --- a/fs/ntfs.c +++ b/fs/ntfs.c @@ -1081,15 +1081,19 @@ grub_ntfs_uuid (grub_device_t device, char **uuid) return grub_errno; } -static struct grub_fs grub_ntfs_fs = { - .name = "ntfs", - .dir = grub_ntfs_dir, - .open = grub_ntfs_open, - .read = grub_ntfs_read, - .close = grub_ntfs_close, - .label = grub_ntfs_label, - .uuid = grub_ntfs_uuid, - .next = 0 +static struct grub_fs grub_ntfs_fs = + { + .name = "ntfs", + .dir = grub_ntfs_dir, + .open = grub_ntfs_open, + .read = grub_ntfs_read, + .close = grub_ntfs_close, + .label = grub_ntfs_label, + .uuid = grub_ntfs_uuid, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, +#endif + .next = 0 }; GRUB_MOD_INIT (ntfs) diff --git a/include/grub/fs.h b/include/grub/fs.h index 41732e48d..132ab4755 100644 --- a/include/grub/fs.h +++ b/include/grub/fs.h @@ -68,6 +68,11 @@ struct grub_fs /* Get writing time of filesystem. */ grub_err_t (*mtime) (grub_device_t device, grub_int32_t *timebuf); +#ifdef GRUB_UTIL + /* Whether this filesystem reserves first sector for DOS-style boot. */ + int reserved_first_sector; +#endif + /* The next filesystem. */ struct grub_fs *next; }; diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index ccfbd1d25..5a46e9e24 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -86,7 +86,7 @@ grub_refresh (void) static void setup (const char *dir, const char *boot_file, const char *core_file, - const char *root, const char *dest, int must_embed, int force) + const char *root, const char *dest, int must_embed, int force, int fs_probe) { char *boot_path, *core_path, *core_path_dev; char *boot_img, *core_img; @@ -251,6 +251,21 @@ setup (const char *dir, if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img)) grub_util_error ("%s", grub_errmsg); + if (dest_dev->disk->partition && fs_probe) + { + grub_fs_t fs; + fs = grub_fs_probe (dest_dev); + if (! fs) + grub_util_error ("Unable to identify a filesystem in %s; safety check can't be performed."); + + if (! fs->reserved_first_sector) + grub_util_error ("%s appears to contain a %s filesystem which isn't known to " + "reserve space for DOS-style boot. Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk).", dest_dev->disk->name, fs->name); + } + /* Copy the possible DOS BPB. */ memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START, tmp_img + GRUB_BOOT_MACHINE_BPB_START, @@ -556,6 +571,7 @@ static struct option options[] = {"device-map", required_argument, 0, 'm'}, {"root-device", required_argument, 0, 'r'}, {"force", no_argument, 0, 'f'}, + {"skip-fs-probe", no_argument, 0, 's'}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"verbose", no_argument, 0, 'v'}, @@ -580,6 +596,7 @@ DEVICE must be a GRUB device (e.g. ``(hd0,1)'').\n\ -m, --device-map=FILE use FILE as the device map [default=%s]\n\ -r, --root-device=DEV use DEV as the root device [default=guessed]\n\ -f, --force install even if problems are detected\n\ + -s, --skip-fs-probe do not probe for filesystems in DEVICE\n\ -h, --help display this message and exit\n\ -V, --version print version information and exit\n\ -v, --verbose print verbose messages\n\ @@ -613,7 +630,7 @@ main (int argc, char *argv[]) char *dev_map = 0; char *root_dev = 0; char *dest_dev; - int must_embed = 0, force = 0; + int must_embed = 0, force = 0, fs_probe = 1; progname = "grub-setup"; @@ -666,6 +683,10 @@ main (int argc, char *argv[]) force = 1; break; + case 's': + fs_probe = 0; + break; + case 'h': usage (0); break; @@ -767,7 +788,7 @@ main (int argc, char *argv[]) setup (dir ? : DEFAULT_DIRECTORY, boot_file ? : DEFAULT_BOOT_FILE, core_file ? : DEFAULT_CORE_FILE, - root_dev, grub_util_get_grub_dev (devicelist[i]), 1, force); + root_dev, grub_util_get_grub_dev (devicelist[i]), 1, force, fs_probe); } } else @@ -776,7 +797,7 @@ main (int argc, char *argv[]) setup (dir ? : DEFAULT_DIRECTORY, boot_file ? : DEFAULT_BOOT_FILE, core_file ? : DEFAULT_CORE_FILE, - root_dev, dest_dev, must_embed, force); + root_dev, dest_dev, must_embed, force, fs_probe); /* Free resources. */ grub_fini_all (); From 4dea1c6f063c5af8a50a8481c0e2ce713190897d Mon Sep 17 00:00:00 2001 From: robertmh Date: Sun, 25 Oct 2009 17:49:27 +0000 Subject: [PATCH 042/165] 2009-10-25 Robert Millan * util/i386/pc/grub-setup.c (setup): Add missing parameter to grub_util_error() call. --- ChangeLog | 5 +++++ util/i386/pc/grub-setup.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 81f3ba601..123a52cb6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-10-25 Robert Millan + + * util/i386/pc/grub-setup.c (setup): Add missing parameter to + grub_util_error() call. + 2009-10-25 Robert Millan * include/grub/fs.h [GRUB_UTIL] (struct grub_fs): Add diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index 5a46e9e24..c536be0c4 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -256,7 +256,8 @@ setup (const char *dir, grub_fs_t fs; fs = grub_fs_probe (dest_dev); if (! fs) - grub_util_error ("Unable to identify a filesystem in %s; safety check can't be performed."); + grub_util_error ("Unable to identify a filesystem in %s; safety check can't be performed.", + dest_dev->disk->name); if (! fs->reserved_first_sector) grub_util_error ("%s appears to contain a %s filesystem which isn't known to " From ee3756ccb3f14b7a3f7d5a967dea15b4104f97c5 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 26 Oct 2009 00:38:26 +0000 Subject: [PATCH 043/165] 2009-10-26 Robert Millan * util/grub.d/10_freebsd.in: Remove. --- ChangeLog | 4 +++ util/grub.d/10_freebsd.in | 76 --------------------------------------- 2 files changed, 4 insertions(+), 76 deletions(-) delete mode 100644 util/grub.d/10_freebsd.in diff --git a/ChangeLog b/ChangeLog index 123a52cb6..597dcafcb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-26 Robert Millan + + * util/grub.d/10_freebsd.in: Remove. + 2009-10-25 Robert Millan * util/i386/pc/grub-setup.c (setup): Add missing parameter to diff --git a/util/grub.d/10_freebsd.in b/util/grub.d/10_freebsd.in deleted file mode 100644 index 02694d3e7..000000000 --- a/util/grub.d/10_freebsd.in +++ /dev/null @@ -1,76 +0,0 @@ -#! /bin/sh -e - -# grub-mkconfig helper script. -# Copyright (C) 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 . - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib - -case "${GRUB_DISTRIBUTOR}" in - Debian) OS="${GRUB_DISTRIBUTOR} GNU/kFreeBSD" ;; - *) OS="FreeBSD" ;; -esac - -if test -e /boot/device.hints ; then - devices=/boot/device.hints -fi - -if test -e /boot/kernel/kernel ; then - kfreebsd=/boot/kernel/kernel -fi -if test -e /boot/kernel/kernel.gz ; then - kfreebsd=/boot/kernel/kernel.gz -fi - -if [ "x$kfreebsd" != "x" ] ; then - echo "Found kernel of FreeBSD: $kfreebsd" >&2 - - kfreebsd_basename=`basename $kfreebsd` - kfreebsd_dirname=`dirname $kfreebsd` - kfreebsd_rel_dirname=`make_system_path_relative_to_its_root $kfreebsd_dirname` - - if [ x"$devices" != "x" ] ; then - devices_basename=`basename $devices` - devices_dirname=`dirname $devices` - devices_rel_dirname=`make_system_path_relative_to_its_root $devices_dirname` - fi - - case ${GRUB_FS} in - ufs1 | ufs2) kfreebsd_fs=ufs ;; - *) kfreebsd_fs=${GRUB_FS} ;; - esac - - cat << EOF -menuentry "${OS}" { -EOF - prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" - cat << EOF - kfreebsd ${kfreebsd_rel_dirname}/${kfreebsd_basename} -EOF - - if [ x"$devices" != "x" ] ; then - cat << EOF - kfreebsd_loadenv ${devices_rel_dirname}/${devices_basename} -EOF - fi - cat << EOF - set kFreeBSD.vfs.root.mountfrom=${kfreebsd_fs}:${GRUB_DEVICE} - set kFreeBSD.vfs.root.mountfrom.options=rw -} -EOF -fi From 5c35048e23a02f91b7b910645e8b80993b65eab3 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 26 Oct 2009 00:38:38 +0000 Subject: [PATCH 044/165] 2009-10-26 Robert Millan * docs/grub.cfg: Fix example usage of *BSD loaders. --- ChangeLog | 2 +- docs/grub.cfg | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 597dcafcb..8a3c0dcb7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ 2009-10-26 Robert Millan - * util/grub.d/10_freebsd.in: Remove. + * docs/grub.cfg: Fix example usage of *BSD loaders. 2009-10-25 Robert Millan diff --git a/docs/grub.cfg b/docs/grub.cfg index 0a9ab6bc7..e14cdb776 100644 --- a/docs/grub.cfg +++ b/docs/grub.cfg @@ -34,26 +34,26 @@ menuentry "GNU/Linux" { # For booting FreeBSD menuentry "FreeBSD (or GNU/kFreeBSD), direct boot" { set root=(hd0,1,a) - freebsd /boot/kernel/kernel - freebsd_loadenv /boot/device.hints - freebsd_module /boot/splash.bmp type=splash_image_data - set FreeBSD.vfs.root.mountfrom=ufs:ad0s1a + kfreebsd /boot/kernel/kernel + kfreebsd_loadenv /boot/device.hints + kfreebsd_module /boot/splash.bmp type=splash_image_data + set kFreeBSD.vfs.root.mountfrom=ufs:ad0s1a } menuentry "FreeBSD (or GNU/kFreeBSD), via /boot/loader" { set root=(hd0,1,a) - freebsd /boot/loader + kfreebsd /boot/loader } # For booting NetBSD menuentry "NetBSD" { set root=(hd0,1,a) - netbsd /netbsd + knetbsd /netbsd } # For booting OpenBSD menuentry "OpenBSD" { set root=(hd0,1,a) - openbsd /bsd + kopenbsd /bsd } # For booting Microsoft Windows From 67937d4dca09e70d2d0a4ff72629ae1340355451 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 26 Oct 2009 00:41:54 +0000 Subject: [PATCH 045/165] 2009-10-26 Robert Millan * util/grub.d/10_freebsd.in: Remove. * util/grub.d/10_kfreebsd.in: New file (based on 10_linux.in). * configure.ac: Set host_kernel=kfreebsd for FreeBSD and GNU/kFreeBSD. --- ChangeLog | 6 +++ configure.ac | 2 +- util/grub.d/10_kfreebsd.in | 102 +++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 util/grub.d/10_kfreebsd.in diff --git a/ChangeLog b/ChangeLog index 8a3c0dcb7..6ca49a0e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-26 Robert Millan + + * util/grub.d/10_freebsd.in: Remove. + * util/grub.d/10_kfreebsd.in: New file (based on 10_linux.in). + * configure.ac: Set host_kernel=kfreebsd for FreeBSD and GNU/kFreeBSD. + 2009-10-26 Robert Millan * docs/grub.cfg: Fix example usage of *BSD loaders. diff --git a/configure.ac b/configure.ac index 048333ba5..4bd28f2e8 100644 --- a/configure.ac +++ b/configure.ac @@ -107,7 +107,7 @@ esac case "$host_os" in gnu*) host_kernel=hurd ;; linux*) host_kernel=linux ;; - freebsd* | kfreebsd*-gnu) host_kernel=freebsd ;; + freebsd* | kfreebsd*-gnu) host_kernel=kfreebsd ;; cygwin) host_kernel=windows ;; esac diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in new file mode 100644 index 000000000..1473a42a2 --- /dev/null +++ b/util/grub.d/10_kfreebsd.in @@ -0,0 +1,102 @@ +#! /bin/sh -e + +# grub-mkconfig helper script. +# Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +. ${libdir}/grub/grub-mkconfig_lib + +if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then + OS=GNU/Linux +else + OS="${GRUB_DISTRIBUTOR} GNU/Linux" +fi + +# loop-AES arranges things so that /dev/loop/X can be our root device, but +# the initrds that Linux uses don't like that. +case ${GRUB_DEVICE} in + /dev/loop/*|/dev/loop[0-9]) + GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"` + ;; +esac + +if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ + || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ; then + LINUX_ROOT_DEVICE=${GRUB_DEVICE} +else + LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} +fi + +linux_entry () +{ + cat << EOF +menuentry "$1" { +EOF + prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" + cat << EOF + linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro $2 +EOF + if test -n "${initrd}" ; then + cat << EOF + initrd ${rel_dirname}/${initrd} +EOF + fi + cat << EOF +} +EOF +} + +list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do + if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi + done` + +while [ "x$list" != "x" ] ; do + linux=`version_find_latest $list` + echo "Found linux image: $linux" >&2 + basename=`basename $linux` + dirname=`dirname $linux` + rel_dirname=`make_system_path_relative_to_its_root $dirname` + version=`echo $basename | sed -e "s,^[^0-9]*-,,g"` + alt_version=`echo $version | sed -e "s,\.old$,,g"` + linux_root_device_thisversion="${LINUX_ROOT_DEVICE}" + + initrd= + for i in "initrd.img-${version}" "initrd-${version}.img" \ + "initrd-${version}" "initrd.img-${alt_version}" \ + "initrd-${alt_version}.img" "initrd-${alt_version}"; do + if test -e "${dirname}/${i}" ; then + initrd="$i" + break + fi + done + if test -n "${initrd}" ; then + echo "Found initrd image: ${dirname}/${initrd}" >&2 + else + # "UUID=" magic is parsed by initrds. Since there's no initrd, it can't work here. + linux_root_device_thisversion=${GRUB_DEVICE} + fi + + linux_entry "${OS}, with Linux ${version}" \ + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" + if [ "x${GRUB_DISABLE_LINUX_RECOVERY}" != "xtrue" ]; then + linux_entry "${OS}, with Linux ${version} (recovery mode)" \ + "single ${GRUB_CMDLINE_LINUX}" + fi + + list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '` +done From ba36be41191d89f225a4b981ffcad474955f48e6 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 26 Oct 2009 00:41:58 +0000 Subject: [PATCH 046/165] 2009-10-26 Robert Millan * util/grub.d/10_freebsd.in: Remove. * util/grub.d/10_kfreebsd.in: New file (based on 10_linux.in). * configure.ac: Set host_kernel=kfreebsd for FreeBSD and GNU/kFreeBSD. --- util/grub.d/10_kfreebsd.in | 98 +++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index 1473a42a2..4fb704c49 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -21,82 +21,82 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ . ${libdir}/grub/grub-mkconfig_lib -if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then - OS=GNU/Linux -else - OS="${GRUB_DISTRIBUTOR} GNU/Linux" -fi - -# loop-AES arranges things so that /dev/loop/X can be our root device, but -# the initrds that Linux uses don't like that. -case ${GRUB_DEVICE} in - /dev/loop/*|/dev/loop[0-9]) - GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"` - ;; +case "${GRUB_DISTRIBUTOR}" in + Debian) OS="${GRUB_DISTRIBUTOR} GNU/kFreeBSD" ;; + *) OS="FreeBSD" ;; esac -if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ - || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ; then - LINUX_ROOT_DEVICE=${GRUB_DEVICE} -else - LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} -fi - -linux_entry () +kfreebsd_entry () { cat << EOF menuentry "$1" { EOF prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" cat << EOF - linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro $2 + kfreebsd ${rel_dirname}/${basename} EOF - if test -n "${initrd}" ; then + + if test -n "${devices}" ; then cat << EOF - initrd ${rel_dirname}/${initrd} + kfreebsd_loadenv ${devices_rel_dirname}/${devices_basename} EOF fi + + if test -n "${acpi_ko}" ; then + cat << EOF + kfreebsd_module_elf ${acpi_ko_rel_dirname}/${acpi_ko_basename} +EOF + fi + cat << EOF + set kFreeBSD.vfs.root.mountfrom=${kfreebsd_fs}:${GRUB_DEVICE} + set kFreeBSD.vfs.root.mountfrom.options=rw } EOF } -list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do +list=`for i in /boot/kfreebsd-* /boot/kernel/kernel ; do if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi done` while [ "x$list" != "x" ] ; do - linux=`version_find_latest $list` - echo "Found linux image: $linux" >&2 - basename=`basename $linux` - dirname=`dirname $linux` + kfreebsd=`version_find_latest $list` + echo "Found kernel of FreeBSD: $kfreebsd" >&2 + basename=`basename $kfreebsd` + dirname=`dirname $kfreebsd` rel_dirname=`make_system_path_relative_to_its_root $dirname` - version=`echo $basename | sed -e "s,^[^0-9]*-,,g"` - alt_version=`echo $version | sed -e "s,\.old$,,g"` - linux_root_device_thisversion="${LINUX_ROOT_DEVICE}" - initrd= - for i in "initrd.img-${version}" "initrd-${version}.img" \ - "initrd-${version}" "initrd.img-${alt_version}" \ - "initrd-${alt_version}.img" "initrd-${alt_version}"; do - if test -e "${dirname}/${i}" ; then - initrd="$i" + if [ -f /boot/device.hints ] ; then + devices=/boot/device.hints + devices_basename=`basename $devices` + devices_dirname=`dirname $devices` + devices_rel_dirname=`make_system_path_relative_to_its_root $devices_dirname` + fi + + case ${GRUB_FS} in + ufs1 | ufs2) kfreebsd_fs=ufs ;; + *) kfreebsd_fs=${GRUB_FS} ;; + esac + + version=`echo $basename | sed -e "s,^[^0-9]*-,,g;s/\.gz$//g"` + alt_version=`echo $version | sed -e "s,\.old$,,g"` + + acpi_ko= + for i in "/lib/modules/${version}/acpi.ko" "/lib/modules/${alt_version}/acpi.ko" \ + "/boot/kernel/acpi.ko"; do + if test -e "$i" ; then + acpi_ko="$i" break fi done - if test -n "${initrd}" ; then - echo "Found initrd image: ${dirname}/${initrd}" >&2 - else - # "UUID=" magic is parsed by initrds. Since there's no initrd, it can't work here. - linux_root_device_thisversion=${GRUB_DEVICE} + if test -n "${acpi_ko}" ; then + echo "Found ACPI module: ${acpi_ko}" >&2 + acpi_ko_basename=`basename ${acpi_ko}` + acpi_ko_dirname=`dirname ${acpi_ko}` + acpi_ko_rel_dirname=`make_system_path_relative_to_its_root $acpi_ko_dirname` fi - linux_entry "${OS}, with Linux ${version}" \ - "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" - if [ "x${GRUB_DISABLE_LINUX_RECOVERY}" != "xtrue" ]; then - linux_entry "${OS}, with Linux ${version} (recovery mode)" \ - "single ${GRUB_CMDLINE_LINUX}" - fi + kfreebsd_entry "${OS}, kFreeBSD ${version}" - list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '` + list=`echo $list | tr ' ' '\n' | grep -vx $kfreebsd | tr '\n' ' '` done From e4f6809bbc51ceac3eea354a3f264b3cf0c483d3 Mon Sep 17 00:00:00 2001 From: cjwatson Date: Mon, 26 Oct 2009 16:28:04 +0000 Subject: [PATCH 047/165] 2009-10-26 Colin Watson Improve grub-mkconfig performance when there are several menu entries on a single filesystem. * util/grub.d/10_linux.in (linux_entry): Cache the output of prepare_grub_to_access_device. * util/grub.d/10_kfreebsd.in (kfreebsd_entry): Likewise. * util/grub.d/30_os-prober.in: Likewise. --- ChangeLog | 10 ++++++++++ util/grub.d/10_kfreebsd.in | 6 +++++- util/grub.d/10_linux.in | 6 +++++- util/grub.d/30_os-prober.in | 6 +++++- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6ca49a0e2..e7e01fa37 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-10-26 Colin Watson + + Improve grub-mkconfig performance when there are several menu + entries on a single filesystem. + + * util/grub.d/10_linux.in (linux_entry): Cache the output of + prepare_grub_to_access_device. + * util/grub.d/10_kfreebsd.in (kfreebsd_entry): Likewise. + * util/grub.d/30_os-prober.in: Likewise. + 2009-10-26 Robert Millan * util/grub.d/10_freebsd.in: Remove. diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index 4fb704c49..cd8c186be 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -31,7 +31,10 @@ kfreebsd_entry () cat << EOF menuentry "$1" { EOF - prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" + if [ -z "${prepare_boot_cache}" ]; then + prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" + fi + printf '%s\n' "${prepare_boot_cache}" cat << EOF kfreebsd ${rel_dirname}/${basename} EOF @@ -58,6 +61,7 @@ EOF list=`for i in /boot/kfreebsd-* /boot/kernel/kernel ; do if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi done` +prepare_boot_cache= while [ "x$list" != "x" ] ; do kfreebsd=`version_find_latest $list` diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 1473a42a2..f17955846 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -47,7 +47,10 @@ linux_entry () cat << EOF menuentry "$1" { EOF - prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" + if [ -z "${prepare_boot_cache}" ]; then + prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" + fi + printf '%s\n' "${prepare_boot_cache}" cat << EOF linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro $2 EOF @@ -64,6 +67,7 @@ EOF list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi done` +prepare_boot_cache= while [ "x$list" != "x" ] ; do linux=`version_find_latest $list` diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in index 84e227ee7..6fd97fc4e 100644 --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in @@ -74,6 +74,7 @@ EOF ;; linux) LINUXPROBED="`linux-boot-prober ${DEVICE} 2> /dev/null | tr ' ' '^' | paste -s -d ' '`" + prepare_boot_cache= for LINUX in ${LINUXPROBED} ; do LROOT="`echo ${LINUX} | cut -d ':' -f 1`" @@ -90,7 +91,10 @@ EOF cat << EOF menuentry "${LLABEL} (on ${DEVICE})" { EOF - prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" + if [ -z "${prepare_boot_cache}" ]; then + prepare_boot_cache="$(prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/")" + fi + printf '%s\n' "${prepare_boot_cache}" cat << EOF linux ${LKERNEL} ${LPARAMS} EOF From 9031b03aaca8c601f60e13ab5cc9f032094cb119 Mon Sep 17 00:00:00 2001 From: cjwatson Date: Mon, 26 Oct 2009 16:33:13 +0000 Subject: [PATCH 048/165] 2009-10-26 Colin Watson * util/grub-editenv.c (main): If only a command is given, use DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG as a default file name. (usage): FILENAME is now optional and has a default. --- ChangeLog | 6 ++++++ util/grub-editenv.c | 19 ++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index e7e01fa37..ab7ccf39c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-26 Colin Watson + + * util/grub-editenv.c (main): If only a command is given, use + DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG as a default file name. + (usage): FILENAME is now optional and has a default. + 2009-10-26 Colin Watson Improve grub-mkconfig performance when there are several menu diff --git a/util/grub-editenv.c b/util/grub-editenv.c index a8dc137c5..5b688d9cb 100644 --- a/util/grub-editenv.c +++ b/util/grub-editenv.c @@ -72,7 +72,7 @@ usage (int status) fprintf (stderr, "Try ``grub-editenv --help'' for more information.\n"); else printf ("\ -Usage: grub-editenv [OPTIONS] FILENAME COMMAND\n\ +Usage: grub-editenv [OPTIONS] [FILENAME] COMMAND\n\ \n\ Tool to edit environment block.\n\ \nCommands:\n\ @@ -85,7 +85,10 @@ Tool to edit environment block.\n\ -V, --version print version information and exit\n\ -v, --verbose print verbose messages\n\ \n\ -Report bugs to <%s>.\n", PACKAGE_BUGREPORT); +If not given explicitly, FILENAME defaults to %s.\n\ +\n\ +Report bugs to <%s>.\n", +DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG, PACKAGE_BUGREPORT); exit (status); } @@ -288,12 +291,14 @@ main (int argc, char *argv[]) if (optind + 1 >= argc) { - fprintf (stderr, "no command specified\n"); - usage (1); + filename = DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG; + command = argv[optind]; + } + else + { + filename = argv[optind]; + command = argv[optind + 1]; } - - filename = argv[optind]; - command = argv[optind + 1]; if (strcmp (command, "create") == 0) create_envblk_file (filename); From 94180ff6c7166b80ca18ef30587abc372e0e30fd Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 26 Oct 2009 18:02:19 +0000 Subject: [PATCH 049/165] 2009-10-26 Robert Millan * conf/i386-coreboot.rmk (script/sh/lexer.c_DEPENDENCIES): Moved from here ... * conf/common.rmk (script/sh/lexer.c_DEPENDENCIES): ... to here. * conf/i386-efi.rmk (script/sh/lexer.c_DEPENDENCIES): Remove. * conf/i386-ieee1275.rmk: Likewise. * conf/i386-pc.rmk: Likewise. * conf/powerpc-ieee1275.rmk: Likewise. * conf/sparc64-ieee1275.rmk: Likewise. * conf/x86_64-efi.rmk: Likewise. --- ChangeLog | 12 ++++++++++++ conf/common.rmk | 2 ++ conf/i386-coreboot.rmk | 1 - conf/i386-efi.rmk | 1 - conf/i386-ieee1275.rmk | 1 - conf/i386-pc.rmk | 1 - conf/powerpc-ieee1275.rmk | 1 - conf/sparc64-ieee1275.rmk | 1 - conf/x86_64-efi.rmk | 1 - 9 files changed, 14 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index ab7ccf39c..5a1a7b35e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2009-10-26 Robert Millan + + * conf/i386-coreboot.rmk (script/sh/lexer.c_DEPENDENCIES): Moved + from here ... + * conf/common.rmk (script/sh/lexer.c_DEPENDENCIES): ... to here. + * conf/i386-efi.rmk (script/sh/lexer.c_DEPENDENCIES): Remove. + * conf/i386-ieee1275.rmk: Likewise. + * conf/i386-pc.rmk: Likewise. + * conf/powerpc-ieee1275.rmk: Likewise. + * conf/sparc64-ieee1275.rmk: Likewise. + * conf/x86_64-efi.rmk: Likewise. + 2009-10-26 Colin Watson * util/grub-editenv.c (main): If only a command is given, use diff --git a/conf/common.rmk b/conf/common.rmk index c1f0bbdcf..ce7c33084 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -1,5 +1,7 @@ # -*- makefile -*- +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h + # For grub-mkelfimage. bin_UTILITIES += grub-mkelfimage grub_mkelfimage_SOURCES = util/elf/grub-mkimage.c util/misc.c \ diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk index 09ec7787c..3c2061b4e 100644 --- a/conf/i386-coreboot.rmk +++ b/conf/i386-coreboot.rmk @@ -5,7 +5,6 @@ COMMON_CFLAGS = -fno-builtin -mrtd -mregparm=3 -m32 COMMON_LDFLAGS = -m32 -nostdlib # Used by various components. These rules need to precede them. -script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk index 99ab06f64..0440359e5 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -5,7 +5,6 @@ COMMON_CFLAGS = -fno-builtin -m32 COMMON_LDFLAGS = -melf_i386 -nostdlib # Used by various components. These rules need to precede them. -script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Utilities. bin_UTILITIES = grub-mkimage diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk index 4b640de49..c70ecf4dd 100644 --- a/conf/i386-ieee1275.rmk +++ b/conf/i386-ieee1275.rmk @@ -5,7 +5,6 @@ COMMON_CFLAGS = -ffreestanding -mrtd -mregparm=3 COMMON_LDFLAGS = -nostdlib # Used by various components. These rules need to precede them. -script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. pkglib_PROGRAMS = kernel.img diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index bf8fbfb9d..30847dfa7 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -7,7 +7,6 @@ COMMON_CFLAGS = -fno-builtin -mrtd -mregparm=3 -m32 COMMON_LDFLAGS = -m32 -nostdlib # Used by various components. These rules need to precede them. -script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. pkglib_IMAGES = boot.img cdboot.img diskboot.img kernel.img lnxboot.img \ diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index ee7f9ec27..9165e4bc0 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -6,7 +6,6 @@ COMMON_CFLAGS = -ffreestanding COMMON_LDFLAGS += -nostdlib # Used by various components. These rules need to precede them. -script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk index 62e951a5e..1156fe2a9 100644 --- a/conf/sparc64-ieee1275.rmk +++ b/conf/sparc64-ieee1275.rmk @@ -6,7 +6,6 @@ COMMON_CFLAGS = -ffreestanding -m64 -mno-app-regs COMMON_LDFLAGS = -melf64_sparc -nostdlib -mno-relax # Used by various components. These rules need to precede them. -script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. pkglib_IMAGES = boot.img diskboot.img kernel.img diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk index 5be1b404f..173227575 100644 --- a/conf/x86_64-efi.rmk +++ b/conf/x86_64-efi.rmk @@ -5,7 +5,6 @@ COMMON_CFLAGS = -fno-builtin -m64 COMMON_LDFLAGS = -melf_x86_64 -nostdlib # Used by various components. These rules need to precede them. -script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Utilities. bin_UTILITIES = grub-mkimage From 5947ae32f588d62077cbf341382a78fc9efc2f5b Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 26 Oct 2009 18:02:30 +0000 Subject: [PATCH 050/165] 2009-10-26 Robert Millan * Makefile.in (docs/grub.info): Use make syntax to ignore errors in $(MAKEINFO) invocation. This makes it clear in output that errors are being ignored. --- ChangeLog | 6 ++++++ Makefile.in | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5a1a7b35e..2a9c04844 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-26 Robert Millan + + * Makefile.in (docs/grub.info): Use make syntax to ignore errors + in $(MAKEINFO) invocation. This makes it clear in output that + errors are being ignored. + 2009-10-26 Robert Millan * conf/i386-coreboot.rmk (script/sh/lexer.c_DEPENDENCIES): Moved diff --git a/Makefile.in b/Makefile.in index e0edbdb04..80ed07124 100644 --- a/Makefile.in +++ b/Makefile.in @@ -197,7 +197,7 @@ docs/stamp-vti: docs/grub.texi configure.ac # Use --force until such time as the documentation is cleaned up. docs/grub.info: docs/grub.texi docs/version.texi docs/fdl.texi $(MKDIR_P) docs - $(MAKEINFO) -P $(builddir)/docs --no-split --force $< -o $@ || : + -$(MAKEINFO) -P $(builddir)/docs --no-split --force $< -o $@ ifeq (, $(UNIFONT_BDF)) else From 083d16798e9ab51e3b2cd7fb94c7e960bb92f8de Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 26 Oct 2009 18:04:37 +0000 Subject: [PATCH 051/165] 2009-10-26 Robert Millan * gensymlist.sh.in (COMPILE_TIME_ASSERT): Copy macro declaration from here ... * include/grub/misc.h (COMPILE_TIME_ASSERT): ... to here. --- ChangeLog | 6 ++++++ include/grub/misc.h | 1 + 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2a9c04844..afe67af2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-26 Robert Millan + + * gensymlist.sh.in (COMPILE_TIME_ASSERT): Copy macro declaration + from here ... + * include/grub/misc.h (COMPILE_TIME_ASSERT): ... to here. + 2009-10-26 Robert Millan * Makefile.in (docs/grub.info): Use make syntax to ignore errors diff --git a/include/grub/misc.h b/include/grub/misc.h index 7589f43a2..e3a062898 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -28,6 +28,7 @@ #define ALIGN_UP(addr, align) \ ((addr + (typeof (addr)) align - 1) & ~((typeof (addr)) align - 1)) #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0])) +#define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; } #define grub_dprintf(condition, fmt, args...) grub_real_dprintf(__FILE__, __LINE__, condition, fmt, ## args) /* XXX: If grub_memmove is too slow, we must implement grub_memcpy. */ From 478df40933d8acb1e6cdae9af4b7eb70cb3ee983 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 26 Oct 2009 18:06:23 +0000 Subject: [PATCH 052/165] 2009-10-26 Robert Millan * disk/scsi.c: Remove `' (not needed). --- ChangeLog | 4 ++++ disk/scsi.c | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index afe67af2b..769e4fb2a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-26 Robert Millan + + * disk/scsi.c: Remove `' (not needed). + 2009-10-26 Robert Millan * gensymlist.sh.in (COMPILE_TIME_ASSERT): Copy macro declaration diff --git a/disk/scsi.c b/disk/scsi.c index 24ebdb6cd..d0e248511 100644 --- a/disk/scsi.c +++ b/disk/scsi.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include From 0579b753d611588a50604934253c32e4abb33455 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 26 Oct 2009 18:25:02 +0000 Subject: [PATCH 053/165] 2009-10-26 Robert Millan * Makefile.in (RMKFILES): Rewrite using $(wildcard). --- ChangeLog | 4 ++++ Makefile.in | 4 +--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 769e4fb2a..1e05f770e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-26 Robert Millan + + * Makefile.in (RMKFILES): Rewrite using $(wildcard). + 2009-10-26 Robert Millan * disk/scsi.c: Remove `' (not needed). diff --git a/Makefile.in b/Makefile.in index 80ed07124..bde80889b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -115,9 +115,7 @@ enable_efiemu = @enable_efiemu@ ### General variables. -RMKFILES = $(addprefix conf/,common.rmk i386-coreboot.rmk i386-efi.rmk \ - i386-qemu.rmk i386-ieee1275.rmk i386-pc.rmk i386.rmk powerpc-ieee1275.rmk \ - sparc64-ieee1275.rmk x86_64-efi.rmk) +RMKFILES = $(wildcard conf/*.rmk) MKFILES = $(patsubst %.rmk,%.mk,$(RMKFILES)) From ed96ab6d201e50fbeb7833f7d85e0a1182a62f40 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 26 Oct 2009 19:39:35 +0000 Subject: [PATCH 054/165] 2009-10-26 Robert Millan * gendistlist.sh: Simplify .svn check. Skip .bzr as well. --- ChangeLog | 4 ++++ gendistlist.sh | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1e05f770e..b59e2d945 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-26 Robert Millan + + * gendistlist.sh: Simplify .svn check. Skip .bzr as well. + 2009-10-26 Robert Millan * Makefile.in (RMKFILES): Rewrite using $(wildcard). diff --git a/gendistlist.sh b/gendistlist.sh index 7f6c32a44..36685a092 100644 --- a/gendistlist.sh +++ b/gendistlist.sh @@ -35,7 +35,7 @@ dir=`dirname $0` cd $dir for dir in $DISTDIRS; do - for d in `find $dir -type d | sed '/\/\.svn$/d;\/\.svn\//d' | sort`; do + for d in `find $dir -type d -not -name .svn -not -name .bzr | sort`; do find $d -maxdepth 1 -name '*.[chSy]' -o -name '*.mk' -o -name '*.rmk' \ -o -name '*.rb' -o -name '*.in' -o -name '*.tex' -o -name '*.texi' \ -o -name '*.info' -o -name 'grub.cfg' -o -name 'README' \ From cefabfe1c4fb58877770034db338d850d2e6f0b9 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 26 Oct 2009 20:04:43 +0000 Subject: [PATCH 055/165] 2009-10-26 Robert Millan * autogen.sh: Support addition of external modules via `GRUB_CONTRIB' variable. * Makefile.in: Likewise. --- ChangeLog | 6 ++++++ Makefile.in | 3 +++ autogen.sh | 6 ++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b59e2d945..56ff263ed 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-26 Robert Millan + + * autogen.sh: Support addition of external modules via `GRUB_CONTRIB' + variable. + * Makefile.in: Likewise. + 2009-10-26 Robert Millan * gendistlist.sh: Simplify .svn check. Skip .bzr as well. diff --git a/Makefile.in b/Makefile.in index bde80889b..f99bc3c2a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -148,6 +148,9 @@ $(addprefix $(srcdir)/,$(MKFILES)): %.mk: %.rmk genmk.rb include $(srcdir)/conf/$(target_cpu)-$(platform).mk +# For external modules. +-include $(wildcard $(GRUB_CONTRIB)/*/conf/common.mk) + ### General targets. CLEANFILES += $(pkglib_DATA) $(pkgdata_DATA) diff --git a/autogen.sh b/autogen.sh index 6895de221..4fb6bf7db 100644 --- a/autogen.sh +++ b/autogen.sh @@ -5,8 +5,10 @@ set -e autoconf autoheader echo timestamp > stamp-h.in -for rmk in conf/*.rmk; do - ruby genmk.rb < $rmk > `echo $rmk | sed 's/\.rmk$/.mk/'` +for rmk in conf/*.rmk ${GRUB_CONTRIB}/*/conf/*.rmk; do + if test -e $rmk ; then + ruby genmk.rb < $rmk > `echo $rmk | sed 's/\.rmk$/.mk/'` + fi done ./gendistlist.sh > DISTLIST From fdcdde1905d36e3ff8283ae3c9b97ea1d37fde50 Mon Sep 17 00:00:00 2001 From: fzielcke Date: Wed, 28 Oct 2009 18:24:10 +0000 Subject: [PATCH 056/165] 2009-10-28 Felix Zielcke * commands/acpi.c (grub_cmd_acpi): Fix the out of memory error strings. --- ChangeLog | 5 +++++ commands/acpi.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 56ff263ed..1a1be5746 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-10-28 Felix Zielcke + + * commands/acpi.c (grub_cmd_acpi): Fix the out of memory error + strings. + 2009-10-26 Robert Millan * autogen.sh: Support addition of external modules via `GRUB_CONTRIB' diff --git a/commands/acpi.c b/commands/acpi.c index e7cb9e6b4..9cfd8ef10 100644 --- a/commands/acpi.c +++ b/commands/acpi.c @@ -552,7 +552,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd, grub_free (exclude); grub_free (load_only); return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "Could allocate table"); + "Couldn't allocate table"); } grub_memcpy (table_dsdt, dsdt, dsdt->length); } @@ -579,7 +579,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd, grub_free (exclude); grub_free (load_only); return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "Could allocate table structure"); + "Couldn't allocate table structure"); } table->size = curtable->length; table->addr = grub_malloc (table->size); @@ -588,7 +588,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd, { free_tables (); return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "Could allocate table"); + "Couldn't allocate table"); } table->next = acpi_tables; acpi_tables = table; @@ -675,7 +675,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd, { free_tables (); return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "Could allocate table structure"); + "Couldn't allocate table structure"); } table->size = size; From 2ed19dfdeda64c7319fde370b6e4e14f5ee85894 Mon Sep 17 00:00:00 2001 From: robertmh Date: Wed, 28 Oct 2009 22:02:54 +0000 Subject: [PATCH 057/165] 2009-10-28 Robert Millan * kern/i386/coreboot/init.c (grub_exit): Reimplement in a way that doesn't cause an infinite call loop. --- ChangeLog | 5 +++++ kern/i386/coreboot/init.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1a1be5746..a792f04e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-10-28 Robert Millan + + * kern/i386/coreboot/init.c (grub_exit): Reimplement in a way that + doesn't cause an infinite call loop. + 2009-10-28 Felix Zielcke * commands/acpi.c (grub_cmd_acpi): Fix the out of memory error diff --git a/kern/i386/coreboot/init.c b/kern/i386/coreboot/init.c index 1b9ca3815..0bf4934fb 100644 --- a/kern/i386/coreboot/init.c +++ b/kern/i386/coreboot/init.c @@ -62,7 +62,10 @@ grub_stop_floppy (void) void grub_exit (void) { - grub_fatal ("grub_exit() is not implemented.\n"); + /* We can't use grub_fatal() in this function. This would create an infinite + loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */ + while (1) + grub_cpu_idle (); } void From 95b9239e13de05188c989c1542b936a62b5e8c10 Mon Sep 17 00:00:00 2001 From: robertmh Date: Wed, 28 Oct 2009 22:55:27 +0000 Subject: [PATCH 058/165] 2009-10-28 Robert Millan * include/grub/misc.h: Stop checking for APPLE_CC. --- ChangeLog | 4 ++++ include/grub/misc.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a792f04e5..ff7098c58 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-28 Robert Millan + + * include/grub/misc.h: Stop checking for APPLE_CC. + 2009-10-28 Robert Millan * kern/i386/coreboot/init.c (grub_exit): Reimplement in a way that diff --git a/include/grub/misc.h b/include/grub/misc.h index e3a062898..faa2d5c42 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -76,7 +76,7 @@ grub_strncat (char *dest, const char *src, int c) } /* Prototypes for aliases. */ -#if !defined (GRUB_UTIL) && !defined (APPLE_CC) +#ifndef GRUB_UTIL int EXPORT_FUNC(memcmp) (const void *s1, const void *s2, grub_size_t n); void *EXPORT_FUNC(memmove) (void *dest, const void *src, grub_size_t n); void *EXPORT_FUNC(memcpy) (void *dest, const void *src, grub_size_t n); From cee15086c312902c4e4bfe26829746b67cdd05d3 Mon Sep 17 00:00:00 2001 From: robertmh Date: Wed, 28 Oct 2009 23:16:32 +0000 Subject: [PATCH 059/165] 2009-10-28 Robert Millan * Makefile.in (TARGET_CPPFLAGS): Add `-nostdinc'. --- ChangeLog | 4 ++++ Makefile.in | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ff7098c58..12e8932e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-10-28 Robert Millan + + * Makefile.in (TARGET_CPPFLAGS): Add `-nostdinc'. + 2009-10-28 Robert Millan * include/grub/misc.h: Stop checking for APPLE_CC. diff --git a/Makefile.in b/Makefile.in index f99bc3c2a..103d2d3d2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -75,7 +75,7 @@ TARGET_ASFLAGS = @TARGET_ASFLAGS@ TARGET_MODULE_FORMAT = @TARGET_MODULE_FORMAT@ TARGET_APPLE_CC = @TARGET_APPLE_CC@ OBJCONV = @OBJCONV@ -TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -I$(builddir) -I$(builddir)/include -I$(srcdir)/include \ +TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -nostdinc -I$(builddir) -I$(builddir)/include -I$(srcdir)/include \ -Wall -W TARGET_LDFLAGS = @TARGET_LDFLAGS@ TARGET_IMG_LDSCRIPT = @TARGET_IMG_LDSCRIPT@ From fa6e945f506c09046acebee1963398daca3b83fe Mon Sep 17 00:00:00 2001 From: robertmh Date: Thu, 29 Oct 2009 10:03:13 +0000 Subject: [PATCH 060/165] 2009-10-29 Robert Millan Revert SVN r2660. * conf/common.rmk (script/sh/lexer.c_DEPENDENCIES): Moved from here ... * conf/i386-coreboot.rmk (script/sh/lexer.c_DEPENDENCIES): ... to here. * conf/i386-efi.rmk (script/sh/lexer.c_DEPENDENCIES): ... and here. * conf/i386-ieee1275.rmk: Likewise. * conf/i386-pc.rmk: Likewise. * conf/powerpc-ieee1275.rmk: Likewise. * conf/sparc64-ieee1275.rmk: Likewise. * conf/x86_64-efi.rmk: Likewise. --- ChangeLog | 13 +++++++++++++ conf/common.rmk | 2 -- conf/i386-coreboot.rmk | 1 + conf/i386-efi.rmk | 1 + conf/i386-ieee1275.rmk | 1 + conf/i386-pc.rmk | 1 + conf/powerpc-ieee1275.rmk | 1 + conf/sparc64-ieee1275.rmk | 1 + conf/x86_64-efi.rmk | 1 + 9 files changed, 20 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 12e8932e7..1d504a2cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2009-10-29 Robert Millan + + Revert SVN r2660. + + * conf/common.rmk (script/sh/lexer.c_DEPENDENCIES): Moved from here ... + * conf/i386-coreboot.rmk (script/sh/lexer.c_DEPENDENCIES): ... to here. + * conf/i386-efi.rmk (script/sh/lexer.c_DEPENDENCIES): ... and here. + * conf/i386-ieee1275.rmk: Likewise. + * conf/i386-pc.rmk: Likewise. + * conf/powerpc-ieee1275.rmk: Likewise. + * conf/sparc64-ieee1275.rmk: Likewise. + * conf/x86_64-efi.rmk: Likewise. + 2009-10-28 Robert Millan * Makefile.in (TARGET_CPPFLAGS): Add `-nostdinc'. diff --git a/conf/common.rmk b/conf/common.rmk index ce7c33084..c1f0bbdcf 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -1,7 +1,5 @@ # -*- makefile -*- -script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h - # For grub-mkelfimage. bin_UTILITIES += grub-mkelfimage grub_mkelfimage_SOURCES = util/elf/grub-mkimage.c util/misc.c \ diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk index 3c2061b4e..09ec7787c 100644 --- a/conf/i386-coreboot.rmk +++ b/conf/i386-coreboot.rmk @@ -5,6 +5,7 @@ COMMON_CFLAGS = -fno-builtin -mrtd -mregparm=3 -m32 COMMON_LDFLAGS = -m32 -nostdlib # Used by various components. These rules need to precede them. +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk index 0440359e5..99ab06f64 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -5,6 +5,7 @@ COMMON_CFLAGS = -fno-builtin -m32 COMMON_LDFLAGS = -melf_i386 -nostdlib # Used by various components. These rules need to precede them. +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Utilities. bin_UTILITIES = grub-mkimage diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk index c70ecf4dd..4b640de49 100644 --- a/conf/i386-ieee1275.rmk +++ b/conf/i386-ieee1275.rmk @@ -5,6 +5,7 @@ COMMON_CFLAGS = -ffreestanding -mrtd -mregparm=3 COMMON_LDFLAGS = -nostdlib # Used by various components. These rules need to precede them. +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. pkglib_PROGRAMS = kernel.img diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 30847dfa7..bf8fbfb9d 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -7,6 +7,7 @@ COMMON_CFLAGS = -fno-builtin -mrtd -mregparm=3 -m32 COMMON_LDFLAGS = -m32 -nostdlib # Used by various components. These rules need to precede them. +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. pkglib_IMAGES = boot.img cdboot.img diskboot.img kernel.img lnxboot.img \ diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index 9165e4bc0..ee7f9ec27 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -6,6 +6,7 @@ COMMON_CFLAGS = -ffreestanding COMMON_LDFLAGS += -nostdlib # Used by various components. These rules need to precede them. +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk index 1156fe2a9..62e951a5e 100644 --- a/conf/sparc64-ieee1275.rmk +++ b/conf/sparc64-ieee1275.rmk @@ -6,6 +6,7 @@ COMMON_CFLAGS = -ffreestanding -m64 -mno-app-regs COMMON_LDFLAGS = -melf64_sparc -nostdlib -mno-relax # Used by various components. These rules need to precede them. +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Images. pkglib_IMAGES = boot.img diskboot.img kernel.img diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk index 173227575..5be1b404f 100644 --- a/conf/x86_64-efi.rmk +++ b/conf/x86_64-efi.rmk @@ -5,6 +5,7 @@ COMMON_CFLAGS = -fno-builtin -m64 COMMON_LDFLAGS = -melf_x86_64 -nostdlib # Used by various components. These rules need to precede them. +script/sh/lexer.c_DEPENDENCIES = grub_script.tab.h # Utilities. bin_UTILITIES = grub-mkimage From 805111a4fd4183d134e5da13530b57fd0b3677b3 Mon Sep 17 00:00:00 2001 From: robertmh Date: Fri, 30 Oct 2009 22:37:38 +0000 Subject: [PATCH 061/165] 2009-10-30 Robert Millan * util/i386/pc/grub-install.in: Remove hint that device.map should be checked (grub-install doesn't currently rely on it). --- ChangeLog | 5 +++++ util/i386/pc/grub-install.in | 7 ------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1d504a2cc..26de80e89 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-10-30 Robert Millan + + * util/i386/pc/grub-install.in: Remove hint that device.map should be + checked (grub-install doesn't currently rely on it). + 2009-10-29 Robert Millan Revert SVN r2660. diff --git a/util/i386/pc/grub-install.in b/util/i386/pc/grub-install.in index 69028b662..8a06213cb 100644 --- a/util/i386/pc/grub-install.in +++ b/util/i386/pc/grub-install.in @@ -319,14 +319,7 @@ else $grub_mkimage -d ${pkglibdir} --output=/boot/multiboot.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 fi -# Prompt the user to check if the device map is correct. echo "Installation finished. No error reported." -echo "This is the contents of the device map $device_map." -echo "Check if this is correct or not. If any of the lines is incorrect," -echo "fix it and re-run the script \`grub-install'." -echo - -cat $device_map # Bye. exit 0 From d9e2cd701b71fd46a344f1e9b1075c8fe4499658 Mon Sep 17 00:00:00 2001 From: robertmh Date: Fri, 30 Oct 2009 22:51:52 +0000 Subject: [PATCH 062/165] 2009-10-30 Robert Millan Fix build problem. * Makefile.in (TARGET_CPPFLAGS): Replace `-nostdinc' with `-isystem=$(srcdir)/include'. --- ChangeLog | 7 +++++++ Makefile.in | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 26de80e89..25d7b753d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2009-10-30 Robert Millan + + Fix build problem. + + * Makefile.in (TARGET_CPPFLAGS): Replace `-nostdinc' with + `-isystem=$(srcdir)/include'. + 2009-10-30 Robert Millan * util/i386/pc/grub-install.in: Remove hint that device.map should be diff --git a/Makefile.in b/Makefile.in index 103d2d3d2..2776fff17 100644 --- a/Makefile.in +++ b/Makefile.in @@ -75,7 +75,7 @@ TARGET_ASFLAGS = @TARGET_ASFLAGS@ TARGET_MODULE_FORMAT = @TARGET_MODULE_FORMAT@ TARGET_APPLE_CC = @TARGET_APPLE_CC@ OBJCONV = @OBJCONV@ -TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -nostdinc -I$(builddir) -I$(builddir)/include -I$(srcdir)/include \ +TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -isystem=$(srcdir)/include -I$(builddir) -I$(builddir)/include \ -Wall -W TARGET_LDFLAGS = @TARGET_LDFLAGS@ TARGET_IMG_LDSCRIPT = @TARGET_IMG_LDSCRIPT@ From 5b1538672ef1c87b9fb88b43a46fb5c00b210630 Mon Sep 17 00:00:00 2001 From: fzielcke Date: Sun, 1 Nov 2009 18:19:04 +0000 Subject: [PATCH 063/165] 2009-11-01 Felix Zielcke * Makefile.in (TARGET_CPPFLAGS): Add `-I$(srcdir)/include'. --- ChangeLog | 4 ++++ Makefile.in | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 25d7b753d..2e5c7484d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-11-01 Felix Zielcke + + * Makefile.in (TARGET_CPPFLAGS): Add `-I$(srcdir)/include'. + 2009-10-30 Robert Millan Fix build problem. diff --git a/Makefile.in b/Makefile.in index 2776fff17..61b966995 100644 --- a/Makefile.in +++ b/Makefile.in @@ -75,7 +75,7 @@ TARGET_ASFLAGS = @TARGET_ASFLAGS@ TARGET_MODULE_FORMAT = @TARGET_MODULE_FORMAT@ TARGET_APPLE_CC = @TARGET_APPLE_CC@ OBJCONV = @OBJCONV@ -TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -isystem=$(srcdir)/include -I$(builddir) -I$(builddir)/include \ +TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -isystem=$(srcdir)/include -I$(srcdir)/include -I$(builddir) -I$(builddir)/include \ -Wall -W TARGET_LDFLAGS = @TARGET_LDFLAGS@ TARGET_IMG_LDSCRIPT = @TARGET_IMG_LDSCRIPT@ From a50569e135f5be747a5b66f63843c5e5eadf8022 Mon Sep 17 00:00:00 2001 From: robertmh Date: Sun, 1 Nov 2009 23:03:09 +0000 Subject: [PATCH 064/165] 2009-11-01 Robert Millan Based on patch from BVK Chaitanya * kern/misc.c (grub_strchr, grub_strrchr): Fix to handle c == '\0' case. --- ChangeLog | 6 ++++++ kern/misc.c | 10 +++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2e5c7484d..5a3f80e05 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-11-01 Robert Millan + + Based on patch from BVK Chaitanya + * kern/misc.c (grub_strchr, grub_strrchr): Fix to handle c == '\0' + case. + 2009-11-01 Felix Zielcke * Makefile.in (TARGET_CPPFLAGS): Add `-I$(srcdir)/include'. diff --git a/kern/misc.c b/kern/misc.c index 1c38fe661..cacfbc753 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -223,12 +223,12 @@ grub_strncmp (const char *s1, const char *s2, grub_size_t n) char * grub_strchr (const char *s, int c) { - while (*s) + do { if (*s == c) return (char *) s; - s++; } + while (*s++); return 0; } @@ -236,14 +236,14 @@ grub_strchr (const char *s, int c) char * grub_strrchr (const char *s, int c) { - char *p = 0; + char *p = NULL; - while (*s) + do { if (*s == c) p = (char *) s; - s++; } + while (*s++); return p; } From 61697d9c7017da7b84f760b4171144f167be32f4 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 2 Nov 2009 13:55:25 +0000 Subject: [PATCH 065/165] 2009-11-02 Samuel Thibault * util/grub.d/10_hurd.in: Call prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} before loading /boot kernel. --- ChangeLog | 5 +++++ util/grub.d/10_hurd.in | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5a3f80e05..24dbdbf31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-11-02 Samuel Thibault + + * util/grub.d/10_hurd.in: Call prepare_grub_to_access_device + ${GRUB_DEVICE_BOOT} before loading /boot kernel. + 2009-11-01 Robert Millan Based on patch from BVK Chaitanya diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index b52f37498..fdfb7acb7 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -71,9 +71,12 @@ fi cat << EOF menuentry "${OS}" { EOF -prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/" +prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" cat << EOF multiboot ${kernel} root=device:${GRUB_DEVICE} +EOF +prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/" +cat << EOF module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\ --multiboot-command-line='\${kernel-command-line}' \\ --host-priv-port='\${host-port}' \\ From ff1a9bca3a3884a00b4156ffc4ea7f06b053c521 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 2 Nov 2009 19:14:00 +0000 Subject: [PATCH 066/165] 2009-11-02 Samuel Thibault * util/hostdisk.c (grub_util_biosdisk_get_grub_dev): Subtract 1 from GNU partition number to get internal GRUB partition number. --- ChangeLog | 5 +++++ util/hostdisk.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 24dbdbf31..38b9ffed1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-11-02 Samuel Thibault + + * util/hostdisk.c (grub_util_biosdisk_get_grub_dev): Subtract 1 from + GNU partition number to get internal GRUB partition number. + 2009-11-02 Samuel Thibault * util/grub.d/10_hurd.in: Call prepare_grub_to_access_device diff --git a/util/hostdisk.c b/util/hostdisk.c index 22b856e29..e1058a100 100644 --- a/util/hostdisk.c +++ b/util/hostdisk.c @@ -1057,7 +1057,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) n = strtol (p, &q, 10); if (p != q && n != GRUB_LONG_MIN && n != GRUB_LONG_MAX) { - dos_part = (int) n; + dos_part = (int) n - 1; if (*q >= 'a' && *q <= 'g') bsd_part = *q - 'a'; From b82bd5e192aa6776be2214b7d578d662a0a098a7 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 2 Nov 2009 19:32:12 +0000 Subject: [PATCH 067/165] 2009-11-02 Samuel Thibault * util/grub.d/10_hurd.in: Drop /dev/ prefix from root device path before giving it to GNU Mach. --- ChangeLog | 5 +++++ util/grub.d/10_hurd.in | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 38b9ffed1..e2aacd760 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-11-02 Samuel Thibault + + * util/grub.d/10_hurd.in: Drop /dev/ prefix from root device path before + giving it to GNU Mach. + 2009-11-02 Samuel Thibault * util/hostdisk.c (grub_util_biosdisk_get_grub_dev): Subtract 1 from diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index fdfb7acb7..e693c7dfa 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -73,7 +73,7 @@ menuentry "${OS}" { EOF prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" cat << EOF - multiboot ${kernel} root=device:${GRUB_DEVICE} + multiboot ${kernel} root=device:${GRUB_DEVICE#/dev/} EOF prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/" cat << EOF From 4f9dfb3701f46297395151c1e57b3936f5ae1da7 Mon Sep 17 00:00:00 2001 From: robertmh Date: Mon, 2 Nov 2009 21:01:14 +0000 Subject: [PATCH 068/165] 2009-11-02 Samuel Thibault * util/grub.d/30_os-prober.in: Add GNU/Hurd support --- ChangeLog | 4 ++++ util/grub.d/30_os-prober.in | 23 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e2aacd760..ea2145770 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2009-11-02 Samuel Thibault + + * util/grub.d/30_os-prober.in: Add GNU/Hurd support + 2009-11-02 Samuel Thibault * util/grub.d/10_hurd.in: Drop /dev/ prefix from root device path before diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in index 6fd97fc4e..e14a07316 100644 --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in @@ -159,7 +159,28 @@ EOF EOF ;; hurd|*) - echo " ${LONGNAME} is not yet supported by grub-mkconfig." >&2 + cat << EOF +menuentry "${LONGNAME} (on ${DEVICE})" { +EOF + prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" + grub_device="`${grub_probe} --device ${DEVICE} --target=drive`" + mach_device="`echo "${grub_device}" | tr -d '()' | tr , s`" + grub_fs="`${grub_probe} --device ${DEVICE} --target=fs`" + case "${grub_fs}" in + *fs) hurd_fs="${grub_fs}" ;; + *) hurd_fs="${grub_fs}fs" ;; + esac + cat << EOF + multiboot /boot/gnumach.gz root=device:${mach_device} + module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\ + --multiboot-command-line='\${kernel-command-line}' \\ + --host-priv-port='\${host-port}' \\ + --device-master-port='\${device-port}' \\ + --exec-server-task='\${exec-task}' -T typed '\${root}' \\ + '\$(task-create)' '\$(task-resume)' + module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)' +} +EOF ;; esac done From 246cd78f70fd3a9a89c2b2c97cc33854b2f86e4c Mon Sep 17 00:00:00 2001 From: fzielcke Date: Tue, 3 Nov 2009 14:25:34 +0000 Subject: [PATCH 069/165] 2009-11-03 Samuel Thibault * util/grub.d/30_os-prober.in: Restore default behavior for unsupported OSes. --- ChangeLog | 5 +++++ util/grub.d/30_os-prober.in | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ea2145770..ffe8911d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-11-03 Samuel Thibault + + * util/grub.d/30_os-prober.in: Restore default behavior for unsupported + OSes. + 2009-11-02 Samuel Thibault * util/grub.d/30_os-prober.in: Add GNU/Hurd support diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in index e14a07316..c5728866c 100644 --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in @@ -158,7 +158,7 @@ EOF } EOF ;; - hurd|*) + hurd) cat << EOF menuentry "${LONGNAME} (on ${DEVICE})" { EOF @@ -182,5 +182,8 @@ EOF } EOF ;; + *) + echo " ${LONGNAME} is not yet supported by grub-mkconfig." >&2 + ;; esac done From 86e5b1dbb75accb880e243344044639055c5fc25 Mon Sep 17 00:00:00 2001 From: fzielcke Date: Wed, 4 Nov 2009 08:20:53 +0000 Subject: [PATCH 070/165] 2009-11-04 Felix Zielcke * configure.ac (AC_PREREQ): Bump to 2.59d. * INSTALL: Make it more clear when Autoconf and Ruby are needed and when to run `./autogen.sh'. --- ChangeLog | 6 ++++++ INSTALL | 17 +++++++++++------ configure.ac | 2 +- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index ffe8911d8..c4fecdd40 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-11-04 Felix Zielcke + + * configure.ac (AC_PREREQ): Bump to 2.59d. + * INSTALL: Make it more clear when Autoconf and Ruby are + needed and when to run `./autogen.sh'. + 2009-11-03 Samuel Thibault * util/grub.d/30_os-prober.in: Restore default behavior for unsupported diff --git a/INSTALL b/INSTALL index e751d508f..f9ae8f9d2 100644 --- a/INSTALL +++ b/INSTALL @@ -16,8 +16,12 @@ configuring the GRUB. * GNU Bison 2.3 or later * GNU binutils 2.9.1.0.23 or later * Other standard GNU/Unix tools + +If you use a development snapshot or want to hack on GRUB you may +need the following. + * Ruby 1.6 or later -* Autoconf 2.59 or later +* Autoconf 2.59d or later Configuring the GRUB ==================== @@ -48,11 +52,12 @@ Building the GRUB The simplest way to compile this package is: - 1. `cd' to the directory containing the package's source code and - type `./autogen.sh' and then `./configure' to configure the - package for your system. If you're using `csh' on an old version - of System V, you might need to type `sh ./configure' instead to - prevent `csh' from trying to execute `configure' itself. + 1. `cd' to the directory containing the package's source code. If + you don't use a release tarball you have to type `./autogen.sh'. + Type `./configure' to configure the package for your system. + If you're using `csh' on an old version of System V, you might + need to type `sh ./configure' instead to prevent `csh' from trying + to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. diff --git a/configure.ac b/configure.ac index 4bd28f2e8..0953e0410 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,7 @@ dnl type. AC_INIT([GRUB],[1.97],[bug-grub@gnu.org]) -AC_PREREQ(2.59) +AC_PREREQ(2.59d) AC_CONFIG_SRCDIR([include/grub/dl.h]) AC_CONFIG_HEADER([config.h]) From c926e1d58502bff159ebd12aa11684341db5b8a4 Mon Sep 17 00:00:00 2001 From: robertmh Date: Sat, 7 Nov 2009 21:06:30 +0000 Subject: [PATCH 071/165] 2009-11-07 Robert Millan Fix build with GNU gold. * conf/i386-pc.rmk (boot_img_LDFLAGS, pxeboot_img_LDFLAGS) (diskboot_img_LDFLAGS, lnxboot_img_LDFLAGS) (cdboot_img_LDFLAGS): Prepend `0x' qualifier to hexadecimal link addresses. * aclocal.m4: Likewise. --- ChangeLog | 10 ++++++++++ aclocal.m4 | 2 +- conf/i386-pc.rmk | 10 +++++----- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index c4fecdd40..843be6dc5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-11-07 Robert Millan + + Fix build with GNU gold. + + * conf/i386-pc.rmk (boot_img_LDFLAGS, pxeboot_img_LDFLAGS) + (diskboot_img_LDFLAGS, lnxboot_img_LDFLAGS) + (cdboot_img_LDFLAGS): Prepend `0x' qualifier to hexadecimal + link addresses. + * aclocal.m4: Likewise. + 2009-11-04 Felix Zielcke * configure.ac (AC_PREREQ): Bump to 2.59d. diff --git a/aclocal.m4 b/aclocal.m4 index 899eca409..6f9baf18f 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -92,7 +92,7 @@ else AC_MSG_ERROR([${CC-cc} cannot compile C source code]) fi grub_cv_prog_objcopy_absolute=yes -for link_addr in 2000 8000 7C00; do +for link_addr in 0x2000 0x8000 0x7C00; do if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -nostdlib ${TARGET_IMG_LDFLAGS_AC} -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec]); then : else AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr]) diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index bf8fbfb9d..373b942cc 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -16,31 +16,31 @@ pkglib_IMAGES = boot.img cdboot.img diskboot.img kernel.img lnxboot.img \ # For boot.img. boot_img_SOURCES = boot/i386/pc/boot.S boot_img_ASFLAGS = $(COMMON_ASFLAGS) -boot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)7C00 +boot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)0x7C00 boot_img_FORMAT = binary # For pxeboot.img pxeboot_img_SOURCES = boot/i386/pc/pxeboot.S pxeboot_img_ASFLAGS = $(COMMON_ASFLAGS) -pxeboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)7C00 +pxeboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)0x7C00 pxeboot_img_FORMAT = binary # For diskboot.img. diskboot_img_SOURCES = boot/i386/pc/diskboot.S diskboot_img_ASFLAGS = $(COMMON_ASFLAGS) -diskboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)8000 +diskboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)0x8000 diskboot_img_FORMAT = binary # For lnxboot.img. lnxboot_img_SOURCES = boot/i386/pc/lnxboot.S lnxboot_img_ASFLAGS = $(COMMON_ASFLAGS) -lnxboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)6000 +lnxboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)0x6000 lnxboot_img_FORMAT = binary # For cdboot.img. cdboot_img_SOURCES = boot/i386/pc/cdboot.S cdboot_img_ASFLAGS = $(COMMON_ASFLAGS) -cdboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)7C00 +cdboot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)0x7C00 cdboot_img_FORMAT = binary # For kernel.img. From e4eb23732d11fa03938ae053449eae66d07a3971 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 8 Nov 2009 16:23:23 +0000 Subject: [PATCH 072/165] 2009-11-08 Robert Millan * kern/i386/multiboot_mmap.c (grub_machine_mmap_init): Improve error message for coreboot users. --- ChangeLog | 5 +++++ kern/i386/multiboot_mmap.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 843be6dc5..57cb49d95 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-11-08 Robert Millan + + * kern/i386/multiboot_mmap.c (grub_machine_mmap_init): Improve error + message for coreboot users. + 2009-11-07 Robert Millan Fix build with GNU gold. diff --git a/kern/i386/multiboot_mmap.c b/kern/i386/multiboot_mmap.c index 8331bd5df..6578a4834 100644 --- a/kern/i386/multiboot_mmap.c +++ b/kern/i386/multiboot_mmap.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,7 +40,7 @@ void grub_machine_mmap_init () { if (! startup_multiboot_info) - grub_fatal ("Must be loaded using Multiboot specification (is this an old version of coreboot?)"); + grub_fatal ("Unable to find Multiboot Information (is CONFIG_MULTIBOOT disabled in coreboot?)"); /* Move MBI to a safe place. */ grub_memmove (&kern_multiboot_info, startup_multiboot_info, sizeof (struct grub_multiboot_info)); From 31bd05ccca276daabd65eb26de6207af13f0f3ab Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 8 Nov 2009 16:40:24 +0000 Subject: [PATCH 073/165] Add exec bit. --- autogen.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 autogen.sh diff --git a/autogen.sh b/autogen.sh old mode 100644 new mode 100755 From 0411481297c20dfc8b7913f32538cc738019a887 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 8 Nov 2009 16:43:36 +0000 Subject: [PATCH 074/165] 2009-11-08 Robert Millan * autogen.sh: Use `sh gendistlist.sh' to avoid reliing on executable bit. --- ChangeLog | 5 +++++ autogen.sh | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 57cb49d95..525a6d5e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-11-08 Robert Millan + + * autogen.sh: Use `sh gendistlist.sh' to avoid reliing on + executable bit. + 2009-11-08 Robert Millan * kern/i386/multiboot_mmap.c (grub_machine_mmap_init): Improve error diff --git a/autogen.sh b/autogen.sh index 4fb6bf7db..6751c8adc 100755 --- a/autogen.sh +++ b/autogen.sh @@ -10,6 +10,6 @@ for rmk in conf/*.rmk ${GRUB_CONTRIB}/*/conf/*.rmk; do ruby genmk.rb < $rmk > `echo $rmk | sed 's/\.rmk$/.mk/'` fi done -./gendistlist.sh > DISTLIST +sh gendistlist.sh > DISTLIST exit 0 From c02a7334960edaf716bd936efa1e7babd67406c6 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 8 Nov 2009 16:57:31 +0000 Subject: [PATCH 075/165] Add a few files that were lost during transition from svn. --- include/grub/i386/coreboot/boot.h | 1 + include/grub/i386/coreboot/init.h | 28 ++++++++++++++++++++++++++++ include/grub/i386/coreboot/loader.h | 1 + include/grub/i386/coreboot/serial.h | 1 + include/grub/i386/coreboot/time.h | 1 + 5 files changed, 32 insertions(+) create mode 100644 include/grub/i386/coreboot/boot.h create mode 100644 include/grub/i386/coreboot/init.h create mode 100644 include/grub/i386/coreboot/loader.h create mode 100644 include/grub/i386/coreboot/serial.h create mode 100644 include/grub/i386/coreboot/time.h diff --git a/include/grub/i386/coreboot/boot.h b/include/grub/i386/coreboot/boot.h new file mode 100644 index 000000000..6cd23aa83 --- /dev/null +++ b/include/grub/i386/coreboot/boot.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/i386/coreboot/init.h b/include/grub/i386/coreboot/init.h new file mode 100644 index 000000000..e67007414 --- /dev/null +++ b/include/grub/i386/coreboot/init.h @@ -0,0 +1,28 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +#ifndef GRUB_INIT_I386_LINUXBIOS_HEADER +#define GRUB_INIT_I386_LINUXBIOS_HEADER 1 + +#include +#include + +void EXPORT_FUNC(grub_stop) (void) __attribute__ ((noreturn)); +void EXPORT_FUNC(grub_stop_floppy) (void); + +#endif diff --git a/include/grub/i386/coreboot/loader.h b/include/grub/i386/coreboot/loader.h new file mode 100644 index 000000000..d3f36bba5 --- /dev/null +++ b/include/grub/i386/coreboot/loader.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/i386/coreboot/serial.h b/include/grub/i386/coreboot/serial.h new file mode 100644 index 000000000..2c527f626 --- /dev/null +++ b/include/grub/i386/coreboot/serial.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/i386/coreboot/time.h b/include/grub/i386/coreboot/time.h new file mode 100644 index 000000000..2298ee8f4 --- /dev/null +++ b/include/grub/i386/coreboot/time.h @@ -0,0 +1 @@ +#include From b97b7b914b09a757533119d818332a089b671c8d Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 8 Nov 2009 20:02:16 +0000 Subject: [PATCH 076/165] 2009-11-08 Robert Millan * kern/i386/multiboot_mmap.c (grub_machine_mmap_init): Improve error message for excessively large memory map. --- ChangeLog | 5 +++++ kern/i386/multiboot_mmap.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 525a6d5e0..ac3950f2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-11-08 Robert Millan + + * kern/i386/multiboot_mmap.c (grub_machine_mmap_init): Improve + error message for excessively large memory map. + 2009-11-08 Robert Millan * autogen.sh: Use `sh gendistlist.sh' to avoid reliing on diff --git a/kern/i386/multiboot_mmap.c b/kern/i386/multiboot_mmap.c index 6578a4834..67d824313 100644 --- a/kern/i386/multiboot_mmap.c +++ b/kern/i386/multiboot_mmap.c @@ -51,7 +51,8 @@ grub_machine_mmap_init () /* Move the memory map to a safe place. */ if (kern_multiboot_info.mmap_length > sizeof (mmap_entries)) { - grub_printf ("WARNING: Memory map size exceeds limit; it will be truncated\n"); + grub_printf ("WARNING: Memory map size exceeds limit (0x%x > 0x%x); it will be truncated\n", + kern_multiboot_info.mmap_length, sizeof (mmap_entries)); kern_multiboot_info.mmap_length = sizeof (mmap_entries); } grub_memmove (mmap_entries, (void *) kern_multiboot_info.mmap_addr, kern_multiboot_info.mmap_length); From ef4b915ad982877fbc2e41f9fdb4a4bb57c853d2 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 8 Nov 2009 20:56:32 +0000 Subject: [PATCH 077/165] Implement grub-mkrescue for coreboot (needs external grub-mkisofs) --- ChangeLog.branch | 5 + conf/i386-coreboot.rmk | 3 + util/i386/coreboot/grub-mkrescue.in | 144 ++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 ChangeLog.branch create mode 100644 util/i386/coreboot/grub-mkrescue.in diff --git a/ChangeLog.branch b/ChangeLog.branch new file mode 100644 index 000000000..4794498ff --- /dev/null +++ b/ChangeLog.branch @@ -0,0 +1,5 @@ +2009-11-08 Robert Millan + + * util/i386/coreboot/grub-mkrescue.in: New file. + * conf/i386-coreboot.rmk (bin_SCRIPTS, grub_mkrescue_SOURCES): New + variables. diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk index 09ec7787c..5645395b8 100644 --- a/conf/i386-coreboot.rmk +++ b/conf/i386-coreboot.rmk @@ -152,6 +152,9 @@ grub_emu_LDFLAGS = $(LIBCURSES) sbin_SCRIPTS += grub-install grub_install_SOURCES = util/i386/pc/grub-install.in +bin_SCRIPTS += grub-mkrescue +grub_mkrescue_SOURCES = util/i386/coreboot/grub-mkrescue.in + # Modules. pkglib_MODULES = linux.mod multiboot.mod \ aout.mod play.mod serial.mod ata.mod \ diff --git a/util/i386/coreboot/grub-mkrescue.in b/util/i386/coreboot/grub-mkrescue.in new file mode 100644 index 000000000..fbfc13841 --- /dev/null +++ b/util/i386/coreboot/grub-mkrescue.in @@ -0,0 +1,144 @@ +#! /bin/sh -e + +# Make GRUB rescue image +# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +# Initialize some variables. +transform="@program_transform_name@" + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +libdir=@libdir@ +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_TARNAME=@PACKAGE_TARNAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ +target_cpu=@target_cpu@ +platform=@platform@ +pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` + +grub_mkimage=${bindir}/`echo grub-mkelfimage | sed ${transform}` + +# Usage: usage +# Print the usage. +usage () { + cat <. +EOF +} + +input_dir=${pkglibdir} + +# Check the arguments. +for option in "$@"; do + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "grub-mkrescue (GNU GRUB ${PACKAGE_VERSION})" + exit 0 ;; + --modules=*) + modules=`echo "$option" | sed 's/--modules=//'` ;; + --overlay=*) + overlay=${overlay}${overlay:+ }`echo "$option" | sed 's/--overlay=//'` ;; + --pkglibdir=*) + input_dir=`echo "$option" | sed 's/--pkglibdir=//'` ;; + --grub-mkimage=*) + grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + -*) + echo "Unrecognized option \`$option'" 1>&2 + usage + exit 1 + ;; + *) + if test "x$output_image" != x; then + echo "Unrecognized option \`$option'" 1>&2 + usage + exit 1 + fi + output_image="${option}" ;; + esac +done + +if test "x$output_image" = x; then + usage + exit 1 +fi + +memdisk_dir=`mktemp -d` +iso9660_dir=`mktemp -d` +mkdir -p ${memdisk_dir}/boot/grub ${iso9660_dir}/boot/grub + +for file in ${input_dir}/*.mod ${input_dir}/efiemu??.o \ + ${input_dir}/command.lst ${input_dir}/moddep.lst ${input_dir}/fs.lst \ + ${input_dir}/handler.lst ${input_dir}/parttool.lst; do + if test -f "$file"; then + cp -f "$file" ${iso9660_dir}/boot/grub/ + fi +done + +# obtain date-based UUID +iso_uuid=$(date +%Y-%m-%d-%H-%M-%S-00) + +# first-stage grub.cfg +cat << EOF >> ${memdisk_dir}/boot/grub/grub.cfg +search --fs-uuid --set ${iso_uuid} +set prefix=(\${root})/boot/grub +source /boot/grub/grub.cfg +EOF + +# build memdisk +memdisk_img=`mktemp` +tar -C ${memdisk_dir} -cf ${memdisk_img} boot +rm -rf ${memdisk_dir} + +# build core.img +mkdir -p ${iso9660_dir}/boot/grub +${grub_mkimage} -d ${input_dir}/ -m ${memdisk_img} -o ${iso9660_dir}/boot/multiboot.img \ + at_keyboard memdisk tar ata search iso9660 configfile sh +rm -f ${memdisk_img} + +for d in ${overlay}; do + echo "Overlaying $d" + cp -dpR "${d}"/* "${iso9660_dir}"/ +done + +# second-stage grub.cfg +modules="`cat ${input_dir}/partmap.lst` ${modules}" +for i in ${modules} ; do + echo "insmod $i" +done > ${iso9660_dir}/boot/grub/grub.cfg + +# build iso image +grub-mkisofs \ + --modification-date=$(echo ${iso_uuid} | sed -e s/-//g) \ + -o ${output_image} -r -J ${iso9660_dir} + +exit 0 From 79cb3a568b3f7c7ea1f2fe42d37bc67aba40a6c9 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 8 Nov 2009 21:52:59 +0000 Subject: [PATCH 078/165] Fix miss-identification as `grub-mkimage' (and use `$0' when possible). --- util/i386/pc/grub-mkrescue.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/i386/pc/grub-mkrescue.in b/util/i386/pc/grub-mkrescue.in index da937768b..cc581bffe 100644 --- a/util/i386/pc/grub-mkrescue.in +++ b/util/i386/pc/grub-mkrescue.in @@ -36,7 +36,7 @@ grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` # Print the usage. usage () { cat <. EOF @@ -67,7 +67,7 @@ for option in "$@"; do usage exit 0 ;; -v | --version) - echo "grub-mkrescue (GNU GRUB ${PACKAGE_VERSION})" + echo "$0 (GNU GRUB ${PACKAGE_VERSION})" exit 0 ;; --modules=*) modules=`echo "$option" | sed 's/--modules=//'` ;; From 3716b12ce271668bb02677dca7175fbea0f5dd86 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 8 Nov 2009 21:55:25 +0000 Subject: [PATCH 079/165] 2009-11-08 Robert Millan * util/i386/pc/grub-mkrescue.in: Fix miss-identification as `grub-mkimage' (and use $0 when possible). --- ChangeLog | 5 +++++ util/i386/pc/grub-mkrescue.in | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index ac3950f2e..d6c3b7927 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-11-08 Robert Millan + + * util/i386/pc/grub-mkrescue.in: Fix miss-identification as + `grub-mkimage' (and use $0 when possible). + 2009-11-08 Robert Millan * kern/i386/multiboot_mmap.c (grub_machine_mmap_init): Improve diff --git a/util/i386/pc/grub-mkrescue.in b/util/i386/pc/grub-mkrescue.in index da937768b..cc581bffe 100644 --- a/util/i386/pc/grub-mkrescue.in +++ b/util/i386/pc/grub-mkrescue.in @@ -36,7 +36,7 @@ grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` # Print the usage. usage () { cat <. EOF @@ -67,7 +67,7 @@ for option in "$@"; do usage exit 0 ;; -v | --version) - echo "grub-mkrescue (GNU GRUB ${PACKAGE_VERSION})" + echo "$0 (GNU GRUB ${PACKAGE_VERSION})" exit 0 ;; --modules=*) modules=`echo "$option" | sed 's/--modules=//'` ;; From 4b4c4f64002ab606034c8f7e1d76a74269b92018 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 8 Nov 2009 22:51:08 +0000 Subject: [PATCH 080/165] Import http://www.tux.org/pub/people/eric-youngdale/mkisofs/mkisofs-1.11.3.tar.gz --- util/mkisofs/defaults.h | 44 ++ util/mkisofs/eltorito.c | 265 ++++++++ util/mkisofs/exclude.h | 10 + util/mkisofs/fnmatch.c | 226 +++++++ util/mkisofs/hash.c | 226 +++++++ util/mkisofs/iso9660.h | 157 +++++ util/mkisofs/match.c | 56 ++ util/mkisofs/match.h | 14 + util/mkisofs/mkisofs.c | 660 ++++++++++++++++++++ util/mkisofs/mkisofs.h | 339 ++++++++++ util/mkisofs/multi.c | 1018 ++++++++++++++++++++++++++++++ util/mkisofs/name.c | 390 ++++++++++++ util/mkisofs/rock.c | 556 +++++++++++++++++ util/mkisofs/tree.c | 1292 +++++++++++++++++++++++++++++++++++++++ util/mkisofs/write.c | 1142 ++++++++++++++++++++++++++++++++++ 15 files changed, 6395 insertions(+) create mode 100644 util/mkisofs/defaults.h create mode 100644 util/mkisofs/eltorito.c create mode 100644 util/mkisofs/exclude.h create mode 100644 util/mkisofs/fnmatch.c create mode 100644 util/mkisofs/hash.c create mode 100644 util/mkisofs/iso9660.h create mode 100644 util/mkisofs/match.c create mode 100644 util/mkisofs/match.h create mode 100644 util/mkisofs/mkisofs.c create mode 100644 util/mkisofs/mkisofs.h create mode 100644 util/mkisofs/multi.c create mode 100644 util/mkisofs/name.c create mode 100644 util/mkisofs/rock.c create mode 100644 util/mkisofs/tree.c create mode 100644 util/mkisofs/write.c diff --git a/util/mkisofs/defaults.h b/util/mkisofs/defaults.h new file mode 100644 index 000000000..91e678992 --- /dev/null +++ b/util/mkisofs/defaults.h @@ -0,0 +1,44 @@ +/* + * Header file defaults.h - assorted default values for character strings in + * the volume descriptor. + * + * $Id: defaults.h,v 1.4 1997/04/10 03:31:53 eric Rel $ + */ + +#define PREPARER_DEFAULT NULL +#define PUBLISHER_DEFAULT NULL +#define APPID_DEFAULT NULL +#define COPYRIGHT_DEFAULT NULL +#define BIBLIO_DEFAULT NULL +#define ABSTRACT_DEFAULT NULL +#define VOLSET_ID_DEFAULT NULL +#define VOLUME_ID_DEFAULT "CDROM" +#define BOOT_CATALOG_DEFAULT "boot.catalog" +#define BOOT_IMAGE_DEFAULT NULL +#ifdef __QNX__ +#define SYSTEM_ID_DEFAULT "QNX" +#endif + +#ifdef __osf__ +#define SYSTEM_ID_DEFAULT "OSF" +#endif + +#ifdef __sun +#define SYSTEM_ID_DEFAULT "Solaris" +#endif + +#ifdef __hpux +#define SYSTEM_ID_DEFAULT "HP-UX" +#endif + +#ifdef __sgi +#define SYSTEM_ID_DEFAULT "SGI" +#endif + +#ifdef _AIX +#define SYSTEM_ID_DEFAULT "AIX" +#endif + +#ifndef SYSTEM_ID_DEFAULT +#define SYSTEM_ID_DEFAULT "LINUX" +#endif diff --git a/util/mkisofs/eltorito.c b/util/mkisofs/eltorito.c new file mode 100644 index 000000000..0ac5a1290 --- /dev/null +++ b/util/mkisofs/eltorito.c @@ -0,0 +1,265 @@ +/* + * Program eltorito.c - Handle El Torito specific extensions to iso9660. + * + + Written by Michael Fulbright (1996). + + Copyright 1996 RedHat Software, Incorporated + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +static char rcsid[] ="$Id: eltorito.c,v 1.7 1997/05/17 15:44:31 eric Exp $"; + +#include +#include +#include +#include +#include +#include + +#include "mkisofs.h" +#include "iso9660.h" + +#undef MIN +#define MIN(a, b) (((a) < (b))? (a): (b)) + +static struct eltorito_validation_entry valid_desc; +static struct eltorito_defaultboot_entry default_desc; + +/* + * Check for presence of boot catalog. If it does not exist then make it + */ +void FDECL1(init_boot_catalog, const char *, path) +{ + + int bcat; + char * bootpath; /* filename of boot catalog */ + char * buf; + struct stat statbuf; + + bootpath = (char *) e_malloc(strlen(boot_catalog)+strlen(path)+2); + strcpy(bootpath, path); + if (bootpath[strlen(bootpath)-1] != '/') + { + strcat(bootpath,"/"); + } + + strcat(bootpath, boot_catalog); + + /* + * check for the file existing + */ +#ifdef DEBUG_TORITO + printf("Looking for boot catalog file %s\n",bootpath); +#endif + + if (!stat_filter(bootpath, &statbuf)) + { + /* + * make sure its big enough to hold what we want + */ + if (statbuf.st_size == 2048) + { + /* + * printf("Boot catalog exists, so we do nothing\n"); + */ + free(bootpath); + return; + } + else + { + fprintf(stderr, "A boot catalog exists and appears corrupted.\n"); + fprintf(stderr, "Please check the following file: %s.\n",bootpath); + fprintf(stderr, "This file must be removed before a bootable CD can be done.\n"); + free(bootpath); + exit(1); + } + } + + /* + * file does not exist, so we create it + * make it one CD sector long + */ + bcat = open(bootpath, O_WRONLY | O_CREAT, S_IROTH | S_IRGRP | S_IRWXU ); + if (bcat == -1) + { + fprintf(stderr, "Error creating boot catalog, exiting...\n"); + perror(""); + exit(1); + } + + buf = (char *) e_malloc( 2048 ); + write(bcat, buf, 2048); + close(bcat); + free(bootpath); +} /* init_boot_catalog(... */ + +void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) +{ + int bootcat; + int checksum; + unsigned char * checksum_ptr; + struct directory_entry * de; + struct directory_entry * de2; + int i; + int nsectors; + + memset(boot_desc, 0, sizeof(*boot_desc)); + boot_desc->id[0] = 0; + memcpy(boot_desc->id2, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID)); + boot_desc->version[0] = 1; + + memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof(EL_TORITO_ID)); + + /* + * search from root of iso fs to find boot catalog + */ + de2 = search_tree_file(root, boot_catalog); + if (!de2) + { + fprintf(stderr,"Uh oh, I cant find the boot catalog!\n"); + exit(1); + } + + set_731(boot_desc->bootcat_ptr, + (unsigned int) get_733(de2->isorec.extent)); + + /* + * now adjust boot catalog + * lets find boot image first + */ + de=search_tree_file(root, boot_image); + if (!de) + { + fprintf(stderr,"Uh oh, I cant find the boot image!\n"); + exit(1); + } + + /* + * we have the boot image, so write boot catalog information + * Next we write out the primary descriptor for the disc + */ + memset(&valid_desc, 0, sizeof(valid_desc)); + valid_desc.headerid[0] = 1; + valid_desc.arch[0] = EL_TORITO_ARCH_x86; + + /* + * we'll shove start of publisher id into id field, may get truncated + * but who really reads this stuff! + */ + if (publisher) + memcpy_max(valid_desc.id, publisher, MIN(23, strlen(publisher))); + + valid_desc.key1[0] = 0x55; + valid_desc.key2[0] = 0xAA; + + /* + * compute the checksum + */ + checksum=0; + checksum_ptr = (unsigned char *) &valid_desc; + for (i=0; isize + 511) & ~(511))/512; + printf("\nSize of boot image is %d sectors -> ", nsectors); + + /* + * choose size of emulated floppy based on boot image size + */ + if (nsectors == 2880 ) + { + default_desc.boot_media[0] = EL_TORITO_MEDIA_144FLOP; + printf("Emulating a 1.44 meg floppy\n"); + } + else if (nsectors == 5760 ) + { + default_desc.boot_media[0] = EL_TORITO_MEDIA_288FLOP; + printf("Emulating a 2.88 meg floppy\n"); + } + else if (nsectors == 2400 ) + { + default_desc.boot_media[0] = EL_TORITO_MEDIA_12FLOP; + printf("Emulating a 1.2 meg floppy\n"); + } + else + { + fprintf(stderr,"\nError - boot image is not the an allowable size.\n"); + exit(1); + } + + + /* + * FOR NOW LOAD 1 SECTOR, JUST LIKE FLOPPY BOOT!!! + */ + nsectors = 1; + set_721(default_desc.nsect, (unsigned int) nsectors ); +#ifdef DEBUG_TORITO + printf("Extent of boot images is %d\n",get_733(de->isorec.extent)); +#endif + set_731(default_desc.bootoff, + (unsigned int) get_733(de->isorec.extent)); + + /* + * now write it to disk + */ + bootcat = open(de2->whole_name, O_RDWR); + if (bootcat == -1) + { + fprintf(stderr,"Error opening boot catalog for update.\n"); + perror(""); + exit(1); + } + + /* + * write out + */ + write(bootcat, &valid_desc, 32); + write(bootcat, &default_desc, 32); + close(bootcat); +} /* get_torito_desc(... */ diff --git a/util/mkisofs/exclude.h b/util/mkisofs/exclude.h new file mode 100644 index 000000000..b9581a9e9 --- /dev/null +++ b/util/mkisofs/exclude.h @@ -0,0 +1,10 @@ +/* + * 9-Dec-93 R.-D. Marzusch, marzusch@odiehh.hanse.de: + * added 'exclude' option (-x) to specify pathnames NOT to be included in + * CD image. + * + * $Id: exclude.h,v 1.1 1997/02/23 15:53:19 eric Rel $ + */ + +void exclude(); +int is_excluded(); diff --git a/util/mkisofs/fnmatch.c b/util/mkisofs/fnmatch.c new file mode 100644 index 000000000..cd5c0b27c --- /dev/null +++ b/util/mkisofs/fnmatch.c @@ -0,0 +1,226 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + +NOTE: The canonical source of this file is maintained with the GNU C Library. +Bugs can be reported to bug-glibc@prep.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 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +static char rcsid[] ="$Id: fnmatch.c,v 1.3 1997/03/22 02:53:13 eric Rel $"; + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#ifndef FNM_FILE_NAME +#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +#endif + +#ifndef FNM_LEADING_DIR +#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ +#endif + +#ifndef FNM_CASEFOLD +#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +#endif + + +#include + +#if defined (STDC_HEADERS) || !defined (isascii) +#define ISASCII(c) 1 +#else +#define ISASCII(c) isascii(c) +#endif + +#define ISUPPER(c) (ISASCII (c) && isupper (c)) + + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) +extern int errno; +#endif + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +int +fnmatch (pattern, string, flags) + const char *pattern; + const char *string; + int flags; +{ + register const char *p = pattern, *n = string; + register char c; + +/* Note that this evalutes C many times. */ +#define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) + + while ((c = *p++) != '\0') + { + c = FOLD (c); + + switch (c) + { + case '?': + if (*n == '\0') + return FNM_NOMATCH; + else if ((flags & FNM_FILE_NAME) && *n == '/') + return FNM_NOMATCH; + else if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + c = FOLD (c); + } + if (FOLD (*n) != c) + return FNM_NOMATCH; + break; + + case '*': + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) + if (((flags & FNM_FILE_NAME) && *n == '/') || + (c == '?' && *n == '\0')) + return FNM_NOMATCH; + + if (c == '\0') + return 0; + + { + char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; + c1 = FOLD (c1); + for (--p; *n != '\0'; ++n) + if ((c == '[' || FOLD (*n) == c1) && + fnmatch (p, n, flags & ~FNM_PERIOD) == 0) + return 0; + return FNM_NOMATCH; + } + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + register int not; + + if (*n == '\0') + return FNM_NOMATCH; + + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + not = (*p == '!' || *p == '^'); + if (not) + ++p; + + c = *p++; + for (;;) + { + register char cstart = c, cend = c; + + if (!(flags & FNM_NOESCAPE) && c == '\\') + cstart = cend = *p++; + + cstart = cend = FOLD (cstart); + + if (c == '\0') + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + c = FOLD (c); + + if ((flags & FNM_FILE_NAME) && c == '/') + /* [/] can never match. */ + return FNM_NOMATCH; + + if (c == '-' && *p != ']') + { + cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return FNM_NOMATCH; + cend = FOLD (cend); + + c = *p++; + } + + if (FOLD (*n) >= cstart && FOLD (*n) <= cend) + goto matched; + + if (c == ']') + break; + } + if (!not) + return FNM_NOMATCH; + break; + + matched:; + /* Skip the rest of the [...] that already matched. */ + while (c != ']') + { + if (c == '\0') + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + if (!(flags & FNM_NOESCAPE) && c == '\\') + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + if (not) + return FNM_NOMATCH; + } + break; + + default: + if (c != FOLD (*n)) + return FNM_NOMATCH; + } + + ++n; + } + + if (*n == '\0') + return 0; + + if ((flags & FNM_LEADING_DIR) && *n == '/') + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/util/mkisofs/hash.c b/util/mkisofs/hash.c new file mode 100644 index 000000000..67098d580 --- /dev/null +++ b/util/mkisofs/hash.c @@ -0,0 +1,226 @@ +/* + * File hash.c - generate hash tables for iso9660 filesystem. + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +static char rcsid[] ="$Id: hash.c,v 1.2 1997/02/23 16:11:15 eric Rel $"; + +#include +#include "mkisofs.h" + +#define NR_HASH 1024 + +#define HASH_FN(DEV, INO) ((DEV + INO + (INO >> 2) + (INO << 8)) % NR_HASH) + +static struct file_hash * hash_table[NR_HASH] = {0,}; + +void FDECL1(add_hash, struct directory_entry *, spnt){ + struct file_hash * s_hash; + unsigned int hash_number; + + if(spnt->size == 0 || spnt->starting_block == 0) + if(spnt->size != 0 || spnt->starting_block != 0) { + fprintf(stderr,"Non zero-length file assigned zero extent.\n"); + exit(1); + }; + + if (spnt->dev == (dev_t) UNCACHED_DEVICE || spnt->inode == UNCACHED_INODE) return; + hash_number = HASH_FN((unsigned int) spnt->dev, (unsigned int) spnt->inode); + +#if 0 + if (verbose) fprintf(stderr,"%s ",spnt->name); +#endif + s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash)); + s_hash->next = hash_table[hash_number]; + s_hash->inode = spnt->inode; + s_hash->dev = spnt->dev; + s_hash->starting_block = spnt->starting_block; + s_hash->size = spnt->size; + hash_table[hash_number] = s_hash; +} + +struct file_hash * FDECL2(find_hash, dev_t, dev, ino_t, inode){ + unsigned int hash_number; + struct file_hash * spnt; + hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode); + if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL; + + spnt = hash_table[hash_number]; + while(spnt){ + if(spnt->inode == inode && spnt->dev == dev) return spnt; + spnt = spnt->next; + }; + return NULL; +} + + +static struct file_hash * directory_hash_table[NR_HASH] = {0,}; + +void FDECL2(add_directory_hash, dev_t, dev, ino_t, inode){ + struct file_hash * s_hash; + unsigned int hash_number; + + if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return; + hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode); + + s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash)); + s_hash->next = directory_hash_table[hash_number]; + s_hash->inode = inode; + s_hash->dev = dev; + directory_hash_table[hash_number] = s_hash; +} + +struct file_hash * FDECL2(find_directory_hash, dev_t, dev, ino_t, inode){ + unsigned int hash_number; + struct file_hash * spnt; + hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode); + if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL; + + spnt = directory_hash_table[hash_number]; + while(spnt){ + if(spnt->inode == inode && spnt->dev == dev) return spnt; + spnt = spnt->next; + }; + return NULL; +} + +struct name_hash +{ + struct name_hash * next; + struct directory_entry * de; +}; + +#define NR_NAME_HASH 128 + +static struct name_hash * name_hash_table[NR_NAME_HASH] = {0,}; + +/* + * Find the hash bucket for this name. + */ +static unsigned int FDECL1(name_hash, const char *, name) +{ + unsigned int hash = 0; + const char * p; + + p = name; + + while (*p) + { + /* + * Don't hash the iso9660 version number. This way + * we can detect duplicates in cases where we have + * directories (i.e. foo) and non-directories + * (i.e. foo;1). + */ + if( *p == ';' ) + { + break; + } + hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++; + } + return hash % NR_NAME_HASH; +} + +void FDECL1(add_file_hash, struct directory_entry *, de){ + struct name_hash * new; + int hash; + + new = (struct name_hash *) e_malloc(sizeof(struct name_hash)); + new->de = de; + new->next = NULL; + hash = name_hash(de->isorec.name); + + /* Now insert into the hash table */ + new->next = name_hash_table[hash]; + name_hash_table[hash] = new; +} + +struct directory_entry * FDECL1(find_file_hash, char *, name) +{ + struct name_hash * nh; + char * p1; + char * p2; + + for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next) + { + p1 = name; + p2 = nh->de->isorec.name; + + /* + * Look for end of string, or a mismatch. + */ + while(1==1) + { + if( (*p1 == '\0' || *p1 == ';') + || (*p2 == '\0' || *p2 == ';') + || (*p1 != *p2) ) + { + break; + } + p1++; + p2++; + } + + /* + * If we are at the end of both strings, then + * we have a match. + */ + if( (*p1 == '\0' || *p1 == ';') + && (*p2 == '\0' || *p2 == ';') ) + { + return nh->de; + } + } + return NULL; +} + +int FDECL1(delete_file_hash, struct directory_entry *, de){ + struct name_hash * nh, *prev; + int hash; + + prev = NULL; + hash = name_hash(de->isorec.name); + for(nh = name_hash_table[hash]; nh; nh = nh->next) { + if(nh->de == de) break; + prev = nh; + } + if(!nh) return 1; + if(!prev) + name_hash_table[hash] = nh->next; + else + prev->next = nh->next; + free(nh); + return 0; +} + +void flush_file_hash(){ + struct name_hash * nh, *nh1; + int i; + + for(i=0; inext; + free(nh); + nh = nh1; + } + name_hash_table[i] = NULL; + + } +} diff --git a/util/mkisofs/iso9660.h b/util/mkisofs/iso9660.h new file mode 100644 index 000000000..a58f96f0d --- /dev/null +++ b/util/mkisofs/iso9660.h @@ -0,0 +1,157 @@ +/* + * Header file iso9660.h - assorted structure definitions and typecasts. + * specific to iso9660 filesystem. + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + * $Id: iso9660.h,v 1.1 1997/02/23 15:55:25 eric Rel $ + */ + +#ifndef _ISOFS_FS_H +#define _ISOFS_FS_H + +/* + * The isofs filesystem constants/structures + */ + +/* This part borrowed from the bsd386 isofs */ +#define ISODCL(from, to) (to - from + 1) + +struct iso_volume_descriptor { + char type[ISODCL(1,1)]; /* 711 */ + char id[ISODCL(2,6)]; + char version[ISODCL(7,7)]; + char data[ISODCL(8,2048)]; +}; + +/* volume descriptor types */ +#define ISO_VD_PRIMARY 1 +#define ISO_VD_END 255 + +#define ISO_STANDARD_ID "CD001" + +#define EL_TORITO_ID "EL TORITO SPECIFICATION" +#define EL_TORITO_ARCH_x86 0 +#define EL_TORITO_ARCH_PPC 1 +#define EL_TORITO_ARCH_MAC 2 +#define EL_TORITO_BOOTABLE 0x88 +#define EL_TORITO_MEDIA_NOEMUL 0 +#define EL_TORITO_MEDIA_12FLOP 1 +#define EL_TORITO_MEDIA_144FLOP 2 +#define EL_TORITO_MEDIA_288FLOP 3 +#define EL_TORITO_MEDIA_HD 4 + +struct iso_primary_descriptor { + char type [ISODCL ( 1, 1)]; /* 711 */ + char id [ISODCL ( 2, 6)]; + char version [ISODCL ( 7, 7)]; /* 711 */ + char unused1 [ISODCL ( 8, 8)]; + char system_id [ISODCL ( 9, 40)]; /* achars */ + char volume_id [ISODCL ( 41, 72)]; /* dchars */ + char unused2 [ISODCL ( 73, 80)]; + char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + char unused3 [ISODCL ( 89, 120)]; + char volume_set_size [ISODCL (121, 124)]; /* 723 */ + char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + char logical_block_size [ISODCL (129, 132)]; /* 723 */ + char path_table_size [ISODCL (133, 140)]; /* 733 */ + char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + char volume_set_id [ISODCL (191, 318)]; /* dchars */ + char publisher_id [ISODCL (319, 446)]; /* achars */ + char preparer_id [ISODCL (447, 574)]; /* achars */ + char application_id [ISODCL (575, 702)]; /* achars */ + char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + char file_structure_version [ISODCL (882, 882)]; /* 711 */ + char unused4 [ISODCL (883, 883)]; + char application_data [ISODCL (884, 1395)]; + char unused5 [ISODCL (1396, 2048)]; +}; + +/* El Torito Boot Record Volume Descriptor */ +struct eltorito_boot_descriptor { + char id [ISODCL ( 1, 1)]; /* 711 */ + char id2 [ISODCL ( 2, 6)]; + char version [ISODCL ( 7, 7)]; /* 711 */ + char system_id [ISODCL ( 8, 39)]; + char unused2 [ISODCL ( 40, 71)]; + char bootcat_ptr [ISODCL ( 72 , 75)]; + char unused5 [ISODCL ( 76, 2048)]; +}; + +/* Validation entry for El Torito */ +struct eltorito_validation_entry { + char headerid [ISODCL ( 1, 1)]; /* 711 */ + char arch [ISODCL ( 2, 2)]; + char pad1 [ISODCL ( 3, 4)]; /* 711 */ + char id [ISODCL ( 5, 28)]; + char cksum [ISODCL ( 29, 30)]; + char key1 [ISODCL ( 31, 31)]; + char key2 [ISODCL ( 32, 32)]; +}; + +/* El Torito initial/default entry in boot catalog */ +struct eltorito_defaultboot_entry { + char boot_id [ISODCL ( 1, 1)]; /* 711 */ + char boot_media [ISODCL ( 2, 2)]; + char loadseg [ISODCL ( 3, 4)]; /* 711 */ + char arch [ISODCL ( 5, 5)]; + char pad1 [ISODCL ( 6, 6)]; + char nsect [ISODCL ( 7, 8)]; + char bootoff [ISODCL ( 9, 12)]; + char pad2 [ISODCL ( 13, 32)]; +}; + + +/* We use this to help us look up the parent inode numbers. */ + +struct iso_path_table{ + unsigned char name_len[2]; /* 721 */ + char extent[4]; /* 731 */ + char parent[2]; /* 721 */ + char name[1]; +}; + +struct iso_directory_record { + unsigned char length [ISODCL (1, 1)]; /* 711 */ + char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + char extent [ISODCL (3, 10)]; /* 733 */ + char size [ISODCL (11, 18)]; /* 733 */ + char date [ISODCL (19, 25)]; /* 7 by 711 */ + char flags [ISODCL (26, 26)]; + char file_unit_size [ISODCL (27, 27)]; /* 711 */ + char interleave [ISODCL (28, 28)]; /* 711 */ + char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + char name [34]; /* Not really, but we need something here */ +}; +#endif + + + diff --git a/util/mkisofs/match.c b/util/mkisofs/match.c new file mode 100644 index 000000000..0f5c7d8a7 --- /dev/null +++ b/util/mkisofs/match.c @@ -0,0 +1,56 @@ +/* + * 27-Mar-96: Jan-Piet Mens + * added 'match' option (-m) to specify regular expressions NOT to be included + * in the CD image. + */ + +static char rcsid[] ="$Id: match.c,v 1.2 1997/02/23 16:10:42 eric Rel $"; + +#include +#ifndef VMS +#ifdef HAVE_MALLOC_H +#include +#else +#include +#endif +#endif +#include +#include "match.h" + +#define MAXMATCH 1000 +static char *mat[MAXMATCH]; + +void add_match(fn) +char * fn; +{ + register int i; + + for (i=0; mat[i] && i excluded filenmae */ + } + } + return 0; /* not found -> not excluded */ +} diff --git a/util/mkisofs/match.h b/util/mkisofs/match.h new file mode 100644 index 000000000..90def7c2d --- /dev/null +++ b/util/mkisofs/match.h @@ -0,0 +1,14 @@ +/* + * 27th March 1996. Added by Jan-Piet Mens for matching regular expressions + * in paths. + * + */ + +/* + * $Id: match.h,v 1.1 1997/02/23 15:56:12 eric Rel $ + */ + +#include "fnmatch.h" + +void add_match(); +int matches(); diff --git a/util/mkisofs/mkisofs.c b/util/mkisofs/mkisofs.c new file mode 100644 index 000000000..a2e2d1874 --- /dev/null +++ b/util/mkisofs/mkisofs.c @@ -0,0 +1,660 @@ +/* + * Program mkisofs.c - generate iso9660 filesystem based upon directory + * tree on hard disk. + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +static char rcsid[] ="$Id: mkisofs.c,v 1.10.1.3 1998/06/02 03:36:16 eric Exp $"; + +/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ + +#include +#include "mkisofs.h" +#include "config.h" + +#ifdef linux +#include +#endif + +#include "iso9660.h" +#include + +#ifndef VMS +#include +#else +#include +#include "vms.h" +#endif + +#include +#include + +#ifndef VMS +#ifdef HAVE_UNISTD_H +#include +#endif +#endif + +#include "exclude.h" + +#ifdef __NetBSD__ +#include +#include +#endif + +struct directory * root = NULL; + +static char version_string[] = "mkisofs v1.11.3"; + +FILE * discimage; +unsigned int next_extent = 0; +unsigned int last_extent = 0; +unsigned int session_start = 0; +unsigned int path_table_size = 0; +unsigned int path_table[4] = {0,}; +unsigned int path_blocks = 0; +struct iso_directory_record root_record; +char * extension_record = NULL; +int extension_record_extent = 0; +static int extension_record_size = 0; + +/* These variables are associated with command line options */ +int use_eltorito = 0; +int use_RockRidge = 0; +int verbose = 0; +int all_files = 0; +int follow_links = 0; +int rationalize = 0; +int generate_tables = 0; +char * preparer = PREPARER_DEFAULT; +char * publisher = PUBLISHER_DEFAULT; +char * appid = APPID_DEFAULT; +char * copyright = COPYRIGHT_DEFAULT; +char * biblio = BIBLIO_DEFAULT; +char * abstract = ABSTRACT_DEFAULT; +char * volset_id = VOLSET_ID_DEFAULT; +char * volume_id = VOLUME_ID_DEFAULT; +char * system_id = SYSTEM_ID_DEFAULT; +char * boot_catalog = BOOT_CATALOG_DEFAULT; +char * boot_image = BOOT_IMAGE_DEFAULT; + +int omit_period = 0; /* Violates iso9660, but these are a pain */ +int transparent_compression = 0; /* So far only works with linux */ +int omit_version_number = 0; /* May violate iso9660, but noone uses vers*/ +int RR_relocation_depth = 6; /* Violates iso9660, but most systems work */ +int full_iso9660_filenames = 0; /* Used with Amiga. Disc will not work with + DOS */ +int allow_leading_dots = 0; /* DOS cannot read names with leading dots */ + +struct rcopts{ + char * tag; + char ** variable; +}; + +struct rcopts rcopt[] = { + {"PREP", &preparer}, + {"PUBL", &publisher}, + {"APPI", &appid}, + {"COPY", ©right}, + {"BIBL", &biblio}, + {"ABST", &abstract}, + {"VOLS", &volset_id}, + {"VOLI", &volume_id}, + {"SYSI", &system_id}, + {NULL, NULL} +}; + +#if defined(ultrix) || defined(_AUX_SOURCE) +char *strdup(s) +char *s;{char *c;if(c=(char *)malloc(strlen(s)+1))strcpy(c,s);return c;} +#endif + +void FDECL1(read_rcfile, char *, appname) +{ + FILE * rcfile; + struct rcopts * rco; + char * pnt, *pnt1; + char linebuffer[256]; + static char rcfn[] = ".mkisofsrc"; + char filename[1000]; + int linum; + + strcpy(filename, rcfn); + rcfile = fopen(filename, "r"); + if (!rcfile && errno != ENOENT) + perror(filename); + + if (!rcfile) + { + pnt = getenv("MKISOFSRC"); + if (pnt && strlen(pnt) <= sizeof(filename)) + { + strcpy(filename, pnt); + rcfile = fopen(filename, "r"); + if (!rcfile && errno != ENOENT) + perror(filename); + } + } + + if (!rcfile) + { + pnt = getenv("HOME"); + if (pnt && strlen(pnt) + strlen(rcfn) + 2 <= sizeof(filename)) + { + strcpy(filename, pnt); + strcat(filename, "/"); + strcat(filename, rcfn); + rcfile = fopen(filename, "r"); + if (!rcfile && errno != ENOENT) + perror(filename); + } + } + if (!rcfile && strlen(appname)+sizeof(rcfn)+2 <= sizeof(filename)) + { + strcpy(filename, appname); + pnt = strrchr(filename, '/'); + if (pnt) + { + strcpy(pnt + 1, rcfn); + rcfile = fopen(filename, "r"); + if (!rcfile && errno != ENOENT) + perror(filename); + } + } + if (!rcfile) + return; + fprintf(stderr, "Using \"%s\"\n", filename); + /* OK, we got it. Now read in the lines and parse them */ + linum = 0; + while (fgets(linebuffer, sizeof(linebuffer), rcfile)) + { + char *name; + char *name_end; + ++linum; + /* skip any leading white space */ + pnt = linebuffer; + while (*pnt == ' ' || *pnt == '\t') + ++pnt; + /* If we are looking at a # character, this line is a comment. */ + if (*pnt == '#') + continue; + /* The name should begin in the left margin. Make sure it is in + upper case. Stop when we see white space or a comment. */ + name = pnt; + while (*pnt && isalpha(*pnt)) + { + if(islower(*pnt)) + *pnt = toupper(*pnt); + pnt++; + } + if (name == pnt) + { + fprintf(stderr, "%s:%d: name required\n", filename, linum); + continue; + } + name_end = pnt; + /* Skip past white space after the name */ + while (*pnt == ' ' || *pnt == '\t') + pnt++; + /* silently ignore errors in the rc file. */ + if (*pnt != '=') + { + fprintf(stderr, "%s:%d: equals sign required\n", filename, linum); + continue; + } + /* Skip pas the = sign, and any white space following it */ + pnt++; /* Skip past '=' sign */ + while (*pnt == ' ' || *pnt == '\t') + pnt++; + + /* now it is safe to NUL terminate the name */ + + *name_end = 0; + + /* Now get rid of trailing newline */ + + pnt1 = pnt; + while (*pnt1) + { + if (*pnt1 == '\n') + { + *pnt1 = 0; + break; + } + pnt1++; + }; + /* OK, now figure out which option we have */ + for(rco = rcopt; rco->tag; rco++) { + if(strcmp(rco->tag, name) == 0) + { + *rco->variable = strdup(pnt); + break; + }; + } + if (rco->tag == NULL) + { + fprintf(stderr, "%s:%d: field name \"%s\" unknown\n", filename, linum, + name); + } + } + if (ferror(rcfile)) + perror(filename); + fclose(rcfile); +} + +char * path_table_l = NULL; +char * path_table_m = NULL; +int goof = 0; + +void usage(){ + fprintf(stderr,"Usage:\n"); + fprintf(stderr, +"mkisofs [-o outfile] [-R] [-V volid] [-v] [-a] \ +[-T]\n [-l] [-d] [-V] [-D] [-L] [-p preparer]" +#ifdef ADD_FILES +"[-i file] \n" +#endif +"[-P publisher] [ -A app_id ] [-z] \n \ +[-b boot_image_name] [-c boot_catalog-name] \ +[-x path -x path ...] path\n"); + exit(1); +} + + +/* + * Fill in date in the iso9660 format + * + * The standards state that the timezone offset is in multiples of 15 + * minutes, and is what you add to GMT to get the localtime. The U.S. + * is always at a negative offset, from -5h to -8h (can vary a little + * with DST, I guess). The Linux iso9660 filesystem has had the sign + * of this wrong for ages (mkisofs had it wrong too for the longest time). + */ +int FDECL2(iso9660_date,char *, result, time_t, ctime){ + struct tm *local; + local = localtime(&ctime); + result[0] = local->tm_year; + result[1] = local->tm_mon + 1; + result[2] = local->tm_mday; + result[3] = local->tm_hour; + result[4] = local->tm_min; + result[5] = local->tm_sec; + + /* + * Must recalculate proper timezone offset each time, + * as some files use daylight savings time and some don't... + */ + result[6] = local->tm_yday; /* save yday 'cause gmtime zaps it */ + local = gmtime(&ctime); + local->tm_year -= result[0]; + local->tm_yday -= result[6]; + local->tm_hour -= result[3]; + local->tm_min -= result[4]; + if (local->tm_year < 0) + { + local->tm_yday = -1; + } + else + { + if (local->tm_year > 0) local->tm_yday = 1; + } + + result[6] = -(local->tm_min + 60*(local->tm_hour + 24*local->tm_yday)) / 15; + + return 0; +} + + +extern char * cdwrite_data; + +int FDECL2(main, int, argc, char **, argv){ + char * outfile; + struct directory_entry de; + unsigned long mem_start; + struct stat statbuf; + char * scan_tree; + char * merge_image = NULL; + struct iso_directory_record * mrootp = NULL; + int c; +#ifdef ADD_FILES + char *add_file_file = NULL; +#endif + + if (argc < 2) + usage(); + + /* Get the defaults from the .mkisofsrc file */ + read_rcfile(argv[0]); + + outfile = NULL; + while ((c = getopt(argc, argv, "i:o:V:RrfvaTp:P:b:c:x:dDlLNzA:M:m:C:")) != EOF) + switch (c) + { + case 'C': + /* + * This is a temporary hack until cdwrite gets the proper hooks in + * it. + */ + cdwrite_data = optarg; + break; + case 'a': + all_files++; + break; + case 'b': + use_eltorito++; + boot_image = optarg; /* pathname of the boot image on cd */ + if (boot_image == NULL) { + fprintf(stderr,"Required boot image pathname missing\n"); + exit(1); + } + break; + case 'c': + use_eltorito++; + boot_catalog = optarg; /* pathname of the boot image on cd */ + if (boot_catalog == NULL) { + fprintf(stderr,"Required boot catalog pathname missing\n"); + exit(1); + } + break; + case 'A': + appid = optarg; + if(strlen(appid) > 128) { + fprintf(stderr,"Application-id string too long\n"); + exit(1); + }; + break; + case 'd': + omit_period++; + break; + case 'D': + RR_relocation_depth = 32767; + break; + case 'f': + follow_links++; + break; + case 'i': +#ifdef ADD_FILES + add_file_file = optarg; + break; +#else + usage(); + exit(1); +#endif + case 'l': + full_iso9660_filenames++; + break; + case 'L': + allow_leading_dots++; + break; + case 'M': + merge_image = optarg; + break; + case 'N': + omit_version_number++; + break; + case 'o': + outfile = optarg; + break; + case 'p': + preparer = optarg; + if(strlen(preparer) > 128) { + fprintf(stderr,"Preparer string too long\n"); + exit(1); + }; + break; + case 'P': + publisher = optarg; + if(strlen(publisher) > 128) { + fprintf(stderr,"Publisher string too long\n"); + exit(1); + }; + break; + case 'R': + use_RockRidge++; + break; + case 'r': + rationalize++; + use_RockRidge++; + break; + case 'T': + generate_tables++; + break; + case 'V': + volume_id = optarg; + break; + case 'v': + verbose++; + break; + case 'z': +#ifdef VMS + fprintf(stderr,"Transparent compression not supported with VMS\n"); + exit(1); +#else + transparent_compression++; +#endif + break; + case 'm': + add_match(optarg); + break; + case 'x': + exclude(optarg); + break; + default: + usage(); + exit(1); + } +#ifdef __NetBSD__ + { + int resource; + struct rlimit rlp; + if (getrlimit(RLIMIT_DATA,&rlp) == -1) + perror("Warning: getrlimit"); + else { + rlp.rlim_cur=33554432; + if (setrlimit(RLIMIT_DATA,&rlp) == -1) + perror("Warning: setrlimit"); + } + } +#endif +#ifdef HAVE_SBRK + mem_start = (unsigned long) sbrk(0); +#endif + + if(verbose) fprintf(stderr,"%s\n", version_string); + + if( (cdwrite_data != NULL && merge_image == NULL) + || (cdwrite_data == NULL && merge_image != NULL) ) + { + fprintf(stderr,"Multisession usage bug - both -C and -M must be specified.\n"); + exit(0); + } + + /* The first step is to scan the directory tree, and take some notes */ + + scan_tree = argv[optind]; + +#ifdef ADD_FILES + if (add_file_file) { + add_file(add_file_file); + } + add_file_list (argc, argv, optind+1); +#endif + + if(!scan_tree){ + usage(); + exit(1); + }; + +#ifndef VMS + if(scan_tree[strlen(scan_tree)-1] != '/') { + scan_tree = (char *) e_malloc(strlen(argv[optind])+2); + strcpy(scan_tree, argv[optind]); + strcat(scan_tree, "/"); + }; +#endif + + if(use_RockRidge){ +#if 1 + extension_record = generate_rr_extension_record("RRIP_1991A", + "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS", + "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.", &extension_record_size); +#else + extension_record = generate_rr_extension_record("IEEE_P1282", + "THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS", + "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION.", &extension_record_size); +#endif + } + + /* + * See if boot catalog file exists in root directory, if not + * we will create it. + */ + if (use_eltorito) + init_boot_catalog(argv[optind]); + + /* + * Find the device and inode number of the root directory. + * Record this in the hash table so we don't scan it more than + * once. + */ + stat_filter(argv[optind], &statbuf); + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + + memset(&de, 0, sizeof(de)); + + de.filedir = root; /* We need this to bootstrap */ + + if( merge_image != NULL ) + { + mrootp = merge_isofs(merge_image); + if( mrootp == NULL ) + { + /* + * Complain and die. + */ + fprintf(stderr,"Unable to open previous session image %s\n", + merge_image); + exit(1); + } + + memcpy(&de.isorec.extent, mrootp->extent, 8); + } + + /* + * Scan the actual directory (and any we find below it) + * for files to write out to the output image. + */ + if (!scan_directory_tree(argv[optind], &de, mrootp)) + { + exit(1); + } + + /* + * Fix a couple of things in the root directory so that everything + * is self consistent. + */ + root->self = root->contents; /* Fix this up so that the path tables get done right */ + + if(reloc_dir) sort_n_finish(reloc_dir); + + if (goof) exit(1); + + /* + * OK, ready to write the file. Open it up, and generate the thing. + */ + if (outfile){ + discimage = fopen(outfile, "w"); + if (!discimage){ + fprintf(stderr,"Unable to open disc image file\n"); + exit(1); + + }; + } else + discimage = stdout; + + /* Now assign addresses on the disc for the path table. */ + + path_blocks = (path_table_size + (SECTOR_SIZE - 1)) >> 11; + if (path_blocks & 1) path_blocks++; + + path_table[0] = session_start + 0x10 + 2 + (use_eltorito ? 1 : 0); + path_table[1] = 0; + path_table[2] = path_table[0] + path_blocks; + path_table[3] = 0; + + last_extent += path_table[2] - session_start + path_blocks; + /* The next free block */ + + /* The next step is to go through the directory tree and assign extent + numbers for all of the directories */ + + assign_directory_addresses(root); + + if(extension_record) { + struct directory_entry * s_entry; + extension_record_extent = last_extent++; + s_entry = root->contents; + set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 24, + extension_record_extent); + set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 8, + extension_record_size); + }; + + if (use_RockRidge && reloc_dir) + finish_cl_pl_entries(); + + /* Now we generate the path tables that are used by DOS to improve directory + access times. */ + generate_path_tables(); + + /* Generate root record for volume descriptor. */ + generate_root_record(); + + if (verbose) + dump_tree(root); + + if( in_image != NULL ) + { + fclose(in_image); + } + + iso_write(discimage); + +#ifdef HAVE_SBRK + fprintf(stderr,"Max brk space used %x\n", + (unsigned int)(((unsigned long)sbrk(0)) - mem_start)); +#endif + fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9); +#ifdef VMS + return 1; +#else + return 0; +#endif +} + +void * +FDECL1(e_malloc, size_t, size) +{ +void* pt = 0; + if( (size > 0) && ((pt=malloc(size))==NULL) ) { + fprintf(stderr, "Not enough memory\n"); + exit (1); + } +return pt; +} diff --git a/util/mkisofs/mkisofs.h b/util/mkisofs/mkisofs.h new file mode 100644 index 000000000..bc264d99a --- /dev/null +++ b/util/mkisofs/mkisofs.h @@ -0,0 +1,339 @@ +/* + * Header file mkisofs.h - assorted structure definitions and typecasts. + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + * $Id: mkisofs.h,v 1.5 1997/05/17 15:50:28 eric Exp $ + */ + +/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ + +#include + +/* This symbol is used to indicate that we do not have things like + symlinks, devices, and so forth available. Just files and dirs */ + +#ifdef VMS +#define NON_UNIXFS +#endif + +#ifdef DJGPP +#define NON_UNIXFS +#endif + +#ifdef VMS +#include +#define dirent direct +#else +#include +#endif + +#include +#include +#include + +#ifdef linux +#include +#endif + +#ifdef ultrix +extern char *strdup(); +#endif + +#ifdef __STDC__ +#define DECL(NAME,ARGS) NAME ARGS +#define FDECL1(NAME,TYPE0, ARG0) \ + NAME(TYPE0 ARG0) +#define FDECL2(NAME,TYPE0, ARG0,TYPE1, ARG1) \ + NAME(TYPE0 ARG0, TYPE1 ARG1) +#define FDECL3(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2) \ + NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2) +#define FDECL4(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3) \ + NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3) +#define FDECL5(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4) \ + NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3, TYPE4 ARG4) +#define FDECL6(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4, TYPE5, ARG5) \ + NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3, TYPE4 ARG4, TYPE5 ARG5) +#else +#define DECL(NAME,ARGS) NAME() +#define FDECL1(NAME,TYPE0, ARG0) NAME(ARG0) TYPE0 ARG0; +#define FDECL2(NAME,TYPE0, ARG0,TYPE1, ARG1) NAME(ARG0, ARG1) TYPE0 ARG0; TYPE1 ARG1; +#define FDECL3(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2) \ + NAME(ARG0, ARG1, ARG2) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; +#define FDECL4(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3) \ + NAME(ARG0, ARG1, ARG2, ARG3, ARG4) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; +#define FDECL5(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4) \ + NAME(ARG0, ARG1, ARG2, ARG3, ARG4) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; TYPE4 ARG4; +#define FDECL6(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4, TYPE5, ARG5) \ + NAME(ARG0, ARG1, ARG2, ARG3, ARG4, ARG5) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; TYPE4 ARG4; TYPE5 ARG5; +#define const +#endif + + +#ifdef __svr4__ +#include +#else +extern int optind; +extern char *optarg; +/* extern int getopt (int __argc, char **__argv, char *__optstring); */ +#endif + +#include "iso9660.h" +#include "defaults.h" + +struct directory_entry{ + struct directory_entry * next; + struct iso_directory_record isorec; + unsigned int starting_block; + unsigned int size; + unsigned int priority; + char * name; + char * table; + char * whole_name; + struct directory * filedir; + struct directory_entry * parent_rec; + unsigned int de_flags; + ino_t inode; /* Used in the hash table */ + dev_t dev; /* Used in the hash table */ + unsigned char * rr_attributes; + unsigned int rr_attr_size; + unsigned int total_rr_attr_size; +}; + +struct file_hash{ + struct file_hash * next; + ino_t inode; /* Used in the hash table */ + dev_t dev; /* Used in the hash table */ + unsigned int starting_block; + unsigned int size; +}; + +/* + * This structure describes one complete directory. It has pointers + * to other directories in the overall tree so that it is clear where + * this directory lives in the tree, and it also must contain pointers + * to the contents of the directory. Note that subdirectories of this + * directory exist twice in this stucture. Once in the subdir chain, + * and again in the contents chain. + */ +struct directory{ + struct directory * next; /* Next directory at same level as this one */ + struct directory * subdir; /* First subdirectory in this directory */ + struct directory * parent; + struct directory_entry * contents; + struct directory_entry * self; + char * whole_name; /* Entire path */ + char * de_name; /* Entire path */ + unsigned int ce_bytes; /* Number of bytes of CE entries reqd for this dir */ + unsigned int depth; + unsigned int size; + unsigned int extent; + unsigned short path_index; +}; + +struct deferred{ + struct deferred * next; + unsigned int starting_block; + char * name; + struct directory * filedir; + unsigned int flags; +}; + +extern int goof; +extern struct directory * root; +extern struct directory * reloc_dir; +extern unsigned int next_extent; +extern unsigned int last_extent; +extern unsigned int last_extent_written; +extern unsigned int session_start; +extern unsigned int path_table_size; +extern unsigned int path_table[4]; +extern unsigned int path_blocks; +extern char * path_table_l; +extern char * path_table_m; +extern struct iso_directory_record root_record; + +extern int use_eltorito; +extern int use_RockRidge; +extern int rationalize; +extern int follow_links; +extern int verbose; +extern int all_files; +extern int generate_tables; +extern int omit_period; +extern int omit_version_number; +extern int transparent_compression; +extern int RR_relocation_depth; +extern int full_iso9660_filenames; + +/* tree.c */ +extern int DECL(stat_filter, (char *, struct stat *)); +extern void DECL(sort_n_finish,(struct directory *)); +extern void finish_cl_pl_entries(); +extern int DECL(scan_directory_tree,(char * path, + struct directory_entry * self, + struct iso_directory_record *)); +extern void DECL(generate_iso9660_directories,(struct directory *, FILE*)); +extern void DECL(dump_tree,(struct directory * node)); +extern struct directory_entry * DECL(search_tree_file, (struct + directory * node,char * filename)); + +/* eltorito.c */ +extern void DECL(init_boot_catalog, (const char * path )); +extern void DECL(get_torito_desc, (struct eltorito_boot_descriptor * path )); + +/* write.c */ +extern void DECL(assign_directory_addresses,(struct directory * root)); +extern int DECL(get_733,(char *)); +extern int DECL(isonum_733,(unsigned char *)); +extern void DECL(set_723,(char *, unsigned int)); +extern void DECL(set_731,(char *, unsigned int)); +extern void DECL(set_721,(char *, unsigned int)); +extern void DECL(set_733,(char *, unsigned int)); +extern void DECL(sort_directory,(struct directory_entry **)); +extern void generate_root_record(); +extern void DECL(generate_one_directory,(struct directory *, FILE*)); +extern void generate_path_tables(); +extern int DECL(iso_write,(FILE * outfile)); +extern void DECL(memcpy_max, (char *, char *, int)); + + +/* multi.c */ + +extern FILE * in_image; +extern struct iso_directory_record * + DECL(merge_isofs,(char * path)); + +extern int DECL(free_mdinfo, (struct directory_entry **, int len)); + +extern struct directory_entry ** + DECL(read_merging_directory,(struct iso_directory_record *, int*)); +extern void + DECL(merge_remaining_entries, (struct directory *, + struct directory_entry **, int)); + +/* match.c */ +extern int DECL(matches, (char *)); +extern void DECL(add_match, (char *)); + +/* files.c */ +struct dirent * DECL(readdir_add_files, (char **, char *, DIR *)); + +/* */ + +extern int DECL(iso9660_file_length,(const char* name, + struct directory_entry * sresult, int flag)); +extern int DECL(iso9660_date,(char *, time_t)); +extern void DECL(add_hash,(struct directory_entry *)); +extern struct file_hash * DECL(find_hash,(dev_t, ino_t)); +extern void DECL(add_directory_hash,(dev_t, ino_t)); +extern struct file_hash * DECL(find_directory_hash,(dev_t, ino_t)); +extern void flush_file_hash(); +extern int DECL(delete_file_hash,(struct directory_entry *)); +extern struct directory_entry * DECL(find_file_hash,(char *)); +extern void DECL(add_file_hash,(struct directory_entry *)); +extern int DECL(generate_rock_ridge_attributes,(char *, char *, + struct directory_entry *, + struct stat *, struct stat *, + int deep_flag)); +extern char * DECL(generate_rr_extension_record,(char * id, char * descriptor, + char * source, int * size)); + +extern int DECL(check_prev_session, (struct directory_entry **, int len, + struct directory_entry *, + struct stat *, + struct stat *, + struct directory_entry **)); + +#ifdef USE_SCG +/* scsi.c */ +extern int readsecs(int startsecno, void *buffer, int sectorcount); +extern int scsidev_open(char *path); +#endif + +extern char * extension_record; +extern int extension_record_extent; +extern int n_data_extents; + +/* These are a few goodies that can be specified on the command line, and are + filled into the root record */ + +extern char * preparer; +extern char * publisher; +extern char * copyright; +extern char * biblio; +extern char * abstract; +extern char * appid; +extern char * volset_id; +extern char * system_id; +extern char * volume_id; +extern char * boot_catalog; +extern char * boot_image; + +extern void * DECL(e_malloc,(size_t)); + + +#define SECTOR_SIZE (2048) +#define ROUND_UP(X) ((X + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1)) + +#define NEED_RE 1 +#define NEED_PL 2 +#define NEED_CL 4 +#define NEED_CE 8 +#define NEED_SP 16 + +#define PREV_SESS_DEV (sizeof(dev_t) >= 4 ? 0x7ffffffd : 0x7ffd) +#define TABLE_INODE (sizeof(ino_t) >= 4 ? 0x7ffffffe : 0x7ffe) +#define UNCACHED_INODE (sizeof(ino_t) >= 4 ? 0x7fffffff : 0x7fff) +#define UNCACHED_DEVICE (sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff) + +#ifdef VMS +#define STAT_INODE(X) (X.st_ino[0]) +#define PATH_SEPARATOR ']' +#define SPATH_SEPARATOR "" +#else +#define STAT_INODE(X) (X.st_ino) +#define PATH_SEPARATOR '/' +#define SPATH_SEPARATOR "/" +#endif + +/* + * When using multi-session, indicates that we can reuse the + * TRANS.TBL information for this directory entry. If this flag + * is set for all entries in a directory, it means we can just + * reuse the TRANS.TBL and not generate a new one. + */ +#define SAFE_TO_REUSE_TABLE_ENTRY 1 +/* + * Volume sequence number to use in all of the iso directory records. + */ +#define DEF_VSN 1 + +/* + * Make sure we have a definition for this. If not, take a very conservative + * guess. From what I can tell SunOS is the only one with this trouble. + */ +#ifndef NAME_MAX +#ifdef FILENAME_MAX +#define NAME_MAX FILENAME_MAX +#else +#define NAME_MAX 128 +#endif +#endif diff --git a/util/mkisofs/multi.c b/util/mkisofs/multi.c new file mode 100644 index 000000000..13ba6f6d1 --- /dev/null +++ b/util/mkisofs/multi.c @@ -0,0 +1,1018 @@ +/* + * File multi.c - scan existing iso9660 image and merge into + * iso9660 filesystem. Used for multisession support. + * + * Written by Eric Youngdale (1996). + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +static char rcsid[] ="$Id: multi.c,v 1.6.1.3 1998/06/02 03:00:25 eric Exp $"; + +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#ifndef VMS + +#ifdef HAVE_UNISTD_H +#include +#endif + +#else +#include +#include +#include "vms.h" +extern char * strdup(const char *); +#endif + +#include "mkisofs.h" +#include "iso9660.h" + +#define TF_CREATE 1 +#define TF_MODIFY 2 +#define TF_ACCESS 4 +#define TF_ATTRIBUTES 8 + +static int DECL(get_session_start, (int *)); +static int DECL(merge_old_directory_into_tree, (struct directory_entry *, + struct directory *)); + +static int +isonum_711 (unsigned char * p) +{ + return (*p & 0xff); +} + +int +isonum_721 (unsigned char * p) +{ + return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); +} + +static int +isonum_723 (unsigned char * p) +{ +#if 0 + if (p[0] != p[3] || p[1] != p[2]) { + fprintf (stderr, "invalid format 7.2.3 number\n"); + exit (1); + } +#endif + return (isonum_721 (p)); +} + +int +isonum_731 (unsigned char * p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +int +isonum_733 (unsigned char * p) +{ + return (isonum_731 (p)); +} + +FILE * in_image = NULL; + +#ifndef USE_SCG +/* + * Don't define readsecs if mkisofs is linked with + * the SCSI library. + * readsecs() will be implemented as SCSI command in this case. + * + * Use global var in_image directly in readsecs() + * the SCSI equivalent will not use a FILE* for I/O. + * + * The main point of this pointless abstraction is that Solaris won't let + * you read 2K sectors from the cdrom driver. The fact that 99.9% of the + * discs out there have a 2K sectorsize doesn't seem to matter that much. + * Anyways, this allows the use of a scsi-generics type of interface on + * Solaris. + */ +static int +readsecs(int startsecno, void *buffer, int sectorcount) +{ + int f = fileno(in_image); + + if (lseek(f, (off_t)startsecno * SECTOR_SIZE, 0) == (off_t)-1) { + fprintf(stderr," Seek error on old image\n"); + exit(10); + } + return (read(f, buffer, sectorcount * SECTOR_SIZE)); +} +#endif + +/* + * Parse the RR attributes so we can find the file name. + */ +static int +FDECL3(parse_rr, unsigned char *, pnt, int, len, struct directory_entry *,dpnt) +{ + int cont_extent, cont_offset, cont_size; + char name_buf[256]; + + cont_extent = cont_offset = cont_size = 0; + + while(len >= 4){ + if(pnt[3] != 1) { + printf("**BAD RRVERSION"); + return -1; + }; + if(strncmp((char *) pnt, "NM", 2) == 0) { + strncpy(name_buf, (char *) pnt+5, pnt[2] - 5); + name_buf[pnt[2] - 5] = 0; + dpnt->name = strdup(name_buf); + return 0; + } + + if(strncmp((char *) pnt, "CE", 2) == 0) { + cont_extent = isonum_733(pnt+4); + cont_offset = isonum_733(pnt+12); + cont_size = isonum_733(pnt+20); + }; + + len -= pnt[2]; + pnt += pnt[2]; + if(len <= 3 && cont_extent) { + unsigned char sector[SECTOR_SIZE]; + readsecs(cont_extent, sector, 1); + parse_rr(§or[cont_offset], cont_size, dpnt); + }; + }; + return 0; +} + + +static int +FDECL4(check_rr_dates, struct directory_entry *, dpnt, + struct directory_entry *, current, + struct stat *, statbuf, + struct stat *,lstatbuf) +{ + int cont_extent, cont_offset, cont_size; + int offset; + unsigned char * pnt; + int len; + int same_file; + int same_file_type; + mode_t mode; + char time_buf[7]; + + + cont_extent = cont_offset = cont_size = 0; + same_file = 1; + same_file_type = 1; + + pnt = dpnt->rr_attributes; + len = dpnt->rr_attr_size; + /* + * We basically need to parse the rr attributes again, and + * dig out the dates and file types. + */ + while(len >= 4){ + if(pnt[3] != 1) { + printf("**BAD RRVERSION"); + return -1; + }; + + /* + * If we have POSIX file modes, make sure that the file type + * is the same. If it isn't, then we must always + * write the new file. + */ + if(strncmp((char *) pnt, "PX", 2) == 0) { + mode = isonum_733(pnt + 4); + if( (lstatbuf->st_mode & S_IFMT) != (mode & S_IFMT) ) + { + same_file_type = 0; + same_file = 0; + } + } + + if(strncmp((char *) pnt, "TF", 2) == 0) { + offset = 5; + if( pnt[4] & TF_CREATE ) + { + iso9660_date((char *) time_buf, lstatbuf->st_ctime); + if(memcmp(time_buf, pnt+offset, 7) == 0) + same_file = 0; + offset += 7; + } + if( pnt[4] & TF_MODIFY ) + { + iso9660_date((char *) time_buf, lstatbuf->st_mtime); + if(memcmp(time_buf, pnt+offset, 7) == 0) + same_file = 0; + offset += 7; + } + } + + if(strncmp((char *) pnt, "CE", 2) == 0) { + cont_extent = isonum_733(pnt+4); + cont_offset = isonum_733(pnt+12); + cont_size = isonum_733(pnt+20); + }; + + len -= pnt[2]; + pnt += pnt[2]; + if(len <= 3 && cont_extent) { + unsigned char sector[SECTOR_SIZE]; + + readsecs(cont_extent, sector, 1); + parse_rr(§or[cont_offset], cont_size, dpnt); + }; + }; + + /* + * If we have the same fundamental file type, then it is clearly + * safe to reuse the TRANS.TBL entry. + */ + if( same_file_type ) + { + current->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY; + } + + return same_file; +} + +struct directory_entry ** +FDECL2(read_merging_directory, struct iso_directory_record *, mrootp, + int *, nent) +{ + unsigned char * cpnt; + unsigned char * cpnt1; + char * dirbuff; + int i; + struct iso_directory_record * idr; + int len; + struct directory_entry **pnt; + int rlen; + struct directory_entry **rtn; + int seen_rockridge; + unsigned char * tt_buf; + int tt_extent; + int tt_size; + + /* + * First, allocate a buffer large enough to read in the entire + * directory. + */ + dirbuff = (char *) e_malloc(isonum_733((unsigned char *)mrootp->size)); + + readsecs(isonum_733((unsigned char *)mrootp->extent), dirbuff, + isonum_733((unsigned char *)mrootp->size)/SECTOR_SIZE); + + /* + * Next look over the directory, and count up how many entries we + * have. + */ + len = isonum_733((unsigned char *)mrootp->size); + i = 0; + *nent = 0; + while(i < len ) + { + idr = (struct iso_directory_record *) &dirbuff[i]; + if(idr->length[0] == 0) + { + i = (i + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1); + continue; + } + (*nent)++; + i += idr->length[0]; + } + + /* + * Now allocate the buffer which will hold the array we are + * about to return. + */ + rtn = (struct directory_entry **) e_malloc(*nent * sizeof(*rtn)); + + /* + * Finally, scan the directory one last time, and pick out the + * relevant bits of information, and store it in the relevant + * bits of the structure. + */ + i = 0; + pnt = rtn; + tt_extent = 0; + seen_rockridge = 0; + tt_size = 0; + while(i < len ) + { + idr = (struct iso_directory_record *) &dirbuff[i]; + if(idr->length[0] == 0) + { + i = (i + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1); + continue; + } + *pnt = (struct directory_entry *) e_malloc(sizeof(**rtn)); + (*pnt)->next = NULL; + (*pnt)->isorec = *idr; + (*pnt)->starting_block = isonum_733((unsigned char *)idr->extent); + (*pnt)->size = isonum_733((unsigned char *)idr->size); + (*pnt)->priority = 0; + (*pnt)->name = NULL; + (*pnt)->table = NULL; + (*pnt)->whole_name = NULL; + (*pnt)->filedir = NULL; + (*pnt)->parent_rec = NULL; + /* + * Set this information so that we correctly cache previous + * session bits of information. + */ + (*pnt)->inode = (*pnt)->starting_block; + (*pnt)->dev = PREV_SESS_DEV; + (*pnt)->rr_attributes = NULL; + (*pnt)->rr_attr_size = 0; + (*pnt)->total_rr_attr_size = 0; + (*pnt)->de_flags = SAFE_TO_REUSE_TABLE_ENTRY; + + /* + * Check for and parse any RR attributes for the file. + * All we are really looking for here is the original name + * of the file. + */ + rlen = idr->length[0] & 0xff; + cpnt = (unsigned char *) idr; + + rlen -= sizeof(struct iso_directory_record); + cpnt += sizeof(struct iso_directory_record); + + rlen += sizeof(idr->name); + cpnt -= sizeof(idr->name); + + rlen -= idr->name_len[0]; + cpnt += idr->name_len[0]; + + if((idr->name_len[0] & 1) == 0){ + cpnt++; + rlen--; + }; + + if( rlen != 0 ) + { + (*pnt)->total_rr_attr_size = (*pnt)->rr_attr_size = rlen; + (*pnt)->rr_attributes = e_malloc(rlen); + memcpy((*pnt)->rr_attributes, cpnt, rlen); + seen_rockridge = 1; + } + + /* + * Now zero out the remainder of the name field. + */ + cpnt = (unsigned char *) &(*pnt)->isorec.name; + cpnt += idr->name_len[0]; + memset(cpnt, 0, sizeof((*pnt)->isorec.name) - idr->name_len[0]); + + parse_rr((*pnt)->rr_attributes, rlen, *pnt); + + if( ((*pnt)->isorec.name_len[0] == 1) + && ( ((*pnt)->isorec.name[0] == 0) + || ((*pnt)->isorec.name[0] == 1)) ) + { + if( (*pnt)->name != NULL ) + { + free((*pnt)->name); + } + if( (*pnt)->whole_name != NULL ) + { + free((*pnt)->whole_name); + } + if( (*pnt)->isorec.name[0] == 0 ) + { + (*pnt)->name = strdup("."); + } + else + { + (*pnt)->name = strdup(".."); + } + } + + if( strncmp(idr->name, "TRANS.TBL", 9) == 0) + { + if( (*pnt)->name != NULL ) + { + free((*pnt)->name); + } + if( (*pnt)->whole_name != NULL ) + { + free((*pnt)->whole_name); + } + (*pnt)->name = strdup(""); + tt_extent = isonum_733((unsigned char *)idr->extent); + tt_size = isonum_733((unsigned char *)idr->size); + } + + pnt++; + i += idr->length[0]; + } + + /* + * If there was a TRANS.TBL;1 entry, then grab it, read it, and use it + * to get the filenames of the files. Also, save the table info, just + * in case we need to use it. + */ + if( tt_extent != 0 && tt_size != 0 ) + { + tt_buf = (unsigned char *) e_malloc(tt_size); + readsecs(tt_extent, tt_buf, tt_size/SECTOR_SIZE); + + /* + * Loop through the file, examine each entry, and attempt to + * attach it to the correct entry. + */ + cpnt = tt_buf; + cpnt1 = tt_buf; + while( cpnt - tt_buf < tt_size ) + { + while(*cpnt1 != '\n' && *cpnt1 != '\0') cpnt1++; + *cpnt1 = '\0'; + + for(pnt = rtn, i = 0; i <*nent; i++, pnt++) + { + rlen = isonum_711((*pnt)->isorec.name_len); + if( strncmp((char *) cpnt + 2, (*pnt)->isorec.name, + rlen) == 0 + && cpnt[2+rlen] == ' ') + { + (*pnt)->table = e_malloc(strlen((char*)cpnt) - 34); + sprintf((*pnt)->table, "%c\t%s\n", + *cpnt, cpnt+37); + if( (*pnt)->name == NULL ) + { + (*pnt)->name = strdup((char *) cpnt+37); + } + break; + } + } + cpnt = cpnt1 + 1; + cpnt1 = cpnt; + } + + free(tt_buf); + } + else if( !seen_rockridge ) + { + /* + * This is a fatal error right now because we must have some mechanism + * for taking the 8.3 names back to the original unix names. + * In principle we could do this the hard way, and try and translate + * the unix names that we have seen forwards, but this would be + * a real pain in the butt. + */ + fprintf(stderr,"Previous session must have either Rock Ridge (-R) or\n"); + fprintf(stderr,"TRANS.TBL (-T) for mkisofs to be able to correctly\n"); + fprintf(stderr,"generate additional sessions.\n"); + exit(3); + } + + if( dirbuff != NULL ) + { + free(dirbuff); + } + + return rtn; +} + +/* + * Free any associated data related to the structures. + */ +int +FDECL2(free_mdinfo, struct directory_entry ** , ptr, int, len ) +{ + int i; + struct directory_entry **p; + + p = ptr; + for(i=0; iname != NULL ) + { + free((*p)->name); + } + + if( (*p)->whole_name != NULL ) + { + free((*p)->whole_name); + } + + if( (*p)->rr_attributes != NULL ) + { + free((*p)->rr_attributes); + } + + if( (*p)->table != NULL ) + { + free((*p)->table); + } + + free(*p); + + } + + free(ptr); + return 0; +} + +/* + * Search the list to see if we have any entries from the previous + * session that match this entry. If so, copy the extent number + * over so we don't bother to write it out to the new session. + */ + +int +FDECL6(check_prev_session, struct directory_entry ** , ptr, int, len, + struct directory_entry *, curr_entry, + struct stat *, statbuf, struct stat *, lstatbuf, + struct directory_entry **, odpnt) +{ + int i; + + for( i=0; i < len; i++ ) + { + if( ptr[i] == NULL ) + { + continue; + } + +#if 0 + if( ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1 + && ptr[i]->name[0] == '\0' ) + { + continue; + } + if( ptr[i]->name != NULL && ptr[i]->isorec.name_len[0] == 1 + && ptr[i]->name[0] == 1) + { + continue; + } +#else + if( ptr[i]->name != NULL && strcmp(ptr[i]->name, ".") == 0 ) + { + continue; + } + if( ptr[i]->name != NULL && strcmp(ptr[i]->name, "..") == 0 ) + { + continue; + } +#endif + + if( ptr[i]->name != NULL + && strcmp(ptr[i]->name, curr_entry->name) != 0 ) + { + continue; + } + + /* + * We know that the files have the same name. If they also have + * the same file type (i.e. file, dir, block, etc), then we + * can safely reuse the TRANS.TBL entry for this file. + * The check_rr_dates function will do this for us. + * + * Verify that the file type and dates are consistent. + * If not, we probably have a different file, and we need + * to write it out again. + */ + if( (ptr[i]->rr_attributes != NULL) + && (check_rr_dates(ptr[i], curr_entry, statbuf, lstatbuf)) ) + { + goto found_it; + } + + + /* + * Verify size and timestamp. If rock ridge is in use, we need + * to compare dates from RR too. Directories are special, we + * calculate their size later. + */ + if( (curr_entry->isorec.flags[0] & 2) == 0 + && ptr[i]->size != curr_entry->size ) + { + goto found_it; + } + + if( memcmp(ptr[i]->isorec.date, curr_entry->isorec.date,7) != 0 ) + { + goto found_it; + } + + /* + * Never ever reuse directory extents. See comments in + * tree.c for an explaination of why this must be the case. + */ + if( (curr_entry->isorec.flags[0] & 2) != 0 ) + { + goto found_it; + } + + memcpy(curr_entry->isorec.extent, ptr[i]->isorec.extent, 8); + curr_entry->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY; + goto found_it; + } + return 0; + +found_it: + if( odpnt != NULL ) + { + *odpnt = ptr[i]; + } + else + { + free(ptr[i]); + } + ptr[i] = NULL; + return 0; +} + +/* + * merge_isofs: Scan an existing image, and return a pointer + * to the root directory for this image. + */ +struct iso_directory_record * FDECL1(merge_isofs, char *, path) +{ + char buffer[SECTOR_SIZE]; + int file_addr; + int i; + struct iso_primary_descriptor * pri = NULL; + struct iso_directory_record * rootp; + struct iso_volume_descriptor * vdp; + + /* + * Start by opening up the image and searching for the volume header. + * Ultimately, we need to search for volume headers in multiple places + * because we might be starting with a multisession image. + * FIXME(eric). + */ + +#ifndef USE_SCG + in_image = fopen(path, "rb"); + if( in_image == NULL ) + { + return NULL; + } +#else + if (strchr(path, '/')) { + in_image = fopen(path, "rb"); + if( in_image == NULL ) { + return NULL; + } + } else { + if (scsidev_open(path) < 0) + return NULL; + } +#endif + + get_session_start(&file_addr); + + for(i = 0; i< 100; i++) + { + if (readsecs(file_addr/SECTOR_SIZE, &buffer, + sizeof(buffer)/SECTOR_SIZE) != sizeof(buffer)) + { + fprintf(stderr," Read error on old image %s\n", path); + exit(10); + } + + vdp = (struct iso_volume_descriptor *)buffer; + + if( (strncmp(vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) + && (isonum_711((unsigned char *) vdp->type) == ISO_VD_PRIMARY) ) + { + break; + } + file_addr += SECTOR_SIZE; + } + + if( i == 100 ) + { + return NULL; + } + + pri = (struct iso_primary_descriptor *)vdp; + + /* + * Check the blocksize of the image to make sure it is compatible. + */ + if( (isonum_723 ((unsigned char *) pri->logical_block_size) != SECTOR_SIZE) + || (isonum_723 ((unsigned char *) pri->volume_set_size) != 1) ) + { + return NULL; + } + + /* + * Get the location and size of the root directory. + */ + rootp = (struct iso_directory_record *) + malloc(sizeof(struct iso_directory_record)); + + memcpy(rootp, pri->root_directory_record, sizeof(*rootp)); + + return rootp; +} + +void FDECL3(merge_remaining_entries, struct directory *, this_dir, + struct directory_entry **, pnt, + int, n_orig) +{ + int i; + struct directory_entry * s_entry; + unsigned int ttbl_extent = 0; + unsigned int ttbl_index = 0; + + /* + * Whatever is leftover in the list needs to get merged back + * into the directory. + */ + for( i=0; i < n_orig; i++ ) + { + if( pnt[i] == NULL ) + { + continue; + } + + if( pnt[i]->name != NULL + && strcmp(pnt[i]->name, "") == 0 ) + { + ttbl_extent = isonum_733((unsigned char *) pnt[i]->isorec.extent); + ttbl_index = i; + continue; + } + /* + * Skip directories for now - these need to be treated + * differently. + */ + if( (pnt[i]->isorec.flags[0] & 2) != 0 ) + { + /* + * FIXME - we need to insert this directory into the + * tree, so that the path tables we generate will + * be correct. + */ + if( (strcmp(pnt[i]->name, ".") == 0) + || (strcmp(pnt[i]->name, "..") == 0) ) + { + free(pnt[i]); + pnt[i] = NULL; + continue; + } + else + { + merge_old_directory_into_tree(pnt[i], this_dir); + } + } + pnt[i]->next = this_dir->contents; + pnt[i]->filedir = this_dir; + this_dir->contents = pnt[i]; + pnt[i] = NULL; + } + + + /* + * If we don't have an entry for the translation table, then + * don't bother trying to copy the starting extent over. + * Note that it is possible that if we are copying the entire + * directory, the entry for the translation table will have already + * been inserted into the linked list and removed from the old + * entries list, in which case we want to leave the extent number + * as it was before. + */ + if( ttbl_extent == 0 ) + { + return; + } + + /* + * Finally, check the directory we are creating to see whether + * there are any new entries in it. If there are not, we can + * reuse the same translation table. + */ + for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) + { + /* + * Don't care about '.' or '..'. They are never in the table + * anyways. + */ + if( s_entry->name != NULL && strcmp(s_entry->name, ".") == 0 ) + { + continue; + } + if( s_entry->name != NULL && strcmp(s_entry->name, "..") == 0 ) + { + continue; + } + if( strcmp(s_entry->name, "") == 0) + { + continue; + } + if( (s_entry->de_flags & SAFE_TO_REUSE_TABLE_ENTRY) == 0 ) + { + return; + } + } + + /* + * Locate the translation table, and re-use the same extent. + * It isn't clear that there should ever be one in there already + * so for now we try and muddle through the best we can. + */ + for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) + { + if( strcmp(s_entry->name, "") == 0) + { + fprintf(stderr,"Should never get here\n"); + set_733(s_entry->isorec.extent, ttbl_extent); + return; + } + } + + pnt[ttbl_index]->next = this_dir->contents; + pnt[ttbl_index]->filedir = this_dir; + this_dir->contents = pnt[ttbl_index]; + pnt[ttbl_index] = NULL; +} + + +/* + * Here we have a case of a directory that has completely disappeared from + * the face of the earth on the tree we are mastering from. Go through and + * merge it into the tree, as well as everything beneath it. + * + * Note that if a directory has been moved for some reason, this will + * incorrectly pick it up and attempt to merge it back into the old + * location. FIXME(eric). + */ +static int +FDECL2(merge_old_directory_into_tree, struct directory_entry *, dpnt, + struct directory *, parent) +{ + struct directory_entry **contents = NULL; + int i; + int n_orig; + struct directory * this_dir, *next_brother; + char whole_path[1024]; + + this_dir = (struct directory *) e_malloc(sizeof(struct directory)); + this_dir->next = NULL; + this_dir->subdir = NULL; + this_dir->self = dpnt; + this_dir->contents = NULL; + this_dir->size = 0; + this_dir->extent = 0; + this_dir->depth = parent->depth + 1; + this_dir->parent = parent; + if(!parent->subdir) + parent->subdir = this_dir; + else { + next_brother = parent->subdir; + while(next_brother->next) next_brother = next_brother->next; + next_brother->next = this_dir; + } + + /* + * Set the name for this directory. + */ + strcpy(whole_path, parent->de_name); + strcat(whole_path, SPATH_SEPARATOR); + strcat(whole_path, dpnt->name); + this_dir->de_name = strdup(whole_path); + this_dir->whole_name = strdup(whole_path); + + /* + * Now fill this directory using information from the previous + * session. + */ + contents = read_merging_directory(&dpnt->isorec, &n_orig); + /* + * Start by simply copying the '.', '..' and non-directory + * entries to this directory. Technically we could let + * merge_remaining_entries handle this, but it gets rather confused + * by the '.' and '..' entries. + */ + for(i=0; i < n_orig; i ++ ) + { + /* + * We can always reuse the TRANS.TBL in this particular case. + */ + contents[i]->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY; + + if( ((contents[i]->isorec.flags[0] & 2) != 0) + && (i >= 2) ) + { + continue; + } + + /* + * If we have a directory, don't reuse the extent number. + */ + if( (contents[i]->isorec.flags[0] & 2) != 0 ) + { + memset(contents[i]->isorec.extent, 0, 8); + } + + contents[i]->next = this_dir->contents; + contents[i]->filedir = this_dir; + this_dir->contents = contents[i]; + contents[i] = NULL; + } + + /* + * Zero the extent number for ourselves. + */ + memset(dpnt->isorec.extent, 0, 8); + + /* + * Anything that is left are other subdirectories that need to be merged. + */ + merge_remaining_entries(this_dir, contents, n_orig); + free_mdinfo(contents, n_orig); + sort_n_finish(this_dir); + + return 0; +} + + +char * cdwrite_data = NULL; + +static int +FDECL1(get_session_start, int *, file_addr) +{ + char * pnt; + +#ifdef CDWRITE_DETERMINES_FIRST_WRITABLE_ADDRESS + /* + * FIXME(eric). We need to coordinate with cdwrite to obtain + * the parameters. For now, we assume we are writing the 2nd session, + * so we start from the session that starts at 0. + */ + + *file_addr = (16 << 11); + + /* + * We need to coordinate with cdwrite to get the next writable address + * from the device. Here is where we use it. + */ + session_start = last_extent = last_extent_written = cdwrite_result(); + +#else + + if( cdwrite_data == NULL ) + { + fprintf(stderr,"Special parameters for cdwrite not specified with -C\n"); + exit(1); + } + + /* + * Next try and find the ',' in there which delimits the two numbers. + */ + pnt = strchr(cdwrite_data, ','); + if( pnt == NULL ) + { + fprintf(stderr, "Malformed cdwrite parameters\n"); + exit(1); + } + + *pnt = '\0'; + *file_addr = atol(cdwrite_data) * SECTOR_SIZE; + pnt++; + + session_start = last_extent = last_extent_written = atol(pnt); + + pnt--; + *pnt = ','; + +#endif + return 0; +} + diff --git a/util/mkisofs/name.c b/util/mkisofs/name.c new file mode 100644 index 000000000..10475d43e --- /dev/null +++ b/util/mkisofs/name.c @@ -0,0 +1,390 @@ +/* + * File name.c - map full Unix file names to unique 8.3 names that + * would be valid on DOS. + * + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +static char rcsid[] ="$Id: name.c,v 1.7 1997/11/09 16:42:51 eric Exp $"; + +#include "mkisofs.h" + +#include + +extern int allow_leading_dots; + +/* + * Function: iso9660_file_length + * + * Purpose: Map file name to 8.3 format, return length + * of result. + * + * Arguments: name file name we need to map. + * sresult directory entry structure to contain mapped name. + * dirflag flag indicating whether this is a directory or not. + * + * Notes: This procedure probably needs to be rationalized somehow. + * New options to affect the behavior of this function + * would also be nice to have. + */ +int FDECL3(iso9660_file_length, + const char*, name, + struct directory_entry *, sresult, + int, dirflag) +{ + char * c; + int chars_after_dot = 0; + int chars_before_dot = 0; + int current_length = 0; + int extra = 0; + int ignore = 0; + char * last_dot; + const char * pnt; + int priority = 32767; + char * result; + int seen_dot = 0; + int seen_semic = 0; + int tildes = 0; + + result = sresult->isorec.name; + + /* + * For the '.' entry, generate the correct record, and return + * 1 for the length. + */ + if(strcmp(name,".") == 0) + { + if(result) + { + *result = 0; + } + return 1; + } + + /* + * For the '..' entry, generate the correct record, and return + * 1 for the length. + */ + if(strcmp(name,"..") == 0) + { + if(result) + { + *result++ = 1; + *result++ = 0; + } + return 1; + } + + /* + * Now scan the directory one character at a time, and figure out + * what to do. + */ + pnt = name; + + /* + * Find the '.' that we intend to use for the extension. Usually this + * is the last dot, but if we have . followed by nothing or a ~, we + * would consider this to be unsatisfactory, and we keep searching. + */ + last_dot = strrchr (pnt,'.'); + if( (last_dot != NULL) + && ( (last_dot[1] == '~') + || (last_dot[1] == '\0') + || (last_dot[1] == '\0')) ) + { + c = last_dot; + *c = '\0'; + last_dot = strrchr (pnt,'.'); + *c = '.'; + } + + while(*pnt) + { +#ifdef VMS + if( strcmp(pnt,".DIR;1") == 0 ) + { + break; + } +#endif + + /* + * This character indicates a Unix style of backup file + * generated by some editors. Lower the priority of + * the file. + */ + if(*pnt == '#') + { + priority = 1; + pnt++; + continue; + } + + /* + * This character indicates a Unix style of backup file + * generated by some editors. Lower the priority of + * the file. + */ + if(*pnt == '~') + { + priority = 1; + tildes++; + pnt++; + continue; + } + + /* + * This might come up if we had some joker already try and put + * iso9660 version numbers into the file names. This would be + * a silly thing to do on a Unix box, but we check for it + * anyways. If we see this, then we don't have to add our + * own version number at the end. + */ + if(*pnt == ';') + { + seen_semic = 1; + *result++ = *pnt++; + continue; + } + + /* + * If we have a name with multiple '.' characters, we ignore everything + * after we have gotten the extension. + */ + if(ignore) + { + pnt++; + continue; + } + + /* + * Spin past any iso9660 version number we might have. + */ + if(seen_semic) + { + if(*pnt >= '0' && *pnt <= '9') + { + *result++ = *pnt; + } + extra++; + pnt++; + continue; + } + + /* + * If we have full names, the names we generate will not + * work on a DOS machine, since they are not guaranteed + * to be 8.3. Nonetheless, in many cases this is a useful + * option. We still only allow one '.' character in the + * name, however. + */ + if(full_iso9660_filenames) + { + /* Here we allow a more relaxed syntax. */ + if(*pnt == '.') + { + if (seen_dot) + { + ignore++; + continue; + } + seen_dot++; + } + if(current_length < 30) + { + if( *pnt < 0 ) + { + *result++ = '_'; + } + else + { + *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt); + } + } + } + else + { + /* + * Dos style filenames. We really restrict the + * names here. + */ + /* It would be nice to have .tar.gz transform to .tgz, + * .ps.gz to .psz, ... + */ + if(*pnt == '.') + { + if (!chars_before_dot && !allow_leading_dots) + { + /* DOS can't read files with dot first */ + chars_before_dot++; + if (result) + { + *result++ = '_'; /* Substitute underscore */ + } + } + else if( pnt != last_dot ) + { + /* + * If this isn't the dot that we use for the extension, + * then change the character into a '_' instead. + */ + if(chars_before_dot < 8) + { + chars_before_dot++; + if(result) + { + *result++ = '_'; + } + } + } + else + { + if (seen_dot) + { + ignore++; continue; + } + if(result) + { + *result++ = '.'; + } + seen_dot++; + } + } + else + { + if( (seen_dot && (chars_after_dot < 3) && ++chars_after_dot) + || (!seen_dot && (chars_before_dot < 8) && ++chars_before_dot) ) + { + if(result) + { + switch (*pnt) + { + default: + if( *pnt < 0 ) + { + *result++ = '_'; + } + else + { + *result++ = islower(*pnt) ? toupper(*pnt) : *pnt; + } + break; + + /* + * Descriptions of DOS's 'Parse Filename' + * (function 29H) describes V1 and V2.0+ + * separator and terminator characters. + * These characters in a DOS name make + * the file visible but un-manipulable + * (all useful operations error off. + */ + /* separators */ + case '+': + case '=': + case '%': /* not legal DOS filename */ + case ':': + case ';': /* already handled */ + case '.': /* already handled */ + case ',': /* already handled */ + case '\t': + case ' ': + /* V1 only separators */ + case '/': + case '"': + case '[': + case ']': + /* terminators */ + case '>': + case '<': + case '|': + /* Hmm - what to do here? Skip? + * Win95 looks like it substitutes '_' + */ + *result++ = '_'; + break; + } /* switch (*pnt) */ + } /* if (result) */ + } /* if (chars_{after,before}_dot) ... */ + } /* else *pnt == '.' */ + } /* else DOS file names */ + current_length++; + pnt++; + } /* while (*pnt) */ + + /* + * OK, that wraps up the scan of the name. Now tidy up a few other + * things. + */ + + /* + * Look for emacs style of numbered backups, like foo.c.~3~. If + * we see this, convert the version number into the priority + * number. In case of name conflicts, this is what would end + * up being used as the 'extension'. + */ + if(tildes == 2) + { + int prio1 = 0; + pnt = name; + while (*pnt && *pnt != '~') + { + pnt++; + } + if (*pnt) + { + pnt++; + } + while(*pnt && *pnt != '~') + { + prio1 = 10*prio1 + *pnt - '0'; + pnt++; + } + priority = prio1; + } + + /* + * If this is not a directory, force a '.' in case we haven't + * seen one, and add a version number if we haven't seen one + * of those either. + */ + if (!dirflag) + { + if (!seen_dot && !omit_period) + { + if (result) *result++ = '.'; + extra++; + } + if(!omit_version_number && !seen_semic) + { + if(result) + { + *result++ = ';'; + *result++ = '1'; + }; + extra += 2; + } + } + + if(result) + { + *result++ = 0; + } + sresult->priority = priority; + + return (chars_before_dot + chars_after_dot + seen_dot + extra); +} diff --git a/util/mkisofs/rock.c b/util/mkisofs/rock.c new file mode 100644 index 000000000..47cba5527 --- /dev/null +++ b/util/mkisofs/rock.c @@ -0,0 +1,556 @@ +/* + * File rock.c - generate RRIP records for iso9660 filesystems. + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +static char rcsid[] ="$Id: rock.c,v 1.3 1997/05/17 15:45:26 eric Exp $"; + +#include + +#include "config.h" + +#ifndef VMS +#if defined(MAJOR_IN_SYSMACROS) +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#endif +#if defined(MAJOR_IN_MKDEV) +#include +#include +#endif + +#include "mkisofs.h" +#include "iso9660.h" +#include + +#ifdef NON_UNIXFS +#define S_ISLNK(m) (0) +#else +#ifndef S_ISLNK +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#endif +#endif + +#define SU_VERSION 1 + +#define SL_ROOT 8 +#define SL_PARENT 4 +#define SL_CURRENT 2 +#define SL_CONTINUE 1 + +#define CE_SIZE 28 +#define CL_SIZE 12 +#define ER_SIZE 8 +#define NM_SIZE 5 +#define PL_SIZE 12 +#define PN_SIZE 20 +#define PX_SIZE 36 +#define RE_SIZE 4 +#define SL_SIZE 20 +#define ZZ_SIZE 15 +#ifdef __QNX__ +#define TF_SIZE (5 + 4 * 7) +#else +#define TF_SIZE (5 + 3 * 7) +#endif + +/* If we need to store this number of bytes, make sure we + do not box ourselves in so that we do not have room for + a CE entry for the continuation record */ + +#define MAYBE_ADD_CE_ENTRY(BYTES) \ + (BYTES + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0) + +/* + * Buffer to build RR attributes + */ + +static unsigned char Rock[16384]; +static unsigned char symlink_buff[256]; +static int ipnt = 0; +static int recstart = 0; +static int currlen = 0; +static int mainrec = 0; +static int reclimit; + +static void add_CE_entry(){ + if(recstart) + set_733((char*)Rock + recstart - 8, ipnt + 28 - recstart); + Rock[ipnt++] ='C'; + Rock[ipnt++] ='E'; + Rock[ipnt++] = CE_SIZE; + Rock[ipnt++] = SU_VERSION; + set_733((char*)Rock + ipnt, 0); + ipnt += 8; + set_733((char*)Rock + ipnt, 0); + ipnt += 8; + set_733((char*)Rock + ipnt, 0); + ipnt += 8; + recstart = ipnt; + currlen = 0; + if(!mainrec) mainrec = ipnt; + reclimit = SECTOR_SIZE - 8; /* Limit to one sector */ +} + +#ifdef __STDC__ +int generate_rock_ridge_attributes (char * whole_name, char * name, + struct directory_entry * s_entry, + struct stat * statbuf, + struct stat * lstatbuf, + int deep_opt) +#else +int generate_rock_ridge_attributes (whole_name, name, + s_entry, + statbuf, + lstatbuf, + deep_opt) +char * whole_name; char * name; struct directory_entry * s_entry; +struct stat * statbuf, *lstatbuf; +int deep_opt; +#endif +{ + int flagpos, flagval; + int need_ce; + + statbuf = statbuf; /* this shuts up unreferenced compiler warnings */ + mainrec = recstart = ipnt = 0; + reclimit = 0xf8; + + /* Obtain the amount of space that is currently used for the directory + record. Assume max for name, since name conflicts may cause us + to rename the file later on */ + currlen = sizeof(s_entry->isorec); + + /* Identify that we are using the SUSP protocol */ + if(deep_opt & NEED_SP){ + Rock[ipnt++] ='S'; + Rock[ipnt++] ='P'; + Rock[ipnt++] = 7; + Rock[ipnt++] = SU_VERSION; + Rock[ipnt++] = 0xbe; + Rock[ipnt++] = 0xef; + Rock[ipnt++] = 0; + }; + + /* First build the posix name field */ + Rock[ipnt++] ='R'; + Rock[ipnt++] ='R'; + Rock[ipnt++] = 5; + Rock[ipnt++] = SU_VERSION; + flagpos = ipnt; + flagval = 0; + Rock[ipnt++] = 0; /* We go back and fix this later */ + + if(strcmp(name,".") && strcmp(name,"..")){ + char * npnt; + int remain, use; + + remain = strlen(name); + npnt = name; + + while(remain){ + use = remain; + need_ce = 0; + /* Can we fit this SUSP and a CE entry? */ + if(use + currlen + CE_SIZE + (ipnt - recstart) > reclimit) { + use = reclimit - currlen - CE_SIZE - (ipnt - recstart); + need_ce++; + } + + /* Only room for 256 per SUSP field */ + if(use > 0xf8) use = 0xf8; + + /* First build the posix name field */ + Rock[ipnt++] ='N'; + Rock[ipnt++] ='M'; + Rock[ipnt++] = NM_SIZE + use; + Rock[ipnt++] = SU_VERSION; + Rock[ipnt++] = (remain != use ? 1 : 0); + flagval |= (1<<3); + strncpy((char *)&Rock[ipnt], npnt, use); + npnt += use; + ipnt += use; + remain -= use; + if(remain && need_ce) add_CE_entry(); + }; + }; + + /* + * Add the posix modes + */ + if(MAYBE_ADD_CE_ENTRY(PX_SIZE)) add_CE_entry(); + Rock[ipnt++] ='P'; + Rock[ipnt++] ='X'; + Rock[ipnt++] = PX_SIZE; + Rock[ipnt++] = SU_VERSION; + flagval |= (1<<0); + set_733((char*)Rock + ipnt, lstatbuf->st_mode); + ipnt += 8; + set_733((char*)Rock + ipnt, lstatbuf->st_nlink); + ipnt += 8; + set_733((char*)Rock + ipnt, lstatbuf->st_uid); + ipnt += 8; + set_733((char*)Rock + ipnt, lstatbuf->st_gid); + ipnt += 8; + + /* + * Check for special devices + */ +#ifndef NON_UNIXFS + if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) { + if(MAYBE_ADD_CE_ENTRY(PN_SIZE)) add_CE_entry(); + Rock[ipnt++] ='P'; + Rock[ipnt++] ='N'; + Rock[ipnt++] = PN_SIZE; + Rock[ipnt++] = SU_VERSION; + flagval |= (1<<1); +#if !defined(MAJOR_IN_SYSMACROS) && !defined(MAJOR_IN_MKDEV) + set_733((char*)Rock + ipnt, major(lstatbuf->st_rdev )); + ipnt += 8; + set_733((char*)Rock + ipnt, minor(lstatbuf->st_rdev)); + ipnt += 8; +#else + /* + * If we don't have sysmacros.h, then we have to guess as to how + * best to pick apart the device number for major/minor. + * Note: this may very well be wrong for many systems, so + * it is always best to use the major/minor macros if the + * system supports it. + */ + if(sizeof(dev_t) <= 2) { + set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8)); + ipnt += 8; + set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xff); + ipnt += 8; + } + else if(sizeof(dev_t) <= 4) { + set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8) >> 8); + ipnt += 8; + set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xffff); + ipnt += 8; + } + else { + set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 16) >> 16); + ipnt += 8; + set_733((char*)Rock + ipnt, lstatbuf->st_rdev); + ipnt += 8; + } +#endif + }; +#endif + /* + * Check for and symbolic links. VMS does not have these. + */ + if (S_ISLNK(lstatbuf->st_mode)){ + int lenpos, lenval, j0, j1; + int nchar; + unsigned char * cpnt, *cpnt1; + nchar = readlink(whole_name, symlink_buff, sizeof(symlink_buff)); + symlink_buff[nchar < 0 ? 0 : nchar] = 0; + set_733(s_entry->isorec.size, 0); + cpnt = &symlink_buff[0]; + flagval |= (1<<2); + + while(nchar){ + if(MAYBE_ADD_CE_ENTRY(SL_SIZE)) add_CE_entry(); + Rock[ipnt++] ='S'; + Rock[ipnt++] ='L'; + lenpos = ipnt; + Rock[ipnt++] = SL_SIZE; + Rock[ipnt++] = SU_VERSION; + Rock[ipnt++] = 0; /* Flags */ + lenval = 5; + while(*cpnt){ + cpnt1 = (unsigned char *) strchr((char *) cpnt, '/'); + if(cpnt1) { + nchar--; + *cpnt1 = 0; + }; + + /* We treat certain components in a special way. */ + if(cpnt[0] == '.' && cpnt[1] == '.' && cpnt[2] == 0){ + if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry(); + Rock[ipnt++] = SL_PARENT; + Rock[ipnt++] = 0; /* length is zero */ + lenval += 2; + nchar -= 2; + } else if(cpnt[0] == '.' && cpnt[1] == 0){ + if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry(); + Rock[ipnt++] = SL_CURRENT; + Rock[ipnt++] = 0; /* length is zero */ + lenval += 2; + nchar -= 1; + } else if(cpnt[0] == 0){ + if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry(); + Rock[ipnt++] = SL_ROOT; + Rock[ipnt++] = 0; /* length is zero */ + lenval += 2; + } else { + /* If we do not have enough room for a component, start + a new continuations segment now */ + if(MAYBE_ADD_CE_ENTRY(6)) { + add_CE_entry(); + if(cpnt1){ + *cpnt1 = '/'; + nchar++; + cpnt1 = NULL; /* A kluge so that we can restart properly */ + } + break; + } + j0 = strlen((char *) cpnt); + while(j0) { + j1 = j0; + if(j1 > 0xf8) j1 = 0xf8; + need_ce = 0; + if(j1 + currlen + CE_SIZE + (ipnt - recstart) > reclimit) { + j1 = reclimit - currlen - CE_SIZE - (ipnt - recstart); + need_ce++; + } + Rock[ipnt++] = (j1 != j0 ? SL_CONTINUE : 0); + Rock[ipnt++] = j1; + strncpy((char *) Rock + ipnt, (char *) cpnt, j1); + ipnt += j1; + lenval += j1 + 2; + cpnt += j1; + nchar -= j1; /* Number we processed this time */ + j0 -= j1; + if(need_ce) { + add_CE_entry(); + if(cpnt1) { + *cpnt1 = '/'; + nchar++; + cpnt1 = NULL; /* A kluge so that we can restart properly */ + } + break; + } + } + }; + if(cpnt1) { + cpnt = cpnt1 + 1; + } else + break; + } + Rock[lenpos] = lenval; + if(nchar) Rock[lenpos + 2] = SL_CONTINUE; /* We need another SL entry */ + } /* while nchar */ + } /* Is a symbolic link */ + /* + * Add in the Rock Ridge TF time field + */ + if(MAYBE_ADD_CE_ENTRY(TF_SIZE)) add_CE_entry(); + Rock[ipnt++] ='T'; + Rock[ipnt++] ='F'; + Rock[ipnt++] = TF_SIZE; + Rock[ipnt++] = SU_VERSION; +#ifdef __QNX__ + Rock[ipnt++] = 0x0f; +#else + Rock[ipnt++] = 0x0e; +#endif + flagval |= (1<<7); +#ifdef __QNX__ + iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime); + ipnt += 7; +#endif + iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime); + ipnt += 7; + iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime); + ipnt += 7; + iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime); + ipnt += 7; + + /* + * Add in the Rock Ridge RE time field + */ + if(deep_opt & NEED_RE){ + if(MAYBE_ADD_CE_ENTRY(RE_SIZE)) add_CE_entry(); + Rock[ipnt++] ='R'; + Rock[ipnt++] ='E'; + Rock[ipnt++] = RE_SIZE; + Rock[ipnt++] = SU_VERSION; + flagval |= (1<<6); + }; + /* + * Add in the Rock Ridge PL record, if required. + */ + if(deep_opt & NEED_PL){ + if(MAYBE_ADD_CE_ENTRY(PL_SIZE)) add_CE_entry(); + Rock[ipnt++] ='P'; + Rock[ipnt++] ='L'; + Rock[ipnt++] = PL_SIZE; + Rock[ipnt++] = SU_VERSION; + set_733((char*)Rock + ipnt, 0); + ipnt += 8; + flagval |= (1<<5); + }; + + /* + * Add in the Rock Ridge CL field, if required. + */ + if(deep_opt & NEED_CL){ + if(MAYBE_ADD_CE_ENTRY(CL_SIZE)) add_CE_entry(); + Rock[ipnt++] ='C'; + Rock[ipnt++] ='L'; + Rock[ipnt++] = CL_SIZE; + Rock[ipnt++] = SU_VERSION; + set_733((char*)Rock + ipnt, 0); + ipnt += 8; + flagval |= (1<<4); + }; + +#ifndef VMS + /* If transparent compression was requested, fill in the correct + field for this file */ + if(transparent_compression && + S_ISREG(lstatbuf->st_mode) && + strlen(name) > 3 && + strcmp(name + strlen(name) - 3,".gZ") == 0){ + FILE * zipfile; + char * checkname; + unsigned int file_size; + unsigned char header[8]; + int OK_flag; + + /* First open file and verify that the correct algorithm was used */ + file_size = 0; + OK_flag = 1; + + zipfile = fopen(whole_name, "r"); + fread(header, 1, sizeof(header), zipfile); + + /* Check some magic numbers from gzip. */ + if(header[0] != 0x1f || header[1] != 0x8b || header[2] != 8) OK_flag = 0; + /* Make sure file was blocksized. */ + if(((header[3] & 0x40) == 0)) OK_flag = 0; + /* OK, now go to the end of the file and get some more info */ + if(OK_flag){ + int status; + status = (long)lseek(fileno(zipfile), (off_t)(-8), SEEK_END); + if(status == -1) OK_flag = 0; + } + if(OK_flag){ + if(read(fileno(zipfile), (char*)header, sizeof(header)) != sizeof(header)) + OK_flag = 0; + else { + int blocksize; + blocksize = (header[3] << 8) | header[2]; + file_size = ((unsigned int)header[7] << 24) | + ((unsigned int)header[6] << 16) | + ((unsigned int)header[5] << 8) | header[4]; +#if 0 + fprintf(stderr,"Blocksize = %d %d\n", blocksize, file_size); +#endif + if(blocksize != SECTOR_SIZE) OK_flag = 0; + } + } + fclose(zipfile); + + checkname = strdup(whole_name); + checkname[strlen(whole_name)-3] = 0; + zipfile = fopen(checkname, "r"); + if(zipfile) { + OK_flag = 0; + fprintf(stderr,"Unable to insert transparent compressed file - name conflict\n"); + fclose(zipfile); + } + + free(checkname); + + if(OK_flag){ + if(MAYBE_ADD_CE_ENTRY(ZZ_SIZE)) add_CE_entry(); + Rock[ipnt++] ='Z'; + Rock[ipnt++] ='Z'; + Rock[ipnt++] = ZZ_SIZE; + Rock[ipnt++] = SU_VERSION; + Rock[ipnt++] = 'g'; /* Identify compression technique used */ + Rock[ipnt++] = 'z'; + Rock[ipnt++] = 3; + set_733((char*)Rock + ipnt, file_size); /* Real file size */ + ipnt += 8; + }; + } +#endif + /* + * Add in the Rock Ridge CE field, if required. We use this for the + * extension record that is stored in the root directory. + */ + if(deep_opt & NEED_CE) add_CE_entry(); + /* + * Done filling in all of the fields. Now copy it back to a buffer for the + * file in question. + */ + + /* Now copy this back to the buffer for the file */ + Rock[flagpos] = flagval; + + /* If there was a CE, fill in the size field */ + if(recstart) + set_733((char*)Rock + recstart - 8, ipnt - recstart); + + s_entry->rr_attributes = (unsigned char *) e_malloc(ipnt); + s_entry->total_rr_attr_size = ipnt; + s_entry->rr_attr_size = (mainrec ? mainrec : ipnt); + memcpy(s_entry->rr_attributes, Rock, ipnt); + return ipnt; +} + +/* Guaranteed to return a single sector with the relevant info */ + +char * FDECL4(generate_rr_extension_record, char *, id, char *, descriptor, + char *, source, int *, size){ + int ipnt = 0; + char * pnt; + int len_id, len_des, len_src; + + len_id = strlen(id); + len_des = strlen(descriptor); + len_src = strlen(source); + Rock[ipnt++] ='E'; + Rock[ipnt++] ='R'; + Rock[ipnt++] = ER_SIZE + len_id + len_des + len_src; + Rock[ipnt++] = 1; + Rock[ipnt++] = len_id; + Rock[ipnt++] = len_des; + Rock[ipnt++] = len_src; + Rock[ipnt++] = 1; + + memcpy(Rock + ipnt, id, len_id); + ipnt += len_id; + + memcpy(Rock + ipnt, descriptor, len_des); + ipnt += len_des; + + memcpy(Rock + ipnt, source, len_src); + ipnt += len_src; + + if(ipnt > SECTOR_SIZE) { + fprintf(stderr,"Extension record too long\n"); + exit(1); + }; + pnt = (char *) e_malloc(SECTOR_SIZE); + memset(pnt, 0, SECTOR_SIZE); + memcpy(pnt, Rock, ipnt); + *size = ipnt; + return pnt; +} diff --git a/util/mkisofs/tree.c b/util/mkisofs/tree.c new file mode 100644 index 000000000..7180905df --- /dev/null +++ b/util/mkisofs/tree.c @@ -0,0 +1,1292 @@ +/* + * File tree.c - scan directory tree and build memory structures for iso9660 + * filesystem + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +static char rcsid[] ="$Id: tree.c,v 1.9.1.2 1998/06/02 03:17:31 eric Exp $"; + +/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ + +#include +#include +#include +#include + +#include "config.h" + +#ifndef VMS +#if defined(MAJOR_IN_SYSMACROS) +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#if defined(MAJOR_IN_MKDEV) +#include +#include +#endif +#else +#include +#include +#include "vms.h" +extern char * strdup(const char *); +#endif + +/* + * Autoconf should be able to figure this one out for us and let us know + * whether the system has memmove or not. + */ +# ifndef HAVE_MEMMOVE +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif + +#include "mkisofs.h" +#include "iso9660.h" + +#include + +#include "exclude.h" + +#ifdef NON_UNIXFS +#define S_ISLNK(m) (0) +#define S_ISSOCK(m) (0) +#define S_ISFIFO(m) (0) +#else +#ifndef S_ISLNK +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#endif +#ifndef S_ISSOCK +# ifdef S_IFSOCK +# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +# else +# define S_ISSOCK(m) (0) +# endif +#endif +#endif + +#ifdef __svr4__ +extern char * strdup(const char *); +#endif + +static unsigned char symlink_buff[256]; + +extern int verbose; + +struct stat fstatbuf = {0,}; /* We use this for the artificial entries we create */ + +struct stat root_statbuf = {0, }; /* Stat buffer for root directory */ + +struct directory * reloc_dir = NULL; + +void +FDECL1(stat_fix, struct stat *, st) +{ + /* Remove the uid and gid, they will only be useful on the author's + system. */ + st->st_uid = 0; + st->st_gid = 0; + + /* + * Make sure the file modes make sense. Turn on all read bits. Turn + * on all exec/search bits if any exec/search bit is set. Turn off + * all write bits, and all special mode bits (on a r/o fs lock bits + * are useless, and with uid+gid 0 don't want set-id bits, either). + */ + st->st_mode |= 0444; + if (st->st_mode & 0111) + st->st_mode |= 0111; + st->st_mode &= ~07222; +} + +int +FDECL2(stat_filter, char *, path, struct stat *, st) +{ + int result = stat(path, st); + if (result >= 0 && rationalize) + stat_fix(st); + return result; +} + +int +FDECL2(lstat_filter, char *, path, struct stat *, st) +{ + int result = lstat(path, st); + if (result >= 0 && rationalize) + stat_fix(st); + return result; +} + +void FDECL1(sort_n_finish, struct directory *, this_dir) +{ + struct directory_entry * s_entry; + struct directory_entry * s_entry1; + time_t current_time; + struct directory_entry * table; + int count; + int d1; + int d2; + int d3; + int new_reclen; + char * c; + int tablesize = 0; + char newname[34]; + char rootname[34]; + + /* Here we can take the opportunity to toss duplicate entries from the + directory. */ + + table = NULL; + + if(fstatbuf.st_ctime == 0) + { + time (¤t_time); + fstatbuf.st_uid = 0; + fstatbuf.st_gid = 0; + fstatbuf.st_ctime = current_time; + fstatbuf.st_mtime = current_time; + fstatbuf.st_atime = current_time; + } + + flush_file_hash(); + s_entry = this_dir->contents; + while(s_entry) + { + + /* + * First assume no conflict, and handle this case + */ + if(!(s_entry1 = find_file_hash(s_entry->isorec.name))) + { + add_file_hash(s_entry); + s_entry = s_entry->next; + continue; + } + + if(s_entry1 == s_entry) + { + fprintf(stderr,"Fatal goof\n"); + exit(1); + } + + /* + * OK, handle the conflicts. Try substitute names until we come + * up with a winner + */ + strcpy(rootname, s_entry->isorec.name); + if(full_iso9660_filenames) + { + if(strlen(rootname) > 27) rootname[27] = 0; + } + + /* + * Strip off the non-significant part of the name so that we are left + * with a sensible root filename. If we don't find a '.', then try + * a ';'. + */ + c = strchr(rootname, '.'); + if (c) + *c = 0; + else + { + c = strchr(rootname, ';'); + if (c) *c = 0; + } + for(d1 = 0; d1 < 36; d1++) + { + for(d2 = 0; d2 < 36; d2++) + { + for(d3 = 0; d3 < 36; d3++) + { + sprintf(newname,"%s.%c%c%c%s", rootname, + (d1 <= 9 ? '0' + d1 : 'A' + d1 - 10), + (d2 <= 9 ? '0' + d2 : 'A' + d2 - 10), + (d3 <= 9 ? '0' + d3 : 'A' + d3 - 10), + (s_entry->isorec.flags[0] == 2 || + omit_version_number ? "" : ";1")); + +#ifdef VMS + /* Sigh. VAXCRTL seems to be broken here */ + { + int ijk = 0; + while(newname[ijk]) + { + if(newname[ijk] == ' ') newname[ijk] = '0'; + ijk++; + } + } +#endif + + if(!find_file_hash(newname)) goto got_valid_name; + } + } + } + + /* + * If we fell off the bottom here, we were in real trouble. + */ + fprintf(stderr,"Unable to generate unique name for file %s\n", s_entry->name); + exit(1); + +got_valid_name: + /* + * OK, now we have a good replacement name. Now decide which one + * of these two beasts should get the name changed + */ + if(s_entry->priority < s_entry1->priority) + { + fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, this_dir->whole_name, SPATH_SEPARATOR, s_entry->name, s_entry1->name); + s_entry->isorec.name_len[0] = strlen(newname); + new_reclen = sizeof(struct iso_directory_record) - + sizeof(s_entry->isorec.name) + + strlen(newname); + if(use_RockRidge) + { + if (new_reclen & 1) new_reclen++; /* Pad to an even byte */ + new_reclen += s_entry->rr_attr_size; + } + if (new_reclen & 1) new_reclen++; /* Pad to an even byte */ + s_entry->isorec.length[0] = new_reclen; + strcpy(s_entry->isorec.name, newname); + } + else + { + delete_file_hash(s_entry1); + fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, this_dir->whole_name, SPATH_SEPARATOR, s_entry1->name, s_entry->name); + s_entry1->isorec.name_len[0] = strlen(newname); + new_reclen = sizeof(struct iso_directory_record) - + sizeof(s_entry1->isorec.name) + + strlen(newname); + if(use_RockRidge) + { + if (new_reclen & 1) new_reclen++; /* Pad to an even byte */ + new_reclen += s_entry1->rr_attr_size; + } + if (new_reclen & 1) new_reclen++; /* Pad to an even byte */ + s_entry1->isorec.length[0] = new_reclen; + strcpy(s_entry1->isorec.name, newname); + add_file_hash(s_entry1); + } + add_file_hash(s_entry); + s_entry = s_entry->next; + } + + if(generate_tables + && !find_file_hash("TRANS.TBL") + && (reloc_dir != this_dir) + && (this_dir->extent == 0) ) + { + /* + * First we need to figure out how big this table is + */ + for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) + { + if(strcmp(s_entry->name, ".") == 0 || + strcmp(s_entry->name, "..") == 0) continue; + if(s_entry->table) tablesize += 35 + strlen(s_entry->table); + } + } + + if( tablesize > 0 ) + { + table = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memset(table, 0, sizeof(struct directory_entry)); + table->table = NULL; + table->next = this_dir->contents; + this_dir->contents = table; + + table->filedir = root; + table->isorec.flags[0] = 0; + table->priority = 32768; + iso9660_date(table->isorec.date, fstatbuf.st_mtime); + table->inode = TABLE_INODE; + table->dev = (dev_t) UNCACHED_DEVICE; + set_723(table->isorec.volume_sequence_number, DEF_VSN); + set_733((char *) table->isorec.size, tablesize); + table->size = tablesize; + table->filedir = this_dir; + table->name = strdup(""); + table->table = (char *) e_malloc(ROUND_UP(tablesize)); + memset(table->table, 0, ROUND_UP(tablesize)); + iso9660_file_length ("TRANS.TBL", table, 0); + + if(use_RockRidge) + { + fstatbuf.st_mode = 0444 | S_IFREG; + fstatbuf.st_nlink = 1; + generate_rock_ridge_attributes("", + "TRANS.TBL", table, + &fstatbuf, &fstatbuf, 0); + } + } + + for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) + { + new_reclen = strlen(s_entry->isorec.name); + + if(s_entry->isorec.flags[0] == 2) + { + if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) + { + path_table_size += new_reclen + sizeof(struct iso_path_table) - 1; + if (new_reclen & 1) path_table_size++; + } + else + { + new_reclen = 1; + if (this_dir == root && strlen(s_entry->name) == 1) + path_table_size += sizeof(struct iso_path_table); + } + } + if(path_table_size & 1) path_table_size++; /* For odd lengths we pad */ + s_entry->isorec.name_len[0] = new_reclen; + + new_reclen += + sizeof(struct iso_directory_record) - + sizeof(s_entry->isorec.name); + + if (new_reclen & 1) + new_reclen++; + + new_reclen += s_entry->rr_attr_size; + + if (new_reclen & 1) new_reclen++; + + if(new_reclen > 0xff) + { + fprintf(stderr,"Fatal error - RR overflow for file %s\n", + s_entry->name); + exit(1); + } + s_entry->isorec.length[0] = new_reclen; + } + + sort_directory(&this_dir->contents); + + if(table) + { + count = 0; + for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){ + if(s_entry == table) continue; + if(!s_entry->table) continue; + if(strcmp(s_entry->name, ".") == 0 || + strcmp(s_entry->name, "..") == 0) continue; + + count += sprintf(table->table + count, "%c %-34s%s", + s_entry->table[0], + s_entry->isorec.name, s_entry->table+1); + free(s_entry->table); + s_entry->table = NULL; + } + + if(count != tablesize) + { + fprintf(stderr,"Translation table size mismatch %d %d\n", + count, tablesize); + exit(1); + } + } + + /* + * Now go through the directory and figure out how large this one will be. + * Do not split a directory entry across a sector boundary + */ + s_entry = this_dir->contents; + this_dir->ce_bytes = 0; + while(s_entry) + { + new_reclen = s_entry->isorec.length[0]; + if ((this_dir->size & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE) + this_dir->size = (this_dir->size + (SECTOR_SIZE - 1)) & + ~(SECTOR_SIZE - 1); + this_dir->size += new_reclen; + + /* See if continuation entries were used on disc */ + if(use_RockRidge && + s_entry->rr_attr_size != s_entry->total_rr_attr_size) + { + unsigned char * pnt; + int len; + int nbytes; + + pnt = s_entry->rr_attributes; + len = s_entry->total_rr_attr_size; + + /* + * We make sure that each continuation entry record is not + * split across sectors, but each file could in theory have more + * than one CE, so we scan through and figure out what we need. + */ + while(len > 3) + { + if(pnt[0] == 'C' && pnt[1] == 'E') + { + nbytes = get_733((char *) pnt+20); + + if((this_dir->ce_bytes & (SECTOR_SIZE - 1)) + nbytes >= + SECTOR_SIZE) this_dir->ce_bytes = + ROUND_UP(this_dir->ce_bytes); + /* Now store the block in the ce buffer */ + this_dir->ce_bytes += nbytes; + if(this_dir->ce_bytes & 1) this_dir->ce_bytes++; + } + len -= pnt[2]; + pnt += pnt[2]; + } + } + s_entry = s_entry->next; + } +} + +static void generate_reloc_directory() +{ + int new_reclen; + time_t current_time; + struct directory_entry *s_entry; + + /* Create an entry for our internal tree */ + time (¤t_time); + reloc_dir = (struct directory *) + e_malloc(sizeof(struct directory)); + memset(reloc_dir, 0, sizeof(struct directory)); + reloc_dir->parent = root; + reloc_dir->next = root->subdir; + root->subdir = reloc_dir; + reloc_dir->depth = 1; + reloc_dir->whole_name = strdup("./rr_moved"); + reloc_dir->de_name = strdup("rr_moved"); + reloc_dir->extent = 0; + + new_reclen = strlen(reloc_dir->de_name); + + /* Now create an actual directory entry */ + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memset(s_entry, 0, sizeof(struct directory_entry)); + s_entry->next = root->contents; + reloc_dir->self = s_entry; + + root->contents = s_entry; + root->contents->name = strdup(reloc_dir->de_name); + root->contents->filedir = root; + root->contents->isorec.flags[0] = 2; + root->contents->priority = 32768; + iso9660_date(root->contents->isorec.date, current_time); + root->contents->inode = UNCACHED_INODE; + root->contents->dev = (dev_t) UNCACHED_DEVICE; + set_723(root->contents->isorec.volume_sequence_number, DEF_VSN); + iso9660_file_length (reloc_dir->de_name, root->contents, 1); + + if(use_RockRidge){ + fstatbuf.st_mode = 0555 | S_IFDIR; + fstatbuf.st_nlink = 2; + generate_rock_ridge_attributes("", + "rr_moved", s_entry, + &fstatbuf, &fstatbuf, 0); + }; + + /* Now create the . and .. entries in rr_moved */ + /* Now create an actual directory entry */ + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry, root->contents, + sizeof(struct directory_entry)); + s_entry->name = strdup("."); + iso9660_file_length (".", s_entry, 1); + + s_entry->filedir = reloc_dir; + reloc_dir->contents = s_entry; + + if(use_RockRidge){ + fstatbuf.st_mode = 0555 | S_IFDIR; + fstatbuf.st_nlink = 2; + generate_rock_ridge_attributes("", + ".", s_entry, + &fstatbuf, &fstatbuf, 0); + }; + + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry, root->contents, + sizeof(struct directory_entry)); + s_entry->name = strdup(".."); + iso9660_file_length ("..", s_entry, 1); + s_entry->filedir = root; + reloc_dir->contents->next = s_entry; + reloc_dir->contents->next->next = NULL; + if(use_RockRidge){ + fstatbuf.st_mode = 0555 | S_IFDIR; + fstatbuf.st_nlink = 2; + generate_rock_ridge_attributes("", + "..", s_entry, + &root_statbuf, &root_statbuf, 0); + }; +} + +static void FDECL1(increment_nlink, struct directory_entry *, s_entry){ + unsigned char * pnt; + int len, nlink; + + pnt = s_entry->rr_attributes; + len = s_entry->total_rr_attr_size; + while(len){ + if(pnt[0] == 'P' && pnt[1] == 'X') { + nlink = get_733((char *) pnt+12); + set_733((char *) pnt+12, nlink+1); + break; + }; + len -= pnt[2]; + pnt += pnt[2]; + }; +} + +void finish_cl_pl_entries(){ + struct directory_entry *s_entry, *s_entry1; + struct directory * d_entry; + + s_entry = reloc_dir->contents; + s_entry = s_entry->next->next; /* Skip past . and .. */ + for(; s_entry; s_entry = s_entry->next){ + d_entry = reloc_dir->subdir; + while(d_entry){ + if(d_entry->self == s_entry) break; + d_entry = d_entry->next; + }; + if(!d_entry){ + fprintf(stderr,"Unable to locate directory parent\n"); + exit(1); + }; + + /* First fix the PL pointer in the directory in the rr_reloc dir */ + s_entry1 = d_entry->contents->next; + set_733((char *) s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8, + s_entry->filedir->extent); + + /* Now fix the CL pointer */ + s_entry1 = s_entry->parent_rec; + + set_733((char *) s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8, + d_entry->extent); + + s_entry->filedir = reloc_dir; /* Now we can fix this */ + } + /* Next we need to modify the NLINK terms in the assorted root directory records + to account for the presence of the RR_MOVED directory */ + + increment_nlink(root->self); + increment_nlink(root->self->next); + d_entry = root->subdir; + while(d_entry){ + increment_nlink(d_entry->contents->next); + d_entry = d_entry->next; + }; +} + +/* + * This function scans the directory tree, looking for files, and it makes + * note of everything that is found. We also begin to construct the ISO9660 + * directory entries, so that we can determine how large each directory is. + */ + +int +FDECL3(scan_directory_tree,char *, path, struct directory_entry *, de, + struct iso_directory_record *, mrootp){ + DIR * current_dir; + char whole_path[1024]; + struct dirent * d_entry; + struct directory_entry * s_entry, *s_entry1; + struct directory * this_dir, *next_brother, *parent; + struct stat statbuf, lstatbuf; + int status, dflag; + int lstatus; + int n_orig; + struct directory_entry **orig_contents = NULL; + struct directory_entry * odpnt = NULL; + char * cpnt; + int new_reclen; + int deep_flag; + char * old_path; + + current_dir = opendir(path); + d_entry = NULL; + + /* Apparently NFS sometimes allows you to open the directory, but + then refuses to allow you to read the contents. Allow for this */ + + old_path = path; + + if(current_dir) d_entry = readdir_add_files(&path, old_path, current_dir); + + if(!current_dir || !d_entry) { + fprintf(stderr,"Unable to open directory %s\n", path); + de->isorec.flags[0] &= ~2; /* Mark as not a directory */ + if(current_dir) closedir(current_dir); + return 0; + }; + + parent = de->filedir; + /* Set up the struct for the current directory, and insert it into the + tree */ + +#ifdef VMS + vms_path_fixup(path); +#endif + + this_dir = (struct directory *) e_malloc(sizeof(struct directory)); + this_dir->next = NULL; + new_reclen = 0; + this_dir->subdir = NULL; + this_dir->self = de; + this_dir->contents = NULL; + this_dir->whole_name = strdup(path); + cpnt = strrchr(path, PATH_SEPARATOR); + if(cpnt) + cpnt++; + else + cpnt = path; + this_dir->de_name = strdup(cpnt); + this_dir->size = 0; + this_dir->extent = 0; + + if(!parent || parent == root){ + if (!root) { + root = this_dir; /* First time through for root directory only */ + root->depth = 0; + root->parent = root; + } else { + this_dir->depth = 1; + if(!root->subdir) + root->subdir = this_dir; + else { + next_brother = root->subdir; + while(next_brother->next) next_brother = next_brother->next; + next_brother->next = this_dir; + }; + this_dir->parent = parent; + }; + } else { + /* Come through here for normal traversal of tree */ +#ifdef DEBUG + fprintf(stderr,"%s(%d) ", path, this_dir->depth); +#endif + if(parent->depth > RR_relocation_depth) { + fprintf(stderr,"Directories too deep %s\n", path); + exit(1); + }; + + this_dir->parent = parent; + this_dir->depth = parent->depth + 1; + + if(!parent->subdir) + parent->subdir = this_dir; + else { + next_brother = parent->subdir; + while(next_brother->next) next_brother = next_brother->next; + next_brother->next = this_dir; + } + } + + /* + * Parse the same directory in the image that we are merging + * for multisession stuff. + */ + if( mrootp != NULL ) + { + orig_contents = read_merging_directory(mrootp, &n_orig); + } + +/* Now we scan the directory itself, and look at what is inside of it. */ + + dflag = 0; + while(1==1){ + + /* The first time through, skip this, since we already asked for + the first entry when we opened the directory. */ + if(dflag) d_entry = readdir_add_files(&path, old_path, current_dir); + dflag++; + + if(!d_entry) break; + + /* OK, got a valid entry */ + + /* If we do not want all files, then pitch the backups. */ + if(!all_files){ + if(strchr(d_entry->d_name,'~')) continue; + if(strchr(d_entry->d_name,'#')) continue; + }; + + if(strlen(path)+strlen(d_entry->d_name) + 2 > sizeof(whole_path)){ + fprintf(stderr, "Overflow of stat buffer\n"); + exit(1); + }; + + /* Generate the complete ASCII path for this file */ + strcpy(whole_path, path); +#ifndef VMS + if(whole_path[strlen(whole_path)-1] != '/') + strcat(whole_path, "/"); +#endif + strcat(whole_path, d_entry->d_name); + + /* Should we exclude this file? */ + if (is_excluded(whole_path)) { + if (verbose) { + fprintf(stderr, "Excluded: %s\n",whole_path); + } + continue; + } + /** Should we exclude this file ? */ + if (matches(d_entry->d_name)) { + if (verbose) { + fprintf(stderr, "Excluded by match: %s\n", whole_path); + } + continue; + } + + if( generate_tables + && strcmp(d_entry->d_name, "TRANS.TBL") == 0 ) + { + /* + * Ignore this entry. We are going to be generating new + * versions of these files, and we need to ignore any + * originals that we might have found. + */ + if (verbose) + { + fprintf(stderr, "Excluded: %s\n",whole_path); + } + continue; + } + +#if 0 + if (verbose) fprintf(stderr, "%s\n",whole_path); +#endif + status = stat_filter(whole_path, &statbuf); + + lstatus = lstat_filter(whole_path, &lstatbuf); + + if( (status == -1) && (lstatus == -1) ) + { + /* + * This means that the file doesn't exist, or isn't accessible. + * Sometimes this is because of NFS permissions problems + * or it could mean that the user has attempted to 'add' something + * with the -i option and the directory being added doesn't exist. + */ + fprintf(stderr, "Non-existant or inaccessible: %s\n",whole_path); + continue; + } + + if(this_dir == root && strcmp(d_entry->d_name, ".") == 0) + root_statbuf = statbuf; /* Save this for later on */ + + /* We do this to make sure that the root entries are consistent */ + if(this_dir == root && strcmp(d_entry->d_name, "..") == 0) { + statbuf = root_statbuf; + lstatbuf = root_statbuf; + }; + + if(S_ISLNK(lstatbuf.st_mode)){ + + /* Here we decide how to handle the symbolic links. Here + we handle the general case - if we are not following + links or there is an error, then we must change + something. If RR is in use, it is easy, we let RR + describe the file. If not, then we punt the file. */ + + if((status || !follow_links)){ + if(use_RockRidge){ + status = 0; + statbuf.st_size = 0; + STAT_INODE(statbuf) = UNCACHED_INODE; + statbuf.st_dev = (dev_t) UNCACHED_DEVICE; + statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG; + } else { + if(follow_links) fprintf(stderr, + "Unable to stat file %s - ignoring and continuing.\n", + whole_path); + else fprintf(stderr, + "Symlink %s ignored - continuing.\n", + whole_path); + continue; /* Non Rock Ridge discs - ignore all symlinks */ + }; + } + + /* Here we handle a different kind of case. Here we have + a symlink, but we want to follow symlinks. If we run + across a directory loop, then we need to pretend that + we are not following symlinks for this file. If this + is the first time we have seen this, then make this + seem as if there was no symlink there in the first + place */ + + if( follow_links + && S_ISDIR(statbuf.st_mode) ) + { + if( strcmp(d_entry->d_name, ".") + && strcmp(d_entry->d_name, "..") ) + { + if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) + { + if(!use_RockRidge) + { + fprintf(stderr, "Already cached directory seen (%s)\n", + whole_path); + continue; + } + statbuf.st_size = 0; + STAT_INODE(statbuf) = UNCACHED_INODE; + statbuf.st_dev = (dev_t) UNCACHED_DEVICE; + statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG; + } else { + lstatbuf = statbuf; + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + } + } + } + + /* + * For non-directories, we just copy the stat information over + * so we correctly include this file. + */ + if( follow_links + && !S_ISDIR(statbuf.st_mode) ) + { + lstatbuf = statbuf; + } + } + + /* + * Add directories to the cache so that we don't waste space even + * if we are supposed to be following symlinks. + */ + if( follow_links + && strcmp(d_entry->d_name, ".") + && strcmp(d_entry->d_name, "..") + && S_ISDIR(statbuf.st_mode) ) + { + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + } +#ifdef VMS + if(!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX && + statbuf.st_fab_rfm != FAB$C_STMLF)) { + fprintf(stderr,"Warning - file %s has an unsupported VMS record" + " format (%d)\n", + whole_path, statbuf.st_fab_rfm); + } +#endif + + if(S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK))){ + fprintf(stderr, "File %s is not readable (errno = %d) - ignoring\n", + whole_path, errno); + continue; + } + + /* Add this so that we can detect directory loops with hard links. + If we are set up to follow symlinks, then we skip this checking. */ + if( !follow_links + && S_ISDIR(lstatbuf.st_mode) + && strcmp(d_entry->d_name, ".") + && strcmp(d_entry->d_name, "..") ) + { + if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) { + fprintf(stderr,"Directory loop - fatal goof (%s %lx %lu).\n", + whole_path, (unsigned long) statbuf.st_dev, + (unsigned long) STAT_INODE(statbuf)); + exit(1); + }; + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + }; + + if (!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) && + !S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode) + && !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) && + !S_ISDIR(lstatbuf.st_mode)) { + fprintf(stderr,"Unknown file type %s - ignoring and continuing.\n", + whole_path); + continue; + }; + + /* Who knows what trash this is - ignore and continue */ + + if(status) { + fprintf(stderr, + "Unable to stat file %s - ignoring and continuing.\n", + whole_path); + continue; + }; + + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + s_entry->next = this_dir->contents; + memset(s_entry->isorec.extent, 0, 8); + this_dir->contents = s_entry; + deep_flag = 0; + s_entry->table = NULL; + + s_entry->name = strdup(d_entry->d_name); + s_entry->whole_name = strdup (whole_path); + + s_entry->de_flags = 0; + s_entry->filedir = this_dir; + s_entry->isorec.flags[0] = 0; + s_entry->isorec.ext_attr_length[0] = 0; + iso9660_date(s_entry->isorec.date, statbuf.st_mtime); + s_entry->isorec.file_unit_size[0] = 0; + s_entry->isorec.interleave[0] = 0; + if(parent && parent == reloc_dir && strcmp(d_entry->d_name, "..") == 0){ + s_entry->inode = UNCACHED_INODE; + s_entry->dev = (dev_t) UNCACHED_DEVICE; + deep_flag = NEED_PL; + } else { + s_entry->inode = STAT_INODE(statbuf); + s_entry->dev = statbuf.st_dev; + }; + set_723(s_entry->isorec.volume_sequence_number, DEF_VSN); + iso9660_file_length(d_entry->d_name, s_entry, S_ISDIR(statbuf.st_mode)); + s_entry->rr_attr_size = 0; + s_entry->total_rr_attr_size = 0; + s_entry->rr_attributes = NULL; + + /* Directories are assigned sizes later on */ + if (!S_ISDIR(statbuf.st_mode)) { + set_733((char *) s_entry->isorec.size, statbuf.st_size); + + if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) || + S_ISFIFO(lstatbuf.st_mode) || S_ISSOCK(lstatbuf.st_mode) + || S_ISLNK(lstatbuf.st_mode)) + s_entry->size = 0; + else + s_entry->size = statbuf.st_size; + } else + s_entry->isorec.flags[0] = 2; + + /* + * We always should create an entirely new directory tree whenever + * we generate a new session, unless there were *no* changes whatsoever + * to any of the directories, in which case it would be kind of pointless + * to generate a new session. + * + * I believe it is possible to rigorously prove that any change anywhere + * in the filesystem will force the entire tree to be regenerated + * because the modified directory will get a new extent number. Since + * each subdirectory of the changed directory has a '..' entry, all of + * them will need to be rewritten too, and since the parent directory + * of the modified directory will have an extent pointer to the directory + * it too will need to be rewritten. Thus we will never be able to reuse + * any directory information when writing new sessions. + * + * We still check the previous session so we can mark off the equivalent + * entry in the list we got from the original disc, however. + */ + if(S_ISDIR(statbuf.st_mode) && orig_contents != NULL){ + check_prev_session(orig_contents, n_orig, s_entry, + &statbuf, &lstatbuf, &odpnt); + } + + if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..") && + S_ISDIR(statbuf.st_mode) && this_dir->depth > RR_relocation_depth){ + if(!reloc_dir) generate_reloc_directory(); + + s_entry1 = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry1, this_dir->contents, + sizeof(struct directory_entry)); + s_entry1->table = NULL; + s_entry1->name = strdup(this_dir->contents->name); + s_entry1->whole_name = strdup(this_dir->contents->whole_name); + s_entry1->next = reloc_dir->contents; + reloc_dir->contents = s_entry1; + s_entry1->priority = 32768; + s_entry1->parent_rec = this_dir->contents; + + deep_flag = NEED_RE; + + if(use_RockRidge) { + generate_rock_ridge_attributes(whole_path, + d_entry->d_name, s_entry1, + &statbuf, &lstatbuf, deep_flag); + } + + deep_flag = 0; + + /* We need to set this temporarily so that the parent to this is correctly + determined. */ + s_entry1->filedir = reloc_dir; + if( odpnt != NULL ) + { + scan_directory_tree(whole_path, s_entry1, &odpnt->isorec); + } + else + { + scan_directory_tree(whole_path, s_entry1, NULL); + } + if( odpnt != NULL ) + { + free(odpnt); + odpnt = NULL; + } + s_entry1->filedir = this_dir; + + statbuf.st_size = 0; + statbuf.st_mode &= 0777; + set_733((char *) s_entry->isorec.size, 0); + s_entry->size = 0; + s_entry->isorec.flags[0] = 0; + s_entry->inode = UNCACHED_INODE; + deep_flag = NEED_CL; + }; + + if(generate_tables && strcmp(s_entry->name, ".") && strcmp(s_entry->name, "..")) { + char buffer[2048]; + int nchar; + switch(lstatbuf.st_mode & S_IFMT){ + case S_IFDIR: + sprintf(buffer,"D\t%s\n", + s_entry->name); + break; +#ifndef NON_UNIXFS + case S_IFBLK: + sprintf(buffer,"B\t%s\t%lu %lu\n", + s_entry->name, + (unsigned long) major(statbuf.st_rdev), + (unsigned long) minor(statbuf.st_rdev)); + break; + case S_IFIFO: + sprintf(buffer,"P\t%s\n", + s_entry->name); + break; + case S_IFCHR: + sprintf(buffer,"C\t%s\t%lu %lu\n", + s_entry->name, + (unsigned long) major(statbuf.st_rdev), + (unsigned long) minor(statbuf.st_rdev)); + break; + case S_IFLNK: + nchar = readlink(whole_path, + symlink_buff, + sizeof(symlink_buff)); + symlink_buff[nchar < 0 ? 0 : nchar] = 0; + sprintf(buffer,"L\t%s\t%s\n", + s_entry->name, symlink_buff); + break; +#ifdef S_IFSOCK + case S_IFSOCK: + sprintf(buffer,"S\t%s\n", + s_entry->name); + break; +#endif +#endif /* NON_UNIXFS */ + case S_IFREG: + default: + sprintf(buffer,"F\t%s\n", + s_entry->name); + break; + }; + s_entry->table = strdup(buffer); + }; + + /* + * See if we have an entry for this guy in the previous session. + */ + if( orig_contents != NULL && !S_ISDIR(statbuf.st_mode)) + { + check_prev_session(orig_contents, n_orig, s_entry, + &statbuf, &lstatbuf, NULL); + } + + if(S_ISDIR(statbuf.st_mode)){ + int dflag; + if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..")) { + if( odpnt != NULL ) + { + dflag = scan_directory_tree(whole_path, s_entry, + &odpnt->isorec); + } + else + { + dflag = scan_directory_tree(whole_path, s_entry, NULL); + } + /* If unable to scan directory, mark this as a non-directory */ + if(!dflag) + lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG; + if( odpnt != NULL ) + { + free(odpnt); + odpnt = NULL; + } + } + } + + if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".") == 0) + deep_flag |= NEED_CE | NEED_SP; /* For extension record */ + + /* Now figure out how much room this file will take in the directory */ + + if(use_RockRidge) { + generate_rock_ridge_attributes(whole_path, + d_entry->d_name, s_entry, + &statbuf, &lstatbuf, deep_flag); + + } + } + closedir(current_dir); + + if( orig_contents != NULL ) + { + merge_remaining_entries(this_dir, orig_contents, n_orig); + free_mdinfo(orig_contents, n_orig); + } + + if( this_dir->contents == NULL ) + { + /* + * This directory must have been inaccessible. + */ + return 0; + } + sort_n_finish(this_dir); + + return 1; +} + + +void FDECL2(generate_iso9660_directories, struct directory *, node, FILE*, outfile){ + struct directory * dpnt; + + dpnt = node; + + while (dpnt){ + if( dpnt->extent > session_start ) + { + generate_one_directory(dpnt, outfile); + } + if(dpnt->subdir) generate_iso9660_directories(dpnt->subdir, outfile); + dpnt = dpnt->next; + } +} + +void FDECL1(dump_tree, struct directory *, node){ + struct directory * dpnt; + + dpnt = node; + + while (dpnt){ + fprintf(stderr,"%4d %5d %s\n",dpnt->extent, dpnt->size, dpnt->de_name); + if(dpnt->subdir) dump_tree(dpnt->subdir); + dpnt = dpnt->next; + } +} + +/* + * something quick and dirty to locate a file given a path + * recursively walks down path in filename until it finds the + * directory entry for the desired file + */ +struct directory_entry * FDECL2(search_tree_file, struct directory *, + node,char *, filename) +{ + struct directory_entry * depnt; + struct directory * dpnt; + char * p1; + char * rest; + char * subdir; + + /* + * strip off next directory name from filename + */ + subdir = strdup(filename); + + if( (p1=strchr(subdir, '/')) == subdir ) + { + fprintf(stderr,"call to search_tree_file with an absolute path, stripping\n"); + fprintf(stderr,"initial path separator. Hope this was intended...\n"); + memmove(subdir, subdir+1, strlen(subdir)-1); + p1 = strchr(subdir, '/'); + } + + /* + * do we need to find a subdirectory + */ + if (p1) + { + *p1 = '\0'; + +#ifdef DEBUG_TORITO + printf("Looking for subdir called %s\n",p1); +#endif + + rest = p1+1; + +#ifdef DEBUG_TORITO + printf("Remainder of path name is now %s\n", rest); +#endif + + dpnt = node->subdir; + while( dpnt ) + { +#ifdef DEBUG_TORITO + fprintf(stderr,"%4d %5d %s\n", dpnt->extent, dpnt->size, + dpnt->de_name); +#endif + if (!strcmp(subdir, dpnt->de_name)) + { +#ifdef DEBUG_TORITO + printf("Calling next level with filename = %s", rest); +#endif + return(search_tree_file( dpnt, rest )); + } + dpnt = dpnt->next; + } + + /* if we got here means we couldnt find the subdir */ + return (NULL); + } + else + { + /* + * look for a normal file now + */ + depnt = node->contents; + while (depnt) + { +#ifdef DEBUG_TORITO + fprintf(stderr,"%4d %5d %s\n",depnt->isorec.extent, + depnt->size, depnt->name); +#endif + if (!strcmp(filename, depnt->name)) + { +#ifdef DEBUG_TORITO + printf("Found our file %s", filename); +#endif + return(depnt); + } + depnt = depnt->next; + } + /* + * if we got here means we couldnt find the subdir + */ + return (NULL); + } + fprintf(stderr,"We cant get here in search_tree_file :-/ \n"); +} + diff --git a/util/mkisofs/write.c b/util/mkisofs/write.c new file mode 100644 index 000000000..cfc9b763c --- /dev/null +++ b/util/mkisofs/write.c @@ -0,0 +1,1142 @@ +/* + * Program write.c - dump memory structures to file for iso9660 filesystem. + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +static char rcsid[] ="$Id: write.c,v 1.6.1.3 1997/11/13 05:07:13 eric Exp $"; + +#include +#include +#include "mkisofs.h" +#include "iso9660.h" +#include +#include + +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef __svr4__ +extern char * strdup(const char *); +#endif + +#ifdef VMS +extern char * strdup(const char *); +#endif + + +/* Max number of sectors we will write at one time */ +#define NSECT 16 + +/* Counters for statistics */ + +static int table_size = 0; +static int total_dir_size = 0; +static int rockridge_size = 0; +static struct directory ** pathlist; +static next_path_index = 1; + +/* Used to fill in some of the information in the volume descriptor. */ +static struct tm local; +static struct tm gmt; + +/* Routines to actually write the disc. We write sequentially so that + we could write a tape, or write the disc directly */ + + +#define FILL_SPACE(X) memset(vol_desc.X, ' ', sizeof(vol_desc.X)) + +void FDECL2(set_721, char *, pnt, unsigned int, i) +{ + pnt[0] = i & 0xff; + pnt[1] = (i >> 8) & 0xff; +} + +void FDECL2(set_722, char *, pnt, unsigned int, i) +{ + pnt[0] = (i >> 8) & 0xff; + pnt[1] = i & 0xff; +} + +void FDECL2(set_723, char *, pnt, unsigned int, i) +{ + pnt[3] = pnt[0] = i & 0xff; + pnt[2] = pnt[1] = (i >> 8) & 0xff; +} + +void FDECL2(set_731, char *, pnt, unsigned int, i) +{ + pnt[0] = i & 0xff; + pnt[1] = (i >> 8) & 0xff; + pnt[2] = (i >> 16) & 0xff; + pnt[3] = (i >> 24) & 0xff; +} + +void FDECL2(set_732, char *, pnt, unsigned int, i) +{ + pnt[3] = i & 0xff; + pnt[2] = (i >> 8) & 0xff; + pnt[1] = (i >> 16) & 0xff; + pnt[0] = (i >> 24) & 0xff; +} + +int FDECL1(get_733, char *, p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +void FDECL2(set_733, char *, pnt, unsigned int, i) +{ + pnt[7] = pnt[0] = i & 0xff; + pnt[6] = pnt[1] = (i >> 8) & 0xff; + pnt[5] = pnt[2] = (i >> 16) & 0xff; + pnt[4] = pnt[3] = (i >> 24) & 0xff; +} + +void FDECL4(xfwrite, void *, buffer, int, count, int, size, FILE *, file) +{ + while(count) + { + int got = fwrite(buffer,size,count,file); + + if(got<=0) + { + fprintf(stderr,"cannot fwrite %d*%d\n",size,count); + exit(1); + } + count-=got,*(char**)&buffer+=size*got; + } +} + +struct deferred_write +{ + struct deferred_write * next; + char * table; + unsigned int extent; + unsigned int size; + char * name; +}; + +static struct deferred_write * dw_head = NULL, * dw_tail = NULL; + +static struct directory_entry * sort_dir; +static struct eltorito_boot_descriptor boot_desc; + +unsigned int last_extent_written =0; +static struct iso_primary_descriptor vol_desc; +static path_table_index; +static time_t begun; + +/* We recursively walk through all of the directories and assign extent + numbers to them. We have already assigned extent numbers to everything that + goes in front of them */ + +void FDECL1(assign_directory_addresses, struct directory *, node) +{ + int dir_size; + struct directory * dpnt; + + dpnt = node; + + while (dpnt) + { + /* + * If we already have an extent for this (i.e. it came from + * a multisession disc), then don't reassign a new extent. + */ + dpnt->path_index = next_path_index++; + if( dpnt->extent == 0 ) + { + dpnt->extent = last_extent; + dir_size = (dpnt->size + (SECTOR_SIZE - 1)) >> 11; + + last_extent += dir_size; + + /* + * Leave room for the CE entries for this directory. Keep them + * close to the reference directory so that access will be + * quick. + */ + if(dpnt->ce_bytes) + { + last_extent += ROUND_UP(dpnt->ce_bytes) >> 11; + } + } + + if(dpnt->subdir) + { + assign_directory_addresses(dpnt->subdir); + } + + dpnt = dpnt->next; + } +} + +static void FDECL3(write_one_file, char *, filename, + unsigned int, size, FILE *, outfile) +{ + char buffer[SECTOR_SIZE * NSECT]; + FILE * infile; + int remain; + int use; + + + if ((infile = fopen(filename, "rb")) == NULL) + { +#if defined(sun) || defined(_AUX_SOURCE) + fprintf(stderr, "cannot open %s: (%d)\n", filename, errno); +#else + fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno)); +#endif + exit(1); + } + remain = size; + + while(remain > 0) + { + use = (remain > SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain); + use = ROUND_UP(use); /* Round up to nearest sector boundary */ + memset(buffer, 0, use); + if (fread(buffer, 1, use, infile) == 0) + { + fprintf(stderr,"cannot read from %s\n",filename); + exit(1); + } + xfwrite(buffer, 1, use, outfile); + last_extent_written += use/SECTOR_SIZE; +#if 0 + if((last_extent_written % 1000) < use/SECTOR_SIZE) + { + fprintf(stderr,"%d..", last_extent_written); + } +#else + if((last_extent_written % 5000) < use/SECTOR_SIZE) + { + time_t now; + time_t the_end; + double frac; + + time(&now); + frac = last_extent_written / (double)last_extent; + the_end = begun + (now - begun) / frac; + fprintf(stderr, "%6.2f%% done, estimate finish %s", + frac * 100., ctime(&the_end)); + } +#endif + remain -= use; + } + fclose(infile); +} /* write_one_file(... */ + +static void FDECL1(write_files, FILE *, outfile) +{ + struct deferred_write * dwpnt, *dwnext; + dwpnt = dw_head; + while(dwpnt) + { + if(dwpnt->table) + { + xfwrite(dwpnt->table, 1, ROUND_UP(dwpnt->size), outfile); + last_extent_written += ROUND_UP(dwpnt->size) / SECTOR_SIZE; + table_size += dwpnt->size; +/* fprintf(stderr,"Size %d ", dwpnt->size); */ + free(dwpnt->table); + } + else + { + +#ifdef VMS + vms_write_one_file(dwpnt->name, dwpnt->size, outfile); +#else + write_one_file(dwpnt->name, dwpnt->size, outfile); +#endif + free(dwpnt->name); + } + + dwnext = dwpnt; + dwpnt = dwpnt->next; + free(dwnext); + } +} /* write_files(... */ + +#if 0 +static void dump_filelist() +{ + struct deferred_write * dwpnt; + dwpnt = dw_head; + while(dwpnt) + { + fprintf(stderr, "File %s\n",dwpnt->name); + dwpnt = dwpnt->next; + } + fprintf(stderr,"\n"); +} +#endif + +int FDECL2(compare_dirs, const void *, rr, const void *, ll) +{ + char * rpnt, *lpnt; + struct directory_entry ** r, **l; + + r = (struct directory_entry **) rr; + l = (struct directory_entry **) ll; + rpnt = (*r)->isorec.name; + lpnt = (*l)->isorec.name; + + /* + * Put the '.' and '..' entries on the head of the sorted list. + * For normal ASCII, this always happens to be the case, but out of + * band characters cause this not to be the case sometimes. + */ + if( strcmp(rpnt, ".") == 0 ) return -1; + if( strcmp(lpnt, ".") == 0 ) return 1; + + if( strcmp(rpnt, "..") == 0 ) return -1; + if( strcmp(lpnt, "..") == 0 ) return 1; + + while(*rpnt && *lpnt) + { + if(*rpnt == ';' && *lpnt != ';') return -1; + if(*rpnt != ';' && *lpnt == ';') return 1; + + if(*rpnt == ';' && *lpnt == ';') return 0; + + if(*rpnt == '.' && *lpnt != '.') return -1; + if(*rpnt != '.' && *lpnt == '.') return 1; + + if((unsigned char)*rpnt < (unsigned char)*lpnt) return -1; + if((unsigned char)*rpnt > (unsigned char)*lpnt) return 1; + rpnt++; lpnt++; + } + if(*rpnt) return 1; + if(*lpnt) return -1; + return 0; +} + +void FDECL1(sort_directory, struct directory_entry **, sort_dir) +{ + int dcount = 0; + int i, len; + struct directory_entry * s_entry; + struct directory_entry ** sortlist; + + s_entry = *sort_dir; + while(s_entry) + { + dcount++; + s_entry = s_entry->next; + } + + /* + * OK, now we know how many there are. Build a vector for sorting. + */ + sortlist = (struct directory_entry **) + e_malloc(sizeof(struct directory_entry *) * dcount); + + dcount = 0; + s_entry = *sort_dir; + while(s_entry) + { + sortlist[dcount] = s_entry; + len = s_entry->isorec.name_len[0]; + s_entry->isorec.name[len] = 0; + dcount++; + s_entry = s_entry->next; + } + + qsort(sortlist, dcount, sizeof(struct directory_entry *), + (int (*)(const void *, const void *))compare_dirs); + + /* + * Now reassemble the linked list in the proper sorted order + */ + for(i=0; inext = sortlist[i+1]; + } + + sortlist[dcount-1]->next = NULL; + *sort_dir = sortlist[0]; + + free(sortlist); + +} + +void generate_root_record() +{ + time_t ctime; + + time (&ctime); + + local = *localtime(&ctime); + gmt = *gmtime(&ctime); + + root_record.length[0] = 1 + sizeof(struct iso_directory_record) + - sizeof(root_record.name); + root_record.ext_attr_length[0] = 0; + set_733((char *) root_record.extent, root->extent); + set_733((char *) root_record.size, ROUND_UP(root->size)); + iso9660_date(root_record.date, ctime); + root_record.flags[0] = 2; + root_record.file_unit_size[0] = 0; + root_record.interleave[0] = 0; + set_723(root_record.volume_sequence_number, DEF_VSN); + root_record.name_len[0] = 1; +} + +static void FDECL1(assign_file_addresses, struct directory *, dpnt) +{ + struct directory * finddir; + struct directory_entry * s_entry; + struct file_hash *s_hash; + struct deferred_write * dwpnt; + char whole_path[1024]; + + while (dpnt) + { + s_entry = dpnt->contents; + for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) + { + + /* + * If we already have an extent for this entry, + * then don't assign a new one. It must have come + * from a previous session on the disc. Note that + * we don't end up scheduling the thing for writing + * either. + */ + if( isonum_733((unsigned char *) s_entry->isorec.extent) != 0 ) + { + continue; + } + + /* + * This saves some space if there are symlinks present + */ + s_hash = find_hash(s_entry->dev, s_entry->inode); + if(s_hash) + { + if(verbose) + { + fprintf(stderr, "Cache hit for %s%s%s\n",s_entry->filedir->de_name, + SPATH_SEPARATOR, s_entry->name); + } + set_733((char *) s_entry->isorec.extent, s_hash->starting_block); + set_733((char *) s_entry->isorec.size, s_hash->size); + continue; + } + + /* + * If this is for a directory that is not a . or a .. entry, + * then look up the information for the entry. We have already + * assigned extents for directories, so we just need to + * fill in the blanks here. + */ + if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..") && + s_entry->isorec.flags[0] == 2) + { + finddir = dpnt->subdir; + while(1==1) + { + if(finddir->self == s_entry) break; + finddir = finddir->next; + if(!finddir) + { + fprintf(stderr,"Fatal goof\n"); exit(1); + } + } + set_733((char *) s_entry->isorec.extent, finddir->extent); + s_entry->starting_block = finddir->extent; + s_entry->size = ROUND_UP(finddir->size); + total_dir_size += s_entry->size; + add_hash(s_entry); + set_733((char *) s_entry->isorec.size, ROUND_UP(finddir->size)); + continue; + } + + + /* + * If this is . or .., then look up the relevant info from the + * tables. + */ + if(strcmp(s_entry->name,".") == 0) + { + set_733((char *) s_entry->isorec.extent, dpnt->extent); + + /* + * Set these so that the hash table has the + * correct information + */ + s_entry->starting_block = dpnt->extent; + s_entry->size = ROUND_UP(dpnt->size); + + add_hash(s_entry); + s_entry->starting_block = dpnt->extent; + set_733((char *) s_entry->isorec.size, ROUND_UP(dpnt->size)); + continue; + } + + if(strcmp(s_entry->name,"..") == 0) + { + if(dpnt == root) + { + total_dir_size += root->size; + } + set_733((char *) s_entry->isorec.extent, dpnt->parent->extent); + + /* + * Set these so that the hash table has the + * correct information + */ + s_entry->starting_block = dpnt->parent->extent; + s_entry->size = ROUND_UP(dpnt->parent->size); + + add_hash(s_entry); + s_entry->starting_block = dpnt->parent->extent; + set_733((char *) s_entry->isorec.size, ROUND_UP(dpnt->parent->size)); + continue; + } + + /* + * Some ordinary non-directory file. Just schedule the + * file to be written. This is all quite + * straightforward, just make a list and assign extents + * as we go. Once we get through writing all of the + * directories, we should be ready write out these + * files + */ + if(s_entry->size) + { + dwpnt = (struct deferred_write *) + e_malloc(sizeof(struct deferred_write)); + if(dw_tail) + { + dw_tail->next = dwpnt; + dw_tail = dwpnt; + } + else + { + dw_head = dwpnt; + dw_tail = dwpnt; + } + if(s_entry->inode == TABLE_INODE) + { + dwpnt->table = s_entry->table; + dwpnt->name = NULL; + sprintf(whole_path,"%s%sTRANS.TBL", + s_entry->filedir->whole_name, SPATH_SEPARATOR); + } + else + { + dwpnt->table = NULL; + strcpy(whole_path, s_entry->whole_name); + dwpnt->name = strdup(whole_path); + } + dwpnt->next = NULL; + dwpnt->size = s_entry->size; + dwpnt->extent = last_extent; + set_733((char *) s_entry->isorec.extent, last_extent); + s_entry->starting_block = last_extent; + add_hash(s_entry); + last_extent += ROUND_UP(s_entry->size) >> 11; + if(verbose) + { + fprintf(stderr,"%d %d %s\n", s_entry->starting_block, + last_extent-1, whole_path); + } +#ifdef DBG_ISO + if((ROUND_UP(s_entry->size) >> 11) > 500) + { + fprintf(stderr,"Warning: large file %s\n", whole_path); + fprintf(stderr,"Starting block is %d\n", s_entry->starting_block); + fprintf(stderr,"Reported file size is %d extents\n", s_entry->size); + + } +#endif + if(last_extent > (800000000 >> 11)) + { + /* + * More than 800Mb? Punt + */ + fprintf(stderr,"Extent overflow processing file %s\n", whole_path); + fprintf(stderr,"Starting block is %d\n", s_entry->starting_block); + fprintf(stderr,"Reported file size is %d extents\n", s_entry->size); + exit(1); + } + continue; + } + + /* + * This is for zero-length files. If we leave the extent 0, + * then we get screwed, because many readers simply drop files + * that have an extent of zero. Thus we leave the size 0, + * and just assign the extent number. + */ + set_733((char *) s_entry->isorec.extent, last_extent); + } + if(dpnt->subdir) + { + assign_file_addresses(dpnt->subdir); + } + dpnt = dpnt->next; + } +} /* assign_file_addresses(... */ + +void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile) +{ + unsigned int ce_address = 0; + char * ce_buffer; + unsigned int ce_index = 0; + unsigned int ce_size; + unsigned int dir_index; + char * directory_buffer; + int new_reclen; + struct directory_entry * s_entry; + struct directory_entry * s_entry_d; + unsigned int total_size; + + total_size = (dpnt->size + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1); + directory_buffer = (char *) e_malloc(total_size); + memset(directory_buffer, 0, total_size); + dir_index = 0; + + ce_size = (dpnt->ce_bytes + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1); + ce_buffer = NULL; + + if(ce_size) + { + ce_buffer = (char *) e_malloc(ce_size); + memset(ce_buffer, 0, ce_size); + + ce_index = 0; + + /* + * Absolute byte address of CE entries for this directory + */ + ce_address = last_extent_written + (total_size >> 11); + ce_address = ce_address << 11; + } + + s_entry = dpnt->contents; + while(s_entry) + { + + /* + * We do not allow directory entries to cross sector boundaries. + * Simply pad, and then start the next entry at the next sector + */ + new_reclen = s_entry->isorec.length[0]; + if( (dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE ) + { + dir_index = (dir_index + (SECTOR_SIZE - 1)) & + ~(SECTOR_SIZE - 1); + } + + memcpy(directory_buffer + dir_index, &s_entry->isorec, + sizeof(struct iso_directory_record) - + sizeof(s_entry->isorec.name) + s_entry->isorec.name_len[0]); + dir_index += sizeof(struct iso_directory_record) - + sizeof (s_entry->isorec.name)+ s_entry->isorec.name_len[0]; + + /* + * Add the Rock Ridge attributes, if present + */ + if(s_entry->rr_attr_size) + { + if(dir_index & 1) + { + directory_buffer[dir_index++] = 0; + } + + /* + * If the RR attributes were too long, then write the + * CE records, as required. + */ + if(s_entry->rr_attr_size != s_entry->total_rr_attr_size) + { + unsigned char * pnt; + int len, nbytes; + + /* + * Go through the entire record and fix up the CE entries + * so that the extent and offset are correct + */ + + pnt = s_entry->rr_attributes; + len = s_entry->total_rr_attr_size; + while(len > 3) + { +#ifdef DEBUG + if (!ce_size) + { + fprintf(stderr,"Warning: ce_index(%d) && ce_address(%d) not initialized\n", + ce_index, ce_address); + } +#endif + + if(pnt[0] == 'C' && pnt[1] == 'E') + { + nbytes = get_733( (char *) pnt+20); + + if((ce_index & (SECTOR_SIZE - 1)) + nbytes >= + SECTOR_SIZE) + { + ce_index = ROUND_UP(ce_index); + } + + set_733( (char *) pnt+4, + (ce_address + ce_index) >> 11); + set_733( (char *) pnt+12, + (ce_address + ce_index) & (SECTOR_SIZE - 1)); + + + /* + * Now store the block in the ce buffer + */ + memcpy(ce_buffer + ce_index, + pnt + pnt[2], nbytes); + ce_index += nbytes; + if(ce_index & 1) + { + ce_index++; + } + } + len -= pnt[2]; + pnt += pnt[2]; + } + + } + + rockridge_size += s_entry->total_rr_attr_size; + memcpy(directory_buffer + dir_index, s_entry->rr_attributes, + s_entry->rr_attr_size); + dir_index += s_entry->rr_attr_size; + } + if(dir_index & 1) + { + directory_buffer[dir_index++] = 0; + } + + s_entry_d = s_entry; + s_entry = s_entry->next; + + if (s_entry_d->rr_attributes) free(s_entry_d->rr_attributes); + if( s_entry_d->name != NULL ) + { + free (s_entry_d->name); + } + if( s_entry_d->whole_name != NULL ) + { + free (s_entry_d->whole_name); + } + free (s_entry_d); + } + sort_dir = NULL; + + if(dpnt->size != dir_index) + { + fprintf(stderr,"Unexpected directory length %d %d %s\n",dpnt->size, + dir_index, dpnt->de_name); + } + + xfwrite(directory_buffer, 1, total_size, outfile); + last_extent_written += total_size >> 11; + free(directory_buffer); + + if(ce_size) + { + if(ce_index != dpnt->ce_bytes) + { + fprintf(stderr,"Continuation entry record length mismatch (%d %d).\n", + ce_index, dpnt->ce_bytes); + } + xfwrite(ce_buffer, 1, ce_size, outfile); + last_extent_written += ce_size >> 11; + free(ce_buffer); + } + +} /* generate_one_directory(... */ + +static +void FDECL1(build_pathlist, struct directory *, node) +{ + struct directory * dpnt; + + dpnt = node; + + while (dpnt) + { + pathlist[dpnt->path_index] = dpnt; + if(dpnt->subdir) build_pathlist(dpnt->subdir); + dpnt = dpnt->next; + } +} /* build_pathlist(... */ + +int FDECL2(compare_paths, void const *, r, void const *, l) +{ + struct directory const *ll = *(struct directory * const *)l; + struct directory const *rr = *(struct directory * const *)r; + + if (rr->parent->path_index < ll->parent->path_index) + { + return -1; + } + + if (rr->parent->path_index > ll->parent->path_index) + { + return 1; + } + + return strcmp(rr->self->isorec.name, ll->self->isorec.name); + +} /* compare_paths(... */ + +void generate_path_tables() +{ + struct directory_entry * de; + struct directory * dpnt; + int fix; + int i; + int j; + int namelen; + char * npnt; + char * npnt1; + int tablesize; + + /* + * First allocate memory for the tables and initialize the memory + */ + tablesize = path_blocks << 11; + path_table_m = (char *) e_malloc(tablesize); + path_table_l = (char *) e_malloc(tablesize); + memset(path_table_l, 0, tablesize); + memset(path_table_m, 0, tablesize); + + /* + * Now start filling in the path tables. Start with root directory + */ + path_table_index = 0; + pathlist = (struct directory **) e_malloc(sizeof(struct directory *) + * next_path_index); + memset(pathlist, 0, sizeof(struct directory *) * next_path_index); + build_pathlist(root); + + do + { + fix = 0; + qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *), + (int (*)(const void *, const void *))compare_paths); + + for(j=1; jpath_index != j) + { + pathlist[j]->path_index = j; + fix++; + } + } + } while(fix); + + for(j=1; jde_name; + + /* + * So the root comes out OK + */ + if( (*npnt == 0) || (dpnt == root) ) + { + npnt = "."; + } + npnt1 = strrchr(npnt, PATH_SEPARATOR); + if(npnt1) + { + npnt = npnt1 + 1; + } + + de = dpnt->self; + if(!de) + { + fprintf(stderr,"Fatal goof\n"); + exit(1); + } + + + namelen = de->isorec.name_len[0]; + + path_table_l[path_table_index] = namelen; + path_table_m[path_table_index] = namelen; + path_table_index += 2; + + set_731(path_table_l + path_table_index, dpnt->extent); + set_732(path_table_m + path_table_index, dpnt->extent); + path_table_index += 4; + + set_721(path_table_l + path_table_index, + dpnt->parent->path_index); + set_722(path_table_m + path_table_index, + dpnt->parent->path_index); + path_table_index += 2; + + for(i =0; iisorec.name[i]; + path_table_m[path_table_index] = de->isorec.name[i]; + path_table_index++; + } + if(path_table_index & 1) + { + path_table_index++; /* For odd lengths we pad */ + } + } + + free(pathlist); + if(path_table_index != path_table_size) + { + fprintf(stderr,"Path table lengths do not match %d %d\n", + path_table_index, + path_table_size); + } +} /* generate_path_tables(... */ + +void +FDECL3(memcpy_max, char *, to, char *, from, int, max) +{ + int n = strlen(from); + if (n > max) + { + n = max; + } + memcpy(to, from, n); + +} /* memcpy_max(... */ + +int FDECL1(iso_write, FILE *, outfile) +{ + char buffer[2048]; + int i; + char iso_time[17]; + int should_write; + + time(&begun); + assign_file_addresses(root); + + memset(buffer, 0, sizeof(buffer)); + + /* + * This will break in the year 2000, I supose, but there is no good way + * to get the top two digits of the year. + */ + sprintf(iso_time, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00", 1900 + local.tm_year, + local.tm_mon+1, local.tm_mday, + local.tm_hour, local.tm_min, local.tm_sec); + + local.tm_min -= gmt.tm_min; + local.tm_hour -= gmt.tm_hour; + local.tm_yday -= gmt.tm_yday; + iso_time[16] = (local.tm_min + 60*(local.tm_hour + 24*local.tm_yday)) / 15; + + /* + * First, we output 16 sectors of all zero + */ + + for(i=0; i<16; i++) + { + xfwrite(buffer, 1, sizeof(buffer), outfile); + } + + last_extent_written += 16; + + /* + * Next we write out the primary descriptor for the disc + */ + memset(&vol_desc, 0, sizeof(vol_desc)); + vol_desc.type[0] = ISO_VD_PRIMARY; + memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID)); + vol_desc.version[0] = 1; + + memset(vol_desc.system_id, ' ', sizeof(vol_desc.system_id)); + memcpy_max(vol_desc.system_id, system_id, strlen(system_id)); + + memset(vol_desc.volume_id, ' ', sizeof(vol_desc.volume_id)); + memcpy_max(vol_desc.volume_id, volume_id, strlen(volume_id)); + + should_write = last_extent - session_start; + set_733((char *) vol_desc.volume_space_size, should_write); + set_723(vol_desc.volume_set_size, 1); + set_723(vol_desc.volume_sequence_number, DEF_VSN); + set_723(vol_desc.logical_block_size, 2048); + + /* + * The path tables are used by DOS based machines to cache directory + * locations + */ + + set_733((char *) vol_desc.path_table_size, path_table_size); + set_731(vol_desc.type_l_path_table, path_table[0]); + set_731(vol_desc.opt_type_l_path_table, path_table[1]); + set_732(vol_desc.type_m_path_table, path_table[2]); + set_732(vol_desc.opt_type_m_path_table, path_table[3]); + + /* + * Now we copy the actual root directory record + */ + memcpy(vol_desc.root_directory_record, &root_record, + sizeof(struct iso_directory_record) + 1); + + /* + * The rest is just fluff. It looks nice to fill in many of these fields, + * though. + */ + FILL_SPACE(volume_set_id); + if(volset_id) memcpy_max(vol_desc.volume_set_id, volset_id, strlen(volset_id)); + + FILL_SPACE(publisher_id); + if(publisher) memcpy_max(vol_desc.publisher_id, publisher, strlen(publisher)); + + FILL_SPACE(preparer_id); + if(preparer) memcpy_max(vol_desc.preparer_id, preparer, strlen(preparer)); + + FILL_SPACE(application_id); + if(appid) memcpy_max(vol_desc.application_id, appid, strlen(appid)); + + FILL_SPACE(copyright_file_id); + if(copyright) memcpy_max(vol_desc.copyright_file_id, copyright, + strlen(copyright)); + + FILL_SPACE(abstract_file_id); + if(abstract) memcpy_max(vol_desc.abstract_file_id, abstract, + strlen(abstract)); + + FILL_SPACE(bibliographic_file_id); + if(biblio) memcpy_max(vol_desc.bibliographic_file_id, biblio, + strlen(biblio)); + + FILL_SPACE(creation_date); + FILL_SPACE(modification_date); + FILL_SPACE(expiration_date); + FILL_SPACE(effective_date); + vol_desc.file_structure_version[0] = 1; + FILL_SPACE(application_data); + + memcpy(vol_desc.creation_date, iso_time, 17); + memcpy(vol_desc.modification_date, iso_time, 17); + memcpy(vol_desc.expiration_date, "0000000000000000", 17); + memcpy(vol_desc.effective_date, iso_time, 17); + + /* + * if not a bootable cd do it the old way + */ + xfwrite(&vol_desc, 1, 2048, outfile); + last_extent_written++; + if (use_eltorito) + { + /* + * Next we write out the boot volume descriptor for the disc + */ + get_torito_desc(&boot_desc); + xfwrite(&boot_desc, 1, 2048, outfile); + last_extent_written ++; + } + + /* + * Now write the end volume descriptor. Much simpler than the other one + */ + memset(&vol_desc, 0, sizeof(vol_desc)); + vol_desc.type[0] = ISO_VD_END; + memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID)); + vol_desc.version[0] = 1; + xfwrite(&vol_desc, 1, 2048, outfile); + last_extent_written += 1; + + /* + * Next we write the path tables + */ + xfwrite(path_table_l, 1, path_blocks << 11, outfile); + xfwrite(path_table_m, 1, path_blocks << 11, outfile); + last_extent_written += 2*path_blocks; + free(path_table_l); + free(path_table_m); + path_table_l = NULL; + path_table_m = NULL; + + /* + * OK, all done with that crap. Now write out the directories. + * This is where the fur starts to fly, because we need to keep track of + * each file as we find it and keep track of where we put it. + */ + +#ifdef DBG_ISO + fprintf(stderr,"Total directory extents being written = %d\n", last_extent); +#endif +#if 0 + generate_one_directory(root, outfile); +#endif + generate_iso9660_directories(root, outfile); + + if(extension_record) + { + xfwrite(extension_record, 1, SECTOR_SIZE, outfile); + last_extent_written++; + } + + /* + * Now write all of the files that we need. + */ + fprintf(stderr,"Total extents scheduled to be written = %d\n", + last_extent - session_start); + write_files(outfile); + + fprintf(stderr,"Total extents actually written = %d\n", + last_extent_written - session_start); + /* + * Hard links throw us off here + */ + if(should_write != last_extent - session_start) + { + fprintf(stderr,"Number of extents written not what was predicted. Please fix.\n"); + fprintf(stderr,"Predicted = %d, written = %d\n", should_write, last_extent); + } + + fprintf(stderr,"Total translation table size: %d\n", table_size); + fprintf(stderr,"Total rockridge attributes bytes: %d\n", rockridge_size); + fprintf(stderr,"Total directory bytes: %d\n", total_dir_size); + fprintf(stderr,"Path table size(bytes): %d\n", path_table_size); + +#ifdef DEBUG + fprintf(stderr, "next extent, last_extent, last_extent_written %d %d %d\n", + next_extent, last_extent, last_extent_written); +#endif + + return 0; + +} /* iso_write(... */ From 63eb2d63b134cc5877bab10a6c4cacc2ae738be4 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 8 Nov 2009 22:51:41 +0000 Subject: [PATCH 081/165] Import http://www.tux.org/pub/people/eric-youngdale/mkisofs/mkisofs-1.12b4.tar.gz --- util/mkisofs/defaults.h | 12 +- util/mkisofs/eltorito.c | 42 +- util/mkisofs/getopt.c | 760 +++++++++++++++++++ util/mkisofs/getopt1.c | 190 +++++ util/mkisofs/hash.c | 5 +- util/mkisofs/iso9660.h | 9 +- util/mkisofs/joliet.c | 972 ++++++++++++++++++++++++ util/mkisofs/mkisofs.c | 652 ++++++++++++++-- util/mkisofs/mkisofs.h | 154 +++- util/mkisofs/multi.c | 137 +++- util/mkisofs/name.c | 24 +- util/mkisofs/rock.c | 51 +- util/mkisofs/tree.c | 1571 +++++++++++++++++++++++++-------------- util/mkisofs/write.c | 503 +++++++++---- 14 files changed, 4270 insertions(+), 812 deletions(-) create mode 100644 util/mkisofs/getopt.c create mode 100644 util/mkisofs/getopt1.c create mode 100644 util/mkisofs/joliet.c diff --git a/util/mkisofs/defaults.h b/util/mkisofs/defaults.h index 91e678992..9e8f3331a 100644 --- a/util/mkisofs/defaults.h +++ b/util/mkisofs/defaults.h @@ -2,7 +2,7 @@ * Header file defaults.h - assorted default values for character strings in * the volume descriptor. * - * $Id: defaults.h,v 1.4 1997/04/10 03:31:53 eric Rel $ + * $Id: defaults.h,v 1.6 1998/06/02 02:40:37 eric Exp $ */ #define PREPARER_DEFAULT NULL @@ -24,7 +24,11 @@ #endif #ifdef __sun -#define SYSTEM_ID_DEFAULT "Solaris" +#ifdef __svr4__ +#define SYSTEM_ID_DEFAULT "Solaris" +#else +#define SYSTEM_ID_DEFAULT "SunOS" +#endif #endif #ifdef __hpux @@ -39,6 +43,10 @@ #define SYSTEM_ID_DEFAULT "AIX" #endif +#ifdef _WIN +#define SYSTEM_ID_DEFAULT "Win32" +#endif /* _WIN */ + #ifndef SYSTEM_ID_DEFAULT #define SYSTEM_ID_DEFAULT "LINUX" #endif diff --git a/util/mkisofs/eltorito.c b/util/mkisofs/eltorito.c index 0ac5a1290..3ff50e92e 100644 --- a/util/mkisofs/eltorito.c +++ b/util/mkisofs/eltorito.c @@ -21,7 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: eltorito.c,v 1.7 1997/05/17 15:44:31 eric Exp $"; +static char rcsid[] ="$Id: eltorito.c,v 1.12 1998/06/02 02:40:37 eric Exp $"; #include #include @@ -30,14 +30,22 @@ static char rcsid[] ="$Id: eltorito.c,v 1.7 1997/05/17 15:44:31 eric Exp $"; #include #include +#include "config.h" #include "mkisofs.h" #include "iso9660.h" +/* used by Win32 for opening binary file - not used by Unix */ +#ifndef O_BINARY +#define O_BINARY 0 +#endif /* O_BINARY */ + #undef MIN #define MIN(a, b) (((a) < (b))? (a): (b)) static struct eltorito_validation_entry valid_desc; static struct eltorito_defaultboot_entry default_desc; +static struct eltorito_boot_descriptor boot_desc; + /* * Check for presence of boot catalog. If it does not exist then make it @@ -63,7 +71,7 @@ void FDECL1(init_boot_catalog, const char *, path) * check for the file existing */ #ifdef DEBUG_TORITO - printf("Looking for boot catalog file %s\n",bootpath); + fprintf(stderr,"Looking for boot catalog file %s\n",bootpath); #endif if (!stat_filter(bootpath, &statbuf)) @@ -93,7 +101,7 @@ void FDECL1(init_boot_catalog, const char *, path) * file does not exist, so we create it * make it one CD sector long */ - bcat = open(bootpath, O_WRONLY | O_CREAT, S_IROTH | S_IRGRP | S_IRWXU ); + bcat = open(bootpath, O_WRONLY | O_CREAT | O_BINARY, S_IROTH | S_IRGRP | S_IRWXU ); if (bcat == -1) { fprintf(stderr, "Error creating boot catalog, exiting...\n"); @@ -207,7 +215,7 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) * assume 512 bytes/sector on a bootable floppy */ nsectors = ((de->size + 511) & ~(511))/512; - printf("\nSize of boot image is %d sectors -> ", nsectors); + fprintf(stderr, "\nSize of boot image is %d sectors -> ", nsectors); /* * choose size of emulated floppy based on boot image size @@ -215,17 +223,17 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) if (nsectors == 2880 ) { default_desc.boot_media[0] = EL_TORITO_MEDIA_144FLOP; - printf("Emulating a 1.44 meg floppy\n"); + fprintf(stderr, "Emulating a 1.44 meg floppy\n"); } else if (nsectors == 5760 ) { default_desc.boot_media[0] = EL_TORITO_MEDIA_288FLOP; - printf("Emulating a 2.88 meg floppy\n"); + fprintf(stderr,"Emulating a 2.88 meg floppy\n"); } else if (nsectors == 2400 ) { default_desc.boot_media[0] = EL_TORITO_MEDIA_12FLOP; - printf("Emulating a 1.2 meg floppy\n"); + fprintf(stderr,"Emulating a 1.2 meg floppy\n"); } else { @@ -240,7 +248,7 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) nsectors = 1; set_721(default_desc.nsect, (unsigned int) nsectors ); #ifdef DEBUG_TORITO - printf("Extent of boot images is %d\n",get_733(de->isorec.extent)); + fprintf(stderr,"Extent of boot images is %d\n",get_733(de->isorec.extent)); #endif set_731(default_desc.bootoff, (unsigned int) get_733(de->isorec.extent)); @@ -248,7 +256,7 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) /* * now write it to disk */ - bootcat = open(de2->whole_name, O_RDWR); + bootcat = open(de2->whole_name, O_RDWR | O_BINARY); if (bootcat == -1) { fprintf(stderr,"Error opening boot catalog for update.\n"); @@ -263,3 +271,19 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) write(bootcat, &default_desc, 32); close(bootcat); } /* get_torito_desc(... */ + +/* + * Function to write the EVD for the disc. + */ +int FDECL1(tvd_write, FILE *, outfile) +{ + /* + * Next we write out the boot volume descriptor for the disc + */ + get_torito_desc(&boot_desc); + xfwrite(&boot_desc, 1, 2048, outfile); + last_extent_written ++; + return 0; +} + +struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write}; diff --git a/util/mkisofs/getopt.c b/util/mkisofs/getopt.c new file mode 100644 index 000000000..79080aa54 --- /dev/null +++ b/util/mkisofs/getopt.c @@ -0,0 +1,760 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95 + Free Software Foundation, Inc. + +This file is part of the libiberty library. This library 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 library 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +As a special exception, if you link this library with files +compiled with a GNU compiler to produce an executable, this does not cause +the resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why +the executable file might be covered by the GNU General Public License. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +/* We use instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include +#else +#include "config.h" +#endif +#endif + +#ifndef __STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ +/* Many versions of the Linux C library include older, broken versions + of these routines, which will break the linker's command-line + parsing. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include +#endif /* GNU C library. */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include +#define my_index strchr +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +/* If using GCC, we can safely declare strlen this way. + If not using GCC, it is ok not to declare it. */ +#ifdef __GNUC__ +/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. + That was relevant to code that was here before. */ +#ifndef __STDC__ +/* gcc with -traditional declares the built-in strlen to return int, + and has done so at least since version 2.4.5. -- rms. */ +extern int strlen (const char *); +#endif /* not __STDC__ */ +#endif /* __GNUC__ */ + +#endif /* not __GNU_LIBRARY__ */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (argv) + char **argv; +{ + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Initialize the internal data when the first call is made. */ + +static const char * +_getopt_initialize (optstring) + const char *optstring; +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (getenv ("POSIXLY_CORRECT") != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + optarg = NULL; + + if (optind == 0) + optstring = _getopt_initialize (optstring); + + if (argc == 0) + return EOF; + + if (nextchar == NULL || *nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0')) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, nextchar, nameend - nextchar)) + { + if (nameend - nextchar == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); + } + optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = NULL; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + 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 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + 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 ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/util/mkisofs/getopt1.c b/util/mkisofs/getopt1.c new file mode 100644 index 000000000..c3400e5b6 --- /dev/null +++ b/util/mkisofs/getopt1.c @@ -0,0 +1,190 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +/* We use instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include +#else +#include "config.h" +#endif +#endif + +#include "getopt.h" + +#ifndef __STDC__ +/* This is a separate conditional since some stdc systems + reject `defined (const)'. */ +#ifndef const +#define const +#endif +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ +/* Many versions of the Linux C library include older, broken versions + of these routines, which will break the linker's command-line + parsing. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include +#else +char *getenv (); +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +#include + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static 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} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == EOF) + 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': + 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 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + 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 ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/util/mkisofs/hash.c b/util/mkisofs/hash.c index 67098d580..eb673393e 100644 --- a/util/mkisofs/hash.c +++ b/util/mkisofs/hash.c @@ -19,9 +19,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: hash.c,v 1.2 1997/02/23 16:11:15 eric Rel $"; +static char rcsid[] ="$Id: hash.c,v 1.4 1997/12/06 21:05:04 eric Exp $"; #include +#include "config.h" #include "mkisofs.h" #define NR_HASH 1024 @@ -44,7 +45,7 @@ void FDECL1(add_hash, struct directory_entry *, spnt){ hash_number = HASH_FN((unsigned int) spnt->dev, (unsigned int) spnt->inode); #if 0 - if (verbose) fprintf(stderr,"%s ",spnt->name); + if (verbose > 1) fprintf(stderr,"%s ",spnt->name); #endif s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash)); s_hash->next = hash_table[hash_number]; diff --git a/util/mkisofs/iso9660.h b/util/mkisofs/iso9660.h index a58f96f0d..65320121d 100644 --- a/util/mkisofs/iso9660.h +++ b/util/mkisofs/iso9660.h @@ -21,7 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* - * $Id: iso9660.h,v 1.1 1997/02/23 15:55:25 eric Rel $ + * $Id: iso9660.h,v 1.2 1997/05/17 15:46:44 eric Exp $ */ #ifndef _ISOFS_FS_H @@ -42,8 +42,9 @@ struct iso_volume_descriptor { }; /* volume descriptor types */ -#define ISO_VD_PRIMARY 1 -#define ISO_VD_END 255 +#define ISO_VD_PRIMARY 1 +#define ISO_VD_SUPPLEMENTARY 2 /* Used by Joliet */ +#define ISO_VD_END 255 #define ISO_STANDARD_ID "CD001" @@ -67,7 +68,7 @@ struct iso_primary_descriptor { char volume_id [ISODCL ( 41, 72)]; /* dchars */ char unused2 [ISODCL ( 73, 80)]; char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ - char unused3 [ISODCL ( 89, 120)]; + char escape_sequences [ISODCL ( 89, 120)]; char volume_set_size [ISODCL (121, 124)]; /* 723 */ char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ char logical_block_size [ISODCL (129, 132)]; /* 723 */ diff --git a/util/mkisofs/joliet.c b/util/mkisofs/joliet.c new file mode 100644 index 000000000..d3e8cb0e3 --- /dev/null +++ b/util/mkisofs/joliet.c @@ -0,0 +1,972 @@ +/* + * File joliet.c - handle Win95/WinNT long file/unicode extensions for iso9660. + + Copyright 1997 Eric Youngdale. + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +static char rcsid[] ="$Id: joliet.c,v 1.12 1998/06/02 02:40:37 eric Exp $"; + + +/* + * Joliet extensions for ISO9660. These are spottily documented by + * Microsoft. In their infinite stupidity, they completely ignored + * the possibility of using an SUSP record with the long filename + * in it, and instead wrote out a duplicate directory tree with the + * long filenames in it. + * + * I am not sure why they did this. One reason is that they get the path + * tables with the long filenames in them. + * + * There are two basic principles to Joliet, and the non-Unicode variant + * known as Romeo. Long filenames seem to be the main one, and the second + * is that the character set and a few other things is substantially relaxed. + * + * The SVD is identical to the PVD, except: + * + * Id is 2, not 1 (indicates SVD). + * escape_sequences contains UCS-2 indicator (levels 1, 2 or 3). + * The root directory record points to a different extent (with different + * size). + * There are different path tables for the two sets of directory trees. + * + * The following fields are recorded in Unicode: + * system_id + * volume_id + * volume_set_id + * publisher_id + * preparer_id + * application_id + * copyright_file_id + * abstract_file_id + * bibliographic_file_id + * + * Unicode strings are always encoded in big-endian format. + * + * In a directory record, everything is the same as with iso9660, except + * that the name is recorded in unicode. The name length is specified in + * total bytes, not in number of unicode characters. + * + * The character set used for the names is different with UCS - the + * restrictions are that the following are not allowed: + * + * Characters (00)(00) through (00)(1f) (control chars) + * (00)(2a) '*' + * (00)(2f) '/' + * (00)(3a) ':' + * (00)(3b) ';' + * (00)(3f) '?' + * (00)(5c) '\' + */ +#include "config.h" +#include "mkisofs.h" +#include "iso9660.h" + +#include +#include + +static jpath_table_index; +static struct directory ** jpathlist; +static next_jpath_index = 1; +static int sort_goof; + +static int DECL(joliet_sort_directory, (struct directory_entry ** sort_dir)); +static void DECL(assign_joliet_directory_addresses, (struct directory * node)); + +/* + * Function: convert_to_unicode + * + * Purpose: Perform a 1/2 assed unicode conversion on a text + * string. + * + * Notes: + */ +static void FDECL3(convert_to_unicode, unsigned char *, buffer, int, size, char *, source ) +{ + unsigned char * tmpbuf; + int i; + int j; + + /* + * If we get a NULL pointer for the source, it means we have an inplace + * copy, and we need to make a temporary working copy first. + */ + if( source == NULL ) + { + tmpbuf = (u_char *) e_malloc(size); + memcpy( tmpbuf, buffer, size); + } + else + { + tmpbuf = (u_char *)source; + } + + /* + * Now start copying characters. If the size was specified to be 0, then + * assume the input was 0 terminated. + */ + j = 0; + for(i=0; i < size ; i += 2, j++) + { + buffer[i] = 0; + if( tmpbuf[j] < 0x1f && tmpbuf[j] != 0 ) + { + buffer[i+1] = '_'; + } + else + { + switch(tmpbuf[j]) + { + case '*': + case '/': + case ':': + case ';': + case '?': + case '\\': + /* + * Even Joliet has some standards as to what is allowed in a pathname. + * Pretty tame in comparison to what DOS restricts you to. + */ + buffer[i+1] = '_'; + break; + default: + buffer[i+1] = tmpbuf[j]; + break; + } + } + } + + if( source == NULL ) + { + free(tmpbuf); + } +} + +/* + * Function: joliet_strlen + * + * Purpose: Return length in bytes of string after conversion to unicode. + * + * Notes: This is provided mainly as a convenience so that when more intelligent + * Unicode conversion for either Multibyte or 8-bit codes is available that + * we can easily adapt. + */ +static int FDECL1(joliet_strlen, const char *, string) +{ + int rtn; + struct iso_directory_record foobar; + + rtn = strlen(string) << 1; + + /* + * We do clamp the maximum length of a Joliet string to be the + * maximum path size. This helps to ensure that we don't completely + * bolix things up with very long paths. The Joliet specs say + * that the maximum length is 128 bytes, or 64 unicode characters. + */ + if( rtn > 0x80) + { + rtn = 0x80; + } + return rtn; +} + +/* + * Function: get_joliet_vol_desc + * + * Purpose: generate a Joliet compatible volume desc. + * + * Notes: Assume that we have the non-joliet vol desc + * already present in the buffer. Just modifiy the + * appropriate fields. + */ +static void FDECL1(get_joliet_vol_desc, struct iso_primary_descriptor *, vol_desc) +{ + vol_desc->type[0] = ISO_VD_SUPPLEMENTARY; + + /* + * For now, always do Unicode level 3. I don't really know what 1 and 2 + * are - perhaps a more limited Unicode set. + * + * FIXME(eric) - how does Romeo fit in here? + */ + strcpy(vol_desc->escape_sequences, "%/E"); + + /* + * Until we have Unicode path tables, leave these unset. + */ + set_733((char *) vol_desc->path_table_size, jpath_table_size); + set_731(vol_desc->type_l_path_table, jpath_table[0]); + set_731(vol_desc->opt_type_l_path_table, jpath_table[1]); + set_732(vol_desc->type_m_path_table, jpath_table[2]); + set_732(vol_desc->opt_type_m_path_table, jpath_table[3]); + + /* + * Set this one up. + */ + memcpy(vol_desc->root_directory_record, &jroot_record, + sizeof(struct iso_directory_record) + 1); + + /* + * Finally, we have a bunch of strings to convert to Unicode. + * FIXME(eric) - I don't know how to do this in general, so we will + * just be really lazy and do a char -> short conversion. We probably + * will want to filter any characters >= 0x80. + */ + convert_to_unicode((u_char *)vol_desc->system_id, sizeof(vol_desc->system_id), NULL); + convert_to_unicode((u_char *)vol_desc->volume_id, sizeof(vol_desc->volume_id), NULL); + convert_to_unicode((u_char *)vol_desc->volume_set_id, sizeof(vol_desc->volume_set_id), NULL); + convert_to_unicode((u_char *)vol_desc->publisher_id, sizeof(vol_desc->publisher_id), NULL); + convert_to_unicode((u_char *)vol_desc->preparer_id, sizeof(vol_desc->preparer_id), NULL); + convert_to_unicode((u_char *)vol_desc->application_id, sizeof(vol_desc->application_id), NULL); + convert_to_unicode((u_char *)vol_desc->copyright_file_id, sizeof(vol_desc->copyright_file_id), NULL); + convert_to_unicode((u_char *)vol_desc->abstract_file_id, sizeof(vol_desc->abstract_file_id), NULL); + convert_to_unicode((u_char *)vol_desc->bibliographic_file_id, sizeof(vol_desc->bibliographic_file_id), NULL); + + +} + +static void FDECL1(assign_joliet_directory_addresses, struct directory *, node) +{ + int dir_size; + struct directory * dpnt; + + dpnt = node; + + while (dpnt) + { + if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 ) + { + /* + * If we already have an extent for this (i.e. it came from + * a multisession disc), then don't reassign a new extent. + */ + dpnt->jpath_index = next_jpath_index++; + if( dpnt->jextent == 0 ) + { + dpnt->jextent = last_extent; + dir_size = (dpnt->jsize + (SECTOR_SIZE - 1)) >> 11; + last_extent += dir_size; + } + } + + if(dpnt->subdir) + { + assign_joliet_directory_addresses(dpnt->subdir); + } + dpnt = dpnt->next; + } +} + +static +void FDECL1(build_jpathlist, struct directory *, node) +{ + struct directory * dpnt; + + dpnt = node; + + while (dpnt) + + { + if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 ) + { + jpathlist[dpnt->jpath_index] = dpnt; + } + if(dpnt->subdir) build_jpathlist(dpnt->subdir); + dpnt = dpnt->next; + } +} /* build_jpathlist(... */ + +static int FDECL2(joliet_compare_paths, void const *, r, void const *, l) +{ + struct directory const *ll = *(struct directory * const *)l; + struct directory const *rr = *(struct directory * const *)r; + int rparent, lparent; + + rparent = rr->parent->jpath_index; + lparent = ll->parent->jpath_index; + if( rr->parent == reloc_dir ) + { + rparent = rr->self->parent_rec->filedir->jpath_index; + } + + if( ll->parent == reloc_dir ) + { + lparent = ll->self->parent_rec->filedir->jpath_index; + } + + if (rparent < lparent) + { + return -1; + } + + if (rparent > lparent) + { + return 1; + } + + return strcmp(rr->self->name, ll->self->name); + +} /* compare_paths(... */ + +static int generate_joliet_path_tables() +{ + struct directory_entry * de; + struct directory * dpnt; + int fix; + int j; + int namelen; + char * npnt; + char * npnt1; + int tablesize; + + /* + * First allocate memory for the tables and initialize the memory + */ + tablesize = jpath_blocks << 11; + jpath_table_m = (char *) e_malloc(tablesize); + jpath_table_l = (char *) e_malloc(tablesize); + memset(jpath_table_l, 0, tablesize); + memset(jpath_table_m, 0, tablesize); + + /* + * Now start filling in the path tables. Start with root directory + */ + jpath_table_index = 0; + jpathlist = (struct directory **) e_malloc(sizeof(struct directory *) + * next_jpath_index); + memset(jpathlist, 0, sizeof(struct directory *) * next_jpath_index); + build_jpathlist(root); + + do + { + fix = 0; + qsort(&jpathlist[1], next_jpath_index-1, sizeof(struct directory *), + (int (*)(const void *, const void *))joliet_compare_paths); + + for(j=1; jjpath_index != j) + { + jpathlist[j]->jpath_index = j; + fix++; + } + } + } while(fix); + + for(j=1; jde_name; + + npnt1 = strrchr(npnt, PATH_SEPARATOR); + if(npnt1) + { + npnt = npnt1 + 1; + } + + de = dpnt->self; + if(!de) + { + fprintf(stderr,"Fatal goof - directory has amnesia\n"); + exit(1); + } + + namelen = joliet_strlen(de->name); + + if( dpnt == root ) + { + jpath_table_l[jpath_table_index] = 1; + jpath_table_m[jpath_table_index] = 1; + } + else + { + jpath_table_l[jpath_table_index] = namelen; + jpath_table_m[jpath_table_index] = namelen; + } + jpath_table_index += 2; + + set_731(jpath_table_l + jpath_table_index, dpnt->jextent); + set_732(jpath_table_m + jpath_table_index, dpnt->jextent); + jpath_table_index += 4; + + if( dpnt->parent != reloc_dir ) + { + set_721(jpath_table_l + jpath_table_index, + dpnt->parent->jpath_index); + set_722(jpath_table_m + jpath_table_index, + dpnt->parent->jpath_index); + } + else + { + set_721(jpath_table_l + jpath_table_index, + dpnt->self->parent_rec->filedir->jpath_index); + set_722(jpath_table_m + jpath_table_index, + dpnt->self->parent_rec->filedir->jpath_index); + } + + jpath_table_index += 2; + + /* + * The root directory is still represented in non-unicode fashion. + */ + if( dpnt == root ) + { + jpath_table_l[jpath_table_index] = 0; + jpath_table_m[jpath_table_index] = 0; + jpath_table_index ++; + } + else + { + convert_to_unicode((u_char *)jpath_table_l + jpath_table_index, + namelen, de->name); + convert_to_unicode((u_char *)jpath_table_m + jpath_table_index, + namelen, de->name); + jpath_table_index += namelen; + } + + if(jpath_table_index & 1) + { + jpath_table_index++; /* For odd lengths we pad */ + } + } + + free(jpathlist); + if(jpath_table_index != jpath_table_size) + { + fprintf(stderr,"Joliet path table lengths do not match %d %d\n", + jpath_table_index, + jpath_table_size); + } + return 0; +} /* generate_path_tables(... */ + +static void FDECL2(generate_one_joliet_directory, struct directory *, dpnt, FILE *, outfile) +{ + unsigned int dir_index; + char * directory_buffer; + int new_reclen; + struct directory_entry * s_entry; + struct directory_entry * s_entry1; + struct iso_directory_record jrec; + unsigned int total_size; + int cvt_len; + struct directory * finddir; + + total_size = (dpnt->jsize + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1); + directory_buffer = (char *) e_malloc(total_size); + memset(directory_buffer, 0, total_size); + dir_index = 0; + + s_entry = dpnt->jcontents; + while(s_entry) + { + if( (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) == 0 ) + { + /* + * If this entry was a directory that was relocated, we have a bit + * of trouble here. We need to dig out the real thing and put it + * back here. In the Joliet tree, there is no relocated rock + * ridge, as there are no depth limits to a directory tree. + */ + if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 ) + { + for(s_entry1 = reloc_dir->contents; s_entry1; s_entry1 = s_entry1->next) + { + if( s_entry1->parent_rec == s_entry ) + { + break; + } + } + if( s_entry1 == NULL ) + { + /* + * We got trouble. + */ + fprintf(stderr, "Unable to locate relocated directory\n"); + exit(1); + } + } + else + { + s_entry1 = s_entry; + } + + /* + * We do not allow directory entries to cross sector boundaries. + * Simply pad, and then start the next entry at the next sector + */ + new_reclen = s_entry1->jreclen; + if( (dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE ) + { + dir_index = (dir_index + (SECTOR_SIZE - 1)) & + ~(SECTOR_SIZE - 1); + } + + memcpy(&jrec, &s_entry1->isorec, sizeof(struct iso_directory_record) - + sizeof(s_entry1->isorec.name)); + + cvt_len = joliet_strlen(s_entry1->name); + + /* + * Fix the record length - this was the non-Joliet version we + * were seeing. + */ + jrec.name_len[0] = cvt_len; + jrec.length[0] = s_entry1->jreclen; + + /* + * If this is a directory, fix the correct size and extent + * number. + */ + if( (jrec.flags[0] & 2) != 0 ) + { + if(strcmp(s_entry1->name,".") == 0) + { + jrec.name_len[0] = 1; + set_733((char *) jrec.extent, dpnt->jextent); + set_733((char *) jrec.size, ROUND_UP(dpnt->jsize)); + } + else if(strcmp(s_entry1->name,"..") == 0) + { + jrec.name_len[0] = 1; + if( dpnt->parent == reloc_dir ) + { + set_733((char *) jrec.extent, dpnt->self->parent_rec->filedir->jextent); + set_733((char *) jrec.size, ROUND_UP(dpnt->self->parent_rec->filedir->jsize)); + } + else + + { + set_733((char *) jrec.extent, dpnt->parent->jextent); + set_733((char *) jrec.size, ROUND_UP(dpnt->parent->jsize)); + } + } + else + { + if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 ) + { + finddir = reloc_dir->subdir; + } + else + { + finddir = dpnt->subdir; + } + while(1==1) + { + if(finddir->self == s_entry1) break; + finddir = finddir->next; + if(!finddir) + { + fprintf(stderr,"Fatal goof - unable to find directory location\n"); exit(1); + } + } + set_733((char *) jrec.extent, finddir->jextent); + set_733((char *) jrec.size, ROUND_UP(finddir->jsize)); + } + } + + memcpy(directory_buffer + dir_index, &jrec, + sizeof(struct iso_directory_record) - + sizeof(s_entry1->isorec.name)); + + + dir_index += sizeof(struct iso_directory_record) - + sizeof (s_entry1->isorec.name); + + /* + * Finally dump the Unicode version of the filename. + * Note - . and .. are the same as with non-Joliet discs. + */ + if( (jrec.flags[0] & 2) != 0 + && strcmp(s_entry1->name, ".") == 0 ) + { + directory_buffer[dir_index++] = 0; + } + else if( (jrec.flags[0] & 2) != 0 + && strcmp(s_entry1->name, "..") == 0 ) + { + directory_buffer[dir_index++] = 1; + } + else + { + convert_to_unicode((u_char *)directory_buffer + dir_index, + cvt_len, + s_entry1->name); + dir_index += cvt_len; + } + + if(dir_index & 1) + { + directory_buffer[dir_index++] = 0; + } + } + s_entry = s_entry->jnext; + } + + if(dpnt->jsize != dir_index) + { + fprintf(stderr,"Unexpected joliet directory length %d %d %s\n",dpnt->jsize, + dir_index, dpnt->de_name); + } + + xfwrite(directory_buffer, 1, total_size, outfile); + last_extent_written += total_size >> 11; + free(directory_buffer); +} /* generate_one_joliet_directory(... */ + +static int FDECL1(joliet_sort_n_finish, struct directory *, this_dir) +{ + struct directory_entry * s_entry; + int status = 0; + + for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) + { + if( (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0 ) + { + continue; + } + + /* + * First update the path table sizes for directories. + * + * Finally, set the length of the directory entry if Joliet is used. + * The name is longer, but no Rock Ridge is ever used here, so + * depending upon the options the entry size might turn out to be about + * the same. The Unicode name is always a multiple of 2 bytes, so + * we always add 1 to make it an even number. + */ + if(s_entry->isorec.flags[0] == 2) + { + if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) + { + jpath_table_size += joliet_strlen(s_entry->name) + sizeof(struct iso_path_table) - 1; + if (jpath_table_size & 1) + { + jpath_table_size++; + } + } + else + { + if (this_dir == root && strlen(s_entry->name) == 1) + { + jpath_table_size += sizeof(struct iso_path_table); + if (jpath_table_size & 1) jpath_table_size++; + } + } + } + + if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) + { + s_entry->jreclen = sizeof(struct iso_directory_record) + - sizeof(s_entry->isorec.name) + + joliet_strlen(s_entry->name) + + 1; + } + else + { + /* + * Special - for '.' and '..' we generate the same records we + * did for non-Joliet discs. + */ + s_entry->jreclen = sizeof(struct iso_directory_record) + - sizeof(s_entry->isorec.name) + + 1; + } + + + } + + if( (this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) != 0 ) + { + return 0; + } + + this_dir->jcontents = this_dir->contents; + status = joliet_sort_directory(&this_dir->jcontents); + + /* + * Now go through the directory and figure out how large this one will be. + * Do not split a directory entry across a sector boundary + */ + s_entry = this_dir->jcontents; + for(s_entry = this_dir->jcontents; s_entry; s_entry = s_entry->jnext) + { + int jreclen; + + if( (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0 ) + { + continue; + } + + jreclen = s_entry->jreclen; + + if ((this_dir->jsize & (SECTOR_SIZE - 1)) + jreclen >= SECTOR_SIZE) + { + this_dir->jsize = (this_dir->jsize + (SECTOR_SIZE - 1)) & + ~(SECTOR_SIZE - 1); + } + this_dir->jsize += jreclen; + } + return status; +} + +/* + * Similar to the iso9660 case, except here we perform a full sort based upon the + * regular name of the file, not the 8.3 version. + */ +static int FDECL2(joliet_compare_dirs, const void *, rr, const void *, ll) +{ + char * rpnt, *lpnt; + struct directory_entry ** r, **l; + + r = (struct directory_entry **) rr; + l = (struct directory_entry **) ll; + rpnt = (*r)->name; + lpnt = (*l)->name; + + /* + * If the entries are the same, this is an error. + */ + if( strcmp(rpnt, lpnt) == 0 ) + { + sort_goof++; + } + + /* + * Put the '.' and '..' entries on the head of the sorted list. + * For normal ASCII, this always happens to be the case, but out of + * band characters cause this not to be the case sometimes. + */ + if( strcmp(rpnt, ".") == 0 ) return -1; + if( strcmp(lpnt, ".") == 0 ) return 1; + + if( strcmp(rpnt, "..") == 0 ) return -1; + if( strcmp(lpnt, "..") == 0 ) return 1; + + while(*rpnt && *lpnt) + { + if(*rpnt == ';' && *lpnt != ';') return -1; + if(*rpnt != ';' && *lpnt == ';') return 1; + + if(*rpnt == ';' && *lpnt == ';') return 0; + + /* + * Extensions are not special here. Don't treat the dot as something that + * must be bumped to the start of the list. + */ +#if 0 + if(*rpnt == '.' && *lpnt != '.') return -1; + if(*rpnt != '.' && *lpnt == '.') return 1; +#endif + + if(*rpnt < *lpnt) return -1; + if(*rpnt > *lpnt) return 1; + rpnt++; lpnt++; + } + if(*rpnt) return 1; + if(*lpnt) return -1; + return 0; +} + + +/* + * Function: sort_directory + * + * Purpose: Sort the directory in the appropriate ISO9660 + * order. + * + * Notes: Returns 0 if OK, returns > 0 if an error occurred. + */ +static int FDECL1(joliet_sort_directory, struct directory_entry **, sort_dir) +{ + int dcount = 0; + int i, len; + struct directory_entry * s_entry; + struct directory_entry ** sortlist; + + s_entry = *sort_dir; + while(s_entry) + { + dcount++; + s_entry = s_entry->next; + } + + /* + * OK, now we know how many there are. Build a vector for sorting. + */ + sortlist = (struct directory_entry **) + e_malloc(sizeof(struct directory_entry *) * dcount); + + dcount = 0; + s_entry = *sort_dir; + while(s_entry) + { + sortlist[dcount] = s_entry; + dcount++; + s_entry = s_entry->next; + } + + sort_goof = 0; + qsort(sortlist, dcount, sizeof(struct directory_entry *), + (int (*)(const void *, const void *))joliet_compare_dirs); + + /* + * Now reassemble the linked list in the proper sorted order + */ + for(i=0; ijnext = sortlist[i+1]; + } + + sortlist[dcount-1]->jnext = NULL; + *sort_dir = sortlist[0]; + + free(sortlist); + return sort_goof; +} + +int FDECL1(joliet_sort_tree, struct directory *, node) +{ + struct directory * dpnt; + int goof = 0; + + dpnt = node; + + while (dpnt){ + goof = joliet_sort_n_finish(dpnt); + if( goof ) + { + break; + } + if(dpnt->subdir) goof = joliet_sort_tree(dpnt->subdir); + if( goof ) + { + break; + } + dpnt = dpnt->next; + } + return goof; +} + +static void FDECL2(generate_joliet_directories, struct directory *, node, FILE*, outfile){ + struct directory * dpnt; + + dpnt = node; + + while (dpnt) + { + if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 ) + { + /* + * In theory we should never reuse a directory, so this doesn't + * make much sense. + */ + if( dpnt->extent > session_start ) + { + generate_one_joliet_directory(dpnt, outfile); + } + } + if(dpnt->subdir) generate_joliet_directories(dpnt->subdir, outfile); + dpnt = dpnt->next; + } +} + + +/* + * Function to write the EVD for the disc. + */ +static int FDECL1(jpathtab_write, FILE *, outfile) +{ + /* + * Next we write the path tables + */ + xfwrite(jpath_table_l, 1, jpath_blocks << 11, outfile); + xfwrite(jpath_table_m, 1, jpath_blocks << 11, outfile); + last_extent_written += 2*jpath_blocks; + free(jpath_table_l); + free(jpath_table_m); + jpath_table_l = NULL; + jpath_table_m = NULL; + return 0; +} + +static int FDECL1(jdirtree_size, int, starting_extent) +{ + assign_joliet_directory_addresses(root); + return 0; +} + +static int jroot_gen() +{ + jroot_record.length[0] = 1 + sizeof(struct iso_directory_record) + - sizeof(jroot_record.name); + jroot_record.ext_attr_length[0] = 0; + set_733((char *) jroot_record.extent, root->jextent); + set_733((char *) jroot_record.size, ROUND_UP(root->jsize)); + iso9660_date(jroot_record.date, root_statbuf.st_mtime); + jroot_record.flags[0] = 2; + jroot_record.file_unit_size[0] = 0; + jroot_record.interleave[0] = 0; + set_723(jroot_record.volume_sequence_number, DEF_VSN); + jroot_record.name_len[0] = 1; + return 0; +} + +static int FDECL1(jdirtree_write, FILE *, outfile) +{ + generate_joliet_directories(root, outfile); + return 0; +} + +/* + * Function to write the EVD for the disc. + */ +static int FDECL1(jvd_write, FILE *, outfile) +{ + struct iso_primary_descriptor jvol_desc; + + /* + * Next we write out the boot volume descriptor for the disc + */ + jvol_desc = vol_desc; + get_joliet_vol_desc(&jvol_desc); + xfwrite(&jvol_desc, 1, 2048, outfile); + last_extent_written ++; + return 0; +} + +/* + * Functions to describe padding block at the start of the disc. + */ +static int FDECL1(jpathtab_size, int, starting_extent) +{ + jpath_table[0] = starting_extent; + jpath_table[1] = 0; + jpath_table[2] = jpath_table[0] + jpath_blocks; + jpath_table[3] = 0; + + last_extent += 2*jpath_blocks; + return 0; +} + +struct output_fragment joliet_desc = {NULL, oneblock_size, jroot_gen,jvd_write}; +struct output_fragment jpathtable_desc= {NULL, jpathtab_size, generate_joliet_path_tables, jpathtab_write}; +struct output_fragment jdirtree_desc = {NULL, jdirtree_size, NULL, jdirtree_write}; diff --git a/util/mkisofs/mkisofs.c b/util/mkisofs/mkisofs.c index a2e2d1874..3344a921a 100644 --- a/util/mkisofs/mkisofs.c +++ b/util/mkisofs/mkisofs.c @@ -20,16 +20,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: mkisofs.c,v 1.10.1.3 1998/06/02 03:36:16 eric Exp $"; - -/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ +static char rcsid[] ="$Id: mkisofs.c,v 1.29 1998/06/02 03:43:45 eric Exp $"; #include -#include "mkisofs.h" #include "config.h" +#include "mkisofs.h" #ifdef linux #include +#else +#include "getopt.h" #endif #include "iso9660.h" @@ -60,7 +60,7 @@ static char rcsid[] ="$Id: mkisofs.c,v 1.10.1.3 1998/06/02 03:36:16 eric Exp $"; struct directory * root = NULL; -static char version_string[] = "mkisofs v1.11.3"; +static char version_string[] = "mkisofs 1.12b4"; FILE * discimage; unsigned int next_extent = 0; @@ -69,19 +69,30 @@ unsigned int session_start = 0; unsigned int path_table_size = 0; unsigned int path_table[4] = {0,}; unsigned int path_blocks = 0; + + +unsigned int jpath_table_size = 0; +unsigned int jpath_table[4] = {0,}; +unsigned int jpath_blocks = 0; + struct iso_directory_record root_record; +struct iso_directory_record jroot_record; + char * extension_record = NULL; int extension_record_extent = 0; -static int extension_record_size = 0; +int extension_record_size = 0; /* These variables are associated with command line options */ int use_eltorito = 0; int use_RockRidge = 0; -int verbose = 0; +int use_Joliet = 0; +int verbose = 1; int all_files = 0; int follow_links = 0; int rationalize = 0; int generate_tables = 0; +int print_size = 0; +int split_output = 0; char * preparer = PREPARER_DEFAULT; char * publisher = PUBLISHER_DEFAULT; char * appid = APPID_DEFAULT; @@ -101,6 +112,8 @@ int RR_relocation_depth = 6; /* Violates iso9660, but most systems work */ int full_iso9660_filenames = 0; /* Used with Amiga. Disc will not work with DOS */ int allow_leading_dots = 0; /* DOS cannot read names with leading dots */ +int split_SL_component = 1; /* circumvent a bug in the SunOS driver */ +int split_SL_field = 1; /* circumvent a bug in the SunOS */ struct rcopts{ char * tag; @@ -120,6 +133,110 @@ struct rcopts rcopt[] = { {NULL, NULL} }; +/* + * In case it isn't obvious, the option handling code was ripped off from GNU-ld. + */ +struct ld_option +{ + /* The long option information. */ + struct option opt; + /* The short option with the same meaning ('\0' if none). */ + char shortopt; + /* The name of the argument (NULL if none). */ + const char *arg; + /* The documentation string. If this is NULL, this is a synonym for + the previous option. */ + const char *doc; + enum + { + /* Use one dash before long option name. */ + ONE_DASH, + /* Use two dashes before long option name. */ + TWO_DASHES, + /* Don't mention this option in --help output. */ + NO_HELP + } control; +}; + +/* Codes used for the long options with no short synonyms. 150 isn't + special; it's just an arbitrary non-ASCII char value. */ +#define OPTION_HELP 150 +#define OPTION_QUIET 151 +#define OPTION_NOSPLIT_SL_COMPONENT 152 +#define OPTION_NOSPLIT_SL_FIELD 153 +#define OPTION_PRINT_SIZE 154 +#define OPTION_SPLIT_OUTPUT 155 + +static const struct ld_option ld_options[] = +{ + { {"all-files", no_argument, NULL, 'a'}, + 'a', NULL, "Process all files (don't skip backup files)", ONE_DASH }, + { {"appid", required_argument, NULL, 'A'}, + 'A', "ID", "Set Application ID" , ONE_DASH }, + { {"eltorito-boot", required_argument, NULL, 'b'}, + 'b', "FILE", "Set El Torito boot image name" , ONE_DASH }, + { {"eltorito-catalog", required_argument, NULL, 'c'}, + 'c', "FILE", "Set El Torito boot catalog name" , ONE_DASH }, + { {"cdwrite-params", required_argument, NULL, 'C'}, + 'C', "PARAMS", "Magic paramters from cdwrite" , ONE_DASH }, + { {"omit-period", no_argument, NULL, 'd'}, + 'd', NULL, "Omit trailing periods from filenames", ONE_DASH }, + { {"disable-deep-relocation", no_argument, NULL, 'D'}, + 'D', NULL, "Disable deep directory relocation", ONE_DASH }, + { {"follow-links", no_argument, NULL, 'f'}, + 'f', NULL, "Follow symbolic links", ONE_DASH }, + { {"help", no_argument, NULL, OPTION_HELP}, + '\0', NULL, "Print option help", ONE_DASH }, + { {NULL, required_argument, NULL, 'i'}, + 'i', "ADD_FILES", "No longer supported" , TWO_DASHES }, + { {"joliet", no_argument, NULL, 'J'}, + 'J', NULL, "Generate Joliet directory information", ONE_DASH }, + { {"full-iso9660-filenames", no_argument, NULL, 'l'}, + 'l', NULL, "Allow full 32 character filenames for iso9660 names", ONE_DASH }, + { {"allow-leading-dots", no_argument, NULL, 'L'}, + 'L', NULL, "Allow iso9660 filenames to start with '.'", ONE_DASH }, + { {"exclude", required_argument, NULL, 'm'}, + 'm', "GLOBFILE", "Exclude file name" , ONE_DASH }, + { {"prev-session", required_argument, NULL, 'M'}, + 'M', "FILE", "Set path to previous session to merge" , ONE_DASH }, + { {"omit-version-number", no_argument, NULL, 'N'}, + 'N', NULL, "Omit version number from iso9660 filename", ONE_DASH }, + { {"no-split-symlink-components", no_argument, NULL, 0}, + 0, NULL, "Inhibit splitting symlink components" , ONE_DASH }, + { {"no-split-symlink-fields", no_argument, NULL, 0}, + 0, NULL, "Inhibit splitting symlink fields" , ONE_DASH }, + { {"output", required_argument, NULL, 'o'}, + 'o', "FILE", "Set output file name" , ONE_DASH }, + { {"preparer", required_argument, NULL, 'p'}, + 'p', "PREP", "Set Volume preparer" , ONE_DASH }, + { {"print-size", no_argument, NULL, OPTION_PRINT_SIZE}, + '\0', NULL, "Print estimated filesystem size and exit", ONE_DASH }, + { {"publisher", required_argument, NULL, 'P'}, + 'P', "PUB", "Set Volume publisher" , ONE_DASH }, + { {"quiet", no_argument, NULL, OPTION_QUIET}, + '\0', NULL, "Run quietly", ONE_DASH }, + { {"rational-rock", no_argument, NULL, 'r'}, + 'r', NULL, "Generate rationalized Rock Ridge directory information", ONE_DASH }, + { {"rock", no_argument, NULL, 'R'}, + 'R', NULL, "Generate Rock Ridge directory information", ONE_DASH }, + { {"split-output", no_argument, NULL, OPTION_SPLIT_OUTPUT}, + '\0', NULL, "Split output into files of approx. 1GB size", ONE_DASH }, + { {"translation-table", no_argument, NULL, 'T'}, + 'T', NULL, "Generate translation tables for systems that don't understand long filenames", ONE_DASH }, + { {"verbose", no_argument, NULL, 'v'}, + 'v', NULL, "Verbose", ONE_DASH }, + { {"volid", required_argument, NULL, 'V'}, + 'V', "ID", "Set Volume ID" , ONE_DASH }, + { {"old-exclude", required_argument, NULL, 'x'}, + 'x', "FILE", "Exclude file name(depreciated)" , ONE_DASH } +#ifdef ERIC_neverdef + { {"transparent-compression", no_argument, NULL, 'z'}, + 'z', NULL, "Enable transparent compression of files", ONE_DASH }, +#endif +}; + +#define OPTION_COUNT (sizeof ld_options / sizeof ld_options[0]) + #if defined(ultrix) || defined(_AUX_SOURCE) char *strdup(s) char *s;{char *c;if(c=(char *)malloc(strlen(s)+1))strcpy(c,s);return c;} @@ -179,7 +296,11 @@ void FDECL1(read_rcfile, char *, appname) } if (!rcfile) return; - fprintf(stderr, "Using \"%s\"\n", filename); + if ( verbose > 0 ) + { + fprintf(stderr, "Using \"%s\"\n", filename); + } + /* OK, we got it. Now read in the lines and parse them */ linum = 0; while (fgets(linebuffer, sizeof(linebuffer), rcfile)) @@ -260,20 +381,113 @@ void FDECL1(read_rcfile, char *, appname) char * path_table_l = NULL; char * path_table_m = NULL; + +char * jpath_table_l = NULL; +char * jpath_table_m = NULL; + int goof = 0; +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + void usage(){ + const char * program_name = "mkisofs"; +#if 0 fprintf(stderr,"Usage:\n"); fprintf(stderr, "mkisofs [-o outfile] [-R] [-V volid] [-v] [-a] \ [-T]\n [-l] [-d] [-V] [-D] [-L] [-p preparer]" -#ifdef ADD_FILES -"[-i file] \n" -#endif "[-P publisher] [ -A app_id ] [-z] \n \ [-b boot_image_name] [-c boot_catalog-name] \ [-x path -x path ...] path\n"); - exit(1); +#endif + + int i; + const char **targets, **pp; + + fprintf (stderr, "Usage: %s [options] file...\n", program_name); + + fprintf (stderr, "Options:\n"); + for (i = 0; i < OPTION_COUNT; i++) + { + if (ld_options[i].doc != NULL) + { + int comma; + int len; + int j; + + fprintf (stderr, " "); + + comma = FALSE; + len = 2; + + j = i; + do + { + if (ld_options[j].shortopt != '\0' + && ld_options[j].control != NO_HELP) + { + fprintf (stderr, "%s-%c", comma ? ", " : "", ld_options[j].shortopt); + len += (comma ? 2 : 0) + 2; + if (ld_options[j].arg != NULL) + { + if (ld_options[j].opt.has_arg != optional_argument) + { + fprintf (stderr, " "); + ++len; + } + fprintf (stderr, "%s", ld_options[j].arg); + len += strlen (ld_options[j].arg); + } + comma = TRUE; + } + ++j; + } + while (j < OPTION_COUNT && ld_options[j].doc == NULL); + + j = i; + do + { + if (ld_options[j].opt.name != NULL + && ld_options[j].control != NO_HELP) + { + fprintf (stderr, "%s-%s%s", + comma ? ", " : "", + ld_options[j].control == TWO_DASHES ? "-" : "", + ld_options[j].opt.name); + len += ((comma ? 2 : 0) + + 1 + + (ld_options[j].control == TWO_DASHES ? 1 : 0) + + strlen (ld_options[j].opt.name)); + if (ld_options[j].arg != NULL) + { + fprintf (stderr, " %s", ld_options[j].arg); + len += 1 + strlen (ld_options[j].arg); + } + comma = TRUE; + } + ++j; + } + while (j < OPTION_COUNT && ld_options[j].doc == NULL); + + if (len >= 30) + { + fprintf (stderr, "\n"); + len = 0; + } + + for (; len < 30; len++) + fputc (' ', stderr); + + fprintf (stderr, "%s\n", ld_options[i].doc); + } + } + exit(1); } @@ -326,15 +540,18 @@ extern char * cdwrite_data; int FDECL2(main, int, argc, char **, argv){ char * outfile; struct directory_entry de; +#ifdef HAVE_SBRK unsigned long mem_start; +#endif struct stat statbuf; char * scan_tree; char * merge_image = NULL; struct iso_directory_record * mrootp = NULL; + struct output_fragment * opnt; + int longind; + char shortopts[OPTION_COUNT * 3 + 2]; + struct option longopts[OPTION_COUNT + 1]; int c; -#ifdef ADD_FILES - char *add_file_file = NULL; -#endif if (argc < 2) usage(); @@ -343,9 +560,56 @@ int FDECL2(main, int, argc, char **, argv){ read_rcfile(argv[0]); outfile = NULL; - while ((c = getopt(argc, argv, "i:o:V:RrfvaTp:P:b:c:x:dDlLNzA:M:m:C:")) != EOF) + + /* + * Copy long option initialization from GNU-ld. + */ + /* Starting the short option string with '-' is for programs that + expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. */ + { + int i, is, il; + shortopts[0] = '-'; + is = 1; + il = 0; + for (i = 0; i < OPTION_COUNT; i++) + { + if (ld_options[i].shortopt != '\0') + { + shortopts[is] = ld_options[i].shortopt; + ++is; + if (ld_options[i].opt.has_arg == required_argument + || ld_options[i].opt.has_arg == optional_argument) + { + shortopts[is] = ':'; + ++is; + if (ld_options[i].opt.has_arg == optional_argument) + { + shortopts[is] = ':'; + ++is; + } + } + } + if (ld_options[i].opt.name != NULL) + { + longopts[il] = ld_options[i].opt; + ++il; + } + } + shortopts[is] = '\0'; + longopts[il].name = NULL; + } + + while ((c = getopt_long_only (argc, argv, shortopts, longopts, &longind)) != EOF) switch (c) { + case 1: + /* + * A filename that we take as input. + */ + optind--; + goto parse_input_files; case 'C': /* * This is a temporary hack until cdwrite gets the proper hooks in @@ -353,6 +617,13 @@ int FDECL2(main, int, argc, char **, argv){ */ cdwrite_data = optarg; break; + case 'i': + fprintf(stderr, "-i option no longer supported.\n"); + exit(1); + break; + case 'J': + use_Joliet++; + break; case 'a': all_files++; break; @@ -388,14 +659,6 @@ int FDECL2(main, int, argc, char **, argv){ case 'f': follow_links++; break; - case 'i': -#ifdef ADD_FILES - add_file_file = optarg; - break; -#else - usage(); - exit(1); -#endif case 'l': full_iso9660_filenames++; break; @@ -418,6 +681,9 @@ int FDECL2(main, int, argc, char **, argv){ exit(1); }; break; + case OPTION_PRINT_SIZE: + print_size++; + break; case 'P': publisher = optarg; if(strlen(publisher) > 128) { @@ -425,6 +691,9 @@ int FDECL2(main, int, argc, char **, argv){ exit(1); }; break; + case OPTION_QUIET: + verbose = 0; + break; case 'R': use_RockRidge++; break; @@ -432,6 +701,9 @@ int FDECL2(main, int, argc, char **, argv){ rationalize++; use_RockRidge++; break; + case OPTION_SPLIT_OUTPUT: + split_output++; + break; case 'T': generate_tables++; break; @@ -449,16 +721,32 @@ int FDECL2(main, int, argc, char **, argv){ transparent_compression++; #endif break; + case 'x': case 'm': + /* + * Somehow two options to do basically the same thing got added somewhere along + * the way. The 'match' code supports limited globbing, so this is the one + * that got selected. Unfortunately the 'x' switch is probably more intuitive. + */ add_match(optarg); break; - case 'x': - exclude(optarg); + case OPTION_HELP: + usage (); + exit (0); + break; + case OPTION_NOSPLIT_SL_COMPONENT: + split_SL_component = 0; + break; + case OPTION_NOSPLIT_SL_FIELD: + split_SL_field = 0; break; default: usage(); exit(1); } + +parse_input_files: + #ifdef __NetBSD__ { int resource; @@ -476,7 +764,7 @@ int FDECL2(main, int, argc, char **, argv){ mem_start = (unsigned long) sbrk(0); #endif - if(verbose) fprintf(stderr,"%s\n", version_string); + if(verbose > 1) fprintf(stderr,"%s\n", version_string); if( (cdwrite_data != NULL && merge_image == NULL) || (cdwrite_data == NULL && merge_image != NULL) ) @@ -489,12 +777,6 @@ int FDECL2(main, int, argc, char **, argv){ scan_tree = argv[optind]; -#ifdef ADD_FILES - if (add_file_file) { - add_file(add_file_file); - } - add_file_list (argc, argv, optind+1); -#endif if(!scan_tree){ usage(); @@ -557,28 +839,186 @@ int FDECL2(main, int, argc, char **, argv){ } /* - * Scan the actual directory (and any we find below it) - * for files to write out to the output image. + * Create an empty root directory. If we ever scan it for real, we will fill in the + * contents. */ - if (!scan_directory_tree(argv[optind], &de, mrootp)) + find_or_create_directory(NULL, "", &de, TRUE); + + /* + * Scan the actual directory (and any we find below it) + * for files to write out to the output image. Note - we + * take multiple source directories and keep merging them + * onto the image. + */ + while(optind < argc) { - exit(1); + char * node; + struct directory * graft_dir; + struct stat st; + char * short_name; + int status; + char graft_point[1024]; + + /* + * We would like a syntax like: + * + * /tmp=/usr/tmp/xxx + * + * where the user can specify a place to graft each + * component of the tree. To do this, we may have to create + * directories along the way, of course. + * Secondly, I would like to allow the user to do something + * like: + * + * /home/baz/RMAIL=/u3/users/baz/RMAIL + * + * so that normal files could also be injected into the tree + * at an arbitrary point. + * + * The idea is that the last component of whatever is being + * entered would take the name from the last component of + * whatever the user specifies. + * + * The default will be that the file is injected at the + * root of the image tree. + */ + node = strchr(argv[optind], '='); + short_name = NULL; + + if( node != NULL ) + { + char * pnt; + char * xpnt; + + *node = '\0'; + strcpy(graft_point, argv[optind]); + *node = '='; + node++; + + graft_dir = root; + xpnt = graft_point; + if( *xpnt == PATH_SEPARATOR ) + { + xpnt++; + } + + /* + * Loop down deeper and deeper until we + * find the correct insertion spot. + */ + while(1==1) + { + pnt = strchr(xpnt, PATH_SEPARATOR); + if( pnt == NULL ) + { + if( *xpnt != '\0' ) + { + short_name = xpnt; + } + break; + } + *pnt = '\0'; + graft_dir = find_or_create_directory(graft_dir, + graft_point, + NULL, TRUE); + *pnt = PATH_SEPARATOR; + xpnt = pnt + 1; + } + } + else + { + graft_dir = root; + node = argv[optind]; + } + + /* + * Now see whether the user wants to add a regular file, + * or a directory at this point. + */ + status = stat_filter(node, &st); + if( status != 0 ) + { + /* + * This is a fatal error - the user won't be getting what + * they want if we were to proceed. + */ + fprintf(stderr, "Invalid node - %s\n", node); + exit(1); + } + else + { + if( S_ISDIR(st.st_mode) ) + { + if (!scan_directory_tree(graft_dir, node, &de)) + { + exit(1); + } + } + else + { + if( short_name == NULL ) + { + short_name = strrchr(node, PATH_SEPARATOR); + if( short_name == NULL || short_name < node ) + { + short_name = node; + } + else + { + short_name++; + } + } + if( !insert_file_entry(graft_dir, node, short_name) ) + { + exit(1); + } + } + } + + optind++; + } + + + /* + * Now merge in any previous sessions. This is driven on the source + * side, since we may need to create some additional directories. + */ + if( merge_image != NULL ) + { + merge_previous_session(root, mrootp); } /* - * Fix a couple of things in the root directory so that everything - * is self consistent. + * Sort the directories in the required order (by ISO9660). Also, + * choose the names for the 8.3 filesystem if required, and do + * any other post-scan work. */ - root->self = root->contents; /* Fix this up so that the path tables get done right */ + goof += sort_tree(root); - if(reloc_dir) sort_n_finish(reloc_dir); + if( use_Joliet ) + { + goof += joliet_sort_tree(root); + } if (goof) exit(1); + /* + * Fix a couple of things in the root directory so that everything + * is self consistent. + */ + root->self = root->contents; /* Fix this up so that the path + tables get done right */ + /* * OK, ready to write the file. Open it up, and generate the thing. */ - if (outfile){ + if (print_size){ + discimage = fopen("/dev/null", "w"); + if (!discimage){ + fprintf(stderr,"Unable to open /dev/null\n"); + exit(1); + } + } else if (outfile){ discimage = fopen(outfile, "w"); if (!discimage){ fprintf(stderr,"Unable to open disc image file\n"); @@ -593,54 +1033,120 @@ int FDECL2(main, int, argc, char **, argv){ path_blocks = (path_table_size + (SECTOR_SIZE - 1)) >> 11; if (path_blocks & 1) path_blocks++; - path_table[0] = session_start + 0x10 + 2 + (use_eltorito ? 1 : 0); - path_table[1] = 0; - path_table[2] = path_table[0] + path_blocks; - path_table[3] = 0; + jpath_blocks = (jpath_table_size + (SECTOR_SIZE - 1)) >> 11; + if (jpath_blocks & 1) jpath_blocks++; - last_extent += path_table[2] - session_start + path_blocks; - /* The next free block */ + /* + * Start to set up the linked list that we use to track the + * contents of the disc. + */ + outputlist_insert(&padblock_desc); - /* The next step is to go through the directory tree and assign extent - numbers for all of the directories */ + /* + * PVD for disc. + */ + outputlist_insert(&voldesc_desc); - assign_directory_addresses(root); + /* + * SVD for El Torito. MUST be immediately after the PVD! + */ + if( use_eltorito) + { + outputlist_insert(&torito_desc); + } - if(extension_record) { - struct directory_entry * s_entry; - extension_record_extent = last_extent++; - s_entry = root->contents; - set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 24, - extension_record_extent); - set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 8, - extension_record_size); - }; + /* + * SVD for Joliet. + */ + if( use_Joliet) + { + outputlist_insert(&joliet_desc); + } - if (use_RockRidge && reloc_dir) - finish_cl_pl_entries(); + /* + * Finally the last volume desctiptor. + */ + outputlist_insert(&end_vol); - /* Now we generate the path tables that are used by DOS to improve directory - access times. */ - generate_path_tables(); - /* Generate root record for volume descriptor. */ - generate_root_record(); + outputlist_insert(&pathtable_desc); + if( use_Joliet) + { + outputlist_insert(&jpathtable_desc); + } - if (verbose) - dump_tree(root); + outputlist_insert(&dirtree_desc); + if( use_Joliet) + { + outputlist_insert(&jdirtree_desc); + } + + outputlist_insert(&dirtree_clean); + + if(extension_record) + { + outputlist_insert(&extension_desc); + } + + outputlist_insert(&files_desc); + + /* + * Allow room for the various headers we will be writing. There + * will always be a primary and an end volume descriptor. + */ + last_extent = session_start; + + /* + * Calculate the size of all of the components of the disc, and assign + * extent numbers. + */ + for(opnt = out_list; opnt; opnt = opnt->of_next ) + { + if( opnt->of_size != NULL ) + { + (*opnt->of_size)(last_extent); + } + } + + /* + * Generate the contents of any of the sections that we want to generate. + * Not all of the fragments will do anything here - most will generate the + * data on the fly when we get to the write pass. + */ + for(opnt = out_list; opnt; opnt = opnt->of_next ) + { + if( opnt->of_generate != NULL ) + { + (*opnt->of_generate)(); + } + } if( in_image != NULL ) { fclose(in_image); } - iso_write(discimage); + /* + * Now go through the list of fragments and write the data that corresponds to + * each one. + */ + for(opnt = out_list; opnt; opnt = opnt->of_next ) + { + if( opnt->of_write != NULL ) + { + (*opnt->of_write)(discimage); + } + } + if( verbose > 0 ) + { #ifdef HAVE_SBRK - fprintf(stderr,"Max brk space used %x\n", - (unsigned int)(((unsigned long)sbrk(0)) - mem_start)); + fprintf(stderr,"Max brk space used %x\n", + (unsigned int)(((unsigned long)sbrk(0)) - mem_start)); #endif - fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9); + fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9); + } + #ifdef VMS return 1; #else diff --git a/util/mkisofs/mkisofs.h b/util/mkisofs/mkisofs.h index bc264d99a..b512a2865 100644 --- a/util/mkisofs/mkisofs.h +++ b/util/mkisofs/mkisofs.h @@ -20,11 +20,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* - * $Id: mkisofs.h,v 1.5 1997/05/17 15:50:28 eric Exp $ + * $Id: mkisofs.h,v 1.17 1998/06/02 02:40:38 eric Exp $ */ -/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ - #include /* This symbol is used to indicate that we do not have things like @@ -41,16 +39,39 @@ #ifdef VMS #include #define dirent direct -#else -#include #endif +#ifdef _WIN32 +#define NON_UNIXFS +#endif /* _WIN32 */ + #include #include #include -#ifdef linux -#include +#if defined(HAVE_DIRENT_H) +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if defined(HAVE_SYS_NDIR_H) +# include +# endif +# if defined(HAVE_SYS_DIR_H) +# include +# endif +# if defined(HAVE_NDIR_H) +# include +# endif +#endif + +#if defined(HAVE_STRING_H) +#include +#else +#if defined(HAVE_STRINGS_H) +#include +#endif #endif #ifdef ultrix @@ -100,10 +121,12 @@ extern char *optarg; struct directory_entry{ struct directory_entry * next; + struct directory_entry * jnext; struct iso_directory_record isorec; unsigned int starting_block; unsigned int size; - unsigned int priority; + unsigned short priority; + unsigned char jreclen; /* Joliet record len */ char * name; char * table; char * whole_name; @@ -125,6 +148,52 @@ struct file_hash{ unsigned int size; }; + +/* + * This structure is used to control the output of fragments to the cdrom + * image. Everything that will be written to the output image will eventually + * go through this structure. There are two pieces - first is the sizing where + * we establish extent numbers for everything, and the second is when we actually + * generate the contents and write it to the output image. + * + * This makes it trivial to extend mkisofs to write special things in the image. + * All you need to do is hook an additional structure in the list, and the rest + * works like magic. + * + * The three passes each do the following: + * + * The 'size' pass determines the size of each component and assigns the extent number + * for that component. + * + * The 'generate' pass will adjust the contents and pointers as required now that extent + * numbers are assigned. In some cases, the contents of the record are also generated. + * + * The 'write' pass actually writes the data to the disc. + */ +struct output_fragment +{ + struct output_fragment * of_next; + int (*of_size)(int); + int (*of_generate)(void); + int (*of_write)(FILE *); +}; + +extern struct output_fragment * out_list; +extern struct output_fragment * out_tail; + +extern struct output_fragment padblock_desc; +extern struct output_fragment voldesc_desc; +extern struct output_fragment joliet_desc; +extern struct output_fragment torito_desc; +extern struct output_fragment end_vol; +extern struct output_fragment pathtable_desc; +extern struct output_fragment jpathtable_desc; +extern struct output_fragment dirtree_desc; +extern struct output_fragment dirtree_clean; +extern struct output_fragment jdirtree_desc; +extern struct output_fragment extension_desc; +extern struct output_fragment files_desc; + /* * This structure describes one complete directory. It has pointers * to other directories in the overall tree so that it is clear where @@ -138,6 +207,7 @@ struct directory{ struct directory * subdir; /* First subdirectory in this directory */ struct directory * parent; struct directory_entry * contents; + struct directory_entry * jcontents; struct directory_entry * self; char * whole_name; /* Entire path */ char * de_name; /* Entire path */ @@ -145,7 +215,12 @@ struct directory{ unsigned int depth; unsigned int size; unsigned int extent; + unsigned int jsize; + unsigned int jextent; unsigned short path_index; + unsigned short jpath_index; + unsigned short dir_flags; + unsigned short dir_nlink; }; struct deferred{ @@ -163,57 +238,82 @@ extern unsigned int next_extent; extern unsigned int last_extent; extern unsigned int last_extent_written; extern unsigned int session_start; + extern unsigned int path_table_size; extern unsigned int path_table[4]; extern unsigned int path_blocks; extern char * path_table_l; extern char * path_table_m; + +extern unsigned int jpath_table_size; +extern unsigned int jpath_table[4]; +extern unsigned int jpath_blocks; +extern char * jpath_table_l; +extern char * jpath_table_m; + extern struct iso_directory_record root_record; +extern struct iso_directory_record jroot_record; extern int use_eltorito; extern int use_RockRidge; +extern int use_Joliet; extern int rationalize; extern int follow_links; extern int verbose; extern int all_files; extern int generate_tables; +extern int print_size; +extern int split_output; extern int omit_period; extern int omit_version_number; extern int transparent_compression; extern int RR_relocation_depth; extern int full_iso9660_filenames; +extern int split_SL_component; +extern int split_SL_field; /* tree.c */ extern int DECL(stat_filter, (char *, struct stat *)); -extern void DECL(sort_n_finish,(struct directory *)); -extern void finish_cl_pl_entries(); -extern int DECL(scan_directory_tree,(char * path, - struct directory_entry * self, - struct iso_directory_record *)); +extern int DECL(lstat_filter, (char *, struct stat *)); +extern int DECL(sort_tree,(struct directory *)); +extern struct directory * + DECL(find_or_create_directory,(struct directory *, const char *, + struct directory_entry * self, int)); +extern void DECL (finish_cl_pl_entries, (void)); +extern int DECL(scan_directory_tree,(struct directory * this_dir, + char * path, + struct directory_entry * self)); +extern int DECL(insert_file_entry,(struct directory *, char *, + char *)); + extern void DECL(generate_iso9660_directories,(struct directory *, FILE*)); extern void DECL(dump_tree,(struct directory * node)); extern struct directory_entry * DECL(search_tree_file, (struct directory * node,char * filename)); +extern void DECL(update_nlink_field,(struct directory * node)); +extern void DECL (init_fstatbuf, (void)); +extern struct stat root_statbuf; /* eltorito.c */ extern void DECL(init_boot_catalog, (const char * path )); extern void DECL(get_torito_desc, (struct eltorito_boot_descriptor * path )); /* write.c */ -extern void DECL(assign_directory_addresses,(struct directory * root)); extern int DECL(get_733,(char *)); extern int DECL(isonum_733,(unsigned char *)); extern void DECL(set_723,(char *, unsigned int)); extern void DECL(set_731,(char *, unsigned int)); extern void DECL(set_721,(char *, unsigned int)); extern void DECL(set_733,(char *, unsigned int)); -extern void DECL(sort_directory,(struct directory_entry **)); -extern void generate_root_record(); +extern int DECL(sort_directory,(struct directory_entry **)); extern void DECL(generate_one_directory,(struct directory *, FILE*)); -extern void generate_path_tables(); -extern int DECL(iso_write,(FILE * outfile)); extern void DECL(memcpy_max, (char *, char *, int)); - +extern int DECL(oneblock_size, (int starting_extent)); +extern struct iso_primary_descriptor vol_desc; +extern void DECL(xfwrite, (void * buffer, int count, int size, FILE * file)); +extern void DECL(set_732, (char * pnt, unsigned int i)); +extern void DECL(set_722, (char * pnt, unsigned int i)); +extern void DECL(outputlist_insert, (struct output_fragment * frag)); /* multi.c */ @@ -228,6 +328,12 @@ extern struct directory_entry ** extern void DECL(merge_remaining_entries, (struct directory *, struct directory_entry **, int)); +extern int + DECL(merge_previous_session, (struct directory *, + struct iso_directory_record *)); + +/* joliet.c */ +int DECL(joliet_sort_tree, (struct directory * node)); /* match.c */ extern int DECL(matches, (char *)); @@ -245,7 +351,7 @@ extern void DECL(add_hash,(struct directory_entry *)); extern struct file_hash * DECL(find_hash,(dev_t, ino_t)); extern void DECL(add_directory_hash,(dev_t, ino_t)); extern struct file_hash * DECL(find_directory_hash,(dev_t, ino_t)); -extern void flush_file_hash(); +extern void DECL (flush_file_hash, (void)); extern int DECL(delete_file_hash,(struct directory_entry *)); extern struct directory_entry * DECL(find_file_hash,(char *)); extern void DECL(add_file_hash,(struct directory_entry *)); @@ -320,7 +426,13 @@ extern void * DECL(e_malloc,(size_t)); * is set for all entries in a directory, it means we can just * reuse the TRANS.TBL and not generate a new one. */ -#define SAFE_TO_REUSE_TABLE_ENTRY 1 +#define SAFE_TO_REUSE_TABLE_ENTRY 0x01 +#define DIR_HAS_DOT 0x02 +#define DIR_HAS_DOTDOT 0x04 +#define INHIBIT_JOLIET_ENTRY 0x08 +#define INHIBIT_RR_ENTRY 0x10 +#define RELOCATED_DIRECTORY 0x20 + /* * Volume sequence number to use in all of the iso directory records. */ diff --git a/util/mkisofs/multi.c b/util/mkisofs/multi.c index 13ba6f6d1..e49d1c34e 100644 --- a/util/mkisofs/multi.c +++ b/util/mkisofs/multi.c @@ -19,7 +19,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: multi.c,v 1.6.1.3 1998/06/02 03:00:25 eric Exp $"; +static char rcsid[] ="$Id: multi.c,v 1.12 1998/06/02 02:40:38 eric Exp $"; #include #include @@ -137,7 +137,7 @@ FDECL3(parse_rr, unsigned char *, pnt, int, len, struct directory_entry *,dpnt) while(len >= 4){ if(pnt[3] != 1) { - printf("**BAD RRVERSION"); + fprintf(stderr,"**BAD RRVERSION"); return -1; }; if(strncmp((char *) pnt, "NM", 2) == 0) { @@ -193,7 +193,7 @@ FDECL4(check_rr_dates, struct directory_entry *, dpnt, */ while(len >= 4){ if(pnt[3] != 1) { - printf("**BAD RRVERSION"); + fprintf(stderr,"**BAD RRVERSION"); return -1; }; @@ -750,6 +750,7 @@ void FDECL3(merge_remaining_entries, struct directory *, this_dir, struct directory_entry * s_entry; unsigned int ttbl_extent = 0; unsigned int ttbl_index = 0; + char whole_path[1024]; /* * Whatever is leftover in the list needs to get merged back @@ -762,6 +763,18 @@ void FDECL3(merge_remaining_entries, struct directory *, this_dir, continue; } + if( pnt[i]->name != NULL && pnt[i]->whole_name == NULL) + { + /* + * Set the name for this directory. + */ + strcpy(whole_path, this_dir->de_name); + strcat(whole_path, SPATH_SEPARATOR); + strcat(whole_path, pnt[i]->name); + + pnt[i]->whole_name = strdup(whole_path); + } + if( pnt[i]->name != NULL && strcmp(pnt[i]->name, "") == 0 ) { @@ -884,6 +897,7 @@ FDECL2(merge_old_directory_into_tree, struct directory_entry *, dpnt, char whole_path[1024]; this_dir = (struct directory *) e_malloc(sizeof(struct directory)); + memset(this_dir, 0, sizeof(struct directory)); this_dir->next = NULL; this_dir->subdir = NULL; this_dir->self = dpnt; @@ -939,8 +953,23 @@ FDECL2(merge_old_directory_into_tree, struct directory_entry *, dpnt, if( (contents[i]->isorec.flags[0] & 2) != 0 ) { memset(contents[i]->isorec.extent, 0, 8); + + if( strcmp(contents[i]->name, ".") == 0 ) + this_dir->dir_flags |= DIR_HAS_DOT; + + if( strcmp(contents[i]->name, "..") == 0 ) + this_dir->dir_flags |= DIR_HAS_DOTDOT; } + /* + * Set the whole name for this file. + */ + strcpy(whole_path, this_dir->whole_name); + strcat(whole_path, SPATH_SEPARATOR); + strcat(whole_path, contents[i]->name); + + contents[i]->whole_name = strdup(whole_path); + contents[i]->next = this_dir->contents; contents[i]->filedir = this_dir; this_dir->contents = contents[i]; @@ -957,7 +986,13 @@ FDECL2(merge_old_directory_into_tree, struct directory_entry *, dpnt, */ merge_remaining_entries(this_dir, contents, n_orig); free_mdinfo(contents, n_orig); +#if 0 + /* + * This is no longer required. The post-scan sort will handle + * all of this for us. + */ sort_n_finish(this_dir); +#endif return 0; } @@ -1016,3 +1051,99 @@ FDECL1(get_session_start, int *, file_addr) return 0; } +/* + * This function scans the directory tree, looking for files, and it makes + * note of everything that is found. We also begin to construct the ISO9660 + * directory entries, so that we can determine how large each directory is. + */ + +int +FDECL2(merge_previous_session,struct directory *, this_dir, + struct iso_directory_record *, mrootp) +{ + struct directory_entry **orig_contents = NULL; + struct directory_entry * odpnt = NULL; + int n_orig; + struct directory_entry * s_entry; + int dflag; + int status, lstatus; + struct stat statbuf, lstatbuf; + + /* + * Parse the same directory in the image that we are merging + * for multisession stuff. + */ + orig_contents = read_merging_directory(mrootp, &n_orig); + if( orig_contents == NULL ) + { + return 0; + } + + +/* Now we scan the directory itself, and look at what is inside of it. */ + + dflag = 0; + for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) + { + status = stat_filter(s_entry->whole_name, &statbuf); + lstatus = lstat_filter(s_entry->whole_name, &lstatbuf); + + /* + * We always should create an entirely new directory tree whenever + * we generate a new session, unless there were *no* changes whatsoever + * to any of the directories, in which case it would be kind of pointless + * to generate a new session. + * + * I believe it is possible to rigorously prove that any change anywhere + * in the filesystem will force the entire tree to be regenerated + * because the modified directory will get a new extent number. Since + * each subdirectory of the changed directory has a '..' entry, all of + * them will need to be rewritten too, and since the parent directory + * of the modified directory will have an extent pointer to the directory + * it too will need to be rewritten. Thus we will never be able to reuse + * any directory information when writing new sessions. + * + * We still check the previous session so we can mark off the equivalent + * entry in the list we got from the original disc, however. + */ + + /* + * The check_prev_session function looks for an identical entry in + * the previous session. If we see it, then we copy the extent + * number to s_entry, and cross it off the list. + */ + check_prev_session(orig_contents, n_orig, s_entry, + &statbuf, &lstatbuf, &odpnt); + + if(S_ISDIR(statbuf.st_mode) && odpnt != NULL) + { + int dflag; + + if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) + { + struct directory * child; + + child = find_or_create_directory(this_dir, + s_entry->whole_name, + s_entry, 1); + dflag = merge_previous_session(child, + &odpnt->isorec); + /* If unable to scan directory, mark this as a non-directory */ + if(!dflag) + lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG; + free(odpnt); + odpnt = NULL; + } + } + } + + /* + * Whatever is left over, are things which are no longer in the tree + * on disk. We need to also merge these into the tree. + */ + merge_remaining_entries(this_dir, orig_contents, n_orig); + free_mdinfo(orig_contents, n_orig); + + return 1; +} + diff --git a/util/mkisofs/name.c b/util/mkisofs/name.c index 10475d43e..fb88fc9d0 100644 --- a/util/mkisofs/name.c +++ b/util/mkisofs/name.c @@ -21,8 +21,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: name.c,v 1.7 1997/11/09 16:42:51 eric Exp $"; +static char rcsid[] ="$Id: name.c,v 1.10 1998/06/02 02:40:38 eric Exp $"; +#include "config.h" #include "mkisofs.h" #include @@ -105,8 +106,7 @@ int FDECL3(iso9660_file_length, last_dot = strrchr (pnt,'.'); if( (last_dot != NULL) && ( (last_dot[1] == '~') - || (last_dot[1] == '\0') - || (last_dot[1] == '\0')) ) + || (last_dot[1] == '\0')) ) { c = last_dot; *c = '\0'; @@ -154,13 +154,19 @@ int FDECL3(iso9660_file_length, * a silly thing to do on a Unix box, but we check for it * anyways. If we see this, then we don't have to add our * own version number at the end. + * UNLESS the ';' is part of the filename and no version + * number is following. [VK] */ - if(*pnt == ';') - { - seen_semic = 1; - *result++ = *pnt++; - continue; - } + if(*pnt == ';') + { + /* [VK] */ + if (pnt[1] != '\0' && (pnt[1] < '0' || pnt[1] > '9')) + { + pnt++; + ignore++; + continue; + } + } /* * If we have a name with multiple '.' characters, we ignore everything diff --git a/util/mkisofs/rock.c b/util/mkisofs/rock.c index 47cba5527..d851b96fb 100644 --- a/util/mkisofs/rock.c +++ b/util/mkisofs/rock.c @@ -19,7 +19,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: rock.c,v 1.3 1997/05/17 15:45:26 eric Exp $"; +static char rcsid[] ="$Id: rock.c,v 1.7 1998/02/18 04:48:23 eric Exp $"; #include @@ -225,7 +225,7 @@ int deep_opt; Rock[ipnt++] = PN_SIZE; Rock[ipnt++] = SU_VERSION; flagval |= (1<<1); -#if !defined(MAJOR_IN_SYSMACROS) && !defined(MAJOR_IN_MKDEV) +#if defined(MAJOR_IN_SYSMACROS) || defined(MAJOR_IN_MKDEV) set_733((char*)Rock + ipnt, major(lstatbuf->st_rdev )); ipnt += 8; set_733((char*)Rock + ipnt, minor(lstatbuf->st_rdev)); @@ -268,10 +268,36 @@ int deep_opt; unsigned char * cpnt, *cpnt1; nchar = readlink(whole_name, symlink_buff, sizeof(symlink_buff)); symlink_buff[nchar < 0 ? 0 : nchar] = 0; + nchar = strlen((char *) symlink_buff); set_733(s_entry->isorec.size, 0); cpnt = &symlink_buff[0]; flagval |= (1<<2); + if (! split_SL_field) + { + int sl_bytes = 0; + for (cpnt1 = cpnt; *cpnt1 != '\0'; cpnt1++) + { + if (*cpnt1 == '/') + { + sl_bytes += 4; + } + else + { + sl_bytes += 1; + } + } + if (sl_bytes > 250) + { + /* + * the symbolic link won't fit into one SL System Use Field + * print an error message and continue with splited one + */ + fprintf(stderr,"symbolic link ``%s'' to long for one SL System Use Field, splitting", cpnt); + } + if(MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes)) add_CE_entry(); + } + while(nchar){ if(MAYBE_ADD_CE_ENTRY(SL_SIZE)) add_CE_entry(); Rock[ipnt++] ='S'; @@ -309,15 +335,18 @@ int deep_opt; } else { /* If we do not have enough room for a component, start a new continuations segment now */ - if(MAYBE_ADD_CE_ENTRY(6)) { - add_CE_entry(); - if(cpnt1){ - *cpnt1 = '/'; - nchar++; - cpnt1 = NULL; /* A kluge so that we can restart properly */ - } - break; - } + if(split_SL_component ? MAYBE_ADD_CE_ENTRY(6) : + MAYBE_ADD_CE_ENTRY(6 + strlen ((char *) cpnt))) + { + add_CE_entry(); + if(cpnt1) + { + *cpnt1 = '/'; + nchar++; + cpnt1 = NULL; /* A kluge so that we can restart properly */ + } + break; + } j0 = strlen((char *) cpnt); while(j0) { j1 = j0; diff --git a/util/mkisofs/tree.c b/util/mkisofs/tree.c index 7180905df..e5ddbb365 100644 --- a/util/mkisofs/tree.c +++ b/util/mkisofs/tree.c @@ -20,7 +20,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: tree.c,v 1.9.1.2 1998/06/02 03:17:31 eric Exp $"; +static char rcsid[] ="$Id: tree.c,v 1.26 1998/06/02 03:14:58 eric Exp $"; /* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ @@ -88,6 +88,9 @@ extern char * strdup(const char *); #endif static unsigned char symlink_buff[256]; +static void DECL(attach_dot_entries, (struct directory * dirnode, + struct stat * parent_stat)); +static void DECL(delete_directory, (struct directory * parent, struct directory * child)); extern int verbose; @@ -112,7 +115,9 @@ FDECL1(stat_fix, struct stat *, st) * are useless, and with uid+gid 0 don't want set-id bits, either). */ st->st_mode |= 0444; +#ifndef _WIN32 /* make all file "executable" */ if (st->st_mode & 0111) +#endif /* _WIN32 */ st->st_mode |= 0111; st->st_mode &= ~07222; } @@ -135,11 +140,10 @@ FDECL2(lstat_filter, char *, path, struct stat *, st) return result; } -void FDECL1(sort_n_finish, struct directory *, this_dir) +static int FDECL1(sort_n_finish, struct directory *, this_dir) { struct directory_entry * s_entry; struct directory_entry * s_entry1; - time_t current_time; struct directory_entry * table; int count; int d1; @@ -147,6 +151,7 @@ void FDECL1(sort_n_finish, struct directory *, this_dir) int d3; int new_reclen; char * c; + int status = 0; int tablesize = 0; char newname[34]; char rootname[34]; @@ -156,14 +161,17 @@ void FDECL1(sort_n_finish, struct directory *, this_dir) table = NULL; - if(fstatbuf.st_ctime == 0) + init_fstatbuf(); + + /* + * If we had artificially created this directory, then we might be + * missing the required '.' entries. Create these now if we need + * them. + */ + if( (this_dir->dir_flags & (DIR_HAS_DOT | DIR_HAS_DOTDOT)) != + (DIR_HAS_DOT | DIR_HAS_DOTDOT) ) { - time (¤t_time); - fstatbuf.st_uid = 0; - fstatbuf.st_gid = 0; - fstatbuf.st_ctime = current_time; - fstatbuf.st_mtime = current_time; - fstatbuf.st_atime = current_time; + attach_dot_entries(this_dir, &fstatbuf); } flush_file_hash(); @@ -253,7 +261,12 @@ got_valid_name: */ if(s_entry->priority < s_entry1->priority) { - fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, this_dir->whole_name, SPATH_SEPARATOR, s_entry->name, s_entry1->name); + if( verbose > 0 ) + { + fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, + this_dir->whole_name, SPATH_SEPARATOR, + s_entry->name, s_entry1->name); + } s_entry->isorec.name_len[0] = strlen(newname); new_reclen = sizeof(struct iso_directory_record) - sizeof(s_entry->isorec.name) + @@ -270,7 +283,12 @@ got_valid_name: else { delete_file_hash(s_entry1); - fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, this_dir->whole_name, SPATH_SEPARATOR, s_entry1->name, s_entry->name); + if( verbose > 0 ) + { + fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, + this_dir->whole_name, SPATH_SEPARATOR, + s_entry1->name, s_entry->name); + } s_entry1->isorec.name_len[0] = strlen(newname); new_reclen = sizeof(struct iso_directory_record) - sizeof(s_entry1->isorec.name) + @@ -324,6 +342,9 @@ got_valid_name: set_733((char *) table->isorec.size, tablesize); table->size = tablesize; table->filedir = this_dir; +#ifdef ERIC_neverdef + table->de_flags |= INHIBIT_JOLIET_ENTRY; +#endif table->name = strdup(""); table->table = (char *) e_malloc(ROUND_UP(tablesize)); memset(table->table, 0, ROUND_UP(tablesize)); @@ -339,10 +360,17 @@ got_valid_name: } } + /* + * We have now chosen the 8.3 names and we should now know the length + * of every entry in the directory. + */ for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { new_reclen = strlen(s_entry->isorec.name); + /* + * First update the path table sizes for directories. + */ if(s_entry->isorec.flags[0] == 2) { if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) @@ -354,7 +382,9 @@ got_valid_name: { new_reclen = 1; if (this_dir == root && strlen(s_entry->name) == 1) - path_table_size += sizeof(struct iso_path_table); + { + path_table_size += sizeof(struct iso_path_table); + } } } if(path_table_size & 1) path_table_size++; /* For odd lengths we pad */ @@ -380,8 +410,17 @@ got_valid_name: s_entry->isorec.length[0] = new_reclen; } - sort_directory(&this_dir->contents); + status = sort_directory(&this_dir->contents); + if( status > 0 ) + { + fprintf(stderr, "Unable to sort directory %s\n", + this_dir->whole_name); + } + /* + * If we are filling out a TRANS.TBL, generate the entries that will + * go in the thing. + */ if(table) { count = 0; @@ -390,10 +429,15 @@ got_valid_name: if(!s_entry->table) continue; if(strcmp(s_entry->name, ".") == 0 || strcmp(s_entry->name, "..") == 0) continue; - +#if (defined(__sun) && !defined(__svr4__)) + count += strlen(sprintf(table->table + count, "%c %-34s%s", + s_entry->table[0], + s_entry->isorec.name, s_entry->table+1)); +#else count += sprintf(table->table + count, "%c %-34s%s", s_entry->table[0], s_entry->isorec.name, s_entry->table+1); +#endif /* __sun && !__svr4__ */ free(s_entry->table); s_entry->table = NULL; } @@ -419,7 +463,7 @@ got_valid_name: this_dir->size = (this_dir->size + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1); this_dir->size += new_reclen; - + /* See if continuation entries were used on disc */ if(use_RockRidge && s_entry->rr_attr_size != s_entry->total_rr_attr_size) @@ -455,11 +499,11 @@ got_valid_name: } s_entry = s_entry->next; } + return status; } static void generate_reloc_directory() { - int new_reclen; time_t current_time; struct directory_entry *s_entry; @@ -476,7 +520,6 @@ static void generate_reloc_directory() reloc_dir->de_name = strdup("rr_moved"); reloc_dir->extent = 0; - new_reclen = strlen(reloc_dir->de_name); /* Now create an actual directory entry */ s_entry = (struct directory_entry *) @@ -485,6 +528,12 @@ static void generate_reloc_directory() s_entry->next = root->contents; reloc_dir->self = s_entry; + /* + * The rr_moved entry will not appear in the Joliet tree. + */ + reloc_dir->dir_flags |= INHIBIT_JOLIET_ENTRY; + s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; + root->contents = s_entry; root->contents->name = strdup(reloc_dir->de_name); root->contents->filedir = root; @@ -506,57 +555,134 @@ static void generate_reloc_directory() /* Now create the . and .. entries in rr_moved */ /* Now create an actual directory entry */ - s_entry = (struct directory_entry *) - e_malloc(sizeof (struct directory_entry)); - memcpy(s_entry, root->contents, - sizeof(struct directory_entry)); - s_entry->name = strdup("."); - iso9660_file_length (".", s_entry, 1); - - s_entry->filedir = reloc_dir; - reloc_dir->contents = s_entry; - - if(use_RockRidge){ - fstatbuf.st_mode = 0555 | S_IFDIR; - fstatbuf.st_nlink = 2; - generate_rock_ridge_attributes("", - ".", s_entry, - &fstatbuf, &fstatbuf, 0); - }; - - s_entry = (struct directory_entry *) - e_malloc(sizeof (struct directory_entry)); - memcpy(s_entry, root->contents, - sizeof(struct directory_entry)); - s_entry->name = strdup(".."); - iso9660_file_length ("..", s_entry, 1); - s_entry->filedir = root; - reloc_dir->contents->next = s_entry; - reloc_dir->contents->next->next = NULL; - if(use_RockRidge){ - fstatbuf.st_mode = 0555 | S_IFDIR; - fstatbuf.st_nlink = 2; - generate_rock_ridge_attributes("", - "..", s_entry, - &root_statbuf, &root_statbuf, 0); - }; + attach_dot_entries(reloc_dir, &root_statbuf); } -static void FDECL1(increment_nlink, struct directory_entry *, s_entry){ - unsigned char * pnt; - int len, nlink; +/* + * Function: attach_dot_entries + * + * Purpose: Create . and .. entries for a new directory. + * + * Notes: Only used for artificial directories that + * we are creating. + */ +static void FDECL2(attach_dot_entries, struct directory *, dirnode, + struct stat *, parent_stat) +{ + struct directory_entry *s_entry; + struct directory_entry *orig_contents; + int deep_flag = 0; - pnt = s_entry->rr_attributes; - len = s_entry->total_rr_attr_size; - while(len){ - if(pnt[0] == 'P' && pnt[1] == 'X') { - nlink = get_733((char *) pnt+12); - set_733((char *) pnt+12, nlink+1); - break; - }; - len -= pnt[2]; - pnt += pnt[2]; - }; + init_fstatbuf(); + + orig_contents = dirnode->contents; + + if( (dirnode->dir_flags & DIR_HAS_DOTDOT) == 0 ) + { + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry, dirnode->self, + sizeof(struct directory_entry)); + s_entry->name = strdup(".."); + s_entry->whole_name = NULL; + s_entry->isorec.name_len[0] = 1; + s_entry->isorec.flags[0] = 2; /* Mark as a directory */ + iso9660_file_length ("..", s_entry, 1); + iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime); + s_entry->filedir = dirnode->parent; + + dirnode->contents = s_entry; + dirnode->contents->next = orig_contents; + orig_contents = s_entry; + + if(use_RockRidge) + { + if( parent_stat == NULL ) + { + parent_stat = &fstatbuf; + } + generate_rock_ridge_attributes("", + "..", s_entry, + parent_stat, + parent_stat, 0); + } + dirnode->dir_flags |= DIR_HAS_DOTDOT; + } + + if( (dirnode->dir_flags & DIR_HAS_DOT) == 0 ) + { + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry, dirnode->self, + sizeof(struct directory_entry)); + s_entry->name = strdup("."); + s_entry->whole_name = NULL; + s_entry->isorec.name_len[0] = 1; + s_entry->isorec.flags[0] = 2; /* Mark as a directory */ + iso9660_file_length (".", s_entry, 1); + iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime); + s_entry->filedir = dirnode; + + dirnode->contents = s_entry; + dirnode->contents->next = orig_contents; + + if(use_RockRidge) + { + fstatbuf.st_mode = 0555 | S_IFDIR; + fstatbuf.st_nlink = 2; + + if( dirnode == root ) + { + deep_flag |= NEED_CE | NEED_SP; /* For extension record */ + } + + generate_rock_ridge_attributes("", + ".", s_entry, + &fstatbuf, &fstatbuf, deep_flag); + } + + dirnode->dir_flags |= DIR_HAS_DOT; + } + +} + +static void FDECL2(update_nlink, struct directory_entry *, s_entry, int, value) +{ + unsigned char * pnt; + int len; + + pnt = s_entry->rr_attributes; + len = s_entry->total_rr_attr_size; + while(len) + { + if(pnt[0] == 'P' && pnt[1] == 'X') + { + set_733((char *) pnt+12, value); + break; + } + len -= pnt[2]; + pnt += pnt[2]; + } +} + +static void FDECL1(increment_nlink, struct directory_entry *, s_entry) +{ + unsigned char * pnt; + int len, nlink; + + pnt = s_entry->rr_attributes; + len = s_entry->total_rr_attr_size; + while(len) + { + if(pnt[0] == 'P' && pnt[1] == 'X') + { + nlink = get_733((char *) pnt+12); + set_733((char *) pnt+12, nlink+1); + break; + } + len -= pnt[2]; + pnt += pnt[2]; + } } void finish_cl_pl_entries(){ @@ -601,29 +727,25 @@ void finish_cl_pl_entries(){ }; } -/* - * This function scans the directory tree, looking for files, and it makes - * note of everything that is found. We also begin to construct the ISO9660 - * directory entries, so that we can determine how large each directory is. +/* + * Function: scan_directory_tree + * + * Purpose: Walk through a directory on the local machine + * filter those things we don't want to include + * and build our representation of a dir. + * + * Notes: */ - int -FDECL3(scan_directory_tree,char *, path, struct directory_entry *, de, - struct iso_directory_record *, mrootp){ +FDECL3(scan_directory_tree,struct directory *, this_dir, + char *, path, + struct directory_entry *, de) +{ DIR * current_dir; char whole_path[1024]; struct dirent * d_entry; - struct directory_entry * s_entry, *s_entry1; - struct directory * this_dir, *next_brother, *parent; - struct stat statbuf, lstatbuf; - int status, dflag; - int lstatus; - int n_orig; - struct directory_entry **orig_contents = NULL; - struct directory_entry * odpnt = NULL; - char * cpnt; - int new_reclen; - int deep_flag; + struct directory * parent; + int dflag; char * old_path; current_dir = opendir(path); @@ -634,14 +756,15 @@ FDECL3(scan_directory_tree,char *, path, struct directory_entry *, de, old_path = path; - if(current_dir) d_entry = readdir_add_files(&path, old_path, current_dir); + if(current_dir) d_entry = readdir(current_dir); - if(!current_dir || !d_entry) { - fprintf(stderr,"Unable to open directory %s\n", path); - de->isorec.flags[0] &= ~2; /* Mark as not a directory */ - if(current_dir) closedir(current_dir); - return 0; - }; + if(!current_dir || !d_entry) + { + fprintf(stderr,"Unable to open directory %s\n", path); + de->isorec.flags[0] &= ~2; /* Mark as not a directory */ + if(current_dir) closedir(current_dir); + return 0; + } parent = de->filedir; /* Set up the struct for the current directory, and insert it into the @@ -651,77 +774,16 @@ FDECL3(scan_directory_tree,char *, path, struct directory_entry *, de, vms_path_fixup(path); #endif - this_dir = (struct directory *) e_malloc(sizeof(struct directory)); - this_dir->next = NULL; - new_reclen = 0; - this_dir->subdir = NULL; - this_dir->self = de; - this_dir->contents = NULL; - this_dir->whole_name = strdup(path); - cpnt = strrchr(path, PATH_SEPARATOR); - if(cpnt) - cpnt++; - else - cpnt = path; - this_dir->de_name = strdup(cpnt); - this_dir->size = 0; - this_dir->extent = 0; - - if(!parent || parent == root){ - if (!root) { - root = this_dir; /* First time through for root directory only */ - root->depth = 0; - root->parent = root; - } else { - this_dir->depth = 1; - if(!root->subdir) - root->subdir = this_dir; - else { - next_brother = root->subdir; - while(next_brother->next) next_brother = next_brother->next; - next_brother->next = this_dir; - }; - this_dir->parent = parent; - }; - } else { - /* Come through here for normal traversal of tree */ -#ifdef DEBUG - fprintf(stderr,"%s(%d) ", path, this_dir->depth); -#endif - if(parent->depth > RR_relocation_depth) { - fprintf(stderr,"Directories too deep %s\n", path); - exit(1); - }; - - this_dir->parent = parent; - this_dir->depth = parent->depth + 1; - - if(!parent->subdir) - parent->subdir = this_dir; - else { - next_brother = parent->subdir; - while(next_brother->next) next_brother = next_brother->next; - next_brother->next = this_dir; - } - } - - /* - * Parse the same directory in the image that we are merging - * for multisession stuff. + + /* + * Now we scan the directory itself, and look at what is inside of it. */ - if( mrootp != NULL ) - { - orig_contents = read_merging_directory(mrootp, &n_orig); - } - -/* Now we scan the directory itself, and look at what is inside of it. */ - dflag = 0; while(1==1){ /* The first time through, skip this, since we already asked for the first entry when we opened the directory. */ - if(dflag) d_entry = readdir_add_files(&path, old_path, current_dir); + if(dflag) d_entry = readdir(current_dir); dflag++; if(!d_entry) break; @@ -730,9 +792,16 @@ FDECL3(scan_directory_tree,char *, path, struct directory_entry *, de, /* If we do not want all files, then pitch the backups. */ if(!all_files){ - if(strchr(d_entry->d_name,'~')) continue; - if(strchr(d_entry->d_name,'#')) continue; - }; + if( strchr(d_entry->d_name,'~') + || strchr(d_entry->d_name,'#')) + { + if( verbose > 0 ) + { + fprintf(stderr, "Ignoring file %s\n", d_entry->d_name); + } + continue; + } + } if(strlen(path)+strlen(d_entry->d_name) + 2 > sizeof(whole_path)){ fprintf(stderr, "Overflow of stat buffer\n"); @@ -747,16 +816,9 @@ FDECL3(scan_directory_tree,char *, path, struct directory_entry *, de, #endif strcat(whole_path, d_entry->d_name); - /* Should we exclude this file? */ - if (is_excluded(whole_path)) { - if (verbose) { - fprintf(stderr, "Excluded: %s\n",whole_path); - } - continue; - } /** Should we exclude this file ? */ - if (matches(d_entry->d_name)) { - if (verbose) { + if (matches(d_entry->d_name) || matches(whole_path)) { + if (verbose > 1) { fprintf(stderr, "Excluded by match: %s\n", whole_path); } continue; @@ -770,402 +832,498 @@ FDECL3(scan_directory_tree,char *, path, struct directory_entry *, de, * versions of these files, and we need to ignore any * originals that we might have found. */ - if (verbose) + if (verbose > 1) { fprintf(stderr, "Excluded: %s\n",whole_path); } continue; } -#if 0 - if (verbose) fprintf(stderr, "%s\n",whole_path); -#endif - status = stat_filter(whole_path, &statbuf); - - lstatus = lstat_filter(whole_path, &lstatbuf); - - if( (status == -1) && (lstatus == -1) ) + /* + * If we already have a '.' or a '..' entry, then don't + * insert new ones. + */ + if( strcmp(d_entry->d_name, ".") == 0 + && this_dir->dir_flags & DIR_HAS_DOT ) { - /* - * This means that the file doesn't exist, or isn't accessible. - * Sometimes this is because of NFS permissions problems - * or it could mean that the user has attempted to 'add' something - * with the -i option and the directory being added doesn't exist. - */ - fprintf(stderr, "Non-existant or inaccessible: %s\n",whole_path); continue; } - if(this_dir == root && strcmp(d_entry->d_name, ".") == 0) - root_statbuf = statbuf; /* Save this for later on */ - - /* We do this to make sure that the root entries are consistent */ - if(this_dir == root && strcmp(d_entry->d_name, "..") == 0) { - statbuf = root_statbuf; - lstatbuf = root_statbuf; - }; - - if(S_ISLNK(lstatbuf.st_mode)){ - - /* Here we decide how to handle the symbolic links. Here - we handle the general case - if we are not following - links or there is an error, then we must change - something. If RR is in use, it is easy, we let RR - describe the file. If not, then we punt the file. */ - - if((status || !follow_links)){ - if(use_RockRidge){ - status = 0; - statbuf.st_size = 0; - STAT_INODE(statbuf) = UNCACHED_INODE; - statbuf.st_dev = (dev_t) UNCACHED_DEVICE; - statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG; - } else { - if(follow_links) fprintf(stderr, - "Unable to stat file %s - ignoring and continuing.\n", - whole_path); - else fprintf(stderr, - "Symlink %s ignored - continuing.\n", - whole_path); - continue; /* Non Rock Ridge discs - ignore all symlinks */ - }; - } - - /* Here we handle a different kind of case. Here we have - a symlink, but we want to follow symlinks. If we run - across a directory loop, then we need to pretend that - we are not following symlinks for this file. If this - is the first time we have seen this, then make this - seem as if there was no symlink there in the first - place */ - - if( follow_links - && S_ISDIR(statbuf.st_mode) ) - { - if( strcmp(d_entry->d_name, ".") - && strcmp(d_entry->d_name, "..") ) - { - if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) - { - if(!use_RockRidge) - { - fprintf(stderr, "Already cached directory seen (%s)\n", - whole_path); - continue; - } - statbuf.st_size = 0; - STAT_INODE(statbuf) = UNCACHED_INODE; - statbuf.st_dev = (dev_t) UNCACHED_DEVICE; - statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG; - } else { - lstatbuf = statbuf; - add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); - } - } - } - - /* - * For non-directories, we just copy the stat information over - * so we correctly include this file. - */ - if( follow_links - && !S_ISDIR(statbuf.st_mode) ) - { - lstatbuf = statbuf; - } - } - - /* - * Add directories to the cache so that we don't waste space even - * if we are supposed to be following symlinks. - */ - if( follow_links - && strcmp(d_entry->d_name, ".") - && strcmp(d_entry->d_name, "..") - && S_ISDIR(statbuf.st_mode) ) - { - add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); - } -#ifdef VMS - if(!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX && - statbuf.st_fab_rfm != FAB$C_STMLF)) { - fprintf(stderr,"Warning - file %s has an unsupported VMS record" - " format (%d)\n", - whole_path, statbuf.st_fab_rfm); - } -#endif - - if(S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK))){ - fprintf(stderr, "File %s is not readable (errno = %d) - ignoring\n", - whole_path, errno); - continue; - } - - /* Add this so that we can detect directory loops with hard links. - If we are set up to follow symlinks, then we skip this checking. */ - if( !follow_links - && S_ISDIR(lstatbuf.st_mode) - && strcmp(d_entry->d_name, ".") - && strcmp(d_entry->d_name, "..") ) + if( strcmp(d_entry->d_name, "..") == 0 + && this_dir->dir_flags & DIR_HAS_DOTDOT ) { - if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) { - fprintf(stderr,"Directory loop - fatal goof (%s %lx %lu).\n", - whole_path, (unsigned long) statbuf.st_dev, - (unsigned long) STAT_INODE(statbuf)); - exit(1); - }; - add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); - }; - - if (!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) && - !S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode) - && !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) && - !S_ISDIR(lstatbuf.st_mode)) { - fprintf(stderr,"Unknown file type %s - ignoring and continuing.\n", - whole_path); - continue; - }; - - /* Who knows what trash this is - ignore and continue */ - - if(status) { - fprintf(stderr, - "Unable to stat file %s - ignoring and continuing.\n", - whole_path); - continue; - }; - - s_entry = (struct directory_entry *) - e_malloc(sizeof (struct directory_entry)); - s_entry->next = this_dir->contents; - memset(s_entry->isorec.extent, 0, 8); - this_dir->contents = s_entry; - deep_flag = 0; - s_entry->table = NULL; - - s_entry->name = strdup(d_entry->d_name); - s_entry->whole_name = strdup (whole_path); - - s_entry->de_flags = 0; - s_entry->filedir = this_dir; - s_entry->isorec.flags[0] = 0; - s_entry->isorec.ext_attr_length[0] = 0; - iso9660_date(s_entry->isorec.date, statbuf.st_mtime); - s_entry->isorec.file_unit_size[0] = 0; - s_entry->isorec.interleave[0] = 0; - if(parent && parent == reloc_dir && strcmp(d_entry->d_name, "..") == 0){ - s_entry->inode = UNCACHED_INODE; - s_entry->dev = (dev_t) UNCACHED_DEVICE; - deep_flag = NEED_PL; - } else { - s_entry->inode = STAT_INODE(statbuf); - s_entry->dev = statbuf.st_dev; - }; - set_723(s_entry->isorec.volume_sequence_number, DEF_VSN); - iso9660_file_length(d_entry->d_name, s_entry, S_ISDIR(statbuf.st_mode)); - s_entry->rr_attr_size = 0; - s_entry->total_rr_attr_size = 0; - s_entry->rr_attributes = NULL; - - /* Directories are assigned sizes later on */ - if (!S_ISDIR(statbuf.st_mode)) { - set_733((char *) s_entry->isorec.size, statbuf.st_size); - - if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) || - S_ISFIFO(lstatbuf.st_mode) || S_ISSOCK(lstatbuf.st_mode) - || S_ISLNK(lstatbuf.st_mode)) - s_entry->size = 0; - else - s_entry->size = statbuf.st_size; - } else - s_entry->isorec.flags[0] = 2; - - /* - * We always should create an entirely new directory tree whenever - * we generate a new session, unless there were *no* changes whatsoever - * to any of the directories, in which case it would be kind of pointless - * to generate a new session. - * - * I believe it is possible to rigorously prove that any change anywhere - * in the filesystem will force the entire tree to be regenerated - * because the modified directory will get a new extent number. Since - * each subdirectory of the changed directory has a '..' entry, all of - * them will need to be rewritten too, and since the parent directory - * of the modified directory will have an extent pointer to the directory - * it too will need to be rewritten. Thus we will never be able to reuse - * any directory information when writing new sessions. - * - * We still check the previous session so we can mark off the equivalent - * entry in the list we got from the original disc, however. - */ - if(S_ISDIR(statbuf.st_mode) && orig_contents != NULL){ - check_prev_session(orig_contents, n_orig, s_entry, - &statbuf, &lstatbuf, &odpnt); - } - - if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..") && - S_ISDIR(statbuf.st_mode) && this_dir->depth > RR_relocation_depth){ - if(!reloc_dir) generate_reloc_directory(); - - s_entry1 = (struct directory_entry *) - e_malloc(sizeof (struct directory_entry)); - memcpy(s_entry1, this_dir->contents, - sizeof(struct directory_entry)); - s_entry1->table = NULL; - s_entry1->name = strdup(this_dir->contents->name); - s_entry1->whole_name = strdup(this_dir->contents->whole_name); - s_entry1->next = reloc_dir->contents; - reloc_dir->contents = s_entry1; - s_entry1->priority = 32768; - s_entry1->parent_rec = this_dir->contents; - - deep_flag = NEED_RE; - - if(use_RockRidge) { - generate_rock_ridge_attributes(whole_path, - d_entry->d_name, s_entry1, - &statbuf, &lstatbuf, deep_flag); - } - - deep_flag = 0; - - /* We need to set this temporarily so that the parent to this is correctly - determined. */ - s_entry1->filedir = reloc_dir; - if( odpnt != NULL ) - { - scan_directory_tree(whole_path, s_entry1, &odpnt->isorec); - } - else - { - scan_directory_tree(whole_path, s_entry1, NULL); - } - if( odpnt != NULL ) - { - free(odpnt); - odpnt = NULL; - } - s_entry1->filedir = this_dir; - - statbuf.st_size = 0; - statbuf.st_mode &= 0777; - set_733((char *) s_entry->isorec.size, 0); - s_entry->size = 0; - s_entry->isorec.flags[0] = 0; - s_entry->inode = UNCACHED_INODE; - deep_flag = NEED_CL; - }; - - if(generate_tables && strcmp(s_entry->name, ".") && strcmp(s_entry->name, "..")) { - char buffer[2048]; - int nchar; - switch(lstatbuf.st_mode & S_IFMT){ - case S_IFDIR: - sprintf(buffer,"D\t%s\n", - s_entry->name); - break; -#ifndef NON_UNIXFS - case S_IFBLK: - sprintf(buffer,"B\t%s\t%lu %lu\n", - s_entry->name, - (unsigned long) major(statbuf.st_rdev), - (unsigned long) minor(statbuf.st_rdev)); - break; - case S_IFIFO: - sprintf(buffer,"P\t%s\n", - s_entry->name); - break; - case S_IFCHR: - sprintf(buffer,"C\t%s\t%lu %lu\n", - s_entry->name, - (unsigned long) major(statbuf.st_rdev), - (unsigned long) minor(statbuf.st_rdev)); - break; - case S_IFLNK: - nchar = readlink(whole_path, - symlink_buff, - sizeof(symlink_buff)); - symlink_buff[nchar < 0 ? 0 : nchar] = 0; - sprintf(buffer,"L\t%s\t%s\n", - s_entry->name, symlink_buff); - break; -#ifdef S_IFSOCK - case S_IFSOCK: - sprintf(buffer,"S\t%s\n", - s_entry->name); - break; -#endif -#endif /* NON_UNIXFS */ - case S_IFREG: - default: - sprintf(buffer,"F\t%s\n", - s_entry->name); - break; - }; - s_entry->table = strdup(buffer); - }; - - /* - * See if we have an entry for this guy in the previous session. - */ - if( orig_contents != NULL && !S_ISDIR(statbuf.st_mode)) - { - check_prev_session(orig_contents, n_orig, s_entry, - &statbuf, &lstatbuf, NULL); + continue; } - if(S_ISDIR(statbuf.st_mode)){ - int dflag; - if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..")) { - if( odpnt != NULL ) +#if 0 + if (verbose > 1) fprintf(stderr, "%s\n",whole_path); +#endif + /* + * This actually adds the entry to the directory in question. + */ + insert_file_entry(this_dir, whole_path, d_entry->d_name); + } + closedir(current_dir); + + return 1; +} + + +/* + * Function: insert_file_entry + * + * Purpose: Insert one entry into our directory node. + * + * Note: + * This function inserts a single entry into the directory. It + * is assumed that all filtering and decision making regarding what + * we want to include has already been made, so the purpose of this + * is to insert one entry (file, link, dir, etc), into this directory. + * Note that if the entry is a dir (or if we are following links, + * and the thing it points to is a dir), then we will scan those + * trees before we return. + */ +int +FDECL3(insert_file_entry,struct directory *, this_dir, + char *, whole_path, + char *, short_name) +{ + struct stat statbuf, lstatbuf; + struct directory_entry * s_entry, *s_entry1; + int lstatus; + int status; + int deep_flag; + + status = stat_filter(whole_path, &statbuf); + + lstatus = lstat_filter(whole_path, &lstatbuf); + + if( (status == -1) && (lstatus == -1) ) + { + /* + * This means that the file doesn't exist, or isn't accessible. + * Sometimes this is because of NFS permissions problems. + */ + fprintf(stderr, "Non-existant or inaccessible: %s\n",whole_path); + return 0; + } + + if(this_dir == root && strcmp(short_name, ".") == 0) + root_statbuf = statbuf; /* Save this for later on */ + + /* We do this to make sure that the root entries are consistent */ + if(this_dir == root && strcmp(short_name, "..") == 0) + { + statbuf = root_statbuf; + lstatbuf = root_statbuf; + } + + if(S_ISLNK(lstatbuf.st_mode)) + { + + /* Here we decide how to handle the symbolic links. Here + we handle the general case - if we are not following + links or there is an error, then we must change + something. If RR is in use, it is easy, we let RR + describe the file. If not, then we punt the file. */ + + if((status || !follow_links)) + { + if(use_RockRidge) + { + status = 0; + statbuf.st_size = 0; + STAT_INODE(statbuf) = UNCACHED_INODE; + statbuf.st_dev = (dev_t) UNCACHED_DEVICE; + statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG; + } else { + if(follow_links) { - dflag = scan_directory_tree(whole_path, s_entry, - &odpnt->isorec); + fprintf(stderr, + "Unable to stat file %s - ignoring and continuing.\n", + whole_path); } else { - dflag = scan_directory_tree(whole_path, s_entry, NULL); + fprintf(stderr, + "Symlink %s ignored - continuing.\n", + whole_path); + return 0; /* Non Rock Ridge discs - ignore all symlinks */ } - /* If unable to scan directory, mark this as a non-directory */ - if(!dflag) - lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG; - if( odpnt != NULL ) - { - free(odpnt); - odpnt = NULL; - } - } - } - - if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".") == 0) - deep_flag |= NEED_CE | NEED_SP; /* For extension record */ - - /* Now figure out how much room this file will take in the directory */ - - if(use_RockRidge) { - generate_rock_ridge_attributes(whole_path, - d_entry->d_name, s_entry, - &statbuf, &lstatbuf, deep_flag); - - } - } - closedir(current_dir); - - if( orig_contents != NULL ) - { - merge_remaining_entries(this_dir, orig_contents, n_orig); - free_mdinfo(orig_contents, n_orig); - } - - if( this_dir->contents == NULL ) - { + } + } + + /* Here we handle a different kind of case. Here we have + a symlink, but we want to follow symlinks. If we run + across a directory loop, then we need to pretend that + we are not following symlinks for this file. If this + is the first time we have seen this, then make this + seem as if there was no symlink there in the first + place */ + + if( follow_links + && S_ISDIR(statbuf.st_mode) ) + { + if( strcmp(short_name, ".") + && strcmp(short_name, "..") ) + { + if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) + { + if(!use_RockRidge) + { + fprintf(stderr, "Already cached directory seen (%s)\n", + whole_path); + return 0; + } + statbuf.st_size = 0; + STAT_INODE(statbuf) = UNCACHED_INODE; + statbuf.st_dev = (dev_t) UNCACHED_DEVICE; + statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG; + } + else + { + lstatbuf = statbuf; + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + } + } + } + /* - * This directory must have been inaccessible. + * For non-directories, we just copy the stat information over + * so we correctly include this file. */ + if( follow_links + && !S_ISDIR(statbuf.st_mode) ) + { + lstatbuf = statbuf; + } + } + + /* + * Add directories to the cache so that we don't waste space even + * if we are supposed to be following symlinks. + */ + if( follow_links + && strcmp(short_name, ".") + && strcmp(short_name, "..") + && S_ISDIR(statbuf.st_mode) ) + { + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + } +#ifdef VMS + if(!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX && + statbuf.st_fab_rfm != FAB$C_STMLF)) { + fprintf(stderr,"Warning - file %s has an unsupported VMS record" + " format (%d)\n", + whole_path, statbuf.st_fab_rfm); + } +#endif + + if(S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK))) + { + fprintf(stderr, "File %s is not readable (errno = %d) - ignoring\n", + whole_path, errno); return 0; } - sort_n_finish(this_dir); + + /* Add this so that we can detect directory loops with hard links. + If we are set up to follow symlinks, then we skip this checking. */ + if( !follow_links + && S_ISDIR(lstatbuf.st_mode) + && strcmp(short_name, ".") + && strcmp(short_name, "..") ) + { + if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) { + fprintf(stderr,"Directory loop - fatal goof (%s %lx %lu).\n", + whole_path, (unsigned long) statbuf.st_dev, + (unsigned long) STAT_INODE(statbuf)); + exit(1); + } + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + } + + if (!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) && + !S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode) + && !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) && + !S_ISDIR(lstatbuf.st_mode)) { + fprintf(stderr,"Unknown file type %s - ignoring and continuing.\n", + whole_path); + return 0; + } + + /* Who knows what trash this is - ignore and continue */ + + if(status) + { + fprintf(stderr, + "Unable to stat file %s - ignoring and continuing.\n", + whole_path); + return 0; + } + + /* + * Check to see if we have already seen this directory node. + * If so, then we don't create a new entry for it, but we do want + * to recurse beneath it and add any new files we do find. + */ + if (S_ISDIR(statbuf.st_mode)) + { + int dflag; + + for( s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) + { + if( strcmp(s_entry->name, short_name) == 0 ) + { + break; + } + } + if ( s_entry != NULL + && strcmp(short_name,".") + && strcmp(short_name,"..")) + { + struct directory * child; + + if ( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0) + { + for( s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next) + { + if( strcmp(s_entry->name, short_name) == 0 ) + { + break; + } + } + child = find_or_create_directory(reloc_dir, whole_path, + s_entry, 1); + } + else + { + child = find_or_create_directory(this_dir, whole_path, + s_entry, 1); + /* If unable to scan directory, mark this as a non-directory */ + } + dflag = scan_directory_tree(child, whole_path, s_entry); + if(!dflag) + { + lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG; + } + return 0; + } + } + + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + s_entry->next = this_dir->contents; + memset(s_entry->isorec.extent, 0, 8); + this_dir->contents = s_entry; + deep_flag = 0; + s_entry->table = NULL; + + s_entry->name = strdup(short_name); + s_entry->whole_name = strdup (whole_path); + + s_entry->de_flags = 0; + s_entry->filedir = this_dir; + s_entry->isorec.flags[0] = 0; + s_entry->isorec.ext_attr_length[0] = 0; + iso9660_date(s_entry->isorec.date, statbuf.st_mtime); + s_entry->isorec.file_unit_size[0] = 0; + s_entry->isorec.interleave[0] = 0; + if( strcmp(short_name, ".") == 0) + { + this_dir->dir_flags |= DIR_HAS_DOT; + } + + if( strcmp(short_name, "..") == 0) + { + this_dir->dir_flags |= DIR_HAS_DOTDOT; + } + + if( this_dir->parent + && this_dir->parent == reloc_dir + && strcmp(short_name, "..") == 0) + { + s_entry->inode = UNCACHED_INODE; + s_entry->dev = (dev_t) UNCACHED_DEVICE; + deep_flag = NEED_PL; + } + else + { + s_entry->inode = STAT_INODE(statbuf); + s_entry->dev = statbuf.st_dev; + } + set_723(s_entry->isorec.volume_sequence_number, DEF_VSN); + iso9660_file_length(short_name, s_entry, S_ISDIR(statbuf.st_mode)); + s_entry->rr_attr_size = 0; + s_entry->total_rr_attr_size = 0; + s_entry->rr_attributes = NULL; + + /* Directories are assigned sizes later on */ + if (!S_ISDIR(statbuf.st_mode)) + { + if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) || + S_ISFIFO(lstatbuf.st_mode) || S_ISSOCK(lstatbuf.st_mode) + || S_ISLNK(lstatbuf.st_mode)) + { + s_entry->size = 0; + statbuf.st_size = 0; + } + else + { + s_entry->size = statbuf.st_size; + } + + set_733((char *) s_entry->isorec.size, statbuf.st_size); + } + else + { + s_entry->isorec.flags[0] = 2; + } + + if (strcmp(short_name,".") && strcmp(short_name,"..") && + S_ISDIR(statbuf.st_mode) && this_dir->depth > RR_relocation_depth) + { + struct directory * child; + + if(!reloc_dir) generate_reloc_directory(); + + /* + * Replicate the entry for this directory. The old one will stay where it + * is, and it will be neutered so that it no longer looks like a directory. + * The new one will look like a directory, and it will be put in the reloc_dir. + */ + s_entry1 = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry1, s_entry, sizeof(struct directory_entry)); + s_entry1->table = NULL; + s_entry1->name = strdup(this_dir->contents->name); + s_entry1->whole_name = strdup(this_dir->contents->whole_name); + s_entry1->next = reloc_dir->contents; + reloc_dir->contents = s_entry1; + s_entry1->priority = 32768; + s_entry1->parent_rec = this_dir->contents; + + deep_flag = NEED_RE; + + if(use_RockRidge) + { + generate_rock_ridge_attributes(whole_path, + short_name, s_entry1, + &statbuf, &lstatbuf, deep_flag); + } + + deep_flag = 0; + + /* We need to set this temporarily so that the parent to this + is correctly determined. */ + s_entry1->filedir = reloc_dir; + child = find_or_create_directory(reloc_dir, whole_path, + s_entry1, 0); + scan_directory_tree(child, whole_path, s_entry1); + s_entry1->filedir = this_dir; + + statbuf.st_size = 0; + statbuf.st_mode &= 0777; + set_733((char *) s_entry->isorec.size, 0); + s_entry->size = 0; + s_entry->isorec.flags[0] = 0; + s_entry->inode = UNCACHED_INODE; + s_entry->de_flags |= RELOCATED_DIRECTORY; + deep_flag = NEED_CL; + } + + if(generate_tables + && strcmp(s_entry->name, ".") + && strcmp(s_entry->name, "..")) + { + char buffer[2048]; + int nchar; + switch(lstatbuf.st_mode & S_IFMT) + { + case S_IFDIR: + sprintf(buffer,"D\t%s\n", + s_entry->name); + break; +#ifndef NON_UNIXFS + case S_IFBLK: + sprintf(buffer,"B\t%s\t%lu %lu\n", + s_entry->name, + (unsigned long) major(statbuf.st_rdev), + (unsigned long) minor(statbuf.st_rdev)); + break; + case S_IFIFO: + sprintf(buffer,"P\t%s\n", + s_entry->name); + break; + case S_IFCHR: + sprintf(buffer,"C\t%s\t%lu %lu\n", + s_entry->name, + (unsigned long) major(statbuf.st_rdev), + (unsigned long) minor(statbuf.st_rdev)); + break; + case S_IFLNK: + nchar = readlink(whole_path, + symlink_buff, + sizeof(symlink_buff)); + symlink_buff[nchar < 0 ? 0 : nchar] = 0; + sprintf(buffer,"L\t%s\t%s\n", + s_entry->name, symlink_buff); + break; +#ifdef S_IFSOCK + case S_IFSOCK: + sprintf(buffer,"S\t%s\n", + s_entry->name); + break; +#endif +#endif /* NON_UNIXFS */ + case S_IFREG: + default: + sprintf(buffer,"F\t%s\n", + s_entry->name); + break; + }; + s_entry->table = strdup(buffer); + } + + if(S_ISDIR(statbuf.st_mode)) + { + int dflag; + if (strcmp(short_name,".") && strcmp(short_name,"..")) + { + struct directory * child; + + child = find_or_create_directory(this_dir, whole_path, + s_entry, 1); + dflag = scan_directory_tree(child, whole_path, s_entry); + + if(!dflag) + { + lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG; + if( child->contents == NULL ) + { + delete_directory(this_dir, child); + } + } + } + /* If unable to scan directory, mark this as a non-directory */ + } + + if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".") == 0) + { + deep_flag |= NEED_CE | NEED_SP; /* For extension record */ + } + + /* Now figure out how much room this file will take in the + directory */ + + if(use_RockRidge) + { + generate_rock_ridge_attributes(whole_path, + short_name, s_entry, + &statbuf, &lstatbuf, deep_flag); + + } + return 1; } @@ -1185,6 +1343,254 @@ void FDECL2(generate_iso9660_directories, struct directory *, node, FILE*, outfi } } +/* + * Function: find_or_create_directory + * + * Purpose: Locate a directory entry in the tree, create if needed. + * + * Arguments: + */ +struct directory * FDECL4(find_or_create_directory, struct directory *, parent, + const char *, path, + struct directory_entry *, de, int, flag) +{ + struct directory * dpnt; + struct directory_entry * orig_de; + struct directory * next_brother; + const char * cpnt; + const char * pnt; + + orig_de = de; + + pnt = strrchr(path, PATH_SEPARATOR); + if( pnt == NULL ) + { + pnt = path; + } + else + { + pnt++; + } + + if( parent != NULL ) + { + dpnt = parent->subdir; + + while (dpnt) + { + /* + * Weird hack time - if there are two directories by the + * same name in the reloc_dir, they are not treated as the + * same thing unless the entire path matches completely. + */ + if( flag && strcmp(dpnt->de_name, pnt) == 0 ) + { + return dpnt; + } + dpnt = dpnt->next; + } + } + + /* + * We don't know if we have a valid directory entry for this one + * yet. If not, we need to create one. + */ + if( de == NULL ) + { + de = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memset(de, 0, sizeof(struct directory_entry)); + de->next = parent->contents; + parent->contents = de; + de->name = strdup(pnt); + de->filedir = parent; + de->isorec.flags[0] = 2; + de->priority = 32768; + de->inode = UNCACHED_INODE; + de->dev = (dev_t) UNCACHED_DEVICE; + set_723(de->isorec.volume_sequence_number, DEF_VSN); + iso9660_file_length (pnt, de, 1); + + init_fstatbuf(); + /* + * It doesn't exist for real, so we cannot add any Rock Ridge. + */ + if(use_RockRidge) + { + fstatbuf.st_mode = 0555 | S_IFDIR; + fstatbuf.st_nlink = 2; + generate_rock_ridge_attributes("", + (char *) pnt, de, + &fstatbuf, + &fstatbuf, 0); + } + iso9660_date(de->isorec.date, fstatbuf.st_mtime); + + } + + /* + * If we don't have a directory for this one yet, then allocate it + * now, and patch it into the tree in the appropriate place. + */ + dpnt = (struct directory *) e_malloc(sizeof(struct directory)); + memset(dpnt, 0, sizeof(struct directory)); + dpnt->next = NULL; + dpnt->subdir = NULL; + dpnt->self = de; + dpnt->contents = NULL; + dpnt->whole_name = strdup(path); + cpnt = strrchr(path, PATH_SEPARATOR); + if(cpnt) + cpnt++; + else + cpnt = path; + dpnt->de_name = strdup(cpnt); + dpnt->size = 0; + dpnt->extent = 0; + dpnt->jextent = 0; + dpnt->jsize = 0; + + if( orig_de == NULL ) + { + struct stat xstatbuf; + int sts; + + /* + * Now add a . and .. entry in the directory itself. + * This is a little tricky - if the real directory + * exists, we need to stat it first. Otherwise, we + * use the fictitious fstatbuf which points to the time + * at which mkisofs was started. + */ + sts = stat_filter(parent->whole_name, &xstatbuf); + if( sts == 0 ) + { + attach_dot_entries(dpnt, &xstatbuf); + } + else + { + attach_dot_entries(dpnt, &fstatbuf); + } + } + + if(!parent || parent == root) + { + if (!root) + { + root = dpnt; /* First time through for root directory only */ + root->depth = 0; + root->parent = root; + } else { + dpnt->depth = 1; + if(!root->subdir) + { + root->subdir = dpnt; + } + else + { + next_brother = root->subdir; + while(next_brother->next) next_brother = next_brother->next; + next_brother->next = dpnt; + } + dpnt->parent = parent; + } + } + else + { + /* Come through here for normal traversal of tree */ +#ifdef DEBUG + fprintf(stderr,"%s(%d) ", path, dpnt->depth); +#endif + if(parent->depth > RR_relocation_depth) + { + fprintf(stderr,"Directories too deep %s\n", path); + exit(1); + } + + dpnt->parent = parent; + dpnt->depth = parent->depth + 1; + + if(!parent->subdir) + { + parent->subdir = dpnt; + } + else + { + next_brother = parent->subdir; + while(next_brother->next) next_brother = next_brother->next; + next_brother->next = dpnt; + } + } + + return dpnt; +} + +/* + * Function: delete_directory + * + * Purpose: Locate a directory entry in the tree, create if needed. + * + * Arguments: + */ +static void FDECL2(delete_directory, struct directory *, parent, struct directory *, child) +{ + struct directory * tdir; + + if( child->contents != NULL ) + { + fprintf(stderr, "Unable to delete non-empty directory\n"); + exit(1); + } + + free(child->whole_name); + child->whole_name = NULL; + + free(child->de_name); + child->de_name = NULL; + + if( parent->subdir == child ) + { + parent->subdir = child->next; + } + else + { + for( tdir = parent->subdir; tdir->next != NULL; tdir = tdir->next ) + { + if( tdir->next == child ) + { + tdir->next = child->next; + break; + } + } + if( tdir == NULL ) + { + fprintf(stderr, "Unable to locate child directory in parent list\n"); + exit(1); + } + } + free(child); + return; +} + +int FDECL1(sort_tree, struct directory *, node){ + struct directory * dpnt; + int goof = 0; + + dpnt = node; + + while (dpnt){ + goof = sort_n_finish(dpnt); + if( goof ) + { + break; + } + + if(dpnt->subdir) sort_tree(dpnt->subdir); + dpnt = dpnt->next; + } + return goof; +} + void FDECL1(dump_tree, struct directory *, node){ struct directory * dpnt; @@ -1197,6 +1603,59 @@ void FDECL1(dump_tree, struct directory *, node){ } } +void FDECL1(update_nlink_field, struct directory *, node) +{ + struct directory * dpnt; + struct directory * xpnt; + struct directory_entry * s_entry; + int i; + + dpnt = node; + + while (dpnt) + { + /* + * First, count up the number of subdirectories this guy has. + */ + for(i=0, xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next, i++) + continue; + + /* + * Next check to see if we have any relocated directories + * in this directory. The nlink field will include these + * as real directories when they are properly relocated. + * + * In the non-rockridge disk, the relocated entries appear + * as zero length files. + */ + for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) + { + if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 ) + { + i++; + } + } + /* + * Now update the field in the Rock Ridge entry. + */ + update_nlink(dpnt->self, i + 2); + + /* + * Update the '.' entry for this directory. + */ + update_nlink(dpnt->contents, i + 2); + + /* + * Update all of the '..' entries that point to this guy. + */ + for(xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next) + update_nlink(xpnt->contents->next, i + 2); + + if(dpnt->subdir) update_nlink_field(dpnt->subdir); + dpnt = dpnt->next; + } +} + /* * something quick and dirty to locate a file given a path * recursively walks down path in filename until it finds the @@ -1232,13 +1691,13 @@ struct directory_entry * FDECL2(search_tree_file, struct directory *, *p1 = '\0'; #ifdef DEBUG_TORITO - printf("Looking for subdir called %s\n",p1); + fprintf(stderr,"Looking for subdir called %s\n",p1); #endif rest = p1+1; #ifdef DEBUG_TORITO - printf("Remainder of path name is now %s\n", rest); + fprintf(stderr,"Remainder of path name is now %s\n", rest); #endif dpnt = node->subdir; @@ -1251,7 +1710,7 @@ struct directory_entry * FDECL2(search_tree_file, struct directory *, if (!strcmp(subdir, dpnt->de_name)) { #ifdef DEBUG_TORITO - printf("Calling next level with filename = %s", rest); + fprintf(stderr,"Calling next level with filename = %s", rest); #endif return(search_tree_file( dpnt, rest )); } @@ -1276,7 +1735,7 @@ struct directory_entry * FDECL2(search_tree_file, struct directory *, if (!strcmp(filename, depnt->name)) { #ifdef DEBUG_TORITO - printf("Found our file %s", filename); + fprintf(stderr,"Found our file %s", filename); #endif return(depnt); } @@ -1290,3 +1749,25 @@ struct directory_entry * FDECL2(search_tree_file, struct directory *, fprintf(stderr,"We cant get here in search_tree_file :-/ \n"); } +void init_fstatbuf() +{ + time_t current_time; + + if(fstatbuf.st_ctime == 0) + { + time (¤t_time); + if( rationalize ) + { + fstatbuf.st_uid = 0; + fstatbuf.st_gid = 0; + } + else + { + fstatbuf.st_uid = getuid(); + fstatbuf.st_gid = getgid(); + } + fstatbuf.st_ctime = current_time; + fstatbuf.st_mtime = current_time; + fstatbuf.st_atime = current_time; + } +} diff --git a/util/mkisofs/write.c b/util/mkisofs/write.c index cfc9b763c..1976679b4 100644 --- a/util/mkisofs/write.c +++ b/util/mkisofs/write.c @@ -19,10 +19,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: write.c,v 1.6.1.3 1997/11/13 05:07:13 eric Exp $"; +static char rcsid[] ="$Id: write.c,v 1.18 1998/06/02 02:40:39 eric Exp $"; #include #include +#include "config.h" #include "mkisofs.h" #include "iso9660.h" #include @@ -50,15 +51,17 @@ extern char * strdup(const char *); /* Counters for statistics */ -static int table_size = 0; -static int total_dir_size = 0; -static int rockridge_size = 0; +static int table_size = 0; +static int total_dir_size = 0; +static int rockridge_size = 0; static struct directory ** pathlist; -static next_path_index = 1; +static next_path_index = 1; +static int sort_goof; -/* Used to fill in some of the information in the volume descriptor. */ -static struct tm local; -static struct tm gmt; +struct output_fragment * out_tail; +struct output_fragment * out_list; + +struct iso_primary_descriptor vol_desc; /* Routines to actually write the disc. We write sequentially so that we could write a tape, or write the disc directly */ @@ -118,8 +121,30 @@ void FDECL2(set_733, char *, pnt, unsigned int, i) void FDECL4(xfwrite, void *, buffer, int, count, int, size, FILE *, file) { - while(count) - { + /* + * This is a hack that could be made better. XXXIs this the only place? + * It is definitely needed on Operating Systems that do not + * allow to write files that are > 2GB. + * If the system is fast enough to be able to feed 1400 KB/s + * writing speed of a DVD-R drive, use stdout. + * If the system cannot do this reliable, you need to use this + * hacky option. + */ + if (split_output != 0 && ftell(file) > (1024 * 1024 * 1024) ) { + static int idx = 0; + char nbuf[128]; + + sprintf(nbuf, "part_%02d", idx++); + file = freopen(nbuf, "w", file); + if (file == NULL) { + fprintf(stderr, "Cannot open '%s'.\n", nbuf); + exit(1); + } + + } + + while(count) + { int got = fwrite(buffer,size,count,file); if(got<=0) @@ -142,11 +167,7 @@ struct deferred_write static struct deferred_write * dw_head = NULL, * dw_tail = NULL; -static struct directory_entry * sort_dir; -static struct eltorito_boot_descriptor boot_desc; - unsigned int last_extent_written =0; -static struct iso_primary_descriptor vol_desc; static path_table_index; static time_t begun; @@ -154,7 +175,7 @@ static time_t begun; numbers to them. We have already assigned extent numbers to everything that goes in front of them */ -void FDECL1(assign_directory_addresses, struct directory *, node) +static int FDECL1(assign_directory_addresses, struct directory *, node) { int dir_size; struct directory * dpnt; @@ -193,6 +214,7 @@ void FDECL1(assign_directory_addresses, struct directory *, node) dpnt = dpnt->next; } + return 0; } static void FDECL3(write_one_file, char *, filename, @@ -222,8 +244,8 @@ static void FDECL3(write_one_file, char *, filename, memset(buffer, 0, use); if (fread(buffer, 1, use, infile) == 0) { - fprintf(stderr,"cannot read from %s\n",filename); - exit(1); + fprintf(stderr,"cannot read from %s\n",filename); + exit(1); } xfwrite(buffer, 1, use, outfile); last_extent_written += use/SECTOR_SIZE; @@ -296,7 +318,7 @@ static void dump_filelist() } #endif -int FDECL2(compare_dirs, const void *, rr, const void *, ll) +static int FDECL2(compare_dirs, const void *, rr, const void *, ll) { char * rpnt, *lpnt; struct directory_entry ** r, **l; @@ -305,11 +327,24 @@ int FDECL2(compare_dirs, const void *, rr, const void *, ll) l = (struct directory_entry **) ll; rpnt = (*r)->isorec.name; lpnt = (*l)->isorec.name; + + /* + * If the entries are the same, this is an error. + */ + if( strcmp(rpnt, lpnt) == 0 ) + { + sort_goof++; + } /* * Put the '.' and '..' entries on the head of the sorted list. * For normal ASCII, this always happens to be the case, but out of * band characters cause this not to be the case sometimes. + * + * FIXME(eric) - these tests seem redundant, in taht the name is + * never assigned these values. It will instead be \000 or \001, + * and thus should always be sorted correctly. I need to figure + * out why I thought I needed this in the first place. */ if( strcmp(rpnt, ".") == 0 ) return -1; if( strcmp(lpnt, ".") == 0 ) return 1; @@ -336,7 +371,15 @@ int FDECL2(compare_dirs, const void *, rr, const void *, ll) return 0; } -void FDECL1(sort_directory, struct directory_entry **, sort_dir) +/* + * Function: sort_directory + * + * Purpose: Sort the directory in the appropriate ISO9660 + * order. + * + * Notes: Returns 0 if OK, returns > 0 if an error occurred. + */ +int FDECL1(sort_directory, struct directory_entry **, sort_dir) { int dcount = 0; int i, len; @@ -350,6 +393,11 @@ void FDECL1(sort_directory, struct directory_entry **, sort_dir) s_entry = s_entry->next; } + if( dcount == 0 ) + { + return 0; + } + /* * OK, now we know how many there are. Build a vector for sorting. */ @@ -367,44 +415,52 @@ void FDECL1(sort_directory, struct directory_entry **, sort_dir) s_entry = s_entry->next; } - qsort(sortlist, dcount, sizeof(struct directory_entry *), - (int (*)(const void *, const void *))compare_dirs); - - /* - * Now reassemble the linked list in the proper sorted order + /* + * Each directory is required to contain at least . and .. */ - for(i=0; inext = sortlist[i+1]; - } + if( dcount < 2 ) + { + sort_goof = 1; + + } + else + { + sort_goof = 0; + qsort(sortlist, dcount, sizeof(struct directory_entry *), + (int (*)(const void *, const void *))compare_dirs); + + /* + * Now reassemble the linked list in the proper sorted order + */ + for(i=0; inext = sortlist[i+1]; + } + + sortlist[dcount-1]->next = NULL; + *sort_dir = sortlist[0]; + } - sortlist[dcount-1]->next = NULL; - *sort_dir = sortlist[0]; - free(sortlist); - + return sort_goof; } -void generate_root_record() +static int root_gen() { - time_t ctime; - - time (&ctime); - - local = *localtime(&ctime); - gmt = *gmtime(&ctime); + init_fstatbuf(); root_record.length[0] = 1 + sizeof(struct iso_directory_record) - sizeof(root_record.name); root_record.ext_attr_length[0] = 0; set_733((char *) root_record.extent, root->extent); set_733((char *) root_record.size, ROUND_UP(root->size)); - iso9660_date(root_record.date, ctime); + iso9660_date(root_record.date, root_statbuf.st_mtime); root_record.flags[0] = 2; root_record.file_unit_size[0] = 0; root_record.interleave[0] = 0; set_723(root_record.volume_sequence_number, DEF_VSN); root_record.name_len[0] = 1; + return 0; } static void FDECL1(assign_file_addresses, struct directory *, dpnt) @@ -439,7 +495,7 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt) s_hash = find_hash(s_entry->dev, s_entry->inode); if(s_hash) { - if(verbose) + if(verbose > 1) { fprintf(stderr, "Cache hit for %s%s%s\n",s_entry->filedir->de_name, SPATH_SEPARATOR, s_entry->name); @@ -562,7 +618,7 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt) s_entry->starting_block = last_extent; add_hash(s_entry); last_extent += ROUND_UP(s_entry->size) >> 11; - if(verbose) + if(verbose > 1) { fprintf(stderr,"%d %d %s\n", s_entry->starting_block, last_extent-1, whole_path); @@ -576,6 +632,7 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt) } #endif +#ifdef NOT_NEEDED /* Never use this code if you like to create a DVD */ if(last_extent > (800000000 >> 11)) { /* @@ -583,9 +640,10 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt) */ fprintf(stderr,"Extent overflow processing file %s\n", whole_path); fprintf(stderr,"Starting block is %d\n", s_entry->starting_block); - fprintf(stderr,"Reported file size is %d extents\n", s_entry->size); + fprintf(stderr,"Reported file size is %d bytes\n", s_entry->size); exit(1); } +#endif continue; } @@ -605,6 +663,40 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt) } } /* assign_file_addresses(... */ +static void FDECL1(free_one_directory, struct directory *, dpnt) +{ + struct directory_entry * s_entry; + struct directory_entry * s_entry_d; + + s_entry = dpnt->contents; + while(s_entry) + { + s_entry_d = s_entry; + s_entry = s_entry->next; + + if( s_entry_d->name != NULL ) + { + free (s_entry_d->name); + } + if( s_entry_d->whole_name != NULL ) + { + free (s_entry_d->whole_name); + } + free (s_entry_d); + } + dpnt->contents = NULL; +} /* free_one_directory(... */ + +static void FDECL1(free_directories, struct directory *, dpnt) +{ + while (dpnt) + { + free_one_directory(dpnt); + if(dpnt->subdir) free_directories(dpnt->subdir); + dpnt = dpnt->next; + } +} + void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile) { unsigned int ce_address = 0; @@ -743,18 +835,15 @@ void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile) s_entry_d = s_entry; s_entry = s_entry->next; - if (s_entry_d->rr_attributes) free(s_entry_d->rr_attributes); - if( s_entry_d->name != NULL ) + /* + * Joliet doesn't use the Rock Ridge attributes, so we free it here. + */ + if (s_entry_d->rr_attributes) { - free (s_entry_d->name); + free(s_entry_d->rr_attributes); + s_entry_d->rr_attributes = NULL; } - if( s_entry_d->whole_name != NULL ) - { - free (s_entry_d->whole_name); - } - free (s_entry_d); } - sort_dir = NULL; if(dpnt->size != dir_index) { @@ -795,7 +884,7 @@ void FDECL1(build_pathlist, struct directory *, node) } } /* build_pathlist(... */ -int FDECL2(compare_paths, void const *, r, void const *, l) +static int FDECL2(compare_paths, void const *, r, void const *, l) { struct directory const *ll = *(struct directory * const *)l; struct directory const *rr = *(struct directory * const *)r; @@ -814,7 +903,7 @@ int FDECL2(compare_paths, void const *, r, void const *, l) } /* compare_paths(... */ -void generate_path_tables() +static int generate_path_tables() { struct directory_entry * de; struct directory * dpnt; @@ -926,6 +1015,7 @@ void generate_path_tables() path_table_index, path_table_size); } + return 0; } /* generate_path_tables(... */ void @@ -940,17 +1030,102 @@ FDECL3(memcpy_max, char *, to, char *, from, int, max) } /* memcpy_max(... */ -int FDECL1(iso_write, FILE *, outfile) +void FDECL1(outputlist_insert, struct output_fragment *, frag) +{ + if( out_tail == NULL ) + { + out_list = out_tail = frag; + } + else + { + out_tail->of_next = frag; + out_tail = frag; + } +} + +static int FDECL1(file_write, FILE *, outfile) { - char buffer[2048]; - int i; - char iso_time[17]; int should_write; - time(&begun); - assign_file_addresses(root); + /* + * OK, all done with that crap. Now write out the directories. + * This is where the fur starts to fly, because we need to keep track of + * each file as we find it and keep track of where we put it. + */ - memset(buffer, 0, sizeof(buffer)); + should_write = last_extent - session_start; + + if( print_size > 0 ) + { + fprintf(stderr,"Total extents scheduled to be written = %d\n", + last_extent - session_start); + exit(0); + } + + if( verbose > 0 ) + { +#ifdef DBG_ISO + fprintf(stderr,"Total directory extents being written = %d\n", last_extent); +#endif + + fprintf(stderr,"Total extents scheduled to be written = %d\n", + last_extent - session_start); + } + + /* + * Now write all of the files that we need. + */ + write_files(outfile); + + /* + * The rest is just fluff. + */ + if( verbose == 0 ) + { + return 0; + } + + fprintf(stderr,"Total extents actually written = %d\n", + last_extent_written - session_start); + + /* + * Hard links throw us off here + */ + if(should_write != last_extent - session_start) + { + fprintf(stderr,"Number of extents written not what was predicted. Please fix.\n"); + fprintf(stderr,"Predicted = %d, written = %d\n", should_write, last_extent); + } + + fprintf(stderr,"Total translation table size: %d\n", table_size); + fprintf(stderr,"Total rockridge attributes bytes: %d\n", rockridge_size); + fprintf(stderr,"Total directory bytes: %d\n", total_dir_size); + fprintf(stderr,"Path table size(bytes): %d\n", path_table_size); + +#ifdef DEBUG + fprintf(stderr, "next extent, last_extent, last_extent_written %d %d %d\n", + next_extent, last_extent, last_extent_written); +#endif + + return 0; + +} /* iso_write(... */ + +/* + * Function to write the PVD for the disc. + */ +static int FDECL1(pvd_write, FILE *, outfile) +{ + char iso_time[17]; + int should_write; + struct tm local; + struct tm gmt; + + + time(&begun); + + local = *localtime(&begun); + gmt = *gmtime(&begun); /* * This will break in the year 2000, I supose, but there is no good way @@ -965,17 +1140,6 @@ int FDECL1(iso_write, FILE *, outfile) local.tm_yday -= gmt.tm_yday; iso_time[16] = (local.tm_min + 60*(local.tm_hour + 24*local.tm_yday)) / 15; - /* - * First, we output 16 sectors of all zero - */ - - for(i=0; i<16; i++) - { - xfwrite(buffer, 1, sizeof(buffer), outfile); - } - - last_extent_written += 16; - /* * Next we write out the primary descriptor for the disc */ @@ -1011,7 +1175,7 @@ int FDECL1(iso_write, FILE *, outfile) * Now we copy the actual root directory record */ memcpy(vol_desc.root_directory_record, &root_record, - sizeof(struct iso_directory_record) + 1); + sizeof(struct iso_directory_record)); /* * The rest is just fluff. It looks nice to fill in many of these fields, @@ -1058,16 +1222,16 @@ int FDECL1(iso_write, FILE *, outfile) */ xfwrite(&vol_desc, 1, 2048, outfile); last_extent_written++; - if (use_eltorito) - { - /* - * Next we write out the boot volume descriptor for the disc - */ - get_torito_desc(&boot_desc); - xfwrite(&boot_desc, 1, 2048, outfile); - last_extent_written ++; - } - + return 0; +} + +/* + * Function to write the EVD for the disc. + */ +static int FDECL1(evd_write, FILE *, outfile) +{ + struct iso_primary_descriptor vol_desc; + /* * Now write the end volume descriptor. Much simpler than the other one */ @@ -1077,7 +1241,14 @@ int FDECL1(iso_write, FILE *, outfile) vol_desc.version[0] = 1; xfwrite(&vol_desc, 1, 2048, outfile); last_extent_written += 1; + return 0; +} +/* + * Function to write the EVD for the disc. + */ +static int FDECL1(pathtab_write, FILE *, outfile) +{ /* * Next we write the path tables */ @@ -1088,55 +1259,121 @@ int FDECL1(iso_write, FILE *, outfile) free(path_table_m); path_table_l = NULL; path_table_m = NULL; - - /* - * OK, all done with that crap. Now write out the directories. - * This is where the fur starts to fly, because we need to keep track of - * each file as we find it and keep track of where we put it. - */ - -#ifdef DBG_ISO - fprintf(stderr,"Total directory extents being written = %d\n", last_extent); -#endif -#if 0 - generate_one_directory(root, outfile); -#endif - generate_iso9660_directories(root, outfile); - - if(extension_record) - { - xfwrite(extension_record, 1, SECTOR_SIZE, outfile); - last_extent_written++; - } - - /* - * Now write all of the files that we need. - */ - fprintf(stderr,"Total extents scheduled to be written = %d\n", - last_extent - session_start); - write_files(outfile); - - fprintf(stderr,"Total extents actually written = %d\n", - last_extent_written - session_start); - /* - * Hard links throw us off here - */ - if(should_write != last_extent - session_start) - { - fprintf(stderr,"Number of extents written not what was predicted. Please fix.\n"); - fprintf(stderr,"Predicted = %d, written = %d\n", should_write, last_extent); - } - - fprintf(stderr,"Total translation table size: %d\n", table_size); - fprintf(stderr,"Total rockridge attributes bytes: %d\n", rockridge_size); - fprintf(stderr,"Total directory bytes: %d\n", total_dir_size); - fprintf(stderr,"Path table size(bytes): %d\n", path_table_size); - -#ifdef DEBUG - fprintf(stderr, "next extent, last_extent, last_extent_written %d %d %d\n", - next_extent, last_extent, last_extent_written); -#endif - return 0; +} -} /* iso_write(... */ +static int FDECL1(exten_write, FILE *, outfile) +{ + xfwrite(extension_record, 1, SECTOR_SIZE, outfile); + last_extent_written++; + return 0; +} + +/* + * Functions to describe padding block at the start of the disc. + */ +int FDECL1(oneblock_size, int, starting_extent) +{ + last_extent++; + return 0; +} + +/* + * Functions to describe padding block at the start of the disc. + */ +static int FDECL1(pathtab_size, int, starting_extent) +{ + path_table[0] = starting_extent; + + path_table[1] = 0; + path_table[2] = path_table[0] + path_blocks; + path_table[3] = 0; + last_extent += 2*path_blocks; + return 0; +} + +static int FDECL1(padblock_size, int, starting_extent) +{ + last_extent += 16; + return 0; +} + +static int file_gen() +{ + assign_file_addresses(root); + return 0; +} + +static int dirtree_dump() +{ + if (verbose > 1) + dump_tree(root); + return 0; +} + +static int FDECL1(dirtree_fixup, int, starting_extent) +{ + if (use_RockRidge && reloc_dir) + finish_cl_pl_entries(); + + if (use_RockRidge ) + update_nlink_field(root); + return 0; +} + +static int FDECL1(dirtree_size, int, starting_extent) +{ + assign_directory_addresses(root); + return 0; +} + +static int FDECL1(ext_size, int, starting_extent) +{ + extern int extension_record_size; + struct directory_entry * s_entry; + extension_record_extent = starting_extent; + s_entry = root->contents; + set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 24, + extension_record_extent); + set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 8, + extension_record_size); + last_extent++; + return 0; +} + +static int FDECL1(dirtree_write, FILE *, outfile) +{ + generate_iso9660_directories(root, outfile); + return 0; +} + +static int FDECL1(dirtree_cleanup, FILE *, outfile) +{ + free_directories(root); + return 0; +} + +static int FDECL1(padblock_write, FILE *, outfile) +{ + char buffer[2048]; + int i; + + memset(buffer, 0, sizeof(buffer)); + + for(i=0; i<16; i++) + { + xfwrite(buffer, 1, sizeof(buffer), outfile); + } + + last_extent_written += 16; + return 0; +} + +struct output_fragment padblock_desc = {NULL, padblock_size, NULL, padblock_write}; +struct output_fragment voldesc_desc = {NULL, oneblock_size, root_gen, pvd_write}; +struct output_fragment end_vol = {NULL, oneblock_size, NULL, evd_write}; +struct output_fragment pathtable_desc = {NULL, pathtab_size, generate_path_tables, pathtab_write}; +struct output_fragment dirtree_desc = {NULL, dirtree_size, NULL, dirtree_write}; +struct output_fragment dirtree_clean = {NULL, dirtree_fixup, dirtree_dump, dirtree_cleanup}; +struct output_fragment extension_desc = {NULL, ext_size, NULL, exten_write}; +struct output_fragment files_desc = {NULL, NULL, file_gen, file_write}; From 11e9a11511909eb94fbde8451552e1a8143bbe6b Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 8 Nov 2009 22:52:08 +0000 Subject: [PATCH 082/165] Import http://www.tux.org/pub/people/eric-youngdale/mkisofs/mkisofs-1.12b5.tar.gz --- util/mkisofs/defaults.h | 8 +- util/mkisofs/eltorito.c | 11 +- util/mkisofs/exclude.h | 6 +- util/mkisofs/fnmatch.c | 26 ++-- util/mkisofs/include/fctldefs.h | 57 +++++++ util/mkisofs/include/mconfig.h | 268 ++++++++++++++++++++++++++++++++ util/mkisofs/include/prototyp.h | 74 +++++++++ util/mkisofs/include/statdefs.h | 139 +++++++++++++++++ util/mkisofs/joliet.c | 138 ++++++++++------ util/mkisofs/match.c | 93 ++++++++++- util/mkisofs/match.h | 14 +- util/mkisofs/mkisofs.c | 205 +++++++++++++++++++++--- util/mkisofs/mkisofs.h | 22 ++- util/mkisofs/multi.c | 108 ++++++++++--- util/mkisofs/name.c | 6 +- util/mkisofs/rock.c | 56 ++++--- util/mkisofs/tree.c | 173 +++++++++++++++++---- util/mkisofs/write.c | 178 ++++++++++++++------- 18 files changed, 1364 insertions(+), 218 deletions(-) create mode 100644 util/mkisofs/include/fctldefs.h create mode 100644 util/mkisofs/include/mconfig.h create mode 100644 util/mkisofs/include/prototyp.h create mode 100644 util/mkisofs/include/statdefs.h diff --git a/util/mkisofs/defaults.h b/util/mkisofs/defaults.h index 9e8f3331a..dc9ad380c 100644 --- a/util/mkisofs/defaults.h +++ b/util/mkisofs/defaults.h @@ -2,12 +2,14 @@ * Header file defaults.h - assorted default values for character strings in * the volume descriptor. * - * $Id: defaults.h,v 1.6 1998/06/02 02:40:37 eric Exp $ + * $Id: defaults.h,v 1.8 1999/03/02 03:41:25 eric Exp $ */ #define PREPARER_DEFAULT NULL #define PUBLISHER_DEFAULT NULL -#define APPID_DEFAULT NULL +#ifndef APPID_DEFAULT +#define APPID_DEFAULT "MKISOFS ISO 9660 FILESYSTEM BUILDER" +#endif #define COPYRIGHT_DEFAULT NULL #define BIBLIO_DEFAULT NULL #define ABSTRACT_DEFAULT NULL @@ -24,7 +26,7 @@ #endif #ifdef __sun -#ifdef __svr4__ +#ifdef __SVR4 #define SYSTEM_ID_DEFAULT "Solaris" #else #define SYSTEM_ID_DEFAULT "SunOS" diff --git a/util/mkisofs/eltorito.c b/util/mkisofs/eltorito.c index 3ff50e92e..b577c731d 100644 --- a/util/mkisofs/eltorito.c +++ b/util/mkisofs/eltorito.c @@ -21,7 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: eltorito.c,v 1.12 1998/06/02 02:40:37 eric Exp $"; +static char rcsid[] ="$Id: eltorito.c,v 1.13 1999/03/02 03:41:25 eric Exp $"; #include #include @@ -44,8 +44,9 @@ static char rcsid[] ="$Id: eltorito.c,v 1.12 1998/06/02 02:40:37 eric Exp $"; static struct eltorito_validation_entry valid_desc; static struct eltorito_defaultboot_entry default_desc; -static struct eltorito_boot_descriptor boot_desc; +static struct eltorito_boot_descriptor gboot_desc; +static int tvd_write __PR((FILE * outfile)); /* * Check for presence of boot catalog. If it does not exist then make it @@ -275,13 +276,13 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) /* * Function to write the EVD for the disc. */ -int FDECL1(tvd_write, FILE *, outfile) +static int FDECL1(tvd_write, FILE *, outfile) { /* * Next we write out the boot volume descriptor for the disc */ - get_torito_desc(&boot_desc); - xfwrite(&boot_desc, 1, 2048, outfile); + get_torito_desc(&gboot_desc); + xfwrite(&gboot_desc, 1, 2048, outfile); last_extent_written ++; return 0; } diff --git a/util/mkisofs/exclude.h b/util/mkisofs/exclude.h index b9581a9e9..87cd6948a 100644 --- a/util/mkisofs/exclude.h +++ b/util/mkisofs/exclude.h @@ -3,8 +3,8 @@ * added 'exclude' option (-x) to specify pathnames NOT to be included in * CD image. * - * $Id: exclude.h,v 1.1 1997/02/23 15:53:19 eric Rel $ + * $Id: exclude.h,v 1.2 1999/03/02 03:41:25 eric Exp $ */ -void exclude(); -int is_excluded(); +void exclude __PR((char * fn)); +int is_excluded __PR((char * fn)); diff --git a/util/mkisofs/fnmatch.c b/util/mkisofs/fnmatch.c index cd5c0b27c..44de92e07 100644 --- a/util/mkisofs/fnmatch.c +++ b/util/mkisofs/fnmatch.c @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: fnmatch.c,v 1.3 1997/03/22 02:53:13 eric Rel $"; +static char rcsid[] ="$Id: fnmatch.c,v 1.4 1999/03/02 03:41:25 eric Exp $"; #ifdef HAVE_CONFIG_H #include @@ -26,6 +26,10 @@ static char rcsid[] ="$Id: fnmatch.c,v 1.3 1997/03/22 02:53:13 eric Rel $"; #include #include +#ifndef __STDC__ +#define const +#endif + #ifndef FNM_FILE_NAME #define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ #endif @@ -81,7 +85,7 @@ fnmatch (pattern, string, flags) while ((c = *p++) != '\0') { - c = FOLD (c); + c = FOLD ((unsigned char)c); switch (c) { @@ -99,9 +103,9 @@ fnmatch (pattern, string, flags) if (!(flags & FNM_NOESCAPE)) { c = *p++; - c = FOLD (c); + c = FOLD ((unsigned char )c); } - if (FOLD (*n) != c) + if (FOLD ((unsigned char )*n) != c) return FNM_NOMATCH; break; @@ -120,9 +124,9 @@ fnmatch (pattern, string, flags) { char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; - c1 = FOLD (c1); + c1 = FOLD ((unsigned char )c1); for (--p; *n != '\0'; ++n) - if ((c == '[' || FOLD (*n) == c1) && + if ((c == '[' || FOLD ((unsigned char )*n) == c1) && fnmatch (p, n, flags & ~FNM_PERIOD) == 0) return 0; return FNM_NOMATCH; @@ -152,14 +156,14 @@ fnmatch (pattern, string, flags) if (!(flags & FNM_NOESCAPE) && c == '\\') cstart = cend = *p++; - cstart = cend = FOLD (cstart); + cstart = cend = FOLD ((unsigned char)cstart); if (c == '\0') /* [ (unterminated) loses. */ return FNM_NOMATCH; c = *p++; - c = FOLD (c); + c = FOLD ((unsigned char)c); if ((flags & FNM_FILE_NAME) && c == '/') /* [/] can never match. */ @@ -172,12 +176,12 @@ fnmatch (pattern, string, flags) cend = *p++; if (cend == '\0') return FNM_NOMATCH; - cend = FOLD (cend); + cend = FOLD ((unsigned char)cend); c = *p++; } - if (FOLD (*n) >= cstart && FOLD (*n) <= cend) + if (FOLD ((unsigned char)*n) >= cstart && FOLD ((unsigned char)*n) <= cend) goto matched; if (c == ']') @@ -206,7 +210,7 @@ fnmatch (pattern, string, flags) break; default: - if (c != FOLD (*n)) + if (c != FOLD ((unsigned char)*n)) return FNM_NOMATCH; } diff --git a/util/mkisofs/include/fctldefs.h b/util/mkisofs/include/fctldefs.h new file mode 100644 index 000000000..de6b6a394 --- /dev/null +++ b/util/mkisofs/include/fctldefs.h @@ -0,0 +1,57 @@ +/* @(#)fctldefs.h 1.2 98/10/08 Copyright 1996 J. Schilling */ +/* + * Generic header for users of open(), creat() and chmod() + * + * Copyright (c) 1996 J. Schilling + */ +/* + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _FCTLDEFS_H +#define _FCTLDEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +#include +#include + +#ifdef HAVE_FCNTL_H + +# include + +#else /* HAVE_FCNTL_H */ + +# include + +#endif /* HAVE_FCNTL_H */ + +/* + * Do not define more than O_RDONLY / O_WRONLY / O_RDWR + * The values may differ. + */ +#ifndef O_RDONLY +#define O_RDONLY 0 +#endif +#ifndef O_WRONLY +#define O_WRONLY 1 +#endif +#ifndef O_RDWR +#define O_RDWR 2 +#endif + +#endif /* _FCTLDEFS_H */ diff --git a/util/mkisofs/include/mconfig.h b/util/mkisofs/include/mconfig.h new file mode 100644 index 000000000..1725217d3 --- /dev/null +++ b/util/mkisofs/include/mconfig.h @@ -0,0 +1,268 @@ +/* @(#)mconfig.h 1.24 98/12/14 Copyright 1995 J. Schilling */ +/* + * definitions for machine configuration + * + * Copyright (c) 1995 J. Schilling + * + * This file must be included before any other file. + * Use only cpp instructions. + * + * NOTE: SING: (Schily Is Not Gnu) + */ +/* + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _MCONFIG_H +#define _MCONFIG_H + +/* + * This hack that is needed as long as VMS has no POSIX shell. + */ +#ifdef VMS +# define USE_STATIC_CONF +#endif + +#ifdef VANILLA_AUTOCONF +#include +#else +#ifdef USE_STATIC_CONF +#include /* This is the current static autoconf stuff */ +#else +#include /* This is the current dynamic autoconf stuff */ +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(unix) || defined(__unix) || defined(__unix__) +# define IS_UNIX +#endif + +#ifdef __MSDOS__ +# define IS_MSDOS +#endif + +#if defined(tos) || defined(__tos) +# define IS_TOS +#endif + +#ifdef THINK_C +# define IS_MAC +#endif + +#if defined(sun) || defined(__sun) || defined(__sun__) +# define IS_SUN +#endif + +#if defined(__CYGWIN32__) +# define IS_GCC_WIN32 +#endif + +/*--------------------------------------------------------------------------*/ +/* + * Some magic that cannot (yet) be figured out with autoconf. + */ + +#ifdef sparc +# ifndef HAVE_LDSTUB +# define HAVE_LDSTUB +# endif +# ifndef HAVE_SCANSTACK +# define HAVE_SCANSTACK +# endif +#endif +#if defined(__i386_) || defined(i386) +# ifndef HAVE_XCHG +# define HAVE_XCHG +# endif +# ifndef HAVE_SCANSTACK +# define HAVE_SCANSTACK +# endif +#endif + +#if defined(SOL2) || defined(SOL2) || defined(S5R4) || defined(__S5R4) \ + || defined(SVR4) +# ifndef __SVR4 +# define __SVR4 +# endif +#endif + +#ifdef __SVR4 +# ifndef SVR4 +# define SVR4 +# endif +#endif + +/* + * SunOS 4.x / SunOS 5.x + */ +#if defined(IS_SUN) +# define HAVE_GETAV0 +#endif + +/* + * AIX + */ +#if defined(_IBMR2) || defined(_AIX) +# define IS_UNIX /* ??? really ??? */ +#endif + +/* + * Silicon Graphics (must be before SVR4) + */ +#if defined(sgi) || defined(__sgi) +# define __NOT_SVR4__ /* Not a real SVR4 implementation */ +#endif + +/* + * Data General + */ +#if defined(__DGUX__) +#ifdef XXXXXXX +# undef HAVE_MTGET_DSREG +# undef HAVE_MTGET_RESID +# undef HAVE_MTGET_FILENO +# undef HAVE_MTGET_BLKNO +#endif +# define mt_type mt_model +# define mt_dsreg mt_status1 +# define mt_erreg mt_status2 + /* + * DGUX hides its flock as dg_flock. + */ +# define HAVE_FLOCK +# define flock dg_flock + /* + * Use the BSD style wait on DGUX to get the resource usages of child + * processes. + */ +# define _BSD_WAIT_FLAVOR +#endif + +/* + * Apple Rhapsody + */ +#if defined(__NeXT__) && defined(__TARGET_OSNAME) && __TARGET_OSNAME == rhapsody +# define HAVE_OSDEF /* prevent later definitions to overwrite current */ +#endif + +/* + * NextStep + */ +#if defined(__NeXT__) && !defined(HAVE_OSDEF) +#define NO_PRINT_OVR +#undef HAVE_USG_STDIO /* + * NeXT Step 3.x uses __flsbuf(unsigned char , FILE *) + * instead of __flsbuf(int, FILE *) + */ +#endif + +/* + * NextStep 3.x has a broken linker that does not allow us to override + * these functions. + */ +#ifndef __OPRINTF__ + +#ifdef NO_PRINT_OVR +# define printf Xprintf +# define fprintf Xfprintf +# define sprintf Xsprintf +#endif + +#endif /* __OPRINTF__ */ + +/*--------------------------------------------------------------------------*/ +/* + * If there is no flock defined by the system, use emulation + * through fcntl record locking. + */ +#ifndef HAVE_FLOCK +#define LOCK_SH 1 /* shared lock */ +#define LOCK_EX 2 /* exclusive lock */ +#define LOCK_NB 4 /* don't block when locking */ +#define LOCK_UN 8 /* unlock */ +#endif + +#include + +/* + * gcc 2.x generally implements the long long type. + */ +#ifdef __GNUC__ +# if __GNUC__ > 1 +# ifndef HAVE_LONGLONG +# define HAVE_LONGLONG +# endif +# endif +#endif + +/* + * Convert to GNU name + */ +#ifdef HAVE_STDC_HEADERS +# ifndef STDC_HEADERS +# define STDC_HEADERS +# endif +#endif +/* + * Convert to SCHILY name + */ +#ifdef STDC_HEADERS +# ifndef HAVE_STDC_HEADERS +# define HAVE_STDC_HEADERS +# endif +#endif + +#ifdef IS_UNIX +# define PATH_DELIM '/' +# define PATH_DELIM_STR "/" +# define far +# define near +#endif + +#ifdef IS_GCC_WIN32 +# define PATH_DELIM '/' +# define PATH_DELIM_STR "/" +# define far +# define near +#endif + +#ifdef IS_MSDOS +# define PATH_DELIM '\\' +# define PATH_DELIM_STR "\\" +#endif + +#ifdef IS_TOS +# define PATH_DELIM '\\' +# define PATH_DELIM_STR "\\" +# define far +# define near +#endif + +#ifdef IS_MAC +# define PATH_DELIM ':' +# define PATH_DELIM_STR ":" +# define far +# define near +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _MCONFIG_H */ diff --git a/util/mkisofs/include/prototyp.h b/util/mkisofs/include/prototyp.h new file mode 100644 index 000000000..c74ae0af8 --- /dev/null +++ b/util/mkisofs/include/prototyp.h @@ -0,0 +1,74 @@ +/* @(#)prototyp.h 1.7 98/10/08 Copyright 1995 J. Schilling */ +/* + * Definitions for dealing with ANSI / KR C-Compilers + * + * Copyright (c) 1995 J. Schilling + */ +/* + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _PROTOTYP_H +#define _PROTOTYP_H + +#ifndef PROTOTYPES + /* + * If this has already been defined, + * someone else knows better than us... + */ +# ifdef __STDC__ +# if __STDC__ /* ANSI C */ +# define PROTOTYPES +# endif +# if defined(sun) && __STDC__ - 0 == 0 /* Sun C */ +# define PROTOTYPES +# endif +# endif +#endif /* PROTOTYPES */ + +/* + * If we have prototypes, we should have stdlib.h string.h stdarg.h + */ +#ifdef PROTOTYPES +#if !(defined(SABER) && defined(sun)) +# ifndef HAVE_STDARG_H +# define HAVE_STDARG_H +# endif +#endif +# ifndef HAVE_STDLIB_H +# define HAVE_STDLIB_H +# endif +# ifndef HAVE_STRING_H +# define HAVE_STRING_H +# endif +# ifndef HAVE_STDC_HEADERS +# define HAVE_STDC_HEADERS +# endif +# ifndef STDC_HEADERS +# define STDC_HEADERS /* GNU name */ +# endif +#endif + +#ifdef NO_PROTOTYPES /* Force not to use prototypes */ +# undef PROTOTYPES +#endif + +#ifdef PROTOTYPES +# define __PR(a) a +#else +# define __PR(a) () +#endif + +#endif /* _PROTOTYP_H */ diff --git a/util/mkisofs/include/statdefs.h b/util/mkisofs/include/statdefs.h new file mode 100644 index 000000000..0e34805ce --- /dev/null +++ b/util/mkisofs/include/statdefs.h @@ -0,0 +1,139 @@ +/* @(#)statdefs.h 1.1 98/11/22 Copyright 1998 J. Schilling */ +/* + * Definitions for stat() file mode + * + * Copyright (c) 1998 J. Schilling + */ +/* + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _STATDEFS_H +#define _STATDEFS_H + +#ifndef _MCONFIG_H +#include +#endif + +#ifdef STAT_MACROS_BROKEN +#undef S_ISFIFO /* Named pipe */ +#undef S_ISCHR /* Character special */ +#undef S_ISMPC /* UNUSED multiplexed c */ +#undef S_ISDIR /* Directory */ +#undef S_ISNAM /* Named file (XENIX) */ +#undef S_ISBLK /* Block special */ +#undef S_ISMPB /* UNUSED multiplexed b */ +#undef S_ISREG /* Regular file */ +#undef S_ISCNT /* Contiguous file */ +#undef S_ISLNK /* Symbolic link */ +#undef S_ISSHAD /* Solaris shadow inode */ +#undef S_ISSOCK /* UNIX domain socket */ +#undef S_ISDOOR /* Solaris DOOR */ +#endif + +#ifndef S_ISFIFO /* Named pipe */ +# ifdef S_IFIFO +# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +# else +# define S_ISFIFO(m) (0) +# endif +#endif +#ifndef S_ISCHR /* Character special */ +# ifdef S_IFCHR +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +# else +# define S_ISCHR(m) (0) +# endif +#endif +#ifndef S_ISMPC /* UNUSED multiplexed c */ +# ifdef S_IFMPC +# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) +# else +# define S_ISMPC(m) (0) +# endif +#endif +#ifndef S_ISDIR /* Directory */ +# ifdef S_IFDIR +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# else +# define S_ISDIR(m) (0) +# endif +#endif +#ifndef S_ISNAM /* Named file (XENIX) */ +# ifdef S_IFNAM +# define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM) +# else +# define S_ISNAM(m) (0) +# endif +#endif +#ifndef S_ISBLK /* Block special */ +# ifdef S_IFBLK +# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +# else +# define S_ISBLK(m) (0) +# endif +#endif +#ifndef S_ISMPB /* UNUSED multiplexed b */ +# ifdef S_IFMPB +# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) +# else +# define S_ISMPB(m) (0) +# endif +#endif +#ifndef S_ISREG /* Regular file */ +# ifdef S_IFREG +# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +# else +# define S_ISREG(m) (0) +# endif +#endif +#ifndef S_ISCNT /* Contiguous file */ +# ifdef S_IFCNT +# define S_ISCNT(m) (((m) & S_IFMT) == S_IFCNT) +# else +# define S_ISCNT(m) (0) +# endif +#endif +#ifndef S_ISLNK /* Symbolic link */ +# ifdef S_IFLNK +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +# else +# define S_ISLNK(m) (0) +# endif +#endif +#ifndef S_ISSHAD /* Solaris shadow inode */ +# ifdef S_IFSHAD +# define S_ISSHAD(m) (((m) & S_IFMT) == S_IFSHAD) +# else +# define S_ISSHAD(m) (0) +# endif +#endif +#ifndef S_ISSOCK /* UNIX domain socket */ +# ifdef S_IFSOCK +# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +# else +# define S_ISSOCK(m) (0) +# endif +#endif +#ifndef S_ISDOOR /* Solaris DOOR */ +# ifdef S_IFDOOR +# define S_ISDOOR(m) (((m) & S_IFMT) == S_IFDOOR) +# else +# define S_ISDOOR(m) (0) +# endif +#endif + +#endif /* _STATDEFS_H */ + diff --git a/util/mkisofs/joliet.c b/util/mkisofs/joliet.c index d3e8cb0e3..0aa866854 100644 --- a/util/mkisofs/joliet.c +++ b/util/mkisofs/joliet.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: joliet.c,v 1.12 1998/06/02 02:40:37 eric Exp $"; +static char rcsid[] ="$Id: joliet.c,v 1.14 1999/03/07 17:41:19 eric Exp $"; /* @@ -77,13 +77,15 @@ static char rcsid[] ="$Id: joliet.c,v 1.12 1998/06/02 02:40:37 eric Exp $"; #include #include -static jpath_table_index; +static int jpath_table_index; static struct directory ** jpathlist; -static next_jpath_index = 1; +static int next_jpath_index = 1; static int sort_goof; +static int generate_joliet_path_tables __PR((void)); static int DECL(joliet_sort_directory, (struct directory_entry ** sort_dir)); static void DECL(assign_joliet_directory_addresses, (struct directory * node)); +static int jroot_gen __PR((void)); /* * Function: convert_to_unicode @@ -121,7 +123,14 @@ static void FDECL3(convert_to_unicode, unsigned char *, buffer, int, size, char for(i=0; i < size ; i += 2, j++) { buffer[i] = 0; - if( tmpbuf[j] < 0x1f && tmpbuf[j] != 0 ) + /* + * JS integrated from: Achim_Kaiser@t-online.de + * + * Let all valid unicode characters pass through (assuming ISO-8859-1). + * Others are set to '_' . + */ + if( tmpbuf[j] != 0 && + (tmpbuf[j] <= 0x1f || (tmpbuf[j] >= 0x7F && tmpbuf[j] <= 0xA0)) ) { buffer[i+1] = '_'; } @@ -166,7 +175,6 @@ static void FDECL3(convert_to_unicode, unsigned char *, buffer, int, size, char static int FDECL1(joliet_strlen, const char *, string) { int rtn; - struct iso_directory_record foobar; rtn = strlen(string) << 1; @@ -192,32 +200,36 @@ static int FDECL1(joliet_strlen, const char *, string) * already present in the buffer. Just modifiy the * appropriate fields. */ -static void FDECL1(get_joliet_vol_desc, struct iso_primary_descriptor *, vol_desc) +static void FDECL1(get_joliet_vol_desc, struct iso_primary_descriptor *, jvol_desc) { - vol_desc->type[0] = ISO_VD_SUPPLEMENTARY; + jvol_desc->type[0] = ISO_VD_SUPPLEMENTARY; /* * For now, always do Unicode level 3. I don't really know what 1 and 2 * are - perhaps a more limited Unicode set. * - * FIXME(eric) - how does Romeo fit in here? + * FIXME(eric) - how does Romeo fit in here? As mkisofs just + * "expands" 8 bit character codes to 16 bits and does nothing + * special with the Unicode characters, therefore shouldn't mkisofs + * really be stating that it's using UCS-2 Level 1, not Level 3 for + * the Joliet directory tree. */ - strcpy(vol_desc->escape_sequences, "%/E"); + strcpy(jvol_desc->escape_sequences, "%/@"); /* * Until we have Unicode path tables, leave these unset. */ - set_733((char *) vol_desc->path_table_size, jpath_table_size); - set_731(vol_desc->type_l_path_table, jpath_table[0]); - set_731(vol_desc->opt_type_l_path_table, jpath_table[1]); - set_732(vol_desc->type_m_path_table, jpath_table[2]); - set_732(vol_desc->opt_type_m_path_table, jpath_table[3]); + set_733((char *) jvol_desc->path_table_size, jpath_table_size); + set_731(jvol_desc->type_l_path_table, jpath_table[0]); + set_731(jvol_desc->opt_type_l_path_table, jpath_table[1]); + set_732(jvol_desc->type_m_path_table, jpath_table[2]); + set_732(jvol_desc->opt_type_m_path_table, jpath_table[3]); /* * Set this one up. */ - memcpy(vol_desc->root_directory_record, &jroot_record, - sizeof(struct iso_directory_record) + 1); + memcpy(jvol_desc->root_directory_record, &jroot_record, + sizeof(struct iso_directory_record)); /* * Finally, we have a bunch of strings to convert to Unicode. @@ -225,15 +237,15 @@ static void FDECL1(get_joliet_vol_desc, struct iso_primary_descriptor *, vol_des * just be really lazy and do a char -> short conversion. We probably * will want to filter any characters >= 0x80. */ - convert_to_unicode((u_char *)vol_desc->system_id, sizeof(vol_desc->system_id), NULL); - convert_to_unicode((u_char *)vol_desc->volume_id, sizeof(vol_desc->volume_id), NULL); - convert_to_unicode((u_char *)vol_desc->volume_set_id, sizeof(vol_desc->volume_set_id), NULL); - convert_to_unicode((u_char *)vol_desc->publisher_id, sizeof(vol_desc->publisher_id), NULL); - convert_to_unicode((u_char *)vol_desc->preparer_id, sizeof(vol_desc->preparer_id), NULL); - convert_to_unicode((u_char *)vol_desc->application_id, sizeof(vol_desc->application_id), NULL); - convert_to_unicode((u_char *)vol_desc->copyright_file_id, sizeof(vol_desc->copyright_file_id), NULL); - convert_to_unicode((u_char *)vol_desc->abstract_file_id, sizeof(vol_desc->abstract_file_id), NULL); - convert_to_unicode((u_char *)vol_desc->bibliographic_file_id, sizeof(vol_desc->bibliographic_file_id), NULL); + convert_to_unicode((u_char *)jvol_desc->system_id, sizeof(jvol_desc->system_id), NULL); + convert_to_unicode((u_char *)jvol_desc->volume_id, sizeof(jvol_desc->volume_id), NULL); + convert_to_unicode((u_char *)jvol_desc->volume_set_id, sizeof(jvol_desc->volume_set_id), NULL); + convert_to_unicode((u_char *)jvol_desc->publisher_id, sizeof(jvol_desc->publisher_id), NULL); + convert_to_unicode((u_char *)jvol_desc->preparer_id, sizeof(jvol_desc->preparer_id), NULL); + convert_to_unicode((u_char *)jvol_desc->application_id, sizeof(jvol_desc->application_id), NULL); + convert_to_unicode((u_char *)jvol_desc->copyright_file_id, sizeof(jvol_desc->copyright_file_id), NULL); + convert_to_unicode((u_char *)jvol_desc->abstract_file_id, sizeof(jvol_desc->abstract_file_id), NULL); + convert_to_unicode((u_char *)jvol_desc->bibliographic_file_id, sizeof(jvol_desc->bibliographic_file_id), NULL); } @@ -261,8 +273,9 @@ static void FDECL1(assign_joliet_directory_addresses, struct directory *, node) last_extent += dir_size; } } - - if(dpnt->subdir) + + /* skip if hidden - but not for the rr_moved dir */ + if(dpnt->subdir && (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir)) { assign_joliet_directory_addresses(dpnt->subdir); } @@ -341,6 +354,12 @@ static int generate_joliet_path_tables() memset(jpath_table_l, 0, tablesize); memset(jpath_table_m, 0, tablesize); + if( next_jpath_index > 0xffff ) + { + fprintf(stderr, "Unable to generate sane path tables - too many directories (%d)\n", + next_jpath_index); + exit(1); + } /* * Now start filling in the path tables. Start with root directory */ @@ -353,8 +372,13 @@ static int generate_joliet_path_tables() do { fix = 0; +#ifdef __STDC__ qsort(&jpathlist[1], next_jpath_index-1, sizeof(struct directory *), (int (*)(const void *, const void *))joliet_compare_paths); +#else + qsort(&jpathlist[1], next_jpath_index-1, sizeof(struct directory *), + joliet_compare_paths); +#endif for(j=1; jjcontents; while(s_entry) { - if( (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) == 0 ) - { + if(s_entry->de_flags & INHIBIT_JOLIET_ENTRY) { + s_entry = s_entry->jnext; + continue; + } + /* * If this entry was a directory that was relocated, we have a bit * of trouble here. We need to dig out the real thing and put it @@ -617,8 +644,8 @@ static void FDECL2(generate_one_joliet_directory, struct directory *, dpnt, FILE { directory_buffer[dir_index++] = 0; } - } - s_entry = s_entry->jnext; + + s_entry = s_entry->jnext; } if(dpnt->jsize != dir_index) @@ -637,8 +664,15 @@ static int FDECL1(joliet_sort_n_finish, struct directory *, this_dir) struct directory_entry * s_entry; int status = 0; + /* don't want to skip this directory if it's the reloc_dir at the moment */ + if(this_dir != reloc_dir && this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) + { + return 0; + } + for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) { + /* skip hidden entries */ if( (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0 ) { continue; @@ -707,6 +741,10 @@ static int FDECL1(joliet_sort_n_finish, struct directory *, this_dir) * Do not split a directory entry across a sector boundary */ s_entry = this_dir->jcontents; +/* + * XXX Is it ok to comment this out? + */ +/*XXX JS this_dir->ce_bytes = 0;*/ for(s_entry = this_dir->jcontents; s_entry; s_entry = s_entry->jnext) { int jreclen; @@ -798,14 +836,16 @@ static int FDECL2(joliet_compare_dirs, const void *, rr, const void *, ll) static int FDECL1(joliet_sort_directory, struct directory_entry **, sort_dir) { int dcount = 0; - int i, len; + int i; struct directory_entry * s_entry; struct directory_entry ** sortlist; s_entry = *sort_dir; while(s_entry) { - dcount++; + /* skip hidden entries */ + if (!(s_entry->de_flags & INHIBIT_JOLIET_ENTRY)) + dcount++; s_entry = s_entry->next; } @@ -819,14 +859,22 @@ static int FDECL1(joliet_sort_directory, struct directory_entry **, sort_dir) s_entry = *sort_dir; while(s_entry) { - sortlist[dcount] = s_entry; - dcount++; + /* skip hidden entries */ + if (!(s_entry->de_flags & INHIBIT_JOLIET_ENTRY)) { + sortlist[dcount] = s_entry; + dcount++; + } s_entry = s_entry->next; } sort_goof = 0; +#ifdef __STDC__ qsort(sortlist, dcount, sizeof(struct directory_entry *), (int (*)(const void *, const void *))joliet_compare_dirs); +#else + qsort(sortlist, dcount, sizeof(struct directory_entry *), + joliet_compare_dirs); +#endif /* * Now reassemble the linked list in the proper sorted order @@ -846,24 +894,24 @@ static int FDECL1(joliet_sort_directory, struct directory_entry **, sort_dir) int FDECL1(joliet_sort_tree, struct directory *, node) { struct directory * dpnt; - int goof = 0; + int ret = 0; dpnt = node; while (dpnt){ - goof = joliet_sort_n_finish(dpnt); - if( goof ) + ret = joliet_sort_n_finish(dpnt); + if( ret ) { break; } - if(dpnt->subdir) goof = joliet_sort_tree(dpnt->subdir); - if( goof ) + if(dpnt->subdir) ret = joliet_sort_tree(dpnt->subdir); + if( ret ) { break; } dpnt = dpnt->next; } - return goof; + return ret; } static void FDECL2(generate_joliet_directories, struct directory *, node, FILE*, outfile){ @@ -879,12 +927,14 @@ static void FDECL2(generate_joliet_directories, struct directory *, node, FILE*, * In theory we should never reuse a directory, so this doesn't * make much sense. */ - if( dpnt->extent > session_start ) + if( dpnt->jextent > session_start ) { generate_one_joliet_directory(dpnt, outfile); } } - if(dpnt->subdir) generate_joliet_directories(dpnt->subdir, outfile); + /* skip if hidden - but not for the rr_moved dir */ + if(dpnt->subdir && (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir)) + generate_joliet_directories(dpnt->subdir, outfile); dpnt = dpnt->next; } } @@ -925,7 +975,7 @@ static int jroot_gen() jroot_record.flags[0] = 2; jroot_record.file_unit_size[0] = 0; jroot_record.interleave[0] = 0; - set_723(jroot_record.volume_sequence_number, DEF_VSN); + set_723(jroot_record.volume_sequence_number, volume_sequence_number); jroot_record.name_len[0] = 1; return 0; } diff --git a/util/mkisofs/match.c b/util/mkisofs/match.c index 0f5c7d8a7..e01314b0b 100644 --- a/util/mkisofs/match.c +++ b/util/mkisofs/match.c @@ -4,8 +4,10 @@ * in the CD image. */ -static char rcsid[] ="$Id: match.c,v 1.2 1997/02/23 16:10:42 eric Rel $"; +static char rcsid[] ="$Id: match.c,v 1.3 1999/03/02 03:41:25 eric Exp $"; +#include "config.h" +#include #include #ifndef VMS #ifdef HAVE_MALLOC_H @@ -54,3 +56,92 @@ char * fn; } return 0; /* not found -> not excluded */ } + +/* ISO9660/RR hide */ + +static char *i_mat[MAXMATCH]; + +void i_add_match(fn) +char * fn; +{ + register int i; + + for (i=0; i_mat[i] && i excluded filenmae */ + } + } + return 0; /* not found -> not excluded */ +} + +int i_ishidden() +{ + return((int)i_mat[0]); +} + +/* Joliet hide */ + +static char *j_mat[MAXMATCH]; + +void j_add_match(fn) +char * fn; +{ + register int i; + + for (i=0; j_mat[i] && i excluded filenmae */ + } + } + return 0; /* not found -> not excluded */ +} + +int j_ishidden() +{ + return((int)j_mat[0]); +} + diff --git a/util/mkisofs/match.h b/util/mkisofs/match.h index 90def7c2d..7367dd211 100644 --- a/util/mkisofs/match.h +++ b/util/mkisofs/match.h @@ -5,10 +5,18 @@ */ /* - * $Id: match.h,v 1.1 1997/02/23 15:56:12 eric Rel $ + * $Id: match.h,v 1.2 1999/03/02 03:41:25 eric Exp $ */ #include "fnmatch.h" -void add_match(); -int matches(); +void add_match __PR((char *fn)); +int matches __PR((char *fn)); + +void i_add_match __PR((char *fn)); +int i_matches __PR((char *fn)); +int i_ishidden __PR((void)); + +void j_add_match __PR((char *fn)); +int j_matches __PR((char *fn)); +int j_ishidden __PR((void)); diff --git a/util/mkisofs/mkisofs.c b/util/mkisofs/mkisofs.c index 3344a921a..11959c0ca 100644 --- a/util/mkisofs/mkisofs.c +++ b/util/mkisofs/mkisofs.c @@ -20,11 +20,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static char rcsid[] ="$Id: mkisofs.c,v 1.29 1998/06/02 03:43:45 eric Exp $"; +static char rcsid[] ="$Id: mkisofs.c,v 1.32 1999/03/07 21:48:49 eric Exp $"; #include #include "config.h" #include "mkisofs.h" +#include "match.h" #ifdef linux #include @@ -50,6 +51,7 @@ static char rcsid[] ="$Id: mkisofs.c,v 1.29 1998/06/02 03:43:45 eric Exp $"; #include #endif #endif +#include #include "exclude.h" @@ -60,8 +62,9 @@ static char rcsid[] ="$Id: mkisofs.c,v 1.29 1998/06/02 03:43:45 eric Exp $"; struct directory * root = NULL; -static char version_string[] = "mkisofs 1.12b4"; +static char version_string[] = "mkisofs 1.12b5"; +char * outfile; FILE * discimage; unsigned int next_extent = 0; unsigned int last_extent = 0; @@ -104,6 +107,8 @@ char * volume_id = VOLUME_ID_DEFAULT; char * system_id = SYSTEM_ID_DEFAULT; char * boot_catalog = BOOT_CATALOG_DEFAULT; char * boot_image = BOOT_IMAGE_DEFAULT; +int volume_set_size = 1; +int volume_sequence_number = 1; int omit_period = 0; /* Violates iso9660, but these are a pain */ int transparent_compression = 0; /* So far only works with linux */ @@ -166,19 +171,35 @@ struct ld_option #define OPTION_NOSPLIT_SL_FIELD 153 #define OPTION_PRINT_SIZE 154 #define OPTION_SPLIT_OUTPUT 155 +#define OPTION_ABSTRACT 156 +#define OPTION_BIBLIO 157 +#define OPTION_COPYRIGHT 158 +#define OPTION_SYSID 159 +#define OPTION_VOLSET 160 +#define OPTION_VOLSET_SIZE 161 +#define OPTION_VOLSET_SEQ_NUM 162 +#define OPTION_I_HIDE 163 +#define OPTION_J_HIDE 164 +#define OPTION_LOG_FILE 165 static const struct ld_option ld_options[] = { { {"all-files", no_argument, NULL, 'a'}, 'a', NULL, "Process all files (don't skip backup files)", ONE_DASH }, + { {"abstract", required_argument, NULL, OPTION_ABSTRACT}, + '\0', "FILE", "Set Abstract filename" , ONE_DASH }, { {"appid", required_argument, NULL, 'A'}, 'A', "ID", "Set Application ID" , ONE_DASH }, + { {"biblio", required_argument, NULL, OPTION_BIBLIO}, + '\0', "FILE", "Set Bibliographic filename" , ONE_DASH }, + { {"copyright", required_argument, NULL, OPTION_COPYRIGHT}, + '\0', "FILE", "Set Copyright filename" , ONE_DASH }, { {"eltorito-boot", required_argument, NULL, 'b'}, 'b', "FILE", "Set El Torito boot image name" , ONE_DASH }, { {"eltorito-catalog", required_argument, NULL, 'c'}, 'c', "FILE", "Set El Torito boot catalog name" , ONE_DASH }, { {"cdwrite-params", required_argument, NULL, 'C'}, - 'C', "PARAMS", "Magic paramters from cdwrite" , ONE_DASH }, + 'C', "PARAMS", "Magic paramters from cdrecord" , ONE_DASH }, { {"omit-period", no_argument, NULL, 'd'}, 'd', NULL, "Omit trailing periods from filenames", ONE_DASH }, { {"disable-deep-relocation", no_argument, NULL, 'D'}, @@ -187,6 +208,10 @@ static const struct ld_option ld_options[] = 'f', NULL, "Follow symbolic links", ONE_DASH }, { {"help", no_argument, NULL, OPTION_HELP}, '\0', NULL, "Print option help", ONE_DASH }, + { {"hide", required_argument, NULL, OPTION_I_HIDE}, + '\0', "GLOBFILE", "Hide ISO9660/RR file" , ONE_DASH }, + { {"hide-joliet", required_argument, NULL, OPTION_J_HIDE}, + '\0', "GLOBFILE", "Hide Joliet file" , ONE_DASH }, { {NULL, required_argument, NULL, 'i'}, 'i', "ADD_FILES", "No longer supported" , TWO_DASHES }, { {"joliet", no_argument, NULL, 'J'}, @@ -195,6 +220,8 @@ static const struct ld_option ld_options[] = 'l', NULL, "Allow full 32 character filenames for iso9660 names", ONE_DASH }, { {"allow-leading-dots", no_argument, NULL, 'L'}, 'L', NULL, "Allow iso9660 filenames to start with '.'", ONE_DASH }, + { {"log-file", required_argument, NULL, OPTION_LOG_FILE}, + '\0', "LOG_FILE", "Re-direct messages to LOG_FILE", ONE_DASH }, { {"exclude", required_argument, NULL, 'm'}, 'm', "GLOBFILE", "Exclude file name" , ONE_DASH }, { {"prev-session", required_argument, NULL, 'M'}, @@ -221,12 +248,20 @@ static const struct ld_option ld_options[] = 'R', NULL, "Generate Rock Ridge directory information", ONE_DASH }, { {"split-output", no_argument, NULL, OPTION_SPLIT_OUTPUT}, '\0', NULL, "Split output into files of approx. 1GB size", ONE_DASH }, + { {"sysid", required_argument, NULL, OPTION_SYSID}, + '\0', "ID", "Set System ID" , ONE_DASH }, { {"translation-table", no_argument, NULL, 'T'}, 'T', NULL, "Generate translation tables for systems that don't understand long filenames", ONE_DASH }, { {"verbose", no_argument, NULL, 'v'}, 'v', NULL, "Verbose", ONE_DASH }, { {"volid", required_argument, NULL, 'V'}, 'V', "ID", "Set Volume ID" , ONE_DASH }, + { {"volset", required_argument, NULL, OPTION_VOLSET}, + '\0', "ID", "Set Volume set ID" , ONE_DASH }, + { {"volset-size", required_argument, NULL, OPTION_VOLSET_SIZE}, + '\0', "#", "Set Volume set size" , ONE_DASH }, + { {"volset-seqno", required_argument, NULL, OPTION_VOLSET_SEQ_NUM}, + '\0', "#", "Set Volume set sequence number" , ONE_DASH }, { {"old-exclude", required_argument, NULL, 'x'}, 'x', "FILE", "Exclude file name(depreciated)" , ONE_DASH } #ifdef ERIC_neverdef @@ -242,6 +277,10 @@ char *strdup(s) char *s;{char *c;if(c=(char *)malloc(strlen(s)+1))strcpy(c,s);return c;} #endif + void read_rcfile __PR((char * appname)); + void usage __PR((void)); +static void hide_reloc_dir __PR((void)); + void FDECL1(read_rcfile, char *, appname) { FILE * rcfile; @@ -318,10 +357,10 @@ void FDECL1(read_rcfile, char *, appname) /* The name should begin in the left margin. Make sure it is in upper case. Stop when we see white space or a comment. */ name = pnt; - while (*pnt && isalpha(*pnt)) + while (*pnt && isalpha((unsigned char)*pnt)) { - if(islower(*pnt)) - *pnt = toupper(*pnt); + if(islower((unsigned char)*pnt)) + *pnt = toupper((unsigned char)*pnt); pnt++; } if (name == pnt) @@ -408,7 +447,7 @@ void usage(){ #endif int i; - const char **targets, **pp; +/* const char **targets, **pp;*/ fprintf (stderr, "Usage: %s [options] file...\n", program_name); @@ -500,9 +539,9 @@ void usage(){ * with DST, I guess). The Linux iso9660 filesystem has had the sign * of this wrong for ages (mkisofs had it wrong too for the longest time). */ -int FDECL2(iso9660_date,char *, result, time_t, ctime){ +int FDECL2(iso9660_date,char *, result, time_t, crtime){ struct tm *local; - local = localtime(&ctime); + local = localtime(&crtime); result[0] = local->tm_year; result[1] = local->tm_mon + 1; result[2] = local->tm_mday; @@ -515,7 +554,7 @@ int FDECL2(iso9660_date,char *, result, time_t, ctime){ * as some files use daylight savings time and some don't... */ result[6] = local->tm_yday; /* save yday 'cause gmtime zaps it */ - local = gmtime(&ctime); + local = gmtime(&crtime); local->tm_year -= result[0]; local->tm_yday -= result[6]; local->tm_hour -= result[3]; @@ -534,11 +573,28 @@ int FDECL2(iso9660_date,char *, result, time_t, ctime){ return 0; } +/* hide "./rr_moved" if all its contents are hidden */ +static void +hide_reloc_dir() +{ + struct directory_entry * s_entry; + + for (s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next) { + if(strcmp(s_entry->name,".")==0 || strcmp(s_entry->name,"..")==0) + continue; + + if((s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0) + return; + } + + /* all entries are hidden, so hide this directory */ + reloc_dir->dir_flags |= INHIBIT_ISO9660_ENTRY; + reloc_dir->self->de_flags |= INHIBIT_ISO9660_ENTRY; +} extern char * cdwrite_data; int FDECL2(main, int, argc, char **, argv){ - char * outfile; struct directory_entry de; #ifdef HAVE_SBRK unsigned long mem_start; @@ -552,6 +608,7 @@ int FDECL2(main, int, argc, char **, argv){ char shortopts[OPTION_COUNT * 3 + 2]; struct option longopts[OPTION_COUNT + 1]; int c; + char *log_file = 0; if (argc < 2) usage(); @@ -643,6 +700,13 @@ int FDECL2(main, int, argc, char **, argv){ exit(1); } break; + case OPTION_ABSTRACT: + abstract = optarg; + if(strlen(abstract) > 37) { + fprintf(stderr,"Abstract filename string too long\n"); + exit(1); + }; + break; case 'A': appid = optarg; if(strlen(appid) > 128) { @@ -650,6 +714,20 @@ int FDECL2(main, int, argc, char **, argv){ exit(1); }; break; + case OPTION_BIBLIO: + biblio = optarg; + if(strlen(biblio) > 37) { + fprintf(stderr,"Bibliographic filename string too long\n"); + exit(1); + }; + break; + case OPTION_COPYRIGHT: + copyright = optarg; + if(strlen(copyright) > 37) { + fprintf(stderr,"Copyright filename string too long\n"); + exit(1); + }; + break; case 'd': omit_period++; break; @@ -665,6 +743,9 @@ int FDECL2(main, int, argc, char **, argv){ case 'L': allow_leading_dots++; break; + case OPTION_LOG_FILE: + log_file = optarg; + break; case 'M': merge_image = optarg; break; @@ -704,11 +785,39 @@ int FDECL2(main, int, argc, char **, argv){ case OPTION_SPLIT_OUTPUT: split_output++; break; + case OPTION_SYSID: + system_id = optarg; + if(strlen(system_id) > 32) { + fprintf(stderr,"System ID string too long\n"); + exit(1); + }; + break; case 'T': generate_tables++; break; case 'V': volume_id = optarg; + if(strlen(volume_id) > 32) { + fprintf(stderr,"Volume ID string too long\n"); + exit(1); + }; + break; + case OPTION_VOLSET: + volset_id = optarg; + if(strlen(volset_id) > 128) { + fprintf(stderr,"Volume set ID string too long\n"); + exit(1); + }; + break; + case OPTION_VOLSET_SIZE: + volume_set_size = atoi(optarg); + break; + case OPTION_VOLSET_SEQ_NUM: + volume_sequence_number = atoi(optarg); + if (volume_sequence_number > volume_set_size) { + fprintf(stderr,"Volume set sequence number too big\n"); + exit(1); + } break; case 'v': verbose++; @@ -730,6 +839,12 @@ int FDECL2(main, int, argc, char **, argv){ */ add_match(optarg); break; + case OPTION_I_HIDE: + i_add_match(optarg); + break; + case OPTION_J_HIDE: + j_add_match(optarg); + break; case OPTION_HELP: usage (); exit (0); @@ -764,15 +879,23 @@ parse_input_files: mem_start = (unsigned long) sbrk(0); #endif + /* if the -hide-joliet option has been given, set the Joliet option */ + if (!use_Joliet && j_ishidden()) + use_Joliet++; + if(verbose > 1) fprintf(stderr,"%s\n", version_string); - if( (cdwrite_data != NULL && merge_image == NULL) - || (cdwrite_data == NULL && merge_image != NULL) ) + if(cdwrite_data == NULL && merge_image != NULL) { - fprintf(stderr,"Multisession usage bug - both -C and -M must be specified.\n"); + fprintf(stderr,"Multisession usage bug: Must specify -C if -M is used.\n"); exit(0); } + if(cdwrite_data != NULL && merge_image == NULL) + { + fprintf(stderr,"Warning: -C specified without -M: old session data will not be merged.\n"); + } + /* The first step is to scan the directory tree, and take some notes */ scan_tree = argv[optind]; @@ -803,6 +926,34 @@ parse_input_files: #endif } + if (log_file) { + FILE *lfp; + int i; + + /* open log file - test that we can open OK */ + if ((lfp = fopen(log_file, "w")) == NULL) { + fprintf(stderr,"can't open logfile: %s\n", log_file); + exit (1); + } + fclose(lfp); + + /* redirect all stderr message to log_file */ + fprintf(stderr, "re-directing all messages to %s\n", log_file); + fflush(stderr); + + /* associate stderr with the log file */ + if (freopen(log_file, "w", stderr) == NULL) { + fprintf(stderr,"can't open logfile: %s\n", log_file); + exit (1); + } + if(verbose > 1) { + for (i=0;i